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

Unified Diff: pkg/fasta/lib/src/kernel/builder_accessors.dart

Issue 2628043005: Fasta kernel AST builder. (Closed)
Patch Set: Rebased. Created 3 years, 11 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 | « pkg/fasta/lib/src/kernel/body_builder.dart ('k') | pkg/fasta/lib/src/kernel/frontend_accessors.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
+ }
+}
« no previous file with comments | « pkg/fasta/lib/src/kernel/body_builder.dart ('k') | pkg/fasta/lib/src/kernel/frontend_accessors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698