Improve code for checking init args for TR classes
original commit: b2f9bf6e9eed9c1e71923225adb5340046c725b4
This commit is contained in:
parent
3e9cb6c332
commit
2b3e3d11d5
|
@ -11,6 +11,7 @@
|
|||
racket/syntax
|
||||
syntax/id-table
|
||||
syntax/parse
|
||||
syntax/stx
|
||||
"signatures.rkt"
|
||||
(private parse-type syntax-properties type-annotation)
|
||||
(base-env class-prims)
|
||||
|
@ -928,27 +929,9 @@
|
|||
init-args:id
|
||||
init-val:expr)))
|
||||
(define init-name (syntax-e #'init-external))
|
||||
(define init-type (car (dict-ref inits init-name '(#f))))
|
||||
(cond [init-type
|
||||
;; Catch the exception because the error that is produced
|
||||
;; in the case of a type error is incomprehensible for a
|
||||
;; programmer looking at surface syntax. Raise a custom
|
||||
;; type error instead.
|
||||
(with-handlers
|
||||
([exn:fail:syntax?
|
||||
(λ (e) (tc-error/delayed "Default init value has wrong type"))])
|
||||
(parameterize ([delay-errors? #f])
|
||||
(unless (equal? (syntax->datum #'init-val) '(quote #f))
|
||||
(tc-expr/check #'init-val (ret (Un init-type (->* null init-type)))))))]
|
||||
;; If the type can't be found, it means that there was no
|
||||
;; expected type or no annotation was provided via (: ...).
|
||||
;;
|
||||
;; FIXME: is this the right place to raise this error, or
|
||||
;; should it be caught earlier so that this function
|
||||
;; can be simpler?
|
||||
[else
|
||||
(tc-error/delayed "Init argument ~a has no type annotation"
|
||||
init-name)])]
|
||||
(check-init-arg init-name
|
||||
(car (dict-ref inits init-name '(#f)))
|
||||
#'init-val)]
|
||||
;; init-field with default
|
||||
[(begin
|
||||
(quote ((~or (~datum declare-field-assignment)
|
||||
|
@ -967,18 +950,9 @@
|
|||
#:when (free-identifier=? #'x #'y)
|
||||
#:when (free-identifier=? #'obj1 #'obj2)
|
||||
(define init-name (syntax-e #'name))
|
||||
(define init-type (car (dict-ref inits init-name '(#f))))
|
||||
(cond [init-type
|
||||
(with-handlers
|
||||
([exn:fail:syntax?
|
||||
;; FIXME: produce a better error message
|
||||
(λ (e) (tc-error/delayed "Default init value has wrong type"))])
|
||||
(parameterize ([delay-errors? #f])
|
||||
(unless (equal? (syntax->datum #'init-val) '(quote #f))
|
||||
(tc-expr/check #'init-val (ret (Un init-type (->* null init-type)))))))]
|
||||
[else
|
||||
(tc-error/delayed "Init argument ~a has no type annotation"
|
||||
init-name)])]
|
||||
(check-init-arg init-name
|
||||
(car (dict-ref inits init-name '(#f)))
|
||||
#'init-val)]
|
||||
;; any field or an init-field without default
|
||||
[(begin
|
||||
(quote ((~or (~datum declare-field-assignment)
|
||||
|
@ -1000,6 +974,26 @@
|
|||
(tc-expr simplified)]
|
||||
[_ (void)])))
|
||||
|
||||
;; check-init-arg : Id Type Syntax -> Void
|
||||
;; Check the initialization of an init arg variable against the
|
||||
;; expected type provided by an annotation (or the default)
|
||||
(define (check-init-arg init-name init-type init-val)
|
||||
(define thunk?
|
||||
(and (stx-pair? init-val)
|
||||
(free-identifier=? #'#%plain-lambda (stx-car init-val))))
|
||||
(unless (equal? (syntax->datum init-val) '(quote #f))
|
||||
(cond [thunk?
|
||||
(define type
|
||||
(tc-expr/check/t init-val (ret (->* null init-type))))
|
||||
(match type
|
||||
[(Function: (list (arr: _ (Values: (list (Result: result _ _)))
|
||||
_ _ _)))
|
||||
(check-below result init-type)]
|
||||
[_ (int-err "unexpected init value ~a"
|
||||
(syntax->datum init-val))])]
|
||||
[else
|
||||
(tc-expr/check init-val (ret init-type))])))
|
||||
|
||||
;; synthesize-private-field-types : IdTable Dict Hash -> Void
|
||||
;; Given top-level expressions in the class, synthesize types from
|
||||
;; the initialization expressions for private fields.
|
||||
|
|
|
@ -808,7 +808,8 @@
|
|||
[tc-err (class object% (super-new)
|
||||
(: z Integer)
|
||||
(init [z "foo"]))
|
||||
#:ret (ret (-class #:init ([z -Integer #t])))]
|
||||
#:ret (ret (-class #:init ([z -Integer #t])))
|
||||
#:msg #rx"expected: Integer.*given: String"]
|
||||
;; test init field default value
|
||||
[tc-e (let ()
|
||||
(define c% (class object% (super-new)
|
||||
|
@ -1204,7 +1205,7 @@
|
|||
(super-new)
|
||||
(init-field [x : Z] [y : Z 0]))
|
||||
#:ret (ret (-poly (Z) (-class #:init-field ([x Z #f] [y Z #t]))))
|
||||
#:msg #rx"Default init value has wrong type"]
|
||||
#:msg #rx"expected: Z.*given: Zero"]
|
||||
;; fails because default field value cannot be polymorphic
|
||||
[tc-err (class object%
|
||||
#:forall (Z)
|
||||
|
|
Loading…
Reference in New Issue
Block a user