Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: pkg/polymer_expressions/lib/eval.dart

Issue 310903003: Don’t throw on assignments to non-assignable expressions. Allow non-literal indices in assignable e… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/polymer_expressions/lib/polymer_expressions.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 9
10 import 'package:observe/observe.dart'; 10 import 'package:observe/observe.dart';
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 } 74 }
75 75
76 /** 76 /**
77 * 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
78 * of [scope]. 78 * of [scope].
79 * 79 *
80 * [expr] must be an /assignable/ expression, it must not contain 80 * [expr] must be an /assignable/ expression, it must not contain
81 * operators or function invocations, and any index operations must use a 81 * operators or function invocations, and any index operations must use a
82 * literal index. 82 * literal index.
83 */ 83 */
84 Object assign(Expression expr, Object value, Scope scope) { 84 Object assign(Expression expr, Object value, Scope scope,
85 85 {bool checkAssignability: true}) {
86 notAssignable() =>
87 throw new EvalException("Expression is not assignable: $expr");
88 86
89 Expression expression; 87 Expression expression;
90 var property; 88 var property;
91 bool isIndex = false; 89 bool isIndex = false;
92 var filters = <Expression>[]; // reversed order for assignment 90 var filters = <Expression>[]; // reversed order for assignment
93 91
94 while (expr is BinaryOperator) { 92 while (expr is BinaryOperator) {
95 BinaryOperator op = expr; 93 BinaryOperator op = expr;
96 if (op.operator != '|') { 94 if (op.operator != '|') {
97 break; 95 break;
98 } 96 }
99 filters.add(op.right); 97 filters.add(op.right);
100 expr = op.left; 98 expr = op.left;
101 } 99 }
102 100
103 if (expr is Identifier) { 101 if (expr is Identifier) {
104 expression = empty(); 102 expression = empty();
105 Identifier ident = expr; 103 property = expr.value;
106 property = ident.value;
107 } else if (expr is Index) { 104 } else if (expr is Index) {
108 if (expr.argument is! Literal) notAssignable();
109 expression = expr.receiver; 105 expression = expr.receiver;
110 Literal l = expr.argument; 106 property = expr.argument;
111 property = l.value;
112 isIndex = true; 107 isIndex = true;
113 } else if (expr is Getter) { 108 } else if (expr is Getter) {
114 expression = expr.receiver; 109 expression = expr.receiver;
115 property = expr.name; 110 property = expr.name;
116 } else if (expr is Invoke) { 111 } else {
117 expression = expr.receiver; 112 if (checkAssignability) {
118 if (expr.method != null) { 113 throw new EvalException("Expression is not assignable: $expr");
119 if (expr.arguments != null) notAssignable();
120 property = expr.method;
121 } else {
122 notAssignable();
123 } 114 }
124 } else { 115 return null;
125 notAssignable();
126 } 116 }
127 117
128 // transform the values backwards through the filters 118 // transform the values backwards through the filters
129 for (var filterExpr in filters) { 119 for (var filterExpr in filters) {
130 var filter = eval(filterExpr, scope); 120 var filter = eval(filterExpr, scope);
131 if (filter is! Transformer) { 121 if (filter is! Transformer) {
132 throw new EvalException("filter must implement Transformer: $filterExpr"); 122 if (checkAssignability) {
123 throw new EvalException("filter must implement Transformer to be "
124 "assignable: $filterExpr");
125 } else {
126 return null;
127 }
133 } 128 }
134 value = filter.reverse(value); 129 value = filter.reverse(value);
135 } 130 }
136 // make the assignment 131 // evaluate the receiver
137 var o = eval(expression, scope); 132 var o = eval(expression, scope);
138 133
139 // can't assign to a property on a null LHS object. Silently fail. 134 // can't assign to a property on a null LHS object. Silently fail.
140 if (o == null) return null; 135 if (o == null) return null;
141 136
142 if (isIndex) { 137 if (isIndex) {
143 o[property] = value; 138 var index = eval(property, scope);
139 o[index] = value;
144 } else { 140 } else {
145 smoke.write(o, smoke.nameToSymbol(property), value); 141 smoke.write(o, smoke.nameToSymbol(property), value);
146 } 142 }
147 return value; 143 return value;
148 } 144 }
149 145
150 146
151 /** 147 /**
152 * A scope in polymer expressions that can map names to objects. Scopes contain 148 * A scope in polymer expressions that can map names to objects. Scopes contain
153 * a set of named variables and a unique model object. The scope structure 149 * a set of named variables and a unique model object. The scope structure
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after
718 accept(Visitor v) => v.visitInvoke(this); 714 accept(Visitor v) => v.visitInvoke(this);
719 } 715 }
720 716
721 _toBool(v) => (v == null) ? false : v; 717 _toBool(v) => (v == null) ? false : v;
722 718
723 class EvalException implements Exception { 719 class EvalException implements Exception {
724 final String message; 720 final String message;
725 EvalException(this.message); 721 EvalException(this.message);
726 String toString() => "EvalException: $message"; 722 String toString() => "EvalException: $message";
727 } 723 }
OLDNEW
« no previous file with comments | « no previous file | pkg/polymer_expressions/lib/polymer_expressions.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698