case handle null. close #14

This commit is contained in:
2021-11-29 13:28:18 -07:00
parent 61753e71ab
commit 678959708d
4 changed files with 62 additions and 28 deletions

View File

@@ -645,7 +645,6 @@ class Macros {
var bindingList = exps[0].bindingList(funcName); var bindingList = exps[0].bindingList(funcName);
var firstPattern = bindingList.shift(); var firstPattern = bindingList.shift();
var firstValue = bindingList.shift(); var firstValue = bindingList.shift();
var firstValueSymbol = b.symbol();
var thenExp = if (assertLet) b.begin(exps.slice(1)) else exps[1]; var thenExp = if (assertLet) b.begin(exps.slice(1)) else exps[1];
var elseExp = if (!assertLet && exps.length > 2) { var elseExp = if (!assertLet && exps.length > 2) {
@@ -656,13 +655,8 @@ class Macros {
b.symbol("null"); b.symbol("null");
}; };
return b.callSymbol("let", [ return b.callSymbol("case", [
b.list([firstValueSymbol, firstValue]), firstValue,
b.callSymbol("if", [
firstValueSymbol,
b.call(
b.symbol("case"), [
firstValueSymbol,
b.call( b.call(
firstPattern, [ firstPattern, [
if (bindingList.length == 0) { if (bindingList.length == 0) {
@@ -673,11 +667,7 @@ class Macros {
].concat(exps.slice(1)), k); ].concat(exps.slice(1)), k);
} }
]), ]),
b.call( b.callSymbol("otherwise", [
b.symbol("otherwise"), [
elseExp
])
]),
elseExp elseExp
]) ])
]); ]);
@@ -1109,7 +1099,8 @@ class Macros {
return b.callSymbol("case", [ return b.callSymbol("case", [
b.callField(funcName, exps.shift(), exps), b.callField(funcName, exps.shift(), exps),
b.callSymbol("-1", [b.symbol("haxe.ds.Option.None")]), b.callSymbol("-1", [b.symbol("haxe.ds.Option.None")]),
b.callSymbol("other", [b.callSymbol("haxe.ds.Option.Some", [b.symbol("other")])]) b.callSymbol("other", [b.callSymbol("haxe.ds.Option.Some", [b.symbol("other")])]),
b.callSymbol("null", [b.callSymbol("throw", [b.str("Haxe indexOf is broken")])])
]); ]);
} }
macros["indexOf"] = indexOfMacro.bind(false); macros["indexOf"] = indexOfMacro.bind(false);

View File

@@ -12,6 +12,7 @@ using kiss.Reader;
using kiss.Helpers; using kiss.Helpers;
using kiss.Prelude; using kiss.Prelude;
using kiss.Kiss; using kiss.Kiss;
using tink.MacroApi;
// Special forms convert Kiss reader expressions into Haxe macro expressions // Special forms convert Kiss reader expressions into Haxe macro expressions
typedef SpecialFormFunction = (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> Expr; typedef SpecialFormFunction = (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> Expr;
@@ -285,6 +286,14 @@ class SpecialForms {
// Therefore only one case is required in a case statement, because one case could be enough // Therefore only one case is required in a case statement, because one case could be enough
// to cover all patterns. // to cover all patterns.
wholeExp.checkNumArgs(2, null, '(case [expression] [cases...] [optional: (otherwise [default])])'); wholeExp.checkNumArgs(2, null, '(case [expression] [cases...] [optional: (otherwise [default])])');
var isTupleCase = switch (args[0].def) {
case ListExp(_):
true;
default:
false;
}
var b = wholeExp.expBuilder(); var b = wholeExp.expBuilder();
var defaultExpr = switch (args[-1].def) { var defaultExpr = switch (args[-1].def) {
case CallExp({pos: _, def: Symbol("otherwise")}, otherwiseExps): case CallExp({pos: _, def: Symbol("otherwise")}, otherwiseExps):
@@ -293,7 +302,32 @@ class SpecialForms {
default: default:
null; null;
}; };
ESwitch(k.withoutListWrapping().convert(args[0]), args.slice(1).map(Helpers.makeSwitchCase.bind(_, k)), defaultExpr).withMacroPosOf(wholeExp);
var cases = args.slice(1);
// case also override's haxe's switch() behavior by refusing to match null values against <var> patterns.
if (!isTupleCase) {
var nullExpr = defaultExpr;
var idx = 0;
for (arg in cases) {
switch (arg.def) {
case CallExp({pos: _, def: Symbol("null")}, nullExps):
cases.splice(idx, 1);
nullExpr = k.convert(b.begin(nullExps));
break;
default:
}
++idx;
}
if (nullExpr == null) {
throw CompileError.fromExp(wholeExp, "Unmatched pattern: null");
}
var nullCase = b.callSymbol("null", [b.raw(nullExpr.toString())]);
cases.insert(0, nullCase);
}
ESwitch(k.withoutListWrapping().convert(args[0]), cases.map(Helpers.makeSwitchCase.bind(_, k)), defaultExpr).withMacroPosOf(wholeExp);
}; };
// Type check syntax: // Type check syntax:

View File

@@ -327,6 +327,10 @@ class BasicTestCase extends Test {
_testEvalStatic(); _testEvalStatic();
_testEval(); _testEval();
} }
function testCaseOnNull() {
_testCaseOnNull();
}
} }
class BasicObject { class BasicObject {

View File

@@ -351,7 +351,7 @@
(function _testCase [] (function _testCase []
(case (toOption []) (case (toOption [])
(None (Assert.pass)) (None (Assert.pass))
((Some value) (Assert.fail))) (otherwise (Assert.fail)))
(case (toOption "hey") (case (toOption "hey")
(None (Assert.fail)) (None (Assert.fail))
((Some "hey") (Assert.pass)) ((Some "hey") (Assert.pass))
@@ -590,3 +590,8 @@
(function _testEvalStatic [] (function _testEvalStatic []
(Assert.equals 9 (eval 'staticValue)) (Assert.equals 9 (eval 'staticValue))
(assertThrows (eval 'value))) (assertThrows (eval 'value)))
(function _testCaseOnNull []
(Assert.equals 5 (case null (v 10) (null 5)))
(Assert.equals 5 (case null (v 10) (null 5) (otherwise 6)))
(Assert.equals 5 (case null (v 10) (otherwise 5))))