Next: syntaxes unsafe-cast, Previous: syntaxes predicates, Up: syntaxes [Contents][Index]
The following syntactic bindings are exported by the library
(vicare)
.
Validate the type signature of the values returned by ?expr, either at expand–time or run–time. ?expr can be any Scheme expression. ?signature must be a proper or improper list of type annotations representing the type signature.
The syntax assert-signature
returns a single unspecified value.
The syntax assert-signature-and-return
returns the return
values of ?expr with the original type signature of ?expr.
The syntax cast-signature
returns the return values of
?expr with the type signature ?signature.
(type-of 123) ⇒ #[signature (<positive-fixnum>)] (type-of (assert-signature-and-return (<top>) 123)) ⇒ #[signature (<positive-fixnum>)] (type-of (cast-signature (<top>) 123)) ⇒ #[signature (<top>)]
If it is possible to validate the signature at expand–time: when successful, the syntax use just expands to the evaluation of ?expr; when a type mismatch is detected, an expand–time exception is raised. Otherwise the syntax use expands to an expression that validates the values at run–time.
As special cases, when ?signature is ‘()’, a proper or
improper list of <top>
and <list>
types like:
<list> (<top>) (<top> <top> <top>) (<top> <top> . <list>)
no validation is performed at run–time, only at expand–time.
Here are some validation examples:
(assert-signature () (values)) (assert-signature-and-return (<fixnum>) 123) ⇒ 123 (assert-signature-and-return (<string>) "ciao") ⇒ "ciao" (assert-signature-and-return (<fixnum> <flonum>) (values 1 2.0)) ⇒ 1 2.0 (expansion-of (assert-signature (<fixnum>) 123)) ⇒ (begin (quote 123) (quote #!void)) (expansion-of (assert-signature-and-return (<fixnum>) 123)) ⇒ (quote 123) (expansion-of (assert-signature-and-return (<fixnum>) (unsafe-cast-signature <fixnum> (read)))) ⇒ ((primitive read))
There are some interesting special cases:
(assert-signature () ?expr)
(assert-signature <list> ?expr)
which will just expand to the evaluation of ?expr; this might be useful when the syntax is used in the output form of another macro use.
(assert-signature (<top>) ?expr)
(assert-signature (<top> <top>) ?expr)
(assert-signature (<top> <top> . <list>) ?expr)
Let’s say we have a function ‘fun’ such that:
(type-of (fun)) ⇒ #[signature <list>]
there is nothing the expander can do to infer the type signature of the function application.
The following syntax use:
(assert-signature-and-return (<fixnum> <flonum> <string>) (fun))
is expanded to:
(call-with-values (lambda () (fun)) (lambda (arg1 arg2 arg3) (values ((lambda (obj value-index caller-who) (if (fixnum? obj) obj (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ <fixnum>) obj))) arg1 '1 'assert-signature-and-return) ((lambda (obj value-index caller-who) (if (flonum? obj) obj (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ <flonum>) obj))) arg2 '2 'assert-signature-and-return) ((lambda (obj value-index caller-who) (if (string? obj) obj (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ <string>) obj))) arg3 '3 'assert-signature-and-return))))
The following syntax use:
(assert-signature (<fixnum> <flonum> <string>) (fun))
is expanded to:
(call-with-values (lambda () (fun)) (lambda (arg1 arg2 arg3) ((lambda (obj value-index caller-who) (if (not (fixnum? obj)) (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ <fixnum>) obj) '#!void)) arg1 '1 'assert-signature) ((lambda (obj value-index caller-who) (if (not (flonum? obj)) (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ <flonum>) obj) '#!void)) arg2 '2 'assert-signature) ((lambda (obj value-index caller-who) (if (not (string? obj)) (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ <string>) obj) '#!void)) arg3 '3 'assert-signature) (void)))
The following syntax use:
(assert-signature-and-return (list-of <fixnum>) (fun))
is expanded to:
((lambda arg1 (lambda (list-value first-value-index caller-who) (fold-left (lambda (item-index item-value) ((lambda (obj value-index caller-who) (if (not ((letrec ((pred (lambda (obj) (if (pair? obj) (if (fixnum? (car obj)) (pred (cdr obj)) '#f) (null? obj))))) pred) obj)) (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ (list-of <fixnum>)) obj) '#!void)) item-value item-index caller-who) (fxadd1 item-index)) first-value-index list-value) list-value)) (fun))
The following syntax use:
(assert-signature-and-return (<fixnum> <flonum> . (list-of <fixnum>)) (fun))
is expanded to:
(call-with-values (lambda () (fun)) (lambda (arg1 arg2 . arg3) (apply values ((lambda (obj value-index caller-who) (if (fixnum? obj) obj (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ <fixnum>) obj))) arg1 '1 'assert-signature-and-return) ((lambda (obj value-index caller-who) (if (flonum? obj) obj (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ <flonum>) obj))) arg2 '2 'assert-signature-and-return) (lambda (list-value first-value-index caller-who) (fold-left (lambda (item-index item-value) ((lambda (obj value-index caller-who) (if (not ((letrec ((pred (lambda (obj) (if (pair? obj) (if (fixnum? (car obj)) (pred (cdr obj)) '#f) (null? obj))))) pred) obj)) (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ (list-of <fixnum>)) obj) '#!void)) item-value item-index caller-who) (fxadd1 item-index)) first-value-index list-value) list-value) arg3 '3 'assert-signature-and-return)))
The following syntax use:
(assert-signature-and-return (<fixnum>) (fun))
is expanded to:
((lambda (arg1) ((lambda (obj value-index caller-who) (if (fixnum? obj) obj (expression-return-value-violation caller-who '"return value of invalid type" value-index '(is-a? _ <fixnum>) obj))) arg1 '1 'assert-signature-and-return)) (fun))
The following syntax use:
(assert-signature-and-return (<top>) (fun))
is expanded to:
(fun)
there is no need to insert a validation form because a single value of any type matches the type signature.
The following syntax use:
(assert-signature-and-return <list> (fun))
is expanded to:
(fun)
there is no need to insert a validation form because any number of return values of any type matches the type signature.
Next: syntaxes unsafe-cast, Previous: syntaxes predicates, Up: syntaxes [Contents][Index]