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> {
|
public static function bindingList(exp:ReaderExp, forThis:String):Array<ReaderExp> {
|
||||||
return switch (exp.def) {
|
return switch (exp.def) {
|
||||||
case ListExp(bindingExps) if (bindingExps.length > 0 && bindingExps.length % 2 == 0):
|
case ListExp(bindingExps) if (bindingExps.length > 0 && bindingExps.length % 2 == 0):
|
||||||
|
@@ -529,11 +529,11 @@ class Macros {
|
|||||||
// TODO test defnew
|
// TODO test defnew
|
||||||
macros["defnew"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
|
macros["defnew"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
|
||||||
wholeExp.checkNumArgs(2, null, "(defnew [[args...]] [[property bindings...]] [body...]");
|
wholeExp.checkNumArgs(2, null, "(defnew [[args...]] [[property bindings...]] [body...]");
|
||||||
|
|
||||||
|
var args = exps[0];
|
||||||
var bindingList = exps[1].bindingList("defnew");
|
var bindingList = exps[1].bindingList("defnew");
|
||||||
var bindingPairs = Prelude.groups(bindingList, 2);
|
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 propertyDefs = [for (bindingPair in bindingPairs) {
|
||||||
var b = bindingPair[0].expBuilder();
|
var b = bindingPair[0].expBuilder();
|
||||||
b.call(b.symbol("defprop"), [bindingPair[0]]);
|
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]]);
|
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();
|
var b = wholeExp.expBuilder();
|
||||||
|
|
||||||
return b.begin(propertyDefs.concat([
|
return b.begin(propertyDefs.concat([
|
||||||
b.call(b.symbol("defmethod"), [
|
b.call(b.symbol("defmethod"), [
|
||||||
b.symbol("new"),
|
b.symbol("new"),
|
||||||
exps[0]
|
b.list(argList)
|
||||||
].concat(propertySetExps).concat(exps.slice(2)))
|
].concat(propertySetExps).concat(exps.slice(2)))
|
||||||
]));
|
]));
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user