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

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

Issue 2999673002: Implement support for property accessors (Closed)
Patch Set: 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/object_property_access.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';
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 } 155 }
156 156
157 Configuration visitVariableSet(VariableSet node, EvalConfiguration config) { 157 Configuration visitVariableSet(VariableSet node, EvalConfiguration config) {
158 var cont = new VariableSetEK( 158 var cont = new VariableSetEK(
159 node.variable, config.environment, config.continuation); 159 node.variable, config.environment, config.continuation);
160 return new EvalConfiguration( 160 return new EvalConfiguration(
161 node.value, config.environment, config.exceptionComponents, cont); 161 node.value, config.environment, config.exceptionComponents, cont);
162 } 162 }
163 163
164 Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) { 164 Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) {
165 var cont = new PropertyGetEK(node.name, config.continuation); 165 var cont = new PropertyGetEK(
166 node.name, config.exceptionComponents, config.continuation);
166 return new EvalConfiguration( 167 return new EvalConfiguration(
167 node.receiver, config.environment, config.exceptionComponents, cont); 168 node.receiver, config.environment, config.exceptionComponents, cont);
168 } 169 }
169 170
170 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { 171 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) {
171 var cont = new PropertySetEK(node.value, node.name, config.environment, 172 var cont = new PropertySetEK(node.value, node.name, config.environment,
172 config.exceptionComponents, config.continuation); 173 config.exceptionComponents, config.continuation);
173 return new EvalConfiguration( 174 return new EvalConfiguration(
174 node.receiver, config.environment, config.exceptionComponents, cont); 175 node.receiver, config.environment, config.exceptionComponents, cont);
175 } 176 }
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 957
957 Configuration call(Value v) { 958 Configuration call(Value v) {
958 log.info('print(${v.value.runtimeType}: ${v.value})\n'); 959 log.info('print(${v.value.runtimeType}: ${v.value})\n');
959 print(v.value); 960 print(v.value);
960 return new ValuePassingConfiguration(continuation, Value.nullInstance); 961 return new ValuePassingConfiguration(continuation, Value.nullInstance);
961 } 962 }
962 } 963 }
963 964
964 class PropertyGetEK extends ExpressionContinuation { 965 class PropertyGetEK extends ExpressionContinuation {
965 final Name name; 966 final Name name;
967 final ExceptionComponents exceptionComponents;
966 final ExpressionContinuation continuation; 968 final ExpressionContinuation continuation;
967 969
968 PropertyGetEK(this.name, this.continuation); 970 PropertyGetEK(this.name, this.exceptionComponents, this.continuation);
969 971
970 Configuration call(Value receiver) { 972 Configuration call(Value receiver) {
973 if (receiver.class_.isMethod(name)) {
974 var method = receiver.class_.lookup(name);
975 // Return the function value with this bound to receiver.
976 method.location.environment =
977 new Environment.empty().extendWithThis(receiver);
978 return new ValuePassingConfiguration(continuation, method);
979 }
980
981 if (receiver.class_.isGetter(name)) {
982 var getter = receiver.class_.lookup(name);
983 var state = new State.initial()
984 .withReturnContinuation(continuation)
985 .withContinuation(new ExitSK(continuation, Value.nullInstance))
986 .withException(exceptionComponents);
987 return new ExecConfiguration(getter.function.body,
988 new Environment.empty().extendWithThis(receiver), state);
989 }
990
971 Value propertyValue = receiver.class_.lookupImplicitGetter(name)(receiver); 991 Value propertyValue = receiver.class_.lookupImplicitGetter(name)(receiver);
972 return new ValuePassingConfiguration(continuation, propertyValue); 992 return new ValuePassingConfiguration(continuation, propertyValue);
973 } 993 }
974 } 994 }
975 995
976 class PropertySetEK extends ExpressionContinuation { 996 class PropertySetEK extends ExpressionContinuation {
977 final Expression value; 997 final Expression value;
978 final Name setterName; 998 final Name setterName;
979 final Environment environment; 999 final Environment environment;
980 final ExceptionComponents exceptionComponents; 1000 final ExceptionComponents exceptionComponents;
981 final ExpressionContinuation continuation; 1001 final ExpressionContinuation continuation;
982 1002
983 PropertySetEK(this.value, this.setterName, this.environment, 1003 PropertySetEK(this.value, this.setterName, this.environment,
984 this.exceptionComponents, this.continuation); 1004 this.exceptionComponents, this.continuation);
985 1005
986 Configuration call(Value receiver) { 1006 Configuration call(Value receiver) {
987 var cont = new SetterEK(receiver, setterName, continuation); 1007 var cont =
1008 new SetterEK(receiver, setterName, exceptionComponents, continuation);
988 return new EvalConfiguration(value, environment, exceptionComponents, cont); 1009 return new EvalConfiguration(value, environment, exceptionComponents, cont);
989 } 1010 }
990 } 1011 }
991 1012
992 class SetterEK extends ExpressionContinuation { 1013 class SetterEK extends ExpressionContinuation {
993 final Value receiver; 1014 final Value receiver;
994 final Name name; 1015 final Name name;
1016 final ExceptionComponents exceptionComponents;
995 final ExpressionContinuation continuation; 1017 final ExpressionContinuation continuation;
996 1018
997 SetterEK(this.receiver, this.name, this.continuation); 1019 SetterEK(
1020 this.receiver, this.name, this.exceptionComponents, this.continuation);
998 1021
999 Configuration call(Value v) { 1022 Configuration call(Value v) {
1023 if (receiver.class_.isSetter(name)) {
1024 var setter = receiver.class_.lookup(name);
1025 var env = new Environment.empty()
1026 .extendWithThis(receiver)
1027 .extend(setter.function.positionalParameters.first, v);
1028 var state = new State.initial()
1029 .withReturnContinuation(continuation)
1030 .withContinuation(new ExitSK(continuation, Value.nullInstance))
1031 .withException(exceptionComponents);
1032 return new ExecConfiguration(setter.function.body, env, state);
1033 }
1034
1000 Setter setter = receiver.class_.lookupImplicitSetter(name); 1035 Setter setter = receiver.class_.lookupImplicitSetter(name);
1001 setter(receiver, v); 1036 setter(receiver, v);
1002 return new ValuePassingConfiguration(continuation, v); 1037 return new ValuePassingConfiguration(continuation, v);
1003 } 1038 }
1004 } 1039 }
1005 1040
1006 /// Represents a continuation to be called after the evaluation of an actual 1041 /// Represents a continuation to be called after the evaluation of an actual
1007 /// argument for function invocation. 1042 /// argument for function invocation.
1008 class ExpressionListEK extends ExpressionContinuation { 1043 class ExpressionListEK extends ExpressionContinuation {
1009 final InterpreterExpression currentExpression; 1044 final InterpreterExpression currentExpression;
(...skipping 17 matching lines...) Expand all
1027 final Arguments arguments; 1062 final Arguments arguments;
1028 final Name methodName; 1063 final Name methodName;
1029 final Environment environment; 1064 final Environment environment;
1030 final ExceptionComponents exceptionComponents; 1065 final ExceptionComponents exceptionComponents;
1031 final ExpressionContinuation continuation; 1066 final ExpressionContinuation continuation;
1032 1067
1033 MethodInvocationEK(this.arguments, this.methodName, this.environment, 1068 MethodInvocationEK(this.arguments, this.methodName, this.environment,
1034 this.exceptionComponents, this.continuation); 1069 this.exceptionComponents, this.continuation);
1035 1070
1036 Configuration call(Value receiver) { 1071 Configuration call(Value receiver) {
1037 if (receiver is FunctionValue) { 1072 if (receiver is LiteralValue) {
1038 // TODO(zhivkag): use method lookup instead. 1073 // TODO(zhivkag): CPS method invocation for literals
1039 assert(methodName.toString() == 'call'); 1074 if (arguments.positional.isEmpty) {
1040 var args = _getArgumentExpressions(arguments, receiver.function); 1075 Value returnValue = receiver.invokeMethod(methodName);
1041 var acont = 1076 return new ValuePassingConfiguration(continuation, returnValue);
1042 new FunctionValueA(receiver, exceptionComponents, continuation); 1077 }
1043 return new EvalListConfiguration( 1078 var cont = new ArgumentsEK(
1044 args, environment, exceptionComponents, acont); 1079 receiver, methodName, arguments, environment, continuation);
1080
1081 return new EvalConfiguration(
1082 arguments.positional.first, environment, exceptionComponents, cont);
1045 } 1083 }
1046 1084
1047 if (arguments.positional.isEmpty) { 1085 FunctionValue fun;
1048 Value returnValue = receiver.invokeMethod(methodName); 1086 if (receiver is FunctionValue) {
1049 return new ValuePassingConfiguration(continuation, returnValue); 1087 assert(methodName.toString() == "call");
Dmitry Stefantsov 2017/08/16 08:48:55 Maybe it's better to throw an exception here using
zhivkag 2017/08/16 09:39:49 Added a TODO.
1088 fun = receiver;
1089 } else {
1090 assert(receiver.class_.isMethod(methodName));
1091 fun = receiver.class_.lookup(methodName);
1092 fun.location.environment =
1093 new Environment.empty().extendWithThis(receiver);
1050 } 1094 }
1051 var cont = new ArgumentsEK(
1052 receiver, methodName, arguments, environment, continuation);
1053 1095
1054 return new EvalConfiguration( 1096 var args = _getArgumentExpressions(arguments, fun.function);
1055 arguments.positional.first, environment, exceptionComponents, cont); 1097 var acont = new FunctionValueA(receiver, exceptionComponents, continuation);
1098 return new EvalListConfiguration(
1099 args, environment, exceptionComponents, acont);
1056 } 1100 }
1057 } 1101 }
1058 1102
1059 class ArgumentsEK extends ExpressionContinuation { 1103 class ArgumentsEK extends ExpressionContinuation {
1060 final Value receiver; 1104 final Value receiver;
1061 final Name methodName; 1105 final Name methodName;
1062 final Arguments arguments; 1106 final Arguments arguments;
1063 final Environment environment; 1107 final Environment environment;
1064 final ExpressionContinuation continuation; 1108 final ExpressionContinuation continuation;
1065 1109
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after
1695 Getter getter = implicitGetters[name]; 1739 Getter getter = implicitGetters[name];
1696 if (getter != null) return getter; 1740 if (getter != null) return getter;
1697 if (superclass != null) return superclass.lookupImplicitGetter(name); 1741 if (superclass != null) return superclass.lookupImplicitGetter(name);
1698 return (Value receiver) => notImplemented(obj: name); 1742 return (Value receiver) => notImplemented(obj: name);
1699 } 1743 }
1700 1744
1701 Setter lookupImplicitSetter(Name name) { 1745 Setter lookupImplicitSetter(Name name) {
1702 Setter setter = implicitSetters[name]; 1746 Setter setter = implicitSetters[name];
1703 if (setter != null) return setter; 1747 if (setter != null) return setter;
1704 if (superclass != null) return superclass.lookupImplicitSetter(name); 1748 if (superclass != null) return superclass.lookupImplicitSetter(name);
1749 // todo: throw NoSuchInstance error instead.
Dmitry Stefantsov 2017/08/16 08:48:55 todo ==> TODO
zhivkag 2017/08/16 09:39:49 Done.
1705 return (Value receiver, Value value) => notImplemented(obj: name); 1750 return (Value receiver, Value value) => notImplemented(obj: name);
1706 } 1751 }
1707 1752
1753 FunctionValue lookup(Name name) {
1754 var fun = methods[name]?.function;
1755 assert(fun != null);
1756 return new FunctionValue(fun, new EnvironmentLocation.empty());
1757 }
1758
1759 bool isGetter(Name name) => methods[name]?.isGetter ?? false;
1760 bool isSetter(Name name) => methods[name]?.isSetter ?? false;
1761 bool isMethod(Name name) => !(methods[name]?.isAccessor ?? true);
1762
1708 /// Populates implicit getters and setters for the current class and its 1763 /// Populates implicit getters and setters for the current class and its
1709 /// superclass recursively. 1764 /// superclass recursively.
1710 _populateImplicitGettersAndSetters(ast.Class class_) { 1765 _populateImplicitGettersAndSetters(ast.Class class_) {
1711 if (class_.superclass != null) { 1766 if (class_.superclass != null) {
1712 _populateImplicitGettersAndSetters(class_.superclass); 1767 _populateImplicitGettersAndSetters(class_.superclass);
1713 } 1768 }
1714 1769
1715 for (Field f in class_.fields) { 1770 for (Field f in class_.fields) {
1716 if (f.isStatic) continue; 1771 if (f.isStatic) continue;
1717 assert(f.hasImplicitGetter); 1772 assert(f.hasImplicitGetter);
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1954 /// Initializes all non initialized fields from the provided class to 2009 /// Initializes all non initialized fields from the provided class to
1955 /// `Value.nullInstance` in the provided value. 2010 /// `Value.nullInstance` in the provided value.
1956 void _initializeNullFields(Class class_, Value value) { 2011 void _initializeNullFields(Class class_, Value value) {
1957 int startIndex = class_.superclass?.instanceSize ?? 0; 2012 int startIndex = class_.superclass?.instanceSize ?? 0;
1958 for (int i = startIndex; i < class_.instanceSize; i++) { 2013 for (int i = startIndex; i < class_.instanceSize; i++) {
1959 if (value.fields[i].value == null) { 2014 if (value.fields[i].value == null) {
1960 value.fields[i].value = Value.nullInstance; 2015 value.fields[i].value = Value.nullInstance;
1961 } 2016 }
1962 } 2017 }
1963 } 2018 }
OLDNEW
« no previous file with comments | « no previous file | pkg/kernel/testcases/interpreter/object_property_access.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698