Chromium Code Reviews| 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_) { |