[cfe][InternalNodes] Add InternalPattern hierarchy

This adds an internal class hierarch for patterns. This allows for the internal nodes to use InternalVariable rather than Variable and only contain the fields created during body building. This is a step towards separating Variable and InternalVariable fully.

Change-Id: I0e5241bc7163e0771d3420496b1f5ea02b433c87
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/508561
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther
2026-06-02 06:08:24 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent b6015976c9
commit 03ba5dabc2
8 changed files with 1933 additions and 654 deletions
+108 -97
View File
@@ -676,8 +676,8 @@ class BodyBuilderImpl extends StackListenerImpl
return toValue(node);
}
Pattern toPattern(Object? node) {
if (node is Pattern) {
InternalPattern toPattern(Object? node) {
if (node is InternalPattern) {
return node;
} else if (node is Generator) {
return intern.createConstantPattern(node.buildSimpleRead());
@@ -1876,9 +1876,9 @@ class BodyBuilderImpl extends StackListenerImpl
_localScope.kind == LocalScopeKind.orPatternRight;
if (scopeKind != LocalScopeKind.orPatternRight &&
enclosingScopeIsPatternScope) {
if (pattern is Pattern) {
for (Variable variable in pattern.declaredVariables) {
declareVariable(variable as InternalVariable, _localScope);
if (pattern is InternalPattern) {
for (InternalVariable variable in pattern.internalDeclaredVariables) {
declareVariable(variable, _localScope);
}
}
}
@@ -1939,8 +1939,8 @@ class BodyBuilderImpl extends StackListenerImpl
operatorToken.charOffset,
operatorToken.charCount,
);
Pattern right = toPattern(pop());
Pattern left = toPattern(pop());
InternalPattern right = toPattern(pop());
InternalPattern left = toPattern(pop());
String operator = operatorToken.lexeme;
switch (operator) {
@@ -1948,52 +1948,51 @@ class BodyBuilderImpl extends StackListenerImpl
push(intern.createAndPattern(operatorToken.charOffset, left, right));
break;
case '||':
Map<String, Variable> leftVariablesByName = {
for (Variable leftVariable in left.declaredVariables)
leftVariable.name!: leftVariable,
Map<String, InternalVariable> leftVariablesByName = {
for (InternalVariable leftVariable in left.internalDeclaredVariables)
leftVariable.cosmeticName!: leftVariable,
};
for (Variable rightVariable in right.declaredVariables) {
if (!leftVariablesByName.containsKey(rightVariable.name)) {
for (InternalVariable rightVariable
in right.internalDeclaredVariables) {
if (!leftVariablesByName.containsKey(rightVariable.cosmeticName)) {
addProblem(
diag.missingVariablePattern.withArguments(
variableName: rightVariable.name!,
variableName: rightVariable.cosmeticName!,
),
left.fileOffset,
noLength,
);
}
}
Map<String, Variable> rightVariablesByName = {
for (Variable rightVariable in right.declaredVariables)
rightVariable.name!: rightVariable,
Map<String, InternalVariable> rightVariablesByName = {
for (InternalVariable rightVariable
in right.internalDeclaredVariables)
rightVariable.cosmeticName!: rightVariable,
};
for (Variable leftVariable in left.declaredVariables) {
if (!rightVariablesByName.containsKey(leftVariable.name)) {
for (InternalVariable leftVariable in left.internalDeclaredVariables) {
if (!rightVariablesByName.containsKey(leftVariable.cosmeticName)) {
addProblem(
diag.missingVariablePattern.withArguments(
variableName: leftVariable.name!,
variableName: leftVariable.cosmeticName!,
),
right.fileOffset,
noLength,
);
}
}
List<Variable> jointVariables = [
for (Variable leftVariable in left.declaredVariables)
intern
.createSyntheticVariable(
isClosureContextLoweringEnabled:
isClosureContextLoweringEnabled,
name: leftVariable.name!,
fileOffset: leftVariable.fileOffset,
// TODO(johnniwinther): Should this be final if [leftVariable]
// is?
)
.asVariableDeclaration,
List<InternalVariable> jointVariables = [
for (InternalVariable leftVariable in left.internalDeclaredVariables)
intern.createSyntheticVariable(
isClosureContextLoweringEnabled: isClosureContextLoweringEnabled,
name: leftVariable.cosmeticName!,
fileOffset: leftVariable.fileOffset,
// TODO(johnniwinther): Should this be final if [leftVariable]
// is?
),
];
for (Variable variable in jointVariables) {
declareVariable(variable as InternalVariable, _localScope);
assignedVariables.declare(variable);
for (InternalVariable variable in jointVariables) {
declareVariable(variable, _localScope);
assignedVariables.declare(variable.astVariable);
}
push(
intern.createOrPattern(
@@ -3202,10 +3201,10 @@ class BodyBuilderImpl extends StackListenerImpl
]),
);
Pattern pattern = toPattern(peek());
InternalPattern pattern = toPattern(peek());
createAndEnterLocalScope(kind: LocalScopeKind.ifCaseHead);
for (Variable variable in pattern.declaredVariables) {
declareVariable(variable as InternalVariable, _localScope);
for (InternalVariable variable in pattern.internalDeclaredVariables) {
declareVariable(variable, _localScope);
}
}
@@ -3236,8 +3235,9 @@ class BodyBuilderImpl extends StackListenerImpl
// to enter the scope and declare all of the pattern variables.
if (patternGuard != null) {
createAndEnterLocalScope(kind: LocalScopeKind.ifCaseHead);
for (Variable variable in patternGuard.pattern.declaredVariables) {
declareVariable(variable as InternalVariable, _localScope);
InternalPattern pattern = patternGuard.pattern as InternalPattern;
for (InternalVariable variable in pattern.internalDeclaredVariables) {
declareVariable(variable, _localScope);
}
LocalScope thenScope = _localScope.createNestedScope(
kind: LocalScopeKind.statementLocalScope,
@@ -3824,10 +3824,10 @@ class BodyBuilderImpl extends StackListenerImpl
Object expression = pop() as Object;
Object pattern = pop() as Object;
if (pattern is Pattern) {
if (pattern is InternalPattern) {
pop(); // Metadata.
for (Variable variable in pattern.declaredVariables) {
declareVariable(variable as InternalVariable, _localScope);
for (InternalVariable variable in pattern.internalDeclaredVariables) {
declareVariable(variable, _localScope);
}
LocalScope forScope = _localScope.createNestedScope(
kind: LocalScopeKind.forStatement,
@@ -3842,14 +3842,14 @@ class BodyBuilderImpl extends StackListenerImpl
// using the variables with the same name within the same block.
List<InternalVariable> intermediateVariables = [];
List<InternalVariable> internalVariables = [];
for (Variable variable in pattern.declaredVariables) {
for (InternalVariable variable in pattern.internalDeclaredVariables) {
variable.isFinal |= isFinal;
// TODO(johnniwinther): Can we avoid creating synthetic variables here?
InternalVariable intermediateVariable = intern
.createSyntheticVariableForValue(
intern.createVariableGet(
variable as InternalVariable,
variable,
fileOffset: variable.fileOffset,
),
isClosureContextLoweringEnabled: isClosureContextLoweringEnabled,
@@ -3858,7 +3858,7 @@ class BodyBuilderImpl extends StackListenerImpl
InternalVariable internalVariable = intern.createSyntheticVariable(
isClosureContextLoweringEnabled: isClosureContextLoweringEnabled,
name: variable.name!,
name: variable.cosmeticName!,
initializer: intern.createVariableGet(
intermediateVariable,
fileOffset: variable.fileOffset,
@@ -4302,9 +4302,9 @@ class BodyBuilderImpl extends StackListenerImpl
leftBracket.charCount,
);
List<Pattern> patterns = new List<Pattern>.filled(
List<InternalPattern> patterns = new List<InternalPattern>.filled(
count,
dummyPattern,
dummyInternalPattern,
growable: true,
);
for (int i = count - 1; i >= 0; i--) {
@@ -4479,7 +4479,10 @@ class BodyBuilderImpl extends StackListenerImpl
token.charCount,
);
List<Pattern> patterns = new List<Pattern>.filled(count, dummyPattern);
List<InternalPattern> patterns = new List<InternalPattern>.filled(
count,
dummyInternalPattern,
);
for (int i = count - 1; i >= 0; i--) {
patterns[i] = toPattern(pop());
}
@@ -4646,7 +4649,7 @@ class BodyBuilderImpl extends StackListenerImpl
/* key */ unionOfKinds([ValueKinds.Expression, ValueKinds.Generator]),
]),
);
Pattern value = toPattern(pop());
InternalPattern value = toPattern(pop());
Expression key = toValue(pop());
push(intern.createMapPatternEntry(colon.charOffset, key, value));
}
@@ -4669,19 +4672,19 @@ class BodyBuilderImpl extends StackListenerImpl
leftBrace.charOffset,
leftBrace.charCount,
);
List<MapPatternEntry> entries = <MapPatternEntry>[];
List<InternalMapPatternEntry> entries = <InternalMapPatternEntry>[];
for (int i = 0; i < count; i++) {
Object? entry = pop();
if (entry is MapPatternEntry) {
if (entry is InternalMapPatternEntry) {
entries.add(entry);
} else {
entry as RestPattern;
entry as InternalRestPattern;
entries.add(intern.createMapPatternRestEntry(entry.fileOffset));
}
}
for (int i = 0, j = entries.length - 1; i < j; i++, j--) {
MapPatternEntry entry = entries[i];
InternalMapPatternEntry entry = entries[i];
entries[i] = entries[j];
entries[j] = entry;
}
@@ -5258,7 +5261,7 @@ class BodyBuilderImpl extends StackListenerImpl
TypeUse.asType,
allowPotentiallyConstantType: true,
);
Pattern operand = toPattern(pop());
InternalPattern operand = toPattern(pop());
push(intern.createCastPattern(operator.charOffset, operand, type));
}
@@ -7259,8 +7262,9 @@ class BodyBuilderImpl extends StackListenerImpl
enterLocalScope(thenScope);
} else {
createAndEnterLocalScope(kind: LocalScopeKind.ifCaseHead);
for (Variable variable in patternGuard.pattern.declaredVariables) {
declareVariable(variable as InternalVariable, _localScope);
InternalPattern pattern = patternGuard.pattern as InternalPattern;
for (InternalVariable variable in pattern.internalDeclaredVariables) {
declareVariable(variable, _localScope);
}
LocalScope thenScope = _localScope.createNestedScope(
kind: LocalScopeKind.ifElement,
@@ -8288,12 +8292,12 @@ class BodyBuilderImpl extends StackListenerImpl
Object expression = pop() as Object;
Object pattern = pop() as Object;
if (pattern is Pattern) {
if (pattern is InternalPattern) {
pop(); // Metadata.
bool isFinal = patternKeyword?.lexeme == 'final';
for (Variable variable in pattern.declaredVariables) {
for (InternalVariable variable in pattern.internalDeclaredVariables) {
variable.isFinal |= isFinal;
declareVariable(variable as InternalVariable, _localScope);
declareVariable(variable, _localScope);
}
}
@@ -8959,13 +8963,15 @@ class BodyBuilderImpl extends StackListenerImpl
expressionOrPatterns[i];
PatternGuard? patternGuard = expressionOrPattern.patternGuard;
if (patternGuard != null) {
InternalPattern pattern = patternGuard.pattern as InternalPattern;
if (jointPatternVariables == null) {
jointPatternVariables = [
for (Variable variable in patternGuard.pattern.declaredVariables)
for (InternalVariable variable
in pattern.internalDeclaredVariables)
intern.createSyntheticVariable(
isClosureContextLoweringEnabled:
isClosureContextLoweringEnabled,
name: variable.name!,
name: variable.cosmeticName!,
isFinal: variable.isFinal,
fileOffset: variable.fileOffset,
),
@@ -8978,13 +8984,14 @@ class BodyBuilderImpl extends StackListenerImpl
);
}
} else {
Map<String, Variable> patternVariablesByName = {
for (Variable variable in patternGuard.pattern.declaredVariables)
variable.name!: variable,
Map<String, InternalVariable> patternVariablesByName = {
for (InternalVariable variable
in pattern.internalDeclaredVariables)
variable.cosmeticName!: variable,
};
for (InternalVariable jointVariable in jointPatternVariables) {
String jointVariableName = jointVariable.cosmeticName!;
Variable? patternVariable = patternVariablesByName.remove(
InternalVariable? patternVariable = patternVariablesByName.remove(
jointVariableName,
);
if (patternVariable != null) {
@@ -8998,11 +9005,11 @@ class BodyBuilderImpl extends StackListenerImpl
}
}
if (patternVariablesByName.isNotEmpty) {
for (Variable variable in patternVariablesByName.values) {
for (InternalVariable variable in patternVariablesByName.values) {
InternalVariable jointVariable = intern.createSyntheticVariable(
isClosureContextLoweringEnabled:
isClosureContextLoweringEnabled,
name: variable.name!,
name: variable.cosmeticName!,
isFinal: variable.isFinal,
fileOffset: variable.fileOffset,
);
@@ -9081,9 +9088,9 @@ class BodyBuilderImpl extends StackListenerImpl
// Here we declare the pattern variables in the scope of the case head. It
// makes the variables visible in the 'when' clause of the head.
Object? pattern = peek();
if (pattern is Pattern) {
for (Variable variable in pattern.declaredVariables) {
declareVariable(variable as InternalVariable, _localScope);
if (pattern is InternalPattern) {
for (InternalVariable variable in pattern.internalDeclaredVariables) {
declareVariable(variable, _localScope);
}
}
push(constantContext);
@@ -9120,9 +9127,9 @@ class BodyBuilderImpl extends StackListenerImpl
// Here we declare the pattern variables. It makes the variables visible
// body of the case.
Object? pattern = peek();
if (pattern is Pattern) {
for (Variable variable in pattern.declaredVariables) {
declareVariable(variable as InternalVariable, _localScope);
if (pattern is InternalPattern) {
for (InternalVariable variable in pattern.internalDeclaredVariables) {
declareVariable(variable, _localScope);
}
}
}
@@ -9253,8 +9260,9 @@ class BodyBuilderImpl extends StackListenerImpl
PatternGuard? patternGuard =
expressionsOrPatternGuards.first.patternGuard;
if (patternGuard != null) {
for (Variable variable in patternGuard.pattern.declaredVariables) {
String variableName = variable.name!;
InternalPattern pattern = patternGuard.pattern as InternalPattern;
for (InternalVariable variable in pattern.internalDeclaredVariables) {
String variableName = variable.cosmeticName!;
if (usedNamesOffsets[variableName] case [int offset, ...]) {
addProblem(
diag.jointPatternVariableWithLabelDefault.withArguments(
@@ -9442,9 +9450,9 @@ class BodyBuilderImpl extends StackListenerImpl
);
Object? pattern = pop();
createAndEnterLocalScope(kind: LocalScopeKind.caseHead);
if (pattern is Pattern) {
for (Variable variable in pattern.declaredVariables) {
declareVariable(variable as InternalVariable, _localScope);
if (pattern is InternalPattern) {
for (InternalVariable variable in pattern.internalDeclaredVariables) {
declareVariable(variable, _localScope);
}
}
push(pattern);
@@ -10865,14 +10873,14 @@ class BodyBuilderImpl extends StackListenerImpl
beginToken.charOffset,
beginToken.charCount,
);
List<NamedPattern>? fields;
List<InternalNamedPattern>? fields;
for (int i = 0; i < count; i++) {
Object? field = pop();
if (field is NamedPattern) {
(fields ??= <NamedPattern>[]).add(field);
if (field is InternalNamedPattern) {
(fields ??= []).add(field);
} else {
Pattern pattern = toPattern(field);
if (pattern is! InvalidPattern) {
if (pattern is! InternalInvalidPattern) {
addProblem(
diag.unnamedObjectPatternField,
pattern.fileOffset,
@@ -10883,7 +10891,7 @@ class BodyBuilderImpl extends StackListenerImpl
}
if (fields != null) {
for (int i = 0, j = fields.length - 1; i < j; i++, j--) {
NamedPattern field = fields[i];
InternalNamedPattern field = fields[i];
fields[i] = fields[j];
fields[j] = field;
}
@@ -10900,7 +10908,7 @@ class BodyBuilderImpl extends StackListenerImpl
debugEvent("ObjectPattern");
assert(
checkState(firstIdentifier, [
ValueKinds.PatternListOrNull,
ValueKinds.NamedPatternListOrNull,
ValueKinds.TypeArgumentsOrNull,
]),
);
@@ -10911,7 +10919,7 @@ class BodyBuilderImpl extends StackListenerImpl
firstIdentifier.charCount,
);
List<NamedPattern>? fields = pop() as List<NamedPattern>?;
List<InternalNamedPattern>? fields = pop() as List<InternalNamedPattern>?;
List<TypeBuilder>? typeArguments = pop() as List<TypeBuilder>?;
handleIdentifier(firstIdentifier, IdentifierContext.prefixedTypeReference);
@@ -10932,12 +10940,15 @@ class BodyBuilderImpl extends StackListenerImpl
allowPotentiallyConstantType: true,
);
push(
new ObjectPatternInternal(
type,
fields ?? <NamedPattern>[],
typeDeclaration is TypeAliasBuilder ? typeDeclaration.typedef : null,
intern.createObjectPattern(
requiredType: type,
fields: fields ?? [],
typedef: typeDeclaration is TypeAliasBuilder
? typeDeclaration.typedef
: null,
hasExplicitTypeArguments: typeArguments != null,
)..fileOffset = firstIdentifier.charOffset,
fileOffset: firstIdentifier.charOffset,
),
);
}
@@ -10955,7 +10966,7 @@ class BodyBuilderImpl extends StackListenerImpl
]),
);
Pattern? subPattern;
InternalPattern? subPattern;
if (hasSubPattern) {
subPattern = toPattern(pop());
}
@@ -11032,7 +11043,7 @@ class BodyBuilderImpl extends StackListenerImpl
bang.charOffset,
bang.charCount,
);
Pattern operand = toPattern(pop());
InternalPattern operand = toPattern(pop());
push(intern.createNullAssertPattern(bang.charOffset, operand));
}
@@ -11053,7 +11064,7 @@ class BodyBuilderImpl extends StackListenerImpl
question.charOffset,
question.charCount,
);
Pattern operand = toPattern(pop());
InternalPattern operand = toPattern(pop());
push(intern.createNullCheckPattern(question.charOffset, operand));
}
@@ -11155,7 +11166,7 @@ class BodyBuilderImpl extends StackListenerImpl
);
Object? value = pop();
Pattern pattern = toPattern(value);
InternalPattern pattern = toPattern(value);
if (colon != null) {
Object? identifier = pop();
if (identifier is ParserRecovery) {
@@ -11207,12 +11218,12 @@ class BodyBuilderImpl extends StackListenerImpl
]),
);
Expression initializer = popForValue();
Pattern pattern = toPattern(pop());
InternalPattern pattern = toPattern(pop());
bool isFinal = keyword.lexeme == 'final';
for (Variable variable in pattern.declaredVariables) {
for (InternalVariable variable in pattern.internalDeclaredVariables) {
variable.isFinal = isFinal;
variable.hasDeclaredInitializer = true;
declareVariable(variable as InternalVariable, _localScope);
declareVariable(variable, _localScope);
}
// TODO(johnniwinther,cstefantsova): Handle metadata.
pop(NullValues.Metadata) as List<Expression>?;
@@ -47,6 +47,14 @@ LogicalExpression createAndExpression(
..fileOffset = fileOffset;
}
AndPattern createAndPattern({
required Pattern left,
required Pattern right,
required int fileOffset,
}) {
return new AndPattern(left, right)..fileOffset = fileOffset;
}
/// Creates an [Arguments] object for the [positional] and [named] arguments,
/// and [types] as the type arguments.
Arguments createArguments(
@@ -99,6 +107,20 @@ AssertStatement createAssertStatement(
)..fileOffset = fileOffset;
}
AssignedVariablePattern createAssignedVariablePattern({
required Variable variable,
required DartType matchedValueType,
required bool needsCast,
required bool hasObservableEffect,
required int fileOffset,
}) {
return new AssignedVariablePattern(variable)
..matchedValueType = matchedValueType
..needsCast = needsCast
..hasObservableEffect = hasObservableEffect
..fileOffset = fileOffset;
}
/// Creates a block containing the [statements].
Block createBlock(
List<Statement> statements, {
@@ -133,6 +155,14 @@ BreakStatement createBreakStatement(
return new BreakStatement(target)..fileOffset = fileOffset;
}
CastPattern createCastPattern({
required Pattern pattern,
required DartType type,
required int fileOffset,
}) {
return new CastPattern(pattern, type)..fileOffset = fileOffset;
}
CatchVariable createCatchVariable({
required String name,
required DartType? type,
@@ -148,27 +178,6 @@ CatchVariable createCatchVariable({
)..fileOffset = fileOffset;
}
LateVariable createLateVariable({
required String? cosmeticName,
required DartType? type,
bool isFinal = false,
bool isConst = false,
bool isWildcard = false,
required int fileOffset,
Expression? initializer,
bool hasDeclaredInitializer = false,
}) {
return new LateVariable(
cosmeticName: cosmeticName,
type: type,
isFinal: isFinal,
isConst: isConst,
isWildcard: isWildcard,
initializer: initializer,
hasDeclaredInitializer: hasDeclaredInitializer,
)..fileOffset = fileOffset;
}
/// Creates a conditional expression of the [condition] and the [then] and
/// [otherwise] branches with the given [staticType] of the resulting
/// expression.
@@ -191,6 +200,20 @@ ConstantExpression createConstantExpression(
return new ConstantExpression(constant, type)..fileOffset = fileOffset;
}
ConstantPattern createConstantPattern({
required Expression expression,
required DartType expressionType,
required Procedure equalsTarget,
required FunctionType equalsType,
required int fileOffset,
}) {
return new ConstantPattern(expression)
..expressionType = expressionType
..equalsTarget = equalsTarget
..equalsType = equalsType
..fileOffset = fileOffset;
}
Constructor createConstructor(
FunctionNode function, {
required Name name,
@@ -510,6 +533,19 @@ InvalidInitializer createInvalidInitializer(
..isRedirectingInitializer = isRedirectingInitializer;
}
InvalidPattern createInvalidPattern({
required Expression error,
required List<InternalVariable> declaredVariables,
int? fileOffset,
}) {
return new InvalidPattern(
error,
declaredVariables: declaredVariables
.map((InternalVariable variable) => variable.astVariable)
.toList(),
)..fileOffset = fileOffset ?? error.fileOffset;
}
/// Creates an is-test on [operand] against [type].
IsExpression createIsExpression(
Expression operand,
@@ -527,6 +563,27 @@ LabeledStatement createLabeledStatement(
return new LabeledStatement(statement)..fileOffset = fileOffset;
}
LateVariable createLateVariable({
required String? cosmeticName,
required DartType? type,
bool isFinal = false,
bool isConst = false,
bool isWildcard = false,
required int fileOffset,
Expression? initializer,
bool hasDeclaredInitializer = false,
}) {
return new LateVariable(
cosmeticName: cosmeticName,
type: type,
isFinal: isFinal,
isConst: isConst,
isWildcard: isWildcard,
initializer: initializer,
hasDeclaredInitializer: hasDeclaredInitializer,
)..fileOffset = fileOffset;
}
/// Creates a [Let] of [variable] with the given [body] using
/// `variable.fileOffset` as the file offset for the let.
Let createLet(Variable variable, Expression body) {
@@ -541,6 +598,45 @@ Let createLetEffect({required Expression effect, required Expression result}) {
..fileOffset = effect.fileOffset;
}
ListPattern createListPattern({
required DartType? typeArgument,
required List<Pattern> patterns,
required DartType requiredType,
required DartType matchedValueType,
required bool needsCheck,
required DartType lookupType,
required bool hasRestPattern,
required Member lengthTarget,
required DartType lengthType,
required Procedure lengthCheckTarget,
required FunctionType lengthCheckType,
required Procedure sublistTarget,
required FunctionType sublistType,
required Procedure minusTarget,
required FunctionType minusType,
required Procedure indexGetTarget,
required FunctionType indexGetType,
required int fileOffset,
}) {
return new ListPattern(typeArgument, patterns)
..requiredType = requiredType
..matchedValueType = matchedValueType
..needsCheck = needsCheck
..lookupType = lookupType
..hasRestPattern = hasRestPattern
..lengthTarget = lengthTarget
..lengthType = lengthType
..lengthCheckTarget = lengthCheckTarget
..lengthCheckType = lengthCheckType
..sublistTarget = sublistTarget
..sublistType = sublistType
..minusTarget = minusTarget
..minusType = minusType
..indexGetTarget = indexGetTarget
..indexGetType = indexGetType
..fileOffset = fileOffset;
}
/// Creates an invocation of the local function [variable] with the provided
/// [arguments].
LocalFunctionInvocation createLocalFunctionInvocation(
@@ -566,6 +662,47 @@ MapLiteralEntry createMapLiteralEntry(
return new MapLiteralEntry(key, value)..fileOffset = fileOffset;
}
MapPattern createMapPattern({
required DartType? keyType,
required DartType? valueType,
required List<MapPatternEntry> entries,
required DartType requiredType,
required DartType matchedValueType,
required bool needsCheck,
required DartType lookupType,
required Procedure containsKeyTarget,
required FunctionType containsKeyType,
required Procedure indexGetTarget,
required FunctionType indexGetType,
required int fileOffset,
}) {
return new MapPattern(keyType, valueType, entries)
..requiredType = requiredType
..matchedValueType = matchedValueType
..needsCheck = needsCheck
..lookupType = lookupType
..containsKeyTarget = containsKeyTarget
..containsKeyType = containsKeyType
..indexGetTarget = indexGetTarget
..indexGetType = indexGetType
..fileOffset = fileOffset;
}
MapPatternEntry createMapPatternEntry({
required Expression key,
required DartType keyType,
required Pattern value,
required int fileOffset,
}) {
return new MapPatternEntry(key, value)
..keyType = keyType
..fileOffset = fileOffset;
}
MapPatternRestEntry createMapPatternRestEntry({required int fileOffset}) {
return new MapPatternRestEntry()..fileOffset = fileOffset;
}
Field createMutableField(
Name name, {
DartType type = const DynamicType(),
@@ -636,21 +773,64 @@ NamedParameter createNamedParameter({
)..fileOffset = fileOffset;
}
NamedPattern createNamedPattern({
required String name,
Name? fieldName,
required Pattern pattern,
required int fileOffset,
}) {
NamedPattern result = new NamedPattern(name, pattern)
..fileOffset = fileOffset;
if (fieldName != null) {
result.fieldName = fieldName;
}
return result;
}
/// Creates a [Not] of [operand].
Not createNot(Expression operand) {
return new Not(operand)..fileOffset = operand.fileOffset;
}
NullAssertPattern createNullAssertPattern({
required Pattern pattern,
required int fileOffset,
}) {
return new NullAssertPattern(pattern)..fileOffset = fileOffset;
}
/// Creates a [NullCheck] of [expression].
NullCheck createNullCheck(Expression expression, {required int fileOffset}) {
return new NullCheck(expression)..fileOffset = fileOffset;
}
NullCheckPattern createNullCheckPattern({
required Pattern pattern,
required int fileOffset,
}) {
return new NullCheckPattern(pattern)..fileOffset = fileOffset;
}
/// Creates a null literal.
NullLiteral createNullLiteral({required int fileOffset}) {
return new NullLiteral()..fileOffset = fileOffset;
}
ObjectPattern createObjectPattern({
required DartType requiredType,
required List<NamedPattern> fields,
required DartType matchedValueType,
required bool needsCheck,
required DartType lookupType,
required int fileOffset,
}) {
return new ObjectPattern(requiredType, fields)
..matchedValueType = matchedValueType
..needsCheck = needsCheck
..lookupType = lookupType
..fileOffset = fileOffset;
}
/// Creates a logical or expression of [left] and [right].
LogicalExpression createOrExpression(
Expression left,
@@ -661,6 +841,19 @@ LogicalExpression createOrExpression(
..fileOffset = fileOffset;
}
OrPattern createOrPattern({
required Pattern left,
required Pattern right,
required List<Variable> orPatternJointVariables,
required int fileOffset,
}) {
return new OrPattern(
left,
right,
orPatternJointVariables: orPatternJointVariables,
)..fileOffset = fileOffset;
}
// TODO(johnniwinther): Should this require a type?
Variable createParameterVariable(
String? name, {
@@ -761,6 +954,53 @@ Procedure createProcedure(
..fileEndOffset = fileEndOffset;
}
RecordPattern createRecordPattern({
required List<Pattern> patterns,
required RecordType requiredType,
required DartType matchedValueType,
required bool needsCheck,
required RecordType lookupType,
required int fileOffset,
}) {
return new RecordPattern(patterns)
..requiredType = requiredType
..matchedValueType = matchedValueType
..needsCheck = needsCheck
..lookupType = lookupType
..fileOffset = fileOffset;
}
RelationalPattern createRelationalPattern({
required RelationalPatternKind kind,
required Expression expression,
required DartType expressionType,
required DartType matchedValueType,
required RelationalAccessKind accessKind,
required Name? name,
required Procedure? target,
required List<DartType>? typeArguments,
required FunctionType? functionType,
required int fileOffset,
}) {
return new RelationalPattern(kind, expression)
..expressionType = expressionType
..matchedValueType = matchedValueType
..accessKind = accessKind
..name = name
..target = target
..typeArguments = typeArguments
..functionType = functionType
..fileOffset = fileOffset;
}
RestPattern createRestPattern({
required Pattern? subPattern,
required int fileOffset,
}) {
return new RestPattern(subPattern)..fileOffset;
}
ReturnStatement createReturnStatement(
Expression expression, {
int? fileOffset,
@@ -951,6 +1191,17 @@ VariableGet createVariableGet(
..promotedType = promotedType != variable.type ? promotedType : null;
}
VariablePattern createVariablePattern({
required DartType? type,
required Variable variable,
required DartType matchedValueType,
required int fileOffset,
}) {
return new VariablePattern(type, variable)
..matchedValueType = matchedValueType
..fileOffset = fileOffset;
}
/// Creates a [VariableSet] of [variable] with the [value].
Expression createVariableSet(
Variable variable,
@@ -977,3 +1228,10 @@ VariableStatement createVariableStatement(VariableDeclaration declaration) {
return new VariableStatement(declaration)
..fileOffset = declaration.fileOffset;
}
WildcardPattern createWildcardPattern({
required DartType? type,
required int fileOffset,
}) {
return new WildcardPattern(type)..fileOffset = fileOffset;
}
+839 -23
View File
@@ -1483,7 +1483,6 @@ class InternalNamedParameter extends TreeNode
}
@override
// Coverage-ignore(suite): Not run.
List<Expression> get annotations => astVariable.annotations;
@override
@@ -1627,7 +1626,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin
}
@override
// Coverage-ignore(suite): Not run.
List<Expression> get annotations => astVariable.annotations;
@override
@@ -1751,7 +1749,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin
}
@override
// Coverage-ignore(suite): Not run.
bool get isRequired => astVariable.isRequired;
@override
@@ -5360,26 +5357,6 @@ class InternalRecordLiteral extends InternalExpression {
}
}
/// Data structure used by the body builder in place of [ObjectPattern], to
/// allow additional information to be captured that is needed during type
/// inference.
class ObjectPatternInternal extends ObjectPattern {
/// If the type name in the object pattern refers to a typedef, the typedef in
/// question; otherwise `null`.
final Typedef? typedef;
/// Indicates whether the object pattern included explicit type arguments; if
/// `true` this means that no further type inference needs to be performed.
final bool hasExplicitTypeArguments;
ObjectPatternInternal(
super.requiredType,
super.fields,
this.typedef, {
required this.hasExplicitTypeArguments,
});
}
class ExtensionTypeRedirectingInitializer extends InternalInitializer {
Reference targetReference;
ActualArguments arguments;
@@ -6889,3 +6866,842 @@ class InternalFunctionDeclaration extends InternalStatement {
return "$runtimeType(${toStringInternal()}";
}
}
// Coverage-ignore(suite): Not run.
sealed class InternalPattern extends AuxiliaryPattern {
List<InternalVariable> get internalDeclaredVariables;
@override
@Deprecated('Use internalDeclaredVariables instead')
List<Variable> get declaredVariables =>
unsupported("${runtimeType}.declaredVariables", -1, null);
@override
void replaceChild(TreeNode child, TreeNode replacement) {
// Do nothing. The node should not be part of the resulting AST, anyway.
}
@override
void visitChildren(Visitor<dynamic> v) =>
unsupported("${runtimeType}.visitChildren", -1, null);
@override
void transformChildren(Transformer v) =>
unsupported("${runtimeType}.transformChildren", -1, null);
@override
void transformOrRemoveChildren(RemovingTransformer v) {
unsupported("${runtimeType}.transformOrRemoveChildren", -1, null);
}
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
);
}
/// An [InternalPattern] for `pattern || pattern`.
class InternalOrPattern extends InternalPattern {
final InternalPattern left;
final InternalPattern right;
final List<InternalVariable> orPatternJointVariables;
@override
List<InternalVariable> get internalDeclaredVariables =>
orPatternJointVariables;
InternalOrPattern(
this.left,
this.right, {
required this.orPatternJointVariables,
required int fileOffset,
}) {
left.parent = this;
right.parent = this;
this.fileOffset = fileOffset;
}
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalOrPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
left.toTextInternal(printer);
printer.write(' || ');
right.toTextInternal(printer);
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
/// An [InternalPattern] for `pattern && pattern`.
class InternalAndPattern extends InternalPattern {
final InternalPattern left;
final InternalPattern right;
@override
List<InternalVariable> get internalDeclaredVariables => [
...left.internalDeclaredVariables,
...right.internalDeclaredVariables,
];
InternalAndPattern(this.left, this.right, {required int fileOffset}) {
left.parent = this;
right.parent = this;
this.fileOffset = fileOffset;
}
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalAndPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
left.toTextInternal(printer);
printer.write(' && ');
right.toTextInternal(printer);
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
/// An [InternalPattern] based on a constant [Expression].
class InternalConstantPattern extends InternalPattern {
final Expression expression;
InternalConstantPattern({required this.expression, required int fileOffset}) {
expression.parent = this;
this.fileOffset = fileOffset;
}
@override
List<InternalVariable> get internalDeclaredVariables => const [];
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalConstantPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
expression.toTextInternal(printer);
}
@override
String toString() {
return "ConstantPattern(${toStringInternal()})";
}
}
class InternalAssignedVariablePattern extends InternalPattern {
final InternalVariable variable;
InternalAssignedVariablePattern(this.variable, {required int fileOffset}) {
this.fileOffset = fileOffset;
}
@override
List<InternalVariable> get internalDeclaredVariables => const [];
@override
String get variableName => variable.cosmeticName!;
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalAssignedVariablePattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
printer.write(variable.cosmeticName!);
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
/// An [InternalPattern] for `pattern as type`.
class InternalCastPattern extends InternalPattern {
final InternalPattern pattern;
final DartType type;
InternalCastPattern(this.pattern, this.type, {required int fileOffset}) {
pattern.parent = this;
this.fileOffset = fileOffset;
}
@override
String? get variableName => pattern.variableName;
@override
List<InternalVariable> get internalDeclaredVariables =>
pattern.internalDeclaredVariables;
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalCastPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
pattern.toTextInternal(printer);
printer.write(' as ');
printer.writeType(type);
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
class InternalInvalidPattern extends InternalPattern {
final Expression invalidExpression;
@override
final List<InternalVariable> internalDeclaredVariables;
InternalInvalidPattern({
required this.invalidExpression,
required this.internalDeclaredVariables,
required int fileOffset,
}) {
invalidExpression.parent = this;
this.fileOffset = fileOffset;
}
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalInvalidPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
printer.writeExpression(invalidExpression);
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
/// An [InternalPattern] for `<typeArgument>[pattern0, ... patternN]`.
class InternalListPattern extends InternalPattern {
/// The element type argument as specified by the list pattern syntax.
DartType? typeArgument;
List<InternalPattern> patterns;
@override
List<InternalVariable> get internalDeclaredVariables => [
for (InternalPattern pattern in patterns)
...pattern.internalDeclaredVariables,
];
InternalListPattern({
required this.typeArgument,
required this.patterns,
required int fileOffset,
}) {
setParents(patterns, this);
this.fileOffset = fileOffset;
}
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalListPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
if (typeArgument != null) {
printer.write('<');
printer.writeType(typeArgument!);
printer.write('>');
}
printer.write('[');
String comma = '';
for (Pattern pattern in patterns) {
printer.write(comma);
pattern.toTextInternal(printer);
comma = ', ';
}
printer.write(']');
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
final InternalPattern dummyInternalPattern = new InternalConstantPattern(
expression: dummyExpression,
fileOffset: TreeNode.noOffset,
);
class InternalMapPattern extends InternalPattern {
/// The key type arguments as specific in the map pattern syntax.
DartType? keyType;
/// The value type arguments as specific in the map pattern syntax.
DartType? valueType;
final List<InternalMapPatternEntry> entries;
@override
List<InternalVariable> get internalDeclaredVariables => [
for (InternalMapPatternEntry entry in entries)
if (entry is! InternalMapPatternRestEntry)
...entry.value.internalDeclaredVariables,
];
InternalMapPattern({
required this.keyType,
required this.valueType,
required this.entries,
required int fileOffset,
}) : assert((keyType == null) == (valueType == null)) {
setParents(entries, this);
this.fileOffset = fileOffset;
}
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalMapPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
if (keyType != null && valueType != null) {
printer.writeTypeArguments([keyType!, valueType!]);
}
printer.write('{');
String comma = '';
for (InternalMapPatternEntry entry in entries) {
printer.write(comma);
entry.toTextInternal(printer);
comma = ', ';
}
printer.write('}');
}
@override
String toString() {
return '$runtimeType(${toStringInternal()})';
}
}
class InternalMapPatternEntry extends TreeNode with InternalTreeNode {
final Expression key;
final InternalPattern value;
InternalMapPatternEntry({
required this.key,
required this.value,
required int fileOffset,
}) {
value.parent = this;
this.fileOffset = fileOffset;
}
@override
R accept<R>(TreeVisitor<R> v) {
throw new UnimplementedError('${runtimeType}.accept');
}
@override
R accept1<R, A>(TreeVisitor1<R, A> v, A arg) {
throw new UnimplementedError('${runtimeType}.accept1');
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
key.toTextInternal(printer);
printer.write(': ');
value.toTextInternal(printer);
}
@override
String toString() {
return 'MapPatternEntry(${toStringInternal()})';
}
}
class InternalMapPatternRestEntry extends TreeNode
with InternalTreeNode
implements InternalMapPatternEntry {
InternalMapPatternRestEntry({required int fileOffset}) {
this.fileOffset = fileOffset;
}
@override
// Coverage-ignore(suite): Not run.
Expression get key => throw new UnsupportedError('$runtimeType.key');
@override
// Coverage-ignore(suite): Not run.
InternalPattern get value => throw new UnsupportedError('$runtimeType.value');
@override
R accept<R>(TreeVisitor<R> v) {
throw new UnimplementedError('${runtimeType}.accept');
}
@override
R accept1<R, A>(TreeVisitor1<R, A> v, A arg) {
throw new UnimplementedError('${runtimeType}.accept1');
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
printer.write('...');
}
@override
String toString() {
return '$runtimeType(${toStringInternal()})';
}
}
class InternalNamedPattern extends InternalPattern {
final String name;
final InternalPattern pattern;
@override
List<InternalVariable> get internalDeclaredVariables =>
pattern.internalDeclaredVariables;
InternalNamedPattern({
required this.name,
required this.pattern,
required int fileOffset,
}) {
pattern.parent = this;
this.fileOffset = fileOffset;
}
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
// InternalNamedPattern isn't a real pattern; this code should never be
// reached.
throw new StateError(
'$runtimeType.acceptInference should never be reached',
);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
printer.write(name);
printer.write(': ');
pattern.toTextInternal(printer);
}
@override
String toString() {
return '$runtimeType(${toStringInternal()})';
}
}
/// An [InternalPattern] for `pattern!`.
class InternalNullAssertPattern extends InternalPattern {
final InternalPattern pattern;
InternalNullAssertPattern({required this.pattern, required int fileOffset}) {
pattern.parent = this;
this.fileOffset = fileOffset;
}
@override
String? get variableName => pattern.variableName;
@override
List<InternalVariable> get internalDeclaredVariables =>
pattern.internalDeclaredVariables;
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalNullAssertPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
pattern.toTextInternal(printer);
printer.write('!');
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
/// An [InternalPattern] for `pattern?`.
class InternalNullCheckPattern extends InternalPattern {
final InternalPattern pattern;
InternalNullCheckPattern({required this.pattern, required int fileOffset}) {
pattern.parent = this;
this.fileOffset = fileOffset;
}
@override
String? get variableName => pattern.variableName;
@override
List<InternalVariable> get internalDeclaredVariables =>
pattern.internalDeclaredVariables;
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalNullCheckPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
pattern.toTextInternal(printer);
printer.write('?');
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
class InternalObjectPattern extends InternalPattern {
/// The type specified as part of the object pattern syntax.
DartType requiredType;
final List<InternalNamedPattern> fields;
/// If the type name in the object pattern refers to a typedef, the typedef in
/// question; otherwise `null`.
final Typedef? typedef;
/// Indicates whether the object pattern included explicit type arguments; if
/// `true` this means that no further type inference needs to be performed.
final bool hasExplicitTypeArguments;
InternalObjectPattern({
required this.requiredType,
required this.fields,
required this.typedef,
required this.hasExplicitTypeArguments,
required int fileOffset,
}) {
setParents(fields, this);
this.fileOffset = fileOffset;
}
@override
List<InternalVariable> get internalDeclaredVariables {
return [
for (InternalNamedPattern field in fields)
...field.internalDeclaredVariables,
];
}
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalObjectPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
printer.writeType(requiredType);
printer.write('(');
String comma = '';
for (Pattern field in fields) {
printer.write(comma);
field.toTextInternal(printer);
comma = ', ';
}
printer.write(')');
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
class InternalRecordPattern extends InternalPattern {
final List<InternalPattern> patterns;
@override
List<InternalVariable> get internalDeclaredVariables => [
for (InternalPattern pattern in patterns)
...pattern.internalDeclaredVariables,
];
InternalRecordPattern({required this.patterns, required int fileOffset}) {
setParents(patterns, this);
this.fileOffset = fileOffset;
}
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalRecordPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
printer.write('(');
String comma = '';
for (Pattern pattern in patterns) {
printer.write(comma);
pattern.toTextInternal(printer);
comma = ', ';
}
printer.write(')');
}
@override
String toString() {
return '$runtimeType(${toStringInternal()})';
}
}
/// An [InternalPattern] for `operator expression` where `operator is either
/// ==, !=, <, <=, >, or >=.
class InternalRelationalPattern extends InternalPattern {
final RelationalPatternKind kind;
final Expression expression;
InternalRelationalPattern({
required this.kind,
required this.expression,
required int fileOffset,
}) {
expression.parent = this;
this.fileOffset = fileOffset;
}
@override
List<InternalVariable> get internalDeclaredVariables => const [];
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalRelationalPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
switch (kind) {
case RelationalPatternKind.equals:
printer.write('== ');
break;
case RelationalPatternKind.notEquals:
printer.write('!= ');
break;
case RelationalPatternKind.lessThan:
printer.write('< ');
break;
case RelationalPatternKind.lessThanEqual:
printer.write('<= ');
break;
case RelationalPatternKind.greaterThan:
printer.write('> ');
break;
case RelationalPatternKind.greaterThanEqual:
printer.write('>= ');
break;
}
printer.writeExpression(expression);
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
class InternalRestPattern extends InternalPattern {
InternalPattern? subPattern;
InternalRestPattern({required this.subPattern, required int fileOffset}) {
subPattern?.parent = this;
this.fileOffset = fileOffset;
}
@override
List<InternalVariable> get internalDeclaredVariables =>
subPattern?.internalDeclaredVariables ?? const [];
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
// InternalRestPattern isn't a real pattern; this code should never be
// reached.
throw new StateError(
'$runtimeType.acceptInference should never be reached',
);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
printer.write('...');
if (subPattern != null) {
subPattern!.toTextInternal(printer);
}
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
class InternalVariablePattern extends InternalPattern {
// TODO(johnniwinther): Should this be accessed through [variable] instead?
final DartType? type;
final InternalVariable variable;
@override
List<InternalVariable> get internalDeclaredVariables => [variable];
InternalVariablePattern({
required this.type,
required this.variable,
required int fileOffset,
}) {
variable.parent = this;
this.fileOffset = fileOffset;
}
@override
String get variableName => variable.cosmeticName!;
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalVariablePattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
if (type != null) {
type!.toTextInternal(printer);
printer.write(" ");
} else {
printer.write("var ");
}
printer.write(variable.cosmeticName!);
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
class InternalWildcardPattern extends InternalPattern {
final DartType? type;
InternalWildcardPattern({required this.type, required int fileOffset}) {
this.fileOffset = fileOffset;
}
@override
List<InternalVariable> get internalDeclaredVariables => const [];
@override
shared.PatternResult acceptInference(
InferenceVisitorImpl visitor,
SharedMatchContext context,
) {
return visitor.visitInternalWildcardPattern(this, context);
}
@override
// Coverage-ignore(suite): Not run.
void toTextInternal(AstPrinter printer) {
if (type != null) {
type!.toTextInternal(printer);
printer.write(" ");
}
printer.write("_");
}
@override
String toString() {
return "$runtimeType(${toStringInternal()})";
}
}
@@ -30,8 +30,12 @@ Expression checkLibraryIsLoaded(int fileOffset, LibraryDependency dependency) {
return new CheckLibraryIsLoaded(dependency)..fileOffset = fileOffset;
}
AndPattern createAndPattern(int fileOffset, Pattern left, Pattern right) {
return new AndPattern(left, right)..fileOffset = fileOffset;
Pattern createAndPattern(
int fileOffset,
InternalPattern left,
InternalPattern right,
) {
return new InternalAndPattern(left, right, fileOffset: fileOffset);
}
ActualArguments createArguments(
@@ -92,12 +96,11 @@ AssertStatement createAssertStatement(
)..fileOffset = fileOffset;
}
AssignedVariablePattern createAssignedVariablePattern(
Pattern createAssignedVariablePattern(
int fileOffset,
InternalVariable variable,
) {
return new AssignedVariablePattern(variable.asVariableDeclaration)
..fileOffset = fileOffset;
return new InternalAssignedVariablePattern(variable, fileOffset: fileOffset);
}
Expression createAwaitExpression(int fileOffset, Expression operand) {
@@ -159,8 +162,12 @@ Statement createBreakStatement(int fileOffset, Object? label) {
..target = label is LabeledStatement ? label : dummyLabeledStatement;
}
CastPattern createCastPattern(int fileOffset, Pattern pattern, DartType type) {
return new CastPattern(pattern, type)..fileOffset = fileOffset;
Pattern createCastPattern(
int fileOffset,
InternalPattern pattern,
DartType type,
) {
return new InternalCastPattern(pattern, type, fileOffset: fileOffset);
}
/// Return a representation of a catch clause.
@@ -231,8 +238,11 @@ ConditionalExpression createConditionalExpression(
)..fileOffset = fileOffset;
}
ConstantPattern createConstantPattern(Expression expression) {
return new ConstantPattern(expression)..fileOffset = expression.fileOffset;
InternalPattern createConstantPattern(Expression expression) {
return new InternalConstantPattern(
expression: expression,
fileOffset: expression.fileOffset,
);
}
ConstructorTearOff createConstructorTearOff(int fileOffset, Member target) {
@@ -593,12 +603,15 @@ Expression createIntLiteralLarge(
return new LargeIntLiteral(strippedLiteral, literal, fileOffset: fileOffset);
}
InvalidPattern createInvalidPattern(
Pattern createInvalidPattern(
Expression expression, {
required List<Variable> declaredVariables,
required List<InternalVariable> declaredVariables,
}) {
return new InvalidPattern(expression, declaredVariables: declaredVariables)
..fileOffset = expression.fileOffset;
return new InternalInvalidPattern(
invalidExpression: expression,
internalDeclaredVariables: declaredVariables,
fileOffset: expression.fileOffset,
);
}
/// Return a representation of an `is` expression at the given [fileOffset].
@@ -712,12 +725,16 @@ ListLiteral createListLiteral(
)..fileOffset = fileOffset;
}
ListPattern createListPattern(
Pattern createListPattern(
int fileOffset,
DartType? typeArgument,
List<Pattern> patterns,
List<InternalPattern> patterns,
) {
return new ListPattern(typeArgument, patterns)..fileOffset = fileOffset;
return new InternalListPattern(
typeArgument: typeArgument,
patterns: patterns,
fileOffset: fileOffset,
);
}
LoadLibrary createLoadLibrary(
@@ -846,25 +863,34 @@ MapLiteralEntry createMapLiteralEntry(
return new MapLiteralEntry(key, value)..fileOffset = fileOffset;
}
MapPattern createMapPattern(
Pattern createMapPattern(
int fileOffset,
DartType? keyType,
DartType? valueType,
List<MapPatternEntry> entries,
List<InternalMapPatternEntry> entries,
) {
return new MapPattern(keyType, valueType, entries)..fileOffset = fileOffset;
return new InternalMapPattern(
keyType: keyType,
valueType: valueType,
entries: entries,
fileOffset: fileOffset,
);
}
MapPatternEntry createMapPatternEntry(
InternalMapPatternEntry createMapPatternEntry(
int fileOffset,
Expression key,
Pattern value,
InternalPattern value,
) {
return new MapPatternEntry(key, value)..fileOffset = fileOffset;
return new InternalMapPatternEntry(
key: key,
value: value,
fileOffset: fileOffset,
);
}
MapPatternRestEntry createMapPatternRestEntry(int fileOffset) {
return new MapPatternRestEntry()..fileOffset = fileOffset;
InternalMapPatternRestEntry createMapPatternRestEntry(int fileOffset) {
return new InternalMapPatternRestEntry(fileOffset: fileOffset);
}
Expression createMethodInvocation(
@@ -950,16 +976,27 @@ InternalVariable createNamedParameter({
}
}
NamedPattern createNamedPattern(int fileOffset, String name, Pattern pattern) {
return new NamedPattern(name, pattern)..fileOffset = fileOffset;
Pattern 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;
}
NullAssertPattern createNullAssertPattern(int fileOffset, Pattern pattern) {
return new NullAssertPattern(pattern)..fileOffset = fileOffset;
Pattern createNullAssertPattern(int fileOffset, InternalPattern pattern) {
return new InternalNullAssertPattern(
pattern: pattern,
fileOffset: fileOffset,
);
}
Expression createNullAwareElement(int fileOffset, Expression expression) {
@@ -990,8 +1027,8 @@ NullCheck createNullCheck(int fileOffset, Expression expression) {
return new NullCheck(expression)..fileOffset = fileOffset;
}
NullCheckPattern createNullCheckPattern(int fileOffset, Pattern pattern) {
return new NullCheckPattern(pattern)..fileOffset = fileOffset;
Pattern createNullCheckPattern(int fileOffset, InternalPattern pattern) {
return new InternalNullCheckPattern(pattern: pattern, fileOffset: fileOffset);
}
/// Return a representation of a null literal at the given [fileOffset].
@@ -999,17 +1036,34 @@ NullLiteral createNullLiteral(int fileOffset) {
return new NullLiteral()..fileOffset = fileOffset;
}
OrPattern createOrPattern(
Pattern createOrPattern(
int fileOffset,
Pattern left,
Pattern right, {
required List<Variable> orPatternJointVariables,
InternalPattern left,
InternalPattern right, {
required List<InternalVariable> orPatternJointVariables,
}) {
return new OrPattern(
return new InternalOrPattern(
left,
right,
orPatternJointVariables: orPatternJointVariables,
)..fileOffset = fileOffset;
fileOffset: fileOffset,
);
}
Pattern 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(
@@ -1200,8 +1254,8 @@ Expression createPropertySet(
)..fileOffset = fileOffset;
}
RecordPattern createRecordPattern(int fileOffset, List<Pattern> patterns) {
return new RecordPattern(patterns)..fileOffset = fileOffset;
Pattern createRecordPattern(int fileOffset, List<InternalPattern> patterns) {
return new InternalRecordPattern(patterns: patterns, fileOffset: fileOffset);
}
RedirectingFactoryTearOff createRedirectingFactoryTearOff(
@@ -1212,16 +1266,23 @@ RedirectingFactoryTearOff createRedirectingFactoryTearOff(
return new RedirectingFactoryTearOff(procedure)..fileOffset = fileOffset;
}
RelationalPattern createRelationalPattern(
Pattern createRelationalPattern(
int fileOffset,
RelationalPatternKind kind,
Expression expression,
) {
return new RelationalPattern(kind, expression)..fileOffset = fileOffset;
return new InternalRelationalPattern(
kind: kind,
expression: expression,
fileOffset: fileOffset,
);
}
RestPattern createRestPattern(int fileOffset, Pattern? subPattern) {
return new RestPattern(subPattern)..fileOffset = fileOffset;
Pattern createRestPattern(int fileOffset, InternalPattern? subPattern) {
return new InternalRestPattern(
subPattern: subPattern,
fileOffset: fileOffset,
);
}
/// Return a representation of a rethrow statement consisting of the
@@ -1512,13 +1573,16 @@ InternalVariableGet createVariableGet(
return new InternalVariableGet(variable)..fileOffset = fileOffset;
}
VariablePattern createVariablePattern(
Pattern createVariablePattern(
int fileOffset,
DartType? type,
InternalVariable variable,
) {
return new VariablePattern(type, variable.asVariableDeclaration)
..fileOffset = fileOffset;
return new InternalVariablePattern(
type: type,
variable: variable,
fileOffset: fileOffset,
);
}
InternalVariableSet createVariableSet(
@@ -1547,8 +1611,8 @@ Statement createWhileStatement(
return new WhileStatement(condition, body)..fileOffset = fileOffset;
}
WildcardPattern createWildcardPattern(int fileOffset, DartType? type) {
return new WildcardPattern(type)..fileOffset = fileOffset;
Pattern createWildcardPattern(int fileOffset, DartType? type) {
return new InternalWildcardPattern(type: type, fileOffset: fileOffset);
}
/// Return a representation of a yield statement at the given [fileOffset]
+10 -6
View File
@@ -135,17 +135,21 @@ class ValueKinds {
static const ValueKind MapLiteralEntry =
const SingleValueKind<type.MapLiteralEntry>();
static const ValueKind MapPatternEntry =
const SingleValueKind<type.MapPatternEntry>();
const SingleValueKind<type.InternalMapPatternEntry>();
static const ValueKind ParameterList =
const SingleValueKind<List<type.ParameterVariableBuilder>>();
static const ValueKind Pattern = const SingleValueKind<type.Pattern>();
static const ValueKind Pattern =
const SingleValueKind<type.InternalPattern>();
static const ValueKind PatternGuard =
const SingleValueKind<type.PatternGuard>();
static const ValueKind PatternOrNull = const SingleValueKind<type.Pattern>(
NullValues.Pattern,
);
static const ValueKind PatternOrNull =
const SingleValueKind<type.InternalPattern>(NullValues.Pattern);
static const ValueKind PatternListOrNull =
const SingleValueKind<List<type.Pattern>>(NullValues.PatternList);
const SingleValueKind<List<type.InternalPattern>>(NullValues.PatternList);
static const ValueKind NamedPatternListOrNull =
const SingleValueKind<List<type.InternalNamedPattern>>(
NullValues.PatternList,
);
static const ValueKind PrefixOrNull = const SingleValueKind<type.Identifier>(
NullValues.Prefix,
);
@@ -236,7 +236,6 @@ class LoopDepthAllocationStrategy
case ScopeProviderInfoKind.FunctionNode:
case ScopeProviderInfoKind.FunctionNodeWithThis:
case ScopeProviderInfoKind.InstanceField:
// Coverage-ignore(suite): Not run.
case ScopeProviderInfoKind.StaticField:
return true;
}
File diff suppressed because it is too large Load Diff
@@ -11,6 +11,7 @@ import 'package:kernel/core_types.dart';
import '../base/compiler_context.dart';
import '../base/messages.dart';
import '../kernel/internal_ast.dart';
import '../source/check_helper.dart';
import 'inference_visitor.dart';
@@ -249,7 +250,7 @@ class SharedTypeAnalyzerErrors
@override
InvalidExpression relationalPatternOperandTypeNotAssignable({
required covariant RelationalPattern pattern,
required covariant InternalRelationalPattern pattern,
required SharedTypeView operandType,
required SharedTypeView parameterType,
}) {