Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Unified Diff: pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart

Issue 2996063002: Implement type arguments in redirecting factories.
Patch Set: Address Johnni's comments. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/front_end/lib/src/fasta/kernel/kernel_named_type_builder.dart ('k') | pkg/front_end/messages.yaml » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
diff --git a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
index 1fa7dd80fbc534085ebc48ef3453523d81fadbc0..205db064e47f64e17aa2d61affb4f1eef3d8050c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
@@ -6,46 +6,74 @@ library fasta.redirecting_factory_body;
import 'package:kernel/ast.dart'
show
+ DartType,
Expression,
ExpressionStatement,
FunctionNode,
+ InterfaceType,
InvalidExpression,
+ InvalidType,
Let,
Member,
Procedure,
StaticGet,
StringLiteral,
+ TypeParameterType,
VariableDeclaration;
+import 'package:kernel/type_algebra.dart' show Substitution;
+
const String letName = "#redirecting_factory";
class RedirectingFactoryBody extends ExpressionStatement {
- RedirectingFactoryBody.internal(Expression value)
- : super(new Let(new VariableDeclaration(letName, initializer: value),
+ Member cachedRedirectionTarget;
+
+ DartType cachedReturnType;
+
+ RedirectingFactoryBody.internal(Expression value, DartType type)
+ : super(new Let(
+ new VariableDeclaration(letName, initializer: value, type: type),
new InvalidExpression()));
- RedirectingFactoryBody(Member target) : this.internal(new StaticGet(target));
+ RedirectingFactoryBody(Member intermediateTarget, InterfaceType type)
+ : this.internal(new StaticGet(intermediateTarget), type);
RedirectingFactoryBody.unresolved(String name)
- : this.internal(new StringLiteral(name));
+ : this.internal(new StringLiteral(name), new InvalidType());
- Member get target {
- var value = getValue(expression);
+ Member get intermediateTarget {
+ var value = getVariable(expression)?.initializer;
return value is StaticGet ? value.target : null;
}
+ DartType get intermediateReturnType => getVariable(expression)?.type;
+
String get unresolvedName {
- var value = getValue(expression);
+ var value = getVariable(expression)?.initializer;
return value is StringLiteral ? value.value : null;
}
bool get isUnresolved => unresolvedName != null;
- static getValue(Expression expression) {
+ Member get target {
+ if (cachedReturnType == null) {
+ computeRedirectionTarget(this.parent.parent, this);
+ }
+ return cachedRedirectionTarget;
+ }
+
+ DartType get returnType {
+ if (cachedReturnType == null) {
+ computeRedirectionTarget(this.parent.parent, this);
+ }
+ return cachedReturnType;
+ }
+
+ static VariableDeclaration getVariable(Expression expression) {
if (expression is Let) {
VariableDeclaration variable = expression.variable;
if (variable.name == letName) {
- return variable.initializer;
+ return variable;
}
}
return null;
@@ -57,32 +85,73 @@ class RedirectingFactoryBody extends ExpressionStatement {
// [kernel_class_builder.dart](kernel_class_builder.dart).
FunctionNode function = factory.function;
ExpressionStatement statement = function.body;
+ VariableDeclaration variable = getVariable(statement.expression);
function.body =
- new RedirectingFactoryBody.internal(getValue(statement.expression))
+ new RedirectingFactoryBody.internal(variable.initializer, variable.type)
..parent = function;
}
-}
-RedirectingFactoryBody getRedirectingFactoryBody(Member member) {
- return member is Procedure && member.function.body is RedirectingFactoryBody
- ? member.function.body
- : null;
-}
+ static RedirectingFactoryBody getRedirectingFactoryBody(Member member) {
+ return member is Procedure && member.function.body is RedirectingFactoryBody
+ ? member.function.body
+ : null;
+ }
+
+ /// Iterate redirections from [factoryMethod].
+ static void iterateRedirections(
+ Member factoryMethod,
+ bool f(Member member, RedirectingFactoryBody body),
+ void onCycle(Member member, RedirectingFactoryBody body)) {
+ // We use the [tortoise and hare algorithm]
+ // (https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare) to
+ // handle cycles.
-Member getRedirectionTarget(Procedure member) {
- // We use the [tortoise and hare algorithm]
- // (https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare) to
- // handle cycles.
- Member tortoise = member;
- RedirectingFactoryBody tortoiseBody = getRedirectingFactoryBody(tortoise);
- Member hare = tortoiseBody?.target;
- RedirectingFactoryBody hareBody = getRedirectingFactoryBody(hare);
- while (tortoise != hare) {
- if (tortoiseBody?.isUnresolved ?? true) return tortoise;
- tortoise = tortoiseBody.target;
- tortoiseBody = getRedirectingFactoryBody(tortoise);
- hare = getRedirectingFactoryBody(hareBody?.target)?.target;
- hareBody = getRedirectingFactoryBody(hare);
+ Member tortoise = factoryMethod;
+ RedirectingFactoryBody tortoiseBody = getRedirectingFactoryBody(tortoise);
+ Member hare = tortoiseBody?.intermediateTarget;
+ RedirectingFactoryBody hareBody = getRedirectingFactoryBody(hare);
+ while (tortoise != hare) {
+ if (tortoiseBody == null) return;
+ if (!f(tortoise, tortoiseBody)) return;
+ tortoise = tortoiseBody.intermediateTarget;
+ tortoiseBody = getRedirectingFactoryBody(tortoise);
+ hare = getRedirectingFactoryBody(hareBody?.intermediateTarget)
+ ?.intermediateTarget;
+ hareBody = getRedirectingFactoryBody(hare);
+ }
+ onCycle(tortoise, tortoiseBody);
+ }
+
+ static void computeRedirectionTarget(
+ Member factoryMethod, RedirectingFactoryBody body) {
+ DartType returnType = new InterfaceType(
+ factoryMethod.enclosingClass,
+ factoryMethod.function.typeParameters
+ .map((t) => new TypeParameterType(t))
+ .toList());
+ Member target;
+ iterateRedirections(factoryMethod,
+ (Member member, RedirectingFactoryBody body) {
+ if (body.isUnresolved) {
+ target = member;
+ returnType = const InvalidType();
+ return false; // Stop iterating.
+ }
+ target = body.intermediateTarget;
+ if (returnType is InterfaceType) {
+ InterfaceType interfaceType = returnType;
+ returnType = Substitution
+ .fromPairs(
+ member.function.typeParameters, interfaceType.typeArguments)
+ .substituteType(body.intermediateReturnType);
+ }
+ return true; // Continue iterating.
+ }, (Member member, RedirectingFactoryBody body) {
+ returnType = const InvalidType();
+ target = null;
+ });
+ body
+ ..cachedRedirectionTarget = target
+ ..cachedReturnType = returnType;
}
- return null;
}
« no previous file with comments | « pkg/front_end/lib/src/fasta/kernel/kernel_named_type_builder.dart ('k') | pkg/front_end/messages.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698