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

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

Issue 2997563002: Implement support for static accessors (Closed)
Patch Set: Fix execution of setter body Created 3 years, 4 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 | pkg/kernel/testcases/interpreter/static_accessors.dart » ('j') | 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';
11 11
12 class NotImplemented { 12 class NotImplemented {
13 String message; 13 String message;
14 14
15 NotImplemented(this.message); 15 NotImplemented(this.message);
16 16
17 String toString() => message; 17 String toString() => message;
18 } 18 }
19 19
20 class Interpreter { 20 class Interpreter {
21 Program program; 21 Program program;
22 StatementExecuter visitor = new StatementExecuter(); 22 StatementExecuter visitor = new StatementExecuter();
23 23
24 static MainEnvironment mainEnvironment = new MainEnvironment();
25
24 Interpreter(this.program); 26 Interpreter(this.program);
25 27
26 void run() { 28 void run() {
27 assert(program.libraries.isEmpty); 29 assert(program.libraries.isEmpty);
28 Procedure mainMethod = program.mainMethod; 30 Procedure mainMethod = program.mainMethod;
29 31
30 if (mainMethod == null) return; 32 if (mainMethod == null) return;
31 33
32 Statement statementBlock = mainMethod.function.body; 34 Statement statementBlock = mainMethod.function.body;
33 ExecConfiguration configuration = new ExecConfiguration( 35 ExecConfiguration configuration = new ExecConfiguration(
(...skipping 16 matching lines...) Expand all
50 EnvironmentLocation(this.environment); 52 EnvironmentLocation(this.environment);
51 } 53 }
52 54
53 class Binding { 55 class Binding {
54 final VariableDeclaration variable; 56 final VariableDeclaration variable;
55 final Location location; 57 final Location location;
56 58
57 Binding(this.variable, this.location); 59 Binding(this.variable, this.location);
58 } 60 }
59 61
62 class MainEnvironment {
63 Map<Member, Location> _staticFields = <Member, Location>{};
64
65 bool contains(Member member) => _staticFields[member] != null;
66
67 Value lookup(Member member) {
68 assert(contains(member));
69 return _staticFields[member].value;
70 }
71
72 void update(Member member, Value value) {
Dmitry Stefantsov 2017/08/16 08:25:39 I would add a comment that [MainEnvironment] insta
73 if (_staticFields[member] == null) {
74 _staticFields[member] = new Location(value);
75 } else {
76 _staticFields[member].value = value;
77 }
78 }
79 }
80
60 class Environment { 81 class Environment {
61 final List<Binding> bindings = <Binding>[]; 82 final List<Binding> bindings = <Binding>[];
62 final Environment parent; 83 final Environment parent;
63 84
64 Value get thisInstance { 85 Value get thisInstance {
65 return containsThis() 86 return containsThis()
66 ? lookupThis().value 87 ? lookupThis().value
67 : throw "Invalid reference to 'this' expression"; 88 : throw "Invalid reference to 'this' expression";
68 } 89 }
69 90
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 node.receiver, config.environment, config.exceptionComponents, cont); 188 node.receiver, config.environment, config.exceptionComponents, cont);
168 } 189 }
169 190
170 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { 191 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) {
171 var cont = new PropertySetEK(node.value, node.name, config.environment, 192 var cont = new PropertySetEK(node.value, node.name, config.environment,
172 config.exceptionComponents, config.continuation); 193 config.exceptionComponents, config.continuation);
173 return new EvalConfiguration( 194 return new EvalConfiguration(
174 node.receiver, config.environment, config.exceptionComponents, cont); 195 node.receiver, config.environment, config.exceptionComponents, cont);
175 } 196 }
176 197
177 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) => 198 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) {
178 defaultExpression(node, config); 199 Member member = node.target;
179 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) => 200
180 defaultExpression(node, config); 201 if (member is Procedure && !member.isAccessor) {
202 // Create a closure for the method tear off.
203 var v = new FunctionValue(
204 member.function, new EnvironmentLocation(new Environment.empty()));
205 return new ValuePassingConfiguration(config.continuation, v);
206 }
207
208 if (member is Procedure && member.isGetter) {
209 // Execute the body of the getter.
210 var state = new State.initial()
211 .withReturnContinuation(config.continuation)
212 .withContinuation(new ExitSK(config.continuation, Value.nullInstance))
213 .withException(config.exceptionComponents);
214 return new ExecConfiguration(
215 member.function.body, new Environment.empty(), state);
216 }
217
218 assert(member is Field);
219 if (Interpreter.mainEnvironment.contains(member)) {
Dmitry Stefantsov 2017/08/16 08:25:39 I would use a special value to indicate that the s
220 // Read the value for the member in the main environment.
221 return new ValuePassingConfiguration(
222 config.continuation, Interpreter.mainEnvironment.lookup(member));
223 }
224
225 // Otherwise, the static field is accessed for the first time.
226 // We store `Value.nullInstance` if there the field doesn't have an
227 // initializer.
228 if ((member as Field).initializer == null) {
229 Interpreter.mainEnvironment.update(member, Value.nullInstance);
Dmitry Stefantsov 2017/08/16 08:25:39 If the special value for uninitialized variables h
230 return new ValuePassingConfiguration(
231 config.continuation, Value.nullInstance);
232 }
233
234 // The initializer expression is evaluated otherwise.
235 var cont = new StaticSetEK(member, config.continuation);
236 return new EvalConfiguration((member as Field).initializer,
237 new Environment.empty(), config.exceptionComponents, cont);
238 }
239
240 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) {
241 Member member = node.target;
242 ExpressionContinuation cont;
243
244 if (member is Procedure) {
245 assert(member.isSetter);
246 cont = new StaticSetterEK(
247 member.function, config.exceptionComponents, config.continuation);
248 } else {
249 assert(member is Field);
250 cont = new StaticSetEK(member, config.continuation);
251 }
252
253 return new EvalConfiguration(
254 node.value, config.environment, config.exceptionComponents, cont);
255 }
181 256
182 Configuration visitStaticInvocation( 257 Configuration visitStaticInvocation(
183 StaticInvocation node, EvalConfiguration config) { 258 StaticInvocation node, EvalConfiguration config) {
184 if ('print' == node.name.toString()) { 259 if ('print' == node.name.toString()) {
185 var cont = new PrintEK(config.continuation); 260 var cont = new PrintEK(config.continuation);
186 return new EvalConfiguration(node.arguments.positional.first, 261 return new EvalConfiguration(node.arguments.positional.first,
187 config.environment, config.exceptionComponents, cont); 262 config.environment, config.exceptionComponents, cont);
188 } else { 263 } else {
189 log.info('static-invocation-${node.target.name.toString()}\n'); 264 log.info('static-invocation-${node.target.name.toString()}\n');
190 265
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 } 497 }
423 498
424 /// Configuration for execution of a [Statement]. 499 /// Configuration for execution of a [Statement].
425 class ExecConfiguration extends Configuration { 500 class ExecConfiguration extends Configuration {
426 final Statement currentStatement; 501 final Statement currentStatement;
427 final Environment environment; 502 final Environment environment;
428 final State state; 503 final State state;
429 504
430 ExecConfiguration(this.currentStatement, this.environment, this.state); 505 ExecConfiguration(this.currentStatement, this.environment, this.state);
431 506
432 Configuration step(StatementExecuter executer) => 507 Configuration step(StatementExecuter executer) {
433 executer.exec(currentStatement, this); 508 return executer.exec(currentStatement, this);
509 }
434 } 510 }
435 511
436 /// Configuration for applying a [StatementContinuation] to an [Environment]. 512 /// Configuration for applying a [StatementContinuation] to an [Environment].
437 class ForwardConfiguration extends Configuration { 513 class ForwardConfiguration extends Configuration {
438 final StatementContinuation continuation; 514 final StatementContinuation continuation;
439 final Environment environment; 515 final Environment environment;
440 516
441 ForwardConfiguration(this.continuation, this.environment); 517 ForwardConfiguration(this.continuation, this.environment);
442 518
443 Configuration step(StatementExecuter _) => continuation?.call(environment); 519 Configuration step(StatementExecuter _) => continuation?.call(environment);
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 1072
997 SetterEK(this.receiver, this.name, this.continuation); 1073 SetterEK(this.receiver, this.name, this.continuation);
998 1074
999 Configuration call(Value v) { 1075 Configuration call(Value v) {
1000 Setter setter = receiver.class_.lookupImplicitSetter(name); 1076 Setter setter = receiver.class_.lookupImplicitSetter(name);
1001 setter(receiver, v); 1077 setter(receiver, v);
1002 return new ValuePassingConfiguration(continuation, v); 1078 return new ValuePassingConfiguration(continuation, v);
1003 } 1079 }
1004 } 1080 }
1005 1081
1082 class StaticSetEK extends ExpressionContinuation {
1083 final Member member;
1084 final ExpressionContinuation continuation;
1085
1086 StaticSetEK(this.member, this.continuation);
1087
1088 Configuration call(Value v) {
1089 Interpreter.mainEnvironment.update(member, v);
1090 return new ValuePassingConfiguration(continuation, v);
1091 }
1092 }
1093
1094 class StaticSetterEK extends ExpressionContinuation {
1095 final FunctionNode setter;
1096 final ExceptionComponents exceptionComponents;
1097 final ExpressionContinuation expressionContinuation;
1098
1099 StaticSetterEK(
1100 this.setter, this.exceptionComponents, this.expressionContinuation);
1101
1102 Configuration call(Value v) {
1103 VariableDeclaration arg = setter.positionalParameters.first;
1104 var env = new Environment.empty().extend(arg, v);
1105 var state = new State.initial()
1106 .withException(exceptionComponents)
1107 .withReturnContinuation(expressionContinuation)
1108 .withContinuation(
1109 new ExitSK(expressionContinuation, Value.nullInstance));
1110
1111 return new ExecConfiguration(setter.body, env, state);
1112 }
1113 }
1114
1006 /// Represents a continuation to be called after the evaluation of an actual 1115 /// Represents a continuation to be called after the evaluation of an actual
1007 /// argument for function invocation. 1116 /// argument for function invocation.
1008 class ExpressionListEK extends ExpressionContinuation { 1117 class ExpressionListEK extends ExpressionContinuation {
1009 final InterpreterExpression currentExpression; 1118 final InterpreterExpression currentExpression;
1010 final List<InterpreterExpression> expressions; 1119 final List<InterpreterExpression> expressions;
1011 final Environment environment; 1120 final Environment environment;
1012 final ExceptionComponents exceptionComponents; 1121 final ExceptionComponents exceptionComponents;
1013 final ApplicationContinuation applicationContinuation; 1122 final ApplicationContinuation applicationContinuation;
1014 1123
1015 ExpressionListEK(this.currentExpression, this.expressions, this.environment, 1124 ExpressionListEK(this.currentExpression, this.expressions, this.environment,
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
1534 return new EvalConfiguration(node.expression, conf.environment, 1643 return new EvalConfiguration(node.expression, conf.environment,
1535 conf.state.exceptionComponents, cont); 1644 conf.state.exceptionComponents, cont);
1536 } 1645 }
1537 1646
1538 Configuration visitBlock(Block node, ExecConfiguration conf) { 1647 Configuration visitBlock(Block node, ExecConfiguration conf) {
1539 if (node.statements.isEmpty) { 1648 if (node.statements.isEmpty) {
1540 return new ForwardConfiguration( 1649 return new ForwardConfiguration(
1541 conf.state.continuation, conf.environment); 1650 conf.state.continuation, conf.environment);
1542 } 1651 }
1543 1652
1544 var env = new Environment(conf.environment);
1545 var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf); 1653 var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf);
1546 return new ExecConfiguration( 1654 return new ExecConfiguration(node.statements.first, conf.environment,
1547 node.statements.first, env, conf.state.withContinuation(cont)); 1655 conf.state.withContinuation(cont));
1548 } 1656 }
1549 1657
1550 Configuration visitEmptyStatement( 1658 Configuration visitEmptyStatement(
1551 EmptyStatement node, ExecConfiguration conf) { 1659 EmptyStatement node, ExecConfiguration conf) {
1552 return new ForwardConfiguration(conf.state.continuation, conf.environment); 1660 return new ForwardConfiguration(conf.state.continuation, conf.environment);
1553 } 1661 }
1554 1662
1555 Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) { 1663 Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) {
1556 var cont = new IfConditionEK( 1664 var cont = new IfConditionEK(
1557 node.then, node.otherwise, conf.environment, conf.state); 1665 node.then, node.otherwise, conf.environment, conf.state);
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
1954 /// Initializes all non initialized fields from the provided class to 2062 /// Initializes all non initialized fields from the provided class to
1955 /// `Value.nullInstance` in the provided value. 2063 /// `Value.nullInstance` in the provided value.
1956 void _initializeNullFields(Class class_, Value value) { 2064 void _initializeNullFields(Class class_, Value value) {
1957 int startIndex = class_.superclass?.instanceSize ?? 0; 2065 int startIndex = class_.superclass?.instanceSize ?? 0;
1958 for (int i = startIndex; i < class_.instanceSize; i++) { 2066 for (int i = startIndex; i < class_.instanceSize; i++) {
1959 if (value.fields[i].value == null) { 2067 if (value.fields[i].value == null) {
1960 value.fields[i].value = Value.nullInstance; 2068 value.fields[i].value = Value.nullInstance;
1961 } 2069 }
1962 } 2070 }
1963 } 2071 }
OLDNEW
« no previous file with comments | « no previous file | pkg/kernel/testcases/interpreter/static_accessors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698