Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
parenscript
parenscript
Commits
5d143121
Verified
Commit
5d143121
authored
Oct 16, 2018
by
Vladimir Sedach
Browse files
Fixed capture of loop variables, up to let renaming
parent
76f33d35
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/function-definition.lisp
View file @
5d143121
...
...
@@ -157,9 +157,9 @@ of (declare ...) forms, and the remaining body."
(
defun
compile-function-body
(
args
body
)
(
with-declaration-effects
(
body
body
)
(
let*
((
in-function-scope?
t
)
(
*vars-needing-to-be-declared*
())
(
*used-up-names*
())
(
let*
((
in-function-scope?
t
)
(
*vars-needing-to-be-declared*
())
(
*used-up-names*
())
(
*enclosing-function-arguments*
(
append
args
*enclosing-function-arguments*
))
(
*enclosing-lexicals*
...
...
@@ -185,8 +185,7 @@ of (declare ...) forms, and the remaining body."
(
compile-statement
`
(
progn
,@
(
mapcar
(
lambda
(
var
)
`
(
var
,
var
))
(
lambda
(
var
)
`
(
var
,
var
))
(
remove-duplicates
*vars-needing-to-be-declared*
))))))
(
when
in-loop-scope?
;; this might be broken when it comes to let-renaming
(
setf
*loop-scope-lexicals-captured*
...
...
src/special-operators.lisp
View file @
5d143121
...
...
@@ -634,24 +634,20 @@ Parenscript now implements implicit return, update your code! Things like (lambd
init-forms
))
(
defun
compile-loop-body
(
loop-vars
body
)
(
let*
((
in-loop-scope?
t
)
;; provides lexical bindings for all free variables using WITH
(
in-function-scope?
t
)
(
*loop-scope-lexicals*
loop-vars
)
(
*loop-scope-lexicals-captured*
())
(
*ps-gensym-counter*
*ps-gensym-counter*
)
(
compiled-body
(
compile-statement
`
(
progn
,@
body
))))
;; the sort is there to make order for output-tests consistent across implementations
(
aif
(
sort
(
remove-duplicates
*loop-scope-lexicals-captured*
)
#'
string<
:key
#'
symbol-name
)
(
let*
((
in-loop-scope?
t
)
;; provides lexical bindings for all free variables using WITH
(
in-function-scope?
t
)
(
*loop-scope-lexicals*
())
(
*loop-scope-lexicals-captured*
())
(
*ps-gensym-counter*
*ps-gensym-counter*
)
(
compiled-body
(
compile-statement
`
(
progn
,@
body
))))
(
aif
(
remove-duplicates
*loop-scope-lexicals-captured*
)
`
(
ps-js:block
(
ps-js:with
,
(
compile-expression
`
(
create
,@
(
loop
for
x
in
it
collect
x
collect
(
when
(
member
x
loop-vars
)
x
))))
,
compiled-body
))
,
(
compile-expression
`
(
create
,@
(
mapcan
(
lambda
(
x
)
(
list
x
nil
))
it
)))
,
compiled-body
))
compiled-body
)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
...
...
tests/eval-tests.lisp
View file @
5d143121
...
...
@@ -810,3 +810,25 @@
(
test-js-eval
lambda-not-a-docstring
((
lambda
()
"bar"
))
"bar"
)
(
test-js-eval
loop-variable-capture1
(
let
((
x
(
make-array
10
)))
(
dotimes
(
i
10
)
(
setf
(
aref
x
i
)
(
lambda
()
i
)))
(
loop
for
x
across
x
sum
(
funcall
x
)))
100
)
(
test-js-eval
loop-variable-capture2
(
let
((
x
(
make-array
10
)))
(
dotimes
(
i
10
)
(
let
((
y
i
))
(
setf
(
aref
x
i
)
(
lambda
()
y
))))
(
loop
for
x
across
x
sum
(
funcall
x
)))
45
)
(
test-js-eval
loop-variable-capture3
(
let
((
x
(
make-array
10
)))
(
dotimes
(
i
10
)
(
let
((
i
i
))
(
setf
(
aref
x
i
)
(
lambda
()
i
))))
(
loop
for
x
across
x
sum
(
funcall
x
)))
45
)
tests/output-tests.lisp
View file @
5d143121
...
...
@@ -2687,12 +2687,11 @@ return x.offsetLeft;
(
test-ps-js
try-catch-return
(
defun
foo
()
(
return-from
foo
(
try
(
foo
)
(
:catch
(
e
)
(
bar
))
(
:finally
(
cleanup
)))))
(
try
(
foo
)
(
:catch
(
e
)
(
bar
))
(
:finally
(
cleanup
))))
"function foo() {
try {
return foo();
...
...
@@ -2703,6 +2702,21 @@ try {
};
};"
)
(
test-ps-js
let-try
(
let
((
x
(
ps:try
(
+
1
2
)
(
:catch
(
y
)
5
))))
x
)
"(function () {
var x = (function () {
try {
return 1 + 2;
} catch (y) {
return 5;
};
})();
return x;
})();"
)
(
test-ps-js
try-finally-return-from
(
defun
xyz
()
(
return-from
xyz
...
...
@@ -3327,15 +3341,12 @@ var x = bar();")
};
});"
)
;; closures in loops need a new binding per loop iteration (idea borrowed from Scheme2JS)
(
test-ps-js
loop-closures
(
dotimes
(
i
10
)
(
lambda
()
(
+
i
1
)))
"(function () {
for (var i = 0; i < 10; i += 1) {
with ({ i : i }) {
function () {
return i + 1;
};
function () {
return i + 1;
};
};
})();"
)
...
...
@@ -3346,7 +3357,7 @@ for (var i = 0; i < 10; i += 1) {
(
lambda
()
(
+
i
x
))))
"(function () {
for (var i = 0; i < 10; i += 1) {
with ({
i : i,
x : null }) {
with ({ x : null }) {
var x = i + 1;
function () {
return i + x;
...
...
@@ -3356,10 +3367,12 @@ for (var i = 0; i < 10; i += 1) {
})();"
)
(
test-ps-js
loop-closures-flet
(
dotimes
(
i
10
)
(
flet
((
foo
(
x
)
(
+
i
x
)))
(
lambda
()
(
foo
i
))))
(
dotimes
(
i
10
)
(
flet
((
foo
(
x
)
(
+
i
x
)))
(
lambda
()
(
foo
i
))))
"(function () {
for (var i = 0; i < 10; i += 1) {
with ({ foo : null
, i : i
}) {
with ({ foo : null }) {
var foo = function (x) {
return i + x;
};
...
...
@@ -3372,13 +3385,13 @@ for (var i = 0; i < 10; i += 1) {
(
test-ps-js
while-closures-let
(
while
(
foo
)
(
let
((
x
(
bar
)))
(
lambda
()
(
+
1
x
))))
(
let
((
abc
(
bar
)))
(
lambda
()
(
+
1
abc
))))
"while (foo()) {
with ({
x
: null }) {
var
x
= bar();
with ({
abc
: null }) {
var
abc
= bar();
function () {
return 1 +
x
;
return 1 +
abc
;
};
};
};"
)
...
...
@@ -3529,14 +3542,13 @@ for (var i = 0; i < 10; i += 1) {
})();"
)
(
test-ps-js
iteration-lambda-capture-no-need
(
dolist
(
x
y
)
(
lambda
(
x
)
(
1+
x
)))
;; there's really no need to create a 'with' scope in this case
(
dolist
(
x
y
)
(
lambda
(
x
)
(
1+
x
)))
"(function () {
for (var x = null, _js_idx1 = 0; _js_idx1 < y.length; _js_idx1 += 1) {
with ({ x : x }) {
x = y[_js_idx1];
function (x) {
return x + 1;
};
x = y[_js_idx1];
function (x) {
return x + 1;
};
};
})();"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment