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

Side by Side Diff: pkg/kernel/lib/interpreter/interpreter.dart

Issue 2871953002: Refactor argument evaluation for static invocation (Closed)
Patch Set: 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 import '../log.dart'; 9 import '../log.dart';
10 export '../log.dart'; 10 export '../log.dart';
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 bindings.add(new Binding(variable, value)); 79 bindings.add(new Binding(variable, value));
80 } 80 }
81 } 81 }
82 82
83 /// Evaluate expressions. 83 /// Evaluate expressions.
84 class Evaluator 84 class Evaluator
85 extends ExpressionVisitor1<Configuration, ExpressionConfiguration> { 85 extends ExpressionVisitor1<Configuration, ExpressionConfiguration> {
86 Configuration eval(Expression expr, ExpressionConfiguration config) => 86 Configuration eval(Expression expr, ExpressionConfiguration config) =>
87 expr.accept1(this, config); 87 expr.accept1(this, config);
88 88
89 Configuration evalArgs(List<ArgumentExpression> args, Environment env,
90 ApplicationContinuation cont) {
91 if (args.isNotEmpty) {
92 return new ExpressionConfiguration(args.first.expression, env,
93 new ActualArgumentsContinuation(args.first, args.skip(1), env, cont));
94 }
95 return new ArgumentContinuationConfiguration(cont, <ArgumentValue>[]);
96 }
97
89 Configuration defaultExpression( 98 Configuration defaultExpression(
90 Expression node, ExpressionConfiguration config) { 99 Expression node, ExpressionConfiguration config) {
91 throw new NotImplemented('Evaluation for expressions of type ' 100 throw new NotImplemented('Evaluation for expressions of type '
92 '${node.runtimeType} is not implemented.'); 101 '${node.runtimeType} is not implemented.');
93 } 102 }
94 103
95 Configuration visitInvalidExpression1( 104 Configuration visitInvalidExpression1(
96 InvalidExpression node, ExpressionConfiguration config) { 105 InvalidExpression node, ExpressionConfiguration config) {
97 throw 'Invalid expression at ${node.location.toString()}'; 106 throw 'Invalid expression at ${node.location.toString()}';
98 } 107 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 defaultExpression(node, config); 140 defaultExpression(node, config);
132 141
133 Configuration visitStaticInvocation( 142 Configuration visitStaticInvocation(
134 StaticInvocation node, ExpressionConfiguration config) { 143 StaticInvocation node, ExpressionConfiguration config) {
135 if ('print' == node.name.toString()) { 144 if ('print' == node.name.toString()) {
136 var cont = new PrintContinuation(config.continuation); 145 var cont = new PrintContinuation(config.continuation);
137 return new ExpressionConfiguration( 146 return new ExpressionConfiguration(
138 node.arguments.positional.first, config.environment, cont); 147 node.arguments.positional.first, config.environment, cont);
139 } else { 148 } else {
140 log.info('static-invocation-${node.target.name.toString()}\n'); 149 log.info('static-invocation-${node.target.name.toString()}\n');
141 var cont = new ActualArgumentsContinuation(node.arguments, 150
142 node.target.function, config.environment, config.continuation); 151 List<ArgumentExpression> args =
143 return cont.createCurrentConfiguration(); 152 _createArgumentExpressionList(node.arguments, node.target.function);
153 ApplicationContinuation cont = new StaticInvocationApplication(
154 node.target.function, config.continuation);
155 return new ArgumentsConfiguration(args, config.environment, cont);
144 } 156 }
145 } 157 }
146 158
147 Configuration visitMethodInvocation( 159 Configuration visitMethodInvocation(
148 MethodInvocation node, ExpressionConfiguration config) { 160 MethodInvocation node, ExpressionConfiguration config) {
149 // Currently supports only method invocation with <2 arguments and is used 161 // Currently supports only method invocation with <2 arguments and is used
150 // to evaluate implemented operators for int, double and String values. 162 // to evaluate implemented operators for int, double and String values.
151 var cont = new MethodInvocationContinuation( 163 var cont = new MethodInvocationContinuation(
152 node.arguments, node.name, config.environment, config.continuation); 164 node.arguments, node.name, config.environment, config.continuation);
153 165
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 } 333 }
322 } 334 }
323 335
324 /// Represents the configuration for applying an [ExpressionContinuation]. 336 /// Represents the configuration for applying an [ExpressionContinuation].
325 class ContinuationConfiguration extends Configuration { 337 class ContinuationConfiguration extends Configuration {
326 final ExpressionContinuation continuation; 338 final ExpressionContinuation continuation;
327 final Value value; 339 final Value value;
328 340
329 ContinuationConfiguration(this.continuation, this.value); 341 ContinuationConfiguration(this.continuation, this.value);
330 342
331 Configuration step(StatementExecuter executer) => continuation(value); 343 Configuration step(StatementExecuter _) => continuation(value);
344 }
345
346 /// Represents the configuration for applying an [ApplicationContinuation].
347 class ArgumentContinuationConfiguration extends Configuration {
348 final ApplicationContinuation continuation;
349 final List<ArgumentValue> argumentValues;
350
351 ArgumentContinuationConfiguration(this.continuation, this.argumentValues);
352
353 Configuration step(StatementExecuter _) => continuation(argumentValues);
332 } 354 }
333 355
334 /// Represents the configuration for evaluating an [Expression]. 356 /// Represents the configuration for evaluating an [Expression].
335 class ExpressionConfiguration extends Configuration { 357 class ExpressionConfiguration extends Configuration {
336 final Expression expression; 358 final Expression expression;
337 359
338 /// Environment in which the expression is evaluated. 360 /// Environment in which the expression is evaluated.
339 final Environment environment; 361 final Environment environment;
340 362
341 /// Next continuation to be applied. 363 /// Next continuation to be applied.
342 final ExpressionContinuation continuation; 364 final Continuation continuation;
343 365
344 ExpressionConfiguration(this.expression, this.environment, this.continuation); 366 ExpressionConfiguration(this.expression, this.environment, this.continuation);
345 367
346 Configuration step(StatementExecuter executer) => 368 Configuration step(StatementExecuter executer) =>
347 executer.eval(expression, this); 369 executer.eval(expression, this);
348 } 370 }
349 371
372 /// Represents the configuration for evaluating a list of argument expressions.
373 class ArgumentsConfiguration extends Configuration {
374 final List<ArgumentExpression> arguments;
375 final Environment environment;
376 final Continuation continuation;
377
378 ArgumentsConfiguration(this.arguments, this.environment, this.continuation);
379
380 Configuration step(StatementExecuter executer) =>
381 executer.evalArgs(arguments, environment, continuation);
382 }
383
384 abstract class ArgumentExpression {
385 String get name;
386 Expression get expression;
387 }
388
389 class PositionalArgumentExpression extends ArgumentExpression {
390 String get name => throw 'PositionalArgumentExpression has no name';
Dmitry Stefantsov 2017/05/10 08:08:49 It's not clear why we define "name" getter in Argu
zhivkag 2017/05/10 08:27:07 I initially intended to have name for both, but fi
391 final Expression expression;
392
393 PositionalArgumentExpression(this.expression);
394 }
395
396 class NamedArgumentExpression extends ArgumentExpression {
397 final String name;
398 final Expression expression;
399
400 NamedArgumentExpression(this.name, this.expression);
401 }
402
403 abstract class ArgumentValue {
404 Value get value;
405 }
406
407 class PositionalArgumentValue extends ArgumentValue {
408 final Value value;
409
410 PositionalArgumentValue(this.value);
411 }
412
413 class NamedArgumentValue extends ArgumentValue {
414 final String name;
415 final Value value;
416
417 NamedArgumentValue(this.name, this.value);
418 }
419
420 abstract class Continuation {}
421
422 // ------------------------------------------------------------------------
423 // EXPRESSION CONTINUATIONS
424 // ------------------------------------------------------------------------
425
350 /// Represents an expression continuation. 426 /// Represents an expression continuation.
351 abstract class ExpressionContinuation { 427 abstract class ExpressionContinuation extends Continuation {
352 Configuration call(Value v); 428 Configuration call(Value v);
353 } 429 }
354 430
355 /// Represents a continuation that returns the next [StatementConfiguration] 431 /// Represents a continuation that returns the next [StatementConfiguration]
356 /// to be executed. 432 /// to be executed.
357 class ExpressionStatementContinuation extends ExpressionContinuation { 433 class ExpressionStatementContinuation extends ExpressionContinuation {
358 final StatementConfiguration configuration; 434 final StatementConfiguration configuration;
359 435
360 ExpressionStatementContinuation(this.configuration); 436 ExpressionStatementContinuation(this.configuration);
361 437
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 Configuration call(Value v) { 490 Configuration call(Value v) {
415 Setter setter = receiver.class_.lookupSetter(name); 491 Setter setter = receiver.class_.lookupSetter(name);
416 setter(receiver, v); 492 setter(receiver, v);
417 return new ContinuationConfiguration(continuation, v); 493 return new ContinuationConfiguration(continuation, v);
418 } 494 }
419 } 495 }
420 496
421 /// Represents a continuation to be called after the evaluation of an actual 497 /// Represents a continuation to be called after the evaluation of an actual
422 /// argument for function invocation. 498 /// argument for function invocation.
423 /// TODO: Add checks for validation of arguments according to spec. 499 /// TODO: Add checks for validation of arguments according to spec.
424 class ActualArgumentsContinuation extends ExpressionContinuation { 500 class ActualArgumentsContinuation extends Continuation {
425 final Arguments arguments; 501 final ArgumentExpression currentArgument;
426 final FunctionNode functionNode; 502 final List<ArgumentExpression> arguments;
427 final Environment environment; 503 final Environment environment;
428 final ExpressionContinuation continuation; 504 final ApplicationContinuation applicationContinuation;
429 505
430 final List<Value> _positional = <Value>[]; 506 ActualArgumentsContinuation(this.currentArgument, this.arguments,
431 int _currentPositional = 0; 507 this.environment, this.applicationContinuation);
432 final Map<String, Value> _named = <String, Value>{};
433 int _currentNamed = 0;
434
435 ActualArgumentsContinuation(
436 this.arguments, this.functionNode, this.environment, this.continuation);
437 508
438 Configuration call(Value v) { 509 Configuration call(Value v) {
439 if (_currentPositional < arguments.positional.length) { 510 ArgumentValue argumentValue;
440 _positional.add(v); 511 if (currentArgument is NamedArgumentExpression) {
441 _currentPositional++; 512 argumentValue = new NamedArgumentValue(currentArgument.name, v);
442 } else { 513 } else {
443 assert(_currentNamed < arguments.named.length); 514 argumentValue = new PositionalArgumentValue(v);
444 String name = arguments.named[_currentNamed].name;
445 _named[name] = v;
446 _currentNamed++;
447 } 515 }
448 516
449 return createCurrentConfiguration(); 517 return new ArgumentsConfiguration(arguments, environment,
450 } 518 new ArgumentValueApplication(argumentValue, applicationContinuation));
451
452 Configuration createCurrentConfiguration() {
453 // Next argument to evaluate is a provided positional argument.
454 if (_currentPositional < arguments.positional.length) {
455 return new ExpressionConfiguration(
456 arguments.positional[_currentPositional], environment, this);
457 }
458 // Next argument to evaluate is a provided named argument.
459 if (_currentNamed < arguments.named.length) {
460 return new ExpressionConfiguration(
461 arguments.named[_currentNamed].value, environment, this);
462 }
463
464 // TODO: check if the number of actual arguments is larger then the number
465 // of required arguments and smaller then the number of formal arguments.
466
467 return new OptionalArgumentsContinuation(
468 _positional, _named, functionNode, environment, continuation)
469 .createCurrentConfiguration();
470 } 519 }
471 } 520 }
472 521
473 class OptionalArgumentsContinuation extends ExpressionContinuation { 522 /// Represents the continuation called after the evaluation of argument
474 final List<Value> positional; 523 /// expressions.
475 final Map<String, Value> named; 524 abstract class ApplicationContinuation extends Continuation {
476 final FunctionNode functionNode; 525 Configuration call(List<ArgumentValue> args);
477 final Environment environment;
478 final ExpressionContinuation continuation;
479
480 final Map<String, VariableDeclaration> _missingFormalNamed =
481 <String, VariableDeclaration>{};
482
483 int _currentPositional;
484 String _currentNamed;
485
486 OptionalArgumentsContinuation(this.positional, this.named, this.functionNode,
487 this.environment, this.continuation) {
488 _currentPositional = positional.length;
489 assert(_currentPositional >= functionNode.requiredParameterCount);
490
491 for (VariableDeclaration vd in functionNode.namedParameters) {
492 if (named[vd.name] == null) {
493 _missingFormalNamed[vd.name] = vd;
494 }
495 }
496 }
497
498 Configuration call(Value v) {
499 if (_currentPositional < functionNode.positionalParameters.length) {
500 // Value is a optional positional argument
501 positional.add(v);
502 _currentPositional++;
503 } else {
504 // Value is a optional named argument.
505 assert(named[_currentNamed] == null);
506 named[_currentNamed] = v;
507 }
508
509 return createCurrentConfiguration();
510 }
511
512 /// Creates the current configuration for the evaluation of invocation a
513 /// function.
514 Configuration createCurrentConfiguration() {
515 if (_currentPositional < functionNode.positionalParameters.length) {
516 // Next argument to evaluate is a missing positional argument.
517 // Evaluate its initializer.
518 return new ExpressionConfiguration(
519 functionNode.positionalParameters[_currentPositional].initializer,
520 environment,
521 this);
522 }
523 if (named.length < functionNode.namedParameters.length) {
524 // Next argument to evaluate is a missing named argument.
525 // Evaluate its initializer.
526 _currentNamed = _missingFormalNamed.keys.first;
527 Expression initializer = _missingFormalNamed[_currentNamed].initializer;
528 _missingFormalNamed.remove(_currentNamed);
529 return new ExpressionConfiguration(initializer, environment, this);
530 }
531
532 Environment newEnv = _createEnvironment();
533 State bodyState = new State.initial()
534 .withExpressionContinuation(continuation)
535 .withConfiguration(new ExitConfiguration(continuation))
536 .withEnvironment(newEnv);
537
538 return new StatementConfiguration(functionNode.body, bodyState);
539 }
540 526
541 /// Creates an environment binding actual argument values to formal parameters 527 /// Creates an environment binding actual argument values to formal parameters
542 /// of the function in a new environment, which is used to execute the 528 /// of the function in a new environment, which is used to execute the
543 /// body od the function. 529 /// body od the function.
544 Environment _createEnvironment() { 530 static Environment createEnvironment(
531 FunctionNode function, List<ArgumentValue> args) {
545 Environment newEnv = new Environment.empty(); 532 Environment newEnv = new Environment.empty();
533 List<PositionalArgumentValue> positional = args.reversed
534 .where((ArgumentValue av) => av is PositionalArgumentValue)
535 .toList();
536
546 // Add positional parameters. 537 // Add positional parameters.
547 for (int i = 0; i < positional.length; ++i) { 538 for (int i = 0; i < positional.length; ++i) {
548 newEnv.expand(functionNode.positionalParameters[i], positional[i]); 539 newEnv.expand(function.positionalParameters[i], positional[i].value);
549 } 540 }
541
542 Map<String, Value> named = new Map.fromIterable(
543 args.where((ArgumentValue av) => av is NamedArgumentValue),
544 key: (NamedArgumentValue av) => av.name,
545 value: (NamedArgumentValue av) => av.value);
546
550 // Add named parameters. 547 // Add named parameters.
551 for (VariableDeclaration v in functionNode.namedParameters) { 548 for (VariableDeclaration v in function.namedParameters) {
552 newEnv.expand(v, named[v.name.toString()]); 549 newEnv.expand(v, named[v.name.toString()]);
553 } 550 }
554 551
555 return newEnv; 552 return newEnv;
556 } 553 }
557 } 554 }
558 555
556 /// Represents the application continuation for static invocation.
557 class StaticInvocationApplication extends ApplicationContinuation {
558 final FunctionNode function;
559 final ExpressionContinuation continuation;
560
561 StaticInvocationApplication(this.function, this.continuation);
562
563 Configuration call(List<ArgumentValue> args) {
564 Environment functionEnv =
565 ApplicationContinuation.createEnvironment(function, args);
566
567 State bodyState = new State.initial()
568 .withExpressionContinuation(continuation)
569 .withConfiguration(new ExitConfiguration(continuation))
570 .withEnvironment(functionEnv);
571 return new StatementConfiguration(function.body, bodyState);
572 }
573 }
574
575 /// Represents the application continuation called after the evaluation of all
576 /// argument expressions for an invocation.
577 class ArgumentValueApplication extends ApplicationContinuation {
578 final ArgumentValue value;
579 final ApplicationContinuation applicationContinuation;
580
581 ArgumentValueApplication(this.value, this.applicationContinuation);
582
583 Configuration call(List<ArgumentValue> args) {
584 args.add(value);
585 return new ArgumentContinuationConfiguration(applicationContinuation, args);
586 }
587 }
588
559 class MethodInvocationContinuation extends ExpressionContinuation { 589 class MethodInvocationContinuation extends ExpressionContinuation {
560 final Arguments arguments; 590 final Arguments arguments;
561 final Name methodName; 591 final Name methodName;
562 final Environment environment; 592 final Environment environment;
563 final ExpressionContinuation continuation; 593 final ExpressionContinuation continuation;
564 594
565 MethodInvocationContinuation( 595 MethodInvocationContinuation(
566 this.arguments, this.methodName, this.environment, this.continuation); 596 this.arguments, this.methodName, this.environment, this.continuation);
567 597
568 Configuration call(Value receiver) { 598 Configuration call(Value receiver) {
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 void trampolinedExecution(Configuration configuration) { 811 void trampolinedExecution(Configuration configuration) {
782 while (configuration != null) { 812 while (configuration != null) {
783 configuration = configuration.step(this); 813 configuration = configuration.step(this);
784 } 814 }
785 } 815 }
786 816
787 Configuration exec(Statement statement, State state) => 817 Configuration exec(Statement statement, State state) =>
788 statement.accept1(this, state); 818 statement.accept1(this, state);
789 Configuration eval(Expression expression, ExpressionConfiguration config) => 819 Configuration eval(Expression expression, ExpressionConfiguration config) =>
790 evaluator.eval(expression, config); 820 evaluator.eval(expression, config);
821 Configuration evalArgs(
822 List<ArgumentExpression> args, Environment env, Continuation cont) =>
823 evaluator.evalArgs(args, env, cont);
791 824
792 Configuration defaultStatement(Statement node, State state) { 825 Configuration defaultStatement(Statement node, State state) {
793 throw notImplemented( 826 throw notImplemented(
794 m: "Execution is not implemented for statement:\n$node "); 827 m: "Execution is not implemented for statement:\n$node ");
795 } 828 }
796 829
797 Configuration visitInvalidStatement(InvalidStatement node, State state) { 830 Configuration visitInvalidStatement(InvalidStatement node, State state) {
798 throw "Invalid statement at ${node.location}"; 831 throw "Invalid statement at ${node.location}";
799 } 832 }
800 833
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 1136
1104 class NullValue extends LiteralValue { 1137 class NullValue extends LiteralValue {
1105 Object get value => null; 1138 Object get value => null;
1106 1139
1107 const NullValue(); 1140 const NullValue();
1108 } 1141 }
1109 1142
1110 notImplemented({String m, Object obj}) { 1143 notImplemented({String m, Object obj}) {
1111 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); 1144 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
1112 } 1145 }
1146
1147 // ------------------------------------------------------------------------
1148 // INTERNAL FUNCTIONS
1149 // ------------------------------------------------------------------------
1150 /// Creates a list of all argument expressions to be evaluated for the
1151 /// invocation of the provided [FunctionNode] containing the actual arguments
1152 /// and the optional argument initializers.
1153 List<ArgumentExpression> _createArgumentExpressionList(
1154 Arguments providedArgs, FunctionNode fun) {
1155 List<ArgumentExpression> args = <ArgumentExpression>[];
1156 // Add positional arguments expressions.
1157 args.addAll(providedArgs.positional
1158 .map((Expression e) => new PositionalArgumentExpression(e)));
1159
1160 // Add optional positional argument initializers.
1161 for (int i = providedArgs.positional.length;
1162 i < fun.positionalParameters.length;
1163 i++) {
1164 args.add(new PositionalArgumentExpression(
1165 fun.positionalParameters[i].initializer));
1166 }
1167
1168 Map<String, NamedArgumentExpression> namedFormals = new Map.fromIterable(
1169 fun.namedParameters,
1170 key: (VariableDeclaration vd) => vd.name,
1171 value: (VariableDeclaration vd) =>
1172 new NamedArgumentExpression(vd.name, vd.initializer));
1173
1174 // Add named expressions.
1175 for (int i = 0; i < providedArgs.named.length; i++) {
1176 var current = providedArgs.named[i];
1177 args.add(new NamedArgumentExpression(current.name, current.value));
1178 namedFormals.remove(current.name);
1179 }
1180
1181 // Add missing optional named initializers.
1182 args.addAll(namedFormals.values);
1183
1184 return args;
1185 }
OLDNEW
« 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