Chromium Code Reviews| 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 | |
| 477 OptionalArgumentsContinuation(this.positional, this.named, this.functionNode, | |
| 478 this.environment, this.continuation) | |
| 479 : _currentPositional = positional.length { | |
| 480 for (VariableDeclaration vd in functionNode.namedParameters) { | |
| 481 if (named[vd.name] == null) { | |
| 482 _missingFormalNamed[vd.name] = vd; | |
| 483 } | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 Configuration call(Value v) { | |
| 488 if (_currentPositional < functionNode.positionalParameters.length) { | |
| 489 // Value is a optional positional argument | |
| 490 assert(_currentPositional >= functionNode.requiredParameterCount); | |
|
Dmitry Stefantsov
2017/04/21 13:49:36
I think we can make this assertion once, in the co
zhivkag
2017/04/21 16:44:01
Done.
| |
| 491 positional.add(v); | |
| 492 _currentPositional++; | |
| 493 } else { | |
| 494 // Value is a optional named argument. | |
| 495 String name = _missingFormalNamed.keys.first; | |
|
Dmitry Stefantsov
2017/04/21 13:49:36
I think we need to find another way of determining
zhivkag
2017/04/21 16:44:01
Done. Indeed, another approach for this would be b
| |
| 496 named[name] = v; | |
| 497 _missingFormalNamed.remove(name); | |
| 498 } | |
| 499 | |
| 500 return createCurrentConfiguration(); | |
| 501 } | |
| 502 | |
| 503 /// Creates the current configuration for the evaluation of invocation a | |
| 504 /// function. | |
| 505 Configuration createCurrentConfiguration() { | |
| 506 if (_currentPositional < functionNode.positionalParameters.length) { | |
| 507 // Next argument to evaluate is a missing positional argument. | |
| 508 // Evaluate its initializer. | |
| 509 return new ExpressionConfiguration( | |
| 510 functionNode.positionalParameters[_currentPositional].initializer, | |
| 511 environment, | |
| 512 this); | |
| 513 } | |
| 514 if (named.length < functionNode.namedParameters.length) { | |
| 515 // Next argument to evaluate is a missing named argument. | |
| 516 // Evaluate its initializer. | |
| 517 String next = _missingFormalNamed.keys.first; | |
| 518 return new ExpressionConfiguration( | |
| 519 _missingFormalNamed[next].initializer, environment, this); | |
| 520 } | |
| 521 | |
| 522 Environment newEnv = _createEnvironment(); | |
| 523 State bodyState = new State.initial() | |
| 524 .withExpressionContinuation(continuation) | |
| 525 .withConfiguration(new ExitConfiguration(continuation)) | |
| 526 .withEnvironment(newEnv); | |
| 527 | |
| 528 return new StatementConfiguration(functionNode.body, bodyState); | |
| 529 } | |
| 530 | |
| 531 /// Creates an environment binding actual argument values to formal parameters | |
| 532 /// of the function in a new environment, which is used to execute the | |
| 533 /// body od the function. | |
| 534 Environment _createEnvironment() { | |
| 535 Environment newEnv = new Environment.empty(); | |
| 536 // Add positional parameters. | |
| 537 for (int i = 0; i < positional.length; ++i) { | |
| 538 newEnv.expand(functionNode.positionalParameters[i], positional[i]); | |
| 539 } | |
| 540 // Add named parameters. | |
| 541 for (VariableDeclaration v in functionNode.namedParameters) { | |
| 542 newEnv.expand(v, named[v.name.toString()]); | |
| 543 } | |
| 544 | |
| 545 return newEnv; | |
| 546 } | |
| 547 } | |
| 548 | |
| 431 class MethodInvocationContinuation extends ExpressionContinuation { | 549 class MethodInvocationContinuation extends ExpressionContinuation { |
| 432 final Arguments arguments; | 550 final Arguments arguments; |
| 433 final Name methodName; | 551 final Name methodName; |
| 434 final Environment environment; | 552 final Environment environment; |
| 435 final ExpressionContinuation continuation; | 553 final ExpressionContinuation continuation; |
| 436 | 554 |
| 437 MethodInvocationContinuation( | 555 MethodInvocationContinuation( |
| 438 this.arguments, this.methodName, this.environment, this.continuation); | 556 this.arguments, this.methodName, this.environment, this.continuation); |
| 439 | 557 |
| 440 Configuration call(Value receiver) { | 558 Configuration call(Value receiver) { |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 971 | 1089 |
| 972 class NullValue extends LiteralValue { | 1090 class NullValue extends LiteralValue { |
| 973 Object get value => null; | 1091 Object get value => null; |
| 974 | 1092 |
| 975 const NullValue(); | 1093 const NullValue(); |
| 976 } | 1094 } |
| 977 | 1095 |
| 978 notImplemented({String m, Object obj}) { | 1096 notImplemented({String m, Object obj}) { |
| 979 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); | 1097 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); |
| 980 } | 1098 } |
| OLD | NEW |