diff --git a/src/kiss/KissInterp2.kiss b/src/kiss/KissInterp2.kiss index 9fd9cb6..ffee7cd 100644 --- a/src/kiss/KissInterp2.kiss +++ b/src/kiss/KissInterp2.kiss @@ -4,6 +4,8 @@ (import kiss.Reader.ReadTable) (import kiss.ReaderExp) (import kiss.ReaderExp.ReaderExpDef) +(import kiss.ReaderExp.ReaderExpDef.Symbol) +(import kiss.ReaderExp.ReaderExpDef.FieldExp) (import kiss.Stream) (prop &mut :ReadTable readTable (Reader.builtins)) @@ -20,7 +22,7 @@ (method :Map,Dynamic->Void)->Void> _specialForms [] [ =>"if" ->[args cc] - (evalCC (first ~args) + (evalCC (first args) ->val (if val (evalCC (second args) cc) @@ -42,14 +44,35 @@ (throw "Couldn't read valid expression from $s"))) ([:ReaderExpDef def] (case def + // Special form call ((when (specialForms.exists form) (CallExp (object def (Symbol form)) args)) ((dictGet specialForms form) args cc)) + // Field access + ((FieldExp field obj safe) + (evalCC obj ->v + (if v + (cc (Reflect.getProperty v field)) + (if safe + (cc null) + (throw "field access on null! $(Reader.toString obj.def)"))))) + // Symbol ((Symbol ident) // Check for numbers (let [f (Std.parseFloat ident)] (unless (Math.isNaN f) (cc f) (return))) + // Check for field access + (let [idx (ident.indexOf ".")] + (unless (= -1 idx) + (let [parts (ident.split ".") + &mut exp (object pos null def (Symbol (first parts)))] + (doFor part (parts.slice 1) + (let [safe (StringTools.startsWith part "?")] + (when safe (set part (part.substr 1))) + (set exp (object pos null def (FieldExp part exp safe))))) + (evalCC exp cc) + (return)))) (doFor i (range localScopes.length) (let [scope (nth localScopes (- localScopes.length i 1))] (when (scope.exists ident) diff --git a/src/test/cases/KissInterp2TestCase.hx b/src/test/cases/KissInterp2TestCase.hx index 40642e4..4d13da5 100644 --- a/src/test/cases/KissInterp2TestCase.hx +++ b/src/test/cases/KissInterp2TestCase.hx @@ -19,4 +19,7 @@ class KissInterp2TestCase extends Test { function testIf() { _testIf(); } + function testField() { + _testField(); + } } \ No newline at end of file diff --git a/src/test/cases/KissInterp2TestCase.kiss b/src/test/cases/KissInterp2TestCase.kiss index 660d008..f295305 100644 --- a/src/test/cases/KissInterp2TestCase.kiss +++ b/src/test/cases/KissInterp2TestCase.kiss @@ -1,9 +1,18 @@ +(defMacro assertEval [expected exp] + `(interp.evalCC ,exp ->v (Assert.equals ,expected v))) + (function _testEvalGlobal [] (let [interp (new Interp)] (dictSet interp.globals "a" 5) - (interp.evalCC "a" ->v (Assert.equals 5 v)))) + (assertEval 5 "a"))) (function _testIf [] (let [interp (new Interp)] - (interp.evalCC "(if true 5 3)" ->v (Assert.equals 5 v)) - (interp.evalCC "(if false 5 3)" ->v (Assert.equals 3 v)))) \ No newline at end of file + (assertEval 5 "(if true 5 3)") + (assertEval 3 "(if false 5 3)"))) + +(function _testField [] + (let [interp (new Interp)] + (dictSet interp.globals "obj" (object a 5 b (object c 3))) + (assertEval 5 "obj.a") + (assertEval 3 "obj.b.c")))