diff --git a/modules/change_detection/src/parser/ast.js b/modules/change_detection/src/parser/ast.js index f31b3b4104..38e1a36873 100644 --- a/modules/change_detection/src/parser/ast.js +++ b/modules/change_detection/src/parser/ast.js @@ -30,6 +30,7 @@ export class ImplicitReceiver extends AST { } export class Chain extends AST { + @FIELD('final expressions:List') constructor(expressions:List) { this.expressions = expressions; } @@ -42,8 +43,11 @@ export class Chain extends AST { } return result; } -} + visit(visitor) { + visitor.visitChain(this); + } +} export class Conditional extends AST { @FIELD('final condition:AST') @@ -62,9 +66,13 @@ export class Conditional extends AST { return this.falseExp.eval(context); } } + + visit(visitor) { + visitor.visitConditional(this); + } } -export class FieldRead extends AST { +export class AccessMember extends AST { @FIELD('final receiver:AST') @FIELD('final name:string') @FIELD('final getter:Function') @@ -89,15 +97,18 @@ export class FieldRead extends AST { } visit(visitor) { - visitor.visitFieldRead(this); + visitor.visitAccessMember(this); } } export class KeyedAccess extends AST { + @FIELD('final obj:AST') + @FIELD('final key:AST') constructor(obj:AST, key:AST) { this.obj = obj; this.key = key; } + eval(context) { var obj = this.obj.eval(context); var key = this.key.eval(context); @@ -129,6 +140,9 @@ export class KeyedAccess extends AST { return value; } + visit(visitor) { + visitor.visitKeyedAccess(this); + } } export class Formatter extends AST { @@ -152,9 +166,11 @@ export class LiteralPrimitive extends AST { constructor(value) { this.value = value; } + eval(context) { return this.value; } + visit(visitor) { visitor.visitLiteralPrimitive(this); } @@ -165,9 +181,11 @@ export class LiteralArray extends AST { constructor(expressions:List) { this.expressions = expressions; } + eval(context) { return ListWrapper.map(this.expressions, (e) => e.eval(context)); } + visit(visitor) { visitor.visitLiteralArray(this); } @@ -188,6 +206,10 @@ export class LiteralMap extends AST { } return res; } + + visit(visitor) { + visitor.visitLiteralMap(this); + } } export class Binary extends AST { @@ -200,10 +222,6 @@ export class Binary extends AST { this.right = right; } - visit(visitor) { - visitor.visitBinary(this); - } - eval(context) { var left = this.left.eval(context); switch (this.operation) { @@ -234,6 +252,10 @@ export class Binary extends AST { } throw 'Internal error [$operation] not handled'; } + + visit(visitor) { + visitor.visitBinary(this); + } } export class PrefixNot extends AST { @@ -242,10 +264,14 @@ export class PrefixNot extends AST { constructor(expression:AST) { this.expression = expression; } - visit(visitor) { visitor.visitPrefixNot(this); } + eval(context) { return !toBool(this.expression.eval(context)); } + + visit(visitor) { + visitor.visitPrefixNot(this); + } } export class Assignment extends AST { @@ -255,11 +281,14 @@ export class Assignment extends AST { this.target = target; this.value = value; } - visit(visitor) { visitor.visitAssignment(this); } eval(context) { return this.target.assign(context, this.value.eval(context)); } + + visit(visitor) { + visitor.visitAssignment(this); + } } export class MethodCall extends AST { @@ -276,6 +305,10 @@ export class MethodCall extends AST { var obj = this.receiver.eval(context); return this.fn(obj, evalList(context, this.args)); } + + visit(visitor) { + visitor.visitMethodCall(this); + } } export class FunctionCall extends AST { @@ -292,18 +325,28 @@ export class FunctionCall extends AST { var obj = this.target.eval(context); return FunctionWrapper.apply(obj, evalList(context, this.args)); } + + visit(visitor) { + visitor.visitFunctionCall(this); + } } //INTERFACE export class AstVisitor { + visitChain(ast:Chain){} visitImplicitReceiver(ast:ImplicitReceiver) {} - visitFieldRead(ast:FieldRead) {} + visitConditional(ast:Conditional) {} + visitAccessMember(ast:AccessMember) {} + visitKeyedAccess(ast:KeyedAccess) {} visitBinary(ast:Binary) {} visitPrefixNot(ast:PrefixNot) {} visitLiteralPrimitive(ast:LiteralPrimitive) {} visitFormatter(ast:Formatter) {} visitAssignment(ast:Assignment) {} visitLiteralArray(ast:LiteralArray) {} + visitLiteralMap(ast:LiteralMap) {} + visitMethodCall(ast:MethodCall) {} + visitFunctionCall(ast:FunctionCall) {} } var _evalListCache = [[],[0],[0,0],[0,0,0],[0,0,0,0],[0,0,0,0,0]]; diff --git a/modules/change_detection/src/parser/parser.js b/modules/change_detection/src/parser/parser.js index aff7042826..1e111677db 100644 --- a/modules/change_detection/src/parser/parser.js +++ b/modules/change_detection/src/parser/parser.js @@ -6,7 +6,7 @@ import {ClosureMap} from './closure_map'; import { AST, ImplicitReceiver, - FieldRead, + AccessMember, LiteralPrimitive, Expression, Binary, @@ -284,7 +284,7 @@ class _ParseAST { var result = this.parsePrimary(); while (true) { if (this.optionalCharacter($PERIOD)) { - result = this.parseAccessorOrMethodCall(result); + result = this.parseAccessMemberOrMethodCall(result); } else if (this.optionalCharacter($LBRACKET)) { var key = this.parseExpression(); @@ -324,7 +324,7 @@ class _ParseAST { return this.parseLiteralMap(); } else if (this.next.isIdentifier()) { - return this.parseAccessorOrMethodCall(_implicitReceiver); + return this.parseAccessMemberOrMethodCall(_implicitReceiver); } else if (this.next.isNumber()) { var value = this.next.toNumber(); @@ -370,7 +370,7 @@ class _ParseAST { return new LiteralMap(keys, values); } - parseAccessorOrMethodCall(receiver):AST { + parseAccessMemberOrMethodCall(receiver):AST { var id = this.expectIdentifierOrKeyword(); if (this.optionalCharacter($LPAREN)) { @@ -382,7 +382,7 @@ class _ParseAST { } else { var getter = this.closureMap.getter(id); var setter = this.closureMap.setter(id); - return new FieldRead(receiver, id, getter, setter); + return new AccessMember(receiver, id, getter, setter); } } diff --git a/modules/change_detection/src/watch_group.js b/modules/change_detection/src/watch_group.js index bbd565424b..e44ac18a5a 100644 --- a/modules/change_detection/src/watch_group.js +++ b/modules/change_detection/src/watch_group.js @@ -1,6 +1,6 @@ import {ProtoRecord, Record} from './record'; import {FIELD, IMPLEMENTS, isBlank, isPresent} from 'facade/lang'; -import {AST, FieldRead, ImplicitReceiver, AstVisitor} from './parser/ast'; +import {AST, AccessMember, ImplicitReceiver, AstVisitor} from './parser/ast'; export class ProtoWatchGroup { @FIELD('headRecord:ProtoRecord') @@ -126,7 +126,7 @@ class ProtoRecordCreator { //do nothing } - visitFieldRead(ast:FieldRead) { + visitAccessMember(ast:AccessMember) { ast.receiver.visit(this); this.add(new ProtoRecord(this.protoWatchGroup, ast.name, null)); } diff --git a/modules/change_detection/test/change_detector_spec.js b/modules/change_detection/test/change_detector_spec.js index 85a12a3d49..aa422d2d87 100644 --- a/modules/change_detection/test/change_detector_spec.js +++ b/modules/change_detection/test/change_detector_spec.js @@ -1,7 +1,7 @@ import {describe, it, xit, expect} from 'test_lib/test_lib'; import {List, ListWrapper} from 'facade/collection'; -import {ImplicitReceiver, FieldRead} from 'change_detection/parser/ast'; +import {ImplicitReceiver, AccessMember} from 'change_detection/parser/ast'; import {ClosureMap} from 'change_detection/parser/closure_map'; import { @@ -19,7 +19,7 @@ export function main() { var parts = exp.split("."); var cm = new ClosureMap(); return ListWrapper.reduce(parts, function (ast, fieldName) { - return new FieldRead(ast, fieldName, cm.getter(fieldName), cm.setter(fieldName)); + return new AccessMember(ast, fieldName, cm.getter(fieldName), cm.setter(fieldName)); }, new ImplicitReceiver()); } diff --git a/modules/core/test/compiler/view_spec.js b/modules/core/test/compiler/view_spec.js index 55b368b55e..9cd3bcabc7 100644 --- a/modules/core/test/compiler/view_spec.js +++ b/modules/core/test/compiler/view_spec.js @@ -6,7 +6,7 @@ import {ProtoWatchGroup} from 'change_detection/watch_group'; import {ChangeDetector} from 'change_detection/change_detector'; import {DOM, Element} from 'facade/dom'; import {FIELD} from 'facade/lang'; -import {ImplicitReceiver, FieldRead} from 'change_detection/parser/ast'; +import {ImplicitReceiver, AccessMember} from 'change_detection/parser/ast'; import {ClosureMap} from 'change_detection/parser/closure_map'; import {ElementBinder} from 'core/compiler/element_binder'; @@ -20,7 +20,7 @@ class Directive { export function main() { var oneFieldAst = (fieldName) => { var cm = new ClosureMap(); - return new FieldRead(new ImplicitReceiver(), fieldName, + return new AccessMember(new ImplicitReceiver(), fieldName, cm.getter(fieldName), cm.setter(fieldName)); };