From 6a297bfcace1151d0f1840c8d7408c128c740962 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Sat, 16 Jan 2021 21:27:43 -0700 Subject: [PATCH] ifLet --- kiss/src/kiss/Macros.hx | 48 +++++++++++++++++++++++++- kiss/src/test/cases/BasicTestCase.hx | 4 +++ kiss/src/test/cases/BasicTestCase.kiss | 18 +++++++++- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/kiss/src/kiss/Macros.hx b/kiss/src/kiss/Macros.hx index cc0ecaea..917c750a 100644 --- a/kiss/src/kiss/Macros.hx +++ b/kiss/src/kiss/Macros.hx @@ -419,7 +419,53 @@ class Macros { return null; }; - // TODO macros for ifLet, whenLet (for assign then truthy check), caseLet (for extracting from enums) + // Macros that null-check and extract patterns from enums (inspired by Rust) + function ifLet(wholeExp:ReaderExp, exps:Array, k:KissState) { + wholeExp.checkNumArgs(2, null, "(ifLet [[enum bindings...]] [thenExp] [?elseExp])"); + var b = wholeExp.expBuilder(); + + var thenExp = exps[1]; + var elseExp = if (exps.length > 2) { + exps[2]; + } else { + b.symbol("null"); + }; + + var bindingList = exps[0].bindingList("ifLet"); + var firstPattern = bindingList.shift(); + var firstValue = bindingList.shift(); + + return b.call( + b.symbol("if"), [ + firstValue, + b.call( + b.symbol("case"), [ + firstValue, + b.call( + firstPattern, [ + if (bindingList.length == 0) { + exps[1]; + } else { + ifLet(wholeExp, [ + b.list(bindingList) + ].concat(exps.slice(1)), k); + } + ]), + b.call( + b.symbol("otherwise"), [ + elseExp + ]) + ]), + elseExp + ]); + } + + macros["ifLet"] = ifLet; + + // TODO whenLet + // wholeExp.checkNumArgs(2, null, "(whenLet [[enum bindings...]] [body...])"); + // TODO unlessLet + // wholeExp.checkNumArgs(2, null, "(unlessLet [[enum bindings...]] [body...])"); // TODO use expBuilder() function awaitLet(wholeExp:ReaderExp, exps:Array, k:KissState) { diff --git a/kiss/src/test/cases/BasicTestCase.hx b/kiss/src/test/cases/BasicTestCase.hx index df82a90e..501ce124 100644 --- a/kiss/src/test/cases/BasicTestCase.hx +++ b/kiss/src/test/cases/BasicTestCase.hx @@ -269,6 +269,10 @@ class BasicTestCase extends Test { function testAssignArith() { _testAssignArith(); } + + function testPatternLets() { + _testPatternLets(); + } } class BasicObject { diff --git a/kiss/src/test/cases/BasicTestCase.kiss b/kiss/src/test/cases/BasicTestCase.kiss index d77fe717..34e59939 100644 --- a/kiss/src/test/cases/BasicTestCase.kiss +++ b/kiss/src/test/cases/BasicTestCase.kiss @@ -436,4 +436,20 @@ (/= num 25 2) (Assert.equals 1 num) (-= num 5 6) - (Assert.equals -10 num)) \ No newline at end of file + (Assert.equals -10 num)) + +(defun _testPatternLets [] + (let [some5 (Some 5) + some6 (Some 6) + none None + :Null> oops null] + (ifLet [(Some a) some5 + (Some b) some6] + (Assert.equals 11 (+ a b)) + (Assert.fail)) + (ifLet [(Some a) oops] + (Assert.fail)) + (ifLet [(Some (or 5 6)) some5] + (Assert.pass)) + (ifLet [(Some a) none] + (Assert.fail)))) \ No newline at end of file