KissInterp2 lambda/localFunction/function
Some checks failed
CI / test (push) Failing after 56s
CI / test-core (14, ubuntu-latest, 3.x, js) (push) Failing after 1m52s
CI / test-core (14, ubuntu-latest, 3.x, interp) (push) Failing after 1m39s
CI / test-core (14, ubuntu-latest, 3.x, py) (push) Failing after 2m19s
CI / test-core (14, ubuntu-latest, 3.x, nodejs) (push) Failing after 1m46s
CI / test-core (14, ubuntu-latest, 3.x, cpp) (push) Failing after 2m5s

This commit is contained in:
2025-11-11 18:58:11 -06:00
parent b1a31958fa
commit 4f2bdf0f7f
3 changed files with 67 additions and 1 deletions

View File

@@ -16,7 +16,7 @@
(prop &mut :Map<String,ReaderExpDef> callAliases (new Map))
(prop :Map<String,Dynamic> globals [=>"false" false =>"true" true =>"null" null])
(prop :kiss.List<Map<String,Dynamic>> localScopes [])
(prop &mut :kiss.List<Map<String,Dynamic>> localScopes [])
(prop :Map<String,(Array<ReaderExp>,Dynamic->Void)->Void> specialForms)
@@ -28,6 +28,47 @@
(let [name (symbolNameValue (first args))]
(evalCC (second args) ->val {(dictSet scope name val) (cc val)})))
(method makeFunction [:Array<ReaderExp> argExps :Array<ReaderExp> bodyExps]
(let [capture (localScopes.copy)
argNames []
&mut hasOpt false
&mut minArgs 0]
(doFor arg argExps
(case arg.def
((MetaExp "rest" arg)
(throw "KissInterp2 does not support &rest args"))
((MetaExp "opt" arg)
(set hasOpt true)
(argNames.push (symbolNameValue arg)))
((Symbol argName)
(argNames.push argName)
(unless hasOpt
++minArgs))
(never otherwise)))
(let [f_ (lambda [:Array<Dynamic> args]
(let [currentLocals (localScopes.copy)
innerCapture (capture.copy)
// Oof -- everything needs to be synchronous
&mut :Dynamic returnValue null]
(set localScopes innerCapture)
(localScopes.push (new Map))
(doFor [idx argName] (enumerate argNames)
(dictSet (last localScopes) argName
(if (< idx argNames.length)
(nth args idx)
(if hasOpt
null
(throw "not enough arguments! need $argName")))))
(evalCC (ReaderExpDef.CallExp (object pos null def (ReaderExpDef.Symbol "begin")) bodyExps)
->v
{
(set localScopes currentLocals)
(set returnValue v)
})
returnValue))
f (Reflect.makeVarArgs f_)]
f)))
(method :Map<String,(Array<ReaderExp>,Dynamic->Void)->Void> _specialForms [] [
=>"if"
->[args cc]
@@ -36,6 +77,7 @@
(if val
(evalCC (second args) cc)
(evalCC (third args) cc)))
// TODO handle early return
=>"begin"
->[args cc]
(_evalAllCC args ->values
@@ -87,6 +129,22 @@
(evalCC (second args)
->key
(cc (container.get key))))
=>"lambda"
->[args cc]
(let [argExps (Prelude.argList (first args) "lambda") bodyExps (rest args)]
(cc (makeFunction argExps bodyExps)))
=>"localFunction"
->[args cc]
(let [name (symbolNameValue (first args)) argExps (Prelude.argList (second args) "lambda") bodyExps (args.slice 2)
func (makeFunction argExps bodyExps)]
(dictSet (last localScopes) name func)
(cc func))
=>"function"
->[args cc]
(let [name (symbolNameValue (first args)) argExps (Prelude.argList (second args) "lambda") bodyExps (args.slice 2)
func (makeFunction argExps bodyExps)]
(dictSet globals name func)
(cc func))
])
(method :ReaderExp read [:Dynamic input]

View File

@@ -37,4 +37,8 @@ class KissInterp2TestCase extends Test {
function testNth() {
_testNth();
}
function testLambda() {
_testLambda();
}
}

View File

@@ -44,3 +44,7 @@
(let [interp (new Interp)]
(assertEval 2 "(nth [1 2 3] 1)")
(assertEval 9 #"(dictGet [=>"a" 2 =>"b" 9 =>"c" 3] "b")"#)))
(function _testLambda []
(let [interp (new Interp)]
(assertEval 6 "(let [add ->[a b] (+ a b)] (add 2 4))")))