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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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