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

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

Issue 2764073002: Add support for implicit getters and setters (Closed)
Patch Set: Remove static get from Value Created 3 years, 9 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 ea8f0186d1caf2ce425e50666a9d2a3f7bbae838..e31da20022e06f17cc546b39cd4807ce8d213c5d 100644
--- a/pkg/kernel/lib/interpreter/interpreter.dart
+++ b/pkg/kernel/lib/interpreter/interpreter.dart
@@ -119,6 +119,31 @@ class Evaluator extends ExpressionVisitor1<Value> {
return env.assign(node.variable, eval(node.value, env));
}
+ Value visitPropertyGet(PropertyGet node, env) {
+ ObjectValue receiver = eval(node.receiver, env);
Kevin Millikin (Google) 2017/03/23 10:42:51 We have to support property get on things like int
zhivkag 2017/03/23 13:50:39 Indeed, thanks! Done.
+ return receiver.propertyGet(node.name);
Kevin Millikin (Google) 2017/03/23 10:42:50 I suggest we factor this slightly differently: 1.
zhivkag 2017/03/23 13:50:38 Done.
+ }
+
+ Value visitPropertySet(PropertySet node, env) {
+ ObjectValue receiver = eval(node.receiver, env);
+ Value value = eval(node.value, env);
+ return receiver.propertySet(node.name, value);
+ }
+
+ Value visitDirectPropertyGet(DirectPropertyGet node, env) {
+ ObjectValue receiver = eval(node.receiver, env);
+ return receiver.directPropertyGet(node.target);
+ }
+
+ Value visitDirectPropertySet(DirectPropertySet node, env) {
+ ObjectValue receiver = eval(node.receiver, env);
+ Value value = eval(node.value, env);
+ return receiver.directPropertySet(node.target, value);
+ }
+
+ Value visitStaticGet(StaticGet node, env) => defaultExpression(node, env);
+ Value visitStaticSet(StaticSet node, env) => defaultExpression(node, env);
+
Value visitStaticInvocation(StaticInvocation node, env) {
if ('print' == node.name.toString()) {
// Special evaluation of print.
@@ -137,14 +162,27 @@ class Evaluator extends ExpressionVisitor1<Value> {
var receiver = eval(node.receiver, env);
if (node.arguments.positional.isNotEmpty) {
var argValue = eval(node.arguments.positional.first, env);
- return receiver.invokeMethod(node.name.name, argValue);
+ return receiver.invokeMethod(node.name, argValue);
} else {
- return receiver.invokeMethod(node.name.name);
+ return receiver.invokeMethod(node.name);
}
}
- Value visitConstructorInvocation(ConstructorInvocation node, env) =>
- defaultExpression(node, env);
+ Value visitConstructorInvocation(ConstructorInvocation node, env) {
+ ClassDeclaration classDeclaration =
+ new ClassDeclaration(node.target.enclosingClass.reference);
+
+ Environment emptyEnv = new Environment.empty();
+ // Currently we don't support initializers.
+ // TODO: Modify to respect dart semantics for initialization.
+ // 1. Init fields and eval initializers, repeat the same with super.
+ // 2. Eval the Function body of the constructor.
+ List<Value> fields = classDeclaration.instanceFields
+ .map((Field f) => eval(f.initializer, emptyEnv))
+ .toList(growable: false);
+
+ return new ObjectValue(classDeclaration, fields);
+ }
Value visitNot(Not node, env) {
Value operand = eval(node.operand, env).toBoolean();
@@ -207,13 +245,16 @@ class ClassDeclaration {
static final Map<Reference, ClassDeclaration> _classes =
<Reference, ClassDeclaration>{};
- Class currentClass;
- ClassDeclaration superClass;
+ Class superClass;
Kevin Millikin (Google) 2017/03/23 10:42:51 We might not agree, but superclass is one word in
zhivkag 2017/03/23 13:50:38 Done.
+ List<Field> instanceFields = <Field>[];
+ List<Field> staticFields = <Field>[];
+ // Implicit getters and setters for instance Fields.
+ Map<Name, int> getters = <Name, int>{};
Kevin Millikin (Google) 2017/03/23 10:42:51 Thinking ahead, this needs to map names to getters
zhivkag 2017/03/23 13:50:38 Done.
+ Map<Name, int> setters = <Name, int>{};
// The initializers of static fields are evaluated the first time the field
// is accessed.
- List<Value> staticFields = <Value>[];
- List<Procedure> getters = <Procedure>[];
- List<Procedure> setters = <Procedure>[];
+ List<Value> staticFieldValues = <Value>[];
+
List<Procedure> methods = <Procedure>[];
factory ClassDeclaration(Reference classRef) {
@@ -224,11 +265,80 @@ class ClassDeclaration {
return _classes[classRef];
}
- ClassDeclaration._internal(this.currentClass) {
+ ClassDeclaration._internal(Class currentClass) {
if (currentClass.superclass != null) {
- superClass = new ClassDeclaration(currentClass.superclass.reference);
+ superClass = currentClass.superclass;
+ }
+
+ _populateInstanceFields(currentClass);
+
+ // Populate implicit setters and getters.
+ for (int i = 0; i < instanceFields.length; i++) {
+ Field f = instanceFields[i];
+ assert(f.hasImplicitGetter);
+ getters[f.name] = i;
Kevin Millikin (Google) 2017/03/23 10:42:51 So the getter function should be: getters[f.name]
zhivkag 2017/03/23 13:50:38 Done.
+ if (f.hasImplicitSetter) {
+ setters[f.name] = i;
+ }
+ }
+ // TODO: Populate methods.
+ }
+
+ Value propertyGet(ObjectValue object, Name name) {
Kevin Millikin (Google) 2017/03/23 10:42:51 The name should be the verb form: getProperty.
zhivkag 2017/03/23 13:50:38 Done.
+ if (getters.containsKey(name)) {
Kevin Millikin (Google) 2017/03/23 10:42:51 We should look in the superclass for a getter. If
zhivkag 2017/03/23 13:50:38 Makes sense, thanks! Done.
+ return (object.fields)[getters[name]];
+ }
+ // TODO: return NoSuchMethod if Name is not a Getter or Method tear-off
+ return notImplemented(obj: name);
+ }
+
+ Value propertySet(ObjectValue object, Name name, Value value) {
Kevin Millikin (Google) 2017/03/23 10:42:51 Likewise, I's split this into looking up the sette
zhivkag 2017/03/23 13:50:39 Applied the suggestion but I have a doubt whether
+ if (setters.containsKey(name)) {
+ object.fields[setters[name]] = value;
+ }
+ // TODO: return NoSuchMethodError if Name is not a Setter.
+ return Value.nullInstance;
+ }
+
+ Value directPropertyGet(ObjectValue object, Member member) {
+ if (member is Field) {
+ for (int i = 0; i < instanceFields.length; i++) {
+ if (identical(member, instanceFields[i])) {
+ return object.fields[i];
+ }
+ }
+ // TODO: throw NoSuchMethodError instead.
+ return notImplemented(m: 'NoSuchMethod: Field ${member} not found.');
+ }
+ return notImplemented(obj: member);
+ }
+
+ Value directPropertySet(ObjectValue object, Member member, Value value) {
+ if (member is Field) {
+ for (int i = 0; i < instanceFields.length; i++) {
+ if (identical(member, instanceFields[i])) {
+ object.fields[i] = value;
+ }
+ return Value.nullInstance;
+ }
+ // TODO: throw NoSuchMethodError instead.
+ return notImplemented(m: 'NoSuchMethod: Field $member not found.');
+ }
+ return notImplemented(obj: member);
+ }
+
+ // Populates with the instance fields of the current class and all its
+ // superclasses recursively.
+ _populateInstanceFields(Class class_) {
+ for (Field f in class_.fields) {
+ if (f.isInstanceMember) {
+ instanceFields.add(f);
+ }
+ }
+
+ if (class_.superclass != null) {
+ _populateInstanceFields(class_.superclass);
}
- // TODO: Populate getters, setters and methods.
}
}
@@ -250,7 +360,7 @@ abstract class Value {
BoolValue equals(Value other) =>
value == other.value ? Value.trueInstance : Value.falseInstance;
- Value invokeMethod(String name, [Value arg]) {
+ Value invokeMethod(Name name, [Value arg]) {
throw notImplemented(obj: name);
}
}
@@ -261,12 +371,19 @@ class ObjectValue extends Value {
Object get value => this;
- ObjectValue(Constructor constructor, Environment env) {
- // TODO: Init fields and eval initializers, repeat the same with super.
- // TODO: Eval the Function body of the constructor, with env expanded with
- // {VariableDeclaration("this") => this}
- notImplemented(obj: constructor.name);
+ ObjectValue(this.classDeclaration, this.fields);
+
+ Value propertyGet(Name name) {
+ return classDeclaration.propertyGet(this, name);
}
+
+ Value propertySet(Name name, Value value) =>
+ classDeclaration.propertySet(this, name, value);
+
+ Value directPropertyGet(Member member) =>
+ classDeclaration.directPropertyGet(this, member);
+ Value directPropertySet(Member member, Value value) =>
+ classDeclaration.directPropertySet(this, member, value);
}
class StringValue extends Value {
@@ -279,11 +396,11 @@ class StringValue extends Value {
StringValue(this.value);
- Value invokeMethod(String name, [Value arg]) {
- if (!operators.containsKey(name)) {
+ Value invokeMethod(Name name, [Value arg]) {
+ if (!operators.containsKey(name.name)) {
return notImplemented(obj: name);
}
- return operators[name](this, arg);
+ return operators[name.name](this, arg);
}
// Operators
@@ -313,10 +430,10 @@ abstract class NumValue extends Value {
'unary-': (NumValue v1) => -v1,
};
- Value invokeMethod(String name, [Value arg]) {
- if (!operators.containsKey(name)) return notImplemented(obj: name);
- if (arg == null) return operators[name](this);
- return operators[name](this, arg);
+ Value invokeMethod(Name name, [Value arg]) {
+ if (!operators.containsKey(name.name)) return notImplemented(obj: name);
+ if (arg == null) return operators[name.name](this);
+ return operators[name.name](this, arg);
}
// Operators
« 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