countingLambda
This commit is contained in:
@@ -1039,6 +1039,25 @@ class Macros {
|
|||||||
]));
|
]));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
macros["countingLambda"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k:KissState) -> {
|
||||||
|
wholeExp.checkNumArgs(3, null, "(countingLambda <countVar> [<argsNames...>] <body...>)");
|
||||||
|
var b = wholeExp.expBuilder();
|
||||||
|
|
||||||
|
var countVarSymbol = exps[0];
|
||||||
|
var args = exps[1];
|
||||||
|
var body = exps.slice(2);
|
||||||
|
|
||||||
|
return b.let([
|
||||||
|
b.meta("mut", countVarSymbol), b.int(0)
|
||||||
|
], [b.callSymbol("lambda", [
|
||||||
|
args,
|
||||||
|
b.callSymbol("+=", [
|
||||||
|
countVarSymbol,
|
||||||
|
b.int(1)
|
||||||
|
])
|
||||||
|
].concat(body))]);
|
||||||
|
};
|
||||||
|
|
||||||
return macros;
|
return macros;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -96,8 +96,17 @@ class Reader {
|
|||||||
// ->[args] body
|
// ->[args] body
|
||||||
// ->arg body
|
// ->arg body
|
||||||
// ->{body}
|
// ->{body}
|
||||||
// or any of those with the first expression after -> prefixed by :Void
|
// OR, for countingLambda:
|
||||||
readTable["->"] = (stream:Stream, k) -> {
|
// -+>countVar [args] body
|
||||||
|
// -+>countVar arg body
|
||||||
|
// -+>countVar {body}
|
||||||
|
// or any of those with the first expression after -> or -+> prefixed by :Void
|
||||||
|
function arrowSyntax(countingLambda:Bool, stream:Stream, k:KissState) {
|
||||||
|
var countVar = if (countingLambda) {
|
||||||
|
assertRead(stream, k);
|
||||||
|
} else {
|
||||||
|
null;
|
||||||
|
}
|
||||||
var firstExp = assertRead(stream, k);
|
var firstExp = assertRead(stream, k);
|
||||||
var b = firstExp.expBuilder();
|
var b = firstExp.expBuilder();
|
||||||
|
|
||||||
@@ -127,8 +136,15 @@ class Reader {
|
|||||||
if (!returnsValue) {
|
if (!returnsValue) {
|
||||||
argsExp = TypedExp("Void", argsExp).withPosOf(argsExp);
|
argsExp = TypedExp("Void", argsExp).withPosOf(argsExp);
|
||||||
}
|
}
|
||||||
CallExp(b.symbol("lambda"), [argsExp, bodyExp]);
|
return if (countingLambda) {
|
||||||
};
|
CallExp(b.symbol("countingLambda"), [countVar, argsExp, bodyExp]);
|
||||||
|
} else {
|
||||||
|
CallExp(b.symbol("lambda"), [argsExp, bodyExp]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
readTable["->"] = arrowSyntax.bind(false);
|
||||||
|
readTable["-+>"] = arrowSyntax.bind(true);
|
||||||
|
|
||||||
// Because macro keys are sorted by length and peekChars(0) returns "", this will be used as the default reader macro:
|
// Because macro keys are sorted by length and peekChars(0) returns "", this will be used as the default reader macro:
|
||||||
readTable[""] = (stream:Stream, k:KissState) -> {
|
readTable[""] = (stream:Stream, k:KissState) -> {
|
||||||
|
@@ -204,7 +204,7 @@ class SpecialForms {
|
|||||||
};
|
};
|
||||||
|
|
||||||
map["lambda"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> {
|
map["lambda"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> {
|
||||||
wholeExp.checkNumArgs(2, null, "(lambda [[argsNames...]] [body...])");
|
wholeExp.checkNumArgs(2, null, "(lambda [<argsNames...>] <body...>)");
|
||||||
var returnsValue = switch (args[0].def) {
|
var returnsValue = switch (args[0].def) {
|
||||||
case TypedExp("Void", argNames):
|
case TypedExp("Void", argNames):
|
||||||
args[0] = argNames;
|
args[0] = argNames;
|
||||||
|
@@ -317,6 +317,10 @@ class BasicTestCase extends Test {
|
|||||||
function testClamp() {
|
function testClamp() {
|
||||||
_testClamp();
|
_testClamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testCountingLambda() {
|
||||||
|
_testCountingLambda();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BasicObject {
|
class BasicObject {
|
||||||
|
@@ -560,4 +560,14 @@
|
|||||||
(Assert.equals 10 (clamp bigValue 5 10))
|
(Assert.equals 10 (clamp bigValue 5 10))
|
||||||
(Assert.equals 10 bigValue)
|
(Assert.equals 10 bigValue)
|
||||||
(Assert.equals 5 (clamp smallValue 5 10))
|
(Assert.equals 5 (clamp smallValue 5 10))
|
||||||
(Assert.equals 5 smallValue)))
|
(Assert.equals 5 smallValue)))
|
||||||
|
|
||||||
|
(function _testCountingLambda []
|
||||||
|
(let [fullSyntax
|
||||||
|
(countingLambda a [] a)
|
||||||
|
arrowSyntax
|
||||||
|
-+>b {b}]
|
||||||
|
(Assert.equals 1 (fullSyntax))
|
||||||
|
(Assert.equals 2 (fullSyntax))
|
||||||
|
(Assert.equals 1 (arrowSyntax))
|
||||||
|
(Assert.equals 2 (arrowSyntax))))
|
Reference in New Issue
Block a user