blob: f53070a7ab40c8c9e51a8e813b9dfd25b4230512 [file] [log] [blame] [edit]
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of '../../ast.dart';
// ------------------------------------------------------------------------
// CONSTANTS
// ------------------------------------------------------------------------
sealed class Constant extends Node {
/// Calls the `visit*ConstantReference()` method on visitor [v] for all
/// constants referenced in this constant.
///
/// (Note that a constant can be seen as a DAG (directed acyclic graph) and
/// not a tree!)
@override
void visitChildren(Visitor v);
/// Calls the `visit*Constant()` method on the visitor [v].
@override
R accept<R>(ConstantVisitor<R> v);
/// Calls the `visit*Constant()` method on the visitor [v].
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg);
/// Calls the `visit*ConstantReference()` method on the visitor [v].
R acceptReference<R>(ConstantReferenceVisitor<R> v);
/// Calls the `visit*ConstantReference()` method on the visitor [v].
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg);
/// The Kernel AST will reference [Constant]s via [ConstantExpression]s. The
/// constants are not required to be canonicalized, but they have to be deeply
/// comparable via hashCode/==!
@override
int get hashCode;
@override
bool operator ==(Object other);
@override
String toString() => throw '$runtimeType';
/// Returns a textual representation of the this constant.
///
/// If [verbose] is `true`, qualified names will include the library name/uri.
@override
String toText(AstTextStrategy strategy) {
AstPrinter printer = new AstPrinter(strategy);
printer.writeConstant(this);
return printer.getText();
}
@override
void toTextInternal(AstPrinter printer);
/// Gets the type of this constant.
DartType getType(StaticTypeContext context);
}
abstract class AuxiliaryConstant extends Constant {
@override
R accept<R>(ConstantVisitor<R> v) => v.visitAuxiliaryConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitAuxiliaryConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitAuxiliaryConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitAuxiliaryConstantReference(this, arg);
}
sealed class PrimitiveConstant<T> extends Constant {
final T value;
PrimitiveConstant(this.value);
@override
int get hashCode => value.hashCode;
@override
bool operator ==(Object other) =>
other is PrimitiveConstant<T> && other.value == value;
@override
void toTextInternal(AstPrinter printer) {
printer.write('$value');
}
}
class NullConstant extends PrimitiveConstant<Null> {
NullConstant() : super(null);
@override
void visitChildren(Visitor v) {}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitNullConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitNullConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitNullConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitNullConstantReference(this, arg);
@override
DartType getType(StaticTypeContext context) => const NullType();
@override
String toString() => 'NullConstant(${toStringInternal()})';
}
class BoolConstant extends PrimitiveConstant<bool> {
BoolConstant(bool value) : super(value);
@override
void visitChildren(Visitor v) {}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitBoolConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitBoolConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitBoolConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitBoolConstantReference(this, arg);
@override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
@override
String toString() => 'BoolConstant(${toStringInternal()})';
}
/// An integer constant on a non-JS target.
class IntConstant extends PrimitiveConstant<int> {
IntConstant(int value) : super(value);
@override
void visitChildren(Visitor v) {}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitIntConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitIntConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitIntConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitIntConstantReference(this, arg);
@override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.intRawType(context.nonNullable);
@override
String toString() => 'IntConstant(${toStringInternal()})';
}
/// A double constant on a non-JS target or any numeric constant on a JS target.
class DoubleConstant extends PrimitiveConstant<double> {
DoubleConstant(double value) : super(value);
@override
void visitChildren(Visitor v) {}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitDoubleConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitDoubleConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitDoubleConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitDoubleConstantReference(this, arg);
@override
int get hashCode => value.isNaN ? 199 : super.hashCode;
@override
bool operator ==(Object other) =>
other is DoubleConstant && identical(value, other.value);
@override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.doubleRawType(context.nonNullable);
@override
String toString() => 'DoubleConstant(${toStringInternal()})';
}
class StringConstant extends PrimitiveConstant<String> {
StringConstant(String value) : super(value);
@override
void visitChildren(Visitor v) {}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitStringConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitStringConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitStringConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitStringConstantReference(this, arg);
@override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.stringRawType(context.nonNullable);
@override
void toTextInternal(AstPrinter printer) {
printer.write('"');
printer.write(escapeString(value));
printer.write('"');
}
@override
String toString() => 'StringConstant(${toStringInternal()})';
}
class SymbolConstant extends Constant {
final String name;
final Reference? libraryReference;
SymbolConstant(this.name, this.libraryReference);
@override
void visitChildren(Visitor v) {}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitSymbolConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitSymbolConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitSymbolConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitSymbolConstantReference(this, arg);
@override
String toString() => 'SymbolConstant(${toStringInternal()})';
@override
int get hashCode => _Hash.hash2(name, libraryReference);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is SymbolConstant &&
other.name == name &&
other.libraryReference == libraryReference);
@override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.symbolRawType(context.nonNullable);
@override
void toTextInternal(AstPrinter printer) {
printer.write('#');
if (printer.includeAuxiliaryProperties && libraryReference != null) {
printer.write(libraryNameToString(libraryReference!.asLibrary));
printer.write('::');
}
printer.write(name);
}
}
class MapConstant extends Constant {
final DartType keyType;
final DartType valueType;
final List<ConstantMapEntry> entries;
MapConstant(this.keyType, this.valueType, this.entries);
@override
void visitChildren(Visitor v) {
keyType.accept(v);
valueType.accept(v);
for (final ConstantMapEntry entry in entries) {
entry.key.acceptReference(v);
entry.value.acceptReference(v);
}
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitMapConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitMapConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitMapConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitMapConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.write('const <');
printer.writeType(keyType);
printer.write(', ');
printer.writeType(valueType);
printer.write('>{');
for (int i = 0; i < entries.length; i++) {
if (i > 0) {
printer.write(', ');
}
printer.writeConstantMapEntry(entries[i]);
}
printer.write('}');
}
@override
String toString() => 'MapConstant(${toStringInternal()})';
@override
late final int hashCode = _Hash.combine2Finish(
keyType.hashCode, valueType.hashCode, _Hash.combineListHash(entries));
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is MapConstant &&
other.keyType == keyType &&
other.valueType == valueType &&
listEquals(other.entries, entries));
@override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.mapType(keyType, valueType, context.nonNullable);
}
class ConstantMapEntry {
final Constant key;
final Constant value;
ConstantMapEntry(this.key, this.value);
@override
String toString() => 'ConstantMapEntry(${toStringInternal()})';
@override
int get hashCode => _Hash.hash2(key, value);
@override
bool operator ==(Object other) =>
other is ConstantMapEntry && other.key == key && other.value == value;
String toStringInternal() => toText(defaultAstTextStrategy);
String toText(AstTextStrategy strategy) {
AstPrinter printer = new AstPrinter(strategy);
printer.writeConstantMapEntry(this);
return printer.getText();
}
void toTextInternal(AstPrinter printer) {
printer.writeConstant(key);
printer.write(': ');
printer.writeConstant(value);
}
}
class ListConstant extends Constant {
final DartType typeArgument;
final List<Constant> entries;
ListConstant(this.typeArgument, this.entries);
@override
void visitChildren(Visitor v) {
typeArgument.accept(v);
for (final Constant constant in entries) {
constant.acceptReference(v);
}
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitListConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitListConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitListConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitListConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.write('const <');
printer.writeType(typeArgument);
printer.write('>[');
for (int i = 0; i < entries.length; i++) {
if (i > 0) {
printer.write(', ');
}
printer.writeConstant(entries[i]);
}
printer.write(']');
}
@override
String toString() => 'ListConstant(${toStringInternal()})';
@override
late final int hashCode = _Hash.combineFinish(
typeArgument.hashCode, _Hash.combineListHash(entries));
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is ListConstant &&
other.typeArgument == typeArgument &&
listEquals(other.entries, entries));
@override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.listType(typeArgument, context.nonNullable);
}
class SetConstant extends Constant {
final DartType typeArgument;
final List<Constant> entries;
SetConstant(this.typeArgument, this.entries);
@override
void visitChildren(Visitor v) {
typeArgument.accept(v);
for (final Constant constant in entries) {
constant.acceptReference(v);
}
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitSetConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitSetConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitSetConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitSetConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.write('const <');
printer.writeType(typeArgument);
printer.write('>{');
for (int i = 0; i < entries.length; i++) {
if (i > 0) {
printer.write(', ');
}
printer.writeConstant(entries[i]);
}
printer.write('}');
}
@override
String toString() => 'SetConstant(${toStringInternal()})';
@override
late final int hashCode = _Hash.combineFinish(
typeArgument.hashCode, _Hash.combineListHash(entries));
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is SetConstant &&
other.typeArgument == typeArgument &&
listEquals(other.entries, entries));
@override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.setType(typeArgument, context.nonNullable);
}
class RecordConstant extends Constant {
/// Positional field values.
final List<Constant> positional;
/// Named field values, sorted by name.
final Map<String, Constant> named;
/// The runtime type of the constant.
///
/// [recordType] is computed from the individual types of the record fields
/// and reflects runtime type of the record constant, as opposed to the
/// static type of the expression that defined the constant.
///
/// The following program shows the distinction between the static and the
/// runtime types of the constant. The static type of the first record in the
/// invocation of `identical` is `(E, String)`, the static type of the second
/// — `(int, String)`. The runtime type of both constants is `(int, String)`,
/// and the assertion condition should be satisfied.
///
/// extension type const E(Object? it) {}
///
/// main() {
/// const bool check = identical(const (E(1), "foo"), const (1, "foo"));
/// assert(check);
/// }
final RecordType recordType;
RecordConstant(this.positional, this.named, this.recordType)
: assert(positional.length == recordType.positional.length &&
named.length == recordType.named.length &&
recordType.named
.map((f) => f.name)
.toSet()
.containsAll(named.keys)),
assert(() {
// Assert that the named fields are sorted.
String? previous;
for (String name in named.keys) {
if (previous != null && name.compareTo(previous) < 0) {
return false;
}
previous = name;
}
return true;
}(),
"Named fields of a RecordConstant aren't sorted lexicographically: "
"${named.keys.join(", ")}");
RecordConstant.fromTypeContext(
this.positional, this.named, StaticTypeContext staticTypeContext)
: recordType = new RecordType([
for (Constant constant in positional)
constant.getType(staticTypeContext)
], [
for (var MapEntry(key: name, value: constant) in named.entries)
new NamedType(name, constant.getType(staticTypeContext))
], staticTypeContext.nonNullable);
@override
void visitChildren(Visitor v) {
recordType.accept(v);
for (final Constant entry in positional) {
entry.acceptReference(v);
}
for (final Constant entry in named.values) {
entry.acceptReference(v);
}
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitRecordConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitRecordConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitRecordConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitRecordConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.write("const (");
String comma = '';
for (Constant entry in positional) {
printer.write(comma);
printer.writeConstant(entry);
comma = ', ';
}
if (named.isNotEmpty) {
printer.write(comma);
comma = '';
printer.write("{");
for (MapEntry<String, Constant> entry in named.entries) {
printer.write(comma);
printer.write(entry.key);
printer.write(": ");
printer.writeConstant(entry.value);
comma = ', ';
}
printer.write("}");
}
printer.write(")");
}
@override
String toString() => "RecordConstant(${toStringInternal()})";
@override
late final int hashCode =
_Hash.combineMapHashUnordered(named, _Hash.combineListHash(positional));
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is RecordConstant &&
listEquals(other.positional, positional) &&
mapEquals(other.named, named));
@override
DartType getType(StaticTypeContext context) => recordType;
}
class InstanceConstant extends Constant {
final Reference classReference;
final List<DartType> typeArguments;
final Map<Reference, Constant> fieldValues;
InstanceConstant(this.classReference, this.typeArguments, this.fieldValues);
Class get classNode => classReference.asClass;
@override
void visitChildren(Visitor v) {
classReference.asClass.acceptReference(v);
visitList(typeArguments, v);
for (final Reference reference in fieldValues.keys) {
reference.asField.acceptReference(v);
}
for (final Constant constant in fieldValues.values) {
constant.acceptReference(v);
}
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitInstanceConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitInstanceConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitInstanceConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitInstanceConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.write('const ');
printer.writeClassName(classReference);
printer.writeTypeArguments(typeArguments);
printer.write('{');
String comma = '';
fieldValues.forEach((Reference fieldRef, Constant constant) {
printer.write(comma);
printer.writeMemberName(fieldRef);
printer.write(': ');
printer.writeConstant(constant);
comma = ', ';
});
printer.write('}');
}
@override
String toString() => 'InstanceConstant(${toStringInternal()})';
@override
late final int hashCode = _Hash.combine2Finish(classReference.hashCode,
listHashCode(typeArguments), _Hash.combineMapHashUnordered(fieldValues));
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other is InstanceConstant &&
other.classReference == classReference &&
listEquals(other.typeArguments, typeArguments) &&
mapEquals(other.fieldValues, fieldValues));
}
@override
DartType getType(StaticTypeContext context) =>
new InterfaceType(classNode, context.nonNullable, typeArguments);
}
class InstantiationConstant extends Constant {
final Constant tearOffConstant;
final List<DartType> types;
InstantiationConstant(this.tearOffConstant, this.types);
@override
void visitChildren(Visitor v) {
tearOffConstant.acceptReference(v);
visitList(types, v);
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitInstantiationConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitInstantiationConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitInstantiationConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitInstantiationConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.writeConstant(tearOffConstant);
printer.writeTypeArguments(types);
}
@override
String toString() => 'InstantiationConstant(${toStringInternal()})';
@override
int get hashCode => _Hash.combineFinish(
tearOffConstant.hashCode, _Hash.combineListHash(types));
@override
bool operator ==(Object other) {
return other is InstantiationConstant &&
other.tearOffConstant == tearOffConstant &&
listEquals(other.types, types);
}
@override
DartType getType(StaticTypeContext context) {
final FunctionType type = tearOffConstant.getType(context) as FunctionType;
return FunctionTypeInstantiator.instantiate(type, types);
}
}
abstract class TearOffConstant implements Constant {
Reference get targetReference;
Member get target;
FunctionNode get function;
}
class StaticTearOffConstant extends Constant implements TearOffConstant {
@override
final Reference targetReference;
StaticTearOffConstant(Procedure target)
: assert(target.isStatic),
assert(target.kind == ProcedureKind.Method,
"Unexpected static tear off target: $target"),
targetReference = target.reference;
StaticTearOffConstant.byReference(this.targetReference);
@override
Procedure get target => targetReference.asProcedure;
@override
FunctionNode get function => target.function;
@override
void visitChildren(Visitor v) {
target.acceptReference(v);
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitStaticTearOffConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitStaticTearOffConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitStaticTearOffConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitStaticTearOffConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.writeMemberName(targetReference);
}
@override
String toString() => 'StaticTearOffConstant(${toStringInternal()})';
@override
int get hashCode => targetReference.hashCode;
@override
bool operator ==(Object other) {
return other is StaticTearOffConstant &&
other.targetReference == targetReference;
}
@override
FunctionType getType(StaticTypeContext context) {
return target.function.computeFunctionType(context.nonNullable);
}
}
class ConstructorTearOffConstant extends Constant implements TearOffConstant {
@override
final Reference targetReference;
ConstructorTearOffConstant(Member target)
: assert(
target is Constructor || (target is Procedure && target.isFactory),
"Unexpected constructor tear off target: $target"),
this.targetReference = getNonNullableMemberReferenceGetter(target);
ConstructorTearOffConstant.byReference(this.targetReference);
@override
Member get target => targetReference.asMember;
@override
FunctionNode get function => target.function!;
@override
void visitChildren(Visitor v) {
target.acceptReference(v);
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitConstructorTearOffConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitConstructorTearOffConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitConstructorTearOffConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitConstructorTearOffConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.writeMemberName(targetReference);
}
@override
String toString() => 'ConstructorTearOffConstant(${toStringInternal()})';
@override
int get hashCode => targetReference.hashCode;
@override
bool operator ==(Object other) {
return other is ConstructorTearOffConstant &&
other.targetReference == targetReference;
}
@override
FunctionType getType(StaticTypeContext context) {
return function.computeFunctionType(context.nonNullable);
}
}
class RedirectingFactoryTearOffConstant extends Constant
implements TearOffConstant {
@override
final Reference targetReference;
RedirectingFactoryTearOffConstant(Procedure target)
: assert(target.isRedirectingFactory),
this.targetReference = getNonNullableMemberReferenceGetter(target);
RedirectingFactoryTearOffConstant.byReference(this.targetReference);
@override
Procedure get target => targetReference.asProcedure;
@override
FunctionNode get function => target.function;
@override
void visitChildren(Visitor v) {
target.acceptReference(v);
}
@override
R accept<R>(ConstantVisitor<R> v) =>
v.visitRedirectingFactoryTearOffConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitRedirectingFactoryTearOffConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitRedirectingFactoryTearOffConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitRedirectingFactoryTearOffConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.writeMemberName(targetReference);
}
@override
String toString() =>
'RedirectingFactoryTearOffConstant(${toStringInternal()})';
@override
int get hashCode => targetReference.hashCode;
@override
bool operator ==(Object other) {
return other is RedirectingFactoryTearOffConstant &&
other.targetReference == targetReference;
}
@override
FunctionType getType(StaticTypeContext context) {
return function.computeFunctionType(context.nonNullable);
}
}
class TypedefTearOffConstant extends Constant {
final List<StructuralParameter> parameters;
final TearOffConstant tearOffConstant;
final List<DartType> types;
@override
late final int hashCode = _computeHashCode();
TypedefTearOffConstant(this.parameters, this.tearOffConstant, this.types);
@override
void visitChildren(Visitor v) {
visitList(parameters, v);
tearOffConstant.acceptReference(v);
visitList(types, v);
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitTypedefTearOffConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitTypedefTearOffConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitTypedefTearOffConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitTypedefTearOffConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.writeStructuralParameters(parameters);
printer.writeConstant(tearOffConstant);
printer.writeTypeArguments(types);
}
@override
String toString() => 'TypedefTearOffConstant(${toStringInternal()})';
@override
bool operator ==(Object other) {
if (other is! TypedefTearOffConstant) return false;
if (other.tearOffConstant != tearOffConstant) return false;
if (other.parameters.length != parameters.length) return false;
if (parameters.isNotEmpty) {
Assumptions assumptions = new Assumptions();
for (int index = 0; index < parameters.length; index++) {
assumptions.assumeStructuralParameter(
parameters[index], other.parameters[index]);
}
for (int index = 0; index < parameters.length; index++) {
if (!parameters[index]
.bound
.equals(other.parameters[index].bound, assumptions)) {
return false;
}
}
for (int i = 0; i < types.length; ++i) {
if (!types[i].equals(other.types[i], assumptions)) {
return false;
}
}
}
return true;
}
int _computeHashCode() {
int hash = 1237;
for (int i = 0; i < parameters.length; ++i) {
StructuralParameter parameter = parameters[i];
hash = 0x3fffffff & (hash * 31 + parameter.bound.hashCode);
}
for (int i = 0; i < types.length; ++i) {
hash = 0x3fffffff & (hash * 31 + types[i].hashCode);
}
hash = 0x3fffffff & (hash * 31 + tearOffConstant.hashCode);
return hash;
}
@override
DartType getType(StaticTypeContext context) {
FunctionType type = tearOffConstant.getType(context) as FunctionType;
FreshStructuralParameters freshStructuralParameters =
getFreshStructuralParameters(parameters);
type = freshStructuralParameters.substitute(
FunctionTypeInstantiator.instantiate(type, types)) as FunctionType;
return new FunctionType(
type.positionalParameters, type.returnType, type.declaredNullability,
namedParameters: type.namedParameters,
typeParameters: freshStructuralParameters.freshTypeParameters,
requiredParameterCount: type.requiredParameterCount);
}
}
class TypeLiteralConstant extends Constant {
final DartType type;
TypeLiteralConstant(this.type);
@override
void visitChildren(Visitor v) {
type.accept(v);
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitTypeLiteralConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitTypeLiteralConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitTypeLiteralConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitTypeLiteralConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
printer.writeType(type);
}
@override
String toString() => 'TypeLiteralConstant(${toStringInternal()})';
@override
int get hashCode => type.hashCode;
@override
bool operator ==(Object other) {
return other is TypeLiteralConstant && other.type == type;
}
@override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.typeRawType(context.nonNullable);
}
class UnevaluatedConstant extends Constant {
final Expression expression;
UnevaluatedConstant(this.expression) {
expression.parent = null;
}
@override
void visitChildren(Visitor v) {
expression.accept(v);
}
@override
R accept<R>(ConstantVisitor<R> v) => v.visitUnevaluatedConstant(this);
@override
R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
v.visitUnevaluatedConstant(this, arg);
@override
R acceptReference<R>(ConstantReferenceVisitor<R> v) =>
v.visitUnevaluatedConstantReference(this);
@override
R acceptReference1<R, A>(ConstantReferenceVisitor1<R, A> v, A arg) =>
v.visitUnevaluatedConstantReference(this, arg);
@override
DartType getType(StaticTypeContext context) =>
expression.getStaticType(context);
@override
void toTextInternal(AstPrinter printer) {
printer.write('unevaluated{');
printer.writeExpression(expression);
printer.write('}');
}
@override
String toString() {
return "UnevaluatedConstant(${toStringInternal()})";
}
@override
int get hashCode => expression.hashCode;
@override
bool operator ==(Object other) {
return other is UnevaluatedConstant && other.expression == expression;
}
}