summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-05-01 21:00:18 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-05-01 21:00:18 -0700
commitaf08d50472cedf839e3260e2d6e745fc3836d2fc (patch)
tree35288166ce17f2f06c8446ef2e594ab6c492d8b4 /share
parent771499a17a7d6dcdc962e74201d7ee0ffa8d9f87 (diff)
downloadtxr-af08d50472cedf839e3260e2d6e745fc3836d2fc.tar.gz
txr-af08d50472cedf839e3260e2d6e745fc3836d2fc.tar.bz2
txr-af08d50472cedf839e3260e2d6e745fc3836d2fc.zip
compiler: correct semantics of special var args.
The same, correct semantics for special variables in function arguments get implemented in the compiler. * share/txr/stdlib/compiler.tl (compiler comp-lambda): We stick with the strategy that each parameter which is a special variable is aliased by an anonymous lexical variable. The difference is that we bind the underlying special variable from the hidden lexical's value as early as possible. The overall processing is rearranged. On entry into the function, if any of the required arguments are specials, their values are immediately bound to the special variables in a new environment. Then the optional arguments are processed, and they bind specials in the dynamic environment also. Previously, the specials were bound in one fell swoop after processing the optionals, leading to the same incorrect semantics that the interpreter code had.
Diffstat (limited to 'share')
-rw-r--r--share/txr/stdlib/compiler.tl22
1 files changed, 15 insertions, 7 deletions
diff --git a/share/txr/stdlib/compiler.tl b/share/txr/stdlib/compiler.tl
index 2d8962e3..8af7384f 100644
--- a/share/txr/stdlib/compiler.tl
+++ b/share/txr/stdlib/compiler.tl
@@ -780,12 +780,13 @@
(let* ((pars (new (fun-param-parser par-syntax form)))
(need-frame (or (plusp pars.nfix) pars.rest))
(nenv (if need-frame (new env up env co me) env))
- lexsyms specials)
+ lexsyms specials need-dframe)
(flet ((spec-sub (sym)
(cond
((special-var-p sym)
(let ((sub (gensym)))
(push (cons sym sub) specials)
+ (set need-dframe t)
nenv.(extend-var sub)
sub))
(t
@@ -804,12 +805,12 @@
(let* ((col-reg (if opt-pars me.(get-dreg :)))
(tee-reg (if opt-pars me.(get-dreg t)))
(ifrags (collect-each ((op opt-pars))
- (tree-bind (var-sym : init-form have-sym) op
+ (tree-bind (var-sym init-form have-sym) op
(let ((vbind nenv.(lookup-var var-sym)))
me.(compile vbind.loc nenv init-form)))))
(opt-code (append-each ((op opt-pars)
(ifrg ifrags))
- (tree-bind (var-sym : init-form have-sym) op
+ (tree-bind (var-sym init-form have-sym) op
(let ((vbind nenv.(lookup-var var-sym))
(have-bind nenv.(lookup-var have-sym))
(lskip (gensym "l")))
@@ -820,7 +821,14 @@
^((mov ,have-bind.loc nil)))
,*ifrg.code
,*(maybe-mov vbind.loc ifrg.oreg)
- ,lskip)))))
+ ,lskip
+ ,*(whenlet ((spec-sub [find var-sym specials : cdr]))
+ (set specials [remq var-sym specials cdr])
+ ^((bindv ,vbind.loc ,me.(get-dreg (car spec-sub)))))
+ ,*(whenlet ((spec-sub [find have-sym specials : cdr]))
+ (prinl 'have)
+ (set specials [remq have-sym specials cdr])
+ ^((bindv ,have-bind.loc ,me.(get-dreg (car spec-sub))))))))))
(benv (if specials (new env up nenv co me) nenv))
(btreg me.(alloc-treg))
(bfrag me.(comp-progn btreg benv body))
@@ -837,8 +845,7 @@
nenv.(lookup-var (car op)).loc)
,*(if rest-par
(list nenv.(lookup-var rest-par).loc)))
- ,*opt-code
- ,*(if specials
+ ,*(if need-dframe
^((dframe ,benv.lev 0)))
,*(if specials
(collect-each ((vs specials))
@@ -846,8 +853,9 @@
(let ((sub-bind nenv.(lookup-var gensym))
(dreg me.(get-dreg special)))
^(bindv ,sub-bind.loc ,dreg)))))
+ ,*opt-code
,*bfrag.code
- ,*(if specials
+ ,*(if need-dframe
^((end ,boreg)))
,*(maybe-mov boreg bfrag.oreg)
(end ,boreg)