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.boot70
1 files changed, 36 insertions, 34 deletions
diff --git a/src/interp/compiler.boot b/src/interp/compiler.boot
index 6323bf51..7ac0ce3e 100644
--- a/src/interp/compiler.boot
+++ b/src/interp/compiler.boot
@@ -1229,7 +1229,7 @@ canReturn(expr,level,exitCount,ValueFlag) == --SPAD: exit and friends
or/[findThrow(gs,u,level+1,exitCount,ValueFlag) for u in l]
or/[findThrow(gs,u,level,exitCount,ValueFlag) for u in rest expr]
canReturn(data,level,exitCount,ValueFlag)
- op = "COND" =>
+ op = "COND" or op = '%when =>
level = exitCount =>
or/[canReturn(last u,level,exitCount,ValueFlag) for u in rest expr]
or/[or/[canReturn(u,level,exitCount,ValueFlag) for u in v]
@@ -1241,7 +1241,7 @@ canReturn(expr,level,exitCount,ValueFlag) == --SPAD: exit and friends
pp expr
canReturn(a,level,exitCount,nil) or canReturn(b,level,exitCount,ValueFlag)
or canReturn(c,level,exitCount,ValueFlag)
- op = "LET" or op = "LET*" =>
+ op in '(LET LET_* %bind) =>
or/[canReturn(init,level,exitCount,false) for [.,init] in second expr]
or canReturn(third expr,level,exitCount,ValueFlag)
--now we have an ordinary form
@@ -2145,7 +2145,7 @@ compMatchAlternative(sn,sm,pat,stmt,m,e) ==
body :=
null inits => stmtT.expr
atom sn => ["LET",inits,stmtT.expr]
- ["LET*",inits,stmtT.expr]
+ ["%bind",inits,stmtT.expr]
[[guard,body],stmtT.mode,stmtT.env,eF]
++ Analyze and generate code for `is case'-pattern where the
@@ -2171,7 +2171,7 @@ compMatch(["%Match",subject,altBlock],m,env) ==
stackAndThrow('"missing %b otherwise %d alternative in case pattern",nil)
code :=
atom sn => ["LET",[[sn,se]],["COND",:nreverse altsCode]]
- ["LET*",[[n,e] for n in sn for e in rest se],
+ ["%bind",[[n,e] for n in sn for e in rest se],
["COND",:nreverse altsCode]]
[code,m,savedEnv]
@@ -2205,46 +2205,48 @@ compReduce(form,m,e) ==
compReduce1(form,m,e,$formalArgList)
compReduce1(form is ["REDUCE",op,.,collectForm],m,e,$formalArgList) ==
- [collectOp,:itl,body]:= collectForm
- if string? op then op:= INTERN op
+ [collectOp,:itl,body] := collectForm
+ if string? op then op := INTERN op
collectOp ~= "COLLECT" => systemError ['"illegal reduction form:",form]
- $sideEffectsList: local := nil
$until: local := nil
- $initList: local := nil
- $endTestList: local := nil
oldEnv := e
- $e:= e
- itl:= [([.,$e]:= compIterator(x,$e) or return "failed").0 for x in itl]
+ itl := [([.,e]:= compIterator(x,e) or return "failed").0 for x in itl]
itl="failed" => return nil
- e:= $e
- acc:= gensym()
- afterFirst:= gensym()
- bodyVal:= gensym()
- [part1,m,e]:= comp(["%LET",bodyVal,body],m,e) or return nil
- [part2,.,e]:= comp(["%LET",acc,bodyVal],m,e) or return nil
- [part3,.,e]:= comp(["%LET",acc,parseTran [op,acc,bodyVal]],m,e) or return nil
- identityCode:=
- id:= getIdentity(op,e) => u.expr where u() == comp(id,m,e) or return nil
+ b := gensym() -- holds value of the body
+ [bval,bmode,e] := comp(['%LET,b,body],$EmptyMode,e) or return nil
+ accu := gensym() -- holds value of the accumulator
+ [move,.,e] := comp(['%LET,accu,b],$EmptyMode,e) or return nil
+ move.op := '%store -- in reality, we are not defining a new variable
+ [update,mode,e] := comp(['%LET,accu,[op,accu,b]],m,e) or return nil
+ update.op := '%store -- just update the accumulation variable.
+ nval :=
+ id := getIdentity(op,e) => u.expr where
+ u() == comp(id,mode,e) or return nil
["IdentityError",MKQ op]
- finalCode:=
- ["PROGN",
- ["%LET",afterFirst,nil],
- ["REPEAT",:itl,
- ["PROGN",part1,
- ["IF", afterFirst,part3,
- ["PROGN",part2,["%LET",afterFirst,MKQ true]]]]],
- ["IF",afterFirst,acc,identityCode]]
if $until then
- [untilCode,.,e]:= comp($until,$Boolean,e)
- finalCode:= substitute(["UNTIL",untilCode],'$until,finalCode)
- [finalCode,m,oldEnv]
+ [untilCode,.,e]:= comp($until,$Boolean,e) or return nil
+ itl := substitute(["UNTIL",untilCode],'$until,itl)
+ firstTime := gensym()
+ finalCode := ['%reduce,
+ ['%init,accu,'%nil],['%init,firstTime,'%true],:itl,
+ ['%when,[firstTime,nval],['%otherwise,accu]],
+ ['%bind,[[b,third bval]],
+ ['%when,[firstTime,move],['%otherwise,update]],
+ ['%store,firstTime,'%false]]]
+ T := coerce([finalCode,mode,e],m) or return nil
+ [T.expr,T.mode,oldEnv]
++ returns the identity element of the `reduction' operation `x'
++ over a list -- a monoid homomorphism.
getIdentity(x,e) ==
- -- The empty list should be indicated by name, not by its
- -- object representation.
- GETL(x,"THETA") is [y] => (y => y; "nil")
+ GETL(x,"THETA") is [y] =>
+ y = 0 => $Zero
+ y = 1 => $One
+ -- The empty list should be indicated by name, not by its
+ -- object representation.
+ y => y
+ "nil"
+ nil
numberize x ==
x=$Zero => 0