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