[cfe][InternalNodes] Add AuxiliaryPattern

This allows for creating internal pattern nodes in the CFE.

Change-Id: Ifad3c29eb7dd329ecd902c7b43fcff58ad862bcc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/508000
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
This commit is contained in:
Johnni Winther
2026-06-01 05:17:24 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent a185d6355b
commit 5059d9e842
8 changed files with 97 additions and 191 deletions
@@ -926,6 +926,16 @@ class InferenceVisitorImpl extends InferenceVisitorBase
);
}
// Coverage-ignore(suite): Not run.
Never _unhandledPattern(Pattern node) {
problems.unhandled(
"${node.runtimeType}",
"InferenceVisitor",
node.fileOffset,
node.location!.file,
);
}
@override
InitializerInferenceResult visitInvalidInitializer(InvalidInitializer node) {
return new SuccessfulInitializerInferenceResult(node);
@@ -16486,6 +16496,15 @@ 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) {
@@ -938,4 +938,14 @@ class MatchingExpressionVisitor
return new BooleanExpression(true, fileOffset: node.fileOffset);
}
}
@override
DelayedExpression visitAuxiliaryPattern(
AuxiliaryPattern node,
CacheableExpression matchedExpression,
) {
throw new UnsupportedError(
"Unexpected pattern $node (${node.runtimeType}).",
);
}
}
+7
View File
@@ -3188,6 +3188,13 @@ class BinaryPrinter
);
}
@override
void visitAuxiliaryPattern(AuxiliaryPattern node) {
throw new UnsupportedError(
'serialization of auxiliary Pattern: ${node} (${node.runtimeType})',
);
}
@override
void visitBoolConstant(BoolConstant node) {
throw new UnsupportedError('serialization of BoolConstants');
+7
View File
@@ -1374,6 +1374,13 @@ class CloneVisitorNotMembers
"Unsupported auxiliary initializer ${node} (${node.runtimeType}).",
);
}
@override
TreeNode visitAuxiliaryPattern(AuxiliaryPattern node) {
throw new UnsupportedError(
"Unsupported auxiliary pattern ${node} (${node.runtimeType}).",
);
}
}
/// Visitor that return a clone of a tree, maintaining references to cloned
+11
View File
@@ -1485,6 +1485,17 @@ class InvalidPattern extends Pattern {
}
}
/// Abstract subclass of [Pattern] that can be used to add [Pattern]
/// subclasses from outside `package:kernel`.
abstract class AuxiliaryPattern extends Pattern {
@override
R accept<R>(PatternVisitor<R> v) => v.visitAuxiliaryPattern(this);
@override
R accept1<R, A>(PatternVisitor1<R, A> v, A arg) =>
v.visitAuxiliaryPattern(this, arg);
}
class MapPatternEntry extends TreeNode {
Expression key;
Pattern value;
+7
View File
@@ -792,6 +792,13 @@ class CoverageVisitor implements Visitor<void> {
node.visitChildren(this);
}
@override
void visitAuxiliaryPattern(AuxiliaryPattern node) {
throw new UnsupportedError(
"Unsupported auxiliary node $node (${node.runtimeType}).",
);
}
@override
void visitMapPatternEntry(MapPatternEntry node) {
visited.add(NodeKind.MapPatternEntry);
+30
View File
@@ -699,6 +699,11 @@ class EquivalenceVisitor implements Visitor1<bool, Node> {
return strategy.checkInvalidPattern(this, node, other);
}
@override
bool visitAuxiliaryPattern(AuxiliaryPattern node, Node other) {
return strategy.checkAuxiliaryPattern(this, node, other);
}
@override
bool visitMapPatternEntry(MapPatternEntry node, Node other) {
return strategy.checkMapPatternEntry(this, node, other);
@@ -5214,6 +5219,23 @@ class EquivalenceStrategy {
return result;
}
bool checkAuxiliaryPattern(
EquivalenceVisitor visitor,
AuxiliaryPattern? node,
Object? other,
) {
if (identical(node, other)) return true;
if (node is! AuxiliaryPattern) return false;
if (other is! AuxiliaryPattern) return false;
visitor.pushNodeState(node, other);
bool result = true;
if (!checkAuxiliaryPattern_fileOffset(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
visitor.popState();
return result;
}
bool checkMapPatternEntry(
EquivalenceVisitor visitor,
MapPatternEntry? node,
@@ -12380,6 +12402,14 @@ class EquivalenceStrategy {
return checkPattern_fileOffset(visitor, node, other);
}
bool checkAuxiliaryPattern_fileOffset(
EquivalenceVisitor visitor,
AuxiliaryPattern node,
AuxiliaryPattern other,
) {
return checkPattern_fileOffset(visitor, node, other);
}
bool checkMapPatternEntry_key(
EquivalenceVisitor visitor,
MapPatternEntry node,
+6 -191
View File
@@ -262,6 +262,7 @@ abstract class PatternVisitor<R> {
R visitRestPattern(RestPattern node);
R visitVariablePattern(VariablePattern node);
R visitWildcardPattern(WildcardPattern node);
R visitAuxiliaryPattern(AuxiliaryPattern node);
}
/// Helper mixin for [PatternVisitor] that implements visit methods by
@@ -304,198 +305,8 @@ mixin PatternVisitorDefaultMixin<R> implements PatternVisitor<R> {
R visitVariablePattern(VariablePattern node) => defaultPattern(node);
@override
R visitWildcardPattern(WildcardPattern node) => defaultPattern(node);
}
/// [PatternVisitorInternalNodeMixin] is intended to reduce the effects of
/// CFE internal nodes on the backends.
///
/// The mixin provides implementations of the visit methods for the internal
/// nodes that are not expected to be part of AST delivered to backends. The
/// methods throw an exception signaling that the internal nodes aren't
/// supported.
mixin PatternVisitorInternalNodeMixin<R> implements PatternVisitor<R> {
@override
R visitAndPattern(AndPattern node) {
throw StateError("${runtimeType}.visitAndPattern isn't supported.");
}
@override
R visitAssignedVariablePattern(AssignedVariablePattern node) {
throw StateError(
"${runtimeType}.visitAssignedVariablePattern isn't supported.",
);
}
@override
R visitCastPattern(CastPattern node) {
throw StateError("${runtimeType}.visitCastPattern isn't supported.");
}
@override
R visitConstantPattern(ConstantPattern node) {
throw StateError("${runtimeType}.visitConstantPattern isn't supported.");
}
@override
R visitInvalidPattern(InvalidPattern node) {
throw StateError("${runtimeType}.visitInvalidPattern isn't supported.");
}
@override
R visitListPattern(ListPattern node) {
throw StateError("${runtimeType}.visitListPattern isn't supported.");
}
@override
R visitMapPattern(MapPattern node) {
throw StateError("${runtimeType}.visitMapPattern isn't supported.");
}
@override
R visitNamedPattern(NamedPattern node) {
throw StateError("${runtimeType}.visitNamedPattern isn't supported.");
}
@override
R visitNullAssertPattern(NullAssertPattern node) {
throw StateError("${runtimeType}.visitNullAssertPattern isn't supported.");
}
@override
R visitNullCheckPattern(NullCheckPattern node) {
throw StateError("${runtimeType}.visitNullCheckPattern isn't supported.");
}
@override
R visitObjectPattern(ObjectPattern node) {
throw StateError("${runtimeType}.visitObjectPattern isn't supported.");
}
@override
R visitOrPattern(OrPattern node) {
throw StateError("${runtimeType}.visitOrPattern isn't supported.");
}
@override
R visitRecordPattern(RecordPattern node) {
throw StateError("${runtimeType}.visitRecordPattern isn't supported.");
}
@override
R visitRelationalPattern(RelationalPattern node) {
throw StateError("${runtimeType}.visitRelationalPattern isn't supported.");
}
@override
R visitRestPattern(RestPattern node) {
throw StateError("${runtimeType}.visitRestPattern isn't supported.");
}
@override
R visitVariablePattern(VariablePattern node) {
throw StateError("${runtimeType}.visitVariablePattern isn't supported.");
}
@override
R visitWildcardPattern(WildcardPattern node) {
throw StateError("${runtimeType}.visitWildcardPattern isn't supported.");
}
}
/// [PatternVisitor1InternalNodeMixin] is intended to reduce the effects of
/// CFE internal nodes on the backends.
///
/// The mixin provides implementations of the visit methods for the internal
/// nodes that are not expected to be part of AST delivered to backends. The
/// methods throw an exception signaling that the internal nodes aren't
/// supported.
mixin PatternVisitor1InternalNodeMixin<R, A> implements PatternVisitor1<R, A> {
@override
R visitAndPattern(AndPattern node, A arg) {
throw StateError("${runtimeType}.visitAndPattern isn't supported.");
}
@override
R visitAssignedVariablePattern(AssignedVariablePattern node, A arg) {
throw StateError(
"${runtimeType}.visitAssignedVariablePattern isn't supported.",
);
}
@override
R visitCastPattern(CastPattern node, A arg) {
throw StateError("${runtimeType}.visitCastPattern isn't supported.");
}
@override
R visitConstantPattern(ConstantPattern node, A arg) {
throw StateError("${runtimeType}.visitConstantPattern isn't supported.");
}
@override
R visitInvalidPattern(InvalidPattern node, A arg) {
throw StateError("${runtimeType}.visitInvalidPattern isn't supported.");
}
@override
R visitListPattern(ListPattern node, A arg) {
throw StateError("${runtimeType}.visitListPattern isn't supported.");
}
@override
R visitMapPattern(MapPattern node, A arg) {
throw StateError("${runtimeType}.visitMapPattern isn't supported.");
}
@override
R visitNamedPattern(NamedPattern node, A arg) {
throw StateError("${runtimeType}.visitNamedPattern isn't supported.");
}
@override
R visitNullAssertPattern(NullAssertPattern node, A arg) {
throw StateError("${runtimeType}.visitNullAssertPattern isn't supported.");
}
@override
R visitNullCheckPattern(NullCheckPattern node, A arg) {
throw StateError("${runtimeType}.visitNullCheckPattern isn't supported.");
}
@override
R visitObjectPattern(ObjectPattern node, A arg) {
throw StateError("${runtimeType}.visitObjectPattern isn't supported.");
}
@override
R visitOrPattern(OrPattern node, A arg) {
throw StateError("${runtimeType}.visitOrPattern isn't supported.");
}
@override
R visitRecordPattern(RecordPattern node, A arg) {
throw StateError("${runtimeType}.visitRecordPattern isn't supported.");
}
@override
R visitRelationalPattern(RelationalPattern node, A arg) {
throw StateError("${runtimeType}.visitRelationalPattern isn't supported.");
}
@override
R visitRestPattern(RestPattern node, A arg) {
throw StateError("${runtimeType}.visitRestPattern isn't supported.");
}
@override
R visitVariablePattern(VariablePattern node, A arg) {
throw StateError("${runtimeType}.visitVariablePattern isn't supported.");
}
@override
R visitWildcardPattern(WildcardPattern node, A arg) {
throw StateError("${runtimeType}.visitWildcardPattern isn't supported.");
}
R visitAuxiliaryPattern(AuxiliaryPattern node) => defaultPattern(node);
}
abstract class StatementVisitor<R> {
@@ -2811,6 +2622,7 @@ abstract class PatternVisitor1<R, A> {
R visitRestPattern(RestPattern node, A arg);
R visitVariablePattern(VariablePattern node, A arg);
R visitWildcardPattern(WildcardPattern node, A arg);
R visitAuxiliaryPattern(AuxiliaryPattern node, A arg);
}
/// Helper mixin for [PatternVisitor1] that implements visit methods by
@@ -2859,6 +2671,9 @@ mixin PatternVisitor1DefaultMixin<R, A> implements PatternVisitor1<R, A> {
@override
R visitWildcardPattern(WildcardPattern node, A arg) =>
defaultPattern(node, arg);
@override
R visitAuxiliaryPattern(AuxiliaryPattern node, A arg) =>
defaultPattern(node, arg);
}
abstract class StatementVisitor1<R, A> {