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

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

Issue 2764823002: Add representation for object values (Closed)
Patch Set: Add TODO for class representation naming 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.invokeMethod(node.name.name, argValue);
141 } else {
142 return receiver.invokeMethod(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 // TODO(zhivkag): Change misleading name.
205 // This is representation of a class in the interpreter, not a declaration.
206 class ClassDeclaration {
207 static final Map<Reference, ClassDeclaration> _classes =
208 <Reference, ClassDeclaration>{};
209
210 Class currentClass;
211 ClassDeclaration superClass;
212 // The initializers of static fields are evaluated the first time the field
213 // is accessed.
214 List<Value> staticFields = <Value>[];
215 List<Procedure> getters = <Procedure>[];
216 List<Procedure> setters = <Procedure>[];
217 List<Procedure> methods = <Procedure>[];
218
219 factory ClassDeclaration(Reference classRef) {
220 if (_classes.containsKey(classRef)) {
221 return _classes[classRef];
222 }
223 _classes[classRef] = new ClassDeclaration._internal(classRef.asClass);
224 return _classes[classRef];
225 }
226
227 ClassDeclaration._internal(this.currentClass) {
228 if (currentClass.superclass != null) {
229 superClass = new ClassDeclaration(currentClass.superclass.reference);
230 }
231 // TODO: Populate getters, setters and methods.
232 }
233 }
234
186 abstract class Value { 235 abstract class Value {
187 Object get value; 236 Object get value;
188 bool get asBool; 237
238 static final NullValue nullInstance = const NullValue();
239 static final BoolValue trueInstance = const BoolValue(true);
240 static final BoolValue falseInstance = const BoolValue(false);
241
242 const Value();
243
244 BoolValue toBoolean() {
245 return identical(this, Value.trueInstance)
246 ? Value.trueInstance
247 : Value.falseInstance;
248 }
249
250 BoolValue equals(Value other) =>
251 value == other.value ? Value.trueInstance : Value.falseInstance;
252
253 Value invokeMethod(String name, [Value arg]) {
254 throw notImplemented(obj: name);
255 }
256 }
257
258 class ObjectValue extends Value {
259 List<Value> fields;
260 ClassDeclaration classDeclaration;
261
262 Object get value => this;
263
264 ObjectValue(Constructor constructor, Environment env) {
265 // TODO: Init fields and eval initializers, repeat the same with super.
266 // TODO: Eval the Function body of the constructor, with env expanded with
267 // {VariableDeclaration("this") => this}
268 notImplemented(obj: constructor.name);
269 }
189 } 270 }
190 271
191 class StringValue extends Value { 272 class StringValue extends Value {
192 String value; 273 final String value;
193 274
194 bool get asBool => false; 275 static final operators = <String, Function>{
276 '[]': (StringValue v1, Value v2) => v1[v2],
277 '==': (StringValue v1, Value v2) => v1.equals(v2)
278 };
195 279
196 StringValue(this.value); 280 StringValue(this.value);
281
282 Value invokeMethod(String name, [Value arg]) {
283 if (!operators.containsKey(name)) {
284 return notImplemented(obj: name);
285 }
286 return operators[name](this, arg);
287 }
288
289 // Operators
290 Value operator [](Value index) => new StringValue(value[index.value]);
197 } 291 }
198 292
199 class IntValue extends Value { 293 abstract class NumValue extends Value {
200 int value; 294 num get value;
201 295
202 bool get asBool => false; 296 NumValue();
297
298 factory NumValue.fromValue(num value) {
299 if (value is int) {
300 return new IntValue(value);
301 } else {
302 assert(value is double);
303 return new DoubleValue(value);
304 }
305 }
306
307 static final operators = <String, Function>{
308 '+': (NumValue v1, Value v2) => v1 + v2,
309 '-': (NumValue v1, Value v2) => v1 - v2,
310 '>': (NumValue v1, Value v2) => v1 > v2,
311 '<': (NumValue v1, Value v2) => v1 < v2,
312 '==': (NumValue v1, Value v2) => v1.equals(v2),
313 'unary-': (NumValue v1) => -v1,
314 };
315
316 Value invokeMethod(String name, [Value arg]) {
317 if (!operators.containsKey(name)) return notImplemented(obj: name);
318 if (arg == null) return operators[name](this);
319 return operators[name](this, arg);
320 }
321
322 // Operators
323 NumValue operator +(Value other) =>
324 new NumValue.fromValue(value + other.value);
325 NumValue operator -(Value other) =>
326 new NumValue.fromValue(value - other.value);
327 NumValue operator -() => new NumValue.fromValue(-value);
328
329 BoolValue operator >(Value other) =>
330 value > other.value ? Value.trueInstance : Value.falseInstance;
331 BoolValue operator <(Value other) =>
332 value < other.value ? Value.trueInstance : Value.falseInstance;
333 }
334
335 class IntValue extends NumValue {
336 final int value;
203 337
204 IntValue(this.value); 338 IntValue(this.value);
205 } 339 }
206 340
207 class DoubleValue extends Value { 341 class DoubleValue extends NumValue {
208 double value; 342 final double value;
209
210 bool get asBool => false;
211 343
212 DoubleValue(this.value); 344 DoubleValue(this.value);
213 } 345 }
214 346
215 class BoolValue extends Value { 347 class BoolValue extends Value {
216 bool value; 348 final bool value;
217 349
218 bool get asBool => value; 350 const BoolValue(this.value);
219
220 BoolValue(this.value);
221 } 351 }
222 352
223 class NullValue extends Value { 353 class NullValue extends Value {
224 Object get value => null; 354 Object get value => null;
225 bool get asBool => false; 355
356 const NullValue();
226 } 357 }
227 358
228 Object error(obj) { 359 notImplemented({String m, Object obj}) {
229 // TODO: Implement accordingly with support for error handling. 360 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
230 throw new ArgumentError(obj);
231 } 361 }
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