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

Side by Side Diff: pkg/kernel/lib/interpreter/interpreter.dart

Issue 2764823002: Add representation for object values (Closed)
Patch Set: Created 3 years, 9 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
« no previous file with comments | « no previous file | no next file » | 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) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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 library kernerl.interpreter; 4 library kernel.interpreter;
5 5
6 import '../ast.dart'; 6 import '../ast.dart';
7 7
8 class NotImplemented { 8 class NotImplemented {
9 String message; 9 String message;
10 10
11 NotImplemented(this.message); 11 NotImplemented(this.message);
12 12
13 String toString() => message; 13 String toString() => message;
14 } 14 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 117
118 Value visitVariableSet(VariableSet node, env) { 118 Value visitVariableSet(VariableSet node, env) {
119 return env.assign(node.variable, eval(node.value, env)); 119 return env.assign(node.variable, eval(node.value, env));
120 } 120 }
121 121
122 Value visitStaticInvocation(StaticInvocation node, env) { 122 Value visitStaticInvocation(StaticInvocation node, env) {
123 if ('print' == node.name.toString()) { 123 if ('print' == node.name.toString()) {
124 // Special evaluation of print. 124 // Special evaluation of print.
125 var res = eval(node.arguments.positional[0], env); 125 var res = eval(node.arguments.positional[0], env);
126 print(res.value); 126 print(res.value);
127 return new NullValue(); 127 return Value.nullInstance;
128 } else { 128 } else {
129 throw new NotImplemented('Support for statement type ' 129 throw new NotImplemented('Support for statement type '
130 '${node.runtimeType} is not implemented'); 130 '${node.runtimeType} is not implemented');
131 } 131 }
132 } 132 }
133 133
134 Value visitMethodInvocation(MethodInvocation node, env) {
135 // Currently supports only method invocation with <2 arguments and is used
136 // to evaluate implemented operators for int, double and String values.
137 var receiver = eval(node.receiver, env);
138 if (node.arguments.positional.isNotEmpty) {
139 var argValue = eval(node.arguments.positional.first, env);
140 return receiver.callMethod(node.name.name, argValue);
Kevin Millikin (Google) 2017/03/21 11:55:05 We might choose the name 'invokeMethod' to match '
zhivkag 2017/03/21 12:14:48 Done.
141 } else {
142 return receiver.callMethod(node.name.name);
143 }
144 }
145
146 Value visitConstructorInvocation(ConstructorInvocation node, env) =>
147 defaultExpression(node, env);
148
134 Value visitNot(Not node, env) { 149 Value visitNot(Not node, env) {
135 return new BoolValue(!eval(node.operand, env).asBool); 150 Value operand = eval(node.operand, env).toBoolean();
151 return identical(operand, Value.trueInstance)
152 ? Value.falseInstance
153 : Value.trueInstance;
136 } 154 }
137 155
138 Value visitLogicalExpression(LogicalExpression node, env) { 156 Value visitLogicalExpression(LogicalExpression node, env) {
139 if ('||' == node.operator) { 157 if ('||' == node.operator) {
140 bool left = eval(node.left, env).asBool; 158 BoolValue left = eval(node.left, env).toBoolean();
141 return left 159 return identical(left, Value.trueInstance)
142 ? new BoolValue(true) 160 ? Value.trueInstance
143 : new BoolValue(eval(node.right, env).asBool); 161 : eval(node.right, env).toBoolean();
144 } else { 162 } else {
145 assert('&&' == node.operator); 163 assert('&&' == node.operator);
146 bool left = eval(node.left, env).asBool; 164 BoolValue left = eval(node.left, env).toBoolean();
147 return !left 165 return identical(left, Value.falseInstance)
148 ? new BoolValue(false) 166 ? Value.falseInstance
149 : new BoolValue(eval(node.right, env).asBool); 167 : eval(node.right, env).toBoolean();
150 } 168 }
151 } 169 }
152 170
153 Value visitConditionalExpression(ConditionalExpression node, env) { 171 Value visitConditionalExpression(ConditionalExpression node, env) {
154 if (eval(node.condition, env).asBool) { 172 var condition = eval(node.condition, env).toBoolean();
155 return eval(node.then, env); 173 return identical(condition, Value.trueInstance)
156 } else { 174 ? eval(node.then, env)
157 return eval(node.otherwise, env); 175 : eval(node.otherwise, env);
158 }
159 } 176 }
160 177
161 Value visitStringConcatenation(StringConcatenation node, env) { 178 Value visitStringConcatenation(StringConcatenation node, env) {
162 StringBuffer res = new StringBuffer(); 179 StringBuffer res = new StringBuffer();
163 for (Expression e in node.expressions) { 180 for (Expression e in node.expressions) {
164 res.write(eval(e, env).value); 181 res.write(eval(e, env).value);
165 } 182 }
166 return new StringValue(res.toString()); 183 return new StringValue(res.toString());
167 } 184 }
168 185
169 // Evaluation of BasicLiterals. 186 // Evaluation of BasicLiterals.
170 Value visitStringLiteral(StringLiteral node, env) => 187 Value visitStringLiteral(StringLiteral node, env) =>
171 new StringValue(node.value); 188 new StringValue(node.value);
172 Value visitIntLiteral(IntLiteral node, env) => new IntValue(node.value); 189 Value visitIntLiteral(IntLiteral node, env) => new IntValue(node.value);
173 Value visitDoubleLiteral(DoubleLiteral node, env) => 190 Value visitDoubleLiteral(DoubleLiteral node, env) =>
174 new DoubleValue(node.value); 191 new DoubleValue(node.value);
175 Value visitBoolLiteral(BoolLiteral node, env) => new BoolValue(node.value); 192 Value visitBoolLiteral(BoolLiteral node, env) =>
176 Value visitNullLiteral(NullLiteral node, env) => new NullValue(); 193 node.value ? Value.trueInstance : Value.falseInstance;
194 Value visitNullLiteral(NullLiteral node, env) => Value.nullInstance;
177 195
178 Value visitLet(Let node, env) { 196 Value visitLet(Let node, env) {
179 var value = eval(node.variable.initializer, env); 197 var value = eval(node.variable.initializer, env);
180 var letEnv = new Environment(env); 198 var letEnv = new Environment(env);
181 letEnv.expand(node.variable, value); 199 letEnv.expand(node.variable, value);
182 return eval(node.body, letEnv); 200 return eval(node.body, letEnv);
183 } 201 }
184 } 202 }
185 203
204 class ClassDeclaration {
Kevin Millikin (Google) 2017/03/21 11:55:05 Hmmm. This isn't the declaration, it's our repres
zhivkag 2017/03/21 12:14:48 Acknowledged.
205 static final Map<Reference, ClassDeclaration> _classes =
206 <Reference, ClassDeclaration>{};
207
208 Class currentClass;
209 ClassDeclaration superClass;
210 // The initializers of static fields are evaluated the first time the field
211 // is accessed.
212 List<Value> staticFields = <Value>[];
213 List<Procedure> getters = <Procedure>[];
214 List<Procedure> setters = <Procedure>[];
215 List<Procedure> methods = <Procedure>[];
216
217 factory ClassDeclaration(Reference classRef) {
218 if (_classes.containsKey(classRef)) {
219 return _classes[classRef];
220 }
221 _classes[classRef] = new ClassDeclaration._internal(classRef.asClass);
222 return _classes[classRef];
223 }
224
225 ClassDeclaration._internal(this.currentClass) {
226 if (currentClass.superclass != null) {
227 superClass = new ClassDeclaration(currentClass.superclass.reference);
228 }
229 // TODO: Populate getters, setters and methods.
230 }
231 }
232
186 abstract class Value { 233 abstract class Value {
187 Object get value; 234 Object get value;
188 bool get asBool; 235
236 static final NullValue nullInstance = const NullValue();
237 static final BoolValue trueInstance = const BoolValue(true);
238 static final BoolValue falseInstance = const BoolValue(false);
239
240 const Value();
241
242 BoolValue toBoolean() {
243 return identical(this, Value.trueInstance)
244 ? Value.trueInstance
245 : Value.falseInstance;
246 }
247
248 BoolValue equals(Value other) =>
249 value == other.value ? Value.trueInstance : Value.falseInstance;
250
251 Value callMethod(String name, [Value arg]) {
252 throw notImplemented(obj: name);
253 }
254 }
255
256 class ObjectValue extends Value {
257 List<Value> fields;
258 ClassDeclaration classDeclaration;
259
260 Object get value => this;
261
262 ObjectValue(Constructor constructor, Environment env) {
263 // TODO: Init fields and eval initializers, repeat the same with super.
264 // TODO: Eval the Function body of the constructor, with env expanded with
265 // {VariableDeclaration("this") => this}
266 notImplemented(obj: constructor.name);
267 }
189 } 268 }
190 269
191 class StringValue extends Value { 270 class StringValue extends Value {
192 String value; 271 final String value;
193 272
194 bool get asBool => false; 273 static final operators = <String, Function>{
274 '[]': (StringValue v1, Value v2) => v1[v2],
275 '==': (StringValue v1, Value v2) => v1.equals(v2)
276 };
195 277
196 StringValue(this.value); 278 StringValue(this.value);
279
280 Value callMethod(String name, [Value arg]) {
281 if (!operators.containsKey(name)) {
282 return notImplemented(obj: name);
283 }
284 return operators[name](this, arg);
285 }
286
287 // Operators
288 Value operator [](Value index) => new StringValue(value[index.value]);
197 } 289 }
198 290
199 class IntValue extends Value { 291 abstract class NumValue extends Value {
200 int value; 292 num get value;
201 293
202 bool get asBool => false; 294 NumValue();
295
296 factory NumValue.fromValue(num value) {
297 if (value is int) {
298 return new IntValue(value);
299 } else {
300 assert(value is double);
301 return new DoubleValue(value);
302 }
303 }
304
305 static final operators = <String, Function>{
306 '+': (NumValue v1, Value v2) => v1 + v2,
307 '-': (NumValue v1, Value v2) => v1 - v2,
308 '>': (NumValue v1, Value v2) => v1 > v2,
309 '<': (NumValue v1, Value v2) => v1 < v2,
310 '==': (NumValue v1, Value v2) => v1.equals(v2),
311 'unary-': (NumValue v1) => -v1,
312 };
313
314 Value callMethod(String name, [Value arg]) {
315 if (!operators.containsKey(name)) return notImplemented(obj: name);
316 if (arg == null) return operators[name](this);
317 return operators[name](this, arg);
318 }
319
320 // Operators
321 NumValue operator +(Value other) =>
322 new NumValue.fromValue(value + other.value);
323 NumValue operator -(Value other) =>
324 new NumValue.fromValue(value - other.value);
325 NumValue operator -() => new NumValue.fromValue(-value);
326
327 BoolValue operator >(Value other) =>
328 value > other.value ? Value.trueInstance : Value.falseInstance;
329 BoolValue operator <(Value other) =>
330 value < other.value ? Value.trueInstance : Value.falseInstance;
331 }
332
333 class IntValue extends NumValue {
334 final int value;
203 335
204 IntValue(this.value); 336 IntValue(this.value);
205 } 337 }
206 338
207 class DoubleValue extends Value { 339 class DoubleValue extends NumValue {
208 double value; 340 final double value;
209
210 bool get asBool => false;
211 341
212 DoubleValue(this.value); 342 DoubleValue(this.value);
213 } 343 }
214 344
215 class BoolValue extends Value { 345 class BoolValue extends Value {
216 bool value; 346 final bool value;
217 347
218 bool get asBool => value; 348 const BoolValue(this.value);
219
220 BoolValue(this.value);
221 } 349 }
222 350
223 class NullValue extends Value { 351 class NullValue extends Value {
224 Object get value => null; 352 Object get value => null;
225 bool get asBool => false; 353
354 const NullValue();
226 } 355 }
227 356
228 Object error(obj) { 357 notImplemented({String m, Object obj}) {
229 // TODO: Implement accordingly with support for error handling. 358 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
230 throw new ArgumentError(obj);
231 } 359 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698