| Index: pkg/fasta/lib/src/kernel/builder_accessors.dart
|
| diff --git a/pkg/fasta/lib/src/kernel/builder_accessors.dart b/pkg/fasta/lib/src/kernel/builder_accessors.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8728eafb7ae48d744b59b6af3ff14f8f82f87887
|
| --- /dev/null
|
| +++ b/pkg/fasta/lib/src/kernel/builder_accessors.dart
|
| @@ -0,0 +1,730 @@
|
| +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library fasta.builder_accessors;
|
| +
|
| +export 'frontend_accessors.dart' show
|
| + wrapInvalid;
|
| +
|
| +import 'frontend_accessors.dart' show
|
| + Accessor;
|
| +
|
| +import 'package:kernel/ast.dart';
|
| +
|
| +import 'package:kernel/core_types.dart' show
|
| + CoreTypes;
|
| +
|
| +import '../errors.dart' show
|
| + internalError;
|
| +
|
| +import 'frontend_accessors.dart' as kernel show
|
| + IndexAccessor,
|
| + NullAwarePropertyAccessor,
|
| + PropertyAccessor,
|
| + StaticAccessor,
|
| + SuperPropertyAccessor,
|
| + ThisIndexAccessor,
|
| + ThisPropertyAccessor,
|
| + VariableAccessor;
|
| +
|
| +import 'frontend_accessors.dart' show
|
| + buildIsNull,
|
| + makeLet;
|
| +
|
| +import 'kernel_builder.dart' show
|
| + Builder,
|
| + KernelClassBuilder,
|
| + PrefixBuilder,
|
| + TypeDeclarationBuilder;
|
| +
|
| +abstract class BuilderHelper {
|
| + Uri get uri;
|
| +
|
| + CoreTypes get coreTypes;
|
| +
|
| + Constructor lookupConstructor(Name name, {bool isSuper});
|
| +
|
| + Expression toSuperMethodInvocation(MethodInvocation node);
|
| +
|
| + Expression toValue(node);
|
| +
|
| + Member lookupSuperMember(Name name, {bool isSetter: false});
|
| +
|
| + builderToFirstExpression(Builder builder, String name, int charOffset);
|
| +
|
| + finishSend(Object receiver, Arguments arguments, int charOffset);
|
| +
|
| + Expression buildCompileTimeError(error, [int charOffset]);
|
| +
|
| + Initializer buildCompileTimeErrorIntializer(error, [int charOffset]);
|
| +
|
| + Expression buildStaticInvocation(Procedure target, Arguments arguments);
|
| +
|
| + Expression buildProblemExpression(Builder builder, String name);
|
| +}
|
| +
|
| +abstract class BuilderAccessor implements Accessor {
|
| + BuilderHelper get helper;
|
| +
|
| + int get charOffset;
|
| +
|
| + String get plainNameForRead;
|
| +
|
| + Uri get uri => helper.uri;
|
| +
|
| + CoreTypes get coreTypes => helper.coreTypes;
|
| +
|
| + String get plainNameForWrite => plainNameForRead;
|
| +
|
| + Expression buildForEffect() => buildSimpleRead();
|
| +
|
| + Initializer buildFieldInitializer(
|
| + Map<String, FieldInitializer> initializers) {
|
| + // TODO(ahe): This error message is really bad.
|
| + return helper.buildCompileTimeErrorIntializer(
|
| + "Can't use $plainNameForRead here.", charOffset);
|
| + }
|
| +
|
| + Expression makeInvalidRead() {
|
| + return throwNoSuchMethodError(plainNameForRead, new Arguments.empty(), uri,
|
| + charOffset, coreTypes, isGetter: true);
|
| + }
|
| +
|
| + Expression makeInvalidWrite(Expression value) {
|
| + return throwNoSuchMethodError(plainNameForWrite,
|
| + new Arguments(<Expression>[value]), uri, charOffset, coreTypes,
|
| + isSetter: true);
|
| + }
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments);
|
| +
|
| + buildPropertyAccess(IncompleteSend send, bool isNullAware) {
|
| + if (send is SendAccessor) {
|
| + return buildMethodInvocation(buildSimpleRead(), send.name, send.arguments,
|
| + charOffset, isNullAware: isNullAware);
|
| + } else {
|
| + return PropertyAccessor.make(helper, charOffset, buildSimpleRead(),
|
| + send.name, null, null, isNullAware);
|
| + }
|
| + }
|
| +
|
| + Expression buildThrowNoSuchMethodError(Arguments arguments) {
|
| + bool isGetter = false;
|
| + if (arguments == null) {
|
| + arguments = new Arguments.empty();
|
| + isGetter = true;
|
| + }
|
| + return throwNoSuchMethodError(plainNameForWrite, arguments, uri, charOffset,
|
| + coreTypes, isGetter: isGetter);
|
| + }
|
| +
|
| + bool get isThisPropertyAccessor => false;
|
| +}
|
| +
|
| +abstract class CompileTimeErrorAccessor implements Accessor {
|
| + Expression buildError();
|
| +
|
| + Name get name => internalError("Unsupported operation.");
|
| +
|
| + String get plainNameForRead => name.name;
|
| +
|
| + withReceiver(Object receiver, {bool isNullAware}) => this;
|
| +
|
| + Initializer buildFieldInitializer(
|
| + Map<String, FieldInitializer> initializers) {
|
| + return new LocalInitializer(new VariableDeclaration.forValue(buildError()));
|
| + }
|
| +
|
| + doInvocation(int charOffset, Arguments arguments) => this;
|
| +
|
| + buildPropertyAccess(IncompleteSend send, bool isNullAware) => this;
|
| +
|
| + buildThrowNoSuchMethodError(Arguments arguments) => this;
|
| +
|
| + Expression buildAssignment(Expression value, {bool voidContext: false}) {
|
| + return buildError();
|
| + }
|
| +
|
| + Expression buildCompoundAssignment(Name binaryOperator, Expression value,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return buildError();
|
| + }
|
| +
|
| + Expression buildPrefixIncrement(Name binaryOperator,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return buildError();
|
| + }
|
| +
|
| + Expression buildPostfixIncrement(Name binaryOperator,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return buildError();
|
| + }
|
| +
|
| + Expression buildNullAwareAssignment(Expression value, DartType type,
|
| + {bool voidContext: false}) {
|
| + return buildError();
|
| + }
|
| +
|
| + Expression buildSimpleRead() => buildError();
|
| +
|
| + Expression makeInvalidRead() => buildError();
|
| +
|
| + Expression makeInvalidWrite(Expression value) => buildError();
|
| +}
|
| +
|
| +class ThisAccessor extends BuilderAccessor {
|
| + final BuilderHelper helper;
|
| +
|
| + final int charOffset;
|
| +
|
| + final bool isInitializer;
|
| +
|
| + final bool isSuper;
|
| +
|
| + ThisAccessor(this.helper, this.charOffset, this.isInitializer,
|
| + {this.isSuper: false});
|
| +
|
| + String get plainNameForRead => internalError(isSuper ? "super" : "this");
|
| +
|
| + Expression buildSimpleRead() {
|
| + if (!isSuper) {
|
| + return new ThisExpression();
|
| + } else {
|
| + return helper.buildCompileTimeError(
|
| + "Can't use `super` as an expression.", charOffset);
|
| + }
|
| + }
|
| +
|
| + Initializer buildFieldInitializer(
|
| + Map<String, FieldInitializer> initializers) {
|
| + String keyword = isSuper ? "super" : "this";
|
| + return helper.buildCompileTimeErrorIntializer(
|
| + "Can't use '$keyword' here, did you mean '$keyword()'?", charOffset);
|
| + }
|
| +
|
| + buildPropertyAccess(IncompleteSend send, bool isNullAware) {
|
| + if (isInitializer && send is SendAccessor) {
|
| + return buildConstructorInitializer(
|
| + send.charOffset, send.name, send.arguments);
|
| + }
|
| + if (send is SendAccessor) {
|
| + // Notice that 'this' or 'super' can't be null. So we can ignore the
|
| + // value of [isNullAware].
|
| + MethodInvocation result = buildMethodInvocation(new ThisExpression(),
|
| + send.name, send.arguments, charOffset);
|
| + return isSuper ? helper.toSuperMethodInvocation(result) : result;
|
| + } else {
|
| + if (isSuper) {
|
| + Member getter = helper.lookupSuperMember(send.name);
|
| + Member setter = helper.lookupSuperMember(send.name, isSetter: true);
|
| + return new SuperPropertyAccessor(helper, charOffset, send.name, getter,
|
| + setter);
|
| + } else {
|
| + return new ThisPropertyAccessor(helper, charOffset, send.name, null,
|
| + null);
|
| + }
|
| + }
|
| + }
|
| +
|
| + doInvocation(int charOffset, Arguments arguments) {
|
| + if (isInitializer) {
|
| + return buildConstructorInitializer(charOffset, new Name(""), arguments);
|
| + } else {
|
| + return buildMethodInvocation(new ThisExpression(), new Name("call"),
|
| + arguments, charOffset);
|
| + }
|
| + }
|
| +
|
| + Initializer buildConstructorInitializer(int charOffset, Name name,
|
| + Arguments arguments) {
|
| + Constructor constructor = helper.lookupConstructor(name, isSuper: isSuper);
|
| + Initializer result;
|
| + if (constructor == null) {
|
| + result = new LocalInitializer(
|
| + new VariableDeclaration.forValue(
|
| + throwNoSuchMethodError(
|
| + name.name, arguments, uri, charOffset, coreTypes,
|
| + isSuper: isSuper)));
|
| + } else if (isSuper) {
|
| + result = new SuperInitializer(constructor, arguments);
|
| + } else {
|
| + result = new RedirectingInitializer(constructor, arguments);
|
| + }
|
| + return result
|
| + ..fileOffset = charOffset;
|
| + }
|
| +
|
| + Expression buildAssignment(Expression value, {bool voidContext: false}) {
|
| + return internalError("");
|
| + }
|
| +
|
| + Expression buildNullAwareAssignment(Expression value, DartType type,
|
| + {bool voidContext: false}) {
|
| + return internalError("");
|
| + }
|
| +
|
| + Expression buildCompoundAssignment(Name binaryOperator, Expression value,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return internalError("");
|
| + }
|
| +
|
| + Expression buildPrefixIncrement(Name binaryOperator,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return internalError("");
|
| + }
|
| +
|
| + Expression buildPostfixIncrement(Name binaryOperator,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return internalError("");
|
| + }
|
| +
|
| + toString() => "ThisAccessor($charOffset${isSuper ? ', super' : ''})";
|
| +}
|
| +
|
| +abstract class IncompleteSend extends BuilderAccessor {
|
| + final BuilderHelper helper;
|
| +
|
| + final int charOffset;
|
| +
|
| + final Name name;
|
| +
|
| + IncompleteSend(this.helper, this.charOffset, this.name);
|
| +
|
| + withReceiver(Object receiver, {bool isNullAware});
|
| +}
|
| +
|
| +class IncompleteError extends IncompleteSend with CompileTimeErrorAccessor {
|
| + final Object error;
|
| +
|
| + IncompleteError(BuilderHelper helper, int charOffset, this.error)
|
| + : super(helper, charOffset, null);
|
| +
|
| + Expression buildError() {
|
| + return helper.buildCompileTimeError(error, charOffset);
|
| + }
|
| +}
|
| +
|
| +class SendAccessor extends IncompleteSend {
|
| + final Arguments arguments;
|
| +
|
| + SendAccessor(BuilderHelper helper, int charOffset, Name name, this.arguments)
|
| + : super(helper, charOffset, name) {
|
| + assert(arguments != null);
|
| + }
|
| +
|
| + String get plainNameForRead => name.name;
|
| +
|
| + Expression buildSimpleRead() {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + Expression buildAssignment(Expression value, {bool voidContext: false}) {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + withReceiver(Object receiver, {bool isNullAware: false}) {
|
| + if (receiver is TypeDeclarationBuilder) {
|
| + /// `SomeType?.toString` is the same as `SomeType.toString`, not
|
| + /// `(SomeType).toString`.
|
| + isNullAware = false;
|
| + }
|
| + if (receiver is BuilderAccessor) {
|
| + return receiver.buildPropertyAccess(this, isNullAware);
|
| + }
|
| + if (receiver is PrefixBuilder) {
|
| + PrefixBuilder prefix = receiver;
|
| + receiver = helper.builderToFirstExpression(
|
| + prefix.exports[name.name], "${prefix.name}.${name.name}", charOffset);
|
| + return helper.finishSend(receiver, arguments, charOffset);
|
| + }
|
| + Expression result;
|
| + if (receiver is KernelClassBuilder) {
|
| + Builder builder = receiver.findStaticBuilder(name.name);
|
| + if (builder == null) {
|
| + return buildThrowNoSuchMethodError(arguments);
|
| + }
|
| + if (builder.hasProblem) {
|
| + result = helper.buildProblemExpression(builder, name.name);
|
| + } else {
|
| + Member target = builder.target;
|
| + if (target != null) {
|
| + if (target is Field) {
|
| + result = buildMethodInvocation(new StaticGet(target),
|
| + new Name("call"), arguments, charOffset,
|
| + isNullAware: isNullAware);
|
| + } else {
|
| + result = helper.buildStaticInvocation(target, arguments);
|
| + }
|
| + } else {
|
| + result = buildThrowNoSuchMethodError(arguments);
|
| + }
|
| + }
|
| + } else {
|
| + result = buildMethodInvocation(helper.toValue(receiver), name,
|
| + arguments, charOffset, isNullAware: isNullAware);
|
| + }
|
| + return result..fileOffset = charOffset;
|
| + }
|
| +
|
| + Expression buildNullAwareAssignment(Expression value, DartType type,
|
| + {bool voidContext: false}) {
|
| + return internalError("");
|
| + }
|
| +
|
| + Expression buildCompoundAssignment(Name binaryOperator, Expression value,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return internalError("");
|
| + }
|
| +
|
| + Expression buildPrefixIncrement(Name binaryOperator,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + Expression buildPostfixIncrement(Name binaryOperator,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments) {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + toString() => "SendAccessor($charOffset, $name, $arguments)";
|
| +}
|
| +
|
| +class IncompletePropertyAccessor extends IncompleteSend {
|
| + IncompletePropertyAccessor(BuilderHelper helper, int charOffset, Name name)
|
| + : super(helper, charOffset, name);
|
| +
|
| + String get plainNameForRead => name.name;
|
| +
|
| + Expression buildSimpleRead() => internalError("Unhandled");
|
| +
|
| + Expression buildAssignment(Expression value, {bool voidContext: false}) {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + withReceiver(Object receiver, {bool isNullAware: false}) {
|
| + if (receiver is TypeDeclarationBuilder) {
|
| + /// For reasons beyond comprehension, `SomeType?.toString` is the same as
|
| + /// `SomeType.toString`, not `(SomeType).toString`. WTAF!?!
|
| + //
|
| + isNullAware = false;
|
| + }
|
| + if (receiver is BuilderAccessor) {
|
| + return receiver.buildPropertyAccess(this, isNullAware);
|
| + }
|
| + if (receiver is PrefixBuilder) {
|
| + PrefixBuilder prefix = receiver;
|
| + return helper.builderToFirstExpression(
|
| + prefix.exports[name.name], name.name, charOffset);
|
| + }
|
| + if (receiver is KernelClassBuilder) {
|
| + Builder builder = receiver.findStaticBuilder(name.name);
|
| + Member getter = builder?.target;
|
| + Member setter;
|
| + if (builder == null) {
|
| + builder = receiver.findStaticBuilder(name.name, isSetter: true);
|
| + if (builder == null) {
|
| + return buildThrowNoSuchMethodError(null);
|
| + }
|
| + }
|
| + if (builder.hasProblem) {
|
| + return helper.buildProblemExpression(builder, name.name)
|
| + ..fileOffset = charOffset;
|
| + }
|
| + if (getter is Field) {
|
| + if (!getter.isFinal && !getter.isConst) {
|
| + setter = getter;
|
| + }
|
| + } else if (getter is Procedure) {
|
| + if (getter.isGetter) {
|
| + builder = receiver.findStaticBuilder(name.name, isSetter: true);
|
| + if (builder != null && !builder.hasProblem) {
|
| + setter = builder.target;
|
| + }
|
| + }
|
| + }
|
| + if (getter == null) {
|
| + return internalError("no getter for $name");
|
| + }
|
| + return new StaticAccessor(helper, charOffset, getter, setter);
|
| + }
|
| + return PropertyAccessor.make(helper, charOffset, helper.toValue(receiver),
|
| + name, null, null, isNullAware);
|
| + }
|
| +
|
| + Expression buildNullAwareAssignment(Expression value, DartType type,
|
| + {bool voidContext: false}) {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + Expression buildCompoundAssignment(Name binaryOperator, Expression value,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + Expression buildPrefixIncrement(Name binaryOperator,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + Expression buildPostfixIncrement(Name binaryOperator,
|
| + {bool voidContext: false, Procedure interfaceTarget}) {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments) {
|
| + return internalError("Unhandled");
|
| + }
|
| +
|
| + toString() => "IncompletePropertyAccessor($charOffset, $name)";
|
| +}
|
| +
|
| +class IndexAccessor extends kernel.IndexAccessor with BuilderAccessor {
|
| + final BuilderHelper helper;
|
| +
|
| + final int charOffset;
|
| +
|
| + IndexAccessor.internal(this.helper, this.charOffset, Expression receiver,
|
| + Expression index, Procedure getter, Procedure setter)
|
| + : super.internal(receiver, index, getter, setter);
|
| +
|
| + String get plainNameForRead => "[]";
|
| +
|
| + String get plainNameForWrite => "[]=";
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments) {
|
| + return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments,
|
| + charOffset);
|
| + }
|
| +
|
| + toString() => "IndexAccessor()";
|
| +
|
| + static BuilderAccessor make(BuilderHelper helper, int charOffset,
|
| + Expression receiver, Expression index, Procedure getter,
|
| + Procedure setter) {
|
| + if (receiver is ThisExpression) {
|
| + return new ThisIndexAccessor(helper, charOffset, index, getter, setter);
|
| + } else {
|
| + return new IndexAccessor.internal(helper, charOffset, receiver, index,
|
| + getter, setter);
|
| + }
|
| + }
|
| +}
|
| +
|
| +class PropertyAccessor extends kernel.PropertyAccessor with BuilderAccessor {
|
| + final BuilderHelper helper;
|
| +
|
| + final int charOffset;
|
| +
|
| + PropertyAccessor.internal(this.helper, this.charOffset, Expression receiver,
|
| + Name name, Member getter, Member setter)
|
| + : super.internal(receiver, name, getter, setter);
|
| +
|
| + String get plainNameForRead => name.name;
|
| +
|
| + bool get isThisPropertyAccessor => receiver is ThisExpression;
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments) {
|
| + return buildMethodInvocation(receiver, name, arguments, charOffset);
|
| + }
|
| +
|
| + toString() => "PropertyAccessor()";
|
| +
|
| + static BuilderAccessor make(BuilderHelper helper, int charOffset,
|
| + Expression receiver, Name name, Member getter, Member setter,
|
| + bool isNullAware) {
|
| + if (receiver is ThisExpression) {
|
| + return new ThisPropertyAccessor(helper, charOffset, name, getter, setter);
|
| + } else {
|
| + return isNullAware
|
| + ? new NullAwarePropertyAccessor(helper, charOffset, receiver, name,
|
| + getter, setter, null)
|
| + : new PropertyAccessor.internal(helper, charOffset, receiver, name,
|
| + getter, setter);
|
| + }
|
| + }
|
| +}
|
| +
|
| +class StaticAccessor extends kernel.StaticAccessor with BuilderAccessor {
|
| + final BuilderHelper helper;
|
| +
|
| + final int charOffset;
|
| +
|
| + StaticAccessor(this.helper, this.charOffset, Member readTarget,
|
| + Member writeTarget)
|
| + : super(readTarget, writeTarget) {
|
| + assert(readTarget != null || writeTarget != null);
|
| + }
|
| +
|
| + String get plainNameForRead => (readTarget ?? writeTarget).name.name;
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments) {
|
| + if (readTarget == null || isFieldOrGetter(readTarget)) {
|
| + return buildMethodInvocation(buildSimpleRead(), new Name("call"),
|
| + arguments, charOffset);
|
| + } else {
|
| + return helper.buildStaticInvocation(readTarget, arguments)
|
| + ..fileOffset = charOffset;
|
| + }
|
| + }
|
| +
|
| + toString() => "StaticAccessor()";
|
| +}
|
| +
|
| +class SuperPropertyAccessor extends kernel.SuperPropertyAccessor
|
| + with BuilderAccessor {
|
| + final BuilderHelper helper;
|
| +
|
| + final int charOffset;
|
| +
|
| + SuperPropertyAccessor(this.helper, this.charOffset, Name name, Member getter,
|
| + Member setter)
|
| + : super(name, getter, setter);
|
| +
|
| + String get plainNameForRead => name.name;
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments) {
|
| + if (getter == null || isFieldOrGetter(getter)) {
|
| + return buildMethodInvocation(buildSimpleRead(), new Name("call"),
|
| + arguments, charOffset);
|
| + } else {
|
| + return new DirectMethodInvocation(new ThisExpression(), getter, arguments)
|
| + ..fileOffset = charOffset;
|
| + }
|
| + }
|
| +
|
| + toString() => "SuperPropertyAccessor()";
|
| +}
|
| +
|
| +class ThisIndexAccessor extends kernel.ThisIndexAccessor with BuilderAccessor {
|
| + final BuilderHelper helper;
|
| +
|
| + final int charOffset;
|
| +
|
| + ThisIndexAccessor(this.helper, this.charOffset, Expression index,
|
| + Procedure getter, Procedure setter)
|
| + : super(index, getter, setter);
|
| +
|
| + String get plainNameForRead => "[]";
|
| +
|
| + String get plainNameForWrite => "[]=";
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments) {
|
| + return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments,
|
| + charOffset);
|
| + }
|
| +
|
| + toString() => "ThisIndexAccessor()";
|
| +}
|
| +
|
| +class ThisPropertyAccessor extends kernel.ThisPropertyAccessor
|
| + with BuilderAccessor {
|
| + final BuilderHelper helper;
|
| +
|
| + final int charOffset;
|
| +
|
| + ThisPropertyAccessor(this.helper, this.charOffset, Name name, Member getter,
|
| + Member setter)
|
| + : super(name, getter, setter);
|
| +
|
| + String get plainNameForRead => name.name;
|
| +
|
| + bool get isThisPropertyAccessor => true;
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments) {
|
| + Member interfaceTarget = getter;
|
| + if (interfaceTarget is Field) {
|
| + // TODO(ahe): In strong mode we should probably rewrite this to
|
| + // `this.name.call(arguments)`.
|
| + interfaceTarget = null;
|
| + }
|
| + return buildMethodInvocation(new ThisExpression(), name, arguments,
|
| + charOffset);
|
| + }
|
| +
|
| + toString() => "ThisPropertyAccessor()";
|
| +}
|
| +
|
| +class NullAwarePropertyAccessor extends kernel.NullAwarePropertyAccessor
|
| + with BuilderAccessor {
|
| + final BuilderHelper helper;
|
| +
|
| + final int charOffset;
|
| +
|
| + NullAwarePropertyAccessor(this.helper, this.charOffset, Expression receiver,
|
| + Name name, Member getter, Member setter, DartType type)
|
| + : super(receiver, name, getter, setter, type);
|
| +
|
| + String get plainNameForRead => name.name;
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments) {
|
| + return internalError("Not implemented yet.");
|
| + }
|
| +
|
| + toString() => "NullAwarePropertyAccessor()";
|
| +}
|
| +
|
| +
|
| +class VariableAccessor extends kernel.VariableAccessor
|
| + with BuilderAccessor {
|
| + final BuilderHelper helper;
|
| +
|
| + final int charOffset;
|
| +
|
| + VariableAccessor(this.helper, this.charOffset, VariableDeclaration variable,
|
| + [DartType promotedType])
|
| + : super.internal(variable, promotedType);
|
| +
|
| + String get plainNameForRead => variable.name;
|
| +
|
| + Expression doInvocation(int charOffset, Arguments arguments) {
|
| + return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments,
|
| + charOffset);
|
| + }
|
| +
|
| + toString() => "VariableAccessor()";
|
| +}
|
| +
|
| +Expression throwNoSuchMethodError(String name, Arguments arguments, Uri uri,
|
| + int charOffset, CoreTypes coreTypes,
|
| + {bool isSuper: false, isGetter: false, isSetter: false}) {
|
| + print("$uri:$charOffset: method not found: '$name'.");
|
| + Constructor constructor = coreTypes.getCoreClass(
|
| + "dart:core", "NoSuchMethodError").constructors.first;
|
| + return new Throw(new ConstructorInvocation(
|
| + constructor,
|
| + new Arguments(<Expression>[
|
| + new NullLiteral(),
|
| + new SymbolLiteral(name),
|
| + new ListLiteral(arguments.positional),
|
| + new MapLiteral(arguments.named.map((arg) {
|
| + return new MapEntry(new SymbolLiteral(arg.name), arg.value);
|
| + }).toList()),
|
| + new NullLiteral()])));
|
| +}
|
| +
|
| +bool isFieldOrGetter(Member member) {
|
| + return member is Field || (member is Procedure && member.isGetter);
|
| +}
|
| +
|
| +Expression buildMethodInvocation(Expression receiver, Name name,
|
| + Arguments arguments, int charOffset, {bool isNullAware: false}) {
|
| + if (isNullAware) {
|
| + VariableDeclaration variable = new VariableDeclaration.forValue(receiver);
|
| + return makeLet(
|
| + variable,
|
| + new ConditionalExpression(
|
| + buildIsNull(new VariableGet(variable)),
|
| + new NullLiteral(),
|
| + new MethodInvocation(new VariableGet(variable), name, arguments)
|
| + ..fileOffset = charOffset,
|
| + const DynamicType()));
|
| + } else {
|
| + return new MethodInvocation(receiver, name, arguments)
|
| + ..fileOffset = charOffset;
|
| + }
|
| +}
|
|
|