&body macro arguments. Close #7

This commit is contained in:
2021-07-12 20:08:12 -06:00
parent c6834a30fe
commit 5e558e8556
7 changed files with 27 additions and 12 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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))

View File

@@ -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))

View File

@@ -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)]

View File

@@ -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

View File

@@ -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}]