Sat Jan 19 20:01:35 CET 2013

Multi out

Seems not trivial:
- Won't work for expressions: some other "context" is necessary, i.e. let-values.
- Might need separate partial evaluation step to determine # outputs

Function output arity is simple:

;; This one is simpler: all primitive functions are replaced by
;; `void', mapping anything to #void, which yields a (values #void
;; ...) result where only the size is significant.

(define (ai-arity p)
  (define eval-void (p void void void))
  (define nb-in (procedure-arity eval-void))
  (define args (for/list ((i (in-range 0 nb-in))) #f))
  (define nb-out
    (length (call-with-values
                (lambda () (apply eval-void args))
  (values nb-in nb-out))

However, this raises the issue that inner functions cannot be
abstractly evaluated.  It might be best to remove the "poor man's
module" approach now and use a different mechanism for propagating

Anyway, why not use the same approach as in Haskell implementation?
Type classes are implemented by threading the semantics through the
code, passed as a first argument to each function.

A similar approach might work better than units.  Somehow it seems
that units are not modular enough..

I.e. using syntax-parameterize.

Yep, works!

(define-syntax-parameter ai-prims #f)

(define-syntax-rule (ai-lambda (arg ...) expr)
  (lambda (p arg ...)
     ((ai-prims (lambda _ #'p)))

(define-struct ai (add mul integrate))

(define-syntax-rule (add a b)       ((ai-add (ai-prims)) a b))
(define-syntax-rule (mul a b)       ((ai-mul (ai-prims)) a b))
(define-syntax-rule (integrate a b) ((ai-integrate (ai-prims)) a b))

Next is how to do this for nesting ai-lambdas?  Basically this needs a
re-implementation of %app