Keyword functions are a little tricky. This PR addresses issues
checking the body of kw functions.
Basically, a function with keyword arguments such as inc:
(define (inc x #:n [n 1])
(+ x n))
actually expands into a more complex function with 3 arguments that
looks something resembling the following:
(define (inc-expanded n* n-given? x)
(let ([n (if n-given? n* 1)]) (+ x n)))
and calls to inc are converted to match this form:
(inc 42) => (inc-expanded #f #f 42)
(inc 42 #:n 2) => (inc-expanded 2 #t 42)
Note that each optional keyword argument has a boolean flag argument
that signals whether or not the caller provided that keyword argument.
This PR takes advantage of the observation that the value for the n*
argument in inc is only reachable in code when n-given? is #t, and so,
assuming the kw-expansion protocol always only accesses n* if n-given?
is #t, we can actually safely check the body of the function against
the following simple but correct type:
(-> Number Boolean Number Number)
An alternative previous approach expanded the function type into every
possible combination of optional argument and optional argument flag,
but this was prohibitively expensive.