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 []
// Day 1
// TODO implement unless
// TODO list destructuring a funcall results in double evaluation
(let [p (pairWithSum 2020 [1721 979 366 299 675 1456])]
(when !(and (has p 1721) (has p 299))
(throw "pairWithSum is broken")))

View File

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