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]