aboutsummaryrefslogtreecommitdiff
path: root/src/interp
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp')
-rw-r--r--src/interp/c-util.boot6
-rw-r--r--src/interp/g-opt.boot29
-rw-r--r--src/interp/g-util.boot9
3 files changed, 39 insertions, 5 deletions
diff --git a/src/interp/c-util.boot b/src/interp/c-util.boot
index ab80ac63..17d630b4 100644
--- a/src/interp/c-util.boot
+++ b/src/interp/c-util.boot
@@ -1620,8 +1620,10 @@ transformToBackendCode x ==
-- Make it explicitly a sequence of statements if it is not a one liner.
body :=
body is [stmt] and
- (atom stmt or stmt.op = "SEQ" or not CONTAINED("EXIT",stmt)) =>
- body
+ (atom stmt
+ or stmt.op in '(SEQ LET LET_*)
+ or not CONTAINED("EXIT",stmt)) =>
+ body
[simplifySEQ ["SEQ",:body]]
$FluidVars := removeDuplicates nreverse $FluidVars
$LocalVars := S_-(S_-(removeDuplicates nreverse $LocalVars,$FluidVars),
diff --git a/src/interp/g-opt.boot b/src/interp/g-opt.boot
index e47f7be0..f8e28b42 100644
--- a/src/interp/g-opt.boot
+++ b/src/interp/g-opt.boot
@@ -79,6 +79,33 @@ changeVariableDefinitionToStore(form,vars) ==
x is ['%LET,v,:.] and not (v in vars) =>
vars := [v,:vars]
+++ Return true if `x' contains control transfer to a point outside itself.
+jumpToToplevel? x ==
+ isAtomicForm x => false
+ op := x.op
+ op = 'SEQ => CONTAINED('THROW,x.args)
+ op in '(EXIT THROW %leave) => true
+ or/[jumpToToplevel? x' for x' in x]
+
+++ Return true if `form' is just one assignment expression.
+singleAssignment? form ==
+ form is ['%LET,.,rhs] and not CONTAINED('%LET,rhs)
+
+++ Turns `form' into a `%bind'-expression if it starts with a
+++ a sequence of first-time variable definitions.
+groupVariableDefinitions form ==
+ isAtomicForm form => form
+ form isnt ['SEQ,:stmts,['EXIT,val]] => form
+ defs := nil
+ for x in stmts while singleAssignment? x repeat
+ defs := [x.args,:defs]
+ defs = nil or jumpToToplevel? defs => form
+ stmts := drop(#defs,stmts)
+ expr :=
+ stmts = nil => val
+ ['SEQ,:stmts,['EXIT,val]]
+ ['%bind,nreverse defs,expr]
+
optimizeFunctionDef(def) ==
if $reportOptimization then
sayBrightlyI bright '"Original LISP code:"
@@ -109,7 +136,7 @@ optimizeFunctionDef(def) ==
replaceThrowByReturn(first x,g)
replaceThrowByReturn(rest x,g)
changeVariableDefinitionToStore(body',args)
- [name,[slamOrLam,args,body']]
+ [name,[slamOrLam,args,groupVariableDefinitions body']]
optimize x ==
(opt x; x) where
diff --git a/src/interp/g-util.boot b/src/interp/g-util.boot
index ed134390..bf4a02ee 100644
--- a/src/interp/g-util.boot
+++ b/src/interp/g-util.boot
@@ -227,11 +227,16 @@ expandEq ["%eq",:args] ==
["EQ",:expandToVMForm args]
-- Local variable bindings
-expandBind ["%bind",inits,body] ==
+expandBind ['%bind,inits,body] ==
body := expandToVMForm body
inits := [[first x,expandToVMForm second x] for x in inits]
+ n := #inits
+ n = 0 => body
-- FIXME: we should consider turning LET* into LET or direct inlining.
- ["LET*",inits,body]
+ op :=
+ n = 1 => 'LET
+ 'LET_*
+ [op,inits,body]
-- Memory load/store