Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Unified Diff: pkg/kernel/lib/interpreter/interpreter.dart

Issue 2871953002: Refactor argument evaluation for static invocation (Closed)
Patch Set: Remove name getter from ArgumentExpression Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/kernel/lib/interpreter/interpreter.dart
diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart
index c9eb916983451c8313a3bde8a5855781eb984f69..76ddc324089f5a8d4af74f5d83d289e633b7ec13 100644
--- a/pkg/kernel/lib/interpreter/interpreter.dart
+++ b/pkg/kernel/lib/interpreter/interpreter.dart
@@ -86,6 +86,15 @@ class Evaluator
Configuration eval(Expression expr, ExpressionConfiguration config) =>
expr.accept1(this, config);
+ Configuration evalArgs(List<ArgumentExpression> args, Environment env,
+ ApplicationContinuation cont) {
+ if (args.isNotEmpty) {
+ return new ExpressionConfiguration(args.first.expression, env,
+ new ActualArgumentsContinuation(args.first, args.skip(1), env, cont));
+ }
+ return new ArgumentContinuationConfiguration(cont, <ArgumentValue>[]);
+ }
+
Configuration defaultExpression(
Expression node, ExpressionConfiguration config) {
throw new NotImplemented('Evaluation for expressions of type '
@@ -138,9 +147,12 @@ class Evaluator
node.arguments.positional.first, config.environment, cont);
} else {
log.info('static-invocation-${node.target.name.toString()}\n');
- var cont = new ActualArgumentsContinuation(node.arguments,
- node.target.function, config.environment, config.continuation);
- return cont.createCurrentConfiguration();
+
+ List<ArgumentExpression> args =
+ _createArgumentExpressionList(node.arguments, node.target.function);
+ ApplicationContinuation cont = new StaticInvocationApplication(
+ node.target.function, config.continuation);
+ return new ArgumentsConfiguration(args, config.environment, cont);
}
}
@@ -328,7 +340,17 @@ class ContinuationConfiguration extends Configuration {
ContinuationConfiguration(this.continuation, this.value);
- Configuration step(StatementExecuter executer) => continuation(value);
+ Configuration step(StatementExecuter _) => continuation(value);
+}
+
+/// Represents the configuration for applying an [ApplicationContinuation].
+class ArgumentContinuationConfiguration extends Configuration {
+ final ApplicationContinuation continuation;
+ final List<ArgumentValue> argumentValues;
+
+ ArgumentContinuationConfiguration(this.continuation, this.argumentValues);
+
+ Configuration step(StatementExecuter _) => continuation(argumentValues);
}
/// Represents the configuration for evaluating an [Expression].
@@ -339,7 +361,7 @@ class ExpressionConfiguration extends Configuration {
final Environment environment;
/// Next continuation to be applied.
- final ExpressionContinuation continuation;
+ final Continuation continuation;
ExpressionConfiguration(this.expression, this.environment, this.continuation);
@@ -347,8 +369,123 @@ class ExpressionConfiguration extends Configuration {
executer.eval(expression, this);
}
+/// Represents the configuration for evaluating a list of argument expressions.
+class ArgumentsConfiguration extends Configuration {
+ final List<ArgumentExpression> arguments;
+ final Environment environment;
+ final Continuation continuation;
+
+ ArgumentsConfiguration(this.arguments, this.environment, this.continuation);
+
+ Configuration step(StatementExecuter executer) =>
+ executer.evalArgs(arguments, environment, continuation);
+}
+
+abstract class ArgumentExpression {
+ Expression get expression;
+}
+
+class PositionalArgumentExpression extends ArgumentExpression {
+ final Expression expression;
+
+ PositionalArgumentExpression(this.expression);
+}
+
+class NamedArgumentExpression extends ArgumentExpression {
+ final String name;
+ final Expression expression;
+
+ NamedArgumentExpression(this.name, this.expression);
+}
+
+abstract class ArgumentValue {
+ Value get value;
+}
+
+class PositionalArgumentValue extends ArgumentValue {
+ final Value value;
+
+ PositionalArgumentValue(this.value);
+}
+
+class NamedArgumentValue extends ArgumentValue {
+ final String name;
+ final Value value;
+
+ NamedArgumentValue(this.name, this.value);
+}
+
+abstract class Continuation {}
+
+/// Represents the continuation called after the evaluation of argument
+/// expressions.
+abstract class ApplicationContinuation extends Continuation {
+ Configuration call(List<ArgumentValue> args);
+
+ /// 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.
+ static Environment createEnvironment(
+ FunctionNode function, List<ArgumentValue> args) {
+ Environment newEnv = new Environment.empty();
+ List<PositionalArgumentValue> positional = args.reversed
+ .where((ArgumentValue av) => av is PositionalArgumentValue)
+ .toList();
+
+ // Add positional parameters.
+ for (int i = 0; i < positional.length; ++i) {
+ newEnv.expand(function.positionalParameters[i], positional[i].value);
+ }
+
+ Map<String, Value> named = new Map.fromIterable(
+ args.where((ArgumentValue av) => av is NamedArgumentValue),
+ key: (NamedArgumentValue av) => av.name,
+ value: (NamedArgumentValue av) => av.value);
+
+ // Add named parameters.
+ for (VariableDeclaration v in function.namedParameters) {
+ newEnv.expand(v, named[v.name.toString()]);
+ }
+
+ return newEnv;
+ }
+}
+
+/// Represents the application continuation for static invocation.
+class StaticInvocationApplication extends ApplicationContinuation {
+ final FunctionNode function;
+ final ExpressionContinuation continuation;
+
+ StaticInvocationApplication(this.function, this.continuation);
+
+ Configuration call(List<ArgumentValue> args) {
+ Environment functionEnv =
+ ApplicationContinuation.createEnvironment(function, args);
+
+ State bodyState = new State.initial()
+ .withExpressionContinuation(continuation)
+ .withConfiguration(new ExitConfiguration(continuation))
+ .withEnvironment(functionEnv);
+ return new StatementConfiguration(function.body, bodyState);
+ }
+}
+
+/// Represents the application continuation called after the evaluation of all
+/// argument expressions for an invocation.
+class ArgumentValueApplication extends ApplicationContinuation {
+ final ArgumentValue value;
+ final ApplicationContinuation applicationContinuation;
+
+ ArgumentValueApplication(this.value, this.applicationContinuation);
+
+ Configuration call(List<ArgumentValue> args) {
+ args.add(value);
+ return new ArgumentContinuationConfiguration(applicationContinuation, args);
+ }
+}
+
/// Represents an expression continuation.
-abstract class ExpressionContinuation {
+abstract class ExpressionContinuation extends Continuation {
Configuration call(Value v);
}
@@ -422,137 +559,26 @@ class SetterContinuation extends ExpressionContinuation {
/// 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 ArgumentExpression currentArgument;
+ final List<ArgumentExpression> arguments;
final Environment environment;
- final ExpressionContinuation continuation;
-
- final List<Value> _positional = <Value>[];
- int _currentPositional = 0;
- final Map<String, Value> _named = <String, Value>{};
- int _currentNamed = 0;
+ final ApplicationContinuation applicationContinuation;
- ActualArgumentsContinuation(
- this.arguments, this.functionNode, this.environment, this.continuation);
+ ActualArgumentsContinuation(this.currentArgument, this.arguments,
+ this.environment, this.applicationContinuation);
Configuration call(Value v) {
- if (_currentPositional < arguments.positional.length) {
- _positional.add(v);
- _currentPositional++;
+ ArgumentValue argumentValue;
+ if (currentArgument is NamedArgumentExpression) {
+ argumentValue = new NamedArgumentValue(
+ (currentArgument as NamedArgumentExpression).name, v);
Dmitry Stefantsov 2017/05/10 08:41:45 Btw, we don't need the "as" cast here, because of
zhivkag 2017/05/10 09:11:07 Type promotion doesn't seem to be working in this
} 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);
+ assert(currentArgument is PositionalArgumentExpression);
+ argumentValue = new PositionalArgumentValue(v);
}
- // 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;
+ return new ArgumentsConfiguration(arguments, environment,
+ new ArgumentValueApplication(argumentValue, applicationContinuation));
}
}
@@ -788,6 +814,9 @@ class StatementExecuter extends StatementVisitor1<Configuration, State> {
statement.accept1(this, state);
Configuration eval(Expression expression, ExpressionConfiguration config) =>
evaluator.eval(expression, config);
+ Configuration evalArgs(
+ List<ArgumentExpression> args, Environment env, Continuation cont) =>
+ evaluator.evalArgs(args, env, cont);
Configuration defaultStatement(Statement node, State state) {
throw notImplemented(
@@ -1110,3 +1139,43 @@ class NullValue extends LiteralValue {
notImplemented({String m, Object obj}) {
throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
}
+
+// ------------------------------------------------------------------------
+// INTERNAL FUNCTIONS
+// ------------------------------------------------------------------------
+/// Creates a list of all argument expressions to be evaluated for the
+/// invocation of the provided [FunctionNode] containing the actual arguments
+/// and the optional argument initializers.
+List<ArgumentExpression> _createArgumentExpressionList(
+ Arguments providedArgs, FunctionNode fun) {
+ List<ArgumentExpression> args = <ArgumentExpression>[];
+ // Add positional arguments expressions.
+ args.addAll(providedArgs.positional
+ .map((Expression e) => new PositionalArgumentExpression(e)));
+
+ // Add optional positional argument initializers.
+ for (int i = providedArgs.positional.length;
+ i < fun.positionalParameters.length;
+ i++) {
+ args.add(new PositionalArgumentExpression(
+ fun.positionalParameters[i].initializer));
+ }
+
+ Map<String, NamedArgumentExpression> namedFormals = new Map.fromIterable(
+ fun.namedParameters,
+ key: (VariableDeclaration vd) => vd.name,
+ value: (VariableDeclaration vd) =>
+ new NamedArgumentExpression(vd.name, vd.initializer));
+
+ // Add named expressions.
+ for (int i = 0; i < providedArgs.named.length; i++) {
+ var current = providedArgs.named[i];
+ args.add(new NamedArgumentExpression(current.name, current.value));
+ namedFormals.remove(current.name);
+ }
+
+ // Add missing optional named initializers.
+ args.addAll(namedFormals.values);
+
+ return args;
+}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698