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

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

Issue 2781453002: Change layout of fields in a 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 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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 Value visitVariableGet(VariableGet node, env) { 115 Value visitVariableGet(VariableGet node, env) {
115 return env.lookup(node.variable); 116 return env.lookup(node.variable);
116 } 117 }
117 118
118 Value visitVariableSet(VariableSet node, env) { 119 Value visitVariableSet(VariableSet node, env) {
119 return env.assign(node.variable, eval(node.value, env)); 120 return env.assign(node.variable, eval(node.value, env));
120 } 121 }
121 122
122 Value visitPropertyGet(PropertyGet node, env) { 123 Value visitPropertyGet(PropertyGet node, env) {
123 Value receiver = eval(node.receiver, env); 124 Value receiver = eval(node.receiver, env);
124 return receiver.classDeclaration.lookupGetter(node.name)(receiver); 125 return receiver.class_.lookupGetter(node.name)(receiver);
125 } 126 }
126 127
127 Value visitPropertySet(PropertySet node, env) { 128 Value visitPropertySet(PropertySet node, env) {
128 Value receiver = eval(node.receiver, env); 129 Value receiver = eval(node.receiver, env);
129 Value value = eval(node.value, env); 130 Value value = eval(node.value, env);
130 receiver.classDeclaration.lookupSetter(node.name)(receiver, value); 131 receiver.class_.lookupSetter(node.name)(receiver, value);
131 return value; 132 return value;
132 } 133 }
133 134
134 Value visitDirectPropertyGet(DirectPropertyGet node, env) { 135 Value visitDirectPropertyGet(DirectPropertyGet node, env) {
135 Value receiver = eval(node.receiver, env); 136 Value receiver = eval(node.receiver, env);
136 return receiver.classDeclaration.getProperty(receiver, node.target); 137 return receiver.class_.getProperty(receiver, node.target);
137 } 138 }
138 139
139 Value visitDirectPropertySet(DirectPropertySet node, env) { 140 Value visitDirectPropertySet(DirectPropertySet node, env) {
140 Value receiver = eval(node.receiver, env); 141 Value receiver = eval(node.receiver, env);
141 Value value = eval(node.value, env); 142 Value value = eval(node.value, env);
142 receiver.classDeclaration.setProperty(receiver, node.target, value); 143 receiver.class_.setProperty(receiver, node.target, value);
143 return value; 144 return value;
144 } 145 }
145 146
146 Value visitStaticGet(StaticGet node, env) => defaultExpression(node, env); 147 Value visitStaticGet(StaticGet node, env) => defaultExpression(node, env);
147 Value visitStaticSet(StaticSet node, env) => defaultExpression(node, env); 148 Value visitStaticSet(StaticSet node, env) => defaultExpression(node, env);
148 149
149 Value visitStaticInvocation(StaticInvocation node, env) { 150 Value visitStaticInvocation(StaticInvocation node, env) {
150 if ('print' == node.name.toString()) { 151 if ('print' == node.name.toString()) {
151 // Special evaluation of print. 152 // Special evaluation of print.
152 var res = eval(node.arguments.positional[0], env); 153 var res = eval(node.arguments.positional[0], env);
(...skipping 11 matching lines...) Expand all
164 var receiver = eval(node.receiver, env); 165 var receiver = eval(node.receiver, env);
165 if (node.arguments.positional.isNotEmpty) { 166 if (node.arguments.positional.isNotEmpty) {
166 var argValue = eval(node.arguments.positional.first, env); 167 var argValue = eval(node.arguments.positional.first, env);
167 return receiver.invokeMethod(node.name, argValue); 168 return receiver.invokeMethod(node.name, argValue);
168 } else { 169 } else {
169 return receiver.invokeMethod(node.name); 170 return receiver.invokeMethod(node.name);
170 } 171 }
171 } 172 }
172 173
173 Value visitConstructorInvocation(ConstructorInvocation node, env) { 174 Value visitConstructorInvocation(ConstructorInvocation node, env) {
174 ClassDeclaration classDeclaration = 175 Class class_ = new Class(node.target.enclosingClass.reference);
175 new ClassDeclaration(node.target.enclosingClass.reference);
176 176
177 Environment emptyEnv = new Environment.empty(); 177 Environment emptyEnv = new Environment.empty();
178 // Currently we don't support initializers. 178 // Currently we don't support initializers.
179 // TODO: Modify to respect dart semantics for initialization. 179 // TODO: Modify to respect dart semantics for initialization.
180 // 1. Init fields and eval initializers, repeat the same with super. 180 // 1. Init fields and eval initializers, repeat the same with super.
181 // 2. Eval the Function body of the constructor. 181 // 2. Eval the Function body of the constructor.
182 List<Value> fields = classDeclaration.instanceFields 182 List<Value> fields = class_.instanceFields
183 .map((Field f) => eval(f.initializer, emptyEnv)) 183 .map((Field f) => eval(f.initializer ?? new NullLiteral(), emptyEnv))
184 .toList(growable: false); 184 .toList(growable: false);
185 185
186 return new ObjectValue(classDeclaration, fields); 186 return new ObjectValue(class_, fields);
187 } 187 }
188 188
189 Value visitNot(Not node, env) { 189 Value visitNot(Not node, env) {
190 Value operand = eval(node.operand, env).toBoolean(); 190 Value operand = eval(node.operand, env).toBoolean();
191 return identical(operand, Value.trueInstance) 191 return identical(operand, Value.trueInstance)
192 ? Value.falseInstance 192 ? Value.falseInstance
193 : Value.trueInstance; 193 : Value.trueInstance;
194 } 194 }
195 195
196 Value visitLogicalExpression(LogicalExpression node, env) { 196 Value visitLogicalExpression(LogicalExpression node, env) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 letEnv.expand(node.variable, value); 239 letEnv.expand(node.variable, value);
240 return eval(node.body, letEnv); 240 return eval(node.body, letEnv);
241 } 241 }
242 } 242 }
243 243
244 typedef Value Getter(Value receiver); 244 typedef Value Getter(Value receiver);
245 typedef void Setter(Value receiver, Value value); 245 typedef void Setter(Value receiver, Value value);
246 246
247 // TODO(zhivkag): Change misleading name. 247 // TODO(zhivkag): Change misleading name.
248 // This is representation of a class in the interpreter, not a declaration. 248 // This is representation of a class in the interpreter, not a declaration.
249 class ClassDeclaration { 249 class Class {
250 static final Map<Reference, ClassDeclaration> _classes = 250 static final Map<Reference, Class> _classes = <Reference, Class>{};
251 <Reference, ClassDeclaration>{};
252 251
253 ClassDeclaration superclass; 252 Class superclass;
254 List<Field> instanceFields = <Field>[]; 253 List<Field> instanceFields = <Field>[];
255 List<Field> staticFields = <Field>[]; 254 List<Field> staticFields = <Field>[];
256 // Implicit getters and setters for instance Fields. 255 // Implicit getters and setters for instance Fields.
257 Map<Name, Getter> getters = <Name, Getter>{}; 256 Map<Name, Getter> getters = <Name, Getter>{};
258 Map<Name, Setter> setters = <Name, Setter>{}; 257 Map<Name, Setter> setters = <Name, Setter>{};
259 // The initializers of static fields are evaluated the first time the field 258 // The initializers of static fields are evaluated the first time the field
260 // is accessed. 259 // is accessed.
261 List<Value> staticFieldValues = <Value>[]; 260 List<Value> staticFieldValues = <Value>[];
262 261
263 List<Procedure> methods = <Procedure>[]; 262 List<Procedure> methods = <Procedure>[];
264 263
265 factory ClassDeclaration(Reference classRef) { 264 int get classSize => instanceFields.length;
Kevin Millikin (Google) 2017/03/28 06:56:26 This is more like instanceSize.
zhivkag 2017/03/28 09:18:14 Done.
265
266 factory Class(Reference classRef) {
266 if (_classes.containsKey(classRef)) { 267 if (_classes.containsKey(classRef)) {
Kevin Millikin (Google) 2017/03/28 06:56:26 This pattern is in the libraries as putIfAbsent so
zhivkag 2017/03/28 09:18:14 Done.
267 return _classes[classRef]; 268 return _classes[classRef];
268 } 269 }
269 _classes[classRef] = new ClassDeclaration._internal(classRef.asClass); 270 _classes[classRef] = new Class._internal(classRef.asClass);
270 return _classes[classRef]; 271 return _classes[classRef];
271 } 272 }
272 273
273 ClassDeclaration._internal(Class currentClass) { 274 Class._internal(ast.Class currentClass) {
274 if (currentClass.superclass != null) { 275 if (currentClass.superclass != null) {
275 superclass = new ClassDeclaration(currentClass.superclass.reference); 276 superclass = new Class(currentClass.superclass.reference);
276 } 277 }
277 278
278 _populateInstanceFields(currentClass); 279 _populateInstanceFields(currentClass);
279 280
280 // Populate implicit setters and getters. 281 // Populate implicit setters and getters.
281 for (int i = 0; i < instanceFields.length; i++) { 282 for (int i = (superclass?.classSize ?? 0); i < instanceFields.length; i++) {
Kevin Millikin (Google) 2017/03/28 06:56:26 I think it makes sense to move this into _populate
zhivkag 2017/03/28 09:18:14 Done.
282 Field f = instanceFields[i]; 283 Field f = instanceFields[i];
283 assert(f.hasImplicitGetter); 284 assert(f.hasImplicitGetter);
284 getters[f.name] = (Value receiver) => receiver.fields[i]; 285 getters[f.name] = (Value receiver) => receiver.fields[i];
285 if (f.hasImplicitSetter) { 286 if (f.hasImplicitSetter) {
286 setters[f.name] = 287 setters[f.name] =
287 (Value receiver, Value value) => receiver.fields[i] = value; 288 (Value receiver, Value value) => receiver.fields[i] = value;
288 } 289 }
289 } 290 }
290 // TODO: Populate methods. 291 // TODO: Populate methods.
291 } 292 }
(...skipping 28 matching lines...) Expand all
320 // TODO: throw NoSuchMethodError instead. 321 // TODO: throw NoSuchMethodError instead.
321 if (index < 0) return notImplemented(m: 'NoSuchMethod: ${member}'); 322 if (index < 0) return notImplemented(m: 'NoSuchMethod: ${member}');
322 object.fields[index] = value; 323 object.fields[index] = value;
323 return Value.nullInstance; 324 return Value.nullInstance;
324 } 325 }
325 return notImplemented(obj: member); 326 return notImplemented(obj: member);
326 } 327 }
327 328
328 // Populates with the instance fields of the current class and all its 329 // Populates with the instance fields of the current class and all its
329 // superclasses recursively. 330 // superclasses recursively.
330 _populateInstanceFields(Class class_) { 331 _populateInstanceFields(ast.Class class_) {
332 if (class_.superclass != null) {
333 _populateInstanceFields(class_.superclass);
334 }
331 for (Field f in class_.fields) { 335 for (Field f in class_.fields) {
332 if (f.isInstanceMember) { 336 if (f.isInstanceMember) {
333 instanceFields.add(f); 337 instanceFields.add(f);
334 } 338 }
335 } 339 }
336
337 if (class_.superclass != null) {
338 _populateInstanceFields(class_.superclass);
339 }
340 } 340 }
341 } 341 }
342 342
343 abstract class Value { 343 abstract class Value {
344 ClassDeclaration get classDeclaration; 344 Class get class_;
345 List<Value> get fields; 345 List<Value> get fields;
346 Object get value; 346 Object get value;
347 347
348 static final NullValue nullInstance = const NullValue(); 348 static final NullValue nullInstance = const NullValue();
349 static final BoolValue trueInstance = const BoolValue(true); 349 static final BoolValue trueInstance = const BoolValue(true);
350 static final BoolValue falseInstance = const BoolValue(false); 350 static final BoolValue falseInstance = const BoolValue(false);
351 351
352 const Value(); 352 const Value();
353 353
354 BoolValue toBoolean() { 354 BoolValue toBoolean() {
355 return identical(this, Value.trueInstance) 355 return identical(this, Value.trueInstance)
356 ? Value.trueInstance 356 ? Value.trueInstance
357 : Value.falseInstance; 357 : Value.falseInstance;
358 } 358 }
359 359
360 BoolValue equals(Value other) => 360 BoolValue equals(Value other) =>
361 value == other.value ? Value.trueInstance : Value.falseInstance; 361 value == other.value ? Value.trueInstance : Value.falseInstance;
362 362
363 Value invokeMethod(Name name, [Value arg]) { 363 Value invokeMethod(Name name, [Value arg]) {
364 throw notImplemented(obj: name); 364 throw notImplemented(obj: name);
365 } 365 }
366 } 366 }
367 367
368 class ObjectValue extends Value { 368 class ObjectValue extends Value {
369 ClassDeclaration classDeclaration; 369 Class class_;
370 List<Value> fields; 370 List<Value> fields;
371 Object get value => this; 371 Object get value => this;
372 372
373 ObjectValue(this.classDeclaration, this.fields); 373 ObjectValue(this.class_, this.fields);
374 } 374 }
375 375
376 abstract class LiteralValue extends Value { 376 abstract class LiteralValue extends Value {
377 ClassDeclaration get classDeclaration => 377 Class get class_ =>
378 notImplemented(m: "Loading class for literal is not implemented."); 378 notImplemented(m: "Loading class for literal is not implemented.");
379 List<Value> get fields => 379 List<Value> get fields =>
380 notImplemented(m: "Literal value does not have fields"); 380 notImplemented(m: "Literal value does not have fields");
381 381
382 const LiteralValue(); 382 const LiteralValue();
383 } 383 }
384 384
385 class StringValue extends LiteralValue { 385 class StringValue extends LiteralValue {
386 final String value; 386 final String value;
387 387
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 465
466 class NullValue extends LiteralValue { 466 class NullValue extends LiteralValue {
467 Object get value => null; 467 Object get value => null;
468 468
469 const NullValue(); 469 const NullValue();
470 } 470 }
471 471
472 notImplemented({String m, Object obj}) { 472 notImplemented({String m, Object obj}) {
473 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); 473 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
474 } 474 }
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