From f033b0cf7b17e9e3137829a1d0677793105abbb5 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Tue, 1 Dec 2020 16:25:59 -0700 Subject: [PATCH] Fix list destructuring multiple-evaluation bug --- projects/advent-of-code/src/year2020/Solutions.kiss | 1 - src/kiss/SpecialForms.hx | 10 +++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/projects/advent-of-code/src/year2020/Solutions.kiss b/projects/advent-of-code/src/year2020/Solutions.kiss index a7e74e70..2cf18c92 100644 --- a/projects/advent-of-code/src/year2020/Solutions.kiss +++ b/projects/advent-of-code/src/year2020/Solutions.kiss @@ -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"))) diff --git a/src/kiss/SpecialForms.hx b/src/kiss/SpecialForms.hx index 5a0d160a..7c705d44 100644 --- a/src/kiss/SpecialForms.hx +++ b/src/kiss/SpecialForms.hx @@ -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"); };