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

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

Issue 2781453002: Change layout of fields in a object values (Closed)
Patch Set: Apply comments 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 kernel.interpreter; 4 library kernel.interpreter;
5 5
6 import '../ast.dart'; 6 import '../ast.dart';
7 import '../ast.dart' as ast show Class;
7 8
8 class NotImplemented { 9 class NotImplemented {
9 String message; 10 String message;
10 11
11 NotImplemented(this.message); 12 NotImplemented(this.message);
12 13
13 String toString() => message; 14 String toString() => message;
14 } 15 }
15 16
16 class Interpreter { 17 class Interpreter {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 Value visitVariableGet(VariableGet node, env) { 97 Value visitVariableGet(VariableGet node, env) {
97 return env.lookup(node.variable); 98 return env.lookup(node.variable);
98 } 99 }
99 100
100 Value visitVariableSet(VariableSet node, env) { 101 Value visitVariableSet(VariableSet node, env) {
101 return env.assign(node.variable, eval(node.value, env)); 102 return env.assign(node.variable, eval(node.value, env));
102 } 103 }
103 104
104 Value visitPropertyGet(PropertyGet node, env) { 105 Value visitPropertyGet(PropertyGet node, env) {
105 Value receiver = eval(node.receiver, env); 106 Value receiver = eval(node.receiver, env);
106 return receiver.classDeclaration.lookupGetter(node.name)(receiver); 107 return receiver.class_.lookupGetter(node.name)(receiver);
107 } 108 }
108 109
109 Value visitPropertySet(PropertySet node, env) { 110 Value visitPropertySet(PropertySet node, env) {
110 Value receiver = eval(node.receiver, env); 111 Value receiver = eval(node.receiver, env);
111 Value value = eval(node.value, env); 112 Value value = eval(node.value, env);
112 receiver.classDeclaration.lookupSetter(node.name)(receiver, value); 113 receiver.class_.lookupSetter(node.name)(receiver, value);
113 return value; 114 return value;
114 } 115 }
115 116
116 Value visitDirectPropertyGet(DirectPropertyGet node, env) { 117 Value visitDirectPropertyGet(DirectPropertyGet node, env) {
117 Value receiver = eval(node.receiver, env); 118 Value receiver = eval(node.receiver, env);
118 return receiver.classDeclaration.getProperty(receiver, node.target); 119 return receiver.class_.getProperty(receiver, node.target);
119 } 120 }
120 121
121 Value visitDirectPropertySet(DirectPropertySet node, env) { 122 Value visitDirectPropertySet(DirectPropertySet node, env) {
122 Value receiver = eval(node.receiver, env); 123 Value receiver = eval(node.receiver, env);
123 Value value = eval(node.value, env); 124 Value value = eval(node.value, env);
124 receiver.classDeclaration.setProperty(receiver, node.target, value); 125 receiver.class_.setProperty(receiver, node.target, value);
125 return value; 126 return value;
126 } 127 }
127 128
128 Value visitStaticGet(StaticGet node, env) => defaultExpression(node, env); 129 Value visitStaticGet(StaticGet node, env) => defaultExpression(node, env);
129 Value visitStaticSet(StaticSet node, env) => defaultExpression(node, env); 130 Value visitStaticSet(StaticSet node, env) => defaultExpression(node, env);
130 131
131 Value visitStaticInvocation(StaticInvocation node, env) { 132 Value visitStaticInvocation(StaticInvocation node, env) {
132 if ('print' == node.name.toString()) { 133 if ('print' == node.name.toString()) {
133 // Special evaluation of print. 134 // Special evaluation of print.
134 var res = eval(node.arguments.positional[0], env); 135 var res = eval(node.arguments.positional[0], env);
(...skipping 11 matching lines...) Expand all
146 var receiver = eval(node.receiver, env); 147 var receiver = eval(node.receiver, env);
147 if (node.arguments.positional.isNotEmpty) { 148 if (node.arguments.positional.isNotEmpty) {
148 var argValue = eval(node.arguments.positional.first, env); 149 var argValue = eval(node.arguments.positional.first, env);
149 return receiver.invokeMethod(node.name, argValue); 150 return receiver.invokeMethod(node.name, argValue);
150 } else { 151 } else {
151 return receiver.invokeMethod(node.name); 152 return receiver.invokeMethod(node.name);
152 } 153 }
153 } 154 }
154 155
155 Value visitConstructorInvocation(ConstructorInvocation node, env) { 156 Value visitConstructorInvocation(ConstructorInvocation node, env) {
156 ClassDeclaration classDeclaration = 157 Class class_ = new Class(node.target.enclosingClass.reference);
157 new ClassDeclaration(node.target.enclosingClass.reference);
158 158
159 Environment emptyEnv = new Environment.empty(); 159 Environment emptyEnv = new Environment.empty();
160 // Currently we don't support initializers. 160 // Currently we don't support initializers.
161 // TODO: Modify to respect dart semantics for initialization. 161 // TODO: Modify to respect dart semantics for initialization.
162 // 1. Init fields and eval initializers, repeat the same with super. 162 // 1. Init fields and eval initializers, repeat the same with super.
163 // 2. Eval the Function body of the constructor. 163 // 2. Eval the Function body of the constructor.
164 List<Value> fields = classDeclaration.instanceFields 164 List<Value> fields = class_.instanceFields
165 .map((Field f) => eval(f.initializer, emptyEnv)) 165 .map((Field f) => eval(f.initializer ?? new NullLiteral(), emptyEnv))
166 .toList(growable: false); 166 .toList(growable: false);
167 167
168 return new ObjectValue(classDeclaration, fields); 168 return new ObjectValue(class_, fields);
169 } 169 }
170 170
171 Value visitNot(Not node, env) { 171 Value visitNot(Not node, env) {
172 Value operand = eval(node.operand, env).toBoolean(); 172 Value operand = eval(node.operand, env).toBoolean();
173 return identical(operand, Value.trueInstance) 173 return identical(operand, Value.trueInstance)
174 ? Value.falseInstance 174 ? Value.falseInstance
175 : Value.trueInstance; 175 : Value.trueInstance;
176 } 176 }
177 177
178 Value visitLogicalExpression(LogicalExpression node, env) { 178 Value visitLogicalExpression(LogicalExpression node, env) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 : Value.nullInstance; 267 : Value.nullInstance;
268 env.expand(node, value); 268 env.expand(node, value);
269 } 269 }
270 } 270 }
271 271
272 typedef Value Getter(Value receiver); 272 typedef Value Getter(Value receiver);
273 typedef void Setter(Value receiver, Value value); 273 typedef void Setter(Value receiver, Value value);
274 274
275 // TODO(zhivkag): Change misleading name. 275 // TODO(zhivkag): Change misleading name.
276 // This is representation of a class in the interpreter, not a declaration. 276 // This is representation of a class in the interpreter, not a declaration.
277 class ClassDeclaration { 277 class Class {
278 static final Map<Reference, ClassDeclaration> _classes = 278 static final Map<Reference, Class> _classes = <Reference, Class>{};
279 <Reference, ClassDeclaration>{};
280 279
281 ClassDeclaration superclass; 280 Class superclass;
282 List<Field> instanceFields = <Field>[]; 281 List<Field> instanceFields = <Field>[];
283 List<Field> staticFields = <Field>[]; 282 List<Field> staticFields = <Field>[];
284 // Implicit getters and setters for instance Fields. 283 // Implicit getters and setters for instance Fields.
285 Map<Name, Getter> getters = <Name, Getter>{}; 284 Map<Name, Getter> getters = <Name, Getter>{};
286 Map<Name, Setter> setters = <Name, Setter>{}; 285 Map<Name, Setter> setters = <Name, Setter>{};
287 // The initializers of static fields are evaluated the first time the field 286 // The initializers of static fields are evaluated the first time the field
288 // is accessed. 287 // is accessed.
289 List<Value> staticFieldValues = <Value>[]; 288 List<Value> staticFieldValues = <Value>[];
290 289
291 List<Procedure> methods = <Procedure>[]; 290 List<Procedure> methods = <Procedure>[];
292 291
293 factory ClassDeclaration(Reference classRef) { 292 int get instanceSize => instanceFields.length;
294 if (_classes.containsKey(classRef)) { 293
295 return _classes[classRef]; 294 factory Class(Reference classRef) {
296 } 295 return _classes.putIfAbsent(
297 _classes[classRef] = new ClassDeclaration._internal(classRef.asClass); 296 classRef, () => new Class._internal(classRef.asClass));
298 return _classes[classRef];
299 } 297 }
300 298
301 ClassDeclaration._internal(Class currentClass) { 299 Class._internal(ast.Class currentClass) {
302 if (currentClass.superclass != null) { 300 if (currentClass.superclass != null) {
303 superclass = new ClassDeclaration(currentClass.superclass.reference); 301 superclass = new Class(currentClass.superclass.reference);
304 } 302 }
305 303
306 _populateInstanceFields(currentClass); 304 _populateInstanceFields(currentClass);
307
308 // Populate implicit setters and getters.
309 for (int i = 0; i < instanceFields.length; i++) {
310 Field f = instanceFields[i];
311 assert(f.hasImplicitGetter);
312 getters[f.name] = (Value receiver) => receiver.fields[i];
313 if (f.hasImplicitSetter) {
314 setters[f.name] =
315 (Value receiver, Value value) => receiver.fields[i] = value;
316 }
317 }
318 // TODO: Populate methods. 305 // TODO: Populate methods.
319 } 306 }
320 307
321 Getter lookupGetter(Name name) { 308 Getter lookupGetter(Name name) {
322 Getter getter = getters[name]; 309 Getter getter = getters[name];
323 if (getter != null) return getter; 310 if (getter != null) return getter;
324 if (superclass != null) return superclass.lookupGetter(name); 311 if (superclass != null) return superclass.lookupGetter(name);
325 return (Value receiver) => notImplemented(obj: name); 312 return (Value receiver) => notImplemented(obj: name);
326 } 313 }
327 314
(...skipping 18 matching lines...) Expand all
346 if (member is Field) { 333 if (member is Field) {
347 int index = instanceFields.indexOf(member); 334 int index = instanceFields.indexOf(member);
348 // TODO: throw NoSuchMethodError instead. 335 // TODO: throw NoSuchMethodError instead.
349 if (index < 0) return notImplemented(m: 'NoSuchMethod: ${member}'); 336 if (index < 0) return notImplemented(m: 'NoSuchMethod: ${member}');
350 object.fields[index] = value; 337 object.fields[index] = value;
351 return Value.nullInstance; 338 return Value.nullInstance;
352 } 339 }
353 return notImplemented(obj: member); 340 return notImplemented(obj: member);
354 } 341 }
355 342
356 // Populates with the instance fields of the current class and all its 343 /// Populates instance variables and the corresponding implicit getters and
357 // superclasses recursively. 344 /// setters for the current class and its superclass recursively.
358 _populateInstanceFields(Class class_) { 345 _populateInstanceFields(ast.Class class_) {
359 for (Field f in class_.fields) { 346 if (class_.superclass != null) {
360 if (f.isInstanceMember) { 347 _populateInstanceFields(class_.superclass);
361 instanceFields.add(f);
362 }
363 } 348 }
364 349
365 if (class_.superclass != null) { 350 for (Field f in class_.fields) {
366 _populateInstanceFields(class_.superclass); 351 if (f.isStatic) continue;
352 instanceFields.add(f);
353 assert(f.hasImplicitGetter);
354
355 int currentFieldIndex = instanceFields.length - 1;
356
357 // Shadowing an inherited getter with the same name.
358 getters[f.name] = (Value receiver) => receiver.fields[currentFieldIndex];
359 if (f.hasImplicitSetter) {
360 // Shadowing an inherited setter with the same name.
361 setters[f.name] = (Value receiver, Value value) =>
362 receiver.fields[currentFieldIndex] = value;
363 }
367 } 364 }
368 } 365 }
369 } 366 }
370 367
371 abstract class Value { 368 abstract class Value {
372 ClassDeclaration get classDeclaration; 369 Class get class_;
373 List<Value> get fields; 370 List<Value> get fields;
374 Object get value; 371 Object get value;
375 372
376 static final NullValue nullInstance = const NullValue(); 373 static final NullValue nullInstance = const NullValue();
377 static final BoolValue trueInstance = const BoolValue(true); 374 static final BoolValue trueInstance = const BoolValue(true);
378 static final BoolValue falseInstance = const BoolValue(false); 375 static final BoolValue falseInstance = const BoolValue(false);
379 376
380 const Value(); 377 const Value();
381 378
382 BoolValue toBoolean() { 379 BoolValue toBoolean() {
383 return identical(this, Value.trueInstance) 380 return identical(this, Value.trueInstance)
384 ? Value.trueInstance 381 ? Value.trueInstance
385 : Value.falseInstance; 382 : Value.falseInstance;
386 } 383 }
387 384
388 BoolValue equals(Value other) => 385 BoolValue equals(Value other) =>
389 value == other.value ? Value.trueInstance : Value.falseInstance; 386 value == other.value ? Value.trueInstance : Value.falseInstance;
390 387
391 Value invokeMethod(Name name, [Value arg]) { 388 Value invokeMethod(Name name, [Value arg]) {
392 throw notImplemented(obj: name); 389 throw notImplemented(obj: name);
393 } 390 }
394 } 391 }
395 392
396 class ObjectValue extends Value { 393 class ObjectValue extends Value {
397 ClassDeclaration classDeclaration; 394 Class class_;
398 List<Value> fields; 395 List<Value> fields;
399 Object get value => this; 396 Object get value => this;
400 397
401 ObjectValue(this.classDeclaration, this.fields); 398 ObjectValue(this.class_, this.fields);
402 } 399 }
403 400
404 abstract class LiteralValue extends Value { 401 abstract class LiteralValue extends Value {
405 ClassDeclaration get classDeclaration => 402 Class get class_ =>
406 notImplemented(m: "Loading class for literal is not implemented."); 403 notImplemented(m: "Loading class for literal is not implemented.");
407 List<Value> get fields => 404 List<Value> get fields =>
408 notImplemented(m: "Literal value does not have fields"); 405 notImplemented(m: "Literal value does not have fields");
409 406
410 const LiteralValue(); 407 const LiteralValue();
411 } 408 }
412 409
413 class StringValue extends LiteralValue { 410 class StringValue extends LiteralValue {
414 final String value; 411 final String value;
415 412
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 490
494 class NullValue extends LiteralValue { 491 class NullValue extends LiteralValue {
495 Object get value => null; 492 Object get value => null;
496 493
497 const NullValue(); 494 const NullValue();
498 } 495 }
499 496
500 notImplemented({String m, Object obj}) { 497 notImplemented({String m, Object obj}) {
501 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); 498 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
502 } 499 }
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