OLD | NEW |
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 import '../ast.dart' as ast show Class; |
8 | 8 |
9 import '../log.dart'; | 9 import '../log.dart'; |
10 export '../log.dart'; | 10 export '../log.dart'; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 | 99 |
100 /// Evaluate expressions. | 100 /// Evaluate expressions. |
101 class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { | 101 class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { |
102 Configuration eval(Expression expr, EvalConfiguration config) => | 102 Configuration eval(Expression expr, EvalConfiguration config) => |
103 expr.accept1(this, config); | 103 expr.accept1(this, config); |
104 | 104 |
105 Configuration evalList(List<InterpreterExpression> list, Environment env, | 105 Configuration evalList(List<InterpreterExpression> list, Environment env, |
106 ApplicationContinuation cont) { | 106 ApplicationContinuation cont) { |
107 if (list.isNotEmpty) { | 107 if (list.isNotEmpty) { |
108 return new EvalConfiguration(list.first.expression, env, | 108 return new EvalConfiguration(list.first.expression, env, |
109 new ExpressionListContinuation(list.first, list.skip(1), env, cont)); | 109 new ExpressionListEK(list.first, list.skip(1), env, cont)); |
110 } | 110 } |
111 return new ApplicationConfiguration(cont, <InterpreterValue>[]); | 111 return new ApplicationConfiguration(cont, <InterpreterValue>[]); |
112 } | 112 } |
113 | 113 |
114 Configuration defaultExpression(Expression node, EvalConfiguration config) { | 114 Configuration defaultExpression(Expression node, EvalConfiguration config) { |
115 throw new NotImplemented('Evaluation for expressions of type ' | 115 throw new NotImplemented('Evaluation for expressions of type ' |
116 '${node.runtimeType} is not implemented.'); | 116 '${node.runtimeType} is not implemented.'); |
117 } | 117 } |
118 | 118 |
119 Configuration visitInvalidExpression1( | 119 Configuration visitInvalidExpression1( |
120 InvalidExpression node, EvalConfiguration config) { | 120 InvalidExpression node, EvalConfiguration config) { |
121 throw 'Invalid expression at ${node.location.toString()}'; | 121 throw 'Invalid expression at ${node.location.toString()}'; |
122 } | 122 } |
123 | 123 |
124 Configuration visitVariableGet(VariableGet node, EvalConfiguration config) { | 124 Configuration visitVariableGet(VariableGet node, EvalConfiguration config) { |
125 Value value = config.environment.lookup(node.variable); | 125 Value value = config.environment.lookup(node.variable); |
126 return new ValuePassingConfiguration(config.continuation, value); | 126 return new ValuePassingConfiguration(config.continuation, value); |
127 } | 127 } |
128 | 128 |
129 Configuration visitVariableSet(VariableSet node, EvalConfiguration config) { | 129 Configuration visitVariableSet(VariableSet node, EvalConfiguration config) { |
130 var cont = new VariableSetContinuation( | 130 var cont = new VariableSetEK( |
131 node.variable, config.environment, config.continuation); | 131 node.variable, config.environment, config.continuation); |
132 return new EvalConfiguration(node.value, config.environment, cont); | 132 return new EvalConfiguration(node.value, config.environment, cont); |
133 } | 133 } |
134 | 134 |
135 Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) { | 135 Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) { |
136 var cont = new PropertyGetContinuation(node.name, config.continuation); | 136 var cont = new PropertyGetEK(node.name, config.continuation); |
137 return new EvalConfiguration(node.receiver, config.environment, cont); | 137 return new EvalConfiguration(node.receiver, config.environment, cont); |
138 } | 138 } |
139 | 139 |
140 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { | 140 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { |
141 var cont = new PropertySetContinuation( | 141 var cont = new PropertySetEK( |
142 node.value, node.name, config.environment, config.continuation); | 142 node.value, node.name, config.environment, config.continuation); |
143 return new EvalConfiguration(node.receiver, config.environment, cont); | 143 return new EvalConfiguration(node.receiver, config.environment, cont); |
144 } | 144 } |
145 | 145 |
146 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) => | 146 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) => |
147 defaultExpression(node, config); | 147 defaultExpression(node, config); |
148 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) => | 148 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) => |
149 defaultExpression(node, config); | 149 defaultExpression(node, config); |
150 | 150 |
151 Configuration visitStaticInvocation( | 151 Configuration visitStaticInvocation( |
152 StaticInvocation node, EvalConfiguration config) { | 152 StaticInvocation node, EvalConfiguration config) { |
153 if ('print' == node.name.toString()) { | 153 if ('print' == node.name.toString()) { |
154 var cont = new PrintContinuation(config.continuation); | 154 var cont = new PrintEK(config.continuation); |
155 return new EvalConfiguration( | 155 return new EvalConfiguration( |
156 node.arguments.positional.first, config.environment, cont); | 156 node.arguments.positional.first, config.environment, cont); |
157 } else { | 157 } else { |
158 log.info('static-invocation-${node.target.name.toString()}\n'); | 158 log.info('static-invocation-${node.target.name.toString()}\n'); |
159 | 159 |
160 List<InterpreterExpression> args = | 160 List<InterpreterExpression> args = |
161 _createArgumentExpressionList(node.arguments, node.target.function); | 161 _createArgumentExpressionList(node.arguments, node.target.function); |
162 ApplicationContinuation cont = new StaticInvocationApplication( | 162 ApplicationContinuation cont = |
163 node.target.function, config.continuation); | 163 new StaticInvocationA(node.target.function, config.continuation); |
164 return new EvalListConfiguration(args, config.environment, cont); | 164 return new EvalListConfiguration(args, config.environment, cont); |
165 } | 165 } |
166 } | 166 } |
167 | 167 |
168 Configuration visitMethodInvocation( | 168 Configuration visitMethodInvocation( |
169 MethodInvocation node, EvalConfiguration config) { | 169 MethodInvocation node, EvalConfiguration config) { |
170 // Currently supports only method invocation with <2 arguments and is used | 170 // Currently supports only method invocation with <2 arguments and is used |
171 // to evaluate implemented operators for int, double and String values. | 171 // to evaluate implemented operators for int, double and String values. |
172 var cont = new MethodInvocationContinuation( | 172 var cont = new MethodInvocationEK( |
173 node.arguments, node.name, config.environment, config.continuation); | 173 node.arguments, node.name, config.environment, config.continuation); |
174 | 174 |
175 return new EvalConfiguration(node.receiver, config.environment, cont); | 175 return new EvalConfiguration(node.receiver, config.environment, cont); |
176 } | 176 } |
177 | 177 |
178 Configuration visitConstructorInvocation( | 178 Configuration visitConstructorInvocation( |
179 ConstructorInvocation node, EvalConfiguration config) { | 179 ConstructorInvocation node, EvalConfiguration config) { |
180 ApplicationContinuation cont = | 180 ApplicationContinuation cont = |
181 new ConstructorInvocationApplication(node.target, config.continuation); | 181 new ConstructorInvocationA(node.target, config.continuation); |
182 var args = | 182 var args = |
183 _createArgumentExpressionList(node.arguments, node.target.function); | 183 _createArgumentExpressionList(node.arguments, node.target.function); |
184 | 184 |
185 return new EvalListConfiguration(args, config.environment, cont); | 185 return new EvalListConfiguration(args, config.environment, cont); |
186 } | 186 } |
187 | 187 |
188 Configuration visitNot(Not node, EvalConfiguration config) { | 188 Configuration visitNot(Not node, EvalConfiguration config) { |
189 return new EvalConfiguration(node.operand, config.environment, | 189 return new EvalConfiguration( |
190 new NotContinuation(config.continuation)); | 190 node.operand, config.environment, new NotEK(config.continuation)); |
191 } | 191 } |
192 | 192 |
193 Configuration visitLogicalExpression( | 193 Configuration visitLogicalExpression( |
194 LogicalExpression node, EvalConfiguration config) { | 194 LogicalExpression node, EvalConfiguration config) { |
195 if ('||' == node.operator) { | 195 if ('||' == node.operator) { |
196 var cont = new OrContinuation( | 196 var cont = new OrEK(node.right, config.environment, config.continuation); |
197 node.right, config.environment, config.continuation); | |
198 return new EvalConfiguration(node.left, config.environment, cont); | 197 return new EvalConfiguration(node.left, config.environment, cont); |
199 } else { | 198 } else { |
200 assert('&&' == node.operator); | 199 assert('&&' == node.operator); |
201 var cont = new AndContinuation( | 200 var cont = new AndEK(node.right, config.environment, config.continuation); |
202 node.right, config.environment, config.continuation); | |
203 return new EvalConfiguration(node.left, config.environment, cont); | 201 return new EvalConfiguration(node.left, config.environment, cont); |
204 } | 202 } |
205 } | 203 } |
206 | 204 |
207 Configuration visitConditionalExpression( | 205 Configuration visitConditionalExpression( |
208 ConditionalExpression node, EvalConfiguration config) { | 206 ConditionalExpression node, EvalConfiguration config) { |
209 var cont = new ConditionalContinuation( | 207 var cont = new ConditionalEK( |
210 node.then, node.otherwise, config.environment, config.continuation); | 208 node.then, node.otherwise, config.environment, config.continuation); |
211 return new EvalConfiguration(node.condition, config.environment, cont); | 209 return new EvalConfiguration(node.condition, config.environment, cont); |
212 } | 210 } |
213 | 211 |
214 Configuration visitStringConcatenation( | 212 Configuration visitStringConcatenation( |
215 StringConcatenation node, EvalConfiguration config) { | 213 StringConcatenation node, EvalConfiguration config) { |
216 var cont = new StringConcatenationContinuation(config.continuation); | 214 var cont = new StringConcatenationA(config.continuation); |
217 var expressions = node.expressions | 215 var expressions = node.expressions |
218 .map((Expression e) => new PositionalExpression(e)) | 216 .map((Expression e) => new PositionalExpression(e)) |
219 .toList(); | 217 .toList(); |
220 return new EvalListConfiguration(expressions, config.environment, cont); | 218 return new EvalListConfiguration(expressions, config.environment, cont); |
221 } | 219 } |
222 | 220 |
223 Configuration visitThisExpression( | 221 Configuration visitThisExpression( |
224 ThisExpression node, EvalConfiguration config) { | 222 ThisExpression node, EvalConfiguration config) { |
225 return new ValuePassingConfiguration( | 223 return new ValuePassingConfiguration( |
226 config.continuation, config.environment.thisInstance); | 224 config.continuation, config.environment.thisInstance); |
(...skipping 21 matching lines...) Expand all Loading... |
248 Value value = node.value ? Value.trueInstance : Value.falseInstance; | 246 Value value = node.value ? Value.trueInstance : Value.falseInstance; |
249 return new ValuePassingConfiguration(config.continuation, value); | 247 return new ValuePassingConfiguration(config.continuation, value); |
250 } | 248 } |
251 | 249 |
252 Configuration visitNullLiteral(NullLiteral node, EvalConfiguration config) { | 250 Configuration visitNullLiteral(NullLiteral node, EvalConfiguration config) { |
253 return new ValuePassingConfiguration( | 251 return new ValuePassingConfiguration( |
254 config.continuation, Value.nullInstance); | 252 config.continuation, Value.nullInstance); |
255 } | 253 } |
256 | 254 |
257 Configuration visitLet(Let node, EvalConfiguration config) { | 255 Configuration visitLet(Let node, EvalConfiguration config) { |
258 var letCont = new LetContinuation( | 256 var letCont = new LetEK( |
259 node.variable, node.body, config.environment, config.continuation); | 257 node.variable, node.body, config.environment, config.continuation); |
260 return new EvalConfiguration( | 258 return new EvalConfiguration( |
261 node.variable.initializer, config.environment, letCont); | 259 node.variable.initializer, config.environment, letCont); |
262 } | 260 } |
263 } | 261 } |
264 | 262 |
265 /// Represents a state for statement execution. | 263 /// Represents a state for statement execution. |
266 class State { | 264 class State { |
267 final Environment environment; | 265 final Environment environment; |
268 final Label labels; | 266 final Label labels; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 | 306 |
309 Label(this.statement, this.configuration, this.enclosingLabel); | 307 Label(this.statement, this.configuration, this.enclosingLabel); |
310 | 308 |
311 Label lookupLabel(LabeledStatement s) { | 309 Label lookupLabel(LabeledStatement s) { |
312 if (identical(s, statement)) return this; | 310 if (identical(s, statement)) return this; |
313 assert(enclosingLabel != null); | 311 assert(enclosingLabel != null); |
314 return enclosingLabel.lookupLabel(s); | 312 return enclosingLabel.lookupLabel(s); |
315 } | 313 } |
316 } | 314 } |
317 | 315 |
| 316 // ------------------------------------------------------------------------ |
| 317 // Configurations |
| 318 // ------------------------------------------------------------------------ |
| 319 |
318 abstract class Configuration { | 320 abstract class Configuration { |
319 /// Executes the current and returns the next configuration. | 321 /// Executes the current and returns the next configuration. |
320 Configuration step(StatementExecuter executer); | 322 Configuration step(StatementExecuter executer); |
321 } | 323 } |
322 | 324 |
| 325 /// Represents the configuration for evaluating an [Expression]. |
| 326 class EvalConfiguration extends Configuration { |
| 327 final Expression expression; |
| 328 |
| 329 /// Environment in which the expression is evaluated. |
| 330 final Environment environment; |
| 331 |
| 332 /// Next continuation to be applied. |
| 333 final Continuation continuation; |
| 334 |
| 335 EvalConfiguration(this.expression, this.environment, this.continuation); |
| 336 |
| 337 Configuration step(StatementExecuter executer) => |
| 338 executer.eval(expression, this); |
| 339 } |
| 340 |
| 341 /// Represents the configuration for evaluating a list of expressions. |
| 342 class EvalListConfiguration extends Configuration { |
| 343 final List<InterpreterExpression> expressions; |
| 344 final Environment environment; |
| 345 final Continuation continuation; |
| 346 |
| 347 EvalListConfiguration(this.expressions, this.environment, this.continuation); |
| 348 |
| 349 Configuration step(StatementExecuter executer) => |
| 350 executer.evalList(expressions, environment, continuation); |
| 351 } |
| 352 |
323 /// Represents the configuration for execution of statement. | 353 /// Represents the configuration for execution of statement. |
324 class ExecConfiguration extends Configuration { | 354 class ExecConfiguration extends Configuration { |
325 final Statement statement; | 355 final Statement statement; |
326 final State state; | 356 final State state; |
327 | 357 |
328 ExecConfiguration(this.statement, this.state); | 358 ExecConfiguration(this.statement, this.state); |
329 | 359 |
330 Configuration step(StatementExecuter executer) => | 360 Configuration step(StatementExecuter executer) => |
331 executer.exec(statement, state); | 361 executer.exec(statement, state); |
332 } | 362 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 /// Represents the configuration for applying an [ApplicationContinuation]. | 396 /// Represents the configuration for applying an [ApplicationContinuation]. |
367 class ApplicationConfiguration extends Configuration { | 397 class ApplicationConfiguration extends Configuration { |
368 final ApplicationContinuation continuation; | 398 final ApplicationContinuation continuation; |
369 final List<InterpreterValue> values; | 399 final List<InterpreterValue> values; |
370 | 400 |
371 ApplicationConfiguration(this.continuation, this.values); | 401 ApplicationConfiguration(this.continuation, this.values); |
372 | 402 |
373 Configuration step(StatementExecuter _) => continuation(values); | 403 Configuration step(StatementExecuter _) => continuation(values); |
374 } | 404 } |
375 | 405 |
376 /// Represents the configuration for evaluating an [Expression]. | 406 // ------------------------------------------------------------------------ |
377 class EvalConfiguration extends Configuration { | 407 // Interpreter Expressions and Values |
378 final Expression expression; | 408 // ------------------------------------------------------------------------ |
379 | |
380 /// Environment in which the expression is evaluated. | |
381 final Environment environment; | |
382 | |
383 /// Next continuation to be applied. | |
384 final Continuation continuation; | |
385 | |
386 EvalConfiguration(this.expression, this.environment, this.continuation); | |
387 | |
388 Configuration step(StatementExecuter executer) => | |
389 executer.eval(expression, this); | |
390 } | |
391 | |
392 /// Represents the configuration for evaluating a list of expressions. | |
393 class EvalListConfiguration extends Configuration { | |
394 final List<InterpreterExpression> expressions; | |
395 final Environment environment; | |
396 final Continuation continuation; | |
397 | |
398 EvalListConfiguration(this.expressions, this.environment, this.continuation); | |
399 | |
400 Configuration step(StatementExecuter executer) => | |
401 executer.evalList(expressions, environment, continuation); | |
402 } | |
403 | |
404 abstract class InterpreterExpression { | 409 abstract class InterpreterExpression { |
405 Expression get expression; | 410 Expression get expression; |
406 | 411 |
407 InterpreterValue assignValue(Value v); | 412 InterpreterValue assignValue(Value v); |
408 } | 413 } |
409 | 414 |
410 class PositionalExpression extends InterpreterExpression { | 415 class PositionalExpression extends InterpreterExpression { |
411 final Expression expression; | 416 final Expression expression; |
412 | 417 |
413 PositionalExpression(this.expression); | 418 PositionalExpression(this.expression); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 final Field field; | 476 final Field field; |
472 final Value value; | 477 final Value value; |
473 | 478 |
474 FieldInitializerValue(this.field, this.value); | 479 FieldInitializerValue(this.field, this.value); |
475 } | 480 } |
476 | 481 |
477 abstract class Continuation {} | 482 abstract class Continuation {} |
478 | 483 |
479 /// Represents the continuation called after the evaluation of argument | 484 /// Represents the continuation called after the evaluation of argument |
480 /// expressions. | 485 /// expressions. |
| 486 /// |
| 487 /// There are various kinds of [ApplicationContinuation] and their names are |
| 488 /// suffixed with "A". |
481 abstract class ApplicationContinuation extends Continuation { | 489 abstract class ApplicationContinuation extends Continuation { |
482 Configuration call(List<InterpreterValue> values); | 490 Configuration call(List<InterpreterValue> values); |
483 | 491 |
484 /// Binds actual argument values to formal parameters of the function in a | 492 /// Binds actual argument values to formal parameters of the function in a |
485 /// new environment or in the provided initial environment. | 493 /// new environment or in the provided initial environment. |
486 /// TODO: Add checks for validation of arguments according to spec. | 494 /// TODO: Add checks for validation of arguments according to spec. |
487 static Environment createEnvironment( | 495 static Environment createEnvironment( |
488 FunctionNode function, List<InterpreterValue> args, | 496 FunctionNode function, List<InterpreterValue> args, |
489 [Environment parentEnv]) { | 497 [Environment parentEnv]) { |
490 Environment newEnv = new Environment(parentEnv); | 498 Environment newEnv = new Environment(parentEnv); |
(...skipping 13 matching lines...) Expand all Loading... |
504 | 512 |
505 // Add named parameters. | 513 // Add named parameters. |
506 for (VariableDeclaration v in function.namedParameters) { | 514 for (VariableDeclaration v in function.namedParameters) { |
507 newEnv.expand(v, named[v.name.toString()]); | 515 newEnv.expand(v, named[v.name.toString()]); |
508 } | 516 } |
509 | 517 |
510 return newEnv; | 518 return newEnv; |
511 } | 519 } |
512 } | 520 } |
513 | 521 |
| 522 class StringConcatenationA extends ApplicationContinuation { |
| 523 final ExpressionContinuation continuation; |
| 524 |
| 525 StringConcatenationA(this.continuation); |
| 526 |
| 527 Configuration call(List<InterpreterValue> values) { |
| 528 StringBuffer result = new StringBuffer(); |
| 529 for (InterpreterValue v in values.reversed) { |
| 530 result.write(v.value.value); |
| 531 } |
| 532 return new ValuePassingConfiguration( |
| 533 continuation, new StringValue(result.toString())); |
| 534 } |
| 535 } |
| 536 |
514 /// Represents the application continuation for static invocation. | 537 /// Represents the application continuation for static invocation. |
515 class StaticInvocationApplication extends ApplicationContinuation { | 538 class StaticInvocationA extends ApplicationContinuation { |
516 final FunctionNode function; | 539 final FunctionNode function; |
517 final ExpressionContinuation continuation; | 540 final ExpressionContinuation continuation; |
518 | 541 |
519 StaticInvocationApplication(this.function, this.continuation); | 542 StaticInvocationA(this.function, this.continuation); |
520 | 543 |
521 Configuration call(List<InterpreterValue> argValues) { | 544 Configuration call(List<InterpreterValue> argValues) { |
522 Environment functionEnv = | 545 Environment functionEnv = |
523 ApplicationContinuation.createEnvironment(function, argValues); | 546 ApplicationContinuation.createEnvironment(function, argValues); |
524 | 547 |
525 State bodyState = new State.initial() | 548 State bodyState = new State.initial() |
526 .withExpressionContinuation(continuation) | 549 .withExpressionContinuation(continuation) |
527 .withConfiguration(new ExitConfiguration(continuation)) | 550 .withConfiguration(new ExitConfiguration(continuation)) |
528 .withEnvironment(functionEnv); | 551 .withEnvironment(functionEnv); |
529 return new ExecConfiguration(function.body, bodyState); | 552 return new ExecConfiguration(function.body, bodyState); |
530 } | 553 } |
531 } | 554 } |
532 | 555 |
533 /// Represents the application continuation for constructor invocation applied | 556 /// Represents the application continuation for constructor invocation applied |
534 /// on the list of evaluated arguments. | 557 /// on the list of evaluated arguments. |
535 class ConstructorInvocationApplication extends ApplicationContinuation { | 558 class ConstructorInvocationA extends ApplicationContinuation { |
536 final Constructor constructor; | 559 final Constructor constructor; |
537 final ExpressionContinuation continuation; | 560 final ExpressionContinuation continuation; |
538 | 561 |
539 ConstructorInvocationApplication(this.constructor, this.continuation); | 562 ConstructorInvocationA(this.constructor, this.continuation); |
540 | 563 |
541 Configuration call(List<InterpreterValue> argValues) { | 564 Configuration call(List<InterpreterValue> argValues) { |
542 Environment ctrEnv = ApplicationContinuation.createEnvironment( | 565 Environment ctrEnv = ApplicationContinuation.createEnvironment( |
543 constructor.function, argValues); | 566 constructor.function, argValues); |
544 | 567 |
545 var class_ = new Class(constructor.enclosingClass.reference); | 568 var class_ = new Class(constructor.enclosingClass.reference); |
546 var newObject = | 569 var newObject = |
547 new ObjectValue(class_, new List<Value>(class_.instanceSize)); | 570 new ObjectValue(class_, new List<Value>(class_.instanceSize)); |
548 | 571 |
549 return new ObjectInitializationConfiguration( | 572 return new ObjectInitializationConfiguration( |
550 constructor, | 573 constructor, |
551 new InstanceEnvironment(newObject, ctrEnv), | 574 new InstanceEnvironment(newObject, ctrEnv), |
552 new NewInstanceConfiguration(continuation, newObject)); | 575 new NewInstanceConfiguration(continuation, newObject)); |
553 } | 576 } |
554 } | 577 } |
555 | 578 |
556 /// Represents the application continuation for redirecting constructor | 579 /// Represents the application continuation for redirecting constructor |
557 /// invocation applied on the list of evaluated arguments. | 580 /// invocation applied on the list of evaluated arguments. |
558 class RedirectingConstructorApplication extends ApplicationContinuation { | 581 class RedirectingConstructorA extends ApplicationContinuation { |
559 final Constructor constructor; | 582 final Constructor constructor; |
560 final Environment environment; | 583 final Environment environment; |
561 final ExecConfiguration configuration; | 584 final ExecConfiguration configuration; |
562 | 585 |
563 RedirectingConstructorApplication( | 586 RedirectingConstructorA( |
564 this.constructor, this.environment, this.configuration); | 587 this.constructor, this.environment, this.configuration); |
565 | 588 |
566 Configuration call(List<InterpreterValue> argValues) { | 589 Configuration call(List<InterpreterValue> argValues) { |
567 Value object = environment.thisInstance; | 590 Value object = environment.thisInstance; |
568 Environment ctrEnv = ApplicationContinuation.createEnvironment( | 591 Environment ctrEnv = ApplicationContinuation.createEnvironment( |
569 constructor.function, | 592 constructor.function, |
570 argValues, | 593 argValues, |
571 new InstanceEnvironment(object, new Environment.empty())); | 594 new InstanceEnvironment(object, new Environment.empty())); |
572 | 595 |
573 return new ObjectInitializationConfiguration( | 596 return new ObjectInitializationConfiguration( |
574 constructor, ctrEnv, configuration); | 597 constructor, ctrEnv, configuration); |
575 } | 598 } |
576 } | 599 } |
577 | 600 |
578 /// Represents the application continuation for super constructor | 601 /// Represents the application continuation for super constructor |
579 /// invocation applied on the list of evaluated arguments. | 602 /// invocation applied on the list of evaluated arguments. |
580 class SuperConstructorApplication extends ApplicationContinuation { | 603 class SuperConstructorA extends ApplicationContinuation { |
581 final Constructor constructor; | 604 final Constructor constructor; |
582 final Environment environment; | 605 final Environment environment; |
583 final ExecConfiguration configuration; | 606 final ExecConfiguration configuration; |
584 | 607 |
585 SuperConstructorApplication( | 608 SuperConstructorA(this.constructor, this.environment, this.configuration); |
586 this.constructor, this.environment, this.configuration); | |
587 | 609 |
588 Configuration call(List<InterpreterValue> argValues) { | 610 Configuration call(List<InterpreterValue> argValues) { |
589 Value object = environment.thisInstance; | 611 Value object = environment.thisInstance; |
590 | 612 |
591 Environment superEnv = ApplicationContinuation.createEnvironment( | 613 Environment superEnv = ApplicationContinuation.createEnvironment( |
592 constructor.function, | 614 constructor.function, |
593 argValues, | 615 argValues, |
594 new InstanceEnvironment(object, new Environment.empty())); | 616 new InstanceEnvironment(object, new Environment.empty())); |
595 | 617 |
596 return new ObjectInitializationConfiguration( | 618 return new ObjectInitializationConfiguration( |
(...skipping 10 matching lines...) Expand all Loading... |
607 | 629 |
608 ObjectInitializationConfiguration( | 630 ObjectInitializationConfiguration( |
609 this.constructor, this.environment, this.configuration); | 631 this.constructor, this.environment, this.configuration); |
610 | 632 |
611 Configuration step(StatementExecuter _) { | 633 Configuration step(StatementExecuter _) { |
612 if (constructor.initializers.isNotEmpty && | 634 if (constructor.initializers.isNotEmpty && |
613 constructor.initializers.last is RedirectingInitializer) { | 635 constructor.initializers.last is RedirectingInitializer) { |
614 // Constructor is redirecting. | 636 // Constructor is redirecting. |
615 Initializer initializer = constructor.initializers.first; | 637 Initializer initializer = constructor.initializers.first; |
616 if (initializer is RedirectingInitializer) { | 638 if (initializer is RedirectingInitializer) { |
617 var app = new RedirectingConstructorApplication( | 639 var app = new RedirectingConstructorA( |
618 initializer.target, environment, configuration); | 640 initializer.target, environment, configuration); |
619 var args = _createArgumentExpressionList( | 641 var args = _createArgumentExpressionList( |
620 initializer.arguments, initializer.target.function); | 642 initializer.arguments, initializer.target.function); |
621 | 643 |
622 return new EvalListConfiguration(args, environment, app); | 644 return new EvalListConfiguration(args, environment, app); |
623 } | 645 } |
624 // Redirecting initializer is not the only initializer. | 646 // Redirecting initializer is not the only initializer. |
625 for (Initializer i in constructor.initializers.reversed.skip(1)) { | 647 for (Initializer i in constructor.initializers.reversed.skip(1)) { |
626 assert(i is LocalInitializer); | 648 assert(i is LocalInitializer); |
627 } | 649 } |
628 var class_ = new Class(constructor.enclosingClass.reference); | 650 var class_ = new Class(constructor.enclosingClass.reference); |
629 var initEnv = new Environment(environment); | 651 var initEnv = new Environment(environment); |
630 var cont = new InitializerContinuation( | 652 var cont = new InitializerEK( |
631 class_, initEnv, constructor.initializers, configuration); | 653 class_, initEnv, constructor.initializers, configuration); |
632 return new EvalConfiguration( | 654 return new EvalConfiguration( |
633 (initializer as LocalInitializer).variable.initializer, | 655 (initializer as LocalInitializer).variable.initializer, |
634 initEnv, | 656 initEnv, |
635 cont); | 657 cont); |
636 } | 658 } |
637 | 659 |
638 // Set head of configurations to be executed to configuration for current | 660 // Set head of configurations to be executed to configuration for current |
639 // constructor body. | 661 // constructor body. |
640 var state = new State.initial() | 662 var state = new State.initial() |
641 .withEnvironment(environment) | 663 .withEnvironment(environment) |
642 .withConfiguration(configuration); | 664 .withConfiguration(configuration); |
643 var bodyConfig = new ExecConfiguration(constructor.function.body, state); | 665 var bodyConfig = new ExecConfiguration(constructor.function.body, state); |
644 | 666 |
645 // Initialize fields in immediately enclosing class. | 667 // Initialize fields in immediately enclosing class. |
646 var cont = | 668 var cont = new InstanceFieldsA(constructor, environment, bodyConfig); |
647 new InstanceFieldsApplication(constructor, environment, bodyConfig); | |
648 var fieldExpressions = _createInstanceInitializers(constructor); | 669 var fieldExpressions = _createInstanceInitializers(constructor); |
649 | 670 |
650 return new EvalListConfiguration( | 671 return new EvalListConfiguration( |
651 fieldExpressions, new Environment.empty(), cont); | 672 fieldExpressions, new Environment.empty(), cont); |
652 } | 673 } |
653 | 674 |
654 /// Creates a list of expressions for instance field initializers in | 675 /// Creates a list of expressions for instance field initializers in |
655 /// immediately enclosing class. | 676 /// immediately enclosing class. |
656 static List<InterpreterExpression> _createInstanceInitializers( | 677 static List<InterpreterExpression> _createInstanceInitializers( |
657 Constructor ctr) { | 678 Constructor ctr) { |
658 Class currentClass = new Class(ctr.enclosingClass.reference); | 679 Class currentClass = new Class(ctr.enclosingClass.reference); |
659 List<InterpreterExpression> es = <InterpreterExpression>[]; | 680 List<InterpreterExpression> es = <InterpreterExpression>[]; |
660 | 681 |
661 for (int i = currentClass.superclass?.instanceSize ?? 0; | 682 for (int i = currentClass.superclass?.instanceSize ?? 0; |
662 i < currentClass.instanceSize; | 683 i < currentClass.instanceSize; |
663 i++) { | 684 i++) { |
664 Field current = currentClass.instanceFields[i]; | 685 Field current = currentClass.instanceFields[i]; |
665 if (current.initializer != null) { | 686 if (current.initializer != null) { |
666 es.add(new FieldInitializerExpression(current, current.initializer)); | 687 es.add(new FieldInitializerExpression(current, current.initializer)); |
667 } | 688 } |
668 } | 689 } |
669 | 690 |
670 return es; | 691 return es; |
671 } | 692 } |
672 } | 693 } |
673 | 694 |
674 /// Represents the application continuation applied on the list of evaluated | 695 /// Represents the application continuation applied on the list of evaluated |
675 /// field initializer expressions. | 696 /// field initializer expressions. |
676 class InstanceFieldsApplication extends ApplicationContinuation { | 697 class InstanceFieldsA extends ApplicationContinuation { |
677 final Constructor constructor; | 698 final Constructor constructor; |
678 final Environment environment; | 699 final Environment environment; |
679 final ExecConfiguration configuration; | 700 final ExecConfiguration configuration; |
680 | 701 |
681 final Class _currentClass; | 702 final Class _currentClass; |
682 final ObjectValue _newObject; | 703 final ObjectValue _newObject; |
683 | 704 |
684 InstanceFieldsApplication( | 705 InstanceFieldsA(this.constructor, this.environment, this.configuration) |
685 this.constructor, this.environment, this.configuration) | |
686 : _currentClass = new Class(constructor.enclosingClass.reference), | 706 : _currentClass = new Class(constructor.enclosingClass.reference), |
687 _newObject = environment.thisInstance; | 707 _newObject = environment.thisInstance; |
688 | 708 |
689 Configuration call(List<InterpreterValue> fieldValues) { | 709 Configuration call(List<InterpreterValue> fieldValues) { |
690 for (FieldInitializerValue current in fieldValues.reversed) { | 710 for (FieldInitializerValue current in fieldValues.reversed) { |
691 _currentClass.setProperty(_newObject, current.field, current.value); | 711 _currentClass.setProperty(_newObject, current.field, current.value); |
692 } | 712 } |
693 | 713 |
694 if (constructor.initializers.isEmpty) { | 714 if (constructor.initializers.isEmpty) { |
695 _initializeNullFields(_currentClass, _newObject); | 715 _initializeNullFields(_currentClass, _newObject); |
696 return configuration; | 716 return configuration; |
697 } | 717 } |
698 | 718 |
699 // Produce next configuration. | 719 // Produce next configuration. |
700 if (constructor.initializers.first is SuperInitializer) { | 720 if (constructor.initializers.first is SuperInitializer) { |
701 // SuperInitializer appears last in the initializer list. | 721 // SuperInitializer appears last in the initializer list. |
702 assert(constructor.initializers.length == 1); | 722 assert(constructor.initializers.length == 1); |
703 SuperInitializer current = constructor.initializers.first; | 723 SuperInitializer current = constructor.initializers.first; |
704 var args = _createArgumentExpressionList( | 724 var args = _createArgumentExpressionList( |
705 current.arguments, current.target.function); | 725 current.arguments, current.target.function); |
706 | 726 |
707 var superApp = new SuperConstructorApplication( | 727 var superApp = |
708 current.target, environment, configuration); | 728 new SuperConstructorA(current.target, environment, configuration); |
709 _initializeNullFields(_currentClass, _newObject); | 729 _initializeNullFields(_currentClass, _newObject); |
710 return new EvalListConfiguration(args, environment, superApp); | 730 return new EvalListConfiguration(args, environment, superApp); |
711 } | 731 } |
712 | 732 |
713 Class class_ = new Class(constructor.enclosingClass.reference); | 733 Class class_ = new Class(constructor.enclosingClass.reference); |
714 Environment initEnv = new Environment(environment); | 734 Environment initEnv = new Environment(environment); |
715 | 735 |
716 var cont = new InitializerContinuation( | 736 var cont = new InitializerEK( |
717 class_, initEnv, constructor.initializers, configuration); | 737 class_, initEnv, constructor.initializers, configuration); |
718 return new EvalConfiguration( | 738 return new EvalConfiguration( |
719 _getExpression(constructor.initializers.first), initEnv, cont); | 739 _getExpression(constructor.initializers.first), initEnv, cont); |
720 } | 740 } |
721 } | 741 } |
722 | 742 |
723 /// Represents the expression continuation applied on the list of evaluated | 743 /// Represents the expression continuation applied on the list of evaluated |
724 /// initializer expressions preceding a super call in the list. | 744 /// initializer expressions preceding a super call in the list. |
725 class InitializerContinuation extends ExpressionContinuation { | 745 class InitializerEK extends ExpressionContinuation { |
726 final Class currentClass; | 746 final Class currentClass; |
727 final Environment initializerEnvironment; | 747 final Environment initializerEnvironment; |
728 final List<Initializer> initializers; | 748 final List<Initializer> initializers; |
729 final ExecConfiguration configuration; | 749 final ExecConfiguration configuration; |
730 | 750 |
731 InitializerContinuation(this.currentClass, this.initializerEnvironment, | 751 InitializerEK(this.currentClass, this.initializerEnvironment, |
732 this.initializers, this.configuration); | 752 this.initializers, this.configuration); |
733 | 753 |
734 Configuration call(Value v) { | 754 Configuration call(Value v) { |
735 ObjectValue newObject = initializerEnvironment.thisInstance; | 755 ObjectValue newObject = initializerEnvironment.thisInstance; |
736 Initializer current = initializers.first; | 756 Initializer current = initializers.first; |
737 if (current is FieldInitializer) { | 757 if (current is FieldInitializer) { |
738 currentClass.setProperty(newObject, current.field, v); | 758 currentClass.setProperty(newObject, current.field, v); |
739 } else if (current is LocalInitializer) { | 759 } else if (current is LocalInitializer) { |
740 initializerEnvironment.expand(current.variable, v); | 760 initializerEnvironment.expand(current.variable, v); |
741 } else { | 761 } else { |
742 throw 'Assigning value $v to ${current.runtimeType}'; | 762 throw 'Assigning value $v to ${current.runtimeType}'; |
743 } | 763 } |
744 | 764 |
745 if (initializers.length <= 1) { | 765 if (initializers.length <= 1) { |
746 _initializeNullFields(currentClass, newObject); | 766 _initializeNullFields(currentClass, newObject); |
747 return configuration; | 767 return configuration; |
748 } | 768 } |
749 | 769 |
750 Initializer next = initializers[1]; | 770 Initializer next = initializers[1]; |
751 | 771 |
752 if (next is RedirectingInitializer) { | 772 if (next is RedirectingInitializer) { |
753 // RedirectingInitializer appears last in the initializer list. | 773 // RedirectingInitializer appears last in the initializer list. |
754 assert(initializers.length == 2); | 774 assert(initializers.length == 2); |
755 var app = new RedirectingConstructorApplication( | 775 var app = new RedirectingConstructorA( |
756 next.target, initializerEnvironment, configuration); | 776 next.target, initializerEnvironment, configuration); |
757 var args = | 777 var args = |
758 _createArgumentExpressionList(next.arguments, next.target.function); | 778 _createArgumentExpressionList(next.arguments, next.target.function); |
759 return new EvalListConfiguration(args, initializerEnvironment, app); | 779 return new EvalListConfiguration(args, initializerEnvironment, app); |
760 } | 780 } |
761 | 781 |
762 if (next is SuperInitializer) { | 782 if (next is SuperInitializer) { |
763 // SuperInitializer appears last in the initializer list. | 783 // SuperInitializer appears last in the initializer list. |
764 assert(initializers.length == 2); | 784 assert(initializers.length == 2); |
765 var args = | 785 var args = |
766 _createArgumentExpressionList(next.arguments, next.target.function); | 786 _createArgumentExpressionList(next.arguments, next.target.function); |
767 var superApp = new SuperConstructorApplication( | 787 var superApp = new SuperConstructorA( |
768 next.target, initializerEnvironment, configuration); | 788 next.target, initializerEnvironment, configuration); |
769 _initializeNullFields(currentClass, newObject); | 789 _initializeNullFields(currentClass, newObject); |
770 return new EvalListConfiguration(args, initializerEnvironment, superApp); | 790 return new EvalListConfiguration(args, initializerEnvironment, superApp); |
771 } | 791 } |
772 | 792 |
773 var cont = new InitializerContinuation(currentClass, initializerEnvironment, | 793 var cont = new InitializerEK(currentClass, initializerEnvironment, |
774 initializers.skip(1).toList(), configuration); | 794 initializers.skip(1).toList(), configuration); |
775 return new EvalConfiguration( | 795 return new EvalConfiguration( |
776 _getExpression(next), initializerEnvironment, cont); | 796 _getExpression(next), initializerEnvironment, cont); |
777 } | 797 } |
778 } | 798 } |
779 | 799 |
780 /// Represents the application continuation called after the evaluation of all | 800 /// Represents the application continuation called after the evaluation of all |
781 /// argument expressions for an invocation. | 801 /// argument expressions for an invocation. |
782 class ValueApplication extends ApplicationContinuation { | 802 class ValueA extends ApplicationContinuation { |
783 final InterpreterValue value; | 803 final InterpreterValue value; |
784 final ApplicationContinuation applicationContinuation; | 804 final ApplicationContinuation applicationContinuation; |
785 | 805 |
786 ValueApplication(this.value, this.applicationContinuation); | 806 ValueA(this.value, this.applicationContinuation); |
787 | 807 |
788 Configuration call(List<InterpreterValue> args) { | 808 Configuration call(List<InterpreterValue> args) { |
789 args.add(value); | 809 args.add(value); |
790 return new ApplicationConfiguration(applicationContinuation, args); | 810 return new ApplicationConfiguration(applicationContinuation, args); |
791 } | 811 } |
792 } | 812 } |
793 | 813 |
| 814 // ------------------------------------------------------------------------ |
| 815 // Expression Continuations |
| 816 // ------------------------------------------------------------------------ |
794 /// Represents an expression continuation. | 817 /// Represents an expression continuation. |
| 818 /// |
| 819 /// There are various kinds of [ExpressionContinuation]s and their names are |
| 820 /// suffixed with "EK". |
795 abstract class ExpressionContinuation extends Continuation { | 821 abstract class ExpressionContinuation extends Continuation { |
796 Configuration call(Value v); | 822 Configuration call(Value v); |
797 } | 823 } |
798 | 824 |
799 /// Represents a continuation that returns the next [ExecConfiguration] | 825 /// Represents a continuation that returns the next [ExecConfiguration] |
800 /// to be executed. | 826 /// to be executed. |
801 class ExpressionStatementContinuation extends ExpressionContinuation { | 827 class ExpressionEK extends ExpressionContinuation { |
802 final ExecConfiguration configuration; | 828 final ExecConfiguration configuration; |
803 | 829 |
804 ExpressionStatementContinuation(this.configuration); | 830 ExpressionEK(this.configuration); |
805 | 831 |
806 Configuration call(Value _) { | 832 Configuration call(Value _) { |
807 return configuration; | 833 return configuration; |
808 } | 834 } |
809 } | 835 } |
810 | 836 |
811 class PrintContinuation extends ExpressionContinuation { | 837 class PrintEK extends ExpressionContinuation { |
812 final ExpressionContinuation continuation; | 838 final ExpressionContinuation continuation; |
813 | 839 |
814 PrintContinuation(this.continuation); | 840 PrintEK(this.continuation); |
815 | 841 |
816 Configuration call(Value v) { | 842 Configuration call(Value v) { |
817 log.info('print(${v.value.runtimeType}: ${v.value})\n'); | 843 log.info('print(${v.value.runtimeType}: ${v.value})\n'); |
818 print(v.value); | 844 print(v.value); |
819 return new ValuePassingConfiguration(continuation, Value.nullInstance); | 845 return new ValuePassingConfiguration(continuation, Value.nullInstance); |
820 } | 846 } |
821 } | 847 } |
822 | 848 |
823 class PropertyGetContinuation extends ExpressionContinuation { | 849 class PropertyGetEK extends ExpressionContinuation { |
824 final Name name; | 850 final Name name; |
825 final ExpressionContinuation continuation; | 851 final ExpressionContinuation continuation; |
826 | 852 |
827 PropertyGetContinuation(this.name, this.continuation); | 853 PropertyGetEK(this.name, this.continuation); |
828 | 854 |
829 Configuration call(Value receiver) { | 855 Configuration call(Value receiver) { |
830 // TODO: CPS the invocation of the getter. | 856 // TODO: CPS the invocation of the getter. |
831 Value propertyValue = receiver.class_.lookupGetter(name)(receiver); | 857 Value propertyValue = receiver.class_.lookupGetter(name)(receiver); |
832 return new ValuePassingConfiguration(continuation, propertyValue); | 858 return new ValuePassingConfiguration(continuation, propertyValue); |
833 } | 859 } |
834 } | 860 } |
835 | 861 |
836 class PropertySetContinuation extends ExpressionContinuation { | 862 class PropertySetEK extends ExpressionContinuation { |
837 final Expression value; | 863 final Expression value; |
838 final Name setterName; | 864 final Name setterName; |
839 final Environment environment; | 865 final Environment environment; |
840 final ExpressionContinuation continuation; | 866 final ExpressionContinuation continuation; |
841 | 867 |
842 PropertySetContinuation( | 868 PropertySetEK( |
843 this.value, this.setterName, this.environment, this.continuation); | 869 this.value, this.setterName, this.environment, this.continuation); |
844 | 870 |
845 Configuration call(Value receiver) { | 871 Configuration call(Value receiver) { |
846 var cont = new SetterContinuation(receiver, setterName, continuation); | 872 var cont = new SetterEK(receiver, setterName, continuation); |
847 return new EvalConfiguration(value, environment, cont); | 873 return new EvalConfiguration(value, environment, cont); |
848 } | 874 } |
849 } | 875 } |
850 | 876 |
851 class SetterContinuation extends ExpressionContinuation { | 877 class SetterEK extends ExpressionContinuation { |
852 final Value receiver; | 878 final Value receiver; |
853 final Name name; | 879 final Name name; |
854 final ExpressionContinuation continuation; | 880 final ExpressionContinuation continuation; |
855 | 881 |
856 SetterContinuation(this.receiver, this.name, this.continuation); | 882 SetterEK(this.receiver, this.name, this.continuation); |
857 | 883 |
858 Configuration call(Value v) { | 884 Configuration call(Value v) { |
859 Setter setter = receiver.class_.lookupSetter(name); | 885 Setter setter = receiver.class_.lookupSetter(name); |
860 setter(receiver, v); | 886 setter(receiver, v); |
861 return new ValuePassingConfiguration(continuation, v); | 887 return new ValuePassingConfiguration(continuation, v); |
862 } | 888 } |
863 } | 889 } |
864 | 890 |
865 /// Represents a continuation to be called after the evaluation of an actual | 891 /// Represents a continuation to be called after the evaluation of an actual |
866 /// argument for function invocation. | 892 /// argument for function invocation. |
867 class ExpressionListContinuation extends ExpressionContinuation { | 893 class ExpressionListEK extends ExpressionContinuation { |
868 final InterpreterExpression currentExpression; | 894 final InterpreterExpression currentExpression; |
869 final List<InterpreterExpression> expressions; | 895 final List<InterpreterExpression> expressions; |
870 final Environment environment; | 896 final Environment environment; |
871 final ApplicationContinuation applicationContinuation; | 897 final ApplicationContinuation applicationContinuation; |
872 | 898 |
873 ExpressionListContinuation(this.currentExpression, this.expressions, | 899 ExpressionListEK(this.currentExpression, this.expressions, this.environment, |
874 this.environment, this.applicationContinuation); | 900 this.applicationContinuation); |
875 | 901 |
876 Configuration call(Value v) { | 902 Configuration call(Value v) { |
877 ValueApplication app = new ValueApplication( | 903 ValueA app = |
878 currentExpression.assignValue(v), applicationContinuation); | 904 new ValueA(currentExpression.assignValue(v), applicationContinuation); |
879 return new EvalListConfiguration(expressions, environment, app); | 905 return new EvalListConfiguration(expressions, environment, app); |
880 } | 906 } |
881 } | 907 } |
882 | 908 |
883 class MethodInvocationContinuation extends ExpressionContinuation { | 909 class MethodInvocationEK extends ExpressionContinuation { |
884 final Arguments arguments; | 910 final Arguments arguments; |
885 final Name methodName; | 911 final Name methodName; |
886 final Environment environment; | 912 final Environment environment; |
887 final ExpressionContinuation continuation; | 913 final ExpressionContinuation continuation; |
888 | 914 |
889 MethodInvocationContinuation( | 915 MethodInvocationEK( |
890 this.arguments, this.methodName, this.environment, this.continuation); | 916 this.arguments, this.methodName, this.environment, this.continuation); |
891 | 917 |
892 Configuration call(Value receiver) { | 918 Configuration call(Value receiver) { |
893 if (arguments.positional.isEmpty) { | 919 if (arguments.positional.isEmpty) { |
894 Value returnValue = receiver.invokeMethod(methodName); | 920 Value returnValue = receiver.invokeMethod(methodName); |
895 return new ValuePassingConfiguration(continuation, returnValue); | 921 return new ValuePassingConfiguration(continuation, returnValue); |
896 } | 922 } |
897 var cont = new ArgumentsContinuation( | 923 var cont = new ArgumentsEK( |
898 receiver, methodName, arguments, environment, continuation); | 924 receiver, methodName, arguments, environment, continuation); |
899 | 925 |
900 return new EvalConfiguration(arguments.positional.first, environment, cont); | 926 return new EvalConfiguration(arguments.positional.first, environment, cont); |
901 } | 927 } |
902 } | 928 } |
903 | 929 |
904 class ArgumentsContinuation extends ExpressionContinuation { | 930 class ArgumentsEK extends ExpressionContinuation { |
905 final Value receiver; | 931 final Value receiver; |
906 final Name methodName; | 932 final Name methodName; |
907 final Arguments arguments; | 933 final Arguments arguments; |
908 final Environment environment; | 934 final Environment environment; |
909 final ExpressionContinuation continuation; | 935 final ExpressionContinuation continuation; |
910 | 936 |
911 ArgumentsContinuation(this.receiver, this.methodName, this.arguments, | 937 ArgumentsEK(this.receiver, this.methodName, this.arguments, this.environment, |
912 this.environment, this.continuation); | 938 this.continuation); |
913 | 939 |
914 Configuration call(Value value) { | 940 Configuration call(Value value) { |
915 // Currently evaluates only one argument, for simple method invocations | 941 // Currently evaluates only one argument, for simple method invocations |
916 // with 1 argument. | 942 // with 1 argument. |
917 Value returnValue = receiver.invokeMethod(methodName, value); | 943 Value returnValue = receiver.invokeMethod(methodName, value); |
918 return new ValuePassingConfiguration(continuation, returnValue); | 944 return new ValuePassingConfiguration(continuation, returnValue); |
919 } | 945 } |
920 } | 946 } |
921 | 947 |
922 class VariableSetContinuation extends ExpressionContinuation { | 948 class VariableSetEK extends ExpressionContinuation { |
923 final VariableDeclaration variable; | 949 final VariableDeclaration variable; |
924 final Environment environment; | 950 final Environment environment; |
925 final ExpressionContinuation continuation; | 951 final ExpressionContinuation continuation; |
926 | 952 |
927 VariableSetContinuation(this.variable, this.environment, this.continuation); | 953 VariableSetEK(this.variable, this.environment, this.continuation); |
928 | 954 |
929 Configuration call(Value value) { | 955 Configuration call(Value value) { |
930 environment.assign(variable, value); | 956 environment.assign(variable, value); |
931 return new ValuePassingConfiguration(continuation, value); | 957 return new ValuePassingConfiguration(continuation, value); |
932 } | 958 } |
933 } | 959 } |
934 | 960 |
935 class NotContinuation extends ExpressionContinuation { | 961 class NotEK extends ExpressionContinuation { |
936 final ExpressionContinuation continuation; | 962 final ExpressionContinuation continuation; |
937 | 963 |
938 NotContinuation(this.continuation); | 964 NotEK(this.continuation); |
939 | 965 |
940 Configuration call(Value value) { | 966 Configuration call(Value value) { |
941 Value notValue = identical(Value.trueInstance, value) | 967 Value notValue = identical(Value.trueInstance, value) |
942 ? Value.falseInstance | 968 ? Value.falseInstance |
943 : Value.trueInstance; | 969 : Value.trueInstance; |
944 return new ValuePassingConfiguration(continuation, notValue); | 970 return new ValuePassingConfiguration(continuation, notValue); |
945 } | 971 } |
946 } | 972 } |
947 | 973 |
948 class OrContinuation extends ExpressionContinuation { | 974 class OrEK extends ExpressionContinuation { |
949 final Expression right; | 975 final Expression right; |
950 final Environment environment; | 976 final Environment environment; |
951 final ExpressionContinuation continuation; | 977 final ExpressionContinuation continuation; |
952 | 978 |
953 OrContinuation(this.right, this.environment, this.continuation); | 979 OrEK(this.right, this.environment, this.continuation); |
954 | 980 |
955 Configuration call(Value left) { | 981 Configuration call(Value left) { |
956 return identical(Value.trueInstance, left) | 982 return identical(Value.trueInstance, left) |
957 ? new ValuePassingConfiguration(continuation, Value.trueInstance) | 983 ? new ValuePassingConfiguration(continuation, Value.trueInstance) |
958 : new EvalConfiguration(right, environment, continuation); | 984 : new EvalConfiguration(right, environment, continuation); |
959 } | 985 } |
960 } | 986 } |
961 | 987 |
962 class AndContinuation extends ExpressionContinuation { | 988 class AndEK extends ExpressionContinuation { |
963 final Expression right; | 989 final Expression right; |
964 final Environment environment; | 990 final Environment environment; |
965 final ExpressionContinuation continuation; | 991 final ExpressionContinuation continuation; |
966 | 992 |
967 AndContinuation(this.right, this.environment, this.continuation); | 993 AndEK(this.right, this.environment, this.continuation); |
968 | 994 |
969 Configuration call(Value left) { | 995 Configuration call(Value left) { |
970 return identical(Value.falseInstance, left) | 996 return identical(Value.falseInstance, left) |
971 ? new ValuePassingConfiguration(continuation, Value.falseInstance) | 997 ? new ValuePassingConfiguration(continuation, Value.falseInstance) |
972 : new EvalConfiguration(right, environment, continuation); | 998 : new EvalConfiguration(right, environment, continuation); |
973 } | 999 } |
974 } | 1000 } |
975 | 1001 |
976 class ConditionalContinuation extends ExpressionContinuation { | 1002 class ConditionalEK extends ExpressionContinuation { |
977 final Expression then; | 1003 final Expression then; |
978 final Expression otherwise; | 1004 final Expression otherwise; |
979 final Environment environment; | 1005 final Environment environment; |
980 final ExpressionContinuation continuation; | 1006 final ExpressionContinuation continuation; |
981 | 1007 |
982 ConditionalContinuation( | 1008 ConditionalEK(this.then, this.otherwise, this.environment, this.continuation); |
983 this.then, this.otherwise, this.environment, this.continuation); | |
984 | 1009 |
985 Configuration call(Value value) { | 1010 Configuration call(Value value) { |
986 return identical(Value.trueInstance, value) | 1011 return identical(Value.trueInstance, value) |
987 ? new EvalConfiguration(then, environment, continuation) | 1012 ? new EvalConfiguration(then, environment, continuation) |
988 : new EvalConfiguration(otherwise, environment, continuation); | 1013 : new EvalConfiguration(otherwise, environment, continuation); |
989 } | 1014 } |
990 } | 1015 } |
991 | 1016 |
992 class StringConcatenationContinuation extends ApplicationContinuation { | 1017 class LetEK extends ExpressionContinuation { |
993 final ExpressionContinuation continuation; | |
994 | |
995 StringConcatenationContinuation(this.continuation); | |
996 | |
997 Configuration call(List<InterpreterValue> values) { | |
998 StringBuffer result = new StringBuffer(); | |
999 for (InterpreterValue v in values.reversed) { | |
1000 result.write(v.value.value); | |
1001 } | |
1002 return new ValuePassingConfiguration( | |
1003 continuation, new StringValue(result.toString())); | |
1004 } | |
1005 } | |
1006 | |
1007 class LetContinuation extends ExpressionContinuation { | |
1008 final VariableDeclaration variable; | 1018 final VariableDeclaration variable; |
1009 final Expression letBody; | 1019 final Expression letBody; |
1010 final Environment environment; | 1020 final Environment environment; |
1011 final ExpressionContinuation continuation; | 1021 final ExpressionContinuation continuation; |
1012 | 1022 |
1013 LetContinuation( | 1023 LetEK(this.variable, this.letBody, this.environment, this.continuation); |
1014 this.variable, this.letBody, this.environment, this.continuation); | |
1015 | 1024 |
1016 Configuration call(Value value) { | 1025 Configuration call(Value value) { |
1017 var letEnv = new Environment(environment); | 1026 var letEnv = new Environment(environment); |
1018 letEnv.expand(variable, value); | 1027 letEnv.expand(variable, value); |
1019 return new EvalConfiguration(letBody, letEnv, continuation); | 1028 return new EvalConfiguration(letBody, letEnv, continuation); |
1020 } | 1029 } |
1021 } | 1030 } |
1022 | 1031 |
1023 /// Represents the continuation for the condition expression in [WhileStatement]
. | 1032 /// Represents the continuation for the condition expression in [WhileStatement]
. |
1024 class WhileConditionContinuation extends ExpressionContinuation { | 1033 class WhileConditionEK extends ExpressionContinuation { |
1025 final WhileStatement node; | 1034 final WhileStatement node; |
1026 final State state; | 1035 final State state; |
1027 | 1036 |
1028 WhileConditionContinuation(this.node, this.state); | 1037 WhileConditionEK(this.node, this.state); |
1029 | 1038 |
1030 ExecConfiguration call(Value v) { | 1039 ExecConfiguration call(Value v) { |
1031 if (identical(v, Value.trueInstance)) { | 1040 if (identical(v, Value.trueInstance)) { |
1032 // Add configuration for the While statement to the linked list. | 1041 // Add configuration for the While statement to the linked list. |
1033 ExecConfiguration config = new ExecConfiguration(node, state); | 1042 ExecConfiguration config = new ExecConfiguration(node, state); |
1034 // Configuration for the body of the loop. | 1043 // Configuration for the body of the loop. |
1035 return new ExecConfiguration(node.body, state.withConfiguration(config)); | 1044 return new ExecConfiguration(node.body, state.withConfiguration(config)); |
1036 } | 1045 } |
1037 | 1046 |
1038 return state.statementConfiguration; | 1047 return state.statementConfiguration; |
1039 } | 1048 } |
1040 } | 1049 } |
1041 | 1050 |
1042 /// Represents the continuation for the condition expression in [IfStatement]. | 1051 /// Represents the continuation for the condition expression in [IfStatement]. |
1043 class IfConditionContinuation extends ExpressionContinuation { | 1052 class IfConditionEK extends ExpressionContinuation { |
1044 final Statement then; | 1053 final Statement then; |
1045 final Statement otherwise; | 1054 final Statement otherwise; |
1046 final State state; | 1055 final State state; |
1047 | 1056 |
1048 IfConditionContinuation(this.then, this.otherwise, this.state); | 1057 IfConditionEK(this.then, this.otherwise, this.state); |
1049 | 1058 |
1050 ExecConfiguration call(Value v) { | 1059 ExecConfiguration call(Value v) { |
1051 if (identical(v, Value.trueInstance)) { | 1060 if (identical(v, Value.trueInstance)) { |
1052 log.info("if-then\n"); | 1061 log.info("if-then\n"); |
1053 return new ExecConfiguration(then, state); | 1062 return new ExecConfiguration(then, state); |
1054 } else if (otherwise != null) { | 1063 } else if (otherwise != null) { |
1055 log.info("if-otherwise\n"); | 1064 log.info("if-otherwise\n"); |
1056 return new ExecConfiguration(otherwise, state); | 1065 return new ExecConfiguration(otherwise, state); |
1057 } | 1066 } |
1058 return state.statementConfiguration; | 1067 return state.statementConfiguration; |
1059 } | 1068 } |
1060 } | 1069 } |
1061 | 1070 |
1062 /// Represents the continuation for the initializer expression in | 1071 /// Represents the continuation for the initializer expression in |
1063 /// [VariableDeclaration]. | 1072 /// [VariableDeclaration]. |
1064 class VariableInitializerContinuation extends ExpressionContinuation { | 1073 class VariableInitializerEK extends ExpressionContinuation { |
1065 final VariableDeclaration variable; | 1074 final VariableDeclaration variable; |
1066 final Environment environment; | 1075 final Environment environment; |
1067 final ExecConfiguration nextConfiguration; | 1076 final ExecConfiguration nextConfiguration; |
1068 | 1077 |
1069 VariableInitializerContinuation( | 1078 VariableInitializerEK( |
1070 this.variable, this.environment, this.nextConfiguration); | 1079 this.variable, this.environment, this.nextConfiguration); |
1071 | 1080 |
1072 ExecConfiguration call(Value v) { | 1081 ExecConfiguration call(Value v) { |
1073 environment.expand(variable, v); | 1082 environment.expand(variable, v); |
1074 return nextConfiguration; | 1083 return nextConfiguration; |
1075 } | 1084 } |
1076 } | 1085 } |
1077 | 1086 |
1078 /// Executes statements. | 1087 /// Executes statements. |
1079 /// | 1088 /// |
(...skipping 25 matching lines...) Expand all Loading... |
1105 throw notImplemented( | 1114 throw notImplemented( |
1106 m: "Execution is not implemented for statement:\n$node "); | 1115 m: "Execution is not implemented for statement:\n$node "); |
1107 } | 1116 } |
1108 | 1117 |
1109 Configuration visitInvalidStatement(InvalidStatement node, State state) { | 1118 Configuration visitInvalidStatement(InvalidStatement node, State state) { |
1110 throw "Invalid statement at ${node.location}"; | 1119 throw "Invalid statement at ${node.location}"; |
1111 } | 1120 } |
1112 | 1121 |
1113 Configuration visitExpressionStatement( | 1122 Configuration visitExpressionStatement( |
1114 ExpressionStatement node, State state) { | 1123 ExpressionStatement node, State state) { |
1115 var cont = | 1124 var cont = new ExpressionEK(state.statementConfiguration); |
1116 new ExpressionStatementContinuation(state.statementConfiguration); | |
1117 return new EvalConfiguration(node.expression, state.environment, cont); | 1125 return new EvalConfiguration(node.expression, state.environment, cont); |
1118 } | 1126 } |
1119 | 1127 |
1120 Configuration visitBlock(Block node, State state) { | 1128 Configuration visitBlock(Block node, State state) { |
1121 if (node.statements.isEmpty) { | 1129 if (node.statements.isEmpty) { |
1122 return state.statementConfiguration; | 1130 return state.statementConfiguration; |
1123 } | 1131 } |
1124 State blockState = | 1132 State blockState = |
1125 state.withEnvironment(new Environment(state.environment)); | 1133 state.withEnvironment(new Environment(state.environment)); |
1126 ExecConfiguration configuration = state.statementConfiguration; | 1134 ExecConfiguration configuration = state.statementConfiguration; |
1127 for (Statement s in node.statements.reversed) { | 1135 for (Statement s in node.statements.reversed) { |
1128 configuration = | 1136 configuration = |
1129 new ExecConfiguration(s, blockState.withConfiguration(configuration)); | 1137 new ExecConfiguration(s, blockState.withConfiguration(configuration)); |
1130 } | 1138 } |
1131 return configuration; | 1139 return configuration; |
1132 } | 1140 } |
1133 | 1141 |
1134 Configuration visitEmptyStatement(EmptyStatement node, State state) { | 1142 Configuration visitEmptyStatement(EmptyStatement node, State state) { |
1135 return state.statementConfiguration; | 1143 return state.statementConfiguration; |
1136 } | 1144 } |
1137 | 1145 |
1138 Configuration visitIfStatement(IfStatement node, State state) { | 1146 Configuration visitIfStatement(IfStatement node, State state) { |
1139 var cont = new IfConditionContinuation(node.then, node.otherwise, state); | 1147 var cont = new IfConditionEK(node.then, node.otherwise, state); |
1140 | 1148 |
1141 return new EvalConfiguration(node.condition, state.environment, cont); | 1149 return new EvalConfiguration(node.condition, state.environment, cont); |
1142 } | 1150 } |
1143 | 1151 |
1144 Configuration visitLabeledStatement(LabeledStatement node, State state) { | 1152 Configuration visitLabeledStatement(LabeledStatement node, State state) { |
1145 return new ExecConfiguration(node.body, state.withBreak(node)); | 1153 return new ExecConfiguration(node.body, state.withBreak(node)); |
1146 } | 1154 } |
1147 | 1155 |
1148 Configuration visitBreakStatement(BreakStatement node, State state) { | 1156 Configuration visitBreakStatement(BreakStatement node, State state) { |
1149 return state.lookupLabel(node.target).configuration; | 1157 return state.lookupLabel(node.target).configuration; |
1150 } | 1158 } |
1151 | 1159 |
1152 Configuration visitWhileStatement(WhileStatement node, State state) { | 1160 Configuration visitWhileStatement(WhileStatement node, State state) { |
1153 var cont = new WhileConditionContinuation(node, state); | 1161 var cont = new WhileConditionEK(node, state); |
1154 | 1162 |
1155 return new EvalConfiguration(node.condition, state.environment, cont); | 1163 return new EvalConfiguration(node.condition, state.environment, cont); |
1156 } | 1164 } |
1157 | 1165 |
1158 Configuration visitDoStatement(DoStatement node, State state) { | 1166 Configuration visitDoStatement(DoStatement node, State state) { |
1159 WhileStatement whileStatement = | 1167 WhileStatement whileStatement = |
1160 new WhileStatement(node.condition, node.body); | 1168 new WhileStatement(node.condition, node.body); |
1161 ExecConfiguration configuration = | 1169 ExecConfiguration configuration = |
1162 new ExecConfiguration(whileStatement, state); | 1170 new ExecConfiguration(whileStatement, state); |
1163 | 1171 |
1164 return new ExecConfiguration( | 1172 return new ExecConfiguration( |
1165 node.body, state.withConfiguration(configuration)); | 1173 node.body, state.withConfiguration(configuration)); |
1166 } | 1174 } |
1167 | 1175 |
1168 Configuration visitReturnStatement(ReturnStatement node, State state) { | 1176 Configuration visitReturnStatement(ReturnStatement node, State state) { |
1169 assert(state.returnContinuation != null); | 1177 assert(state.returnContinuation != null); |
1170 log.info('return\n'); | 1178 log.info('return\n'); |
1171 if (node.expression == null) { | 1179 if (node.expression == null) { |
1172 return new ValuePassingConfiguration( | 1180 return new ValuePassingConfiguration( |
1173 state.returnContinuation, Value.nullInstance); | 1181 state.returnContinuation, Value.nullInstance); |
1174 } | 1182 } |
1175 | 1183 |
1176 return new EvalConfiguration( | 1184 return new EvalConfiguration( |
1177 node.expression, state.environment, state.returnContinuation); | 1185 node.expression, state.environment, state.returnContinuation); |
1178 } | 1186 } |
1179 | 1187 |
1180 Configuration visitVariableDeclaration( | 1188 Configuration visitVariableDeclaration( |
1181 VariableDeclaration node, State state) { | 1189 VariableDeclaration node, State state) { |
1182 if (node.initializer != null) { | 1190 if (node.initializer != null) { |
1183 var cont = new VariableInitializerContinuation( | 1191 var cont = new VariableInitializerEK( |
1184 node, state.environment, state.statementConfiguration); | 1192 node, state.environment, state.statementConfiguration); |
1185 return new EvalConfiguration(node.initializer, state.environment, cont); | 1193 return new EvalConfiguration(node.initializer, state.environment, cont); |
1186 } | 1194 } |
1187 state.environment.expand(node, Value.nullInstance); | 1195 state.environment.expand(node, Value.nullInstance); |
1188 return state.statementConfiguration; | 1196 return state.statementConfiguration; |
1189 } | 1197 } |
1190 } | 1198 } |
1191 | 1199 |
1192 // ------------------------------------------------------------------------ | 1200 // ------------------------------------------------------------------------ |
1193 // VALUES | 1201 // VALUES |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1476 void _initializeNullFields(Class class_, ObjectValue newObject) { | 1484 void _initializeNullFields(Class class_, ObjectValue newObject) { |
1477 int superClassSize = class_.superclass?.instanceSize ?? 0; | 1485 int superClassSize = class_.superclass?.instanceSize ?? 0; |
1478 for (int i = superClassSize; i < class_.instanceSize; i++) { | 1486 for (int i = superClassSize; i < class_.instanceSize; i++) { |
1479 Field field = class_.instanceFields[i]; | 1487 Field field = class_.instanceFields[i]; |
1480 if (class_.getProperty(newObject, field) == null) { | 1488 if (class_.getProperty(newObject, field) == null) { |
1481 assert(field.initializer == null); | 1489 assert(field.initializer == null); |
1482 class_.setProperty(newObject, field, Value.nullInstance); | 1490 class_.setProperty(newObject, field, Value.nullInstance); |
1483 } | 1491 } |
1484 } | 1492 } |
1485 } | 1493 } |
OLD | NEW |