ac477b9233
This adds internal nodes for VariableStatement, VariableDeclaration, Let, and ForStatement. The prepares for separating Variable from InternalVariable and allows for the removal of Variable.asVariableDeclaration. Change-Id: Ib0593f64b3d22ce99c187ab4af32c8dc8cbea6e9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/509980 Reviewed-by: Chloe Stefantsova <cstefantsova@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
1803 lines
48 KiB
Dart
1803 lines
48 KiB
Dart
// 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' as ast_helper show isThisExpression;
|
|
import 'package:kernel/ast.dart';
|
|
import 'package:kernel/src/printer.dart';
|
|
|
|
import '../base/problems.dart' show unsupported;
|
|
import '../type_inference/type_schema.dart';
|
|
import 'body_builder.dart';
|
|
import 'collections.dart'
|
|
show
|
|
ForElement,
|
|
ForInElement,
|
|
ForInMapEntry,
|
|
ForMapEntry,
|
|
IfCaseElement,
|
|
IfCaseMapEntry,
|
|
IfElement,
|
|
IfMapEntry,
|
|
NullAwareElement,
|
|
NullAwareMapEntry,
|
|
PatternForElement,
|
|
PatternForMapEntry,
|
|
SpreadElement;
|
|
import 'external_ast_helper.dart' as extern;
|
|
import 'internal_ast.dart';
|
|
|
|
Expression checkLibraryIsLoaded(int fileOffset, LibraryDependency dependency) {
|
|
return new CheckLibraryIsLoaded(dependency)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createAndPattern(
|
|
int fileOffset,
|
|
InternalPattern left,
|
|
InternalPattern right,
|
|
) {
|
|
return new InternalAndPattern(left, right, fileOffset: fileOffset);
|
|
}
|
|
|
|
ActualArguments createArguments(
|
|
int fileOffset, {
|
|
required List<Argument> arguments,
|
|
required bool hasNamedBeforePositional,
|
|
required int positionalCount,
|
|
}) {
|
|
return new ActualArguments(
|
|
argumentList: arguments,
|
|
hasNamedBeforePositional: hasNamedBeforePositional,
|
|
positionalCount: positionalCount,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
ActualArguments createArgumentsEmpty(int fileOffset) {
|
|
return createArguments(
|
|
fileOffset,
|
|
arguments: [],
|
|
hasNamedBeforePositional: false,
|
|
positionalCount: 0,
|
|
);
|
|
}
|
|
|
|
Expression createAsExpression(
|
|
int fileOffset,
|
|
Expression expression,
|
|
DartType type, {
|
|
bool forDynamic = false,
|
|
}) {
|
|
return new AsExpression(expression, type)
|
|
..fileOffset = fileOffset
|
|
..isForDynamic = forDynamic;
|
|
}
|
|
|
|
/// Return a representation of an assert that appears in a constructor's
|
|
/// initializer list.
|
|
AssertInitializer createAssertInitializer(
|
|
int fileOffset,
|
|
AssertStatement assertStatement,
|
|
) {
|
|
return new AssertInitializer(assertStatement)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of an assert that appears as a statement.
|
|
AssertStatement createAssertStatement(
|
|
int fileOffset,
|
|
Expression condition,
|
|
Expression? message,
|
|
int conditionStartOffset,
|
|
int conditionEndOffset,
|
|
) {
|
|
return new AssertStatement(
|
|
condition,
|
|
conditionStartOffset: conditionStartOffset,
|
|
conditionEndOffset: conditionEndOffset,
|
|
message: message,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createAssignedVariablePattern(
|
|
int fileOffset,
|
|
InternalVariable variable,
|
|
) {
|
|
return new InternalAssignedVariablePattern(variable, fileOffset: fileOffset);
|
|
}
|
|
|
|
Expression createAwaitExpression(int fileOffset, Expression operand) {
|
|
return new AwaitExpression(operand)..fileOffset = fileOffset;
|
|
}
|
|
|
|
BinaryExpression createBinary(
|
|
int fileOffset,
|
|
Expression left,
|
|
Name binaryName,
|
|
Expression right,
|
|
) {
|
|
return new BinaryExpression(left, binaryName, right)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a block of [statements] at the given
|
|
/// [fileOffset].
|
|
Block createBlock(
|
|
List<Statement> statements, {
|
|
required int fileOffset,
|
|
required int fileEndOffset,
|
|
}) {
|
|
List<Statement>? copy;
|
|
for (int i = 0; i < statements.length; i++) {
|
|
Statement statement = statements[i];
|
|
if (statement is _VariablesDeclaration) {
|
|
copy ??= new List<Statement>.of(statements.getRange(0, i));
|
|
for (InternalVariableDeclaration declaration in statement.declarations) {
|
|
copy.add(createVariableStatement(declaration));
|
|
}
|
|
} else if (copy != null) {
|
|
copy.add(statement);
|
|
}
|
|
}
|
|
return new Block(copy ?? statements)
|
|
..fileOffset = fileOffset
|
|
..fileEndOffset = fileEndOffset;
|
|
}
|
|
|
|
BlockExpression createBlockExpression(
|
|
Block body,
|
|
Expression value, {
|
|
required int fileOffset,
|
|
}) {
|
|
return new BlockExpression(body, value)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a boolean literal at the given [fileOffset].
|
|
/// The literal has the given [value].
|
|
BoolLiteral createBoolLiteral(int fileOffset, bool value) {
|
|
return new BoolLiteral(value)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a break statement.
|
|
Statement createBreakStatement(int fileOffset, Object? label) {
|
|
// TODO(johnniwinther): Use [label]?
|
|
return new BreakStatementImpl(isContinue: false)
|
|
..fileOffset = fileOffset
|
|
..target = label is LabeledStatement ? label : dummyLabeledStatement;
|
|
}
|
|
|
|
InternalPattern createCastPattern(
|
|
int fileOffset,
|
|
InternalPattern pattern,
|
|
DartType type,
|
|
) {
|
|
return new InternalCastPattern(pattern, type, fileOffset: fileOffset);
|
|
}
|
|
|
|
/// Return a representation of a catch clause.
|
|
InternalCatch createCatch(
|
|
int fileOffset,
|
|
DartType exceptionType,
|
|
InternalVariable? exceptionParameter,
|
|
InternalVariable? stackTraceParameter,
|
|
DartType stackTraceType,
|
|
Statement body,
|
|
) {
|
|
return new InternalCatch(
|
|
exception: exceptionParameter,
|
|
body: body,
|
|
guard: exceptionType,
|
|
stackTrace: stackTraceParameter,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
InternalVariable createCatchVariable({
|
|
required bool isClosureContextLoweringEnabled,
|
|
required String name,
|
|
required DartType type,
|
|
required bool isImplicitlyTyped,
|
|
required bool isWildcard,
|
|
required bool isFinal,
|
|
required int fileOffset,
|
|
}) {
|
|
if (isClosureContextLoweringEnabled) {
|
|
return new InternalCatchVariable(
|
|
astVariable: extern.createCatchVariable(
|
|
name: name,
|
|
type: type,
|
|
isWildcard: isWildcard,
|
|
isFinal: isFinal,
|
|
fileOffset: fileOffset,
|
|
),
|
|
isImplicitlyTyped: isImplicitlyTyped,
|
|
fileOffset: fileOffset,
|
|
);
|
|
} else {
|
|
return new VariableDeclarationImpl(
|
|
name,
|
|
fileOffset: fileOffset,
|
|
// [VariableDeclarationImpl] uses `null` to signal an omitted type.
|
|
type: isImplicitlyTyped ? null : type,
|
|
isWildcard: isWildcard,
|
|
isFinal: isFinal,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Return a representation of a conditional expression at the given
|
|
/// [fileOffset]. The [condition] is the expression preceding the question
|
|
/// mark. The [thenExpression] is the expression following the question mark.
|
|
/// The [elseExpression] is the expression following the colon.
|
|
ConditionalExpression createConditionalExpression(
|
|
int fileOffset,
|
|
Expression condition,
|
|
Expression thenExpression,
|
|
Expression elseExpression,
|
|
) {
|
|
return new ConditionalExpression(
|
|
condition,
|
|
thenExpression,
|
|
elseExpression,
|
|
const UnknownType(),
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createConstantPattern(Expression expression) {
|
|
return new InternalConstantPattern(
|
|
expression: expression,
|
|
fileOffset: expression.fileOffset,
|
|
);
|
|
}
|
|
|
|
ConstructorTearOff createConstructorTearOff(int fileOffset, Member target) {
|
|
assert(
|
|
target is Constructor || (target is Procedure && target.isFactory),
|
|
"Unexpected constructor tear off target: $target",
|
|
);
|
|
return new ConstructorTearOff(target)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a continue statement.
|
|
Statement createContinueStatement(int fileOffset, Object? label) {
|
|
// TODO(johnniwinther): Use [label]?
|
|
return new BreakStatementImpl(isContinue: true)..fileOffset = fileOffset;
|
|
}
|
|
|
|
Statement createContinueSwitchStatement({required int fileOffset}) {
|
|
return new InternalContinueSwitchStatement(fileOffset: fileOffset);
|
|
}
|
|
|
|
/// Return a representation of a do statement.
|
|
Statement createDoStatement(
|
|
int fileOffset,
|
|
Statement body,
|
|
Expression condition,
|
|
) {
|
|
return new DoStatement(body, condition)..fileOffset = fileOffset;
|
|
}
|
|
|
|
DotShorthand createDotShorthandContext(
|
|
int fileOffset,
|
|
Expression innerExpression,
|
|
) {
|
|
return new DotShorthand(innerExpression)..fileOffset = fileOffset;
|
|
}
|
|
|
|
DotShorthandInvocation createDotShorthandInvocation(
|
|
int fileOffset,
|
|
Name name,
|
|
TypeArguments? typeArguments,
|
|
ActualArguments arguments, {
|
|
required int nameOffset,
|
|
required bool isConst,
|
|
}) {
|
|
return new DotShorthandInvocation(
|
|
name,
|
|
typeArguments,
|
|
arguments,
|
|
nameOffset: nameOffset,
|
|
isConst: isConst,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
DotShorthandPropertyGet createDotShorthandPropertyGet(
|
|
int fileOffset,
|
|
Name name, {
|
|
required int nameOffset,
|
|
}) {
|
|
return new DotShorthandPropertyGet(name, nameOffset: nameOffset)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a double literal at the given [fileOffset]. The
|
|
/// literal has the given [value].
|
|
DoubleLiteral createDoubleLiteral(int fileOffset, double value) {
|
|
return new DoubleLiteral(value)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of an empty statement at the given [fileOffset].
|
|
Statement createEmptyStatement(int fileOffset) {
|
|
return new EmptyStatement()..fileOffset = fileOffset;
|
|
}
|
|
|
|
EqualsExpression createEquals(
|
|
int fileOffset,
|
|
Expression left,
|
|
Expression right, {
|
|
required bool isNot,
|
|
}) {
|
|
return new EqualsExpression(left, right, isNot: isNot)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
Expression createExpressionInvocation(
|
|
int fileOffset,
|
|
Expression expression,
|
|
TypeArguments? typeArguments,
|
|
ActualArguments arguments,
|
|
) {
|
|
return new ExpressionInvocation(expression, typeArguments, arguments)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of an expression statement at the given
|
|
/// [fileOffset] containing the [expression].
|
|
Statement createExpressionStatement(
|
|
Expression expression, {
|
|
required int fileOffset,
|
|
}) {
|
|
return new ExpressionStatement(expression)..fileOffset = fileOffset;
|
|
}
|
|
|
|
ForElement createForElement(
|
|
int fileOffset,
|
|
List<InternalVariableDeclaration> variables,
|
|
Expression? condition,
|
|
List<Expression> updates,
|
|
Expression body,
|
|
) {
|
|
return new ForElement(variables, condition, updates, body)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
ForInElement createForInElement(
|
|
InternalForInElement element,
|
|
Expression iterable,
|
|
Expression body, {
|
|
required bool isAsync,
|
|
required int forOffset,
|
|
required int fileOffset,
|
|
}) {
|
|
return new ForInElement(
|
|
element,
|
|
iterable,
|
|
body,
|
|
isAsync: isAsync,
|
|
forOffset: forOffset,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
ForInMapEntry createForInMapEntry(
|
|
InternalForInElement element,
|
|
Expression iterable,
|
|
MapLiteralEntry body, {
|
|
required bool isAsync,
|
|
required int forOffset,
|
|
required int fileOffset,
|
|
}) {
|
|
return new ForInMapEntry(
|
|
element,
|
|
iterable,
|
|
body,
|
|
isAsync: isAsync,
|
|
forOffset: forOffset,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
// Coverage-ignore(suite): Not run.
|
|
ForInStatement createForInStatement(
|
|
Variable variable,
|
|
Expression expression,
|
|
Statement body, {
|
|
required bool isAsync,
|
|
required int fileOffset,
|
|
required int bodyOffset,
|
|
}) {
|
|
return new ForInStatement(variable, expression, body, isAsync: isAsync)
|
|
..fileOffset = fileOffset
|
|
..bodyOffset = bodyOffset;
|
|
}
|
|
|
|
ForMapEntry createForMapEntry(
|
|
int fileOffset,
|
|
List<InternalVariableDeclaration> variables,
|
|
Expression? condition,
|
|
List<Expression> updates,
|
|
MapLiteralEntry body,
|
|
) {
|
|
return new ForMapEntry(variables, condition, updates, body)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a for statement.
|
|
Statement createForStatement(
|
|
int fileOffset,
|
|
List<InternalVariableDeclaration>? variables,
|
|
Expression? condition,
|
|
List<Expression> updaters,
|
|
Statement body,
|
|
) {
|
|
return new InternalForStatement(
|
|
variables ?? // Coverage-ignore(suite): Not run.
|
|
[],
|
|
condition,
|
|
updaters,
|
|
body,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalFunctionNode createFunctionNode({
|
|
required Statement? body,
|
|
required List<TypeParameter>? typeParameters,
|
|
required List<InternalVariable> positionalParameters,
|
|
required List<InternalVariable> namedParameters,
|
|
required int? requiredParameterCount,
|
|
required DartType? returnType,
|
|
required int fileOffset,
|
|
required int? fileEndOffset,
|
|
required AsyncMarker asyncMarker,
|
|
}) {
|
|
return new InternalFunctionNode(
|
|
returnType: returnType,
|
|
typeParameters: typeParameters ?? [],
|
|
positionalParameters: positionalParameters,
|
|
namedParameters: namedParameters,
|
|
requiredParameterCount: requiredParameterCount ?? 0,
|
|
asyncMarker: asyncMarker,
|
|
body: body,
|
|
fileOffset: fileOffset,
|
|
fileEndOffset: fileEndOffset ?? TreeNode.noOffset,
|
|
);
|
|
}
|
|
|
|
Statement createFunctionDeclaration({
|
|
required InternalVariable variable,
|
|
required int fileOffset,
|
|
}) {
|
|
return new InternalFunctionDeclaration(
|
|
variable: variable,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
Expression createFunctionExpression({
|
|
required InternalFunctionNode function,
|
|
required int fileOffset,
|
|
}) {
|
|
return new InternalFunctionExpression(
|
|
function: function,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
Expression createIfCaseElement(
|
|
int fileOffset, {
|
|
required List<Statement> prelude,
|
|
required Expression expression,
|
|
required InternalPatternGuard patternGuard,
|
|
required Expression then,
|
|
Expression? otherwise,
|
|
}) {
|
|
return new IfCaseElement(
|
|
prelude: prelude,
|
|
expression: expression,
|
|
internalPatternGuard: patternGuard,
|
|
then: then,
|
|
otherwise: otherwise,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
MapLiteralEntry createIfCaseMapEntry(
|
|
int fileOffset, {
|
|
required List<Statement> prelude,
|
|
required Expression expression,
|
|
required InternalPatternGuard patternGuard,
|
|
required MapLiteralEntry then,
|
|
MapLiteralEntry? otherwise,
|
|
}) {
|
|
return new IfCaseMapEntry(
|
|
prelude: prelude,
|
|
expression: expression,
|
|
internalPatternGuard: patternGuard,
|
|
then: then,
|
|
otherwise: otherwise,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
Statement createIfCaseStatement(
|
|
int fileOffset,
|
|
Expression expression,
|
|
InternalPatternGuard patternGuard,
|
|
Statement then,
|
|
Statement? otherwise,
|
|
) {
|
|
return new InternalIfCaseStatement(
|
|
expression: expression,
|
|
patternGuard: patternGuard,
|
|
then: then,
|
|
otherwise: otherwise,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
Expression createIfElement(
|
|
int fileOffset,
|
|
Expression condition,
|
|
Expression then, [
|
|
Expression? otherwise,
|
|
]) {
|
|
return new IfElement(condition, then, otherwise)..fileOffset = fileOffset;
|
|
}
|
|
|
|
MapLiteralEntry createIfMapEntry(
|
|
int fileOffset,
|
|
Expression condition,
|
|
MapLiteralEntry then, [
|
|
MapLiteralEntry? otherwise,
|
|
]) {
|
|
return new IfMapEntry(condition, then, otherwise)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of an `if` statement.
|
|
Statement createIfStatement(
|
|
int fileOffset,
|
|
Expression condition,
|
|
Statement thenStatement,
|
|
Statement? elseStatement,
|
|
) {
|
|
return new IfStatement(condition, thenStatement, elseStatement)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
IndexGet createIndexGet(
|
|
int fileOffset,
|
|
Expression receiver,
|
|
Expression index, {
|
|
required bool isNullAware,
|
|
}) {
|
|
return new IndexGet(receiver, index, isNullAware: isNullAware)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
IndexSet createIndexSet(
|
|
int fileOffset,
|
|
Expression receiver,
|
|
Expression index,
|
|
Expression value, {
|
|
required bool forEffect,
|
|
required bool isNullAware,
|
|
}) {
|
|
return new IndexSet(
|
|
receiver,
|
|
index,
|
|
value,
|
|
forEffect: forEffect,
|
|
isNullAware: isNullAware,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
Instantiation createInstantiation(
|
|
Expression expression,
|
|
List<DartType> typeArguments, {
|
|
required int fileOffset,
|
|
}) {
|
|
return new Instantiation(expression, typeArguments)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of an integer literal at the given [fileOffset].
|
|
/// The literal has the given [value].
|
|
Expression createIntLiteral(int fileOffset, int value, [String? literal]) {
|
|
return new InternalIntLiteral(value, literal, fileOffset: fileOffset);
|
|
}
|
|
|
|
Expression createIntLiteralLarge(
|
|
int fileOffset,
|
|
String strippedLiteral,
|
|
String literal,
|
|
) {
|
|
return new LargeIntLiteral(strippedLiteral, literal, fileOffset: fileOffset);
|
|
}
|
|
|
|
InternalPattern createInvalidPattern(
|
|
Expression expression, {
|
|
required List<InternalVariable> declaredVariables,
|
|
}) {
|
|
return new InternalInvalidPattern(
|
|
invalidExpression: expression,
|
|
declaredVariables: declaredVariables,
|
|
fileOffset: expression.fileOffset,
|
|
);
|
|
}
|
|
|
|
/// Return a representation of an `is` expression at the given [fileOffset].
|
|
/// The [operand] is the representation of the left operand. The [type] is a
|
|
/// representation of the type that is the right operand. If [notFileOffset]
|
|
/// is non-null the test is negated the that file offset.
|
|
Expression createIsExpression(
|
|
int fileOffset,
|
|
Expression operand,
|
|
DartType type, {
|
|
int? notFileOffset,
|
|
}) {
|
|
Expression result = new IsExpression(operand, type)..fileOffset = fileOffset;
|
|
if (notFileOffset != null) {
|
|
result = createNot(notFileOffset, result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// The given [statement] is being used as the target of either a break or
|
|
/// continue statement. Return the statement that should be used as the actual
|
|
/// target.
|
|
LabeledStatement createLabeledStatement(Statement statement) {
|
|
return new LabeledStatement(statement)..fileOffset = statement.fileOffset;
|
|
}
|
|
|
|
InternalVariable createLateVariable({
|
|
required bool isClosureContextLoweringEnabled,
|
|
required String? name,
|
|
required DartType? type,
|
|
bool isFinal = false,
|
|
bool isConst = false,
|
|
bool isWildcard = false,
|
|
required int fileOffset,
|
|
Expression? initializer,
|
|
bool hasDeclaredInitializer = false,
|
|
bool forSyntheticToken = false,
|
|
bool isImplicitlyTyped = false,
|
|
bool isStaticLate = false,
|
|
int fileEqualsOffset = TreeNode.noOffset,
|
|
}) {
|
|
if (isClosureContextLoweringEnabled) {
|
|
return new InternalLateVariable(
|
|
astVariable: extern.createLateVariable(
|
|
cosmeticName: name,
|
|
type: type,
|
|
isFinal: isFinal,
|
|
isConst: isConst,
|
|
isWildcard: isWildcard,
|
|
hasDeclaredInitializer: initializer != null,
|
|
fileOffset: fileOffset,
|
|
initializer: initializer,
|
|
),
|
|
forSyntheticToken: forSyntheticToken,
|
|
isImplicitlyTyped: isImplicitlyTyped,
|
|
isStaticLate: isStaticLate,
|
|
fileEqualsOffset: fileEqualsOffset,
|
|
fileOffset: fileOffset,
|
|
);
|
|
} else {
|
|
return new VariableDeclarationImpl(
|
|
name,
|
|
fileOffset: fileOffset,
|
|
forSyntheticToken: forSyntheticToken,
|
|
hasDeclaredInitializer: hasDeclaredInitializer,
|
|
initializer: initializer,
|
|
type: type,
|
|
isFinal: isFinal,
|
|
isConst: isConst,
|
|
isLate: true,
|
|
isStaticLate: isStaticLate,
|
|
isWildcard: isWildcard,
|
|
fileEqualsOffset: fileEqualsOffset,
|
|
);
|
|
}
|
|
}
|
|
|
|
InternalLet createLetForEffect({
|
|
required bool isClosureContextLoweringEnabled,
|
|
required Expression effect,
|
|
required DartType effectType,
|
|
required Expression expression,
|
|
}) {
|
|
return new InternalLet(
|
|
createSyntheticVariableForValue(
|
|
effect,
|
|
isClosureContextLoweringEnabled: isClosureContextLoweringEnabled,
|
|
type: effectType,
|
|
),
|
|
expression,
|
|
)..fileOffset = effect.fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a list literal at the given [fileOffset]. The
|
|
/// [isConst] is `true` if the literal is either explicitly or implicitly a
|
|
/// constant. The [typeArgument] is the representation of the single valid
|
|
/// type argument preceding the list literal, or `null` if there is no type
|
|
/// argument, there is more than one type argument, or if the type argument
|
|
/// cannot be resolved. The list of [expressions] is a list of the
|
|
/// representations of the list elements.
|
|
ListLiteral createListLiteral(
|
|
int fileOffset,
|
|
DartType typeArgument,
|
|
List<Expression> expressions, {
|
|
required bool isConst,
|
|
}) {
|
|
return new ListLiteral(
|
|
expressions,
|
|
typeArgument: typeArgument,
|
|
isConst: isConst,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createListPattern(
|
|
int fileOffset,
|
|
DartType? typeArgument,
|
|
List<InternalPattern> patterns,
|
|
) {
|
|
return new InternalListPattern(
|
|
typeArgument: typeArgument,
|
|
patterns: patterns,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
LoadLibrary createLoadLibrary(
|
|
int fileOffset,
|
|
LibraryDependency dependency,
|
|
ActualArguments? arguments,
|
|
) {
|
|
return new LoadLibraryImpl(dependency, arguments)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalVariable createLocalVariable({
|
|
required bool isClosureContextLoweringEnabled,
|
|
required String name,
|
|
required DartType? type,
|
|
bool isFinal = false,
|
|
bool isConst = false,
|
|
bool isWildcard = false,
|
|
required int fileOffset,
|
|
Expression? initializer,
|
|
bool hasDeclaredInitializer = false,
|
|
bool forSyntheticToken = false,
|
|
bool isImplicitlyTyped = false,
|
|
bool isStaticLate = false,
|
|
bool isLocalFunction = false,
|
|
int fileEqualsOffset = TreeNode.noOffset,
|
|
}) {
|
|
if (isClosureContextLoweringEnabled) {
|
|
return new InternalLocalVariable(
|
|
astVariable: new LocalVariable(
|
|
cosmeticName: name,
|
|
type: type,
|
|
isFinal: isFinal,
|
|
isConst: isConst,
|
|
isWildcard: isWildcard,
|
|
initializer: initializer,
|
|
hasDeclaredInitializer: hasDeclaredInitializer,
|
|
)..fileOffset = fileOffset,
|
|
forSyntheticToken: forSyntheticToken,
|
|
isImplicitlyTyped: isImplicitlyTyped,
|
|
fileOffset: fileOffset,
|
|
isStaticLate: isStaticLate,
|
|
isLocalFunction: isLocalFunction,
|
|
fileEqualsOffset: fileEqualsOffset,
|
|
);
|
|
} else {
|
|
return new VariableDeclarationImpl(
|
|
name,
|
|
fileOffset: fileOffset,
|
|
forSyntheticToken: forSyntheticToken,
|
|
hasDeclaredInitializer: hasDeclaredInitializer,
|
|
initializer: initializer,
|
|
type: type,
|
|
isFinal: isFinal,
|
|
isConst: isConst,
|
|
isLocalFunction: isLocalFunction,
|
|
isStaticLate: isStaticLate,
|
|
isWildcard: isWildcard,
|
|
fileEqualsOffset: fileEqualsOffset,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Return a representation of a logical expression at the given [fileOffset]
|
|
/// having the [leftOperand], [rightOperand] and the [operatorString]
|
|
/// (either `&&` or `||`).
|
|
Expression createLogicalExpression(
|
|
int fileOffset,
|
|
Expression leftOperand,
|
|
String operatorString,
|
|
Expression rightOperand,
|
|
) {
|
|
LogicalExpressionOperator operator;
|
|
if (operatorString == '&&') {
|
|
operator = LogicalExpressionOperator.AND;
|
|
} else if (operatorString == '||') {
|
|
operator = LogicalExpressionOperator.OR;
|
|
} else {
|
|
throw new UnsupportedError("Unhandled logical operator '$operatorString'");
|
|
}
|
|
|
|
return new LogicalExpression(leftOperand, operator, rightOperand)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a key/value pair in a literal map at the given
|
|
/// [fileOffset]. The [key] is the representation of the expression used to
|
|
/// compute the key. The [value] is the representation of the expression used
|
|
/// to compute the value.
|
|
MapLiteralEntry createMapEntry(
|
|
int fileOffset,
|
|
Expression key,
|
|
Expression value,
|
|
) {
|
|
return new MapLiteralEntry(key, value)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a map literal at the given [fileOffset]. The
|
|
/// [isConst] is `true` if the literal is either explicitly or implicitly a
|
|
/// constant. The [keyType] is the representation of the first type argument
|
|
/// preceding the map literal, or `null` if there are not exactly two type
|
|
/// arguments or if the first type argument cannot be resolved. The
|
|
/// [valueType] is the representation of the second type argument preceding
|
|
/// the map literal, or `null` if there are not exactly two type arguments or
|
|
/// if the second type argument cannot be resolved. The list of [entries] is a
|
|
/// list of the representations of the map entries.
|
|
MapLiteral createMapLiteral(
|
|
int fileOffset,
|
|
DartType keyType,
|
|
DartType valueType,
|
|
List<MapLiteralEntry> entries, {
|
|
required bool isConst,
|
|
}) {
|
|
return new MapLiteral(
|
|
entries,
|
|
keyType: keyType,
|
|
valueType: valueType,
|
|
isConst: isConst,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
MapLiteralEntry createMapLiteralEntry(
|
|
Expression key,
|
|
Expression value, {
|
|
required int fileOffset,
|
|
}) {
|
|
return new MapLiteralEntry(key, value)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createMapPattern(
|
|
int fileOffset,
|
|
DartType? keyType,
|
|
DartType? valueType,
|
|
List<InternalMapPatternEntry> entries,
|
|
) {
|
|
return new InternalMapPattern(
|
|
keyType: keyType,
|
|
valueType: valueType,
|
|
entries: entries,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
InternalMapPatternEntry createMapPatternEntry(
|
|
int fileOffset,
|
|
Expression key,
|
|
InternalPattern value,
|
|
) {
|
|
return new InternalMapPatternEntry(
|
|
key: key,
|
|
value: value,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
InternalMapPatternRestEntry createMapPatternRestEntry(int fileOffset) {
|
|
return new InternalMapPatternRestEntry(fileOffset: fileOffset);
|
|
}
|
|
|
|
Expression createMethodInvocation(
|
|
int fileOffset,
|
|
Expression expression,
|
|
Name name,
|
|
TypeArguments? typeArguments,
|
|
ActualArguments arguments, {
|
|
required bool isNullAware,
|
|
}) {
|
|
return new MethodInvocation(
|
|
expression,
|
|
name,
|
|
typeArguments,
|
|
arguments,
|
|
isNullAware: isNullAware,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
NamedExpression createNamedExpression(
|
|
String name,
|
|
Expression value, {
|
|
required int fileOffset,
|
|
}) {
|
|
return new NamedExpression(name, value)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalVariable createNamedParameter({
|
|
required bool isClosureContextLoweringEnabled,
|
|
required String parameterName,
|
|
required DartType type,
|
|
Expression? defaultValue,
|
|
bool isCovariantByDeclaration = false,
|
|
bool isRequired = false,
|
|
bool isInitializingFormal = false,
|
|
bool isSuperInitializingFormal = false,
|
|
bool isFinal = false,
|
|
bool hasDeclaredDefaultValue = false,
|
|
bool isLowered = false,
|
|
bool isSynthesized = false,
|
|
bool isWildcard = false,
|
|
required int fileOffset,
|
|
bool isImplicitlyTyped = false,
|
|
bool forSyntheticToken = false,
|
|
}) {
|
|
if (isClosureContextLoweringEnabled) {
|
|
return new InternalNamedParameter(
|
|
astVariable: extern.createNamedParameter(
|
|
parameterName: parameterName,
|
|
type: type,
|
|
defaultValue: defaultValue,
|
|
isCovariantByDeclaration: isCovariantByDeclaration,
|
|
isRequired: isRequired,
|
|
isInitializingFormal: isInitializingFormal,
|
|
isFinal: isFinal,
|
|
hasDeclaredDefaultType: hasDeclaredDefaultValue,
|
|
isSynthesized: isSynthesized,
|
|
isWildcard: isWildcard,
|
|
fileOffset: fileOffset,
|
|
),
|
|
isImplicitlyTyped: isImplicitlyTyped,
|
|
forSyntheticToken: forSyntheticToken,
|
|
fileOffset: fileOffset,
|
|
);
|
|
} else {
|
|
return new VariableDeclarationImpl(
|
|
parameterName,
|
|
fileOffset: fileOffset,
|
|
forSyntheticToken: forSyntheticToken,
|
|
hasDeclaredInitializer: hasDeclaredDefaultValue,
|
|
initializer: defaultValue,
|
|
// [VariableDeclarationImpl] uses `null` to signal an omitted type.
|
|
type: isImplicitlyTyped ? null : type,
|
|
isFinal: isFinal,
|
|
isInitializingFormal: isInitializingFormal,
|
|
isSuperInitializingFormal: isSuperInitializingFormal,
|
|
isCovariantByDeclaration: isCovariantByDeclaration,
|
|
isRequired: isRequired,
|
|
isLowered: isLowered,
|
|
isSynthesized: isSynthesized,
|
|
isWildcard: isWildcard,
|
|
);
|
|
}
|
|
}
|
|
|
|
InternalPattern createNamedPattern(
|
|
int fileOffset,
|
|
String name,
|
|
InternalPattern pattern,
|
|
) {
|
|
return new InternalNamedPattern(
|
|
name: name,
|
|
pattern: pattern,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
Expression createNot(int fileOffset, Expression operand) {
|
|
return new Not(operand)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createNullAssertPattern(
|
|
int fileOffset,
|
|
InternalPattern pattern,
|
|
) {
|
|
return new InternalNullAssertPattern(
|
|
pattern: pattern,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
Expression createNullAwareElement(int fileOffset, Expression expression) {
|
|
return new NullAwareElement(expression)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a null-aware key/value pair, were either the
|
|
/// key or the value might be `null`, in a literal map at the given
|
|
/// [fileOffset]. The [key] is the representation of the expression used to
|
|
/// compute the key. The [value] is the representation of the expression used
|
|
/// to compute the value.
|
|
NullAwareMapEntry createNullAwareMapEntry(
|
|
int fileOffset, {
|
|
required bool isKeyNullAware,
|
|
required Expression key,
|
|
required bool isValueNullAware,
|
|
required Expression value,
|
|
}) {
|
|
return new NullAwareMapEntry(
|
|
isKeyNullAware: isKeyNullAware,
|
|
key: key,
|
|
isValueNullAware: isValueNullAware,
|
|
value: value,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
NullCheck createNullCheck(int fileOffset, Expression expression) {
|
|
return new NullCheck(expression)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createNullCheckPattern(
|
|
int fileOffset,
|
|
InternalPattern pattern,
|
|
) {
|
|
return new InternalNullCheckPattern(pattern: pattern, fileOffset: fileOffset);
|
|
}
|
|
|
|
/// Return a representation of a null literal at the given [fileOffset].
|
|
NullLiteral createNullLiteral(int fileOffset) {
|
|
return new NullLiteral()..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createOrPattern(
|
|
int fileOffset,
|
|
InternalPattern left,
|
|
InternalPattern right, {
|
|
required List<InternalVariable> orPatternJointVariables,
|
|
}) {
|
|
return new InternalOrPattern(
|
|
left,
|
|
right,
|
|
orPatternJointVariables: orPatternJointVariables,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
InternalPattern createObjectPattern({
|
|
required DartType requiredType,
|
|
required List<InternalNamedPattern> fields,
|
|
required Typedef? typedef,
|
|
required bool hasExplicitTypeArguments,
|
|
required int fileOffset,
|
|
}) {
|
|
return new InternalObjectPattern(
|
|
requiredType: requiredType,
|
|
fields: fields,
|
|
typedef: typedef,
|
|
hasExplicitTypeArguments: hasExplicitTypeArguments,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
ParenthesizedExpression createParenthesized(
|
|
int fileOffset,
|
|
Expression expression,
|
|
) {
|
|
return new ParenthesizedExpression(expression)..fileOffset = fileOffset;
|
|
}
|
|
|
|
Expression createPatternAssignment(
|
|
int fileOffset,
|
|
InternalPattern pattern,
|
|
Expression expression,
|
|
) {
|
|
return new InternalPatternAssignment(
|
|
pattern: pattern,
|
|
expression: expression,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
PatternForElement createPatternForElement(
|
|
int fileOffset, {
|
|
required InternalPatternVariableDeclaration patternVariableDeclaration,
|
|
required List<InternalVariableDeclaration> intermediateVariables,
|
|
required List<InternalVariableDeclaration> variables,
|
|
required Expression? condition,
|
|
required List<Expression> updates,
|
|
required Expression body,
|
|
}) {
|
|
return new PatternForElement(
|
|
internalPatternVariableDeclaration: patternVariableDeclaration,
|
|
intermediateVariables: intermediateVariables,
|
|
internalVariables: variables,
|
|
condition: condition,
|
|
updates: updates,
|
|
body: body,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
PatternForMapEntry createPatternForMapEntry(
|
|
int fileOffset, {
|
|
required InternalPatternVariableDeclaration patternVariableDeclaration,
|
|
required List<InternalVariableDeclaration> intermediateVariables,
|
|
required List<InternalVariableDeclaration> variableInitializations,
|
|
required Expression? condition,
|
|
required List<Expression> updates,
|
|
required MapLiteralEntry body,
|
|
}) {
|
|
return new PatternForMapEntry(
|
|
internalPatternVariableDeclaration: patternVariableDeclaration,
|
|
intermediateVariables: intermediateVariables,
|
|
internalVariables: variableInitializations,
|
|
condition: condition,
|
|
updates: updates,
|
|
body: body,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPatternGuard createPatternGuard(
|
|
int fileOffset,
|
|
InternalPattern pattern, [
|
|
Expression? guard,
|
|
]) {
|
|
return new InternalPatternGuard(
|
|
pattern: pattern,
|
|
guard: guard,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
InternalPatternSwitchCase createPatternSwitchCase(
|
|
int fileOffset,
|
|
List<int> caseOffsets,
|
|
List<InternalPatternGuard> patternGuards,
|
|
Statement body, {
|
|
required bool isDefault,
|
|
required List<Label>? labels,
|
|
required List<InternalVariable>? jointVariables,
|
|
required List<int>? jointVariableFirstUseOffsets,
|
|
}) {
|
|
return new InternalPatternSwitchCase(
|
|
caseOffsets: caseOffsets,
|
|
patternGuards: patternGuards,
|
|
body: body,
|
|
isDefault: isDefault,
|
|
labels: labels,
|
|
jointVariables: jointVariables ?? [],
|
|
jointVariableFirstUseOffsets: jointVariableFirstUseOffsets,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
Statement createPatternSwitchStatement(
|
|
int fileOffset,
|
|
Expression expression,
|
|
List<InternalPatternSwitchCase> cases,
|
|
) {
|
|
return new InternalPatternSwitchStatement(
|
|
expression: expression,
|
|
cases: cases,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
Statement createPatternVariableDeclaration(
|
|
int fileOffset,
|
|
InternalPattern pattern,
|
|
Expression initializer, {
|
|
required bool isFinal,
|
|
}) {
|
|
return new InternalPatternVariableDeclaration(
|
|
pattern: pattern,
|
|
initializer: initializer,
|
|
isFinal: isFinal,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
InternalVariable createPositionalParameter({
|
|
required bool isClosureContextLoweringEnabled,
|
|
String? cosmeticName,
|
|
required DartType type,
|
|
bool isImplicitlyTyped = false,
|
|
Expression? defaultValue,
|
|
bool hasDeclaredDefaultValue = false,
|
|
bool isCovariantByDeclaration = false,
|
|
bool isRequired = false,
|
|
bool isInitializingFormal = false,
|
|
bool isSuperInitializingFormal = false,
|
|
bool isFinal = false,
|
|
bool isLowered = false,
|
|
bool isSynthesized = false,
|
|
bool isWildcard = false,
|
|
required int fileOffset,
|
|
bool forSyntheticToken = false,
|
|
}) {
|
|
if (isClosureContextLoweringEnabled) {
|
|
return new InternalPositionalParameter(
|
|
astVariable: extern.createPositionalParameter(
|
|
cosmeticName: cosmeticName,
|
|
type: type,
|
|
defaultValue: defaultValue,
|
|
isCovariantByDeclaration: isCovariantByDeclaration,
|
|
isInitializingFormal: isInitializingFormal,
|
|
isFinal: isFinal,
|
|
hasDeclaredDefaultType: hasDeclaredDefaultValue,
|
|
isLowered: isLowered,
|
|
isSynthesized: isSynthesized,
|
|
isWildcard: isWildcard,
|
|
fileOffset: fileOffset,
|
|
),
|
|
forSyntheticToken: forSyntheticToken,
|
|
isImplicitlyTyped: isImplicitlyTyped,
|
|
fileOffset: fileOffset,
|
|
);
|
|
} else {
|
|
return new VariableDeclarationImpl(
|
|
cosmeticName,
|
|
fileOffset: fileOffset,
|
|
forSyntheticToken: forSyntheticToken,
|
|
hasDeclaredInitializer: hasDeclaredDefaultValue,
|
|
initializer: defaultValue,
|
|
// [VariableDeclarationImpl] uses `null` to signal an omitted
|
|
// type.
|
|
type: isImplicitlyTyped ? null : type,
|
|
isFinal: isFinal,
|
|
isInitializingFormal: isInitializingFormal,
|
|
isSuperInitializingFormal: isSuperInitializingFormal,
|
|
isCovariantByDeclaration: isCovariantByDeclaration,
|
|
isRequired: isRequired,
|
|
isLowered: isLowered,
|
|
isSynthesized: isSynthesized,
|
|
isWildcard: isWildcard,
|
|
);
|
|
}
|
|
}
|
|
|
|
Expression createPropertyGet(
|
|
int fileOffset,
|
|
Expression receiver,
|
|
Name name, {
|
|
required bool isNullAware,
|
|
}) {
|
|
return new PropertyGet(receiver, name, isNullAware: isNullAware)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
Expression createPropertySet(
|
|
int fileOffset,
|
|
Expression receiver,
|
|
Name name,
|
|
Expression value, {
|
|
required bool forEffect,
|
|
bool readOnlyReceiver = false,
|
|
required bool isNullAware,
|
|
}) {
|
|
return new PropertySet(
|
|
receiver,
|
|
name,
|
|
value,
|
|
forEffect: forEffect,
|
|
readOnlyReceiver: readOnlyReceiver,
|
|
isNullAware: isNullAware,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createRecordPattern(
|
|
int fileOffset,
|
|
List<InternalPattern> patterns,
|
|
) {
|
|
return new InternalRecordPattern(patterns: patterns, fileOffset: fileOffset);
|
|
}
|
|
|
|
RedirectingFactoryTearOff createRedirectingFactoryTearOff(
|
|
int fileOffset,
|
|
Procedure procedure,
|
|
) {
|
|
assert(procedure.isRedirectingFactory);
|
|
return new RedirectingFactoryTearOff(procedure)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createRelationalPattern(
|
|
int fileOffset,
|
|
RelationalPatternKind kind,
|
|
Expression expression,
|
|
) {
|
|
return new InternalRelationalPattern(
|
|
kind: kind,
|
|
expression: expression,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
InternalPattern createRestPattern(int fileOffset, InternalPattern? subPattern) {
|
|
return new InternalRestPattern(
|
|
subPattern: subPattern,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
/// Return a representation of a rethrow statement consisting of the
|
|
/// rethrow at [rethrowFileOffset] and the statement at [statementFileOffset].
|
|
Statement createRethrowStatement(
|
|
int rethrowFileOffset,
|
|
int statementFileOffset,
|
|
) {
|
|
return new ExpressionStatement(new Rethrow()..fileOffset = rethrowFileOffset)
|
|
..fileOffset = statementFileOffset;
|
|
}
|
|
|
|
/// Return a representation of a return statement.
|
|
Statement createReturnStatement(
|
|
int fileOffset,
|
|
Expression? expression, {
|
|
bool isArrow = true,
|
|
}) {
|
|
return new ReturnStatementImpl(isArrow, expression)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a set literal at the given [fileOffset]. The
|
|
/// [isConst] is `true` if the literal is either explicitly or implicitly a
|
|
/// constant. The [typeArgument] is the representation of the single valid
|
|
/// type argument preceding the set literal, or `null` if there is no type
|
|
/// argument, there is more than one type argument, or if the type argument
|
|
/// cannot be resolved. The list of [expressions] is a list of the
|
|
/// representations of the set elements.
|
|
SetLiteral createSetLiteral(
|
|
int fileOffset,
|
|
DartType typeArgument,
|
|
List<Expression> expressions, {
|
|
required bool isConst,
|
|
}) {
|
|
return new SetLiteral(
|
|
expressions,
|
|
typeArgument: typeArgument,
|
|
isConst: isConst,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
Expression createSpreadElement(
|
|
int fileOffset,
|
|
Expression expression, {
|
|
required bool isNullAware,
|
|
}) {
|
|
return new SpreadElement(expression, isNullAware: isNullAware)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
StaticGet createStaticGet(int fileOffset, Member target) {
|
|
assert(target is Field || (target is Procedure && target.isGetter));
|
|
return new StaticGet(target)..fileOffset = fileOffset;
|
|
}
|
|
|
|
StaticSet createStaticSet(
|
|
Member target,
|
|
Expression value, {
|
|
required int fileOffset,
|
|
}) {
|
|
assert(target is Field || (target is Procedure && target.isSetter));
|
|
return new StaticSet(target, value)..fileOffset = fileOffset;
|
|
}
|
|
|
|
StaticTearOff createStaticTearOff(int fileOffset, Procedure procedure) {
|
|
assert(
|
|
procedure.kind == ProcedureKind.Method,
|
|
"Unexpected static tear off target: $procedure",
|
|
);
|
|
assert(
|
|
!procedure.isRedirectingFactory,
|
|
"Unexpected static tear off target: $procedure",
|
|
);
|
|
return new StaticTearOff(procedure)..fileOffset = fileOffset;
|
|
}
|
|
|
|
Expression createStringConcatenation(
|
|
int fileOffset,
|
|
List<Expression> expressions,
|
|
) {
|
|
assert(fileOffset != TreeNode.noOffset);
|
|
return new StringConcatenation(expressions)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a simple string literal at the given
|
|
/// [fileOffset]. The literal has the given [value]. This does not include
|
|
/// either adjacent strings or interpolated strings.
|
|
StringLiteral createStringLiteral(int fileOffset, String value) {
|
|
return new StringLiteral(value)..fileOffset = fileOffset;
|
|
}
|
|
|
|
Expression createSuperMethodInvocation(
|
|
int fileOffset,
|
|
Name name,
|
|
Procedure procedure,
|
|
TypeArguments? typeArguments,
|
|
ActualArguments arguments,
|
|
) {
|
|
return new InternalSuperMethodInvocation(
|
|
name,
|
|
typeArguments,
|
|
arguments,
|
|
procedure,
|
|
)..fileOffset = fileOffset;
|
|
}
|
|
|
|
SuperPropertyGet createSuperPropertyGet(
|
|
Expression receiver,
|
|
Name name,
|
|
Member target, {
|
|
required int fileOffset,
|
|
}) {
|
|
return new SuperPropertyGet(receiver, name, target)..fileOffset = fileOffset;
|
|
}
|
|
|
|
SuperPropertySet createSuperPropertySet(
|
|
Expression receiver,
|
|
Name name,
|
|
Member target,
|
|
Expression value, {
|
|
required int fileOffset,
|
|
}) {
|
|
return new SuperPropertySet(receiver, name, value, target)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
Expression createSwitchExpression(
|
|
int fileOffset,
|
|
Expression expression,
|
|
List<InternalSwitchExpressionCase> cases,
|
|
) {
|
|
return new InternalSwitchExpression(
|
|
expression: expression,
|
|
cases: cases,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
InternalSwitchExpressionCase createSwitchExpressionCase(
|
|
int fileOffset,
|
|
InternalPatternGuard patternGuard,
|
|
Expression expression,
|
|
) {
|
|
return new InternalSwitchExpressionCase(
|
|
patternGuard: patternGuard,
|
|
expression: expression,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
Statement createSwitchStatement(
|
|
Expression expression,
|
|
List<InternalSwitchStatementCase> cases, {
|
|
required int fileOffset,
|
|
}) {
|
|
return new InternalRegularSwitchStatement(
|
|
expression: expression,
|
|
cases: cases,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
InternalSwitchStatementCase createSwitchStatementCase({
|
|
required List<Expression> expressions,
|
|
required List<int> expressionOffsets,
|
|
required Statement body,
|
|
required bool isDefault,
|
|
required List<int> caseOffsets,
|
|
required List<Label>? labels,
|
|
required int fileOffset,
|
|
}) {
|
|
return new InternalSwitchStatementCase(
|
|
caseOffsets: caseOffsets,
|
|
expressions: expressions,
|
|
expressionOffsets: expressionOffsets,
|
|
body: body,
|
|
isDefault: isDefault,
|
|
labels: labels,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
/// Return a representation of a symbol literal defined by [value] at the
|
|
/// given [fileOffset].
|
|
SymbolLiteral createSymbolLiteral(int fileOffset, String value) {
|
|
return new SymbolLiteral(value)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalVariable createSyntheticVariable({
|
|
String? name,
|
|
required bool isClosureContextLoweringEnabled,
|
|
DartType? type,
|
|
required int fileOffset,
|
|
Expression? initializer,
|
|
bool isFinal = false,
|
|
bool isSynthesized = false,
|
|
}) {
|
|
if (isClosureContextLoweringEnabled) {
|
|
// Coverage-ignore-block(suite): Not run.
|
|
return new InternalSyntheticVariable(
|
|
astVariable: new SyntheticVariable(
|
|
cosmeticName: name,
|
|
type: type ?? const DynamicType(),
|
|
isFinal: isFinal,
|
|
initializer: initializer,
|
|
)..fileOffset = fileOffset,
|
|
isImplicitlyTyped: type == null,
|
|
fileOffset: fileOffset,
|
|
);
|
|
} else {
|
|
return new VariableDeclarationImpl(
|
|
name,
|
|
type: type,
|
|
initializer: initializer,
|
|
isFinal: isFinal,
|
|
isSynthesized: isSynthesized,
|
|
hasDeclaredInitializer: initializer != null,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
}
|
|
|
|
InternalVariable createSyntheticVariableForEffect(
|
|
Expression expression, {
|
|
required bool isClosureContextLoweringEnabled,
|
|
}) {
|
|
return createSyntheticVariable(
|
|
initializer: expression,
|
|
isClosureContextLoweringEnabled: isClosureContextLoweringEnabled,
|
|
isFinal: true,
|
|
fileOffset: expression.fileOffset,
|
|
type: const DynamicType(),
|
|
isSynthesized: true,
|
|
);
|
|
}
|
|
|
|
InternalVariable createSyntheticVariableForValue(
|
|
Expression initializer, {
|
|
required bool isClosureContextLoweringEnabled,
|
|
DartType? type,
|
|
}) {
|
|
return createSyntheticVariable(
|
|
initializer: initializer,
|
|
isClosureContextLoweringEnabled: isClosureContextLoweringEnabled,
|
|
isFinal: true,
|
|
fileOffset: initializer.fileOffset,
|
|
type: type,
|
|
isSynthesized: true,
|
|
);
|
|
}
|
|
|
|
Expression createThisExpression({required int fileOffset}) {
|
|
return new ThisExpression()..fileOffset = fileOffset;
|
|
}
|
|
|
|
ThisVariable createThisVariable({
|
|
required DartType type,
|
|
required int fileOffset,
|
|
}) {
|
|
return new ThisVariable(type: type)..fileOffset = fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a throw expression at the given [fileOffset].
|
|
Expression createThrow(int fileOffset, Expression expression) {
|
|
return new Throw(expression)..fileOffset = fileOffset;
|
|
}
|
|
|
|
Statement createTryStatement(
|
|
int fileOffset,
|
|
Statement tryBlock,
|
|
List<InternalCatch>? catchBlocks,
|
|
Statement? finallyBlock,
|
|
) {
|
|
return new TryStatement(tryBlock, catchBlocks ?? [], finallyBlock)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
TypedefTearOff createTypedefTearOff(
|
|
int fileOffset,
|
|
List<StructuralParameter> typeParameters,
|
|
Expression expression,
|
|
List<DartType> typeArguments,
|
|
) {
|
|
return new TypedefTearOff(typeParameters, expression, typeArguments)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
TypeLiteral createTypeLiteral(int fileOffset, DartType type) {
|
|
return new TypeLiteral(type)..fileOffset = fileOffset;
|
|
}
|
|
|
|
TypeParameterType createTypeParameterTypeWithDefaultNullabilityForLibrary(
|
|
TypeParameter typeParameter,
|
|
Library library,
|
|
) {
|
|
return new TypeParameterType.withDefaultNullability(typeParameter);
|
|
}
|
|
|
|
UnaryExpression createUnary(
|
|
int fileOffset,
|
|
Name unaryName,
|
|
Expression expression,
|
|
) {
|
|
return new UnaryExpression(unaryName, expression)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalVariableDeclaration createVariableDeclaration(
|
|
InternalVariable variable, {
|
|
int? fileOffset,
|
|
}) {
|
|
return new InternalVariableDeclaration(variable)
|
|
..fileOffset = fileOffset ?? variable.fileOffset;
|
|
}
|
|
|
|
InternalVariableGet createVariableGet(
|
|
InternalVariable variable, {
|
|
required int fileOffset,
|
|
}) {
|
|
return new InternalVariableGet(variable)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createVariablePattern(
|
|
int fileOffset,
|
|
DartType? type,
|
|
InternalVariable variable,
|
|
) {
|
|
return new InternalVariablePattern(
|
|
type: type,
|
|
variable: variable,
|
|
fileOffset: fileOffset,
|
|
);
|
|
}
|
|
|
|
InternalVariableSet createVariableSet(
|
|
InternalVariable variable,
|
|
Expression value, {
|
|
required int fileOffset,
|
|
}) {
|
|
return new InternalVariableSet(variable, value)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalVariableStatement createVariableStatement(
|
|
InternalVariableDeclaration declaration, {
|
|
int? fileOffset,
|
|
}) {
|
|
return new InternalVariableStatement(declaration)
|
|
..fileOffset = fileOffset ?? declaration.fileOffset;
|
|
}
|
|
|
|
/// Return a representation of a while statement at the given [fileOffset]
|
|
/// consisting of the given [condition] and [body].
|
|
Statement createWhileStatement(
|
|
int fileOffset,
|
|
Expression condition,
|
|
Statement body,
|
|
) {
|
|
return new WhileStatement(condition, body)..fileOffset = fileOffset;
|
|
}
|
|
|
|
InternalPattern createWildcardPattern(int fileOffset, DartType? type) {
|
|
return new InternalWildcardPattern(type: type, fileOffset: fileOffset);
|
|
}
|
|
|
|
/// Return a representation of a yield statement at the given [fileOffset]
|
|
/// of the given [expression]. If [isYieldStar] is `true` the created
|
|
/// statement is a yield* statement.
|
|
Statement createYieldStatement(
|
|
int fileOffset,
|
|
Expression expression, {
|
|
required bool isYieldStar,
|
|
}) {
|
|
return new YieldStatement(expression, isYieldStar: isYieldStar)
|
|
..fileOffset = fileOffset;
|
|
}
|
|
|
|
bool isErroneousNode(Object? node) {
|
|
if (node is ExpressionStatement) {
|
|
// Coverage-ignore-block(suite): Not run.
|
|
ExpressionStatement statement = node;
|
|
node = statement.expression;
|
|
}
|
|
if (node is Variable) {
|
|
// Coverage-ignore-block(suite): Not run.
|
|
Variable variable = node;
|
|
node = variable.initializer;
|
|
}
|
|
if (node is Let) {
|
|
// Coverage-ignore-block(suite): Not run.
|
|
Let let = node;
|
|
node = let.variable.initializer;
|
|
}
|
|
return node is InvalidExpression;
|
|
}
|
|
|
|
bool isThisExpression(Object node) =>
|
|
node is Expression && ast_helper.isThisExpression(node);
|
|
|
|
bool isVariablesDeclaration(Object? node) => node is _VariablesDeclaration;
|
|
|
|
_VariablesDeclaration variablesDeclaration(
|
|
List<InternalVariableDeclaration> declarations,
|
|
Uri uri,
|
|
) {
|
|
return new _VariablesDeclaration(declarations, uri);
|
|
}
|
|
|
|
List<InternalVariableDeclaration> variablesDeclarationExtractDeclarations(
|
|
Object? variablesDeclaration,
|
|
) {
|
|
return (variablesDeclaration as _VariablesDeclaration).declarations;
|
|
}
|
|
|
|
Statement wrapVariables(Statement statement) {
|
|
if (statement is _VariablesDeclaration) {
|
|
return new Block(
|
|
new List<Statement>.generate(
|
|
statement.declarations.length,
|
|
(int index) => createVariableStatement(statement.declarations[index]),
|
|
growable: true,
|
|
),
|
|
)..fileOffset = statement.fileOffset;
|
|
} else if (statement is InternalVariableStatement) {
|
|
return new Block(<Statement>[statement])..fileOffset = statement.fileOffset;
|
|
} else {
|
|
return statement;
|
|
}
|
|
}
|
|
|
|
class _VariablesDeclaration extends AuxiliaryStatement {
|
|
final List<InternalVariableDeclaration> declarations;
|
|
final Uri uri;
|
|
|
|
new(this.declarations, this.uri) {
|
|
setParents(declarations, this);
|
|
}
|
|
|
|
@override
|
|
// Coverage-ignore(suite): Not run.
|
|
R accept<R>(v) {
|
|
throw unsupported("accept", fileOffset, uri);
|
|
}
|
|
|
|
@override
|
|
// Coverage-ignore(suite): Not run.
|
|
R accept1<R, A>(v, arg) {
|
|
throw unsupported("accept1", fileOffset, uri);
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return "_VariablesDeclaration(${toStringInternal()})";
|
|
}
|
|
|
|
@override
|
|
// Coverage-ignore(suite): Not run.
|
|
void toTextInternal(AstPrinter printer) {
|
|
for (int index = 0; index < declarations.length; index++) {
|
|
if (index > 0) {
|
|
printer.write(', ');
|
|
}
|
|
printer.writeVariableInitialization(
|
|
declarations[index].variable.astVariable,
|
|
includeModifiersAndType: index == 0,
|
|
);
|
|
}
|
|
printer.write(';');
|
|
}
|
|
|
|
@override
|
|
// Coverage-ignore(suite): Not run.
|
|
Never transformChildren(v) {
|
|
throw unsupported("transformChildren", fileOffset, uri);
|
|
}
|
|
|
|
@override
|
|
// Coverage-ignore(suite): Not run.
|
|
Never transformOrRemoveChildren(v) {
|
|
throw unsupported("transformOrRemoveChildren", fileOffset, uri);
|
|
}
|
|
|
|
@override
|
|
// Coverage-ignore(suite): Not run.
|
|
Never visitChildren(v) {
|
|
throw unsupported("visitChildren", fileOffset, uri);
|
|
}
|
|
}
|