implement field access
This commit is contained in:
@@ -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<String,(Array<ReaderExp>,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)
|
||||
|
@@ -19,4 +19,7 @@ class KissInterp2TestCase extends Test {
|
||||
function testIf() {
|
||||
_testIf();
|
||||
}
|
||||
function testField() {
|
||||
_testField();
|
||||
}
|
||||
}
|
@@ -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))))
|
||||
(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")))
|
||||
|
Reference in New Issue
Block a user