aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog9
-rw-r--r--src/interp/g-opt.boot13
-rw-r--r--src/interp/lisp-backend.boot44
3 files changed, 41 insertions, 25 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 126537fa..9a997f7f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,14 @@
2011-12-16 Gabriel Dos Reis <gdr@cs.tamu.edu>
+ * interp/g-opt.boot (freeIteratorFirstValues): New.
+ (cleanLoop!): Use it.
+ * interp/lisp-backend.boot ($freeVarName): Remove.
+ (loopVarInit): Do not generate initializer for free iterators.
+ Adjust callers.
+ (massageFreeVarInits): Remove. Adjust caller.
+
+2011-12-16 Gabriel Dos Reis <gdr@cs.tamu.edu>
+
* interp/compiler.boot (finishListCollect): New.
(compRepeatOrCollect): Use it.
* interp/g-opt.boot (optCollectVector): Likewise.
diff --git a/src/interp/g-opt.boot b/src/interp/g-opt.boot
index c93204bc..e529d56f 100644
--- a/src/interp/g-opt.boot
+++ b/src/interp/g-opt.boot
@@ -345,10 +345,21 @@ removeLeave! x == walkWith!(x,function f) where
x is ['%leave,.,y] and y is ['%return,:.] => resetTo(x,y)
x
+freeIteratorFirstValues iters ==
+ [u for it in iters | u := f it] where
+ f it ==
+ it is ['STEP,['%free,:id],lo,:.] => ['%LET,id,lo]
+ it is ['ON,['%free,:id],l] => ['%LET,id,l]
+ nil
+
cleanLoop! x == prefixWalk!(x,function f) where
f x ==
x is ['%scope,tag,['%repeat,:itl,body,val]] =>
- resetTo(x,f ['%repeat,:itl,g(body,tag),g(val,tag)])
+ body := g(body,tag)
+ val := g(val,tag)
+ firstVals := freeIteratorFirstValues itl =>
+ resetTo(x,mkSeq [:firstVals,f ['%repeat,:itl,body,val]])
+ resetTo(x,f ['%repeat,:itl,body,val])
x
g(x,tag) ==
atomic? x => x
diff --git a/src/interp/lisp-backend.boot b/src/interp/lisp-backend.boot
index f5fcf28f..fb1e012b 100644
--- a/src/interp/lisp-backend.boot
+++ b/src/interp/lisp-backend.boot
@@ -55,11 +55,8 @@ 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,['%LET,id,y]]]
+ x is ['%free,:id] => [id,nil] -- no init form for free iterators.
if x is ['%local,:.] then
x := x.rest
[x,[x,y]]
@@ -67,11 +64,13 @@ loopVarInit(x,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.
+ early? or x is ['%free,:.] => -- give the loop variable a wider scope.
[x,init] := loopVarInit(x,'%nil)
- [[[g,l],init],
- nil,[['%store,g,['%tail,g]]],
- nil,[['%not,['%pair?,g]],['%seq,['%store,x,['%head,g]],'%nil]]]
+ init :=
+ init = nil => [[g,l]]
+ [[g,l],init]
+ [init,nil,[['%store,g,['%tail,g]]],nil,
+ [['%not,['%pair?,g]],['%seq,['%store,x,['%head,g]],'%nil]]]
[x,init] := loopVarInit(x,['%head,g])
[[[g,l]],
[init],[['%store,g,['%tail,g]]],
@@ -79,13 +78,17 @@ expandIN(x,l,early?) ==
expandON(x,l) ==
[x,init] := loopVarInit(x,l)
- [[init],nil,[['%store,x,['%tail,x]]],nil,[['%not,['%pair?,x]]]]
+ if init ~= nil then
+ init := [init]
+ [init,nil,[['%store,x,['%tail,x]]],nil,[['%not,['%pair?,x]]]]
++ Generate code that traverses an interval with lower bound 'lo',
++ arithmetic progression `step, and possible upper bound `final'.
expandSTEP(id,lo,step,final)==
[id,init] := loopVarInit(id,lo)
- loopvar := [init]
+ loopvar :=
+ init = nil => nil
+ [init]
inc :=
atomic? step => step
g1 := gensym()
@@ -143,19 +146,9 @@ 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) =>
- ['%scope,nil,['%seq,init,['%leave,nil,body]]]
- for init in inits repeat
- sameObject?(init.first,$freeVarName) =>
- init.first := gensym()
- ['LET,inits,body]
-
-
expandRepeat ['%repeat,:iters,body,ret] ==
itersCode := expandIterators iters
- itersCode = "failed" => systemErrorHere ["expandLoop",iters]
+ itersCode is "failed" => systemErrorHere ["expandLoop",iters]
body := middleEndExpand body
itersCode := "coagulate"/itersCode
where
@@ -165,14 +158,17 @@ expandRepeat ['%repeat,:iters,body,ret] ==
if filters ~= nil then
body := mkpf([:filters,body],"AND")
-- If there is any body-wide initialization, now is the time.
- body := massageFreeVarInits(body,bodyInits)
+ if bodyInits ~= nil then
+ body := ['%bind,bodyInits,body]
exits :=
exits = nil => body
['%when,[mkpf(exits,"OR"),["RETURN",expandToVMForm ret]],
- [true,body]]
+ ['%otherwise,body]]
body := ['%loop,exits,:cont]
-- Finally, set up loop-wide initializations.
- expandToVMForm optimize! massageFreeVarInits(body,loopInits)
+ if loopInits ~= nil then
+ body := ['LET,loopInits,body]
+ expandToVMForm optimize! body
++ Generate code for list comprehension.
expandCollect ['%collect,:iters,body] ==