defnew &prop
This commit is contained in:
@@ -374,6 +374,15 @@ class Helpers {
|
||||
};
|
||||
}
|
||||
|
||||
public static function argList(exp:ReaderExp, forThis:String):Array<ReaderExp> {
|
||||
return switch (exp.def) {
|
||||
case ListExp(argExps):
|
||||
argExps;
|
||||
default:
|
||||
throw CompileError.fromExp(exp, '$forThis arg list should be a list expression');
|
||||
};
|
||||
}
|
||||
|
||||
public static function bindingList(exp:ReaderExp, forThis:String):Array<ReaderExp> {
|
||||
return switch (exp.def) {
|
||||
case ListExp(bindingExps) if (bindingExps.length > 0 && bindingExps.length % 2 == 0):
|
||||
|
@@ -529,11 +529,11 @@ class Macros {
|
||||
// TODO test defnew
|
||||
macros["defnew"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
|
||||
wholeExp.checkNumArgs(2, null, "(defnew [[args...]] [[property bindings...]] [body...]");
|
||||
|
||||
var args = exps[0];
|
||||
var bindingList = exps[1].bindingList("defnew");
|
||||
var bindingPairs = Prelude.groups(bindingList, 2);
|
||||
|
||||
// TODO allow &prop in the arg list to bind it directly to a same-named variable
|
||||
|
||||
var propertyDefs = [for (bindingPair in bindingPairs) {
|
||||
var b = bindingPair[0].expBuilder();
|
||||
b.call(b.symbol("defprop"), [bindingPair[0]]);
|
||||
@@ -543,11 +543,33 @@ class Macros {
|
||||
b.call(b.symbol("set"), [b.symbol(Helpers.varName("a defprop property binding", bindingPair[0])), bindingPair[1]]);
|
||||
}];
|
||||
|
||||
var argList = [];
|
||||
// &prop in the argument list defines a property supplied directly as an argument
|
||||
for (arg in Helpers.argList(args, "defnew")) {
|
||||
var b = arg.expBuilder();
|
||||
switch (arg.def) {
|
||||
case MetaExp("prop", propExp):
|
||||
argList.push(propExp);
|
||||
propertyDefs.push(
|
||||
b.call(b.symbol("defprop"), [propExp]));
|
||||
switch (propExp.def) {
|
||||
case TypedExp(_, {pos: _, def: Symbol(name)}):
|
||||
propertySetExps.push(
|
||||
b.call(b.symbol("set"), [b.field(name, b.symbol("this")), b.symbol(name)]));
|
||||
default:
|
||||
throw CompileError.fromExp(arg, "invalid use of &prop in defnew");
|
||||
}
|
||||
default:
|
||||
argList.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
var b = wholeExp.expBuilder();
|
||||
|
||||
return b.begin(propertyDefs.concat([
|
||||
b.call(b.symbol("defmethod"), [
|
||||
b.symbol("new"),
|
||||
exps[0]
|
||||
b.list(argList)
|
||||
].concat(propertySetExps).concat(exps.slice(2)))
|
||||
]));
|
||||
};
|
||||
|
Reference in New Issue
Block a user