Refactor to prepare for DRY typeCase
This commit is contained in:
@@ -642,7 +642,13 @@ class Helpers {
|
|||||||
function let(bindings:Array<ReaderExp>, body:Array<ReaderExp>) {
|
function let(bindings:Array<ReaderExp>, body:Array<ReaderExp>) {
|
||||||
return callSymbol("let", [list(bindings)].concat(body));
|
return callSymbol("let", [list(bindings)].concat(body));
|
||||||
}
|
}
|
||||||
|
function throwAssertOrNeverError(messageExp:ReaderExp) {
|
||||||
|
var failureError = KissError.fromExp(posRef, "").toString(AssertionFail);
|
||||||
|
var colonsInPrefix = if (Sys.systemName() == "Windows") 5 else 4;
|
||||||
|
return callSymbol("throw", [
|
||||||
|
callSymbol("kiss.Prelude.runtimeInsertAssertionMessage", [messageExp, str(failureError), int(colonsInPrefix)])
|
||||||
|
]);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
call: call,
|
call: call,
|
||||||
callSymbol: callSymbol,
|
callSymbol: callSymbol,
|
||||||
@@ -666,22 +672,30 @@ class Helpers {
|
|||||||
objectWith: objectWith,
|
objectWith: objectWith,
|
||||||
// Only use within assertion macros
|
// Only use within assertion macros
|
||||||
throwAssertionError: () -> {
|
throwAssertionError: () -> {
|
||||||
var failureError = KissError.fromExp(posRef, "").toString(AssertionFail);
|
var usage = "throwAssertionError can only be used in a builder of an assertion macro";
|
||||||
var colonsInPrefix = if (Sys.systemName() == "Windows") 5 else 4;
|
|
||||||
var exps = switch (posRef.def) {
|
var exps = switch (posRef.def) {
|
||||||
case CallExp(_, exps):
|
case CallExp(_, exps):
|
||||||
exps;
|
exps;
|
||||||
default:
|
default:
|
||||||
throw KissError.fromExp(_symbol("throwAssertionError"), "throwAssertionError can only be used in a builder of an assertion macro");
|
throw KissError.fromExp(_symbol("throwAssertionError"), usage);
|
||||||
}
|
}
|
||||||
var messageExp = if (exps.length > 1) {
|
var messageExp = if (exps.length > 1) {
|
||||||
exps[1];
|
exps[1];
|
||||||
} else {
|
} else {
|
||||||
str("");
|
str("");
|
||||||
};
|
};
|
||||||
callSymbol("throw", [
|
throwAssertOrNeverError(messageExp);
|
||||||
callSymbol("kiss.Prelude.runtimeInsertAssertionMessage", [messageExp, str(failureError), int(colonsInPrefix)])
|
},
|
||||||
|
neverCase: () -> {
|
||||||
|
switch (posRef.def) {
|
||||||
|
case CallExp({pos: _, def: Symbol("never")}, neverExps):
|
||||||
|
posRef.checkNumArgs(1, 1, '(never <pattern>)');
|
||||||
|
call(neverExps[0], [
|
||||||
|
throwAssertOrNeverError(str('case should never match pattern ${Reader.toString(neverExps[0].def)}'))
|
||||||
]);
|
]);
|
||||||
|
default:
|
||||||
|
posRef;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// Compile-time only!
|
// Compile-time only!
|
||||||
throwKissError: (reason:String) -> {
|
throwKissError: (reason:String) -> {
|
||||||
@@ -705,6 +719,16 @@ class Helpers {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function checkNoEarlyOtherwise(cases:kiss.List<ReaderExp>) {
|
||||||
|
for (i in 0...cases.length) {
|
||||||
|
switch (cases[i].def) {
|
||||||
|
case CallExp({pos: _, def: Symbol("otherwise")}, _) if (i != cases.length - 1):
|
||||||
|
throw KissError.fromExp(cases[i], "(otherwise <body...>) branch must come last in a (case <...>) expression");
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static function argList(exp:ReaderExp, forThis:String, allowEmpty = true):Array<ReaderExp> {
|
public static function argList(exp:ReaderExp, forThis:String, allowEmpty = true):Array<ReaderExp> {
|
||||||
return switch (exp.def) {
|
return switch (exp.def) {
|
||||||
case ListExp([]) if (allowEmpty):
|
case ListExp([]) if (allowEmpty):
|
||||||
|
@@ -333,27 +333,11 @@ class SpecialForms {
|
|||||||
// to cover all patterns.
|
// to cover all patterns.
|
||||||
var args:kiss.List<ReaderExp> = args.copy();
|
var args:kiss.List<ReaderExp> = args.copy();
|
||||||
|
|
||||||
var cases:kiss.List<ReaderExp> = args.slice(1);
|
var cases:kiss.List<ReaderExp> = [for (c in args.slice(1)) {
|
||||||
for (i in 0...cases.length) {
|
c.expBuilder().neverCase();
|
||||||
switch (cases[i].def) {
|
}];
|
||||||
case CallExp({pos: _, def: Symbol("never")}, neverExps):
|
|
||||||
cases[i].checkNumArgs(1, 1, '(never <pattern>)');
|
Helpers.checkNoEarlyOtherwise(cases);
|
||||||
var b = cases[i].expBuilder();
|
|
||||||
var failureError = KissError.fromExp(cases[i], '').toString(AssertionFail);
|
|
||||||
var colonsInPrefix = if (Sys.systemName() == "Windows") 5 else 4;
|
|
||||||
cases[i] = b.call(neverExps[0], [
|
|
||||||
b.callSymbol('throw', [
|
|
||||||
b.callSymbol('kiss.Prelude.runtimeInsertAssertionMessage', [b.str('${Reader.toString(neverExps[0].def)} should never match pattern ${Reader.toString(neverExps[0].def)}'), b.str(failureError), b.int(colonsInPrefix)])])]);
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i in 0...cases.length) {
|
|
||||||
switch (cases[i].def) {
|
|
||||||
case CallExp({pos: _, def: Symbol("otherwise")}, _) if (i != cases.length - 1):
|
|
||||||
throw KissError.fromExp(cases[i], "(otherwise <body...>) branch must come last in a (case <...>) expression");
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var isTupleCase = switch (args[0].def) {
|
var isTupleCase = switch (args[0].def) {
|
||||||
case ListExp(_):
|
case ListExp(_):
|
||||||
|
Reference in New Issue
Block a user