blob: ee0c60543366bc7f36bd9e31e03b5b68c68dffbb [file] [log] [blame]
// Copyright (c) 2016, 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.
library fasta.redirecting_factory_body;
import 'package:kernel/ast.dart'
show
ExpressionStatement,
InvalidExpression,
Let,
Member,
Procedure,
StaticGet,
VariableDeclaration;
class RedirectingFactoryBody extends ExpressionStatement {
RedirectingFactoryBody(Member target)
: super(new Let(new VariableDeclaration.forValue(new StaticGet(target)),
new InvalidExpression()));
Member get target {
Let let = expression;
StaticGet staticGet = let.variable.initializer;
return staticGet.target;
}
}
bool isRedirectingFactory(Member member) {
return member is Procedure && member.function.body is RedirectingFactoryBody;
}
Member getImmediateRedirectionTarget(Member member) {
if (isRedirectingFactory(member)) {
Procedure procedure = member;
RedirectingFactoryBody body = procedure.function.body;
return body.target;
} else {
return null;
}
}
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;
Member hare = getImmediateRedirectionTarget(member);
while (tortoise != hare) {
if (!isRedirectingFactory(tortoise)) return tortoise;
tortoise = getImmediateRedirectionTarget(tortoise);
hare = getImmediateRedirectionTarget(getImmediateRedirectionTarget(hare));
}
return null;
}