On Thu 16 Feb 2012 14:18, Noah Lavine <noah.b.lav...@gmail.com> writes:

>>  (let ((x (random)))
>>    (eq? x x))
>
> (let* ((x (random))
>        (y (list x))
>        (z (car y))
>   (eq? x z))

This one should reduce to the same thing, but currently doesn't because
(list x) is not considered a "constant expression" because `let' is a
"constructor" (quotes to indicate the language of peval).  If we can
propagate it (probably true in this case, given that it has only one
use), then the expression folds as before:

  (let* ((x (random))
         (z (car (list x))))
    (eq? x z))
  => 
  (let ((x-129 (random))) 
    (eq? x-129 x-129)))

So I don't think that for this purpose (identity) we need any more
mechanism

> In order to type-check, you need to be able to associate extra
> information with a value (its type) even in cases where you don't know
> the value.

For this purpose, have you considered creating a functional database of
facts?  Then you can add facts when you see conditionals, for example,
and you get different facts in the different branches.

  (if test consequent alternate)
  ;; assuming the test doesn't fold
  => (make-if (for-test test current-facts)
              (for-tail consequent (add-fact test #t current-facts))
              (for-tail consequent (add-fact test #f current-facts)))

You can also join the facts accumulated by a conditional branch with the
current facts if you detect that one of the branches leads to a nonlocal
exit, as in

  (define (foo x)
    (if (not (and (struct? x) (eq? (struct-vtable x) <foo>)))
        (error ...))
    ;; here at this point, we have the fact: x is a struct, and its
    ;; vtable is <foo>
    ...)

This is related to range analysis.  But, it's also something that's
easier to do with an explicit notion of control flow (i.e. a CPS IR).

Regards,

Andy
-- 
http://wingolog.org/

Reply via email to