diff options
Diffstat (limited to 'src/interp/compiler.boot')
-rw-r--r-- | src/interp/compiler.boot | 51 |
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] |