diff --git a/kiss/src/kiss/Helpers.hx b/kiss/src/kiss/Helpers.hx index c593f9cd..4e1343a3 100644 --- a/kiss/src/kiss/Helpers.hx +++ b/kiss/src/kiss/Helpers.hx @@ -164,9 +164,6 @@ class Helpers { 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)]; } diff --git a/kiss/src/kiss/Kiss.hx b/kiss/src/kiss/Kiss.hx index 9f329dff..14eff68d 100644 --- a/kiss/src/kiss/Kiss.hx +++ b/kiss/src/kiss/Kiss.hx @@ -220,6 +220,8 @@ class Kiss { public static function forCaseParsing(k:KissState):KissState { var copy = Reflect.copy(k); copy.wrapListExps = false; + k.macros.remove("or"); + k.specialForms["or"] = SpecialForms.caseOr; return copy; } diff --git a/kiss/src/kiss/SpecialForms.hx b/kiss/src/kiss/SpecialForms.hx index afcc43c1..4d71f95f 100644 --- a/kiss/src/kiss/SpecialForms.hx +++ b/kiss/src/kiss/SpecialForms.hx @@ -335,4 +335,13 @@ class SpecialForms { return map; } + + public static function caseOr(wholeExp:ReaderExp, args:Array, k:KissState):Expr { + wholeExp.checkNumArgs(2, null, "(or [v1] [v2] [values...])"); + return if (args.length == 2) { + macro ${k.convert(args[0])} | ${k.convert(args[1])}; + } else { + macro ${k.convert(args[0])} | ${caseOr(wholeExp, args.slice(1), k)}; + }; + }; } diff --git a/kiss/src/test/cases/BasicTestCase.kiss b/kiss/src/test/cases/BasicTestCase.kiss index 86e55187..0b13ae34 100644 --- a/kiss/src/test/cases/BasicTestCase.kiss +++ b/kiss/src/test/cases/BasicTestCase.kiss @@ -341,16 +341,17 @@ (case 5 ((when false (or 5 6)) (Assert.fail)) (otherwise (Assert.pass))) - // TODO in Haxe, + // In Haxe, // `switch (Some(true)) { case Some(true | false): "a"; default: "b"; }` - // returns "a", so this should also be valid: - /*(case (Some true) + // returns "a", so nested use of `or` in case patterns should also be valid: + (case (Some true) ((Some (or true false)) (Assert.pass)) - (otherwise (Assert.fail)))*/ - // ^ Implement by overriding the `or` macro with an `or` special form to return variadically nested OpOr binop exps - // in KissState.forCaseParsing() instead of handling CallExp(Symbol(or)) specially - ) + (otherwise (Assert.fail))) + (case (Some 5) + ((Some (or 6 5 4)) + (Assert.pass)) + (otherwise (Assert.fail)))) (defun _testMaps [] (deflocal :Map myMap [=>"hey" "you"