diff --git a/src/kiss/Macros.hx b/src/kiss/Macros.hx index 427ec6a..d415001 100644 --- a/src/kiss/Macros.hx +++ b/src/kiss/Macros.hx @@ -497,10 +497,13 @@ class Macros { return null; }; - macros["defalias"] = (wholeExp:ReaderExp, exps:Array, k:KissState) -> { - wholeExp.checkNumArgs(2, 2, "(defalias [[&call or &ident] whenItsThis] [makeItThis])"); - var aliasMap:Map = null; - var nameExp = switch (exps[0].def) { + // Having this floating out here is sketchy, but should work out fine because the variable is always re-set + // through the next function before being used in defalias or undefalias + var aliasMap:Map = null; + + function getAliasName(k:KissState, nameExpWithMeta:ReaderExp, formName:String):String { + var error = CompileError.fromExp(nameExpWithMeta, 'first argument to $formName should be &call [alias] or &ident [alias]'); + var nameExp = switch (nameExpWithMeta.def) { case MetaExp("call", nameExp): aliasMap = k.callAliases; nameExp; @@ -508,18 +511,32 @@ class Macros { aliasMap = k.identAliases; nameExp; default: - throw CompileError.fromExp(exps[0], 'first argument to defalias should be a symbol for the alias annotated with either &call or &ident'); + throw error; }; - var name = switch (nameExp.def) { + return switch (nameExp.def) { case Symbol(whenItsThis): whenItsThis; default: - throw CompileError.fromExp(exps[0], 'first argument to defalias should be a symbol for the alias annotated with either &call or &ident'); + throw error; }; + } + + macros["defalias"] = (wholeExp:ReaderExp, exps:Array, k:KissState) -> { + wholeExp.checkNumArgs(2, 2, "(defalias [[&call or &ident] whenItsThis] [makeItThis])"); + var name = getAliasName(k, exps[0], "defalias"); + aliasMap[name] = exps[1].def; return null; }; + macros["undefalias"] = (wholeExp:ReaderExp, exps:Array, k:KissState) -> { + wholeExp.checkNumArgs(1, 1, "(undefalias [[&call or &ident] alias])"); + var name = getAliasName(k, exps[0], "undefalias"); + + aliasMap.remove(name); + return null; + }; + // Macros that null-check and extract patterns from enums (inspired by Rust) function ifLet(wholeExp:ReaderExp, exps:Array, k:KissState) { wholeExp.checkNumArgs(2, 3, "(ifLet [[enum bindings...]] [thenExp] [?elseExp])"); diff --git a/src/test/cases/ListEatingTestCase.kiss b/src/test/cases/ListEatingTestCase.kiss index 4bd4824..bbf7ebb 100644 --- a/src/test/cases/ListEatingTestCase.kiss +++ b/src/test/cases/ListEatingTestCase.kiss @@ -23,6 +23,7 @@ (Assert.equals 4 b)) (otherwise (Assert.fail))) + (case l ([::...rest last] (Assert.equals (.toString [1 2 3]) (.toString rest)) diff --git a/src/test/cases/MacroTestCase.hx b/src/test/cases/MacroTestCase.hx index f482efc..35cbf47 100644 --- a/src/test/cases/MacroTestCase.hx +++ b/src/test/cases/MacroTestCase.hx @@ -23,4 +23,9 @@ class MacroTestCase extends Test { function testModularMacros() { Assert.equals("Nat 5", nameAndNumber("Nat", 5)); } + + function testUndefAlias() { + Assert.equals(9, print); + Assert.equals(9, aliasValue()); + } } diff --git a/src/test/cases/MacroTestCase.kiss b/src/test/cases/MacroTestCase.kiss index bfc34ac..64d526a 100644 --- a/src/test/cases/MacroTestCase.kiss +++ b/src/test/cases/MacroTestCase.kiss @@ -35,3 +35,12 @@ (altDefun nameAndNumber [name String number Int] "$name $number") + +// If for whatever reason, you wanted to make a variable called print +(undefalias &call print) +(defvar print 9) + +(defalias &ident alias 5) +(undefalias &ident alias) +(defvar alias 9) +(defun aliasValue [] alias) \ No newline at end of file