Index: pkg/kernel/lib/interpreter/interpreter.dart |
diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart |
index 6741928fa9ff7753c95d631e6446171560f27145..b5643a124c8fae1c1273ebeebd7b342e6afebbd0 100644 |
--- a/pkg/kernel/lib/interpreter/interpreter.dart |
+++ b/pkg/kernel/lib/interpreter/interpreter.dart |
@@ -162,7 +162,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); |
} |
@@ -963,11 +964,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. |
+ method.location.environment = |
+ new Environment.empty().extendWithThis(receiver); |
+ return new ValuePassingConfiguration(continuation, method); |
+ } |
+ |
+ 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.function.body, |
+ new Environment.empty().extendWithThis(receiver), state); |
+ } |
+ |
Value propertyValue = receiver.class_.lookupImplicitGetter(name)(receiver); |
return new ValuePassingConfiguration(continuation, propertyValue); |
} |
@@ -984,7 +1004,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); |
} |
} |
@@ -992,11 +1013,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.function.positionalParameters.first, v); |
+ var state = new State.initial() |
+ .withReturnContinuation(continuation) |
+ .withContinuation(new ExitSK(continuation, Value.nullInstance)) |
+ .withException(exceptionComponents); |
+ return new ExecConfiguration(setter.function.body, env, state); |
+ } |
+ |
Setter setter = receiver.class_.lookupImplicitSetter(name); |
setter(receiver, v); |
return new ValuePassingConfiguration(continuation, v); |
@@ -1034,25 +1069,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) { |
+ 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.
|
+ fun = receiver; |
+ } else { |
+ assert(receiver.class_.isMethod(methodName)); |
+ fun = receiver.class_.lookup(methodName); |
+ fun.location.environment = |
+ 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); |
} |
} |
@@ -1702,9 +1746,20 @@ class Class { |
Setter setter = implicitSetters[name]; |
if (setter != null) return setter; |
if (superclass != null) return superclass.lookupImplicitSetter(name); |
+ // todo: throw NoSuchInstance error instead. |
Dmitry Stefantsov
2017/08/16 08:48:55
todo ==> TODO
zhivkag
2017/08/16 09:39:49
Done.
|
return (Value receiver, Value value) => notImplemented(obj: name); |
} |
+ FunctionValue lookup(Name name) { |
+ var fun = methods[name]?.function; |
+ assert(fun != null); |
+ return new FunctionValue(fun, new EnvironmentLocation.empty()); |
+ } |
+ |
+ 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_) { |