mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 12:30:03 +00:00
Start creating common superclass for generators
Change-Id: I9d8c95665eed15be45c2a5b734e541af73a7db91 Reviewed-on: https://dart-review.googlesource.com/56117 Reviewed-by: Dmitry Stefantsov <dmitryas@google.com> Commit-Queue: Peter von der Ahé <ahe@google.com>
This commit is contained in:
parent
2a7188523e
commit
2d79c356e0
|
@ -364,6 +364,28 @@ class AstBuildingForest
|
|||
Statement yieldStatement(Token yieldKeyword, Token star,
|
||||
Expression expression, Token semicolon) =>
|
||||
astFactory.yieldStatement(yieldKeyword, star, expression, semicolon);
|
||||
|
||||
@override
|
||||
Generator<Expression, Statement, _Arguments> variableUseGenerator(
|
||||
ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
|
||||
Token token,
|
||||
VariableDeclarationStatement variable,
|
||||
kernel.DartType promotedType) {
|
||||
// TODO(brianwilkerson) Implement this.
|
||||
throw new UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Generator<Expression, Statement, _Arguments> propertyAccessGenerator(
|
||||
ExpressionGeneratorHelper<Expression, Statement, _Arguments> helper,
|
||||
Token token,
|
||||
Expression receiver,
|
||||
covariant name,
|
||||
covariant getter,
|
||||
covariant setter) {
|
||||
// TODO(brianwilkerson) Implement this.
|
||||
throw new UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
/// A data holder used to conform to the [Forest] API.
|
||||
|
|
|
@ -6,6 +6,9 @@ library fasta.body_builder;
|
|||
|
||||
import 'dart:core' hide MapEntry;
|
||||
|
||||
import 'package:kernel/ast.dart' as kernel
|
||||
show Arguments, Expression, Statement;
|
||||
|
||||
import '../constant_context.dart' show ConstantContext;
|
||||
|
||||
import '../fasta_codes.dart' as fasta;
|
||||
|
@ -118,8 +121,6 @@ import 'kernel_api.dart';
|
|||
|
||||
import 'kernel_ast_api.dart' hide Expression, Statement;
|
||||
|
||||
import 'kernel_ast_api.dart' as kernel show Expression, Statement;
|
||||
|
||||
import 'kernel_builder.dart';
|
||||
|
||||
import 'type_algorithms.dart' show calculateBounds;
|
||||
|
@ -654,8 +655,11 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
}
|
||||
|
||||
@override
|
||||
void finishFunction(List annotations, FormalParameters<Arguments> formals,
|
||||
AsyncMarker asyncModifier, kernel.Statement body) {
|
||||
void finishFunction(
|
||||
List annotations,
|
||||
FormalParameters<Expression, Statement, Arguments> formals,
|
||||
AsyncMarker asyncModifier,
|
||||
kernel.Statement body) {
|
||||
debugEvent("finishFunction");
|
||||
typePromoter.finished();
|
||||
|
||||
|
@ -753,7 +757,7 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
|
||||
enterLocalScope(
|
||||
null,
|
||||
new FormalParameters<Arguments>(
|
||||
new FormalParameters<Expression, Statement, Arguments>(
|
||||
parameters.positionalParameters, null, -1)
|
||||
.computeFormalParameterScope(scope, member, this));
|
||||
|
||||
|
@ -925,7 +929,8 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
if (arguments == null) {
|
||||
push(new IncompletePropertyAccessGenerator(this, beginToken, name));
|
||||
} else {
|
||||
push(new SendAccessGenerator(this, beginToken, name, arguments));
|
||||
push(new SendAccessGenerator(
|
||||
this, beginToken, name, forest.castArguments(arguments)));
|
||||
}
|
||||
} else if (arguments == null) {
|
||||
push(receiver);
|
||||
|
@ -2094,7 +2099,7 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
@override
|
||||
void endFunctionType(Token functionToken, Token endToken) {
|
||||
debugEvent("FunctionType");
|
||||
FormalParameters<Arguments> formals = pop();
|
||||
FormalParameters<Expression, Statement, Arguments> formals = pop();
|
||||
DartType returnType = pop();
|
||||
List<TypeParameter> typeVariables = typeVariableBuildersToKernel(pop());
|
||||
FunctionType type = formals.toFunctionType(returnType, typeVariables);
|
||||
|
@ -2268,7 +2273,7 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
if (inCatchClause || functionNestingLevel != 0) {
|
||||
exitLocalScope();
|
||||
}
|
||||
FormalParameters<Arguments> formals = pop();
|
||||
FormalParameters<Expression, Statement, Arguments> formals = pop();
|
||||
DartType returnType = pop();
|
||||
List<TypeParameter> typeVariables = typeVariableBuildersToKernel(pop());
|
||||
FunctionType type = formals.toFunctionType(returnType, typeVariables);
|
||||
|
@ -2323,8 +2328,8 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
List<VariableDeclaration> variables =
|
||||
new List<VariableDeclaration>.filled(count, null, growable: true);
|
||||
popList(count, variables);
|
||||
FormalParameters<Arguments> formals =
|
||||
new FormalParameters(variables, optional, beginToken.charOffset);
|
||||
var formals = new FormalParameters<Expression, Statement, Arguments>(
|
||||
variables, optional, beginToken.charOffset);
|
||||
constantContext = pop();
|
||||
push(formals);
|
||||
if ((inCatchClause || functionNestingLevel != 0) &&
|
||||
|
@ -2358,7 +2363,8 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
if (catchKeyword != null) {
|
||||
exitLocalScope();
|
||||
}
|
||||
FormalParameters<Arguments> catchParameters = popIfNotNull(catchKeyword);
|
||||
FormalParameters<Expression, Statement, Arguments> catchParameters =
|
||||
popIfNotNull(catchKeyword);
|
||||
DartType type = popIfNotNull(onKeyword) ?? const DynamicType();
|
||||
VariableDeclaration exception;
|
||||
VariableDeclaration stackTrace;
|
||||
|
@ -2421,7 +2427,7 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
lookupInstanceMember(indexGetName, isSuper: true),
|
||||
lookupInstanceMember(indexSetName, isSuper: true)));
|
||||
} else {
|
||||
push(IndexedAccessGenerator.make<Arguments>(
|
||||
push(IndexedAccessGenerator.make(
|
||||
this,
|
||||
openSquareBracket,
|
||||
toKernelExpression(toValue(receiver)),
|
||||
|
@ -2492,7 +2498,7 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
debugEvent("UnaryPostfixAssignmentExpression");
|
||||
var generator = pop();
|
||||
if (generator is Generator) {
|
||||
push(new DelayedPostfixIncrement<Arguments>(
|
||||
push(new DelayedPostfixIncrement(
|
||||
this, token, generator, incrementOperator(token), null));
|
||||
} else {
|
||||
push(
|
||||
|
@ -2794,7 +2800,7 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
? wrapInDeferredCheck(expression, deferredPrefix, checkOffset)
|
||||
: expression);
|
||||
} else if (type is ErroneousExpressionGenerator) {
|
||||
push(type.buildError(arguments));
|
||||
push(type.buildError(forest.castArguments(arguments)));
|
||||
} else {
|
||||
push(throwNoSuchMethodError(storeOffset(forest.literalNull(null), offset),
|
||||
debugName(getNodeName(type), name), arguments, nameToken.charOffset));
|
||||
|
@ -3018,7 +3024,7 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
Statement body = popStatement();
|
||||
AsyncMarker asyncModifier = pop();
|
||||
exitLocalScope();
|
||||
FormalParameters<Arguments> formals = pop();
|
||||
FormalParameters<Expression, Statement, Arguments> formals = pop();
|
||||
var declaration = pop();
|
||||
var returnType = pop();
|
||||
var hasImplicitReturnType = returnType == null;
|
||||
|
@ -3115,7 +3121,7 @@ abstract class BodyBuilder<Expression, Statement, Arguments>
|
|||
Statement body = popStatement();
|
||||
AsyncMarker asyncModifier = pop();
|
||||
exitLocalScope();
|
||||
FormalParameters<Arguments> formals = pop();
|
||||
FormalParameters<Expression, Statement, Arguments> formals = pop();
|
||||
exitFunction();
|
||||
List<TypeParameter> typeParameters = typeVariableBuildersToKernel(pop());
|
||||
FunctionNode function = formals.addToFunction(new FunctionNode(
|
||||
|
@ -4209,11 +4215,12 @@ class Label {
|
|||
String toString() => "label($name)";
|
||||
}
|
||||
|
||||
abstract class ContextAwareGenerator<Arguments> extends Generator<Arguments> {
|
||||
abstract class ContextAwareGenerator
|
||||
extends Generator<kernel.Expression, kernel.Statement, kernel.Arguments> {
|
||||
final Generator generator;
|
||||
|
||||
ContextAwareGenerator(
|
||||
ExpressionGeneratorHelper<dynamic, dynamic, Arguments> helper,
|
||||
ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
|
||||
Token token,
|
||||
this.generator)
|
||||
: super(helper, token);
|
||||
|
@ -4222,7 +4229,7 @@ abstract class ContextAwareGenerator<Arguments> extends Generator<Arguments> {
|
|||
return unsupported("plainNameForRead", token.charOffset, helper.uri);
|
||||
}
|
||||
|
||||
kernel.Expression doInvocation(int charOffset, Arguments arguments) {
|
||||
kernel.Expression doInvocation(int charOffset, kernel.Arguments arguments) {
|
||||
return unhandled("${runtimeType}", "doInvocation", charOffset, uri);
|
||||
}
|
||||
|
||||
|
@ -4275,17 +4282,13 @@ abstract class ContextAwareGenerator<Arguments> extends Generator<Arguments> {
|
|||
}
|
||||
}
|
||||
|
||||
class DelayedAssignment<Arguments> extends ContextAwareGenerator<Arguments> {
|
||||
class DelayedAssignment extends ContextAwareGenerator {
|
||||
final kernel.Expression value;
|
||||
|
||||
final String assignmentOperator;
|
||||
|
||||
DelayedAssignment(
|
||||
ExpressionGeneratorHelper<dynamic, dynamic, Arguments> helper,
|
||||
Token token,
|
||||
Generator generator,
|
||||
this.value,
|
||||
this.assignmentOperator)
|
||||
DelayedAssignment(ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
|
||||
Token token, Generator generator, this.value, this.assignmentOperator)
|
||||
: super(helper, token, generator);
|
||||
|
||||
String get debugName => "DelayedAssignment";
|
||||
|
@ -4367,14 +4370,13 @@ class DelayedAssignment<Arguments> extends ContextAwareGenerator<Arguments> {
|
|||
}
|
||||
}
|
||||
|
||||
class DelayedPostfixIncrement<Arguments>
|
||||
extends ContextAwareGenerator<Arguments> {
|
||||
class DelayedPostfixIncrement extends ContextAwareGenerator {
|
||||
final Name binaryOperator;
|
||||
|
||||
final Procedure interfaceTarget;
|
||||
|
||||
DelayedPostfixIncrement(
|
||||
ExpressionGeneratorHelper<dynamic, dynamic, Arguments> helper,
|
||||
ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper,
|
||||
Token token,
|
||||
Generator generator,
|
||||
this.binaryOperator,
|
||||
|
@ -4536,7 +4538,7 @@ class OptionalFormals {
|
|||
OptionalFormals(this.kind, this.formals);
|
||||
}
|
||||
|
||||
class FormalParameters<Arguments> {
|
||||
class FormalParameters<Expression, Statement, Arguments> {
|
||||
final List<VariableDeclaration> required;
|
||||
final OptionalFormals optional;
|
||||
final int charOffset;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,8 +10,8 @@ import 'package:kernel/ast.dart'
|
|||
show
|
||||
Arguments,
|
||||
AssertInitializer,
|
||||
BreakStatement,
|
||||
Block,
|
||||
BreakStatement,
|
||||
Catch,
|
||||
ContinueSwitchStatement,
|
||||
DartType,
|
||||
|
@ -23,6 +23,8 @@ import 'package:kernel/ast.dart'
|
|||
Let,
|
||||
LibraryDependency,
|
||||
MapEntry,
|
||||
Member,
|
||||
Name,
|
||||
NamedExpression,
|
||||
Statement,
|
||||
SwitchCase,
|
||||
|
@ -37,6 +39,9 @@ import '../problems.dart' show unsupported;
|
|||
|
||||
import '../scanner.dart' show Token;
|
||||
|
||||
import 'kernel_expression_generator.dart'
|
||||
show KernelPropertyAccessGenerator, KernelVariableUseGenerator;
|
||||
|
||||
import 'kernel_shadow_ast.dart'
|
||||
show
|
||||
ShadowArguments,
|
||||
|
@ -76,7 +81,7 @@ import 'kernel_shadow_ast.dart'
|
|||
ShadowWhileStatement,
|
||||
ShadowYieldStatement;
|
||||
|
||||
import 'forest.dart' show Forest;
|
||||
import 'forest.dart' show ExpressionGeneratorHelper, Forest;
|
||||
|
||||
/// A shadow tree factory.
|
||||
class Fangorn extends Forest<Expression, Statement, Token, Arguments> {
|
||||
|
@ -498,6 +503,28 @@ class Fangorn extends Forest<Expression, Statement, Token, Arguments> {
|
|||
SwitchCase target, ContinueSwitchStatement user) {
|
||||
user.target = target;
|
||||
}
|
||||
|
||||
@override
|
||||
KernelVariableUseGenerator variableUseGenerator(
|
||||
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
|
||||
Token token,
|
||||
VariableDeclaration variable,
|
||||
DartType promotedType) {
|
||||
return new KernelVariableUseGenerator(
|
||||
helper, token, variable, promotedType);
|
||||
}
|
||||
|
||||
@override
|
||||
KernelPropertyAccessGenerator propertyAccessGenerator(
|
||||
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
|
||||
Token token,
|
||||
Expression receiver,
|
||||
Name name,
|
||||
Member getter,
|
||||
Member setter) {
|
||||
return new KernelPropertyAccessGenerator.internal(
|
||||
helper, token, receiver, name, getter, setter);
|
||||
}
|
||||
}
|
||||
|
||||
class _VariablesDeclaration extends Statement {
|
||||
|
|
|
@ -9,8 +9,16 @@ import 'package:kernel/ast.dart' as kernel show Arguments, DartType;
|
|||
|
||||
import 'body_builder.dart' show Identifier;
|
||||
|
||||
import 'expression_generator.dart' show Generator;
|
||||
|
||||
import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
|
||||
|
||||
export 'body_builder.dart' show Identifier, Operator;
|
||||
|
||||
export 'expression_generator.dart' show Generator;
|
||||
|
||||
export 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
|
||||
|
||||
/// A tree factory.
|
||||
///
|
||||
/// For now, the [Location] is always a token.
|
||||
|
@ -278,6 +286,20 @@ abstract class Forest<Expression, Statement, Location, Arguments> {
|
|||
void resolveContinueInSwitch(
|
||||
covariant Object target, covariant Statement user);
|
||||
|
||||
Generator<Expression, Statement, Arguments> variableUseGenerator(
|
||||
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
|
||||
Location location,
|
||||
covariant variable,
|
||||
kernel.DartType promotedType);
|
||||
|
||||
Generator<Expression, Statement, Arguments> propertyAccessGenerator(
|
||||
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
|
||||
Location location,
|
||||
Expression receiver,
|
||||
covariant name,
|
||||
covariant getter,
|
||||
covariant setter);
|
||||
|
||||
// TODO(ahe): Remove this method when all users are moved here.
|
||||
kernel.Arguments castArguments(Arguments arguments) {
|
||||
dynamic a = arguments;
|
||||
|
|
|
@ -0,0 +1,445 @@
|
|||
// Copyright (c) 2018, 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.
|
||||
|
||||
import 'package:kernel/ast.dart' show Arguments, Expression, Node, Statement;
|
||||
|
||||
import '../../scanner/token.dart' show Token;
|
||||
|
||||
import '../constant_context.dart' show ConstantContext;
|
||||
|
||||
import '../fasta_codes.dart'
|
||||
show
|
||||
LocatedMessage,
|
||||
messageLoadLibraryTakesNoArguments,
|
||||
messageSuperAsExpression,
|
||||
templateDeferredTypeAnnotation,
|
||||
templateIntegerLiteralIsOutOfRange,
|
||||
templateNotAPrefixInTypeAnnotation,
|
||||
templateUnresolvedPrefixInTypeAnnotation;
|
||||
|
||||
import '../messages.dart' show Message, noLength;
|
||||
|
||||
import '../names.dart' show callName, equalsName, indexGetName, indexSetName;
|
||||
|
||||
import '../parser.dart' show lengthForToken, lengthOfSpan, offsetForToken;
|
||||
|
||||
import '../problems.dart' show unhandled, unsupported;
|
||||
|
||||
import '../scope.dart' show AccessErrorBuilder;
|
||||
|
||||
import 'body_builder.dart' show Identifier, noLocation;
|
||||
|
||||
import 'constness.dart' show Constness;
|
||||
|
||||
import 'expression_generator.dart'
|
||||
show
|
||||
ExpressionGenerator,
|
||||
Generator,
|
||||
PropertyAccessGenerator,
|
||||
VariableUseGenerator;
|
||||
|
||||
import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
|
||||
|
||||
import 'forest.dart' show Forest;
|
||||
|
||||
import 'kernel_builder.dart' show LoadLibraryBuilder, PrefixBuilder;
|
||||
|
||||
import 'kernel_api.dart' show NameSystem, printNodeOn, printQualifiedNameOn;
|
||||
|
||||
import 'kernel_ast_api.dart'
|
||||
show
|
||||
Constructor,
|
||||
DartType,
|
||||
Field,
|
||||
Initializer,
|
||||
InvalidType,
|
||||
Let,
|
||||
Member,
|
||||
Name,
|
||||
Procedure,
|
||||
PropertySet,
|
||||
ShadowComplexAssignment,
|
||||
ShadowIllegalAssignment,
|
||||
ShadowIndexAssign,
|
||||
ShadowMethodInvocation,
|
||||
ShadowNullAwarePropertyGet,
|
||||
ShadowPropertyAssign,
|
||||
ShadowPropertyGet,
|
||||
ShadowStaticAssignment,
|
||||
ShadowSuperMethodInvocation,
|
||||
ShadowSuperPropertyGet,
|
||||
ShadowVariableAssignment,
|
||||
ShadowVariableDeclaration,
|
||||
ShadowVariableGet,
|
||||
StaticSet,
|
||||
SuperMethodInvocation,
|
||||
SuperPropertySet,
|
||||
Throw,
|
||||
TreeNode,
|
||||
TypeParameter,
|
||||
TypeParameterType,
|
||||
VariableDeclaration,
|
||||
VariableGet,
|
||||
VariableSet;
|
||||
|
||||
import 'kernel_builder.dart'
|
||||
show
|
||||
Builder,
|
||||
BuiltinTypeBuilder,
|
||||
FunctionTypeAliasBuilder,
|
||||
KernelClassBuilder,
|
||||
KernelFunctionTypeAliasBuilder,
|
||||
KernelInvalidTypeBuilder,
|
||||
KernelTypeVariableBuilder,
|
||||
LoadLibraryBuilder,
|
||||
PrefixBuilder,
|
||||
TypeDeclarationBuilder;
|
||||
|
||||
part 'kernel_expression_generator_impl.dart';
|
||||
|
||||
abstract class KernelExpressionGenerator
|
||||
implements ExpressionGenerator<Expression, Statement, Arguments> {
|
||||
ExpressionGeneratorHelper<Expression, Statement, Arguments> get helper;
|
||||
|
||||
Token get token;
|
||||
|
||||
Forest<Expression, Statement, Token, Arguments> get forest;
|
||||
|
||||
@override
|
||||
Expression buildSimpleRead() {
|
||||
return _finish(_makeSimpleRead(), null);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression buildAssignment(Expression value, {bool voidContext: false}) {
|
||||
var complexAssignment = startComplexAssignment(value);
|
||||
return _finish(_makeSimpleWrite(value, voidContext, complexAssignment),
|
||||
complexAssignment);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression buildNullAwareAssignment(
|
||||
Expression value, DartType type, int offset,
|
||||
{bool voidContext: false}) {
|
||||
var complexAssignment = startComplexAssignment(value);
|
||||
if (voidContext) {
|
||||
var nullAwareCombiner = helper.storeOffset(
|
||||
forest.conditionalExpression(
|
||||
buildIsNull(_makeRead(complexAssignment), offset, helper),
|
||||
null,
|
||||
_makeWrite(value, false, complexAssignment),
|
||||
null,
|
||||
helper.storeOffset(forest.literalNull(null), offset)),
|
||||
offset);
|
||||
complexAssignment?.nullAwareCombiner = nullAwareCombiner;
|
||||
return _finish(nullAwareCombiner, complexAssignment);
|
||||
}
|
||||
var tmp = new VariableDeclaration.forValue(_makeRead(complexAssignment));
|
||||
var nullAwareCombiner = helper.storeOffset(
|
||||
forest.conditionalExpression(
|
||||
buildIsNull(new VariableGet(tmp), offset, helper),
|
||||
null,
|
||||
_makeWrite(value, false, complexAssignment),
|
||||
null,
|
||||
new VariableGet(tmp)),
|
||||
offset);
|
||||
complexAssignment?.nullAwareCombiner = nullAwareCombiner;
|
||||
return _finish(makeLet(tmp, nullAwareCombiner), complexAssignment);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
|
||||
{int offset: TreeNode.noOffset,
|
||||
bool voidContext: false,
|
||||
Procedure interfaceTarget,
|
||||
bool isPreIncDec: false}) {
|
||||
var complexAssignment = startComplexAssignment(value);
|
||||
complexAssignment?.isPreIncDec = isPreIncDec;
|
||||
var combiner = makeBinary(_makeRead(complexAssignment), binaryOperator,
|
||||
interfaceTarget, value, helper,
|
||||
offset: offset);
|
||||
complexAssignment?.combiner = combiner;
|
||||
return _finish(_makeWrite(combiner, voidContext, complexAssignment),
|
||||
complexAssignment);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression buildPrefixIncrement(Name binaryOperator,
|
||||
{int offset: TreeNode.noOffset,
|
||||
bool voidContext: false,
|
||||
Procedure interfaceTarget}) {
|
||||
return buildCompoundAssignment(
|
||||
binaryOperator, helper.storeOffset(forest.literalInt(1, null), offset),
|
||||
offset: offset,
|
||||
voidContext: voidContext,
|
||||
interfaceTarget: interfaceTarget,
|
||||
isPreIncDec: true);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression buildPostfixIncrement(Name binaryOperator,
|
||||
{int offset: TreeNode.noOffset,
|
||||
bool voidContext: false,
|
||||
Procedure interfaceTarget}) {
|
||||
if (voidContext) {
|
||||
return buildPrefixIncrement(binaryOperator,
|
||||
offset: offset, voidContext: true, interfaceTarget: interfaceTarget);
|
||||
}
|
||||
var rhs = helper.storeOffset(forest.literalInt(1, null), offset);
|
||||
var complexAssignment = startComplexAssignment(rhs);
|
||||
var value = new VariableDeclaration.forValue(_makeRead(complexAssignment));
|
||||
valueAccess() => new VariableGet(value);
|
||||
var combiner = makeBinary(
|
||||
valueAccess(), binaryOperator, interfaceTarget, rhs, helper,
|
||||
offset: offset);
|
||||
complexAssignment?.combiner = combiner;
|
||||
complexAssignment?.isPostIncDec = true;
|
||||
var dummy = new ShadowVariableDeclaration.forValue(
|
||||
_makeWrite(combiner, true, complexAssignment),
|
||||
helper.functionNestingLevel);
|
||||
return _finish(
|
||||
makeLet(value, makeLet(dummy, valueAccess())), complexAssignment);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression makeInvalidRead() {
|
||||
return buildThrowNoSuchMethodError(
|
||||
forest.literalNull(token), forest.argumentsEmpty(noLocation),
|
||||
isGetter: true);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression makeInvalidWrite(Expression value) {
|
||||
return buildThrowNoSuchMethodError(forest.literalNull(token),
|
||||
forest.arguments(<Expression>[value], noLocation),
|
||||
isSetter: true);
|
||||
}
|
||||
|
||||
Expression _makeSimpleRead() => _makeRead(null);
|
||||
|
||||
Expression _makeSimpleWrite(Expression value, bool voidContext,
|
||||
ShadowComplexAssignment complexAssignment) {
|
||||
return _makeWrite(value, voidContext, complexAssignment);
|
||||
}
|
||||
|
||||
Expression _makeRead(ShadowComplexAssignment complexAssignment);
|
||||
|
||||
Expression _makeWrite(Expression value, bool voidContext,
|
||||
ShadowComplexAssignment complexAssignment);
|
||||
|
||||
Expression _finish(
|
||||
Expression body, ShadowComplexAssignment complexAssignment) {
|
||||
if (complexAssignment != null) {
|
||||
complexAssignment.desugared = body;
|
||||
return complexAssignment;
|
||||
} else {
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a data structure for tracking the desugaring of a complex
|
||||
/// assignment expression whose right hand side is [rhs].
|
||||
ShadowComplexAssignment startComplexAssignment(Expression rhs) =>
|
||||
new ShadowIllegalAssignment(rhs);
|
||||
}
|
||||
|
||||
abstract class KernelGenerator = Generator<Expression, Statement, Arguments>
|
||||
with KernelExpressionGenerator;
|
||||
|
||||
class KernelVariableUseGenerator extends KernelGenerator
|
||||
with VariableUseGenerator<Expression, Statement, Arguments> {
|
||||
final VariableDeclaration variable;
|
||||
|
||||
final DartType promotedType;
|
||||
|
||||
KernelVariableUseGenerator(
|
||||
ExpressionGeneratorHelper<dynamic, dynamic, Arguments> helper,
|
||||
Token token,
|
||||
this.variable,
|
||||
this.promotedType)
|
||||
: super(helper, token);
|
||||
|
||||
@override
|
||||
String get plainNameForRead => variable.name;
|
||||
|
||||
@override
|
||||
Expression _makeRead(ShadowComplexAssignment complexAssignment) {
|
||||
var fact = helper.typePromoter
|
||||
.getFactForAccess(variable, helper.functionNestingLevel);
|
||||
var scope = helper.typePromoter.currentScope;
|
||||
var read = new ShadowVariableGet(variable, fact, scope)
|
||||
..fileOffset = offsetForToken(token);
|
||||
complexAssignment?.read = read;
|
||||
return read;
|
||||
}
|
||||
|
||||
@override
|
||||
Expression _makeWrite(Expression value, bool voidContext,
|
||||
ShadowComplexAssignment complexAssignment) {
|
||||
helper.typePromoter.mutateVariable(variable, helper.functionNestingLevel);
|
||||
var write = variable.isFinal || variable.isConst
|
||||
? makeInvalidWrite(value)
|
||||
: new VariableSet(variable, value)
|
||||
..fileOffset = offsetForToken(token);
|
||||
complexAssignment?.write = write;
|
||||
return write;
|
||||
}
|
||||
|
||||
@override
|
||||
Expression doInvocation(int offset, Arguments arguments) {
|
||||
return helper.buildMethodInvocation(buildSimpleRead(), callName, arguments,
|
||||
adjustForImplicitCall(plainNameForRead, offset),
|
||||
isImplicitCall: true);
|
||||
}
|
||||
|
||||
@override
|
||||
ShadowComplexAssignment startComplexAssignment(Expression rhs) =>
|
||||
new ShadowVariableAssignment(rhs);
|
||||
|
||||
@override
|
||||
void printOn(StringSink sink) {
|
||||
NameSystem syntheticNames = new NameSystem();
|
||||
sink.write(", variable: ");
|
||||
printNodeOn(variable, sink, syntheticNames: syntheticNames);
|
||||
sink.write(", promotedType: ");
|
||||
printNodeOn(promotedType, sink, syntheticNames: syntheticNames);
|
||||
}
|
||||
}
|
||||
|
||||
class KernelPropertyAccessGenerator extends KernelGenerator
|
||||
with PropertyAccessGenerator<Expression, Statement, Arguments> {
|
||||
final Expression receiver;
|
||||
|
||||
final Name name;
|
||||
|
||||
final Member getter;
|
||||
|
||||
final Member setter;
|
||||
|
||||
VariableDeclaration _receiverVariable;
|
||||
|
||||
KernelPropertyAccessGenerator.internal(
|
||||
ExpressionGeneratorHelper<dynamic, dynamic, Arguments> helper,
|
||||
Token token,
|
||||
this.receiver,
|
||||
this.name,
|
||||
this.getter,
|
||||
this.setter)
|
||||
: super(helper, token);
|
||||
|
||||
@override
|
||||
String get plainNameForRead => name.name;
|
||||
|
||||
receiverAccess() {
|
||||
_receiverVariable ??= new VariableDeclaration.forValue(receiver);
|
||||
return new VariableGet(_receiverVariable)
|
||||
..fileOffset = offsetForToken(token);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression doInvocation(int offset, Arguments arguments) {
|
||||
return helper.buildMethodInvocation(receiver, name, arguments, offset);
|
||||
}
|
||||
|
||||
@override
|
||||
ShadowComplexAssignment startComplexAssignment(Expression rhs) =>
|
||||
new ShadowPropertyAssign(receiver, rhs);
|
||||
|
||||
@override
|
||||
void printOn(StringSink sink) {
|
||||
NameSystem syntheticNames = new NameSystem();
|
||||
sink.write(", _receiverVariable: ");
|
||||
printNodeOn(_receiverVariable, sink, syntheticNames: syntheticNames);
|
||||
sink.write(", receiver: ");
|
||||
printNodeOn(receiver, sink, syntheticNames: syntheticNames);
|
||||
sink.write(", name: ");
|
||||
sink.write(name.name);
|
||||
sink.write(", getter: ");
|
||||
printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
|
||||
sink.write(", setter: ");
|
||||
printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
|
||||
}
|
||||
|
||||
@override
|
||||
Expression _makeSimpleRead() => new ShadowPropertyGet(receiver, name, getter)
|
||||
..fileOffset = offsetForToken(token);
|
||||
|
||||
@override
|
||||
Expression _makeSimpleWrite(Expression value, bool voidContext,
|
||||
ShadowComplexAssignment complexAssignment) {
|
||||
var write = new PropertySet(receiver, name, value, setter)
|
||||
..fileOffset = offsetForToken(token);
|
||||
complexAssignment?.write = write;
|
||||
return write;
|
||||
}
|
||||
|
||||
@override
|
||||
Expression _makeRead(ShadowComplexAssignment complexAssignment) {
|
||||
var read = new ShadowPropertyGet(receiverAccess(), name, getter)
|
||||
..fileOffset = offsetForToken(token);
|
||||
complexAssignment?.read = read;
|
||||
return read;
|
||||
}
|
||||
|
||||
@override
|
||||
Expression _makeWrite(Expression value, bool voidContext,
|
||||
ShadowComplexAssignment complexAssignment) {
|
||||
var write = new PropertySet(receiverAccess(), name, value, setter)
|
||||
..fileOffset = offsetForToken(token);
|
||||
complexAssignment?.write = write;
|
||||
return write;
|
||||
}
|
||||
|
||||
@override
|
||||
Expression _finish(
|
||||
Expression body, ShadowComplexAssignment complexAssignment) {
|
||||
return super._finish(makeLet(_receiverVariable, body), complexAssignment);
|
||||
}
|
||||
}
|
||||
|
||||
Expression makeLet(VariableDeclaration variable, Expression body) {
|
||||
if (variable == null) return body;
|
||||
return new Let(variable, body);
|
||||
}
|
||||
|
||||
Expression makeBinary(
|
||||
Expression left,
|
||||
Name operator,
|
||||
Procedure interfaceTarget,
|
||||
Expression right,
|
||||
ExpressionGeneratorHelper<Expression, Statement, Arguments> helper,
|
||||
{int offset: TreeNode.noOffset}) {
|
||||
return new ShadowMethodInvocation(
|
||||
left,
|
||||
operator,
|
||||
helper.storeOffset(
|
||||
helper.forest.castArguments(
|
||||
helper.forest.arguments(<Expression>[right], null)),
|
||||
offset),
|
||||
interfaceTarget: interfaceTarget)
|
||||
..fileOffset = offset;
|
||||
}
|
||||
|
||||
Expression buildIsNull(Expression value, int offset,
|
||||
ExpressionGeneratorHelper<dynamic, dynamic, dynamic> helper) {
|
||||
return makeBinary(value, equalsName, null,
|
||||
helper.storeOffset(helper.forest.literalNull(null), offset), helper,
|
||||
offset: offset);
|
||||
}
|
||||
|
||||
VariableDeclaration makeOrReuseVariable(Expression value) {
|
||||
// TODO: Devise a way to remember if a variable declaration was reused
|
||||
// or is fresh (hence needs a let binding).
|
||||
return new VariableDeclaration.forValue(value);
|
||||
}
|
||||
|
||||
int adjustForImplicitCall(String name, int offset) {
|
||||
// Normally the offset is at the start of the token, but in this case,
|
||||
// because we insert a '.call', we want it at the end instead.
|
||||
return offset + (name?.length ?? 0);
|
||||
}
|
||||
|
||||
bool isFieldOrGetter(Member member) {
|
||||
return member is Field || (member is Procedure && member.isGetter);
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -67,10 +67,10 @@ import '../type_inference/type_schema_environment.dart'
|
|||
|
||||
import 'body_builder.dart' show combineStatements;
|
||||
|
||||
import 'expression_generator.dart' show makeLet;
|
||||
|
||||
import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
|
||||
|
||||
import 'kernel_expression_generator.dart' show makeLet;
|
||||
|
||||
/// Indicates whether type inference involving conditional expressions should
|
||||
/// always use least upper bound.
|
||||
///
|
||||
|
|
|
@ -62,11 +62,11 @@ import '../../base/instrumentation.dart'
|
|||
|
||||
import '../fasta_codes.dart';
|
||||
|
||||
import '../kernel/expression_generator.dart' show buildIsNull;
|
||||
|
||||
import '../kernel/expression_generator_helper.dart'
|
||||
show ExpressionGeneratorHelper;
|
||||
|
||||
import '../kernel/kernel_expression_generator.dart' show buildIsNull;
|
||||
|
||||
import '../kernel/kernel_shadow_ast.dart'
|
||||
show
|
||||
getExplicitTypeArguments,
|
||||
|
|
|
@ -18,6 +18,7 @@ import 'package:kernel/ast.dart'
|
|||
Name,
|
||||
Procedure,
|
||||
ProcedureKind,
|
||||
Statement,
|
||||
StringLiteral,
|
||||
TypeParameter,
|
||||
VariableDeclaration,
|
||||
|
@ -44,18 +45,27 @@ import 'package:front_end/src/fasta/kernel/kernel_target.dart'
|
|||
import 'package:front_end/src/fasta/fasta_codes.dart'
|
||||
show Message, templateUnspecified;
|
||||
|
||||
import 'package:front_end/src/fasta/kernel/body_builder.dart'
|
||||
show DelayedAssignment, DelayedPostfixIncrement;
|
||||
|
||||
import 'package:front_end/src/fasta/kernel/expression_generator.dart'
|
||||
show Generator;
|
||||
|
||||
import 'package:front_end/src/fasta/kernel/kernel_body_builder.dart'
|
||||
show KernelBodyBuilder;
|
||||
|
||||
import 'package:front_end/src/fasta/kernel/kernel_expression_generator.dart'
|
||||
show
|
||||
DeferredAccessGenerator,
|
||||
Generator,
|
||||
IncompleteErrorGenerator,
|
||||
IncompletePropertyAccessGenerator,
|
||||
IndexedAccessGenerator,
|
||||
KernelPropertyAccessGenerator,
|
||||
KernelVariableUseGenerator,
|
||||
LargeIntAccessGenerator,
|
||||
LoadLibraryGenerator,
|
||||
NullAwarePropertyAccessGenerator,
|
||||
ParenthesizedExpressionGenerator,
|
||||
PropertyAccessGenerator,
|
||||
ReadOnlyAccessGenerator,
|
||||
SendAccessGenerator,
|
||||
StaticAccessGenerator,
|
||||
|
@ -65,18 +75,12 @@ import 'package:front_end/src/fasta/kernel/expression_generator.dart'
|
|||
ThisIndexedAccessGenerator,
|
||||
ThisPropertyAccessGenerator,
|
||||
TypeDeclarationAccessGenerator,
|
||||
UnresolvedNameGenerator,
|
||||
VariableUseGenerator;
|
||||
|
||||
import 'package:front_end/src/fasta/kernel/body_builder.dart'
|
||||
show DelayedAssignment, DelayedPostfixIncrement;
|
||||
|
||||
import 'package:front_end/src/fasta/kernel/kernel_body_builder.dart'
|
||||
show KernelBodyBuilder;
|
||||
UnresolvedNameGenerator;
|
||||
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token, scanString;
|
||||
|
||||
void check(String expected, Generator<Arguments> generator) {
|
||||
void check(
|
||||
String expected, Generator<Expression, Statement, Arguments> generator) {
|
||||
Expect.stringEquals(expected, "$generator");
|
||||
}
|
||||
|
||||
|
@ -123,8 +127,7 @@ main() {
|
|||
KernelBodyBuilder helper = new KernelBodyBuilder(
|
||||
libraryBuilder, null, null, null, null, null, null, false, uri, null);
|
||||
|
||||
Generator generator =
|
||||
new ThisAccessGenerator<Arguments>(helper, token, false);
|
||||
Generator generator = new ThisAccessGenerator(helper, token, false);
|
||||
|
||||
Library library = new Library(uri);
|
||||
Class cls = new Class();
|
||||
|
@ -136,98 +139,91 @@ main() {
|
|||
check(
|
||||
"DelayedAssignment(offset: 4, value: expression,"
|
||||
" assignmentOperator: +=)",
|
||||
new DelayedAssignment<Arguments>(
|
||||
new DelayedAssignment(
|
||||
helper, token, generator, expression, assignmentOperator));
|
||||
check(
|
||||
"DelayedPostfixIncrement(offset: 4, binaryOperator: +,"
|
||||
" interfaceTarget: $uri::#class1::myInterfaceTarget)",
|
||||
new DelayedPostfixIncrement<Arguments>(
|
||||
new DelayedPostfixIncrement(
|
||||
helper, token, generator, binaryOperator, interfaceTarget));
|
||||
check(
|
||||
"VariableUseGenerator(offset: 4, variable: dynamic #t1;\n,"
|
||||
" promotedType: void)",
|
||||
new VariableUseGenerator<Arguments>(helper, token, variable, type));
|
||||
new KernelVariableUseGenerator(helper, token, variable, type));
|
||||
check(
|
||||
"PropertyAccessGenerator(offset: 4, _receiverVariable: null,"
|
||||
" receiver: expression, name: bar, getter: $uri::myGetter,"
|
||||
" setter: $uri::mySetter)",
|
||||
new PropertyAccessGenerator<Arguments>.internal(
|
||||
new KernelPropertyAccessGenerator.internal(
|
||||
helper, token, expression, name, getter, setter));
|
||||
check(
|
||||
"ThisPropertyAccessGenerator(offset: 4, name: bar,"
|
||||
" getter: $uri::myGetter, setter: $uri::mySetter)",
|
||||
new ThisPropertyAccessGenerator<Arguments>(
|
||||
helper, token, name, getter, setter));
|
||||
new ThisPropertyAccessGenerator(helper, token, name, getter, setter));
|
||||
check(
|
||||
"NullAwarePropertyAccessGenerator(offset: 4,"
|
||||
" receiver: final dynamic #t1 = expression;\n,"
|
||||
" receiverExpression: expression, name: bar, getter: $uri::myGetter,"
|
||||
" setter: $uri::mySetter, type: void)",
|
||||
new NullAwarePropertyAccessGenerator<Arguments>(
|
||||
new NullAwarePropertyAccessGenerator(
|
||||
helper, token, expression, name, getter, setter, type));
|
||||
check(
|
||||
"SuperPropertyAccessGenerator(offset: 4, name: bar,"
|
||||
" getter: $uri::myGetter, setter: $uri::mySetter)",
|
||||
new SuperPropertyAccessGenerator<Arguments>(
|
||||
helper, token, name, getter, setter));
|
||||
new SuperPropertyAccessGenerator(helper, token, name, getter, setter));
|
||||
check(
|
||||
"IndexedAccessGenerator(offset: 4, receiver: expression, index: index,"
|
||||
" getter: $uri::myGetter, setter: $uri::mySetter,"
|
||||
" receiverVariable: null, indexVariable: null)",
|
||||
new IndexedAccessGenerator<Arguments>.internal(
|
||||
new IndexedAccessGenerator.internal(
|
||||
helper, token, expression, index, getter, setter));
|
||||
check(
|
||||
"ThisIndexedAccessGenerator(offset: 4, index: index,"
|
||||
" getter: $uri::myGetter, setter: $uri::mySetter, indexVariable: null)",
|
||||
new ThisIndexedAccessGenerator<Arguments>(
|
||||
helper, token, index, getter, setter));
|
||||
new ThisIndexedAccessGenerator(helper, token, index, getter, setter));
|
||||
check(
|
||||
"SuperIndexedAccessGenerator(offset: 4, index: index,"
|
||||
" getter: $uri::myGetter, setter: $uri::mySetter, indexVariable: null)",
|
||||
new SuperIndexedAccessGenerator<Arguments>(
|
||||
helper, token, index, getter, setter));
|
||||
new SuperIndexedAccessGenerator(helper, token, index, getter, setter));
|
||||
check(
|
||||
"StaticAccessGenerator(offset: 4, readTarget: $uri::myGetter,"
|
||||
" writeTarget: $uri::mySetter)",
|
||||
new StaticAccessGenerator<Arguments>(helper, token, getter, setter));
|
||||
new StaticAccessGenerator(helper, token, getter, setter));
|
||||
check(
|
||||
"LoadLibraryGenerator(offset: 4,"
|
||||
" builder: Instance of 'LoadLibraryBuilder')",
|
||||
new LoadLibraryGenerator<Arguments>(helper, token, loadLibraryBuilder));
|
||||
new LoadLibraryGenerator(helper, token, loadLibraryBuilder));
|
||||
check(
|
||||
"ThisAccessGenerator(offset: 4, isInitializer: false, isSuper: false)",
|
||||
new ThisAccessGenerator<Arguments>(helper, token, false));
|
||||
new ThisAccessGenerator(helper, token, false));
|
||||
check("IncompleteErrorGenerator(offset: 4, message: Unspecified)",
|
||||
new IncompleteErrorGenerator<Arguments>(helper, token, message));
|
||||
new IncompleteErrorGenerator(helper, token, message));
|
||||
check("SendAccessGenerator(offset: 4, name: bar, arguments: (\"arg\"))",
|
||||
new SendAccessGenerator<Arguments>(helper, token, name, arguments));
|
||||
new SendAccessGenerator(helper, token, name, arguments));
|
||||
check("IncompletePropertyAccessGenerator(offset: 4, name: bar)",
|
||||
new IncompletePropertyAccessGenerator<Arguments>(helper, token, name));
|
||||
new IncompletePropertyAccessGenerator(helper, token, name));
|
||||
check(
|
||||
"DeferredAccessGenerator(offset: 4, "
|
||||
"builder: Instance of 'PrefixBuilder',"
|
||||
" generator: ThisAccessGenerator(offset: 4, isInitializer: false,"
|
||||
" isSuper: false))",
|
||||
new DeferredAccessGenerator<Arguments>(
|
||||
helper, token, prefixBuilder, generator));
|
||||
new DeferredAccessGenerator(helper, token, prefixBuilder, generator));
|
||||
check(
|
||||
"ReadOnlyAccessGenerator(offset: 4, expression: expression,"
|
||||
" plainNameForRead: foo, value: null)",
|
||||
new ReadOnlyAccessGenerator<Arguments>(
|
||||
helper, token, expression, "foo"));
|
||||
new ReadOnlyAccessGenerator(helper, token, expression, "foo"));
|
||||
check("LargeIntAccessGenerator(offset: 4, lexeme: myToken)",
|
||||
new LargeIntAccessGenerator<Arguments>(helper, token));
|
||||
new LargeIntAccessGenerator(helper, token));
|
||||
check(
|
||||
"ParenthesizedExpressionGenerator(offset: 4, expression: expression,"
|
||||
" plainNameForRead: null, value: null)",
|
||||
new ParenthesizedExpressionGenerator<Arguments>(
|
||||
helper, token, expression));
|
||||
new ParenthesizedExpressionGenerator(helper, token, expression));
|
||||
check(
|
||||
"TypeDeclarationAccessGenerator(offset: 4, expression: T,"
|
||||
" plainNameForRead: foo, value: null)",
|
||||
new TypeDeclarationAccessGenerator<Arguments>(
|
||||
new TypeDeclarationAccessGenerator(
|
||||
helper, token, prefixBuilder, -1, declaration, "foo"));
|
||||
check("UnresolvedNameGenerator(offset: 4, name: bar)",
|
||||
new UnresolvedNameGenerator<Arguments>(helper, token, name));
|
||||
new UnresolvedNameGenerator(helper, token, name));
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue