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 13 matching lines...) Expand all Loading... |
24 Interpreter(this.program); | 24 Interpreter(this.program); |
25 | 25 |
26 void run() { | 26 void run() { |
27 assert(program.libraries.isEmpty); | 27 assert(program.libraries.isEmpty); |
28 Procedure mainMethod = program.mainMethod; | 28 Procedure mainMethod = program.mainMethod; |
29 | 29 |
30 if (mainMethod == null) return; | 30 if (mainMethod == null) return; |
31 | 31 |
32 Statement statementBlock = mainMethod.function.body; | 32 Statement statementBlock = mainMethod.function.body; |
33 ExecConfiguration configuration = new ExecConfiguration( | 33 ExecConfiguration configuration = new ExecConfiguration( |
34 statementBlock, new Environment.empty(), const State.initial()); | 34 statementBlock, new Environment.empty(), new State.initial()); |
35 visitor.trampolinedExecution(configuration); | 35 visitor.trampolinedExecution(configuration); |
36 } | 36 } |
37 } | 37 } |
38 | 38 |
39 class Location { | 39 class Location { |
40 Value value; | 40 Value value; |
41 | 41 |
42 Location.empty(); | 42 Location.empty(); |
43 Location(this.value); | 43 Location(this.value); |
44 } | 44 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 return extend(new VariableDeclaration('this'), v); | 113 return extend(new VariableDeclaration('this'), v); |
114 } | 114 } |
115 } | 115 } |
116 | 116 |
117 /// Evaluate expressions. | 117 /// Evaluate expressions. |
118 class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { | 118 class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { |
119 Configuration eval(Expression expr, EvalConfiguration config) => | 119 Configuration eval(Expression expr, EvalConfiguration config) => |
120 expr.accept1(this, config); | 120 expr.accept1(this, config); |
121 | 121 |
122 Configuration evalList(List<InterpreterExpression> list, Environment env, | 122 Configuration evalList(List<InterpreterExpression> list, Environment env, |
123 ApplicationContinuation cont) { | 123 ExceptionComponents exceptionComponents, ApplicationContinuation cont) { |
124 if (list.isNotEmpty) { | 124 if (list.isNotEmpty) { |
125 return new EvalConfiguration(list.first.expression, env, | 125 return new EvalConfiguration( |
126 new ExpressionListEK(list.first, list.skip(1), env, cont)); | 126 list.first.expression, |
| 127 env, |
| 128 exceptionComponents, |
| 129 new ExpressionListEK( |
| 130 list.first, list.skip(1), env, exceptionComponents, cont)); |
127 } | 131 } |
128 return new ApplicationConfiguration(cont, <InterpreterValue>[]); | 132 return new ApplicationConfiguration(cont, <InterpreterValue>[]); |
129 } | 133 } |
130 | 134 |
131 Configuration defaultExpression(Expression node, EvalConfiguration config) { | 135 Configuration defaultExpression(Expression node, EvalConfiguration config) { |
132 throw new NotImplemented('Evaluation for expressions of type ' | 136 throw new NotImplemented('Evaluation for expressions of type ' |
133 '${node.runtimeType} is not implemented.'); | 137 '${node.runtimeType} is not implemented.'); |
134 } | 138 } |
135 | 139 |
136 Configuration visitInvalidExpression1( | 140 Configuration visitInvalidExpression1( |
137 InvalidExpression node, EvalConfiguration config) { | 141 InvalidExpression node, EvalConfiguration config) { |
138 throw 'Invalid expression at ${node.location.toString()}'; | 142 throw 'Invalid expression at ${node.location.toString()}'; |
139 } | 143 } |
140 | 144 |
141 Configuration visitVariableGet(VariableGet node, EvalConfiguration config) { | 145 Configuration visitVariableGet(VariableGet node, EvalConfiguration config) { |
142 Value value = config.environment.lookup(node.variable); | 146 Value value = config.environment.lookup(node.variable); |
143 return new ValuePassingConfiguration(config.continuation, value); | 147 return new ValuePassingConfiguration(config.continuation, value); |
144 } | 148 } |
145 | 149 |
146 Configuration visitVariableSet(VariableSet node, EvalConfiguration config) { | 150 Configuration visitVariableSet(VariableSet node, EvalConfiguration config) { |
147 var cont = new VariableSetEK( | 151 var cont = new VariableSetEK( |
148 node.variable, config.environment, config.continuation); | 152 node.variable, config.environment, config.continuation); |
149 return new EvalConfiguration(node.value, config.environment, cont); | 153 return new EvalConfiguration( |
| 154 node.value, config.environment, config.exceptionComponents, cont); |
150 } | 155 } |
151 | 156 |
152 Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) { | 157 Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) { |
153 var cont = new PropertyGetEK(node.name, config.continuation); | 158 var cont = new PropertyGetEK(node.name, config.continuation); |
154 return new EvalConfiguration(node.receiver, config.environment, cont); | 159 return new EvalConfiguration( |
| 160 node.receiver, config.environment, config.exceptionComponents, cont); |
155 } | 161 } |
156 | 162 |
157 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { | 163 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { |
158 var cont = new PropertySetEK( | 164 var cont = new PropertySetEK(node.value, node.name, config.environment, |
159 node.value, node.name, config.environment, config.continuation); | 165 config.exceptionComponents, config.continuation); |
160 return new EvalConfiguration(node.receiver, config.environment, cont); | 166 return new EvalConfiguration( |
| 167 node.receiver, config.environment, config.exceptionComponents, cont); |
161 } | 168 } |
162 | 169 |
163 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) => | 170 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) => |
164 defaultExpression(node, config); | 171 defaultExpression(node, config); |
165 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) => | 172 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) => |
166 defaultExpression(node, config); | 173 defaultExpression(node, config); |
167 | 174 |
168 Configuration visitStaticInvocation( | 175 Configuration visitStaticInvocation( |
169 StaticInvocation node, EvalConfiguration config) { | 176 StaticInvocation node, EvalConfiguration config) { |
170 if ('print' == node.name.toString()) { | 177 if ('print' == node.name.toString()) { |
171 var cont = new PrintEK(config.continuation); | 178 var cont = new PrintEK(config.continuation); |
172 return new EvalConfiguration( | 179 return new EvalConfiguration(node.arguments.positional.first, |
173 node.arguments.positional.first, config.environment, cont); | 180 config.environment, config.exceptionComponents, cont); |
174 } else { | 181 } else { |
175 log.info('static-invocation-${node.target.name.toString()}\n'); | 182 log.info('static-invocation-${node.target.name.toString()}\n'); |
176 | 183 |
177 List<InterpreterExpression> args = | 184 List<InterpreterExpression> args = |
178 _getArgumentExpressions(node.arguments, node.target.function); | 185 _getArgumentExpressions(node.arguments, node.target.function); |
179 ApplicationContinuation cont = | 186 ApplicationContinuation cont = new StaticInvocationA(node.target.function, |
180 new StaticInvocationA(node.target.function, config.continuation); | 187 config.exceptionComponents, config.continuation); |
181 return new EvalListConfiguration(args, config.environment, cont); | 188 return new EvalListConfiguration( |
| 189 args, config.environment, config.exceptionComponents, cont); |
182 } | 190 } |
183 } | 191 } |
184 | 192 |
185 Configuration visitMethodInvocation( | 193 Configuration visitMethodInvocation( |
186 MethodInvocation node, EvalConfiguration config) { | 194 MethodInvocation node, EvalConfiguration config) { |
187 // Currently supports only method invocation with <2 arguments and is used | 195 // Currently supports only method invocation with <2 arguments and is used |
188 // to evaluate implemented operators for int, double and String values. | 196 // to evaluate implemented operators for int, double and String values. |
189 var cont = new MethodInvocationEK( | 197 var cont = new MethodInvocationEK(node.arguments, node.name, |
190 node.arguments, node.name, config.environment, config.continuation); | 198 config.environment, config.exceptionComponents, config.continuation); |
191 | 199 |
192 return new EvalConfiguration(node.receiver, config.environment, cont); | 200 return new EvalConfiguration( |
| 201 node.receiver, config.environment, config.exceptionComponents, cont); |
193 } | 202 } |
194 | 203 |
195 Configuration visitConstructorInvocation( | 204 Configuration visitConstructorInvocation( |
196 ConstructorInvocation node, EvalConfiguration config) { | 205 ConstructorInvocation node, EvalConfiguration config) { |
197 ApplicationContinuation cont = | 206 ApplicationContinuation cont = new ConstructorInvocationA( |
198 new ConstructorInvocationA(node.target, config.continuation); | 207 node.target, config.exceptionComponents, config.continuation); |
199 var args = _getArgumentExpressions(node.arguments, node.target.function); | 208 var args = _getArgumentExpressions(node.arguments, node.target.function); |
200 | 209 |
201 return new EvalListConfiguration(args, config.environment, cont); | 210 return new EvalListConfiguration( |
| 211 args, config.environment, config.exceptionComponents, cont); |
202 } | 212 } |
203 | 213 |
204 Configuration visitNot(Not node, EvalConfiguration config) { | 214 Configuration visitNot(Not node, EvalConfiguration config) { |
205 return new EvalConfiguration( | 215 return new EvalConfiguration(node.operand, config.environment, |
206 node.operand, config.environment, new NotEK(config.continuation)); | 216 config.exceptionComponents, new NotEK(config.continuation)); |
207 } | 217 } |
208 | 218 |
209 Configuration visitLogicalExpression( | 219 Configuration visitLogicalExpression( |
210 LogicalExpression node, EvalConfiguration config) { | 220 LogicalExpression node, EvalConfiguration config) { |
211 if ('||' == node.operator) { | 221 if ('||' == node.operator) { |
212 var cont = new OrEK(node.right, config.environment, config.continuation); | 222 var cont = new OrEK(node.right, config.environment, |
213 return new EvalConfiguration(node.left, config.environment, cont); | 223 config.exceptionComponents, config.continuation); |
| 224 return new EvalConfiguration( |
| 225 node.left, config.environment, config.exceptionComponents, cont); |
214 } else { | 226 } else { |
215 assert('&&' == node.operator); | 227 assert('&&' == node.operator); |
216 var cont = new AndEK(node.right, config.environment, config.continuation); | 228 var cont = new AndEK(node.right, config.environment, |
217 return new EvalConfiguration(node.left, config.environment, cont); | 229 config.exceptionComponents, config.continuation); |
| 230 return new EvalConfiguration( |
| 231 node.left, config.environment, config.exceptionComponents, cont); |
218 } | 232 } |
219 } | 233 } |
220 | 234 |
221 Configuration visitConditionalExpression( | 235 Configuration visitConditionalExpression( |
222 ConditionalExpression node, EvalConfiguration config) { | 236 ConditionalExpression node, EvalConfiguration config) { |
223 var cont = new ConditionalEK( | 237 var cont = new ConditionalEK(node.then, node.otherwise, config.environment, |
224 node.then, node.otherwise, config.environment, config.continuation); | 238 config.exceptionComponents, config.continuation); |
225 return new EvalConfiguration(node.condition, config.environment, cont); | 239 return new EvalConfiguration( |
| 240 node.condition, config.environment, config.exceptionComponents, cont); |
226 } | 241 } |
227 | 242 |
228 Configuration visitStringConcatenation( | 243 Configuration visitStringConcatenation( |
229 StringConcatenation node, EvalConfiguration config) { | 244 StringConcatenation node, EvalConfiguration config) { |
230 var cont = new StringConcatenationA(config.continuation); | 245 var cont = new StringConcatenationA(config.continuation); |
231 var expressions = node.expressions | 246 var expressions = node.expressions |
232 .map((Expression e) => new PositionalExpression(e)) | 247 .map((Expression e) => new PositionalExpression(e)) |
233 .toList(); | 248 .toList(); |
234 return new EvalListConfiguration(expressions, config.environment, cont); | 249 return new EvalListConfiguration( |
| 250 expressions, config.environment, config.exceptionComponents, cont); |
235 } | 251 } |
236 | 252 |
237 Configuration visitThisExpression( | 253 Configuration visitThisExpression( |
238 ThisExpression node, EvalConfiguration config) { | 254 ThisExpression node, EvalConfiguration config) { |
239 return new ValuePassingConfiguration( | 255 return new ValuePassingConfiguration( |
240 config.continuation, config.environment.thisInstance); | 256 config.continuation, config.environment.thisInstance); |
241 } | 257 } |
242 | 258 |
243 // Evaluation of BasicLiterals. | 259 // Evaluation of BasicLiterals. |
244 Configuration visitStringLiteral( | 260 Configuration visitStringLiteral( |
(...skipping 17 matching lines...) Expand all Loading... |
262 Value value = node.value ? Value.trueInstance : Value.falseInstance; | 278 Value value = node.value ? Value.trueInstance : Value.falseInstance; |
263 return new ValuePassingConfiguration(config.continuation, value); | 279 return new ValuePassingConfiguration(config.continuation, value); |
264 } | 280 } |
265 | 281 |
266 Configuration visitNullLiteral(NullLiteral node, EvalConfiguration config) { | 282 Configuration visitNullLiteral(NullLiteral node, EvalConfiguration config) { |
267 return new ValuePassingConfiguration( | 283 return new ValuePassingConfiguration( |
268 config.continuation, Value.nullInstance); | 284 config.continuation, Value.nullInstance); |
269 } | 285 } |
270 | 286 |
271 Configuration visitLet(Let node, EvalConfiguration config) { | 287 Configuration visitLet(Let node, EvalConfiguration config) { |
272 var letCont = new LetEK( | 288 var letCont = new LetEK(node.variable, node.body, config.environment, |
273 node.variable, node.body, config.environment, config.continuation); | 289 config.exceptionComponents, config.continuation); |
274 return new EvalConfiguration( | 290 return new EvalConfiguration(node.variable.initializer, config.environment, |
275 node.variable.initializer, config.environment, letCont); | 291 config.exceptionComponents, letCont); |
276 } | 292 } |
277 } | 293 } |
278 | 294 |
279 /// Represents a state for statement execution. | 295 /// Represents a state for statement execution. |
280 class State { | 296 class State { |
281 final Label labels; | 297 final Label labels; |
282 // TODO: Add switch labels. | 298 // TODO: Add switch labels. |
283 // TODO: Add component for exception support. | 299 final ExceptionComponents exceptionComponents; |
284 final ExpressionContinuation returnContinuation; | 300 final ExpressionContinuation returnContinuation; |
285 final StatementContinuation continuation; | 301 final StatementContinuation continuation; |
286 | 302 |
287 State(this.labels, this.returnContinuation, this.continuation); | 303 State(this.labels, this.exceptionComponents, this.returnContinuation, |
| 304 this.continuation); |
288 | 305 |
289 const State.initial() | 306 State.initial() |
290 : labels = null, | 307 : labels = null, |
| 308 exceptionComponents = new ExceptionComponents.initial(), |
291 returnContinuation = null, | 309 returnContinuation = null, |
292 continuation = null; | 310 continuation = null; |
293 | 311 |
294 State withBreak(Statement stmt, Environment env) { | 312 State withBreak(Statement stmt, Environment env) { |
295 Label breakLabels = new Label(stmt, env, continuation, labels); | 313 Label breakLabels = new Label(stmt, env, continuation, labels); |
296 return new State(breakLabels, returnContinuation, continuation); | 314 return new State( |
| 315 breakLabels, exceptionComponents, returnContinuation, continuation); |
297 } | 316 } |
298 | 317 |
299 State withReturnContinuation(ExpressionContinuation returnCont) { | 318 State withReturnContinuation(ExpressionContinuation returnCont) { |
300 return new State(labels, returnCont, continuation); | 319 return new State(labels, exceptionComponents, returnCont, continuation); |
301 } | 320 } |
302 | 321 |
303 State withContinuation(StatementContinuation cont) { | 322 State withContinuation(StatementContinuation cont) { |
304 return new State(labels, returnContinuation, cont); | 323 return new State(labels, exceptionComponents, returnContinuation, cont); |
| 324 } |
| 325 |
| 326 State withException(ExceptionComponents state) { |
| 327 return new State(labels, state, returnContinuation, continuation); |
305 } | 328 } |
306 | 329 |
307 Label lookupLabel(LabeledStatement s) { | 330 Label lookupLabel(LabeledStatement s) { |
308 assert(labels != null); | 331 assert(labels != null); |
309 return labels.lookupLabel(s); | 332 return labels.lookupLabel(s); |
310 } | 333 } |
311 } | 334 } |
312 | 335 |
313 /// Represents a labeled statement, the corresponding continuation and the | 336 /// Represents a labeled statement, the corresponding continuation and the |
314 /// enclosing label. | 337 /// enclosing label. |
(...skipping 22 matching lines...) Expand all Loading... |
337 Configuration step(StatementExecuter executer); | 360 Configuration step(StatementExecuter executer); |
338 } | 361 } |
339 | 362 |
340 /// Configuration for evaluating an [Expression]. | 363 /// Configuration for evaluating an [Expression]. |
341 class EvalConfiguration extends Configuration { | 364 class EvalConfiguration extends Configuration { |
342 final Expression expression; | 365 final Expression expression; |
343 | 366 |
344 /// Environment in which the expression is evaluated. | 367 /// Environment in which the expression is evaluated. |
345 final Environment environment; | 368 final Environment environment; |
346 | 369 |
| 370 /// Exception components. |
| 371 final ExceptionComponents exceptionComponents; |
| 372 |
347 /// Next continuation to be applied. | 373 /// Next continuation to be applied. |
348 final Continuation continuation; | 374 final Continuation continuation; |
349 | 375 |
350 EvalConfiguration(this.expression, this.environment, this.continuation); | 376 EvalConfiguration(this.expression, this.environment, this.exceptionComponents, |
| 377 this.continuation); |
351 | 378 |
352 Configuration step(StatementExecuter executer) => | 379 Configuration step(StatementExecuter executer) => |
353 executer.eval(expression, this); | 380 executer.eval(expression, this); |
354 } | 381 } |
355 | 382 |
356 /// Configuration for evaluating a `List<InterpreterExpression>`. | 383 /// Configuration for evaluating a `List<InterpreterExpression>`. |
357 class EvalListConfiguration extends Configuration { | 384 class EvalListConfiguration extends Configuration { |
358 final List<InterpreterExpression> expressions; | 385 final List<InterpreterExpression> expressions; |
359 final Environment environment; | 386 final Environment environment; |
| 387 final ExceptionComponents exceptionComponents; |
360 final ApplicationContinuation continuation; | 388 final ApplicationContinuation continuation; |
361 | 389 |
362 EvalListConfiguration(this.expressions, this.environment, this.continuation); | 390 EvalListConfiguration(this.expressions, this.environment, |
| 391 this.exceptionComponents, this.continuation); |
363 | 392 |
364 Configuration step(StatementExecuter executer) => | 393 Configuration step(StatementExecuter executer) => executer.evalList( |
365 executer.evalList(expressions, environment, continuation); | 394 expressions, environment, exceptionComponents, continuation); |
366 } | 395 } |
367 | 396 |
368 /// Configuration for execution of a [Statement]. | 397 /// Configuration for execution of a [Statement]. |
369 class ExecConfiguration extends Configuration { | 398 class ExecConfiguration extends Configuration { |
370 final Statement currentStatement; | 399 final Statement currentStatement; |
371 final Environment environment; | 400 final Environment environment; |
372 final State state; | 401 final State state; |
373 | 402 |
374 ExecConfiguration(this.currentStatement, this.environment, this.state); | 403 ExecConfiguration(this.currentStatement, this.environment, this.state); |
375 | 404 |
(...skipping 25 matching lines...) Expand all Loading... |
401 /// `List<InterpreterValue>`. | 430 /// `List<InterpreterValue>`. |
402 class ApplicationConfiguration extends Configuration { | 431 class ApplicationConfiguration extends Configuration { |
403 final ApplicationContinuation continuation; | 432 final ApplicationContinuation continuation; |
404 final List<InterpreterValue> values; | 433 final List<InterpreterValue> values; |
405 | 434 |
406 ApplicationConfiguration(this.continuation, this.values); | 435 ApplicationConfiguration(this.continuation, this.values); |
407 | 436 |
408 Configuration step(StatementExecuter _) => continuation(values); | 437 Configuration step(StatementExecuter _) => continuation(values); |
409 } | 438 } |
410 | 439 |
| 440 class ThrowConfiguration extends Configuration { |
| 441 final ExceptionHandler handler; |
| 442 final Value exception; |
| 443 final StackTrace stacktrace; |
| 444 |
| 445 ThrowConfiguration(this.handler, this.exception, this.stacktrace); |
| 446 |
| 447 Configuration step(StatementExecuter _) => handler(exception, stacktrace); |
| 448 } |
| 449 |
411 // ------------------------------------------------------------------------ | 450 // ------------------------------------------------------------------------ |
412 // Interpreter Expressions and Values | 451 // Interpreter Expressions and Values |
413 // ------------------------------------------------------------------------ | 452 // ------------------------------------------------------------------------ |
414 | 453 |
415 abstract class InterpreterExpression { | 454 abstract class InterpreterExpression { |
416 Expression get expression; | 455 Expression get expression; |
417 | 456 |
418 InterpreterValue assignValue(Value v); | 457 InterpreterValue assignValue(Value v); |
419 } | 458 } |
420 | 459 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 final Expression condition; | 561 final Expression condition; |
523 final Statement body; | 562 final Statement body; |
524 final Environment enclosingEnv; | 563 final Environment enclosingEnv; |
525 final State state; | 564 final State state; |
526 | 565 |
527 WhileConditionSK(this.condition, this.body, this.enclosingEnv, this.state); | 566 WhileConditionSK(this.condition, this.body, this.enclosingEnv, this.state); |
528 | 567 |
529 Configuration call(Environment _) { | 568 Configuration call(Environment _) { |
530 // Evaluate the condition for the while loop execution. | 569 // Evaluate the condition for the while loop execution. |
531 var cont = new WhileConditionEK(condition, body, enclosingEnv, state); | 570 var cont = new WhileConditionEK(condition, body, enclosingEnv, state); |
532 return new EvalConfiguration(condition, enclosingEnv, cont); | 571 return new EvalConfiguration( |
| 572 condition, enclosingEnv, state.exceptionComponents, cont); |
533 } | 573 } |
534 } | 574 } |
535 | 575 |
536 /// Applies the expression continuation to the provided value. | 576 /// Applies the expression continuation to the provided value. |
537 class NewSK extends StatementContinuation { | 577 class NewSK extends StatementContinuation { |
538 final ExpressionContinuation continuation; | 578 final ExpressionContinuation continuation; |
539 final Location location; | 579 final Location location; |
540 | 580 |
541 NewSK(this.continuation, this.location); | 581 NewSK(this.continuation, this.location); |
542 | 582 |
543 Configuration call(Environment _) => | 583 Configuration call(Environment _) => |
544 new ValuePassingConfiguration(continuation, location.value); | 584 new ValuePassingConfiguration(continuation, location.value); |
545 } | 585 } |
546 | 586 |
547 class ConstructorBodySK extends StatementContinuation { | 587 class ConstructorBodySK extends StatementContinuation { |
548 final Statement body; | 588 final Statement body; |
549 final Environment environment; | 589 final Environment environment; |
550 // TODO(zhivkag): Add component for exception handler. | 590 final ExceptionComponents exceptionComponents; |
551 final StatementContinuation continuation; | 591 final StatementContinuation continuation; |
552 | 592 |
553 ConstructorBodySK(this.body, this.environment, this.continuation); | 593 ConstructorBodySK( |
| 594 this.body, this.environment, this.exceptionComponents, this.continuation); |
554 | 595 |
555 Configuration call(Environment _) { | 596 Configuration call(Environment _) { |
556 return new ExecConfiguration( | 597 return new ExecConfiguration(body, environment, |
557 body, environment, new State(null, null, continuation)); | 598 new State(null, exceptionComponents, null, continuation)); |
558 } | 599 } |
559 } | 600 } |
560 | 601 |
561 // ------------------------------------------------------------------------ | 602 // ------------------------------------------------------------------------ |
562 // Application Continuations | 603 // Application Continuations |
563 // ------------------------------------------------------------------------ | 604 // ------------------------------------------------------------------------ |
564 | 605 |
565 /// Represents the continuation called after the evaluation of argument | 606 /// Represents the continuation called after the evaluation of argument |
566 /// expressions. | 607 /// expressions. |
567 /// | 608 /// |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 result.write(v.value.value); | 668 result.write(v.value.value); |
628 } | 669 } |
629 return new ValuePassingConfiguration( | 670 return new ValuePassingConfiguration( |
630 continuation, new StringValue(result.toString())); | 671 continuation, new StringValue(result.toString())); |
631 } | 672 } |
632 } | 673 } |
633 | 674 |
634 /// Represents the application continuation for static invocation. | 675 /// Represents the application continuation for static invocation. |
635 class StaticInvocationA extends ApplicationContinuation { | 676 class StaticInvocationA extends ApplicationContinuation { |
636 final FunctionNode function; | 677 final FunctionNode function; |
| 678 final ExceptionComponents exceptionComponents; |
637 final ExpressionContinuation continuation; | 679 final ExpressionContinuation continuation; |
638 | 680 |
639 StaticInvocationA(this.function, this.continuation); | 681 StaticInvocationA(this.function, this.exceptionComponents, this.continuation); |
640 | 682 |
641 Configuration call(List<InterpreterValue> argValues) { | 683 Configuration call(List<InterpreterValue> argValues) { |
642 Environment functionEnv = | 684 Environment functionEnv = |
643 ApplicationContinuation.createEnvironment(function, argValues); | 685 ApplicationContinuation.createEnvironment(function, argValues); |
644 State bodyState = new State( | 686 State bodyState = new State(null, exceptionComponents, continuation, |
645 null, continuation, new ExitSK(continuation, Value.nullInstance)); | 687 new ExitSK(continuation, Value.nullInstance)); |
646 | 688 |
647 return new ExecConfiguration(function.body, functionEnv, bodyState); | 689 return new ExecConfiguration(function.body, functionEnv, bodyState); |
648 } | 690 } |
649 } | 691 } |
650 | 692 |
651 /// Represents the application continuation for constructor invocation applied | 693 /// Represents the application continuation for constructor invocation applied |
652 /// on the list of evaluated arguments when a constructor is invoked with new. | 694 /// on the list of evaluated arguments when a constructor is invoked with new. |
653 /// | 695 /// |
654 /// It creates the newly allocated object instance. | 696 /// It creates the newly allocated object instance. |
655 class ConstructorInvocationA extends ApplicationContinuation { | 697 class ConstructorInvocationA extends ApplicationContinuation { |
656 final Constructor constructor; | 698 final Constructor constructor; |
| 699 final ExceptionComponents exceptionComponents; |
657 final ExpressionContinuation continuation; | 700 final ExpressionContinuation continuation; |
658 | 701 |
659 ConstructorInvocationA(this.constructor, this.continuation); | 702 ConstructorInvocationA( |
| 703 this.constructor, this.exceptionComponents, this.continuation); |
660 | 704 |
661 Configuration call(List<InterpreterValue> argValues) { | 705 Configuration call(List<InterpreterValue> argValues) { |
662 Environment ctrEnv = ApplicationContinuation.createEnvironment( | 706 Environment ctrEnv = ApplicationContinuation.createEnvironment( |
663 constructor.function, argValues); | 707 constructor.function, argValues); |
664 var class_ = new Class(constructor.enclosingClass.reference); | 708 var class_ = new Class(constructor.enclosingClass.reference); |
665 var newObject = new ObjectValue(class_); | 709 var newObject = new ObjectValue(class_); |
666 var cont = new InitializationEK( | 710 var cont = new InitializationEK(constructor, ctrEnv, exceptionComponents, |
667 constructor, ctrEnv, new NewSK(continuation, new Location(newObject))); | 711 new NewSK(continuation, new Location(newObject))); |
668 | 712 |
669 return new ValuePassingConfiguration(cont, newObject); | 713 return new ValuePassingConfiguration(cont, newObject); |
670 } | 714 } |
671 } | 715 } |
672 | 716 |
673 /// Represents the application continuation for constructor invocation applied | 717 /// Represents the application continuation for constructor invocation applied |
674 /// on the list of evaluated arguments when a constructor is invoked in a | 718 /// on the list of evaluated arguments when a constructor is invoked in a |
675 /// constructor initializer list with a [RedirectingInitializer] or | 719 /// constructor initializer list with a [RedirectingInitializer] or |
676 /// [SuperInitializer]. | 720 /// [SuperInitializer]. |
677 class ConstructorInitializerA extends ApplicationContinuation { | 721 class ConstructorInitializerA extends ApplicationContinuation { |
678 final Constructor constructor; | 722 final Constructor constructor; |
679 final Location location; | 723 final Location location; |
| 724 final ExceptionComponents exceptionComponents; |
680 final ConstructorBodySK continuation; | 725 final ConstructorBodySK continuation; |
681 | 726 |
682 ConstructorInitializerA(this.constructor, this.location, this.continuation); | 727 ConstructorInitializerA(this.constructor, this.location, |
| 728 this.exceptionComponents, this.continuation); |
683 | 729 |
684 Configuration call(List<InterpreterValue> vs) { | 730 Configuration call(List<InterpreterValue> vs) { |
685 Environment ctrEnv = | 731 Environment ctrEnv = |
686 ApplicationContinuation.createEnvironment(constructor.function, vs); | 732 ApplicationContinuation.createEnvironment(constructor.function, vs); |
687 var cont = new InitializationEK(constructor, ctrEnv, continuation); | 733 var cont = new InitializationEK( |
| 734 constructor, ctrEnv, exceptionComponents, continuation); |
688 | 735 |
689 return new ValuePassingConfiguration(cont, location.value); | 736 return new ValuePassingConfiguration(cont, location.value); |
690 } | 737 } |
691 } | 738 } |
692 | 739 |
693 /// Represents the application continuation applied on the list of evaluated | 740 /// Represents the application continuation applied on the list of evaluated |
694 /// field initializer expressions. | 741 /// field initializer expressions. |
695 class InstanceFieldsA extends ApplicationContinuation { | 742 class InstanceFieldsA extends ApplicationContinuation { |
696 final Constructor constructor; | 743 final Constructor constructor; |
697 final Location location; | 744 final Location location; |
698 final Environment environment; | 745 final Environment environment; |
| 746 final ExceptionComponents exceptionComponents; |
699 final ConstructorBodySK continuation; | 747 final ConstructorBodySK continuation; |
700 | 748 |
701 final Class _currentClass; | 749 final Class _currentClass; |
702 | 750 |
703 InstanceFieldsA( | 751 InstanceFieldsA(this.constructor, this.location, this.environment, |
704 this.constructor, this.location, this.environment, this.continuation) | 752 this.exceptionComponents, this.continuation) |
705 : _currentClass = new Class(constructor.enclosingClass.reference); | 753 : _currentClass = new Class(constructor.enclosingClass.reference); |
706 | 754 |
707 Configuration call(List<InterpreterValue> fieldValues) { | 755 Configuration call(List<InterpreterValue> fieldValues) { |
708 for (FieldInitializerValue f in fieldValues) { | 756 for (FieldInitializerValue f in fieldValues) { |
709 // Directly set the field with the corresponding implicit setter. | 757 // Directly set the field with the corresponding implicit setter. |
710 _currentClass.implicitSetters[f.field.name](location.value, f.value); | 758 _currentClass.implicitSetters[f.field.name](location.value, f.value); |
711 } | 759 } |
712 | 760 |
713 if (constructor.initializers.length == 0) { | 761 if (constructor.initializers.length == 0) { |
714 // This can happen when initializing fields of a constructor with an empty | 762 // This can happen when initializing fields of a constructor with an empty |
(...skipping 14 matching lines...) Expand all Loading... |
729 } | 777 } |
730 | 778 |
731 // Otherwise, the next expression from Field or Local initializers will be | 779 // Otherwise, the next expression from Field or Local initializers will be |
732 // evaluated. | 780 // evaluated. |
733 return _createEvalConfig(constructor.initializers.first); | 781 return _createEvalConfig(constructor.initializers.first); |
734 } | 782 } |
735 | 783 |
736 Configuration _createEvalListConfig(SuperInitializer initializer) { | 784 Configuration _createEvalListConfig(SuperInitializer initializer) { |
737 List<InterpreterExpression> args = _getArgumentExpressions( | 785 List<InterpreterExpression> args = _getArgumentExpressions( |
738 initializer.arguments, initializer.target.function); | 786 initializer.arguments, initializer.target.function); |
739 var cont = | 787 var cont = new ConstructorInitializerA( |
740 new ConstructorInitializerA(initializer.target, location, continuation); | 788 initializer.target, location, exceptionComponents, continuation); |
741 | 789 |
742 return new EvalListConfiguration(args, environment, cont); | 790 return new EvalListConfiguration( |
| 791 args, environment, exceptionComponents, cont); |
743 } | 792 } |
744 | 793 |
745 EvalConfiguration _createEvalConfig(Initializer initializer) { | 794 EvalConfiguration _createEvalConfig(Initializer initializer) { |
746 Expression expr = (initializer is FieldInitializer) | 795 Expression expr = (initializer is FieldInitializer) |
747 ? initializer.value | 796 ? initializer.value |
748 : (initializer as LocalInitializer).variable.initializer; | 797 : (initializer as LocalInitializer).variable.initializer; |
749 | 798 |
750 // We start with index = 0 since we are evaluating the expression for the | 799 // We start with index = 0 since we are evaluating the expression for the |
751 // first initializer in the initializer list. | 800 // first initializer in the initializer list. |
752 var cont = new InitializerListEK( | 801 var cont = new InitializerListEK(constructor, 0, location, environment, |
753 constructor, 0, location, environment, continuation); | 802 exceptionComponents, continuation); |
754 return new EvalConfiguration(expr, environment, cont); | 803 return new EvalConfiguration(expr, environment, exceptionComponents, cont); |
755 } | 804 } |
756 } | 805 } |
757 // ------------------------------------------------------------------------ | 806 // ------------------------------------------------------------------------ |
758 // Expression Continuations | 807 // Expression Continuations |
759 // ------------------------------------------------------------------------ | 808 // ------------------------------------------------------------------------ |
760 | 809 |
761 /// Represents an expression continuation. | 810 /// Represents an expression continuation. |
762 /// | 811 /// |
763 /// There are various kinds of [ExpressionContinuation]s and their names are | 812 /// There are various kinds of [ExpressionContinuation]s and their names are |
764 /// suffixed with "EK". | 813 /// suffixed with "EK". |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 Configuration call(Value receiver) { | 849 Configuration call(Value receiver) { |
801 Value propertyValue = receiver.class_.lookupImplicitGetter(name)(receiver); | 850 Value propertyValue = receiver.class_.lookupImplicitGetter(name)(receiver); |
802 return new ValuePassingConfiguration(continuation, propertyValue); | 851 return new ValuePassingConfiguration(continuation, propertyValue); |
803 } | 852 } |
804 } | 853 } |
805 | 854 |
806 class PropertySetEK extends ExpressionContinuation { | 855 class PropertySetEK extends ExpressionContinuation { |
807 final Expression value; | 856 final Expression value; |
808 final Name setterName; | 857 final Name setterName; |
809 final Environment environment; | 858 final Environment environment; |
| 859 final ExceptionComponents exceptionComponents; |
810 final ExpressionContinuation continuation; | 860 final ExpressionContinuation continuation; |
811 | 861 |
812 PropertySetEK( | 862 PropertySetEK(this.value, this.setterName, this.environment, |
813 this.value, this.setterName, this.environment, this.continuation); | 863 this.exceptionComponents, this.continuation); |
814 | 864 |
815 Configuration call(Value receiver) { | 865 Configuration call(Value receiver) { |
816 var cont = new SetterEK(receiver, setterName, continuation); | 866 var cont = new SetterEK(receiver, setterName, continuation); |
817 return new EvalConfiguration(value, environment, cont); | 867 return new EvalConfiguration(value, environment, exceptionComponents, cont); |
818 } | 868 } |
819 } | 869 } |
820 | 870 |
821 class SetterEK extends ExpressionContinuation { | 871 class SetterEK extends ExpressionContinuation { |
822 final Value receiver; | 872 final Value receiver; |
823 final Name name; | 873 final Name name; |
824 final ExpressionContinuation continuation; | 874 final ExpressionContinuation continuation; |
825 | 875 |
826 SetterEK(this.receiver, this.name, this.continuation); | 876 SetterEK(this.receiver, this.name, this.continuation); |
827 | 877 |
828 Configuration call(Value v) { | 878 Configuration call(Value v) { |
829 Setter setter = receiver.class_.lookupImplicitSetter(name); | 879 Setter setter = receiver.class_.lookupImplicitSetter(name); |
830 setter(receiver, v); | 880 setter(receiver, v); |
831 return new ValuePassingConfiguration(continuation, v); | 881 return new ValuePassingConfiguration(continuation, v); |
832 } | 882 } |
833 } | 883 } |
834 | 884 |
835 /// Represents a continuation to be called after the evaluation of an actual | 885 /// Represents a continuation to be called after the evaluation of an actual |
836 /// argument for function invocation. | 886 /// argument for function invocation. |
837 class ExpressionListEK extends ExpressionContinuation { | 887 class ExpressionListEK extends ExpressionContinuation { |
838 final InterpreterExpression currentExpression; | 888 final InterpreterExpression currentExpression; |
839 final List<InterpreterExpression> expressions; | 889 final List<InterpreterExpression> expressions; |
840 final Environment environment; | 890 final Environment environment; |
| 891 final ExceptionComponents exceptionComponents; |
841 final ApplicationContinuation applicationContinuation; | 892 final ApplicationContinuation applicationContinuation; |
842 | 893 |
843 ExpressionListEK(this.currentExpression, this.expressions, this.environment, | 894 ExpressionListEK(this.currentExpression, this.expressions, this.environment, |
844 this.applicationContinuation); | 895 this.exceptionComponents, this.applicationContinuation); |
845 | 896 |
846 Configuration call(Value v) { | 897 Configuration call(Value v) { |
847 ValueA app = | 898 ValueA app = |
848 new ValueA(currentExpression.assignValue(v), applicationContinuation); | 899 new ValueA(currentExpression.assignValue(v), applicationContinuation); |
849 return new EvalListConfiguration(expressions, environment, app); | 900 return new EvalListConfiguration( |
| 901 expressions, environment, exceptionComponents, app); |
850 } | 902 } |
851 } | 903 } |
852 | 904 |
853 class MethodInvocationEK extends ExpressionContinuation { | 905 class MethodInvocationEK extends ExpressionContinuation { |
854 final Arguments arguments; | 906 final Arguments arguments; |
855 final Name methodName; | 907 final Name methodName; |
856 final Environment environment; | 908 final Environment environment; |
| 909 final ExceptionComponents exceptionComponents; |
857 final ExpressionContinuation continuation; | 910 final ExpressionContinuation continuation; |
858 | 911 |
859 MethodInvocationEK( | 912 MethodInvocationEK(this.arguments, this.methodName, this.environment, |
860 this.arguments, this.methodName, this.environment, this.continuation); | 913 this.exceptionComponents, this.continuation); |
861 | 914 |
862 Configuration call(Value receiver) { | 915 Configuration call(Value receiver) { |
863 if (arguments.positional.isEmpty) { | 916 if (arguments.positional.isEmpty) { |
864 Value returnValue = receiver.invokeMethod(methodName); | 917 Value returnValue = receiver.invokeMethod(methodName); |
865 return new ValuePassingConfiguration(continuation, returnValue); | 918 return new ValuePassingConfiguration(continuation, returnValue); |
866 } | 919 } |
867 var cont = new ArgumentsEK( | 920 var cont = new ArgumentsEK( |
868 receiver, methodName, arguments, environment, continuation); | 921 receiver, methodName, arguments, environment, continuation); |
869 | 922 |
870 return new EvalConfiguration(arguments.positional.first, environment, cont); | 923 return new EvalConfiguration( |
| 924 arguments.positional.first, environment, exceptionComponents, cont); |
871 } | 925 } |
872 } | 926 } |
873 | 927 |
874 class ArgumentsEK extends ExpressionContinuation { | 928 class ArgumentsEK extends ExpressionContinuation { |
875 final Value receiver; | 929 final Value receiver; |
876 final Name methodName; | 930 final Name methodName; |
877 final Arguments arguments; | 931 final Arguments arguments; |
878 final Environment environment; | 932 final Environment environment; |
879 final ExpressionContinuation continuation; | 933 final ExpressionContinuation continuation; |
880 | 934 |
(...skipping 30 matching lines...) Expand all Loading... |
911 Value notValue = identical(Value.trueInstance, value) | 965 Value notValue = identical(Value.trueInstance, value) |
912 ? Value.falseInstance | 966 ? Value.falseInstance |
913 : Value.trueInstance; | 967 : Value.trueInstance; |
914 return new ValuePassingConfiguration(continuation, notValue); | 968 return new ValuePassingConfiguration(continuation, notValue); |
915 } | 969 } |
916 } | 970 } |
917 | 971 |
918 class OrEK extends ExpressionContinuation { | 972 class OrEK extends ExpressionContinuation { |
919 final Expression right; | 973 final Expression right; |
920 final Environment environment; | 974 final Environment environment; |
| 975 final ExceptionComponents exceptionComponents; |
921 final ExpressionContinuation continuation; | 976 final ExpressionContinuation continuation; |
922 | 977 |
923 OrEK(this.right, this.environment, this.continuation); | 978 OrEK(this.right, this.environment, this.exceptionComponents, |
| 979 this.continuation); |
924 | 980 |
925 Configuration call(Value left) { | 981 Configuration call(Value left) { |
926 return identical(Value.trueInstance, left) | 982 return identical(Value.trueInstance, left) |
927 ? new ValuePassingConfiguration(continuation, Value.trueInstance) | 983 ? new ValuePassingConfiguration(continuation, Value.trueInstance) |
928 : new EvalConfiguration(right, environment, continuation); | 984 : new EvalConfiguration( |
| 985 right, environment, exceptionComponents, continuation); |
929 } | 986 } |
930 } | 987 } |
931 | 988 |
932 class AndEK extends ExpressionContinuation { | 989 class AndEK extends ExpressionContinuation { |
933 final Expression right; | 990 final Expression right; |
934 final Environment environment; | 991 final Environment environment; |
| 992 final ExceptionComponents exceptionComponents; |
935 final ExpressionContinuation continuation; | 993 final ExpressionContinuation continuation; |
936 | 994 |
937 AndEK(this.right, this.environment, this.continuation); | 995 AndEK(this.right, this.environment, this.exceptionComponents, |
| 996 this.continuation); |
938 | 997 |
939 Configuration call(Value left) { | 998 Configuration call(Value left) { |
940 return identical(Value.falseInstance, left) | 999 return identical(Value.falseInstance, left) |
941 ? new ValuePassingConfiguration(continuation, Value.falseInstance) | 1000 ? new ValuePassingConfiguration(continuation, Value.falseInstance) |
942 : new EvalConfiguration(right, environment, continuation); | 1001 : new EvalConfiguration( |
| 1002 right, environment, exceptionComponents, continuation); |
943 } | 1003 } |
944 } | 1004 } |
945 | 1005 |
946 class ConditionalEK extends ExpressionContinuation { | 1006 class ConditionalEK extends ExpressionContinuation { |
947 final Expression then; | 1007 final Expression then; |
948 final Expression otherwise; | 1008 final Expression otherwise; |
949 final Environment environment; | 1009 final Environment environment; |
| 1010 final ExceptionComponents exceptionComponents; |
950 final ExpressionContinuation continuation; | 1011 final ExpressionContinuation continuation; |
951 | 1012 |
952 ConditionalEK(this.then, this.otherwise, this.environment, this.continuation); | 1013 ConditionalEK(this.then, this.otherwise, this.environment, |
| 1014 this.exceptionComponents, this.continuation); |
953 | 1015 |
954 Configuration call(Value value) { | 1016 Configuration call(Value value) { |
955 return identical(Value.trueInstance, value) | 1017 return identical(Value.trueInstance, value) |
956 ? new EvalConfiguration(then, environment, continuation) | 1018 ? new EvalConfiguration( |
957 : new EvalConfiguration(otherwise, environment, continuation); | 1019 then, environment, exceptionComponents, continuation) |
| 1020 : new EvalConfiguration( |
| 1021 otherwise, environment, exceptionComponents, continuation); |
958 } | 1022 } |
959 } | 1023 } |
960 | 1024 |
961 class LetEK extends ExpressionContinuation { | 1025 class LetEK extends ExpressionContinuation { |
962 final VariableDeclaration variable; | 1026 final VariableDeclaration variable; |
963 final Expression letBody; | 1027 final Expression letBody; |
964 final Environment environment; | 1028 final Environment environment; |
| 1029 final ExceptionComponents exceptionComponents; |
965 final ExpressionContinuation continuation; | 1030 final ExpressionContinuation continuation; |
966 | 1031 |
967 LetEK(this.variable, this.letBody, this.environment, this.continuation); | 1032 LetEK(this.variable, this.letBody, this.environment, this.exceptionComponents, |
| 1033 this.continuation); |
968 | 1034 |
969 Configuration call(Value value) { | 1035 Configuration call(Value value) { |
970 var letEnv = new Environment(environment); | 1036 var letEnv = new Environment(environment); |
971 letEnv.extend(variable, value); | 1037 letEnv.extend(variable, value); |
972 return new EvalConfiguration(letBody, letEnv, continuation); | 1038 return new EvalConfiguration( |
| 1039 letBody, letEnv, exceptionComponents, continuation); |
973 } | 1040 } |
974 } | 1041 } |
975 | 1042 |
976 /// Represents the continuation for the condition expression in [WhileStatement]
. | 1043 /// Represents the continuation for the condition expression in [WhileStatement]
. |
977 class WhileConditionEK extends ExpressionContinuation { | 1044 class WhileConditionEK extends ExpressionContinuation { |
978 final Expression condition; | 1045 final Expression condition; |
979 final Statement body; | 1046 final Statement body; |
980 final Environment enclosingEnv; | 1047 final Environment enclosingEnv; |
981 final State state; | 1048 final State state; |
982 | 1049 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1025 return new ForwardConfiguration( | 1092 return new ForwardConfiguration( |
1026 continuation, environment.extend(variable, v)); | 1093 continuation, environment.extend(variable, v)); |
1027 } | 1094 } |
1028 } | 1095 } |
1029 | 1096 |
1030 /// Expression continuation that further initializes the newly allocated object | 1097 /// Expression continuation that further initializes the newly allocated object |
1031 /// instance with running the constructor. | 1098 /// instance with running the constructor. |
1032 class InitializationEK extends ExpressionContinuation { | 1099 class InitializationEK extends ExpressionContinuation { |
1033 final Constructor constructor; | 1100 final Constructor constructor; |
1034 final Environment environment; | 1101 final Environment environment; |
1035 // TODO(zhivkag): Add components for exception handling support | 1102 final ExceptionComponents exceptionComponents; |
1036 final StatementContinuation continuation; | 1103 final StatementContinuation continuation; |
1037 | 1104 |
1038 InitializationEK(this.constructor, this.environment, this.continuation); | 1105 InitializationEK(this.constructor, this.environment, this.exceptionComponents, |
| 1106 this.continuation); |
1039 | 1107 |
1040 Configuration call(Value value) { | 1108 Configuration call(Value value) { |
1041 Location location = new Location(value); | 1109 Location location = new Location(value); |
1042 | 1110 |
1043 if (constructor.initializers.isNotEmpty && | 1111 if (constructor.initializers.isNotEmpty && |
1044 constructor.initializers.last is RedirectingInitializer) { | 1112 constructor.initializers.last is RedirectingInitializer) { |
1045 return _createRedirectingInitializerConfig( | 1113 return _createRedirectingInitializerConfig( |
1046 constructor.initializers.first, location); | 1114 constructor.initializers.first, location); |
1047 } | 1115 } |
1048 // The statement body is captured by the next statement continuation and | 1116 // The statement body is captured by the next statement continuation and |
1049 // expressions for field initialization are evaluated. | 1117 // expressions for field initialization are evaluated. |
1050 var ctrEnv = environment.extendWithThis(value); | 1118 var ctrEnv = environment.extendWithThis(value); |
1051 var bodyCont = | 1119 var bodyCont = new ConstructorBodySK( |
1052 new ConstructorBodySK(constructor.function.body, ctrEnv, continuation); | 1120 constructor.function.body, ctrEnv, exceptionComponents, continuation); |
1053 var initializers = _getFieldInitializers(constructor.enclosingClass); | 1121 var initializers = _getFieldInitializers(constructor.enclosingClass); |
1054 var fieldsCont = | 1122 var fieldsCont = new InstanceFieldsA( |
1055 new InstanceFieldsA(constructor, location, ctrEnv, bodyCont); | 1123 constructor, location, ctrEnv, exceptionComponents, bodyCont); |
1056 return new EvalListConfiguration( | 1124 return new EvalListConfiguration( |
1057 initializers, new Environment.empty(), fieldsCont); | 1125 initializers, new Environment.empty(), exceptionComponents, fieldsCont); |
1058 } | 1126 } |
1059 | 1127 |
1060 /// Creates the next configuration to further initializer the value for | 1128 /// Creates the next configuration to further initializer the value for |
1061 /// redirecting constructors. | 1129 /// redirecting constructors. |
1062 Configuration _createRedirectingInitializerConfig( | 1130 Configuration _createRedirectingInitializerConfig( |
1063 Initializer initializer, Location location) { | 1131 Initializer initializer, Location location) { |
1064 Initializer current = constructor.initializers.first; | 1132 Initializer current = constructor.initializers.first; |
1065 if (current is RedirectingInitializer) { | 1133 if (current is RedirectingInitializer) { |
1066 // Evaluate the list of arguments for invoking the target constructor in | 1134 // Evaluate the list of arguments for invoking the target constructor in |
1067 // the current environment. | 1135 // the current environment. |
1068 List<InterpreterExpression> exprs = | 1136 List<InterpreterExpression> exprs = |
1069 _getArgumentExpressions(current.arguments, current.target.function); | 1137 _getArgumentExpressions(current.arguments, current.target.function); |
1070 var cont = | 1138 var cont = new ConstructorInitializerA( |
1071 new ConstructorInitializerA(current.target, location, continuation); | 1139 current.target, location, exceptionComponents, continuation); |
1072 return new EvalListConfiguration(exprs, environment, cont); | 1140 return new EvalListConfiguration( |
| 1141 exprs, environment, exceptionComponents, cont); |
1073 } | 1142 } |
1074 Expression expr = (current is FieldInitializer) | 1143 Expression expr = (current is FieldInitializer) |
1075 ? current.value | 1144 ? current.value |
1076 : (current as LocalInitializer).variable.initializer; | 1145 : (current as LocalInitializer).variable.initializer; |
1077 | 1146 |
1078 // The index is set to 0 since we are evaluating the expression for the | 1147 // The index is set to 0 since we are evaluating the expression for the |
1079 // first initializer in the initializer list. | 1148 // first initializer in the initializer list. |
1080 var cont = new InitializerListEK( | 1149 var cont = new InitializerListEK(constructor, 0, location, environment, |
1081 constructor, 0, location, environment, continuation); | 1150 exceptionComponents, continuation); |
1082 return new EvalConfiguration(expr, environment, cont); | 1151 return new EvalConfiguration(expr, environment, exceptionComponents, cont); |
1083 } | 1152 } |
1084 } | 1153 } |
1085 | 1154 |
1086 class InitializerListEK extends ExpressionContinuation { | 1155 class InitializerListEK extends ExpressionContinuation { |
1087 final Constructor constructor; | 1156 final Constructor constructor; |
1088 final int initializerIndex; | 1157 final int initializerIndex; |
1089 final Location location; | 1158 final Location location; |
1090 final Environment environment; | 1159 final Environment environment; |
1091 // TODO(zhivkag): Add componnents for exception handling. | 1160 final ExceptionComponents exceptionComponents; |
1092 final ConstructorBodySK continuation; | 1161 final ConstructorBodySK continuation; |
| 1162 |
1093 final Class _currentClass; | 1163 final Class _currentClass; |
1094 | 1164 |
1095 InitializerListEK(this.constructor, this.initializerIndex, this.location, | 1165 InitializerListEK(this.constructor, this.initializerIndex, this.location, |
1096 this.environment, this.continuation) | 1166 this.environment, this.exceptionComponents, this.continuation) |
1097 : _currentClass = new Class(constructor.enclosingClass.reference); | 1167 : _currentClass = new Class(constructor.enclosingClass.reference); |
1098 | 1168 |
1099 /// Creates a continuation for the evaluation of the initializer at position | 1169 /// Creates a continuation for the evaluation of the initializer at position |
1100 /// [index]. | 1170 /// [index]. |
1101 InitializerListEK withInitializerIndex(int index) { | 1171 InitializerListEK withInitializerIndex(int index) { |
1102 return new InitializerListEK( | 1172 return new InitializerListEK(constructor, index, location, environment, |
1103 constructor, index, location, environment, continuation); | 1173 exceptionComponents, continuation); |
1104 } | 1174 } |
1105 | 1175 |
1106 Configuration call(Value value) { | 1176 Configuration call(Value value) { |
1107 Initializer current = constructor.initializers[initializerIndex]; | 1177 Initializer current = constructor.initializers[initializerIndex]; |
1108 if (current is FieldInitializer) { | 1178 if (current is FieldInitializer) { |
1109 _currentClass.lookupImplicitSetter(current.field.name)( | 1179 _currentClass.lookupImplicitSetter(current.field.name)( |
1110 location.value, value); | 1180 location.value, value); |
1111 return _createNextConfiguration(environment); | 1181 return _createNextConfiguration(environment); |
1112 } | 1182 } |
1113 if (current is LocalInitializer) { | 1183 if (current is LocalInitializer) { |
(...skipping 18 matching lines...) Expand all Loading... |
1132 | 1202 |
1133 if (next is RedirectingInitializer) { | 1203 if (next is RedirectingInitializer) { |
1134 return _createEvalListConfig(next.arguments, next.target, env); | 1204 return _createEvalListConfig(next.arguments, next.target, env); |
1135 } | 1205 } |
1136 | 1206 |
1137 Expression nextExpr = (next is FieldInitializer) | 1207 Expression nextExpr = (next is FieldInitializer) |
1138 ? next.value | 1208 ? next.value |
1139 : (next as LocalInitializer).variable.initializer; | 1209 : (next as LocalInitializer).variable.initializer; |
1140 | 1210 |
1141 var cont = withInitializerIndex(initializerIndex + 1); | 1211 var cont = withInitializerIndex(initializerIndex + 1); |
1142 return new EvalConfiguration(nextExpr, env, cont); | 1212 return new EvalConfiguration(nextExpr, env, exceptionComponents, cont); |
1143 } | 1213 } |
1144 | 1214 |
1145 Configuration _createEvalListConfig( | 1215 Configuration _createEvalListConfig( |
1146 Arguments args, Constructor ctr, Environment env) { | 1216 Arguments args, Constructor ctr, Environment env) { |
1147 List<InterpreterExpression> exprs = | 1217 List<InterpreterExpression> exprs = |
1148 _getArgumentExpressions(args, ctr.function); | 1218 _getArgumentExpressions(args, ctr.function); |
1149 var cont = new ConstructorInitializerA(ctr, location, continuation); | 1219 var cont = new ConstructorInitializerA( |
1150 return new EvalListConfiguration(exprs, env, cont); | 1220 ctr, location, exceptionComponents, continuation); |
| 1221 return new EvalListConfiguration(exprs, env, exceptionComponents, cont); |
1151 } | 1222 } |
1152 } | 1223 } |
1153 | 1224 |
| 1225 // ------------------------------------------------------------------------ |
| 1226 // Exceptions Handlers |
| 1227 // ------------------------------------------------------------------------ |
| 1228 |
| 1229 abstract class ExceptionHandler extends Continuation { |
| 1230 ExceptionHandler get nextHandler; |
| 1231 |
| 1232 Configuration call(Value exception, StackTrace stacktrace); |
| 1233 } |
| 1234 |
| 1235 // ------------------------------------------------------------------------ |
| 1236 // Exceptions |
| 1237 // ------------------------------------------------------------------------ |
| 1238 /// Represents the components for Exception handling. |
| 1239 /// |
| 1240 /// It contains the list of exception handlers, a stack trace and optional |
| 1241 /// components, current stacktrace and exception. |
| 1242 class ExceptionComponents { |
| 1243 final ExceptionHandler handler; |
| 1244 final StackTrace stackTrace; |
| 1245 |
| 1246 /// Current exception and stack trace. |
| 1247 /// |
| 1248 /// Components enabling support for `rethrow` expressions and set only in |
| 1249 /// catch clauses. |
| 1250 final StackTrace currentStackTrace; |
| 1251 final Value currentException; |
| 1252 |
| 1253 ExceptionComponents(this.handler, this.stackTrace, this.currentStackTrace, |
| 1254 this.currentException); |
| 1255 |
| 1256 // TODO(zhivkag): Add a top level handler for initial exception state. |
| 1257 ExceptionComponents.initial() |
| 1258 : handler = null, |
| 1259 stackTrace = null, |
| 1260 currentStackTrace = null, |
| 1261 currentException = null; |
| 1262 } |
| 1263 |
| 1264 class StackTrace { |
| 1265 final Expression expression; |
| 1266 final StackTrace stackTrace; |
| 1267 |
| 1268 StackTrace(this.expression, this.stackTrace); |
| 1269 } |
| 1270 |
1154 /// Executes statements. | 1271 /// Executes statements. |
1155 /// | 1272 /// |
1156 /// Execution of a statement completes in one of the following ways: | 1273 /// Execution of a statement completes in one of the following ways: |
1157 /// - It completes normally, in which case the execution proceeds to applying | 1274 /// - It completes normally, in which case the execution proceeds to applying |
1158 /// the next continuation. | 1275 /// the next continuation. |
1159 /// - It breaks with a label, in which case the corresponding continuation is | 1276 /// - It breaks with a label, in which case the corresponding continuation is |
1160 /// returned and applied. | 1277 /// returned and applied. |
1161 /// - It returns with or without value, in which case the return continuation is | 1278 /// - It returns with or without value, in which case the return continuation is |
1162 /// returned and applied accordingly. | 1279 /// returned and applied accordingly. |
1163 /// - It throws, in which case the handler is returned and applied accordingly. | 1280 /// - It throws, in which case the handler is returned and applied accordingly. |
1164 class StatementExecuter | 1281 class StatementExecuter |
1165 extends StatementVisitor1<Configuration, ExecConfiguration> { | 1282 extends StatementVisitor1<Configuration, ExecConfiguration> { |
1166 Evaluator evaluator = new Evaluator(); | 1283 Evaluator evaluator = new Evaluator(); |
1167 | 1284 |
1168 void trampolinedExecution(Configuration configuration) { | 1285 void trampolinedExecution(Configuration configuration) { |
1169 while (configuration != null) { | 1286 while (configuration != null) { |
1170 configuration = configuration.step(this); | 1287 configuration = configuration.step(this); |
1171 } | 1288 } |
1172 } | 1289 } |
1173 | 1290 |
1174 Configuration exec(Statement statement, ExecConfiguration conf) => | 1291 Configuration exec(Statement statement, ExecConfiguration conf) => |
1175 statement.accept1(this, conf); | 1292 statement.accept1(this, conf); |
1176 Configuration eval(Expression expression, EvalConfiguration config) => | 1293 Configuration eval(Expression expression, EvalConfiguration config) => |
1177 evaluator.eval(expression, config); | 1294 evaluator.eval(expression, config); |
1178 Configuration evalList( | 1295 Configuration evalList(List<InterpreterExpression> es, Environment env, |
1179 List<InterpreterExpression> es, Environment env, Continuation cont) => | 1296 ExceptionComponents ecs, Continuation cont) => |
1180 evaluator.evalList(es, env, cont); | 1297 evaluator.evalList(es, env, ecs, cont); |
1181 | 1298 |
1182 Configuration defaultStatement(Statement node, ExecConfiguration conf) { | 1299 Configuration defaultStatement(Statement node, ExecConfiguration conf) { |
1183 throw notImplemented( | 1300 throw notImplemented( |
1184 m: "Execution is not implemented for statement:\n$node "); | 1301 m: "Execution is not implemented for statement:\n$node "); |
1185 } | 1302 } |
1186 | 1303 |
1187 Configuration visitInvalidStatement( | 1304 Configuration visitInvalidStatement( |
1188 InvalidStatement node, ExecConfiguration conf) { | 1305 InvalidStatement node, ExecConfiguration conf) { |
1189 throw "Invalid statement at ${node.location}"; | 1306 throw "Invalid statement at ${node.location}"; |
1190 } | 1307 } |
1191 | 1308 |
1192 Configuration visitExpressionStatement( | 1309 Configuration visitExpressionStatement( |
1193 ExpressionStatement node, ExecConfiguration conf) { | 1310 ExpressionStatement node, ExecConfiguration conf) { |
1194 var cont = new ExpressionEK(conf.state.continuation, conf.environment); | 1311 var cont = new ExpressionEK(conf.state.continuation, conf.environment); |
1195 return new EvalConfiguration(node.expression, conf.environment, cont); | 1312 return new EvalConfiguration(node.expression, conf.environment, |
| 1313 conf.state.exceptionComponents, cont); |
1196 } | 1314 } |
1197 | 1315 |
1198 Configuration visitBlock(Block node, ExecConfiguration conf) { | 1316 Configuration visitBlock(Block node, ExecConfiguration conf) { |
1199 if (node.statements.isEmpty) { | 1317 if (node.statements.isEmpty) { |
1200 return new ForwardConfiguration( | 1318 return new ForwardConfiguration( |
1201 conf.state.continuation, conf.environment); | 1319 conf.state.continuation, conf.environment); |
1202 } | 1320 } |
1203 | 1321 |
1204 var env = new Environment(conf.environment); | 1322 var env = new Environment(conf.environment); |
1205 var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf); | 1323 var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf); |
1206 return new ExecConfiguration( | 1324 return new ExecConfiguration( |
1207 node.statements.first, env, conf.state.withContinuation(cont)); | 1325 node.statements.first, env, conf.state.withContinuation(cont)); |
1208 } | 1326 } |
1209 | 1327 |
1210 Configuration visitEmptyStatement( | 1328 Configuration visitEmptyStatement( |
1211 EmptyStatement node, ExecConfiguration conf) { | 1329 EmptyStatement node, ExecConfiguration conf) { |
1212 return new ForwardConfiguration(conf.state.continuation, conf.environment); | 1330 return new ForwardConfiguration(conf.state.continuation, conf.environment); |
1213 } | 1331 } |
1214 | 1332 |
1215 Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) { | 1333 Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) { |
1216 var cont = new IfConditionEK( | 1334 var cont = new IfConditionEK( |
1217 node.then, node.otherwise, conf.environment, conf.state); | 1335 node.then, node.otherwise, conf.environment, conf.state); |
1218 | 1336 |
1219 return new EvalConfiguration(node.condition, conf.environment, cont); | 1337 return new EvalConfiguration( |
| 1338 node.condition, conf.environment, conf.state.exceptionComponents, cont); |
1220 } | 1339 } |
1221 | 1340 |
1222 Configuration visitLabeledStatement( | 1341 Configuration visitLabeledStatement( |
1223 LabeledStatement node, ExecConfiguration conf) { | 1342 LabeledStatement node, ExecConfiguration conf) { |
1224 return new ExecConfiguration(node.body, conf.environment, | 1343 return new ExecConfiguration(node.body, conf.environment, |
1225 conf.state.withBreak(node, conf.environment)); | 1344 conf.state.withBreak(node, conf.environment)); |
1226 } | 1345 } |
1227 | 1346 |
1228 Configuration visitBreakStatement( | 1347 Configuration visitBreakStatement( |
1229 BreakStatement node, ExecConfiguration conf) { | 1348 BreakStatement node, ExecConfiguration conf) { |
1230 Label l = conf.state.lookupLabel(node.target); | 1349 Label l = conf.state.lookupLabel(node.target); |
1231 return new ForwardConfiguration(l.continuation, l.environment); | 1350 return new ForwardConfiguration(l.continuation, l.environment); |
1232 } | 1351 } |
1233 | 1352 |
1234 Configuration visitWhileStatement( | 1353 Configuration visitWhileStatement( |
1235 WhileStatement node, ExecConfiguration conf) { | 1354 WhileStatement node, ExecConfiguration conf) { |
1236 var cont = new WhileConditionEK( | 1355 var cont = new WhileConditionEK( |
1237 node.condition, node.body, conf.environment, conf.state); | 1356 node.condition, node.body, conf.environment, conf.state); |
1238 | 1357 |
1239 return new EvalConfiguration(node.condition, conf.environment, cont); | 1358 return new EvalConfiguration( |
| 1359 node.condition, conf.environment, conf.state.exceptionComponents, cont); |
1240 } | 1360 } |
1241 | 1361 |
1242 Configuration visitDoStatement(DoStatement node, ExecConfiguration conf) { | 1362 Configuration visitDoStatement(DoStatement node, ExecConfiguration conf) { |
1243 var cont = new WhileConditionSK( | 1363 var cont = new WhileConditionSK( |
1244 node.condition, node.body, conf.environment, conf.state); | 1364 node.condition, node.body, conf.environment, conf.state); |
1245 | 1365 |
1246 return new ExecConfiguration( | 1366 return new ExecConfiguration( |
1247 node.body, conf.environment, conf.state.withContinuation(cont)); | 1367 node.body, conf.environment, conf.state.withContinuation(cont)); |
1248 } | 1368 } |
1249 | 1369 |
1250 Configuration visitReturnStatement( | 1370 Configuration visitReturnStatement( |
1251 ReturnStatement node, ExecConfiguration conf) { | 1371 ReturnStatement node, ExecConfiguration conf) { |
1252 assert(conf.state.returnContinuation != null); | 1372 assert(conf.state.returnContinuation != null); |
1253 log.info('return\n'); | 1373 log.info('return\n'); |
1254 if (node.expression == null) { | 1374 if (node.expression == null) { |
1255 return new ValuePassingConfiguration( | 1375 return new ValuePassingConfiguration( |
1256 conf.state.returnContinuation, Value.nullInstance); | 1376 conf.state.returnContinuation, Value.nullInstance); |
1257 } | 1377 } |
1258 | 1378 return new EvalConfiguration(node.expression, conf.environment, |
1259 return new EvalConfiguration( | 1379 conf.state.exceptionComponents, conf.state.returnContinuation); |
1260 node.expression, conf.environment, conf.state.returnContinuation); | |
1261 } | 1380 } |
1262 | 1381 |
1263 Configuration visitVariableDeclaration( | 1382 Configuration visitVariableDeclaration( |
1264 VariableDeclaration node, ExecConfiguration conf) { | 1383 VariableDeclaration node, ExecConfiguration conf) { |
1265 if (node.initializer != null) { | 1384 if (node.initializer != null) { |
1266 var cont = new VariableInitializerEK( | 1385 var cont = new VariableInitializerEK( |
1267 node, conf.environment, conf.state.continuation); | 1386 node, conf.environment, conf.state.continuation); |
1268 return new EvalConfiguration(node.initializer, conf.environment, cont); | 1387 return new EvalConfiguration(node.initializer, conf.environment, |
| 1388 conf.state.exceptionComponents, cont); |
1269 } | 1389 } |
1270 return new ForwardConfiguration(conf.state.continuation, | 1390 return new ForwardConfiguration(conf.state.continuation, |
1271 conf.environment.extend(node, Value.nullInstance)); | 1391 conf.environment.extend(node, Value.nullInstance)); |
1272 } | 1392 } |
1273 } | 1393 } |
1274 | 1394 |
1275 // ------------------------------------------------------------------------ | 1395 // ------------------------------------------------------------------------ |
1276 // VALUES | 1396 // VALUES |
1277 // ------------------------------------------------------------------------ | 1397 // ------------------------------------------------------------------------ |
1278 | 1398 |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1564 /// Initializes all non initialized fields from the provided class to | 1684 /// Initializes all non initialized fields from the provided class to |
1565 /// `Value.nullInstance` in the provided value. | 1685 /// `Value.nullInstance` in the provided value. |
1566 void _initializeNullFields(Class class_, Value value) { | 1686 void _initializeNullFields(Class class_, Value value) { |
1567 int startIndex = class_.superclass?.instanceSize ?? 0; | 1687 int startIndex = class_.superclass?.instanceSize ?? 0; |
1568 for (int i = startIndex; i < class_.instanceSize; i++) { | 1688 for (int i = startIndex; i < class_.instanceSize; i++) { |
1569 if (value.fields[i].value == null) { | 1689 if (value.fields[i].value == null) { |
1570 value.fields[i].value = Value.nullInstance; | 1690 value.fields[i].value = Value.nullInstance; |
1571 } | 1691 } |
1572 } | 1692 } |
1573 } | 1693 } |
OLD | NEW |