&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
|
||||
|
Reference in New Issue
Block a user