&body macro arguments. Close #7
This commit is contained in:
@@ -416,15 +416,16 @@ class Macros {
|
||||
var maxArgs = 0;
|
||||
// Once the &opt meta appears, all following arguments are optional until &rest
|
||||
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 requireRest = false;
|
||||
var argNames = [];
|
||||
|
||||
var macroCallForm = '($name';
|
||||
|
||||
for (arg in argList) {
|
||||
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) {
|
||||
case Symbol(name):
|
||||
@@ -442,10 +443,19 @@ class Macros {
|
||||
optIndex = maxArgs;
|
||||
++maxArgs;
|
||||
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);
|
||||
macroCallForm += ' [$name...]';
|
||||
restIndex = maxArgs;
|
||||
maxArgs = null;
|
||||
case MetaExp("body", {pos: _, def: Symbol(name)}):
|
||||
argNames.push(name);
|
||||
macroCallForm += ' [$name...]';
|
||||
restIndex = maxArgs;
|
||||
requireRest = true;
|
||||
maxArgs = null;
|
||||
default:
|
||||
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) {
|
||||
args[innerArgNames.shift()] = if (exps.length > idx) innerExps[idx] else null;
|
||||
}
|
||||
if (innerArgNames.length > 0)
|
||||
args[innerArgNames.shift()] = innerExps.slice(restIndex);
|
||||
if (innerArgNames.length > 0) {
|
||||
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 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
|
||||
// and put the pieces back together in a modular way
|
||||
(defmacro altDefun [name args &rest body]
|
||||
(defmacro altDefun [name args &body body]
|
||||
(let [argPairs
|
||||
(groups (expList args) 2)
|
||||
untypedArgs
|
||||
|
@@ -1,9 +1,9 @@
|
||||
(defmacro year [num &rest body]
|
||||
(defmacro year [num &body body]
|
||||
`(#when ,(symbol (+ "year" (symbolNameValue num)))
|
||||
(print (+ "year " (Std.string ,num)))
|
||||
,@body))
|
||||
|
||||
(defmacro day [num &rest body]
|
||||
(defmacro day [num &body body]
|
||||
`(#when ,(symbol (+ "day" (symbolNameValue num)))
|
||||
(print (+ "day " (Std.string ,num)))
|
||||
,@body))
|
||||
|
@@ -16,7 +16,7 @@
|
||||
(defmethod _index [x y]
|
||||
(+ x (* y width)))
|
||||
|
||||
(defmacro withIndex [idxName xName yName &rest body]
|
||||
(defmacro withIndex [idxName xName yName &body body]
|
||||
`(let [,idxName (_index ,xName ,yName)]
|
||||
,@body))
|
||||
|
||||
|
@@ -240,7 +240,7 @@
|
||||
random Std.random
|
||||
int Std.int)))
|
||||
|
||||
(defmacro withValueOrInputBox [v &rest body]
|
||||
(defmacro withValueOrInputBox [v &body body]
|
||||
`(if ,v
|
||||
{,@body}
|
||||
(awaitLet [,v (inputBox)]
|
||||
|
@@ -107,7 +107,7 @@
|
||||
(set lastCollector (_composeArgCollector collectedArgs arg lastCollector)))
|
||||
(lastCollector)))
|
||||
|
||||
(defmacro defcommand [name args &rest body]
|
||||
(defmacro defcommand [name args &body body]
|
||||
(let [argPairs
|
||||
(groups (expList args) 2)
|
||||
methodArgs
|
||||
|
@@ -31,7 +31,7 @@
|
||||
|
||||
// Retrieve multiple components from an Entity with mutable access.
|
||||
// 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
|
||||
(groups (expList bindings) 2 Throw)
|
||||
bindingList
|
||||
@@ -49,7 +49,7 @@
|
||||
,@saveList
|
||||
,retValSymbol)))
|
||||
|
||||
(defmacro withWritableEntry [archive e &rest body]
|
||||
(defmacro withWritableEntry [archive e &body body]
|
||||
(let [retValSymbol
|
||||
(symbol)]
|
||||
`(let [,retValSymbol {,@body}]
|
||||
|
Reference in New Issue
Block a user