| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library polymer_expressions.eval; | 5 library polymer_expressions.eval; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 import 'dart:mirrors'; | 9 import 'dart:mirrors'; |
| 10 | 10 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 '+': (a) => a, | 40 '+': (a) => a, |
| 41 '-': (a) => -a, | 41 '-': (a) => -a, |
| 42 '!': (a) => !a, | 42 '!': (a) => !a, |
| 43 }; | 43 }; |
| 44 | 44 |
| 45 final _BOOLEAN_OPERATORS = ['!', '||', '&&']; | 45 final _BOOLEAN_OPERATORS = ['!', '||', '&&']; |
| 46 | 46 |
| 47 /** | 47 /** |
| 48 * Evaluation [expr] in the context of [scope]. | 48 * Evaluation [expr] in the context of [scope]. |
| 49 */ | 49 */ |
| 50 Object eval(Expression expr, Scope scope) => observe(expr, scope)._value; | 50 Object eval(Expression expr, Scope scope) { |
| 51 var observer = observe(expr, scope); |
| 52 new Updater(scope).visit(observer); |
| 53 return observer._value; |
| 54 } |
| 51 | 55 |
| 52 | 56 /** |
| 57 * Returns an [ExpressionObserver] that evaluates [expr] in the context of |
| 58 * scope] and listens for any changes on [Observable] values that are |
| 59 * returned from sub-expressions. When a value changes the expression is |
| 60 * reevaluated and the new result is sent to the [onUpdate] stream of the |
| 61 * [ExpressionObsserver]. |
| 62 */ |
| 53 ExpressionObserver observe(Expression expr, Scope scope) { | 63 ExpressionObserver observe(Expression expr, Scope scope) { |
| 54 var observer = new ObserverBuilder(scope).visit(expr); | 64 var observer = new ObserverBuilder(scope).visit(expr); |
| 55 new Updater(scope).visit(observer); | |
| 56 return observer; | 65 return observer; |
| 57 } | 66 } |
| 58 | 67 |
| 59 /** | 68 /** |
| 69 * Causes [expr] to be reevaluated a returns it's value. |
| 70 */ |
| 71 Object update(ExpressionObserver expr, Scope scope) { |
| 72 new Updater(scope).visit(expr); |
| 73 return expr.currentValue; |
| 74 } |
| 75 |
| 76 /** |
| 60 * Assign [value] to the variable or field referenced by [expr] in the context | 77 * Assign [value] to the variable or field referenced by [expr] in the context |
| 61 * of [scope]. | 78 * of [scope]. |
| 62 * | 79 * |
| 63 * [expr] must be an /assignable/ expression, it must not contain | 80 * [expr] must be an /assignable/ expression, it must not contain |
| 64 * operators or function invocations, and any index operations must use a | 81 * operators or function invocations, and any index operations must use a |
| 65 * literal index. | 82 * literal index. |
| 66 */ | 83 */ |
| 67 void assign(Expression expr, Object value, Scope scope) { | 84 void assign(Expression expr, Object value, Scope scope) { |
| 68 | 85 |
| 69 notAssignable() => | 86 notAssignable() => |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 if (memberMirror is VariableMirror || | 176 if (memberMirror is VariableMirror || |
| 160 (memberMirror is MethodMirror && memberMirror.isGetter)) { | 177 (memberMirror is MethodMirror && memberMirror.isGetter)) { |
| 161 return _convert(_modelMirror.getField(symbol).reflectee); | 178 return _convert(_modelMirror.getField(symbol).reflectee); |
| 162 } else if (memberMirror is MethodMirror) { | 179 } else if (memberMirror is MethodMirror) { |
| 163 return new Method(_modelMirror, symbol); | 180 return new Method(_modelMirror, symbol); |
| 164 } | 181 } |
| 165 } | 182 } |
| 166 if (parent != null) { | 183 if (parent != null) { |
| 167 return _convert(parent[name]); | 184 return _convert(parent[name]); |
| 168 } else { | 185 } else { |
| 169 throw new EvalException("variable not found: $name in $hashCode"); | 186 throw new EvalException("variable '$name' not found"); |
| 170 } | 187 } |
| 171 } | 188 } |
| 172 | 189 |
| 173 Object ownerOf(String name) { | 190 Object ownerOf(String name) { |
| 174 if (name == 'this') { | 191 if (name == 'this') { |
| 175 // we could return the Scope if it were Observable, but since assigning | 192 // we could return the Scope if it were Observable, but since assigning |
| 176 // a model to a template destroys and recreates the instance, it doesn't | 193 // a model to a template destroys and recreates the instance, it doesn't |
| 177 // seem neccessary | 194 // seem neccessary |
| 178 return null; | 195 return null; |
| 179 } else if (_variables.containsKey(name)) { | 196 } else if (_variables.containsKey(name)) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 198 var classMirror = _modelMirror.type; | 215 var classMirror = _modelMirror.type; |
| 199 if (getMemberMirror(classMirror, symbol) != null) { | 216 if (getMemberMirror(classMirror, symbol) != null) { |
| 200 return true; | 217 return true; |
| 201 } | 218 } |
| 202 } | 219 } |
| 203 if (parent != null) { | 220 if (parent != null) { |
| 204 return parent.contains(name); | 221 return parent.contains(name); |
| 205 } | 222 } |
| 206 return false; | 223 return false; |
| 207 } | 224 } |
| 208 | |
| 209 String toString() => 'Scope($hashCode $parent)'; | |
| 210 } | 225 } |
| 211 | 226 |
| 212 Object _convert(v) { | 227 Object _convert(v) { |
| 213 if (v is Stream) return new StreamBinding(v); | 228 if (v is Stream) return new StreamBinding(v); |
| 214 return v; | 229 return v; |
| 215 } | 230 } |
| 216 | 231 |
| 217 abstract class ExpressionObserver<E extends Expression> implements Expression { | 232 abstract class ExpressionObserver<E extends Expression> implements Expression { |
| 218 final E _expr; | 233 final E _expr; |
| 219 ExpressionObserver _parent; | 234 ExpressionObserver _parent; |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 Method(this.mirror, this.symbol); | 632 Method(this.mirror, this.symbol); |
| 618 | 633 |
| 619 dynamic call(List args) => mirror.invoke(symbol, args, null).reflectee; | 634 dynamic call(List args) => mirror.invoke(symbol, args, null).reflectee; |
| 620 } | 635 } |
| 621 | 636 |
| 622 class EvalException implements Exception { | 637 class EvalException implements Exception { |
| 623 final String message; | 638 final String message; |
| 624 EvalException(this.message); | 639 EvalException(this.message); |
| 625 String toString() => "EvalException: $message"; | 640 String toString() => "EvalException: $message"; |
| 626 } | 641 } |
| OLD | NEW |