aboutsummaryrefslogtreecommitdiff
path: root/src/interp/lisp-backend.boot
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp/lisp-backend.boot')
-rw-r--r--src/interp/lisp-backend.boot42
1 files changed, 31 insertions, 11 deletions
diff --git a/src/interp/lisp-backend.boot b/src/interp/lisp-backend.boot
index 36075241..6354a5cf 100644
--- a/src/interp/lisp-backend.boot
+++ b/src/interp/lisp-backend.boot
@@ -55,27 +55,39 @@ module lisp_-backend where
--% 3. predicate guarding loop body execution
--% 4. loop termination predicate
+++ Dummy free var name.
+$freeVarName == KEYWORD::freeVar
+
+loopVarInit(x,y) ==
+ x is ['%free,:id] => [id,[$freeVarName,middleEndExpand ['%LET,id,y]]]
+ if x is ['%local,:.] then
+ x := x.rest
+ [x,[x,middleEndExpand y]]
+
++ Generate code that sequentially visits each component of a list.
expandIN(x,l,early?) ==
g := gensym() -- rest of the list yet to be visited
early? => -- give the loop variable a wider scope.
- [[[g,middleEndExpand l],[x,'NIL]],
+ [x,init] := loopVarInit(x,'%nil)
+ [[[g,middleEndExpand l],init],
nil,[['SETQ,g,['CDR,g]]],
nil,[['NOT,['CONSP,g]],['PROGN,['SETQ,x,['CAR,g]],'NIL]]]
+ [x,init] := loopVarInit(x,['%head,g])
[[[g,middleEndExpand l]],
- [[x,['CAR,g]]],[['SETQ,g,['CDR,g]]],
+ [init],[['SETQ,g,['CDR,g]]],
nil,[['NOT,['CONSP,g]]]]
expandON(x,l) ==
- [[[x,middleEndExpand l]],nil,[["SETQ",x,["CDR",x]]],nil,[["ATOM",x]]]
+ [x,init] := loopVarInit(x,l)
+ [[init],nil,[["SETQ",x,["CDR",x]]],nil,[["ATOM",x]]]
++ Generate code that traverses an interval with lower bound 'lo',
++ arithmetic progression `step, and possible upper bound `final'.
expandSTEP(id,lo,step,final)==
- lo := middleEndExpand lo
step := middleEndExpand step
final := middleEndExpand final
- loopvar := [[id,lo]]
+ [id,init] := loopVarInit(id,lo)
+ loopvar := [init]
inc :=
atomic? step => step
g1 := gensym()
@@ -133,6 +145,16 @@ expandIterators iters ==
it is ["%init",var,val] => expandInit(var,val)
nil
+massageFreeVarInits(body,inits) ==
+ inits = nil => body
+ inits is [[var,init]] and sameObject?(var,$freeVarName) =>
+ ['SEQ,init,['EXIT,body]]
+ for init in inits repeat
+ sameObject?(init.first,$freeVarName) =>
+ init.first := gensym()
+ ['LET,inits,body]
+
+
expandLoop ['%loop,:iters,body,ret] ==
itersCode := expandIterators iters
itersCode = "failed" => systemErrorHere ["expandLoop",iters]
@@ -145,25 +167,23 @@ expandLoop ['%loop,:iters,body,ret] ==
if filters ~= nil then
body := mkpf([:filters,body],"AND")
-- If there is any body-wide initialization, now is the time.
- if bodyInits ~= nil then
- body := ["LET",bodyInits,body]
+ body := massageFreeVarInits(body,bodyInits)
exits := ["COND",
[mkpf(exits,"OR"),["RETURN",expandToVMForm ret]],
[true,body]]
body := ["LOOP",exits,:cont]
-- Finally, set up loop-wide initializations.
- loopInits = nil => body
- ["LET",loopInits,body]
+ massageFreeVarInits(body,loopInits)
++ Generate code for list comprehension.
expandCollect ['%collect,:iters,body] ==
val := gensym() -- result of the list comprehension
-- Transform the body to build the list as we go.
- body := ["SETQ",val,["CONS",middleEndExpand body,val]]
+ body := ['%store,val,['%pair,body,val]]
-- Initialize the variable holding the result; expand as
-- if ordinary loop. But don't forget we built the result
-- in reverse order.
- expandLoop ['%loop,:iters,["%init",val,nil],body,["reverse!",val]]
+ expandLoop ['%loop,:iters,["%init",val,nil],body,['%lreverse!,val]]
expandList(x is ['%list,:args]) ==
args := [expandToVMForm arg for arg in args]