Add TR helpers for new Racket error notation

This commit is contained in:
Asumu Takikawa 2013-12-17 19:37:48 -05:00
parent 54c50dd8d2
commit 0488ce9e0b
2 changed files with 51 additions and 2 deletions

View File

@ -10,10 +10,13 @@
(provide/cond-contract (provide/cond-contract
[tc-error/expr ((string?) (#:return c:any/c #:stx syntax?) #:rest (c:listof c:any/c) [tc-error/expr ((string?) (#:return c:any/c #:stx syntax?) #:rest (c:listof c:any/c)
. c:->* . c:any/c)] . c:->* . c:any/c)]
[tc-error/expr/fields ((string?) (#:more string? #:return c:any/c #:stx syntax?)
#:rest (c:listof c:any/c) . c:->* . c:any/c)]
[lookup-fail (identifier? . c:-> . Type/c)] [lookup-fail (identifier? . c:-> . Type/c)]
[lookup-type-fail (identifier? . c:-> . Type/c)]) [lookup-type-fail (identifier? . c:-> . Type/c)])
;; produce a type-checking error, and also return a result (e.g., a type)
(define (tc-error/expr msg (define (tc-error/expr msg
#:return [return -Bottom] #:return [return -Bottom]
#:stx [stx (current-orig-stx)] #:stx [stx (current-orig-stx)]
@ -21,6 +24,15 @@
(apply tc-error/delayed #:stx stx msg rest) (apply tc-error/delayed #:stx stx msg rest)
return) return)
;; like `tc-error/expr`, but with modern error syntax
(define (tc-error/expr/fields msg
#:more [more #f]
#:stx [stx (current-orig-stx)]
#:return [return -Bottom]
. rst)
(apply tc-error/fields #:more more #:stx stx #:delayed? #t msg rst)
return)
;; error for unbound variables ;; error for unbound variables
(define (lookup-fail e) (define (lookup-fail e)
(match (identifier-binding e) (match (identifier-binding e)

View File

@ -5,8 +5,10 @@ This file is for utilities that are only useful for Typed Racket, but
don't depend on any other portion of the system don't depend on any other portion of the system
|# |#
(require syntax/source-syntax "disappeared-use.rkt" racket/promise (require syntax/source-syntax "disappeared-use.rkt"
syntax/parse (for-syntax racket/base syntax/parse) racket/match) racket/list racket/match racket/promise racket/string
syntax/parse (for-syntax racket/base syntax/parse)
(only-in unstable/sequence in-slice))
(provide ;; parameters (provide ;; parameters
current-orig-stx current-orig-stx
@ -23,6 +25,7 @@ don't depend on any other portion of the system
warn-unreachable warn-unreachable
report-all-errors report-all-errors
tc-error/fields
tc-error/delayed tc-error/delayed
tc-error tc-error
tc-error/stx tc-error/stx
@ -133,6 +136,40 @@ don't depend on any other portion of the system
delayed-errors)) delayed-errors))
(raise-typecheck-error (apply format msg rest) (list stx))))) (raise-typecheck-error (apply format msg rest) (list stx)))))
;; Produce a type error using modern Racket error syntax.
;; Avoid using format directives in the `msg`, `more`, and `field`
;; strings in the rest argument (may cause unexpected errors)
(define (tc-error/fields msg
#:more [more #f]
#:stx [stx (current-orig-stx)]
#:delayed? [delayed? #f]
. rst)
(unless (even? (length rst))
(raise-argument-error
'tc-error/fields
"alternating fields and values"
rst))
(define-values (field-strs vals)
(for/fold ([field-strs null] [vals null])
([field+value (in-slice 2 rst)])
(match-define (list field value) field+value)
(define field-strs*
(cons (format " ~a: ~~a" field) field-strs))
(values field-strs* (cons value vals))))
(define more-msg (if more (string-append ";\n " more "\n") "\n"))
(define all-fields (string-join (reverse field-strs) "\n"))
(define final-msg (chomp (string-append msg more-msg all-fields)))
(if delayed?
(apply tc-error/delayed #:stx stx final-msg (reverse vals))
(apply tc-error/stx stx final-msg (reverse vals))))
;; helper for above, remove \n at end if any
(define (chomp str)
(define len (string-length str))
(if (eq? #\newline (string-ref str (sub1 len)))
(substring str 0 (sub1 len))
str))
;; produce a type error, using the current syntax ;; produce a type error, using the current syntax
(define (tc-error msg . rest) (define (tc-error msg . rest)
(let* ([ostx (current-orig-stx)] (let* ([ostx (current-orig-stx)]