[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
First Class Environments and Their Extenders
My ATN (Augmented Transition Network) is a macro that makes a grammar into
an object. This object (currently) is a closure taking one argument that is
evaluated in an environment where each state has been transformed into a
function of (currently) five arguments using letrec. Roughly:
(define-atn my-atn state2 (state1 arc1 arc2) (state2 arc3 arc4))
is transformed to:
(letrec ((state1 (lambda (...) (nexus arc1 arc2)))
(state2 (lambda (...) (nexus arc3 arc4))) )
(define! my-atn
(lambda (*sentence*) (state2 ...))))
where the "..." means "fill in the blank". NEXUS is a macro that determines
the evaluation order of the arcs (depth-first, breadth-first, parallel, etc).
One problem with this is that if I have a large ATN (with say 100 states,
and an average branching factor of 5), the compile can take a significant
amount of time, even if I have a VAX 780 all to myself at 3AM.
How do you debug the grammar. Well, first you find the state in which it
failed, you modify the source code of the grammar, and then you recompile
the ENTIRE GRAMMAR. Yuck!
The standard solution to this in the literature of ATNs (and AI in
general) seems to be to define each state as a global-binding, and not to
worry about trying to package them all up in objects. I don't like this
because its not modular -- the inards of each compiled atn-grammar is
sprawled out everywhere. I have several different atn-grammars, and I
don't want to worry about them interfering with one another.
The letrec method is a nice method, and I would like to make it work.
My current view of what I think I want is this: That letrec in the
right-hand-side of the transformation at the beginning of this note defined
a new rib (MY_RIB) in front of the "current" environment (OLDENV) creating a
new environment (MY_ENV). I want to rebind variables in MY_RIB to
expressions EVALuated in MY_ENV, and I want to extend MY_RIB with new
variables bound to the evaluations of expressions EVALuated in MY_ENV (with
MY_ENV already extended by the new variable (which is initially bound to
something like '#!unspecified', then rebound to the new value -- that is,
normal letrec semantics). I could then create functions (macros?) like
'editstate', 'addstate', 'trace-state', 'untrace-state', etc. that would do
the obvious things to a particular compiled-atn-grammar. This way, I only
have to recompile the state, not the entire grammar.
Put another way, I can modify the grammar interactively rather than in
batch mode like I am now.
PS -- I designed it this way, because I heard that first class environments
were on their way, and I thought it would eventually work the way I wanted
it too. But apparently now, the idea is that you should ONLY be able to
extend the LAST rib in the rib sequence. Seeing as how I want to extend the
second to the last rib (and two is an arbitrary number), and there being a
number of programming technique reasons for putting new ribs between me and
the second to the last rib, I have to object and call for a facility
something like 'call-with-current-rib-set!' (where set! is rebind
and extend as one), and I need to EVAL (compile, execute) in the proper
environment, MY_ENV, which is not necessarily equal to the current one, and
is procured with something like 'call-with-current-environment'.
'call/c_rib' is not necessarily incompatable with 'call/c_env' (as I almost
thought) as I can:
(let ((MY_RIB (call/c_rib (lambda (x) x)))
(MY_ENV (call/c_env (lambda (x) x))) )
(some function of MY_RIB and MY_ENV here) )
As long as I can grab a rib extender, and EVAL in a environment other than
the current one, everything is fine. The call/c_rib and call/c_env is just
illustration.
As I think that this generalizes to objects (modules), I don't think calls
to rewrite my ATN are in order unless they make the same generalization.