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 class NotImplemented { | 9 class NotImplemented { |
10 String message; | 10 String message; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 StaticSet node, ExpressionConfiguration config) => | 124 StaticSet node, ExpressionConfiguration config) => |
125 defaultExpression(node, config); | 125 defaultExpression(node, config); |
126 | 126 |
127 Configuration visitStaticInvocation( | 127 Configuration visitStaticInvocation( |
128 StaticInvocation node, ExpressionConfiguration config) { | 128 StaticInvocation node, ExpressionConfiguration config) { |
129 if ('print' == node.name.toString()) { | 129 if ('print' == node.name.toString()) { |
130 var cont = new PrintContinuation(config.continuation); | 130 var cont = new PrintContinuation(config.continuation); |
131 return new ExpressionConfiguration( | 131 return new ExpressionConfiguration( |
132 node.arguments.positional.first, config.environment, cont); | 132 node.arguments.positional.first, config.environment, cont); |
133 } else { | 133 } else { |
134 // Currently supports only static invocations with no arguments. | 134 var cont = new ActualArgumentsContinuation(node.arguments, |
135 if (node.arguments.positional.isEmpty && node.arguments.named.isEmpty) { | 135 node.target.function, config.environment, config.continuation); |
136 State statementState = new State.initial() | 136 return cont.createCurrentConfiguration(); |
137 .withExpressionContinuation(config.continuation) | |
138 .withConfiguration(new ExitConfiguration(config.continuation)); | |
139 | |
140 return new StatementConfiguration( | |
141 node.target.function.body, statementState); | |
142 } | |
143 throw new NotImplemented( | |
144 'Support for static invocation with arguments is not implemented'); | |
145 } | 137 } |
146 } | 138 } |
147 | 139 |
148 Configuration visitMethodInvocation( | 140 Configuration visitMethodInvocation( |
149 MethodInvocation node, ExpressionConfiguration config) { | 141 MethodInvocation node, ExpressionConfiguration config) { |
150 // Currently supports only method invocation with <2 arguments and is used | 142 // Currently supports only method invocation with <2 arguments and is used |
151 // to evaluate implemented operators for int, double and String values. | 143 // to evaluate implemented operators for int, double and String values. |
152 var cont = new MethodInvocationContinuation( | 144 var cont = new MethodInvocationContinuation( |
153 node.arguments, node.name, config.environment, config.continuation); | 145 node.arguments, node.name, config.environment, config.continuation); |
154 | 146 |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 | 403 |
412 SetterContinuation(this.receiver, this.name, this.continuation); | 404 SetterContinuation(this.receiver, this.name, this.continuation); |
413 | 405 |
414 Configuration call(Value v) { | 406 Configuration call(Value v) { |
415 Setter setter = receiver.class_.lookupSetter(name); | 407 Setter setter = receiver.class_.lookupSetter(name); |
416 setter(receiver, v); | 408 setter(receiver, v); |
417 return new ContinuationConfiguration(continuation, v); | 409 return new ContinuationConfiguration(continuation, v); |
418 } | 410 } |
419 } | 411 } |
420 | 412 |
421 class StaticInvocationContinuation extends ExpressionContinuation { | 413 /// Represents a continuation to be called after the evaluation of an actual |
| 414 /// argument for function invocation. |
| 415 /// TODO: Add checks for validation of arguments according to spec. |
| 416 class ActualArgumentsContinuation extends ExpressionContinuation { |
| 417 final Arguments arguments; |
| 418 final FunctionNode functionNode; |
| 419 final Environment environment; |
422 final ExpressionContinuation continuation; | 420 final ExpressionContinuation continuation; |
423 | 421 |
424 StaticInvocationContinuation(this.continuation); | 422 final List<Value> _positional = <Value>[]; |
| 423 int _currentPositional = 0; |
| 424 final Map<String, Value> _named = <String, Value>{}; |
| 425 int _currentNamed = 0; |
| 426 |
| 427 ActualArgumentsContinuation( |
| 428 this.arguments, this.functionNode, this.environment, this.continuation); |
425 | 429 |
426 Configuration call(Value v) { | 430 Configuration call(Value v) { |
427 return new ContinuationConfiguration(continuation, v); | 431 if (_currentPositional < arguments.positional.length) { |
| 432 _positional.add(v); |
| 433 _currentPositional++; |
| 434 } else { |
| 435 assert(_currentNamed < arguments.named.length); |
| 436 String name = arguments.named[_currentNamed].name; |
| 437 _named[name] = v; |
| 438 _currentNamed++; |
| 439 } |
| 440 |
| 441 return createCurrentConfiguration(); |
| 442 } |
| 443 |
| 444 Configuration createCurrentConfiguration() { |
| 445 // Next argument to evaluate is a provided positional argument. |
| 446 if (_currentPositional < arguments.positional.length) { |
| 447 return new ExpressionConfiguration( |
| 448 arguments.positional[_currentPositional], environment, this); |
| 449 } |
| 450 // Next argument to evaluate is a provided named argument. |
| 451 if (_currentNamed < arguments.named.length) { |
| 452 return new ExpressionConfiguration( |
| 453 arguments.named[_currentNamed].value, environment, this); |
| 454 } |
| 455 |
| 456 // TODO: check if the number of actual arguments is larger then the number |
| 457 // of required arguments and smaller then the number of formal arguments. |
| 458 |
| 459 return new OptionalArgumentsContinuation( |
| 460 _positional, _named, functionNode, environment, continuation) |
| 461 .createCurrentConfiguration(); |
428 } | 462 } |
429 } | 463 } |
430 | 464 |
| 465 class OptionalArgumentsContinuation extends ExpressionContinuation { |
| 466 final List<Value> positional; |
| 467 final Map<String, Value> named; |
| 468 final FunctionNode functionNode; |
| 469 final Environment environment; |
| 470 final ExpressionContinuation continuation; |
| 471 |
| 472 final Map<String, VariableDeclaration> _missingFormalNamed = |
| 473 <String, VariableDeclaration>{}; |
| 474 |
| 475 int _currentPositional; |
| 476 String _currentNamed; |
| 477 |
| 478 OptionalArgumentsContinuation(this.positional, this.named, this.functionNode, |
| 479 this.environment, this.continuation) { |
| 480 _currentPositional = positional.length; |
| 481 assert(_currentPositional >= functionNode.requiredParameterCount); |
| 482 |
| 483 for (VariableDeclaration vd in functionNode.namedParameters) { |
| 484 if (named[vd.name] == null) { |
| 485 _missingFormalNamed[vd.name] = vd; |
| 486 } |
| 487 } |
| 488 } |
| 489 |
| 490 Configuration call(Value v) { |
| 491 if (_currentPositional < functionNode.positionalParameters.length) { |
| 492 // Value is a optional positional argument |
| 493 positional.add(v); |
| 494 _currentPositional++; |
| 495 } else { |
| 496 // Value is a optional named argument. |
| 497 assert(named[_currentNamed] == null); |
| 498 named[_currentNamed] = v; |
| 499 } |
| 500 |
| 501 return createCurrentConfiguration(); |
| 502 } |
| 503 |
| 504 /// Creates the current configuration for the evaluation of invocation a |
| 505 /// function. |
| 506 Configuration createCurrentConfiguration() { |
| 507 if (_currentPositional < functionNode.positionalParameters.length) { |
| 508 // Next argument to evaluate is a missing positional argument. |
| 509 // Evaluate its initializer. |
| 510 return new ExpressionConfiguration( |
| 511 functionNode.positionalParameters[_currentPositional].initializer, |
| 512 environment, |
| 513 this); |
| 514 } |
| 515 if (named.length < functionNode.namedParameters.length) { |
| 516 // Next argument to evaluate is a missing named argument. |
| 517 // Evaluate its initializer. |
| 518 _currentNamed = _missingFormalNamed.keys.first; |
| 519 Expression initializer = _missingFormalNamed[_currentNamed].initializer; |
| 520 _missingFormalNamed.remove(_currentNamed); |
| 521 return new ExpressionConfiguration(initializer, environment, this); |
| 522 } |
| 523 |
| 524 Environment newEnv = _createEnvironment(); |
| 525 State bodyState = new State.initial() |
| 526 .withExpressionContinuation(continuation) |
| 527 .withConfiguration(new ExitConfiguration(continuation)) |
| 528 .withEnvironment(newEnv); |
| 529 |
| 530 return new StatementConfiguration(functionNode.body, bodyState); |
| 531 } |
| 532 |
| 533 /// Creates an environment binding actual argument values to formal parameters |
| 534 /// of the function in a new environment, which is used to execute the |
| 535 /// body od the function. |
| 536 Environment _createEnvironment() { |
| 537 Environment newEnv = new Environment.empty(); |
| 538 // Add positional parameters. |
| 539 for (int i = 0; i < positional.length; ++i) { |
| 540 newEnv.expand(functionNode.positionalParameters[i], positional[i]); |
| 541 } |
| 542 // Add named parameters. |
| 543 for (VariableDeclaration v in functionNode.namedParameters) { |
| 544 newEnv.expand(v, named[v.name.toString()]); |
| 545 } |
| 546 |
| 547 return newEnv; |
| 548 } |
| 549 } |
| 550 |
431 class MethodInvocationContinuation extends ExpressionContinuation { | 551 class MethodInvocationContinuation extends ExpressionContinuation { |
432 final Arguments arguments; | 552 final Arguments arguments; |
433 final Name methodName; | 553 final Name methodName; |
434 final Environment environment; | 554 final Environment environment; |
435 final ExpressionContinuation continuation; | 555 final ExpressionContinuation continuation; |
436 | 556 |
437 MethodInvocationContinuation( | 557 MethodInvocationContinuation( |
438 this.arguments, this.methodName, this.environment, this.continuation); | 558 this.arguments, this.methodName, this.environment, this.continuation); |
439 | 559 |
440 Configuration call(Value receiver) { | 560 Configuration call(Value receiver) { |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
971 | 1091 |
972 class NullValue extends LiteralValue { | 1092 class NullValue extends LiteralValue { |
973 Object get value => null; | 1093 Object get value => null; |
974 | 1094 |
975 const NullValue(); | 1095 const NullValue(); |
976 } | 1096 } |
977 | 1097 |
978 notImplemented({String m, Object obj}) { | 1098 notImplemented({String m, Object obj}) { |
979 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); | 1099 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); |
980 } | 1100 } |
OLD | NEW |