* Enforce the use of a '*' in list-like rest args.
* Abstract out annotation errors so that we can report it in the other case where it's useful. original commit: c2a53b316be90d81b1af0afd4acb4f22b5dc57c9
This commit is contained in:
parent
4271f734a6
commit
9d55a9e592
|
@ -93,26 +93,32 @@ This file defines two sorts of primitives. All of them are provided into any mod
|
|||
#,(syntax-property #'(require/contract pred pred-cnt lib)
|
||||
'typechecker:ignore #t))))]))
|
||||
|
||||
(define-for-syntax (formal-annotation-error stx src)
|
||||
(let loop ([stx stx])
|
||||
(syntax-case stx ()
|
||||
;; should never happen
|
||||
[() (raise-syntax-error #f "bad annotation syntax" src stx)]
|
||||
[[var : ty]
|
||||
(identifier? #'var)
|
||||
(raise-syntax-error #f "expected dotted or starred type" src #'ty)]
|
||||
[([var : ty] . rest)
|
||||
(identifier? #'var)
|
||||
(loop #'rest)]
|
||||
[([var : ty] . rest)
|
||||
(raise-syntax-error #f "not a variable" src #'var)]
|
||||
[(e . rest)
|
||||
(raise-syntax-error #f "expected annotated variable of the form [x : T], got something else" src #'e)])))
|
||||
|
||||
(define-for-syntax (types-of-formals stx src)
|
||||
(syntax-case stx (:)
|
||||
[([var : ty] ...) (quasisyntax/loc stx (ty ...))]
|
||||
[([var : ty] ... . [rest : rest-ty])
|
||||
[([var : ty] ... . [rest : rest-ty star])
|
||||
(eq? '* (syntax-e #'star))
|
||||
(syntax/loc stx (ty ... rest-ty *))]
|
||||
[([var : ty] ... . [rest : rest-ty ddd bound])
|
||||
(eq? '... (syntax-e #'ddd))
|
||||
(syntax/loc stx (ty ... rest-ty ddd bound))]
|
||||
[_
|
||||
(let loop ([stx stx])
|
||||
(syntax-case stx ()
|
||||
;; should never happen
|
||||
[() (raise-syntax-error #f "bad annotation syntax" src stx)]
|
||||
[([var : ty] . rest)
|
||||
(identifier? #'var)
|
||||
(loop #'rest)]
|
||||
[([var : ty] . rest)
|
||||
(raise-syntax-error #f "not a variable" src #'var)]
|
||||
[(e . rest)
|
||||
(raise-syntax-error #f "expected annotated variable of the form [x : T], got something else" src #'e)]))]))
|
||||
[_ (formal-annotation-error stx src)]))
|
||||
|
||||
|
||||
(define-syntax (plambda: stx)
|
||||
|
@ -144,6 +150,9 @@ This file defines two sorts of primitives. All of them are provided into any mod
|
|||
(syntax-property #'arg 'type-ascription #'ty)]
|
||||
[(_ arg ty)
|
||||
(syntax-property #'arg 'type-ascription #'ty)]
|
||||
[(_ arg ty star)
|
||||
(eq? '* (syntax-e #'star))
|
||||
(syntax-property #'arg 'type-ascription #'ty)]
|
||||
[(_ arg ty ddd bound)
|
||||
(eq? '... (syntax-e #'ddd))
|
||||
(syntax-property (syntax-property #'arg 'type-ascription #'ty)
|
||||
|
@ -200,7 +209,7 @@ This file defines two sorts of primitives. All of them are provided into any mod
|
|||
|
||||
|
||||
;; helper function for annoating the bound names
|
||||
(define-for-syntax (annotate-names stx)
|
||||
(define-for-syntax (annotate-names stx src)
|
||||
(define (label-one var ty)
|
||||
(syntax-property var 'type-label ty))
|
||||
(define (label vars tys)
|
||||
|
@ -215,24 +224,27 @@ This file defines two sorts of primitives. All of them are provided into any mod
|
|||
[[var : ty] (label-one #'var #'ty)]
|
||||
[([var : ty] ...)
|
||||
(label #'(var ...) #'(ty ...))]
|
||||
[([var : ty] ... . [rest : rest-ty])
|
||||
[([var : ty] ... . [rest : rest-ty star])
|
||||
(eq? '* (syntax-e #'star))
|
||||
(append (label #'(var ...) #'(ty ...)) (label-one #'rest #'rest-ty))]
|
||||
[([var : ty] ... . [rest : rest-ty ddd bound])
|
||||
(eq? '... (syntax-e #'ddd))
|
||||
(append (label #'(var ...) #'(ty ...)) (label-dotted #'rest #'rest-ty #'bound))]))
|
||||
(append (label #'(var ...) #'(ty ...)) (label-dotted #'rest #'rest-ty #'bound))]
|
||||
[_ (formal-annotation-error stx src)]))
|
||||
|
||||
(define-syntax-rule (λ: . args) (lambda: . args))
|
||||
|
||||
(define-syntax (lambda: stx)
|
||||
(syntax-case stx (:)
|
||||
[(lambda: formals . body)
|
||||
(with-syntax ([labeled-formals (annotate-names #'formals)])
|
||||
(with-syntax ([labeled-formals (annotate-names #'formals stx)])
|
||||
(syntax/loc stx (lambda labeled-formals . body)))]))
|
||||
|
||||
(define-syntax (case-lambda: stx)
|
||||
(syntax-case stx (:)
|
||||
[(case-lambda: [formals . body] ...)
|
||||
(with-syntax ([(lab-formals ...) (map annotate-names (syntax->list #'(formals ...)))])
|
||||
(with-syntax ([(lab-formals ...) (map (lambda (s) (annotate-names s stx))
|
||||
(syntax->list #'(formals ...)))])
|
||||
(syntax/loc stx (case-lambda [lab-formals . body] ...)))]))
|
||||
|
||||
(define-syntaxes (let-internal: let*: letrec:)
|
||||
|
@ -240,7 +252,7 @@ This file defines two sorts of primitives. All of them are provided into any mod
|
|||
(lambda (stx)
|
||||
(syntax-case stx (:)
|
||||
[(_ ([nm : ty . exprs] ...) . body)
|
||||
(with-syntax* ([(vars ...) (annotate-names #'([nm : ty] ...))]
|
||||
(with-syntax* ([(vars ...) (annotate-names #'([nm : ty] ...) stx)]
|
||||
[bindings (map (lambda (v e loc)
|
||||
(quasisyntax/loc loc [#,v . #,e]))
|
||||
(syntax->list #'(vars ...))
|
||||
|
|
Loading…
Reference in New Issue
Block a user