| Index: pkg/kernel/lib/interpreter/interpreter.dart
|
| diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart
|
| index ac3c15548b51cb702f549a5509584ca11417f5dd..adc225a7ef822b75a488acfa573d9ca3990a11d3 100644
|
| --- a/pkg/kernel/lib/interpreter/interpreter.dart
|
| +++ b/pkg/kernel/lib/interpreter/interpreter.dart
|
| @@ -131,17 +131,9 @@ class Evaluator
|
| return new ExpressionConfiguration(
|
| node.arguments.positional.first, config.environment, cont);
|
| } else {
|
| - // Currently supports only static invocations with no arguments.
|
| - if (node.arguments.positional.isEmpty && node.arguments.named.isEmpty) {
|
| - State statementState = new State.initial()
|
| - .withExpressionContinuation(config.continuation)
|
| - .withConfiguration(new ExitConfiguration(config.continuation));
|
| -
|
| - return new StatementConfiguration(
|
| - node.target.function.body, statementState);
|
| - }
|
| - throw new NotImplemented(
|
| - 'Support for static invocation with arguments is not implemented');
|
| + var cont = new ActualArgumentsContinuation(node.arguments,
|
| + node.target.function, config.environment, config.continuation);
|
| + return cont.createCurrentConfiguration();
|
| }
|
| }
|
|
|
| @@ -418,13 +410,141 @@ class SetterContinuation extends ExpressionContinuation {
|
| }
|
| }
|
|
|
| -class StaticInvocationContinuation extends ExpressionContinuation {
|
| +/// Represents a continuation to be called after the evaluation of an actual
|
| +/// argument for function invocation.
|
| +/// TODO: Add checks for validation of arguments according to spec.
|
| +class ActualArgumentsContinuation extends ExpressionContinuation {
|
| + final Arguments arguments;
|
| + final FunctionNode functionNode;
|
| + final Environment environment;
|
| final ExpressionContinuation continuation;
|
|
|
| - StaticInvocationContinuation(this.continuation);
|
| + final List<Value> _positional = <Value>[];
|
| + int _currentPositional = 0;
|
| + final Map<String, Value> _named = <String, Value>{};
|
| + int _currentNamed = 0;
|
| +
|
| + ActualArgumentsContinuation(
|
| + this.arguments, this.functionNode, this.environment, this.continuation);
|
|
|
| Configuration call(Value v) {
|
| - return new ContinuationConfiguration(continuation, v);
|
| + if (_currentPositional < arguments.positional.length) {
|
| + _positional.add(v);
|
| + _currentPositional++;
|
| + } else {
|
| + assert(_currentNamed < arguments.named.length);
|
| + String name = arguments.named[_currentNamed].name;
|
| + _named[name] = v;
|
| + _currentNamed++;
|
| + }
|
| +
|
| + return createCurrentConfiguration();
|
| + }
|
| +
|
| + Configuration createCurrentConfiguration() {
|
| + // Next argument to evaluate is a provided positional argument.
|
| + if (_currentPositional < arguments.positional.length) {
|
| + return new ExpressionConfiguration(
|
| + arguments.positional[_currentPositional], environment, this);
|
| + }
|
| + // Next argument to evaluate is a provided named argument.
|
| + if (_currentNamed < arguments.named.length) {
|
| + return new ExpressionConfiguration(
|
| + arguments.named[_currentNamed].value, environment, this);
|
| + }
|
| +
|
| + // TODO: check if the number of actual arguments is larger then the number
|
| + // of required arguments and smaller then the number of formal arguments.
|
| +
|
| + return new OptionalArgumentsContinuation(
|
| + _positional, _named, functionNode, environment, continuation)
|
| + .createCurrentConfiguration();
|
| + }
|
| +}
|
| +
|
| +class OptionalArgumentsContinuation extends ExpressionContinuation {
|
| + final List<Value> positional;
|
| + final Map<String, Value> named;
|
| + final FunctionNode functionNode;
|
| + final Environment environment;
|
| + final ExpressionContinuation continuation;
|
| +
|
| + final Map<String, VariableDeclaration> _missingFormalNamed =
|
| + <String, VariableDeclaration>{};
|
| +
|
| + int _currentPositional;
|
| + String _currentNamed;
|
| +
|
| + OptionalArgumentsContinuation(this.positional, this.named, this.functionNode,
|
| + this.environment, this.continuation) {
|
| + _currentPositional = positional.length;
|
| + assert(_currentPositional >= functionNode.requiredParameterCount);
|
| +
|
| + for (VariableDeclaration vd in functionNode.namedParameters) {
|
| + if (named[vd.name] == null) {
|
| + _missingFormalNamed[vd.name] = vd;
|
| + }
|
| + }
|
| + }
|
| +
|
| + Configuration call(Value v) {
|
| + if (_currentPositional < functionNode.positionalParameters.length) {
|
| + // Value is a optional positional argument
|
| + positional.add(v);
|
| + _currentPositional++;
|
| + } else {
|
| + // Value is a optional named argument.
|
| + assert(named[_currentNamed] == null);
|
| + named[_currentNamed] = v;
|
| + }
|
| +
|
| + return createCurrentConfiguration();
|
| + }
|
| +
|
| + /// Creates the current configuration for the evaluation of invocation a
|
| + /// function.
|
| + Configuration createCurrentConfiguration() {
|
| + if (_currentPositional < functionNode.positionalParameters.length) {
|
| + // Next argument to evaluate is a missing positional argument.
|
| + // Evaluate its initializer.
|
| + return new ExpressionConfiguration(
|
| + functionNode.positionalParameters[_currentPositional].initializer,
|
| + environment,
|
| + this);
|
| + }
|
| + if (named.length < functionNode.namedParameters.length) {
|
| + // Next argument to evaluate is a missing named argument.
|
| + // Evaluate its initializer.
|
| + _currentNamed = _missingFormalNamed.keys.first;
|
| + Expression initializer = _missingFormalNamed[_currentNamed].initializer;
|
| + _missingFormalNamed.remove(_currentNamed);
|
| + return new ExpressionConfiguration(initializer, environment, this);
|
| + }
|
| +
|
| + Environment newEnv = _createEnvironment();
|
| + State bodyState = new State.initial()
|
| + .withExpressionContinuation(continuation)
|
| + .withConfiguration(new ExitConfiguration(continuation))
|
| + .withEnvironment(newEnv);
|
| +
|
| + return new StatementConfiguration(functionNode.body, bodyState);
|
| + }
|
| +
|
| + /// Creates an environment binding actual argument values to formal parameters
|
| + /// of the function in a new environment, which is used to execute the
|
| + /// body od the function.
|
| + Environment _createEnvironment() {
|
| + Environment newEnv = new Environment.empty();
|
| + // Add positional parameters.
|
| + for (int i = 0; i < positional.length; ++i) {
|
| + newEnv.expand(functionNode.positionalParameters[i], positional[i]);
|
| + }
|
| + // Add named parameters.
|
| + for (VariableDeclaration v in functionNode.namedParameters) {
|
| + newEnv.expand(v, named[v.name.toString()]);
|
| + }
|
| +
|
| + return newEnv;
|
| }
|
| }
|
|
|
|
|