Chromium Code Reviews| 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 ee0c60543366bc7f36bd9e31e03b5b68c68dffbb..1fa7dd80fbc534085ebc48ef3453523d81fadbc0 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,38 +6,67 @@ library fasta.redirecting_factory_body; |
| import 'package:kernel/ast.dart' |
| show |
| + Expression, |
| ExpressionStatement, |
| + FunctionNode, |
| InvalidExpression, |
| Let, |
| Member, |
| Procedure, |
| StaticGet, |
| + StringLiteral, |
| VariableDeclaration; |
| +const String letName = "#redirecting_factory"; |
| + |
| class RedirectingFactoryBody extends ExpressionStatement { |
| - RedirectingFactoryBody(Member target) |
| - : super(new Let(new VariableDeclaration.forValue(new StaticGet(target)), |
| + RedirectingFactoryBody.internal(Expression value) |
|
Paul Berry
2017/06/12 20:55:41
Nit: I prefer to name internal constructors like t
ahe
2017/06/13 07:11:41
Acknowledged.
|
| + : super(new Let(new VariableDeclaration(letName, initializer: value), |
| new InvalidExpression())); |
| + RedirectingFactoryBody(Member target) : this.internal(new StaticGet(target)); |
| + |
| + RedirectingFactoryBody.unresolved(String name) |
| + : this.internal(new StringLiteral(name)); |
| + |
| Member get target { |
| - Let let = expression; |
| - StaticGet staticGet = let.variable.initializer; |
| - return staticGet.target; |
| + var value = getValue(expression); |
| + return value is StaticGet ? value.target : null; |
| } |
| -} |
| -bool isRedirectingFactory(Member member) { |
| - return member is Procedure && member.function.body is RedirectingFactoryBody; |
| -} |
| + String get unresolvedName { |
| + var value = getValue(expression); |
| + return value is StringLiteral ? value.value : null; |
| + } |
| -Member getImmediateRedirectionTarget(Member member) { |
| - if (isRedirectingFactory(member)) { |
| - Procedure procedure = member; |
| - RedirectingFactoryBody body = procedure.function.body; |
| - return body.target; |
| - } else { |
| + bool get isUnresolved => unresolvedName != null; |
| + |
| + static getValue(Expression expression) { |
| + if (expression is Let) { |
| + VariableDeclaration variable = expression.variable; |
| + if (variable.name == letName) { |
| + return variable.initializer; |
| + } |
| + } |
| return null; |
| } |
| + |
| + static void restoreFromDill(Procedure factory) { |
| + // This is a hack / work around for storing redirecting constructors in |
| + // dill files. See `KernelClassBuilder.addRedirectingConstructor` in |
| + // [kernel_class_builder.dart](kernel_class_builder.dart). |
| + FunctionNode function = factory.function; |
| + ExpressionStatement statement = function.body; |
| + function.body = |
| + new RedirectingFactoryBody.internal(getValue(statement.expression)) |
|
Paul Berry
2017/06/12 20:55:41
Nit: I think we should report an internalError if
ahe
2017/06/13 07:11:41
I think I want to iterate more on this. I'll follo
|
| + ..parent = function; |
| + } |
| +} |
| + |
| +RedirectingFactoryBody getRedirectingFactoryBody(Member member) { |
| + return member is Procedure && member.function.body is RedirectingFactoryBody |
| + ? member.function.body |
| + : null; |
| } |
| Member getRedirectionTarget(Procedure member) { |
| @@ -45,11 +74,15 @@ Member getRedirectionTarget(Procedure member) { |
| // (https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare) to |
| // handle cycles. |
| Member tortoise = member; |
| - Member hare = getImmediateRedirectionTarget(member); |
| + RedirectingFactoryBody tortoiseBody = getRedirectingFactoryBody(tortoise); |
| + Member hare = tortoiseBody?.target; |
| + RedirectingFactoryBody hareBody = getRedirectingFactoryBody(hare); |
| while (tortoise != hare) { |
| - if (!isRedirectingFactory(tortoise)) return tortoise; |
| - tortoise = getImmediateRedirectionTarget(tortoise); |
| - hare = getImmediateRedirectionTarget(getImmediateRedirectionTarget(hare)); |
| + if (tortoiseBody?.isUnresolved ?? true) return tortoise; |
| + tortoise = tortoiseBody.target; |
| + tortoiseBody = getRedirectingFactoryBody(tortoise); |
| + hare = getRedirectingFactoryBody(hareBody?.target)?.target; |
| + hareBody = getRedirectingFactoryBody(hare); |
| } |
| return null; |
| } |