&body macro arguments. Close #7
This commit is contained in:
@@ -416,15 +416,16 @@ class Macros {
|
|||||||
var maxArgs = 0;
|
var maxArgs = 0;
|
||||||
// Once the &opt meta appears, all following arguments are optional until &rest
|
// Once the &opt meta appears, all following arguments are optional until &rest
|
||||||
var optIndex = -1;
|
var optIndex = -1;
|
||||||
// Once the &rest meta appears, no other arguments can be declared
|
// Once the &rest or &body meta appears, no other arguments can be declared
|
||||||
var restIndex = -1;
|
var restIndex = -1;
|
||||||
|
var requireRest = false;
|
||||||
var argNames = [];
|
var argNames = [];
|
||||||
|
|
||||||
var macroCallForm = '($name';
|
var macroCallForm = '($name';
|
||||||
|
|
||||||
for (arg in argList) {
|
for (arg in argList) {
|
||||||
if (restIndex != -1) {
|
if (restIndex != -1) {
|
||||||
throw CompileError.fromExp(arg, "macros cannot declare arguments after a &rest argument");
|
throw CompileError.fromExp(arg, "macros cannot declare arguments after a &rest or &body argument");
|
||||||
}
|
}
|
||||||
switch (arg.def) {
|
switch (arg.def) {
|
||||||
case Symbol(name):
|
case Symbol(name):
|
||||||
@@ -442,10 +443,19 @@ class Macros {
|
|||||||
optIndex = maxArgs;
|
optIndex = maxArgs;
|
||||||
++maxArgs;
|
++maxArgs;
|
||||||
case MetaExp("rest", {pos: _, def: Symbol(name)}):
|
case MetaExp("rest", {pos: _, def: Symbol(name)}):
|
||||||
|
if (name == "body") {
|
||||||
|
CompileError.warnFromExp(arg, "Consider using &body instead of &rest when writing macros with bodies.");
|
||||||
|
}
|
||||||
argNames.push(name);
|
argNames.push(name);
|
||||||
macroCallForm += ' [$name...]';
|
macroCallForm += ' [$name...]';
|
||||||
restIndex = maxArgs;
|
restIndex = maxArgs;
|
||||||
maxArgs = null;
|
maxArgs = null;
|
||||||
|
case MetaExp("body", {pos: _, def: Symbol(name)}):
|
||||||
|
argNames.push(name);
|
||||||
|
macroCallForm += ' [$name...]';
|
||||||
|
restIndex = maxArgs;
|
||||||
|
requireRest = true;
|
||||||
|
maxArgs = null;
|
||||||
default:
|
default:
|
||||||
throw CompileError.fromExp(arg, "macro argument should be an untyped symbol or a symbol annotated with &opt or &rest");
|
throw CompileError.fromExp(arg, "macro argument should be an untyped symbol or a symbol annotated with &opt or &rest");
|
||||||
}
|
}
|
||||||
@@ -468,8 +478,13 @@ class Macros {
|
|||||||
for (idx in optIndex...restIndex) {
|
for (idx in optIndex...restIndex) {
|
||||||
args[innerArgNames.shift()] = if (exps.length > idx) innerExps[idx] else null;
|
args[innerArgNames.shift()] = if (exps.length > idx) innerExps[idx] else null;
|
||||||
}
|
}
|
||||||
if (innerArgNames.length > 0)
|
if (innerArgNames.length > 0) {
|
||||||
args[innerArgNames.shift()] = innerExps.slice(restIndex);
|
var restArgs = innerExps.slice(restIndex);
|
||||||
|
if (requireRest && restArgs.length == 0) {
|
||||||
|
throw CompileError.fromExp(wholeExp, 'Macro $name requires one or more expression for &body');
|
||||||
|
}
|
||||||
|
args[innerArgNames.shift()] = restArgs;
|
||||||
|
}
|
||||||
|
|
||||||
// Return the macro expansion:
|
// Return the macro expansion:
|
||||||
return Helpers.runAtCompileTime(CallExp(Symbol("begin").withPosOf(wholeExp), exps.slice(2)).withPosOf(wholeExp), k, args);
|
return Helpers.runAtCompileTime(CallExp(Symbol("begin").withPosOf(wholeExp), exps.slice(2)).withPosOf(wholeExp), k, args);
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
// You should be able to run list comprehensions on expressions
|
// You should be able to run list comprehensions on expressions
|
||||||
// and put the pieces back together in a modular way
|
// and put the pieces back together in a modular way
|
||||||
(defmacro altDefun [name args &rest body]
|
(defmacro altDefun [name args &body body]
|
||||||
(let [argPairs
|
(let [argPairs
|
||||||
(groups (expList args) 2)
|
(groups (expList args) 2)
|
||||||
untypedArgs
|
untypedArgs
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
(defmacro year [num &rest body]
|
(defmacro year [num &body body]
|
||||||
`(#when ,(symbol (+ "year" (symbolNameValue num)))
|
`(#when ,(symbol (+ "year" (symbolNameValue num)))
|
||||||
(print (+ "year " (Std.string ,num)))
|
(print (+ "year " (Std.string ,num)))
|
||||||
,@body))
|
,@body))
|
||||||
|
|
||||||
(defmacro day [num &rest body]
|
(defmacro day [num &body body]
|
||||||
`(#when ,(symbol (+ "day" (symbolNameValue num)))
|
`(#when ,(symbol (+ "day" (symbolNameValue num)))
|
||||||
(print (+ "day " (Std.string ,num)))
|
(print (+ "day " (Std.string ,num)))
|
||||||
,@body))
|
,@body))
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
(defmethod _index [x y]
|
(defmethod _index [x y]
|
||||||
(+ x (* y width)))
|
(+ x (* y width)))
|
||||||
|
|
||||||
(defmacro withIndex [idxName xName yName &rest body]
|
(defmacro withIndex [idxName xName yName &body body]
|
||||||
`(let [,idxName (_index ,xName ,yName)]
|
`(let [,idxName (_index ,xName ,yName)]
|
||||||
,@body))
|
,@body))
|
||||||
|
|
||||||
|
@@ -240,7 +240,7 @@
|
|||||||
random Std.random
|
random Std.random
|
||||||
int Std.int)))
|
int Std.int)))
|
||||||
|
|
||||||
(defmacro withValueOrInputBox [v &rest body]
|
(defmacro withValueOrInputBox [v &body body]
|
||||||
`(if ,v
|
`(if ,v
|
||||||
{,@body}
|
{,@body}
|
||||||
(awaitLet [,v (inputBox)]
|
(awaitLet [,v (inputBox)]
|
||||||
|
@@ -107,7 +107,7 @@
|
|||||||
(set lastCollector (_composeArgCollector collectedArgs arg lastCollector)))
|
(set lastCollector (_composeArgCollector collectedArgs arg lastCollector)))
|
||||||
(lastCollector)))
|
(lastCollector)))
|
||||||
|
|
||||||
(defmacro defcommand [name args &rest body]
|
(defmacro defcommand [name args &body body]
|
||||||
(let [argPairs
|
(let [argPairs
|
||||||
(groups (expList args) 2)
|
(groups (expList args) 2)
|
||||||
methodArgs
|
methodArgs
|
||||||
|
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
// Retrieve multiple components from an Entity with mutable access.
|
// Retrieve multiple components from an Entity with mutable access.
|
||||||
// All components will be serialized after the block is done.
|
// All components will be serialized after the block is done.
|
||||||
(defmacro withWritableComponents [archive e bindings &rest body]
|
(defmacro withWritableComponents [archive e bindings &body body]
|
||||||
(let [bindingPairs
|
(let [bindingPairs
|
||||||
(groups (expList bindings) 2 Throw)
|
(groups (expList bindings) 2 Throw)
|
||||||
bindingList
|
bindingList
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
,@saveList
|
,@saveList
|
||||||
,retValSymbol)))
|
,retValSymbol)))
|
||||||
|
|
||||||
(defmacro withWritableEntry [archive e &rest body]
|
(defmacro withWritableEntry [archive e &body body]
|
||||||
(let [retValSymbol
|
(let [retValSymbol
|
||||||
(symbol)]
|
(symbol)]
|
||||||
`(let [,retValSymbol {,@body}]
|
`(let [,retValSymbol {,@body}]
|
||||||
|
Reference in New Issue
Block a user