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 |