diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart index 905ea3bf3ce..e08354b4e96 100644 --- a/pkg/front_end/lib/src/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/kernel/body_builder.dart @@ -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 leftVariablesByName = { - for (Variable leftVariable in left.declaredVariables) - leftVariable.name!: leftVariable, + Map 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 rightVariablesByName = { - for (Variable rightVariable in right.declaredVariables) - rightVariable.name!: rightVariable, + Map 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 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 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 intermediateVariables = []; List 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 patterns = new List.filled( + List patterns = new List.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 patterns = new List.filled(count, dummyPattern); + List patterns = new List.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 entries = []; + List entries = []; 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 patternVariablesByName = { - for (Variable variable in patternGuard.pattern.declaredVariables) - variable.name!: variable, + Map 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? fields; + List? fields; for (int i = 0; i < count; i++) { Object? field = pop(); - if (field is NamedPattern) { - (fields ??= []).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? fields = pop() as List?; + List? fields = pop() as List?; List? typeArguments = pop() as List?; handleIdentifier(firstIdentifier, IdentifierContext.prefixedTypeReference); @@ -10932,12 +10940,15 @@ class BodyBuilderImpl extends StackListenerImpl allowPotentiallyConstantType: true, ); push( - new ObjectPatternInternal( - type, - fields ?? [], - 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?; diff --git a/pkg/front_end/lib/src/kernel/external_ast_helper.dart b/pkg/front_end/lib/src/kernel/external_ast_helper.dart index 374528a6872..a7eb62e12d1 100644 --- a/pkg/front_end/lib/src/kernel/external_ast_helper.dart +++ b/pkg/front_end/lib/src/kernel/external_ast_helper.dart @@ -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 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 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 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 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 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 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 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? 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; +} diff --git a/pkg/front_end/lib/src/kernel/internal_ast.dart b/pkg/front_end/lib/src/kernel/internal_ast.dart index b274ffd1588..02b0b82df4c 100644 --- a/pkg/front_end/lib/src/kernel/internal_ast.dart +++ b/pkg/front_end/lib/src/kernel/internal_ast.dart @@ -1483,7 +1483,6 @@ class InternalNamedParameter extends TreeNode } @override - // Coverage-ignore(suite): Not run. List get annotations => astVariable.annotations; @override @@ -1627,7 +1626,6 @@ mixin DelegatingVariableMixin on InternalVariableMixin } @override - // Coverage-ignore(suite): Not run. List 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 get internalDeclaredVariables; + + @override + @Deprecated('Use internalDeclaredVariables instead') + List 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 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 orPatternJointVariables; + + @override + List 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 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 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 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 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 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 `[pattern0, ... patternN]`. +class InternalListPattern extends InternalPattern { + /// The element type argument as specified by the list pattern syntax. + DartType? typeArgument; + + List patterns; + + @override + List 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 entries; + + @override + List 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(TreeVisitor v) { + throw new UnimplementedError('${runtimeType}.accept'); + } + + @override + R accept1(TreeVisitor1 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(TreeVisitor v) { + throw new UnimplementedError('${runtimeType}.accept'); + } + + @override + R accept1(TreeVisitor1 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 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 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 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 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 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 patterns; + + @override + List 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 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 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 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 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()})"; + } +} diff --git a/pkg/front_end/lib/src/kernel/internal_ast_helper.dart b/pkg/front_end/lib/src/kernel/internal_ast_helper.dart index cdebf0b9d97..393d7c37fbe 100644 --- a/pkg/front_end/lib/src/kernel/internal_ast_helper.dart +++ b/pkg/front_end/lib/src/kernel/internal_ast_helper.dart @@ -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 declaredVariables, + required List 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 patterns, + List 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 entries, + List 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 orPatternJointVariables, + InternalPattern left, + InternalPattern right, { + required List orPatternJointVariables, }) { - return new OrPattern( + return new InternalOrPattern( left, right, orPatternJointVariables: orPatternJointVariables, - )..fileOffset = fileOffset; + fileOffset: fileOffset, + ); +} + +Pattern createObjectPattern({ + required DartType requiredType, + required List 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 patterns) { - return new RecordPattern(patterns)..fileOffset = fileOffset; +Pattern createRecordPattern(int fileOffset, List 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] diff --git a/pkg/front_end/lib/src/source/value_kinds.dart b/pkg/front_end/lib/src/source/value_kinds.dart index 9e0d5a20bf1..76bfa0d749d 100644 --- a/pkg/front_end/lib/src/source/value_kinds.dart +++ b/pkg/front_end/lib/src/source/value_kinds.dart @@ -135,17 +135,21 @@ class ValueKinds { static const ValueKind MapLiteralEntry = const SingleValueKind(); static const ValueKind MapPatternEntry = - const SingleValueKind(); + const SingleValueKind(); static const ValueKind ParameterList = const SingleValueKind>(); - static const ValueKind Pattern = const SingleValueKind(); + static const ValueKind Pattern = + const SingleValueKind(); static const ValueKind PatternGuard = const SingleValueKind(); - static const ValueKind PatternOrNull = const SingleValueKind( - NullValues.Pattern, - ); + static const ValueKind PatternOrNull = + const SingleValueKind(NullValues.Pattern); static const ValueKind PatternListOrNull = - const SingleValueKind>(NullValues.PatternList); + const SingleValueKind>(NullValues.PatternList); + static const ValueKind NamedPatternListOrNull = + const SingleValueKind>( + NullValues.PatternList, + ); static const ValueKind PrefixOrNull = const SingleValueKind( NullValues.Prefix, ); diff --git a/pkg/front_end/lib/src/type_inference/context_allocation_strategy.dart b/pkg/front_end/lib/src/type_inference/context_allocation_strategy.dart index 333aa3719b3..dbe31818f3e 100644 --- a/pkg/front_end/lib/src/type_inference/context_allocation_strategy.dart +++ b/pkg/front_end/lib/src/type_inference/context_allocation_strategy.dart @@ -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; } diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/type_inference/inference_visitor.dart index 5cd969bf6f0..a56e967a3ec 100644 --- a/pkg/front_end/lib/src/type_inference/inference_visitor.dart +++ b/pkg/front_end/lib/src/type_inference/inference_visitor.dart @@ -146,7 +146,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase ExpressionVisitor1, StatementVisitor, InitializerVisitor, - PatternVisitor1, InferenceVisitor { /// Debug-only: if `true`, manipulations of [_rewriteStack] performed by /// [popRewrite] and [pushRewrite] will be printed. @@ -922,17 +921,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase "${node.runtimeType}", "InferenceVisitor", node.fileOffset, - node.location!.file, - ); - } - - // Coverage-ignore(suite): Not run. - Never _unhandledPattern(Pattern node) { - problems.unhandled( - "${node.runtimeType}", - "InferenceVisitor", - node.fileOffset, - node.location!.file, + fileUri, ); } @@ -3504,7 +3493,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase }); StatementInferenceResult bodyResult = inferStatement(node.body); if (bodyResult.hasChanged) { - // Coverage-ignore-block(suite): Not run. node.body = bodyResult.statement..parent = node; } flowAnalysis.for_updaterBegin(); @@ -3866,9 +3854,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase node.then, node.otherwise, { - for (Variable variable - in node.patternGuard.pattern.declaredVariables) - variable.name!: variable, + for (InternalVariable variable + in (node.patternGuard.pattern as InternalPattern) + .internalDeclaredVariables) + variable.cosmeticName!: variable.astVariable, }, ); @@ -4286,9 +4275,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase expression: element.expression, pattern: element.patternGuard.pattern, variables: { - for (Variable variable - in element.patternGuard.pattern.declaredVariables) - variable.name!: variable, + for (InternalVariable variable + in (element.patternGuard.pattern as InternalPattern) + .internalDeclaredVariables) + variable.cosmeticName!: variable.astVariable, }, guard: element.patternGuard.guard, ifTrue: element.then, @@ -4340,7 +4330,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase rewrite = popRewrite(); if (!identical(patternGuard.pattern, rewrite)) { - // Coverage-ignore-block(suite): Not run. patternGuard.pattern = (rewrite as Pattern)..parent = patternGuard; } @@ -4394,7 +4383,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase Object? rewrite = popRewrite(NullValues.Expression); if (!identical(patternVariableDeclaration.pattern, rewrite)) { - // Coverage-ignore-block(suite): Not run. patternVariableDeclaration.pattern = (rewrite as Pattern) ..parent = patternVariableDeclaration; } @@ -7413,9 +7401,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase expression: entry.expression, pattern: entry.patternGuard.pattern, variables: { - for (Variable variable - in entry.patternGuard.pattern.declaredVariables) - variable.name!: variable, + for (InternalVariable variable + in (entry.patternGuard.pattern as InternalPattern) + .internalDeclaredVariables) + variable.cosmeticName!: variable.astVariable, }, guard: entry.patternGuard.guard, ifTrue: entry.then, @@ -7495,7 +7484,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase rewrite = popRewrite(); if (!identical(patternGuard.pattern, rewrite)) { - // Coverage-ignore-block(suite): Not run. patternGuard.pattern = (rewrite as Pattern)..parent = patternGuard; } @@ -7543,7 +7531,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase Object? rewrite = popRewrite(NullValues.Expression); if (!identical(patternVariableDeclaration.pattern, rewrite)) { - // Coverage-ignore-block(suite): Not run. patternVariableDeclaration.pattern = (rewrite as Pattern) ..parent = patternVariableDeclaration; } @@ -14280,7 +14267,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase // performed. needsCoercion = needsCoercion || - parent is RelationalPattern && parent.expression == node; + parent is InternalRelationalPattern && parent.expression == node; ExpressionInferenceResult expressionResult = inferExpression( node, @@ -14323,8 +14310,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase @override PatternResult dispatchPattern(SharedMatchContext context, TreeNode node) { - if (node is Pattern) { - return node.accept1(this, context); + if (node is InternalPattern) { + return node.acceptInference(this, context); } else { return analyzeConstantPattern(context, node, node as Expression); } @@ -14332,87 +14319,94 @@ class InferenceVisitorImpl extends InferenceVisitorBase @override SharedTypeSchemaView dispatchPatternSchema(Node node) { - if (node is AndPattern) { - return analyzeLogicalAndPatternSchema(node.left, node.right); - } else if (node is AssignedVariablePattern) { - return analyzeAssignedVariablePatternSchema(node.variable); - } else if (node is CastPattern) { - return analyzeCastPatternSchema(); - } else if (node is ConstantPattern) { - return analyzeConstantPatternSchema(); - } else if (node is ListPattern) { - return analyzeListPatternSchema( - elementType: node.typeArgument?.wrapSharedTypeView(), - elements: node.patterns, - ); - } else if (node is MapPattern) { - return analyzeMapPatternSchema( - typeArguments: - node.keyType != null && - // Coverage-ignore(suite): Not run. - node.valueType != null - ? - // Coverage-ignore(suite): Not run. - ( - keyType: new SharedTypeView(node.keyType!), - valueType: new SharedTypeView(node.valueType!), - ) - : null, - elements: node.entries, - ); - } else if (node is NamedPattern) { - // Coverage-ignore-block(suite): Not run. - return dispatchPatternSchema(node.pattern); - } else if (node is NullAssertPattern) { - return analyzeNullCheckOrAssertPatternSchema( - node.pattern, - isAssert: true, - ); - } else if (node is NullCheckPattern) { - return analyzeNullCheckOrAssertPatternSchema( - node.pattern, - isAssert: false, - ); - } else if (node is ObjectPattern) { - return analyzeObjectPatternSchema(new SharedTypeView(node.requiredType)); - } else if (node is OrPattern) { - // Coverage-ignore-block(suite): Not run. - return analyzeLogicalOrPatternSchema(node.left, node.right); - } else if (node is RecordPattern) { - return analyzeRecordPatternSchema( - fields: >[ - for (Pattern element in node.patterns) - if (element is NamedPattern) - new RecordPatternField( - node: element, - name: element.name, - pattern: element.pattern, - ) - else - new RecordPatternField( - node: element, - name: null, - pattern: element, - ), - ], - ); - } else if (node is RelationalPattern) { - // Coverage-ignore-block(suite): Not run. - return analyzeRelationalPatternSchema(); - } else if (node is RestPattern) { - // Coverage-ignore-block(suite): Not run. - // This pattern can't appear on it's own. - return new SharedTypeSchemaView(const InvalidType()); - } else if (node is VariablePattern) { - return analyzeDeclaredVariablePatternSchema( - node.type?.wrapSharedTypeView(), - ); - } else if (node is WildcardPattern) { - return analyzeDeclaredVariablePatternSchema( - node.type?.wrapSharedTypeView(), - ); - } else if (node is InvalidPattern) { - return new SharedTypeSchemaView(const InvalidType()); + if (node is InternalPattern) { + switch (node) { + case InternalAndPattern(): + return analyzeLogicalAndPatternSchema(node.left, node.right); + case InternalAssignedVariablePattern(): + return analyzeAssignedVariablePatternSchema( + node.variable.astVariable, + ); + case InternalCastPattern(): + return analyzeCastPatternSchema(); + case InternalConstantPattern(): + return analyzeConstantPatternSchema(); + case InternalListPattern(): + return analyzeListPatternSchema( + elementType: node.typeArgument?.wrapSharedTypeView(), + elements: node.patterns, + ); + case InternalMapPattern(): + return analyzeMapPatternSchema( + typeArguments: + node.keyType != null && + // Coverage-ignore(suite): Not run. + node.valueType != null + ? + // Coverage-ignore(suite): Not run. + ( + keyType: new SharedTypeView(node.keyType!), + valueType: new SharedTypeView(node.valueType!), + ) + : null, + elements: node.entries, + ); + case InternalNamedPattern(): + // Coverage-ignore(suite): Not run. + return dispatchPatternSchema(node.pattern); + case InternalNullAssertPattern(): + return analyzeNullCheckOrAssertPatternSchema( + node.pattern, + isAssert: true, + ); + case InternalNullCheckPattern(): + return analyzeNullCheckOrAssertPatternSchema( + node.pattern, + isAssert: false, + ); + case InternalObjectPattern(): + return analyzeObjectPatternSchema( + new SharedTypeView(node.requiredType), + ); + case InternalOrPattern(): + // Coverage-ignore(suite): Not run. + return analyzeLogicalOrPatternSchema(node.left, node.right); + case InternalRecordPattern(): + return analyzeRecordPatternSchema( + fields: >[ + for (InternalPattern element in node.patterns) + if (element is InternalNamedPattern) + new RecordPatternField( + node: element, + name: element.name, + pattern: element.pattern, + ) + else + new RecordPatternField( + node: element, + name: null, + pattern: element, + ), + ], + ); + case InternalRelationalPattern(): + // Coverage-ignore(suite): Not run. + return analyzeRelationalPatternSchema(); + case InternalRestPattern(): + // Coverage-ignore(suite): Not run. + // This pattern can't appear on it's own. + return new SharedTypeSchemaView(const InvalidType()); + case InternalVariablePattern(): + return analyzeDeclaredVariablePatternSchema( + node.type?.wrapSharedTypeView(), + ); + case InternalWildcardPattern(): + return analyzeDeclaredVariablePatternSchema( + node.type?.wrapSharedTypeView(), + ); + case InternalInvalidPattern(): + return new SharedTypeSchemaView(const InvalidType()); + } } else { // Coverage-ignore-block(suite): Not run. return problems.unhandled( @@ -14553,8 +14547,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase (node as SwitchExpression).cases[index]; Pattern pattern = switchExpressionCase.patternGuard.pattern; Map variables = { - for (Variable declaredVariable in pattern.declaredVariables) - declaredVariable.name!: declaredVariable, + for (InternalVariable declaredVariable + in (pattern as InternalPattern).internalDeclaredVariables) + declaredVariable.cosmeticName!: declaredVariable.astVariable, }; return new SwitchExpressionMemberInfo( head: new CaseHeadOrDefaultInfo( @@ -14591,9 +14586,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase pattern: patternGuard.pattern, guard: patternGuard.guard, variables: { - for (Variable variable - in patternGuard.pattern.declaredVariables) - variable.name!: variable, + for (InternalVariable variable + in (patternGuard.pattern as InternalPattern) + .internalDeclaredVariables) + variable.cosmeticName!: variable.astVariable, }, ), if (case_.isDefault) @@ -14822,9 +14818,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase assert(_rewriteStack.isEmpty); } - @override - PatternResult visitVariablePattern( - VariablePattern node, + PatternResult visitInternalVariablePattern( + InternalVariablePattern node, SharedMatchContext context, ) { int? stackBase; @@ -14834,12 +14829,13 @@ class InferenceVisitorImpl extends InferenceVisitorBase analyzeDeclaredVariablePattern( context, node, - node.variable, - node.variable.name!, + node.variable.astVariable, + node.variableName, node.type?.wrapSharedTypeView(), ); - node.matchedValueType = analysisResult.matchedValueType.unwrapTypeView(); + DartType matchedValueType = analysisResult.matchedValueType + .unwrapTypeView(); Pattern? replacement; @@ -14847,10 +14843,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase analysisResult.patternTypeMismatchInIrrefutableContextError; if (error != null) { // Coverage-ignore-block(suite): Not run. - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } DartType inferredType = analysisResult.staticType.unwrapTypeView(); @@ -14858,15 +14854,22 @@ class InferenceVisitorImpl extends InferenceVisitorBase node.variable.type = inferredType; } - pushRewrite(replacement ?? node); + pushRewrite( + replacement ?? + extern.createVariablePattern( + type: node.type, + variable: node.variable.astVariable, + matchedValueType: matchedValueType, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitWildcardPattern( - WildcardPattern node, + PatternResult visitInternalWildcardPattern( + InternalWildcardPattern node, SharedMatchContext context, ) { int? stackBase; @@ -14885,21 +14888,26 @@ class InferenceVisitorImpl extends InferenceVisitorBase analysisResult.patternTypeMismatchInIrrefutableContextError; if (error != null) { // Coverage-ignore-block(suite): Not run. - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } - pushRewrite(replacement ?? node); + pushRewrite( + replacement ?? + extern.createWildcardPattern( + type: node.type, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitConstantPattern( - ConstantPattern node, + PatternResult visitInternalConstantPattern( + InternalConstantPattern node, SharedMatchContext context, ) { int? stackBase; @@ -14913,15 +14921,13 @@ class InferenceVisitorImpl extends InferenceVisitorBase InvalidExpression? error = analysisResult.refutablePatternInIrrefutableContextError; if (error != null) { - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } - DartType expressionType = node.expressionType = analysisResult - .expressionType - .unwrapTypeView(); + DartType expressionType = analysisResult.expressionType.unwrapTypeView(); ObjectAccessTarget equalsInvokeTarget = findInterfaceMember( expressionType, @@ -14936,8 +14942,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase equalsInvokeTarget.isNever, ); - node.equalsTarget = equalsInvokeTarget.classMember as Procedure; - node.equalsType = equalsInvokeTarget + Procedure equalsTarget = equalsInvokeTarget.classMember as Procedure; + FunctionType equalsType = equalsInvokeTarget .getFunctionType(this) .equalsFunctionType; @@ -14946,18 +14952,30 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); Object? rewrite = popRewrite(); + Expression expression = node.expression; if (!identical(node.expression, rewrite)) { - node.expression = (rewrite as Expression)..parent = node; + expression = rewrite as Expression; } - pushRewrite(replacement ?? node); + pushRewrite( + replacement ?? + extern.createConstantPattern( + expression: expression, + expressionType: expressionType, + equalsTarget: equalsTarget, + equalsType: equalsType, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitAndPattern(AndPattern node, SharedMatchContext context) { + PatternResult visitInternalAndPattern( + InternalAndPattern node, + SharedMatchContext context, + ) { int? stackBase; assert(checkStackBase(node, stackBase = stackHeight)); @@ -14976,25 +14994,33 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); Object? rewrite = popRewrite(); + Pattern right = node.right; if (!identical(rewrite, node.right)) { - // Coverage-ignore-block(suite): Not run. - node.right = (rewrite as Pattern)..parent = node; + right = rewrite as Pattern; } rewrite = popRewrite(); + Pattern left = node.left; if (!identical(rewrite, node.left)) { - // Coverage-ignore-block(suite): Not run. - node.left = (rewrite as Pattern)..parent = node; + left = rewrite as Pattern; } - pushRewrite(node); + pushRewrite( + extern.createAndPattern( + left: left, + right: right, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitOrPattern(OrPattern node, SharedMatchContext context) { + PatternResult visitInternalOrPattern( + InternalOrPattern node, + SharedMatchContext context, + ) { int? stackBase; assert(checkStackBase(node, stackBase = stackHeight)); @@ -15014,34 +15040,35 @@ class InferenceVisitorImpl extends InferenceVisitorBase analysisResult.refutablePatternInIrrefutableContextError; if (error != null) { // Coverage-ignore-block(suite): Not run. - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } Object? rewrite = popRewrite(); + Pattern right = node.right; if (!identical(rewrite, node.right)) { - // Coverage-ignore-block(suite): Not run. - node.right = (rewrite as Pattern)..parent = node; + right = rewrite as Pattern; } rewrite = popRewrite(); + Pattern left = node.left; if (!identical(rewrite, node.left)) { - // Coverage-ignore-block(suite): Not run. - node.left = (rewrite as Pattern)..parent = node; + left = rewrite as Pattern; } Map leftDeclaredVariablesByName = { - for (Variable variable in node.left.declaredVariables) - variable.name!: variable, + for (InternalVariable variable in node.left.internalDeclaredVariables) + variable.cosmeticName!: variable.astVariable, }; Map jointVariableNames = { - for (Variable variable in node.orPatternJointVariables) - variable.name!: variable, + for (InternalVariable variable in node.orPatternJointVariables) + variable.cosmeticName!: variable.astVariable, }; - for (Variable rightVariable in node.right.declaredVariables) { - String rightVariableName = rightVariable.name!; + for (InternalVariable rightVariable + in node.right.internalDeclaredVariables) { + String rightVariableName = rightVariable.cosmeticName!; Variable? leftVariable = leftDeclaredVariablesByName[rightVariableName]; Variable? jointVariable = jointVariableNames[rightVariableName]; if (leftVariable != null && jointVariable != null) { @@ -15062,14 +15089,23 @@ class InferenceVisitorImpl extends InferenceVisitorBase } } - pushRewrite(replacement ?? node); + replacement ??= extern.createOrPattern( + left: left, + right: right, + orPatternJointVariables: jointVariableNames.values.toList(), + fileOffset: node.fileOffset, + ); + + pushRewrite(replacement); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitCastPattern(CastPattern node, SharedMatchContext context) { + PatternResult visitInternalCastPattern( + InternalCastPattern node, + SharedMatchContext context, + ) { int? stackBase; assert(checkStackBase(node, stackBase = stackHeight)); @@ -15085,20 +15121,25 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); Object? rewrite = popRewrite(); + Pattern pattern = node.pattern; if (!identical(rewrite, node.pattern)) { - // Coverage-ignore-block(suite): Not run. - node.pattern = (rewrite as Pattern)..parent = node; + pattern = rewrite as Pattern; } - pushRewrite(node); + pushRewrite( + extern.createCastPattern( + pattern: pattern, + type: node.type, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitNullAssertPattern( - NullAssertPattern node, + PatternResult visitInternalNullAssertPattern( + InternalNullAssertPattern node, SharedMatchContext context, ) { int? stackBase; @@ -15122,27 +15163,28 @@ class InferenceVisitorImpl extends InferenceVisitorBase analysisResult.refutablePatternInIrrefutableContextError; if (error != null) { // Coverage-ignore-block(suite): Not run. - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } - Object? rewrite = popRewrite(); - if (!identical(rewrite, node.pattern)) { - // Coverage-ignore-block(suite): Not run. - node.pattern = (rewrite as Pattern)..parent = node; - } + Pattern pattern = popRewrite() as Pattern; - pushRewrite(replacement ?? node); + pushRewrite( + replacement ?? + extern.createNullAssertPattern( + pattern: pattern, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitNullCheckPattern( - NullCheckPattern node, + PatternResult visitInternalNullCheckPattern( + InternalNullCheckPattern node, SharedMatchContext context, ) { int? stackBase; @@ -15160,20 +15202,23 @@ class InferenceVisitorImpl extends InferenceVisitorBase checkStack(node, stackBase, [/* subpattern = */ ValueKinds.Pattern]), ); - Object? rewrite = popRewrite(); - if (!identical(rewrite, node.pattern)) { - // Coverage-ignore-block(suite): Not run. - node.pattern = (rewrite as Pattern)..parent = node; - } + Pattern pattern = popRewrite() as Pattern; - pushRewrite(node); + pushRewrite( + extern.createNullCheckPattern( + pattern: pattern, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitListPattern(ListPattern node, SharedMatchContext context) { + PatternResult visitInternalListPattern( + InternalListPattern node, + SharedMatchContext context, + ) { int? stackBase; assert(checkStackBase(node, stackBase = stackHeight)); @@ -15184,8 +15229,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase elementType: node.typeArgument?.wrapSharedTypeView(), ); - DartType matchedValueType = node.matchedValueType = analysisResult - .matchedValueType + DartType matchedValueType = analysisResult.matchedValueType .unwrapTypeView(); assert( @@ -15202,43 +15246,44 @@ class InferenceVisitorImpl extends InferenceVisitorBase InvalidExpression? error = analysisResult.patternTypeMismatchInIrrefutableContextError; if (error != null) { - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } + List patterns = new List.filled( + node.patterns.length, + dummyPattern, + ); for (int i = node.patterns.length - 1; i >= 0; i--) { Object? rewrite = popRewrite(); InvalidExpression? error = analysisResult.duplicateRestPatternErrors?[i]; if (error != null) { - node.patterns[i] = - new InvalidPattern( - error, - declaredVariables: node.patterns[i].declaredVariables, - ) - ..fileOffset = error.fileOffset - ..parent = node; - } else if (!identical(rewrite, node.patterns[i])) { - node.patterns[i] = (rewrite as Pattern)..parent = node; + patterns[i] = extern.createInvalidPattern( + error: error, + declaredVariables: node.patterns[i].internalDeclaredVariables, + ); + } else { + patterns[i] = rewrite as Pattern; } } // TODO(johnniwinther): The required type computed by the type analyzer // isn't trivially `List` in all cases. Does that matter for the // lowering? - DartType requiredType = node.requiredType = analysisResult.requiredType - .unwrapTypeView(); + DartType requiredType = analysisResult.requiredType.unwrapTypeView(); - node.needsCheck = _needsCheck( + bool needsCheck = _needsCheck( matchedType: matchedValueType, requiredType: requiredType, ); - if (node.needsCheck) { - node.lookupType = requiredType; + DartType lookupType; + if (needsCheck) { + lookupType = requiredType; } else { - node.lookupType = matchedValueType; + lookupType = matchedValueType; } ObjectAccessTarget lengthTarget = findInterfaceMember( @@ -15250,8 +15295,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); assert(lengthTarget.isInstanceMember); - DartType lengthType = node.lengthType = lengthTarget.getGetterType(this); - node.lengthTarget = lengthTarget.classMember!; + DartType lengthType = lengthTarget.getGetterType(this); + Member lengthMember = lengthTarget.classMember!; ObjectAccessTarget sublistInvokeTarget = findInterfaceMember( requiredType, @@ -15262,8 +15307,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); assert(sublistInvokeTarget.isInstanceMember); - node.sublistTarget = sublistInvokeTarget.classMember as Procedure; - node.sublistType = sublistInvokeTarget + Procedure sublistTarget = sublistInvokeTarget.classMember as Procedure; + FunctionType sublistType = sublistInvokeTarget .getFunctionType(this) .sublistFunctionType; @@ -15277,8 +15322,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase assert(minusTarget.isInstanceMember); assert(minusTarget.isSpecialCasedBinaryOperator(this)); - node.minusTarget = minusTarget.classMember as Procedure; - node.minusType = replaceReturnType( + Procedure minusProcedure = minusTarget.classMember as Procedure; + FunctionType minusType = replaceReturnType( minusTarget.getFunctionType(this).minusFunctionType, typeSchemaEnvironment.getTypeOfSpecialCasedBinaryOperator( lengthType, @@ -15295,19 +15340,22 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); assert(indexGetTarget.isInstanceMember); - node.indexGetTarget = indexGetTarget.classMember as Procedure; - node.indexGetType = indexGetTarget + Procedure indexGet = indexGetTarget.classMember as Procedure; + FunctionType indexGetType = indexGetTarget .getFunctionType(this) .indexGetFunctionType; - for (Pattern pattern in node.patterns) { + bool hasRestPattern = false; + for (Pattern pattern in patterns) { if (pattern is RestPattern) { - node.hasRestPattern = true; + hasRestPattern = true; break; } } - if (node.hasRestPattern) { + Procedure lengthCheckTarget; + FunctionType lengthCheckType; + if (hasRestPattern) { ObjectAccessTarget greaterThanOrEqualTarget = findInterfaceMember( lengthType, greaterThanOrEqualsName, @@ -15317,9 +15365,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); assert(greaterThanOrEqualTarget.isInstanceMember); - node.lengthCheckTarget = - greaterThanOrEqualTarget.classMember as Procedure; - node.lengthCheckType = greaterThanOrEqualTarget + lengthCheckTarget = greaterThanOrEqualTarget.classMember as Procedure; + lengthCheckType = greaterThanOrEqualTarget .getFunctionType(this) .greaterThanOrEqualsFunctionType; } else if (node.patterns.isEmpty) { @@ -15332,9 +15379,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); assert(lessThanOrEqualsInvokeTarget.isInstanceMember); - node.lengthCheckTarget = - lessThanOrEqualsInvokeTarget.classMember as Procedure; - node.lengthCheckType = lessThanOrEqualsInvokeTarget + lengthCheckTarget = lessThanOrEqualsInvokeTarget.classMember as Procedure; + lengthCheckType = lessThanOrEqualsInvokeTarget .getFunctionType(this) .lessThanOrEqualsFunctionType; } else { @@ -15347,13 +15393,35 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); assert(equalsInvokeTarget.isInstanceMember); - node.lengthCheckTarget = equalsInvokeTarget.classMember as Procedure; - node.lengthCheckType = equalsInvokeTarget + lengthCheckTarget = equalsInvokeTarget.classMember as Procedure; + lengthCheckType = equalsInvokeTarget .getFunctionType(this) .equalsFunctionType; } - pushRewrite(replacement ?? node); + pushRewrite( + replacement ?? + extern.createListPattern( + typeArgument: node.typeArgument, + patterns: patterns, + requiredType: requiredType, + matchedValueType: matchedValueType, + needsCheck: needsCheck, + lookupType: lookupType, + hasRestPattern: hasRestPattern, + lengthTarget: lengthMember, + lengthType: lengthType, + lengthCheckTarget: lengthCheckTarget, + lengthCheckType: lengthCheckType, + sublistTarget: sublistTarget, + sublistType: sublistType, + minusTarget: minusProcedure, + minusType: minusType, + indexGetTarget: indexGet, + indexGetType: indexGetType, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; @@ -15376,9 +15444,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase matchedType is DynamicType; } - @override - PatternResult visitObjectPattern( - ObjectPattern node, + PatternResult visitInternalObjectPattern( + InternalObjectPattern node, SharedMatchContext context, ) { int? stackBase; @@ -15389,7 +15456,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase context, node, fields: >[ - for (NamedPattern field in node.fields) + for (InternalNamedPattern field in node.fields) new RecordPatternField( node: field, name: field.name, @@ -15398,8 +15465,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase ], ); - DartType matchedValueType = node.matchedValueType = analysisResult - .matchedValueType + DartType matchedValueType = analysisResult.matchedValueType .unwrapTypeView(); assert( @@ -15419,44 +15485,54 @@ class InferenceVisitorImpl extends InferenceVisitorBase analysisResult.patternTypeMismatchInIrrefutableContextError; if (error != null) { // Coverage-ignore-block(suite): Not run. - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } + List fields = new List.filled( + node.fields.length, + dummyNamedPattern, + ); for (int i = node.fields.length - 1; i >= 0; i--) { - NamedPattern field = node.fields[i]; + InternalNamedPattern field = node.fields[i]; Object? rewrite = popRewrite(); InvalidExpression? error = analysisResult.duplicateRecordPatternFieldErrors?[i]; if (error != null) { - field.pattern = - new InvalidPattern( - error, - declaredVariables: field.pattern.declaredVariables, - ) - ..fileOffset = error.fileOffset - ..parent = field; - } else if (!identical(rewrite, field.pattern)) { - field.pattern = (rewrite as Pattern)..parent = field; + fields[i] = extern.createNamedPattern( + name: field.name, + fieldName: new Name(field.name, libraryBuilder.library), + pattern: extern.createInvalidPattern( + error: error, + declaredVariables: field.pattern.internalDeclaredVariables, + ), + fileOffset: field.fileOffset, + ); + } else { + fields[i] = extern.createNamedPattern( + name: field.name, + fieldName: new Name(field.name, libraryBuilder.library), + pattern: rewrite as Pattern, + fileOffset: field.fileOffset, + ); } } - node.needsCheck = _needsCheck( + bool needsCheck = _needsCheck( matchedType: matchedValueType, requiredType: node.requiredType, ); - if (node.needsCheck) { - node.lookupType = node.requiredType; + DartType lookupType; + if (needsCheck) { + lookupType = node.requiredType; } else { - node.lookupType = matchedValueType; + lookupType = matchedValueType; } - for (NamedPattern field in node.fields) { - field.fieldName = new Name(field.name, libraryBuilder.library); - + for (NamedPattern field in fields) { ObjectAccessTarget fieldTarget = findInterfaceMember( node.requiredType, field.fieldName, @@ -15568,27 +15644,35 @@ class InferenceVisitorImpl extends InferenceVisitorBase } } - pushRewrite(replacement ?? node); + pushRewrite( + replacement ?? + extern.createObjectPattern( + requiredType: node.requiredType, + fields: fields, + matchedValueType: matchedValueType, + needsCheck: needsCheck, + lookupType: lookupType, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitRestPattern(RestPattern node, SharedMatchContext context) { - // A rest pattern isn't a real pattern; this code should never be reached. - throw new StateError('visitRestPattern should never be reached'); - } - - @override - PatternResult visitInvalidPattern( - InvalidPattern node, + PatternResult visitInternalInvalidPattern( + InternalInvalidPattern node, SharedMatchContext context, ) { int? stackBase; assert(checkStackBase(node, stackBase = stackHeight)); - pushRewrite(node); + pushRewrite( + extern.createInvalidPattern( + error: node.invalidExpression, + declaredVariables: node.internalDeclaredVariables, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); @@ -15597,9 +15681,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); } - @override - PatternResult visitRelationalPattern( - RelationalPattern node, + PatternResult visitInternalRelationalPattern( + InternalRelationalPattern node, SharedMatchContext context, ) { int? stackBase; @@ -15608,8 +15691,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase RelationalPatternResult analysisResult = analyzeRelationalPattern(context, node, node.expression); - DartType matchedValueType = node.matchedValueType = analysisResult - .matchedValueType + DartType matchedValueType = analysisResult.matchedValueType .unwrapTypeView(); assert( @@ -15623,37 +15705,37 @@ class InferenceVisitorImpl extends InferenceVisitorBase analysisResult.operatorReturnTypeNotAssignableToBoolError ?? analysisResult.argumentTypeNotAssignableError; if (error != null) { - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } Object? rewrite = popRewrite(); + Expression expression = node.expression; if (!identical(rewrite, node.expression)) { - node.expression = (rewrite as Expression)..parent = node; + expression = rewrite as Expression; } DartType expressionType = analysisResult.operandType.unwrapTypeView(); - node.expressionType = expressionType; Name name; switch (node.kind) { case RelationalPatternKind.equals: case RelationalPatternKind.notEquals: - name = node.name = equalsName; + name = equalsName; break; case RelationalPatternKind.lessThan: - name = node.name = lessThanName; + name = lessThanName; break; case RelationalPatternKind.lessThanEqual: - name = node.name = lessThanOrEqualsName; + name = lessThanOrEqualsName; break; case RelationalPatternKind.greaterThan: - name = node.name = greaterThanName; + name = greaterThanName; break; case RelationalPatternKind.greaterThanEqual: - name = node.name = greaterThanOrEqualsName; + name = greaterThanOrEqualsName; break; } ObjectAccessTarget invokeTarget = findInterfaceMember( @@ -15663,6 +15745,10 @@ class InferenceVisitorImpl extends InferenceVisitorBase includeExtensionMethods: true, isSetter: false, ); + FunctionType? functionType; + RelationalAccessKind? accessKind; + Procedure? target; + List? typeArguments; switch (node.kind) { case RelationalPatternKind.equals: case RelationalPatternKind.notEquals: @@ -15672,11 +15758,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase invokeTarget.isNever, ); - node.functionType = invokeTarget - .getFunctionType(this) - .equalsFunctionType; - node.accessKind = RelationalAccessKind.Instance; - node.target = invokeTarget.classMember as Procedure; + functionType = invokeTarget.getFunctionType(this).equalsFunctionType; + accessKind = RelationalAccessKind.Instance; + target = invokeTarget.classMember as Procedure; break; case RelationalPatternKind.lessThan: case RelationalPatternKind.lessThanEqual: @@ -15684,26 +15768,27 @@ class InferenceVisitorImpl extends InferenceVisitorBase case RelationalPatternKind.greaterThanEqual: switch (invokeTarget.kind) { case ObjectAccessTargetKind.instanceMember: - node.functionType = invokeTarget + functionType = invokeTarget .getFunctionType(this) .lessThanOrEqualsFunctionType; - node.target = invokeTarget.classMember as Procedure; - node.accessKind = RelationalAccessKind.Instance; + target = invokeTarget.classMember as Procedure; + accessKind = RelationalAccessKind.Instance; break; case ObjectAccessTargetKind.nullableInstanceMember: case ObjectAccessTargetKind.nullableExtensionMember: case ObjectAccessTargetKind.nullableExtensionTypeMember: case ObjectAccessTargetKind.missing: case ObjectAccessTargetKind.ambiguous: - replacement ??= new InvalidPattern( - createMissingMethodInvocation( + accessKind = RelationalAccessKind.Invalid; + replacement ??= extern.createInvalidPattern( + error: createMissingMethodInvocation( node.fileOffset, matchedValueType, name, isExpressionInvocation: false, ), - declaredVariables: node.declaredVariables, - )..fileOffset = node.fileOffset; + declaredVariables: node.internalDeclaredVariables, + ); break; case ObjectAccessTargetKind.objectMember: case ObjectAccessTargetKind.superMember: @@ -15723,34 +15808,50 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); case ObjectAccessTargetKind.extensionMember: case ObjectAccessTargetKind.extensionTypeMember: - node.functionType = invokeTarget + functionType = invokeTarget .getFunctionType(this) .relationalFunctionType; - node.typeArguments = invokeTarget.receiverTypeArguments; - node.target = invokeTarget.member as Procedure; - node.accessKind = RelationalAccessKind.Static; + typeArguments = invokeTarget.receiverTypeArguments; + target = invokeTarget.member as Procedure; + accessKind = RelationalAccessKind.Static; break; case ObjectAccessTargetKind.dynamic: - node.accessKind = RelationalAccessKind.Dynamic; + accessKind = RelationalAccessKind.Dynamic; break; case ObjectAccessTargetKind.never: - node.accessKind = RelationalAccessKind.Never; + accessKind = RelationalAccessKind.Never; break; case ObjectAccessTargetKind.invalid: - node.accessKind = RelationalAccessKind.Invalid; + accessKind = RelationalAccessKind.Invalid; break; } break; } - pushRewrite(replacement ?? node); + pushRewrite( + replacement ?? + extern.createRelationalPattern( + kind: node.kind, + expression: expression, + expressionType: expressionType, + matchedValueType: matchedValueType, + accessKind: accessKind, + name: name, + target: target, + typeArguments: typeArguments, + functionType: functionType, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitMapPattern(MapPattern node, SharedMatchContext context) { + PatternResult visitInternalMapPattern( + InternalMapPattern node, + SharedMatchContext context, + ) { int? stackBase; assert(checkStackBase(node, stackBase = stackHeight)); @@ -15770,8 +15871,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase elements: node.entries, ); - DartType matchedValueType = node.matchedValueType = analysisResult - .matchedValueType + DartType matchedValueType = analysisResult.matchedValueType .unwrapTypeView(); Pattern? replacement; @@ -15780,35 +15880,35 @@ class InferenceVisitorImpl extends InferenceVisitorBase analysisResult.patternTypeMismatchInIrrefutableContextError; if (error != null) { // Coverage-ignore-block(suite): Not run. - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } error = analysisResult.emptyMapPatternError; if (error != null) { - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } // TODO(johnniwinther): The required type computed by the type analyzer // isn't trivially `Map` in all cases. Does that matter // for the lowering? - DartType requiredType = node.requiredType = analysisResult.requiredType - .unwrapTypeView(); + DartType requiredType = analysisResult.requiredType.unwrapTypeView(); - node.needsCheck = _needsCheck( + bool needsCheck = _needsCheck( matchedType: matchedValueType, requiredType: requiredType, ); - if (node.needsCheck) { - node.lookupType = requiredType; + DartType lookupType; + if (needsCheck) { + lookupType = requiredType; } else { - node.lookupType = matchedValueType; + lookupType = matchedValueType; } ObjectAccessTarget containsKeyTarget = findInterfaceMember( @@ -15821,8 +15921,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase assert(containsKeyTarget.isInstanceMember); - node.containsKeyTarget = containsKeyTarget.classMember as Procedure; - node.containsKeyType = containsKeyTarget + Procedure containsKeyProcedure = containsKeyTarget.classMember as Procedure; + FunctionType containsKeyType = containsKeyTarget .getFunctionType(this) .containsKeyFunctionType; @@ -15835,8 +15935,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); assert(indexGetTarget.isInstanceMember); - node.indexGetTarget = indexGetTarget.classMember as Procedure; - node.indexGetType = indexGetTarget + Procedure indexGetProcedure = indexGetTarget.classMember as Procedure; + FunctionType indexGetType = indexGetTarget .getFunctionType(this) .indexGetFunctionType; @@ -15849,12 +15949,13 @@ class InferenceVisitorImpl extends InferenceVisitorBase ]), ); + List entries = new List.filled( + node.entries.length, + dummyMapPatternEntry, + growable: true, + ); for (int i = node.entries.length - 1; i >= 0; i--) { - Object? rewrite = popRewrite(); - if (!identical(node.entries[i], rewrite)) { - // Coverage-ignore-block(suite): Not run. - node.entries[i] = (rewrite as MapPatternEntry)..parent = node; - } + entries[i] = popRewrite() as MapPatternEntry; } Map? restPatternErrors = @@ -15862,61 +15963,67 @@ class InferenceVisitorImpl extends InferenceVisitorBase if (restPatternErrors != null) { InvalidExpression? firstError; int insertionIndex = 0; - for (int readIndex = 0; readIndex < node.entries.length; readIndex++) { + for (int readIndex = 0; readIndex < entries.length; readIndex++) { InvalidExpression? error = restPatternErrors[readIndex]; if (error != null) { firstError ??= error; } else { - node.entries[insertionIndex++] = node.entries[readIndex]; + entries[insertionIndex++] = entries[readIndex]; } } - node.entries.length = insertionIndex; + entries.length = insertionIndex; if (insertionIndex == 0) { - replacement ??= new InvalidPattern( - firstError!, - declaredVariables: node.declaredVariables, - )..fileOffset = node.fileOffset; + replacement ??= extern.createInvalidPattern( + error: firstError!, + declaredVariables: node.internalDeclaredVariables, + fileOffset: node.fileOffset, + ); } } - pushRewrite(replacement ?? node); + pushRewrite( + replacement ?? + extern.createMapPattern( + keyType: node.keyType, + valueType: node.valueType, + entries: entries, + requiredType: requiredType, + matchedValueType: matchedValueType, + needsCheck: needsCheck, + lookupType: lookupType, + containsKeyTarget: containsKeyProcedure, + containsKeyType: containsKeyType, + indexGetTarget: indexGetProcedure, + indexGetType: indexGetType, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; } - @override - PatternResult visitNamedPattern( - NamedPattern node, - SharedMatchContext context, - ) { - // NamedPattern isn't a real pattern; this code should never be reached. - throw new StateError('visitNamedPattern should never be reached'); - } - - @override - PatternResult visitRecordPattern( - RecordPattern node, + PatternResult visitInternalRecordPattern( + InternalRecordPattern node, SharedMatchContext context, ) { int? stackBase; assert(checkStackBase(node, stackBase = stackHeight)); List> fields = [ - for (Pattern fieldPattern in node.patterns) + for (InternalPattern fieldPattern in node.patterns) new RecordPatternField( node: fieldPattern, - pattern: fieldPattern is NamedPattern + pattern: fieldPattern is InternalNamedPattern ? fieldPattern.pattern : fieldPattern, - name: fieldPattern is NamedPattern ? fieldPattern.name : null, + name: fieldPattern is InternalNamedPattern ? fieldPattern.name : null, ), ]; RecordPatternResult analysisResult = analyzeRecordPattern(context, node, fields: fields); - DartType matchedValueType = node.matchedValueType = analysisResult - .matchedValueType + DartType matchedValueType = analysisResult.matchedValueType .unwrapTypeView(); assert( @@ -15934,50 +16041,62 @@ class InferenceVisitorImpl extends InferenceVisitorBase analysisResult.patternTypeMismatchInIrrefutableContextError ?? analysisResult.duplicateRecordPatternFieldErrors?.values.first; if (error != null) { - replacement = new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement = extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } - RecordType requiredType = node.requiredType = - analysisResult.requiredType as RecordType; + RecordType requiredType = analysisResult.requiredType as RecordType; // TODO(johnniwinther): How does `recordType` relate to `node.recordType`? - node.needsCheck = _needsCheck( + bool needsCheck = _needsCheck( matchedType: matchedValueType, requiredType: requiredType, ); - if (node.needsCheck) { - node.lookupType = requiredType; + RecordType lookupType; + if (needsCheck) { + lookupType = requiredType; } else { DartType resolvedType = matchedValueType.nonTypeParameterBound; if (resolvedType is RecordType) { - node.lookupType = resolvedType; + lookupType = resolvedType; } else { - // Coverage-ignore-block(suite): Not run. // In case of the matched type being an invalid type we use the // required type instead. - node.lookupType = requiredType; + lookupType = requiredType; } } + List patterns = new List.filled( + node.patterns.length, + dummyPattern, + ); for (int i = node.patterns.length - 1; i >= 0; i--) { - Pattern subPattern = node.patterns[i]; + InternalPattern subPattern = node.patterns[i]; Object? rewrite = popRewrite(); - if (subPattern is NamedPattern) { - if (!identical(rewrite, subPattern.pattern)) { - // Coverage-ignore-block(suite): Not run. - subPattern.pattern = (rewrite as Pattern)..parent = subPattern; - } + if (subPattern is InternalNamedPattern) { + patterns[i] = extern.createNamedPattern( + name: subPattern.name, + pattern: rewrite as Pattern, + fileOffset: subPattern.fileOffset, + ); } else { - if (!identical(rewrite, subPattern)) { - node.patterns[i] = (rewrite as Pattern)..parent = node; - } + patterns[i] = rewrite as Pattern; } } - pushRewrite(replacement ?? node); + pushRewrite( + replacement ?? + extern.createRecordPattern( + patterns: patterns, + requiredType: requiredType, + matchedValueType: matchedValueType, + needsCheck: needsCheck, + lookupType: lookupType, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; @@ -16027,9 +16146,8 @@ class InferenceVisitorImpl extends InferenceVisitorBase ); } - @override - PatternResult visitAssignedVariablePattern( - AssignedVariablePattern node, + PatternResult visitInternalAssignedVariablePattern( + InternalAssignedVariablePattern node, SharedMatchContext context, ) { int? stackBase; @@ -16037,7 +16155,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase // TODO(johnniwinther): Share this through the type analyzer. Pattern? replacement; - InternalVariable variable = node.variable as InternalVariable; + InternalVariable variable = node.variable; bool isDefinitelyAssigned = flowAnalysis.isAssigned(variable.astVariable); bool isDefinitelyUnassigned = flowAnalysis.isUnassigned( variable.astVariable, @@ -16045,75 +16163,87 @@ class InferenceVisitorImpl extends InferenceVisitorBase if ((variable.isLate && variable.isFinal) || variable.isLateFinalWithoutInitializer) { if (isDefinitelyAssigned) { - replacement = new InvalidPattern( - problemReporting.buildProblem( + replacement = extern.createInvalidPattern( + error: problemReporting.buildProblem( compilerContext: compilerContext, message: diag.lateDefinitelyAssignedError.withArguments( - variableName: node.variable.name!, + variableName: node.variableName, ), fileUri: fileUri, fileOffset: node.fileOffset, - length: node.variable.name!.length, + length: node.variableName.length, ), - declaredVariables: node.declaredVariables, - )..fileOffset = node.fileOffset; + declaredVariables: node.internalDeclaredVariables, + ); } } else if (variable.isStaticLate) { if (!isDefinitelyUnassigned) { - replacement = new InvalidPattern( - problemReporting.buildProblem( + replacement = extern.createInvalidPattern( + error: problemReporting.buildProblem( compilerContext: compilerContext, message: diag.finalPossiblyAssignedError.withArguments( - variableName: node.variable.name!, + variableName: node.variableName, ), fileUri: fileUri, fileOffset: node.fileOffset, - length: node.variable.name!.length, + length: node.variableName.length, ), - declaredVariables: node.declaredVariables, - )..fileOffset = node.fileOffset; + declaredVariables: node.internalDeclaredVariables, + ); } } else if (variable.isFinal && // Coverage-ignore(suite): Not run. variable.hasDeclaredInitializer) { // Coverage-ignore-block(suite): Not run. - replacement = new InvalidPattern( - problemReporting.buildProblem( + replacement = extern.createInvalidPattern( + error: problemReporting.buildProblem( compilerContext: compilerContext, message: diag.cannotAssignToFinalVariable.withArguments( - variableName: node.variable.name!, + variableName: node.variableName, ), fileUri: fileUri, fileOffset: node.fileOffset, - length: node.variable.name!.length, + length: node.variableName.length, ), - declaredVariables: node.declaredVariables, - )..fileOffset = node.fileOffset; + declaredVariables: node.internalDeclaredVariables, + ); } AssignedVariablePatternResult analysisResult = - analyzeAssignedVariablePattern(context, node, node.variable); + analyzeAssignedVariablePattern( + context, + node, + node.variable.astVariable, + ); - DartType matchedValueType = node.matchedValueType = analysisResult - .matchedValueType + DartType matchedValueType = analysisResult.matchedValueType .unwrapTypeView(); - node.needsCast = _needsCast( + bool needsCast = _needsCast( matchedType: matchedValueType, requiredType: node.variable.type, ); - node.hasObservableEffect = _inTryOrLocalFunction; + bool hasObservableEffect = _inTryOrLocalFunction; InvalidExpression? error = analysisResult.duplicateAssignmentPatternVariableError ?? analysisResult.patternTypeMismatchInIrrefutableContextError; if (error != null) { - replacement ??= new InvalidPattern( - error, - declaredVariables: node.declaredVariables, - )..fileOffset = error.fileOffset; + replacement ??= extern.createInvalidPattern( + error: error, + declaredVariables: node.internalDeclaredVariables, + ); } - pushRewrite(replacement ?? node); + pushRewrite( + replacement ?? + extern.createAssignedVariablePattern( + variable: node.variable.astVariable, + matchedValueType: matchedValueType, + needsCast: needsCast, + hasObservableEffect: hasObservableEffect, + fileOffset: node.fileOffset, + ), + ); assert(checkStack(node, stackBase, [/* pattern = */ ValueKinds.Pattern])); return analysisResult; @@ -16160,7 +16290,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase @override SharedTypeView downwardInferObjectPatternRequiredType({ required SharedTypeView matchedType, - required covariant ObjectPatternInternal pattern, + required covariant InternalObjectPattern pattern, }) { DartType requiredType = pattern.requiredType; if (!pattern.hasExplicitTypeArguments) { @@ -16339,22 +16469,23 @@ class InferenceVisitorImpl extends InferenceVisitorBase @override bool isRestPatternElement(Node node) { - return node is RestPattern || node is MapPatternRestEntry; + return node is InternalRestPattern || node is InternalMapPatternRestEntry; } @override Pattern? getRestPatternElementPattern(TreeNode node) { - if (node is MapPatternRestEntry) { + if (node is InternalMapPatternRestEntry) { return null; } else { - return (node as RestPattern).subPattern; + return (node as InternalRestPattern).subPattern; } } @override void handleListPatternRestElement(Pattern container, TreeNode restElement) { - RestPattern restPattern = restElement as RestPattern; + InternalRestPattern restPattern = restElement as InternalRestPattern; int? stackBase; + Pattern? subPattern; if (restPattern.subPattern != null) { assert(checkStackBase(restPattern, stackBase = stackHeight - 1)); @@ -16364,18 +16495,19 @@ class InferenceVisitorImpl extends InferenceVisitorBase ]), ); - Object? rewrite = popRewrite(); - if (!identical(rewrite, restPattern.subPattern)) { - // Coverage-ignore-block(suite): Not run. - restPattern.subPattern = (rewrite as Pattern)..parent = restPattern; - } + subPattern = popRewrite() as Pattern; } else { assert(checkStackBase(restPattern, stackBase = stackHeight)); } assert(checkStack(restPattern, stackBase, [/*empty*/])); - pushRewrite(restElement); + pushRewrite( + extern.createRestPattern( + subPattern: subPattern, + fileOffset: restPattern.fileOffset, + ), + ); assert( checkStack(restPattern, stackBase, [ @@ -16386,15 +16518,17 @@ class InferenceVisitorImpl extends InferenceVisitorBase @override void handleMapPatternRestElement(Pattern container, TreeNode restElement) { - pushRewrite(restElement); + pushRewrite( + extern.createMapPatternRestEntry(fileOffset: container.fileOffset), + ); } @override shared.MapPatternEntry? getMapPatternEntry( TreeNode element, ) { - element as MapPatternEntry; - if (element is MapPatternRestEntry) { + element as InternalMapPatternEntry; + if (element is InternalMapPatternRestEntry) { return null; } else { return new shared.MapPatternEntry( @@ -16407,32 +16541,33 @@ class InferenceVisitorImpl extends InferenceVisitorBase @override void handleMapPatternEntry( Pattern container, - covariant MapPatternEntry entryElement, + covariant InternalMapPatternEntry entryElement, SharedTypeView keyType, ) { + Pattern value = popRewrite() as Pattern; + Expression key = entryElement.key; Object? rewrite = popRewrite(); - if (!identical(rewrite, entryElement.value)) { - // Coverage-ignore-block(suite): Not run. - entryElement.value = rewrite as Pattern..parent = entryElement; - } - - rewrite = popRewrite(); if (!identical(rewrite, entryElement.key)) { - entryElement.key = (rewrite as Expression)..parent = entryElement; + key = rewrite as Expression; } - entryElement.keyType = keyType.unwrapTypeView(); - - pushRewrite(entryElement); + pushRewrite( + extern.createMapPatternEntry( + key: key, + keyType: keyType.unwrapTypeView(), + value: value, + fileOffset: entryElement.fileOffset, + ), + ); } @override RelationalOperatorResolution? resolveRelationalPatternOperator( - covariant RelationalPattern node, + covariant InternalRelationalPattern node, SharedTypeView matchedValueType, ) { // TODO(johnniwinther): Reuse computed values between here and - // visitRelationalPattern. + // visitInternalRelationalPattern. Name operatorName; RelationalOperatorKind kind = RelationalOperatorKind.other; switch (node.kind) { @@ -16496,15 +16631,6 @@ class InferenceVisitorImpl extends InferenceVisitorBase return _unhandledInitializer(node); } - @override - // Coverage-ignore(suite): Not run. - PatternResult visitAuxiliaryPattern( - AuxiliaryPattern node, - SharedMatchContext context, - ) { - return _unhandledPattern(node); - } - @override // Coverage-ignore(suite): Not run. StatementInferenceResult visitAuxiliaryStatement(AuxiliaryStatement node) { diff --git a/pkg/front_end/lib/src/type_inference/shared_type_analyzer.dart b/pkg/front_end/lib/src/type_inference/shared_type_analyzer.dart index 0b36de6e755..8c02ab93251 100644 --- a/pkg/front_end/lib/src/type_inference/shared_type_analyzer.dart +++ b/pkg/front_end/lib/src/type_inference/shared_type_analyzer.dart @@ -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, }) {