case handle null. close #14
This commit is contained in:
@@ -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);
|
||||||
|
@@ -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:
|
||||||
|
@@ -327,6 +327,10 @@ class BasicTestCase extends Test {
|
|||||||
_testEvalStatic();
|
_testEvalStatic();
|
||||||
_testEval();
|
_testEval();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testCaseOnNull() {
|
||||||
|
_testCaseOnNull();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BasicObject {
|
class BasicObject {
|
||||||
|
@@ -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))))
|
Reference in New Issue
Block a user