Fix list destructuring multiple-evaluation bug

This commit is contained in:
2020-12-01 16:25:59 -07:00
parent 0f30d5d2e7
commit f033b0cf7b
2 changed files with 7 additions and 4 deletions

View File

@@ -1,7 +1,6 @@
(defun main [] (defun main []
// Day 1 // Day 1
// TODO implement unless // TODO implement unless
// TODO list destructuring a funcall results in double evaluation
(let [p (pairWithSum 2020 [1721 979 366 299 675 1456])] (let [p (pairWithSum 2020 [1721 979 366 299 675 1456])]
(when !(and (has p 1721) (has p 299)) (when !(and (has p 1721) (has p 299))
(throw "pairWithSum is broken"))) (throw "pairWithSum is broken")))

View File

@@ -112,13 +112,17 @@ class SpecialForms {
case Symbol(_) | TypedExp(_, {pos: _, def: Symbol(_)}): case Symbol(_) | TypedExp(_, {pos: _, def: Symbol(_)}):
[toVar(namesExp, valueExp, k, isFinal)]; [toVar(namesExp, valueExp, k, isFinal)];
case ListExp(nameExps): case ListExp(nameExps):
var uniqueVarName = "_" + Uuid.v4().toShort();
var uniqueVarSymbol = Symbol(uniqueVarName).withPosOf(valueExp);
var idx = 0; var idx = 0;
[ // Only evaluate the list expression being destructured once:
[toVar(uniqueVarSymbol, valueExp, k, true)].concat([
for (nameExp in nameExps) for (nameExp in nameExps)
toVar(nameExp, toVar(nameExp,
CallExp(Symbol("nth").withPosOf(valueExp), [valueExp, Symbol(Std.string(idx++)).withPosOf(valueExp)]).withPosOf(valueExp), CallExp(Symbol("nth").withPosOf(valueExp),
[uniqueVarSymbol, Symbol(Std.string(idx++)).withPosOf(valueExp)]).withPosOf(valueExp),
k, if (isFinal == false) false else null) k, if (isFinal == false) false else null)
]; ]);
default: default:
throw CompileError.fromExp(namesExp, "Can only bind variables to a symbol or list of symbols for destructuring"); throw CompileError.fromExp(namesExp, "Can only bind variables to a symbol or list of symbols for destructuring");
}; };