change more complicated doc() cases. Close #30

This commit is contained in:
2022-06-11 16:42:13 +00:00
parent 4f5eebc9b3
commit 08c10a8ad2
2 changed files with 53 additions and 48 deletions

View File

@@ -214,31 +214,34 @@ class Macros {
}
}
function bodyIf(formName:String, underlyingIf:String, negated:Bool, wholeExp:ReaderExp, args:Array<ReaderExp>, k) {
wholeExp.checkNumArgs(2, null, '($formName [condition] [body...])');
var b = wholeExp.expBuilder();
var condition = if (negated) {
b.call(
b.symbol("not"), [
args[0]
]);
} else {
args[0];
}
return b.call(b.symbol(underlyingIf), [
condition,
b.begin(args.slice(1))
]);
function addBodyIf(keywordName:String, underlyingIf:String, negated:Bool) {
k.doc(keywordName, 2, null, '($keywordName <condition> <body...>)');
macros[keywordName] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k) -> {
var b = wholeExp.expBuilder();
var condition = if (negated) {
b.call(
b.symbol("not"), [
args[0]
]);
} else {
args[0];
}
return b.call(b.symbol(underlyingIf), [
condition,
b.begin(args.slice(1))
]);
};
}
macros["when"] = bodyIf.bind("when", "if", false);
macros["unless"] = bodyIf.bind("unless", "if", true);
macros["#when"] = bodyIf.bind("#when", "#if", false);
macros["#unless"] = bodyIf.bind("#unless", "#if", true);
macros["cond"] = cond.bind("cond", "if");
macros["#cond"] = cond.bind("#cond", "#if");
addBodyIf("when", "if", false);
addBodyIf("unless", "if", true);
addBodyIf("#when", "#if", false);
addBodyIf("#unless", "#if", true);
addCond(k, macros, "cond", "if");
addCond(k, macros, "#cond", "#if");
k.doc("or", 1, null, "(or <v1> <values...>)");
function _or(wholeExp:ReaderExp, args:Array<ReaderExp>, k) {
wholeExp.checkNumArgs(1, null, "(or <v1> <values...>)");
var b = wholeExp.expBuilder();
var uniqueVarSymbol = b.symbol();
@@ -400,9 +403,9 @@ class Macros {
argNames.push(name);
if (optIndex == -1) {
++minArgs;
macroCallForm += ' [$name]';
macroCallForm += ' <$name>';
} else {
macroCallForm += ' [?$name]';
macroCallForm += ' <?$name>';
}
++maxArgs;
case MetaExp("builder", {pos: _, def: Symbol(name)}):
@@ -413,7 +416,7 @@ class Macros {
}
case MetaExp("opt", {pos: _, def: Symbol(name)}):
argNames.push(name);
macroCallForm += ' [?$name]';
macroCallForm += ' <?$name>';
optIndex = maxArgs;
++maxArgs;
case MetaExp("rest", {pos: _, def: Symbol(name)}):
@@ -421,12 +424,12 @@ class Macros {
KissError.warnFromExp(arg, "Consider using &body instead of &rest when writing macros with bodies.");
}
argNames.push(name);
macroCallForm += ' [$name...]';
macroCallForm += ' <$name...>';
restIndex = maxArgs;
maxArgs = null;
case MetaExp("body", {pos: _, def: Symbol(name)}):
argNames.push(name);
macroCallForm += ' [$name...]';
macroCallForm += ' <$name...>';
restIndex = maxArgs;
requireRest = true;
maxArgs = null;
@@ -441,8 +444,8 @@ class Macros {
if (restIndex == -1)
restIndex = optIndex;
k.doc(name, minArgs, maxArgs, macroCallForm);
macros[name] = (wholeExp:ReaderExp, innerExps:Array<ReaderExp>, k:KissState) -> {
wholeExp.checkNumArgs(minArgs, maxArgs, macroCallForm);
var b = wholeExp.expBuilder();
var innerArgNames = argNames.copy();
@@ -1270,23 +1273,25 @@ class Macros {
}
// cond expands telescopically into a nested if expression
static function cond(formName:String, underlyingIf:String, wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) {
wholeExp.checkNumArgs(1, null, '($formName [cases...])');
var b = wholeExp.expBuilder();
return switch (exps[0].def) {
case CallExp(condition, body):
b.call(b.symbol(underlyingIf), [
condition,
b.begin(body),
if (exps.length > 1) {
cond(formName, underlyingIf, b.callSymbol(formName, exps.slice(1)), exps.slice(1), k);
} else {
b.symbol("null");
}
]);
default:
throw KissError.fromExp(exps[0], 'top-level expression of (cond... ) must be a call list starting with a condition expression');
};
static function addCond(k:KissState, macros:Map<String,MacroFunction>, formName:String, underlyingIf:String) {
k.doc(formName, 1, null, '($formName (<condition> <body...>) <more cases...>)');
function cond (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) {
var b = wholeExp.expBuilder();
return switch (exps[0].def) {
case CallExp(condition, body):
b.call(b.symbol(underlyingIf), [
condition,
b.begin(body),
if (exps.length > 1) {
cond(b.callSymbol(formName, exps.slice(1)), exps.slice(1), k);
} else {
b.symbol("null");
}
]);
default:
throw KissError.fromExp(exps[0], 'top-level expression of ($formName... ) must be a call list starting with a condition expression');
};
}
macros[formName] = cond;
}
}

View File

@@ -473,7 +473,7 @@ class SpecialForms {
}
public static function caseOr(wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState):Expr {
wholeExp.checkNumArgs(2, null, "(or <v1> <v2> <values...>)");
wholeExp.checkNumArgs(2, null, "(or <pattern1> <pattern2> <patterns...>)");
return if (args.length == 2) {
macro ${k.convert(args[0])} | ${k.convert(args[1])};
} else {
@@ -482,7 +482,7 @@ class SpecialForms {
};
public static function caseAs(wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState):Expr {
wholeExp.checkNumArgs(2, 2, "(as [name] [pattern])");
wholeExp.checkNumArgs(2, 2, "(as <name> <pattern>)");
return macro ${k.convert(args[0])} = ${k.convert(args[1])};
};
}