refactor ExpBuilder to be a class, not anonymous object
This commit is contained in:
@@ -5,51 +5,64 @@ using kiss.Helpers;
|
|||||||
using kiss.Reader;
|
using kiss.Reader;
|
||||||
using kiss.ExpBuilder;
|
using kiss.ExpBuilder;
|
||||||
|
|
||||||
class ExpBuilder {
|
// Has convenient functions for succinctly making new ReaderExps that link back to an original exp's
|
||||||
// Return convenient functions for succinctly making new ReaderExps that link back to an original exp's
|
|
||||||
// position in source code
|
// position in source code
|
||||||
|
class ExpBuilder {
|
||||||
|
var posRef:ReaderExp;
|
||||||
|
|
||||||
|
function new(posRef:ReaderExp) {
|
||||||
|
this.posRef = posRef;
|
||||||
|
}
|
||||||
|
|
||||||
public static function expBuilder(posRef:ReaderExp) {
|
public static function expBuilder(posRef:ReaderExp) {
|
||||||
function _symbol(?name:String) {
|
return new ExpBuilder(posRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function symbol(?name:String) {
|
||||||
return Prelude.symbol(name).withPosOf(posRef);
|
return Prelude.symbol(name).withPosOf(posRef);
|
||||||
}
|
}
|
||||||
function call(func:ReaderExp, args:Array<ReaderExp>) {
|
|
||||||
|
public function call(func:ReaderExp, args:Array<ReaderExp>) {
|
||||||
return CallExp(func, args).withPosOf(posRef);
|
return CallExp(func, args).withPosOf(posRef);
|
||||||
}
|
}
|
||||||
function callSymbol(symbol:String, args:Array<ReaderExp>) {
|
|
||||||
return call(_symbol(symbol), args);
|
public function callSymbol(_symbol:String, args:Array<ReaderExp>) {
|
||||||
|
return call(symbol(_symbol), args);
|
||||||
}
|
}
|
||||||
function field(f:String, exp:ReaderExp, ?safe:Bool) {
|
|
||||||
|
public function field(f:String, exp:ReaderExp, ?safe:Bool) {
|
||||||
return FieldExp(f, exp, safe != null && safe).withPosOf(posRef);
|
return FieldExp(f, exp, safe != null && safe).withPosOf(posRef);
|
||||||
}
|
}
|
||||||
function list(exps:Array<ReaderExp>) {
|
|
||||||
|
public function list(exps:Array<ReaderExp>) {
|
||||||
return ListExp(exps).withPosOf(posRef);
|
return ListExp(exps).withPosOf(posRef);
|
||||||
}
|
}
|
||||||
function objectWith (bindings:Array<ReaderExp>, captures:Array<ReaderExp>) {
|
public function objectWith (bindings:Array<ReaderExp>, captures:Array<ReaderExp>) {
|
||||||
return callSymbol("objectWith", [list(bindings)].concat(captures));
|
return callSymbol("objectWith", [list(bindings)].concat(captures));
|
||||||
}
|
}
|
||||||
function str(s:String) {
|
public function str(s:String) {
|
||||||
return StrExp(s).withPosOf(posRef);
|
return StrExp(s).withPosOf(posRef);
|
||||||
}
|
}
|
||||||
function raw(code:String) {
|
public function raw(code:String) {
|
||||||
return RawHaxe(code).withPosOf(posRef);
|
return RawHaxe(code).withPosOf(posRef);
|
||||||
}
|
}
|
||||||
function int(v:Int) {
|
public function int(v:Int) {
|
||||||
return _symbol(Std.string(v));
|
return symbol(Std.string(v));
|
||||||
}
|
}
|
||||||
function float(v:Float) {
|
public function float(v:Float) {
|
||||||
return _symbol(Std.string(v));
|
return symbol(Std.string(v));
|
||||||
}
|
}
|
||||||
function let(bindings:Array<ReaderExp>, body:Array<ReaderExp>) {
|
public function let(bindings:Array<ReaderExp>, body:Array<ReaderExp>) {
|
||||||
return callSymbol("let", [list(bindings)].concat(body));
|
return callSymbol("let", [list(bindings)].concat(body));
|
||||||
}
|
}
|
||||||
function _if(condition:ReaderExp, then:ReaderExp, ?_else:ReaderExp) {
|
public function _if(condition:ReaderExp, then:ReaderExp, ?_else:ReaderExp) {
|
||||||
var args = [condition, then];
|
var args = [condition, then];
|
||||||
if (_else != null)
|
if (_else != null)
|
||||||
args.push(_else);
|
args.push(_else);
|
||||||
return callSymbol("if", args);
|
return callSymbol("if", args);
|
||||||
}
|
}
|
||||||
#if (sys || hxnodejs)
|
#if (sys || hxnodejs)
|
||||||
function throwAssertOrNeverError(messageExp:ReaderExp) {
|
public function throwAssertOrNeverError(messageExp:ReaderExp) {
|
||||||
var failureError = KissError.fromExp(posRef, "").toString(AssertionFail);
|
var failureError = KissError.fromExp(posRef, "").toString(AssertionFail);
|
||||||
var colonsInPrefix = if (Sys.systemName() == "Windows") 5 else 4;
|
var colonsInPrefix = if (Sys.systemName() == "Windows") 5 else 4;
|
||||||
return callSymbol("throw", [
|
return callSymbol("throw", [
|
||||||
@@ -57,53 +70,65 @@ class ExpBuilder {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
function whenUnless(which:String, condition:ReaderExp, body:Array<ReaderExp>) {
|
function _whenUnless(which:String, condition:ReaderExp, body:Array<ReaderExp>) {
|
||||||
return callSymbol(which, [condition].concat(body));
|
return callSymbol(which, [condition].concat(body));
|
||||||
}
|
}
|
||||||
return {
|
public function when(condition:ReaderExp, body:Array<ReaderExp>) {
|
||||||
call: call,
|
return _whenUnless("when", condition, body);
|
||||||
callSymbol: callSymbol,
|
}
|
||||||
callField: (fieldName:String, callOn:ReaderExp, args:Array<ReaderExp>) -> call(field(fieldName, callOn), args),
|
public function unless(condition:ReaderExp, body:Array<ReaderExp>) {
|
||||||
print: (arg:ReaderExp) -> CallExp(Symbol("print").withPosOf(posRef), [arg]).withPosOf(posRef),
|
return _whenUnless("unless", condition, body);
|
||||||
the: (type:ReaderExp, value:ReaderExp) -> callSymbol("the", [type, value]),
|
}
|
||||||
not: (exp:ReaderExp) -> callSymbol("not", [exp]),
|
|
||||||
list: list,
|
public function callField(fieldName:String, callOn:ReaderExp, args:Array<ReaderExp>) {
|
||||||
str: str,
|
return call(field(fieldName, callOn), args);
|
||||||
symbol: _symbol,
|
}
|
||||||
_if: _if,
|
public function print(arg:ReaderExp) {
|
||||||
int: int,
|
return CallExp(Symbol("print").withPosOf(posRef), [arg]).withPosOf(posRef);
|
||||||
float: float,
|
}
|
||||||
raw: raw,
|
public function the(type:ReaderExp, value:ReaderExp) {
|
||||||
typed: (path:String, exp:ReaderExp) -> TypedExp(path, exp).withPosOf(posRef),
|
return callSymbol("the", [type, value]);
|
||||||
meta: (m:String, exp:ReaderExp) -> MetaExp(m, exp).withPosOf(posRef),
|
}
|
||||||
field: field,
|
public function not(exp:ReaderExp) {
|
||||||
keyValue: (key:ReaderExp, value:ReaderExp) -> KeyValueExp(key, value).withPosOf(posRef),
|
return callSymbol("not", [exp]);
|
||||||
begin: (exps:Array<ReaderExp>) -> callSymbol("begin", exps),
|
}
|
||||||
set: (v:ReaderExp, value:ReaderExp) -> callSymbol("set", [v, value]),
|
public function typed(path:String, exp:ReaderExp) {
|
||||||
when: whenUnless.bind("when"),
|
return TypedExp(path, exp).withPosOf(posRef);
|
||||||
unless: whenUnless.bind("unless"),
|
}
|
||||||
let: let,
|
public function meta(m:String, exp:ReaderExp) {
|
||||||
objectWith: objectWith,
|
return MetaExp(m, exp).withPosOf(posRef);
|
||||||
expFromDef: (def:ReaderExpDef) -> def.withPosOf(posRef),
|
}
|
||||||
|
public function keyValue(key:ReaderExp, value:ReaderExp) {
|
||||||
|
return KeyValueExp(key, value).withPosOf(posRef);
|
||||||
|
}
|
||||||
|
public function begin(exps:Array<ReaderExp>) {
|
||||||
|
return callSymbol("begin", exps);
|
||||||
|
}
|
||||||
|
public function set(v:ReaderExp, value:ReaderExp) {
|
||||||
|
return callSymbol("set", [v, value]);
|
||||||
|
}
|
||||||
|
public function expFromDef(def:ReaderExpDef) {
|
||||||
|
return def.withPosOf(posRef);
|
||||||
|
}
|
||||||
#if (sys || hxnodejs)
|
#if (sys || hxnodejs)
|
||||||
// Only use within assertion macros
|
// Only use within assertion macros
|
||||||
throwAssertionError: () -> {
|
public function throwAssertionError() {
|
||||||
var usage = "throwAssertionError can only be used in a builder of an assertion macro";
|
var usage = "throwAssertionError can only be used in a builder of an assertion macro";
|
||||||
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"), usage);
|
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("");
|
||||||
};
|
};
|
||||||
throwAssertOrNeverError(messageExp);
|
return throwAssertOrNeverError(messageExp);
|
||||||
},
|
}
|
||||||
neverCase: () -> {
|
public function neverCase() {
|
||||||
switch (posRef.def) {
|
return switch (posRef.def) {
|
||||||
case CallExp({pos: _, def: Symbol("never")}, neverExps):
|
case CallExp({pos: _, def: Symbol("never")}, neverExps):
|
||||||
posRef.checkNumArgs(1, 1, '(never <pattern>)');
|
posRef.checkNumArgs(1, 1, '(never <pattern>)');
|
||||||
call(neverExps[0], [
|
call(neverExps[0], [
|
||||||
@@ -112,30 +137,32 @@ class ExpBuilder {
|
|||||||
default:
|
default:
|
||||||
posRef;
|
posRef;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
#end
|
#end
|
||||||
// Compile-time only!
|
// Compile-time only!
|
||||||
throwKissError: (reason:String) -> {
|
public function throwKissError(reason:String) {
|
||||||
callSymbol("throw", [
|
return callSymbol("throw", [
|
||||||
callSymbol("KissError.fromExpStr", [
|
callSymbol("KissError.fromExpStr", [
|
||||||
// pos
|
// pos
|
||||||
objectWith([
|
objectWith([
|
||||||
_symbol("file"), str(posRef.pos.file),
|
symbol("file"), str(posRef.pos.file),
|
||||||
_symbol("line"), int(posRef.pos.line),
|
symbol("line"), int(posRef.pos.line),
|
||||||
_symbol("column"), int(posRef.pos.column),
|
symbol("column"), int(posRef.pos.column),
|
||||||
_symbol("absoluteChar"), int(posRef.pos.absoluteChar),
|
symbol("absoluteChar"), int(posRef.pos.absoluteChar),
|
||||||
], []),
|
], []),
|
||||||
// expStr
|
// expStr
|
||||||
str(Reader.toString(posRef.def)),
|
str(Reader.toString(posRef.def)),
|
||||||
str(reason)
|
str(reason)
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
},
|
}
|
||||||
#if macro
|
#if macro
|
||||||
haxeExpr: (e:haxe.macro.Expr) -> Helpers.withMacroPosOf(e.expr, posRef),
|
public function haxeExpr(e:haxe.macro.Expr) {
|
||||||
|
return Helpers.withMacroPosOf(e.expr, posRef);
|
||||||
|
}
|
||||||
#end
|
#end
|
||||||
none: () -> None.withPosOf(posRef)
|
public function none() {
|
||||||
};
|
return None.withPosOf(posRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function checkNumArgs(wholeExp:ReaderExp, min:Null<Int>, max:Null<Int>, ?expectedForm:String) {
|
public static function checkNumArgs(wholeExp:ReaderExp, min:Null<Int>, max:Null<Int>, ?expectedForm:String) {
|
||||||
|
|||||||
Reference in New Issue
Block a user