aboutsummaryrefslogtreecommitdiff
path: root/src/interp/compiler.boot
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp/compiler.boot')
-rw-r--r--src/interp/compiler.boot51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/interp/compiler.boot b/src/interp/compiler.boot
index c4428079..64715539 100644
--- a/src/interp/compiler.boot
+++ b/src/interp/compiler.boot
@@ -2392,6 +2392,8 @@ processInlineRequest(t,e) ==
--% ITERATORS
--%
+++ Generate code for collecting values generated by the expression `body'
+++ controlled by iterators in `iters' into a list.
finishListCollect(iters,body) ==
val := gensym() -- result of the list comprehension
-- Transform the body to build the list as we go.
@@ -2399,6 +2401,53 @@ finishListCollect(iters,body) ==
-- Don't forget we built the result in reverse order.
['%repeat,:iters,['%init,val,'%nil],body,['%lreverse!,val]]
+++ Generate code for collecting values generated by the expression `body'
+++ controlled by iterators in `iters' into a vector with element
+++ type indicated by `eltType'.
+finishVectorCollect(eltType,iters,body) ==
+ fromList := false -- are we drawing from a list?
+ vecSize := nil -- size of vector
+ index := nil -- loop/vector index.
+ for iter in iters while not fromList repeat
+ [op,:.] := iter
+ op in '(_| SUCHTHAT WHILE UNTIL) => fromList := true
+ op in '(IN ON) => vecSize := [['%llength,third iter],:vecSize]
+ op in '(STEP ISTEP) =>
+ -- pick a loop variable that we can use as the loop index.
+ [.,var,lo,inc,:etc] := iter
+ if lo = 0 and inc = 1 then
+ index :=
+ var is [.,:var'] => var'
+ var
+ if [hi] := etc then
+ sz :=
+ inc = 1 =>
+ lo = 1 => hi
+ lo = 0 => ['%iinc,hi]
+ ['%iinc,['%isub,hi,lo]]
+ lo = 1 => ['%idiv,hi,inc]
+ lo = 0 => ['%idiv,['%iinc,hi],inc]
+ ['%idiv,['%isub,['%iinc,hi], lo],inc]
+ vecSize := [sz, :vecSize]
+ systemErrorHere ['finishVectorCollect, iter]
+ -- if we draw from a list, then just build a list and convert to vector.
+ fromList =>
+ ['homogeneousListToVector,['getVMType,eltType],
+ finishListCollect(iters,body)]
+ vecSize = nil => systemErrorHere ['finishVectorCollect,eltType,iters,body]
+ -- get the actual size of the vector.
+ vecSize :=
+ vecSize is [hi] => hi
+ ['%imin,:reverse! vecSize]
+ -- if no suitable loop index was found, introduce one.
+ if index = nil then
+ index := gensym()
+ iters := [:iters,['STEP,index,0,1]]
+ vec := gensym()
+ ['%bind,[[vec,['makeSimpleArray,['getVMType,eltType],vecSize]]],
+ ['%repeat,:iters,['setSimpleArrayEntry,vec,index,body],vec]]
+
+
compReduce(form,m,e) ==
compReduce1(form,m,e,$formalArgList)
@@ -2500,7 +2549,7 @@ compRepeatOrCollect(form,m,e) ==
itl':= substitute(["UNTIL",untilCode],'$until,itl')
form':=
$loopKind = "%CollectV" =>
- ["%CollectV",localReferenceIfThere(m',e'),:itl',body']
+ finishVectorCollect(localReferenceIfThere(m',e'),itl',body')
-- We are phasing out use of LISP macros COLLECT and REPEAT.
$loopKind = "COLLECT" => finishListCollect(itl',body')
['%repeat,:itl',body','%nil]