Index: pkg/kernel/lib/interpreter/interpreter.dart |
diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart |
index 6007a946ac7f17010d482626fede668df43528a8..7f26686d624cb96d621f22b23513e5fcf5e7cee4 100644 |
--- a/pkg/kernel/lib/interpreter/interpreter.dart |
+++ b/pkg/kernel/lib/interpreter/interpreter.dart |
@@ -185,7 +185,8 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { |
} |
Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) { |
- var cont = new PropertyGetEK(node.name, config.continuation); |
+ var cont = new PropertyGetEK( |
+ node.name, config.exceptionComponents, config.continuation); |
return new EvalConfiguration( |
node.receiver, config.environment, config.exceptionComponents, cont); |
} |
@@ -1040,11 +1041,30 @@ class PrintEK extends ExpressionContinuation { |
class PropertyGetEK extends ExpressionContinuation { |
final Name name; |
+ final ExceptionComponents exceptionComponents; |
final ExpressionContinuation continuation; |
- PropertyGetEK(this.name, this.continuation); |
+ PropertyGetEK(this.name, this.exceptionComponents, this.continuation); |
Configuration call(Value receiver) { |
+ if (receiver.class_.isMethod(name)) { |
+ var method = receiver.class_.lookup(name); |
+ // Return the function value with this bound to receiver. |
+ var env = new Environment.empty().extendWithThis(receiver); |
+ return new ValuePassingConfiguration( |
+ continuation, new FunctionValue(method, env)); |
+ } |
+ |
+ if (receiver.class_.isGetter(name)) { |
+ var getter = receiver.class_.lookup(name); |
+ var state = new State.initial() |
+ .withReturnContinuation(continuation) |
+ .withContinuation(new ExitSK(continuation, Value.nullInstance)) |
+ .withException(exceptionComponents); |
+ return new ExecConfiguration( |
+ getter.body, new Environment.empty().extendWithThis(receiver), state); |
+ } |
+ |
Value propertyValue = receiver.class_.lookupImplicitGetter(name)(receiver); |
return new ValuePassingConfiguration(continuation, propertyValue); |
} |
@@ -1061,7 +1081,8 @@ class PropertySetEK extends ExpressionContinuation { |
this.exceptionComponents, this.continuation); |
Configuration call(Value receiver) { |
- var cont = new SetterEK(receiver, setterName, continuation); |
+ var cont = |
+ new SetterEK(receiver, setterName, exceptionComponents, continuation); |
return new EvalConfiguration(value, environment, exceptionComponents, cont); |
} |
} |
@@ -1069,11 +1090,25 @@ class PropertySetEK extends ExpressionContinuation { |
class SetterEK extends ExpressionContinuation { |
final Value receiver; |
final Name name; |
+ final ExceptionComponents exceptionComponents; |
final ExpressionContinuation continuation; |
- SetterEK(this.receiver, this.name, this.continuation); |
+ SetterEK( |
+ this.receiver, this.name, this.exceptionComponents, this.continuation); |
Configuration call(Value v) { |
+ if (receiver.class_.isSetter(name)) { |
+ var setter = receiver.class_.lookup(name); |
+ var env = new Environment.empty() |
+ .extendWithThis(receiver) |
+ .extend(setter.positionalParameters.first, v); |
+ var state = new State.initial() |
+ .withReturnContinuation(continuation) |
+ .withContinuation(new ExitSK(continuation, Value.nullInstance)) |
+ .withException(exceptionComponents); |
+ return new ExecConfiguration(setter.body, env, state); |
+ } |
+ |
Setter setter = receiver.class_.lookupImplicitSetter(name); |
setter(receiver, v); |
return new ValuePassingConfiguration(continuation, v); |
@@ -1144,25 +1179,34 @@ class MethodInvocationEK extends ExpressionContinuation { |
this.exceptionComponents, this.continuation); |
Configuration call(Value receiver) { |
- if (receiver is FunctionValue) { |
- // TODO(zhivkag): use method lookup instead. |
- assert(methodName.toString() == 'call'); |
- var args = _getArgumentExpressions(arguments, receiver.function); |
- var acont = |
- new FunctionValueA(receiver, exceptionComponents, continuation); |
- return new EvalListConfiguration( |
- args, environment, exceptionComponents, acont); |
+ if (receiver is LiteralValue) { |
+ // TODO(zhivkag): CPS method invocation for literals |
+ if (arguments.positional.isEmpty) { |
+ Value returnValue = receiver.invokeMethod(methodName); |
+ return new ValuePassingConfiguration(continuation, returnValue); |
+ } |
+ var cont = new ArgumentsEK( |
+ receiver, methodName, arguments, environment, continuation); |
+ |
+ return new EvalConfiguration( |
+ arguments.positional.first, environment, exceptionComponents, cont); |
} |
- if (arguments.positional.isEmpty) { |
- Value returnValue = receiver.invokeMethod(methodName); |
- return new ValuePassingConfiguration(continuation, returnValue); |
+ FunctionValue fun; |
+ if (receiver is FunctionValue) { |
+ // TODO(zhivkag): Throw an exception when method is not call. |
+ assert(methodName.toString() == "call"); |
+ fun = receiver; |
+ } else { |
+ assert(receiver.class_.isMethod(methodName)); |
+ fun = new FunctionValue(receiver.class_.lookup(methodName), |
+ new Environment.empty().extendWithThis(receiver)); |
} |
- var cont = new ArgumentsEK( |
- receiver, methodName, arguments, environment, continuation); |
- return new EvalConfiguration( |
- arguments.positional.first, environment, exceptionComponents, cont); |
+ var args = _getArgumentExpressions(arguments, fun.function); |
+ var acont = new FunctionValueA(receiver, exceptionComponents, continuation); |
+ return new EvalListConfiguration( |
+ args, environment, exceptionComponents, acont); |
} |
} |
@@ -1811,9 +1855,16 @@ class Class { |
Setter setter = implicitSetters[name]; |
if (setter != null) return setter; |
if (superclass != null) return superclass.lookupImplicitSetter(name); |
+ // TODO(zhivkag): Throw NoSuchInstance error instead. |
return (Value receiver, Value value) => notImplemented(obj: name); |
} |
+ FunctionNode lookup(Name name) => methods[name]?.function; |
+ |
+ bool isGetter(Name name) => methods[name]?.isGetter ?? false; |
+ bool isSetter(Name name) => methods[name]?.isSetter ?? false; |
+ bool isMethod(Name name) => !(methods[name]?.isAccessor ?? true); |
+ |
/// Populates implicit getters and setters for the current class and its |
/// superclass recursively. |
_populateImplicitGettersAndSetters(ast.Class class_) { |