Allow case guards, |
This commit is contained in:
@@ -153,6 +153,37 @@ class Helpers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function makeSwitchCase(caseExp:ReaderExp, k:KissState, ?guard:Expr):Case {
|
||||||
|
var guard:Expr = null;
|
||||||
|
|
||||||
|
function makeSwitchPattern(patternExp:ReaderExp):Array<Expr> {
|
||||||
|
return switch (patternExp.def) {
|
||||||
|
case CallExp({pos: _, def: Symbol("when")}, whenExps):
|
||||||
|
patternExp.checkNumArgs(2, 2, "(when [guard] [pattern])");
|
||||||
|
if (guard != null)
|
||||||
|
throw CompileError.fromExp(caseExp, "case expression can only have one `when` guard");
|
||||||
|
guard = macro Prelude.truthy(${k.convert(whenExps[0])});
|
||||||
|
makeSwitchPattern(whenExps[1]);
|
||||||
|
case CallExp({pos: _, def: Symbol("or")}, orExps):
|
||||||
|
patternExp.checkNumArgs(2, null, "(or [pattern1] [pattern2] [patterns...])");
|
||||||
|
orExps.map(k.forCaseParsing().convert);
|
||||||
|
default:
|
||||||
|
[k.forCaseParsing().convert(patternExp)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return switch (caseExp.def) {
|
||||||
|
case CallExp(patternExp, caseBodyExps):
|
||||||
|
{
|
||||||
|
values: makeSwitchPattern(patternExp),
|
||||||
|
expr: k.convert(CallExp(Symbol("begin").withPosOf(caseExp), caseBodyExps).withPosOf(caseExp)),
|
||||||
|
guard: guard
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
throw CompileError.fromExp(caseExp, "case expressions for (case...) must take the form ([pattern] [body...])");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Throw a CompileError if the given expression has the wrong number of arguments
|
Throw a CompileError if the given expression has the wrong number of arguments
|
||||||
**/
|
**/
|
||||||
|
@@ -252,20 +252,7 @@ class SpecialForms {
|
|||||||
default:
|
default:
|
||||||
null;
|
null;
|
||||||
};
|
};
|
||||||
ESwitch(k.forCaseParsing().convert(args[0]), [
|
ESwitch(k.forCaseParsing().convert(args[0]), args.slice(1).map(Helpers.makeSwitchCase.bind(_, k)), defaultExpr).withMacroPosOf(wholeExp);
|
||||||
for (caseExp in args.slice(1))
|
|
||||||
switch (caseExp.def) {
|
|
||||||
// TODO support CallExp(Symbol("or")) to generate more than one case value
|
|
||||||
// TODO support guards
|
|
||||||
case CallExp(patternExp, caseBodyExps):
|
|
||||||
{
|
|
||||||
values: [k.forCaseParsing().convert(patternExp)],
|
|
||||||
expr: k.convert(CallExp(Symbol("begin").withPosOf(caseExp), caseBodyExps).withPosOf(caseExp))
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
throw CompileError.fromExp(caseExp, "case expressions for (case...) must take the form ([pattern] [body...])");
|
|
||||||
}
|
|
||||||
], defaultExpr).withMacroPosOf(wholeExp);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO macros for ifLet, expectLet, which extract from enums
|
// TODO macros for ifLet, expectLet, which extract from enums
|
||||||
|
@@ -330,7 +330,17 @@
|
|||||||
((Some "hey") (Assert.pass))
|
((Some "hey") (Assert.pass))
|
||||||
(otherwise (Assert.fail)))
|
(otherwise (Assert.fail)))
|
||||||
(Assert.equals 5 (case (toOption 0)
|
(Assert.equals 5 (case (toOption 0)
|
||||||
(otherwise 5))))
|
(otherwise 5)))
|
||||||
|
// Test case with guards and multiple values
|
||||||
|
(case 5
|
||||||
|
((or 5 6) (Assert.pass))
|
||||||
|
(otherwise (Assert.fail)))
|
||||||
|
(case [2 3]
|
||||||
|
((or [_ 3] [1 1]) (Assert.pass))
|
||||||
|
(otherwise (Assert.fail)))
|
||||||
|
(case 5
|
||||||
|
((when false (or 5 6)) (Assert.fail))
|
||||||
|
(otherwise (Assert.pass))))
|
||||||
|
|
||||||
(defun _testMaps []
|
(defun _testMaps []
|
||||||
(deflocal :Map<String,String> myMap [=>"hey" "you"
|
(deflocal :Map<String,String> myMap [=>"hey" "you"
|
||||||
@@ -400,4 +410,4 @@
|
|||||||
// Make sure built-in call aliases don't override user-defined variables
|
// Make sure built-in call aliases don't override user-defined variables
|
||||||
(defun _testCallAlias []
|
(defun _testCallAlias []
|
||||||
(let [map [=>"hey" "you"]]
|
(let [map [=>"hey" "you"]]
|
||||||
(Assert.equals "you" (dictGet map "hey"))))
|
(Assert.equals "you" (dictGet map "hey"))))
|
||||||
|
Reference in New Issue
Block a user