Sat Aug 8 15:28:07 CEST 2009
Implementing this Scheme interpreter without relying on cons or
closures has been most revealing. I never knew I knew so little about
the mechanics. Arrogance tends to get in the way of learning..
There are some meta-confusion things in the syntax representation that
are a bit fishy still:
- Syntax is wrapped in a weird way (tagged s-expressions. a full
parse into an AST so values and terms can never be confused would
probably be better).
- Because of this confusion, primitives can return reducable
expressions (make-ast) and closures (make-closure) that will not
behave as literal data.
As I've mentioned before, this makes make-ast behave as eval.
Maybe the solution is to explicitly represent non-reducable values as
* all primitive return values will be tagged with VALUE
* REDEX that is not a varref or an application is tagged as VALUE
Ok, I see..
It's probably best to get rid of the word "closure", and have two
kinds of values that contain environments:
The trouble is primitive values. In the lambda calculus, there are
only two kinds of terms: applications and abstractions, where
abstractions are values.
So.. Can I get rid of it in one try? The code should be a lot clearer
I think I got the concept right, but there is some stray assignment
that messes up the GC. Maybe time to isolate all assignments?
Inspecting the run state it gives something like:
... (#k_apply(#k_macro(#k_apply(#k_macro(#k_apply( ...
Ok.. recursive macro application.
After some more small tagging bugs (sc_apply_ktx required some head
scratching) it seems to work now. The only remaining problem is the
invokation of (gc) from within scheme.
Was a problem with sc->entries. Added sc->step_entries, which is a
Seems to work now. I can call the interpreter step from within scheme
+ all the state objects are available:
(eval-step (make-state (make-redex 'a '((a . 123))) (mt)))
=> #state(#value(123) #k_mt)
(eval-step (eval-step (make-state (make-redex 'a '((a . 123))) (mt))))
=> #error(halt 123 #state(#value(123) #k_mt))