From 70917e529550d8b507dcd1c1ac65e600e1a48337 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Thu, 19 Nov 2020 13:00:42 -0700 Subject: [PATCH] (let...) --- src/kiss/SpecialForms.hx | 36 ++++++++++++++++++++++++++++++- src/test/cases/BasicTestCase.hx | 4 ++++ src/test/cases/BasicTestCase.kiss | 10 ++++++++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/kiss/SpecialForms.hx b/src/kiss/SpecialForms.hx index 866b6c36..6b764608 100644 --- a/src/kiss/SpecialForms.hx +++ b/src/kiss/SpecialForms.hx @@ -6,6 +6,7 @@ import kiss.Reader; import kiss.Types; using kiss.Helpers; +using kiss.Prelude; // Special forms convert Kiss reader expressions into Haxe macro expressions typedef SpecialFormFunction = (args:Array, convert:ExprConversion) -> Expr; @@ -34,7 +35,40 @@ class SpecialForms { // TODO special form for local var declaration - // TODO let + map["let"] = (args:Array, convert:ExprConversion) -> { + var bindingList = switch (args[0]) { + case ListExp(bindingExps) if (bindingExps.length > 0 && bindingExps.length % 2 == 0): + bindingExps; + default: + throw '${args[0]} should be a list expression with an even number of sub expressions'; + }; + var bindingPairs = bindingList.groups(2); + var varDefs = [ + for (bindingPair in bindingPairs) + { + name: switch (bindingPair[0]) { + case Symbol(name) | TypedExp(_, Symbol(name)): + name; + default: + throw 'first element of binding pair $bindingPair should be a symbol or typed symbol'; + }, + type: switch (bindingPair[0]) { + case TypedExp(type, _): + Helpers.parseTypePath(type); + default: null; + }, + isFinal: true, // Let's give (let...) variable immutability a try + expr: convert(bindingPair[1]) + } + ]; + + var body = args.slice(1); + if (body.length == 0) { + throw '(let....) expression with bindings $bindingPairs needs a body'; + } + + EBlock([EVars(varDefs).withPos(), EBlock(body.map(convert)).withPos()]).withPos(); + }; // TODO special form for lambda diff --git a/src/test/cases/BasicTestCase.hx b/src/test/cases/BasicTestCase.hx index 323c2434..8b73882b 100644 --- a/src/test/cases/BasicTestCase.hx +++ b/src/test/cases/BasicTestCase.hx @@ -146,4 +146,8 @@ class BasicTestCase extends Test { Assert.equals([[1, 2], [3, 4]].toString(), BasicTestCase.myGroups1().toString()); Assert.equals([[1, 2, 3], [4]].toString(), BasicTestCase.myGroups2().toString()); } + + function testLet() { + _testLet(); + } } diff --git a/src/test/cases/BasicTestCase.kiss b/src/test/cases/BasicTestCase.kiss index b23bc54f..a3aff4f5 100644 --- a/src/test/cases/BasicTestCase.kiss +++ b/src/test/cases/BasicTestCase.kiss @@ -91,4 +91,12 @@ (Prelude.groups [1 2 3 4] 2)) (defun myGroups2 [] - (Prelude.groups [1 2 3 4] 3 true)) \ No newline at end of file + (Prelude.groups [1 2 3 4] 3 true)) + +(defun _testLet [] + (let [a 5 + b 6 + :String c "stuff"] + (Assert.equals 5 a) + (Assert.equals 6 b) + (Assert.equals "stuff" c))) \ No newline at end of file