mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
analysis for patterns. Major changes: 1. We no longer try to compute the types of functions in the parser. 2. The type of a function always matches the type of the argument patterns. 3. Every FuncDecl now has a corresponding FuncExpr; that FuncExpr might not have a body, though. 4. We now use a new class "ExprHandle" so that both a pattern and a type can hold a reference to the same expression. Hopefully this will be a more reasonable foundation for further changes to how we compute the types of FuncDecls in generics and for the implementation of type location information. Swift SVN r2370
641 lines
15 KiB
C++
641 lines
15 KiB
C++
//===--- ASTWalker.cpp - AST Traversal ------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements Expr::walk and Stmt::walk.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/ASTWalker.h"
|
|
#include "swift/AST/ASTVisitor.h"
|
|
#include "swift/AST/PrettyStackTrace.h"
|
|
using namespace swift;
|
|
|
|
void ASTWalker::anchor() {}
|
|
|
|
namespace {
|
|
|
|
/// Traversal - This class implements a simple expression/statement
|
|
/// recursive traverser which queries a user-provided walker class
|
|
/// on every node in an AST.
|
|
class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*> {
|
|
friend class ASTVisitor<Traversal, Expr*, Stmt*>;
|
|
|
|
ASTWalker &Walker;
|
|
|
|
typedef ASTVisitor<Traversal, Expr*, Stmt*> inherited;
|
|
|
|
/// \brief RAII object that sets the parent of the walk context
|
|
/// appropriately.
|
|
class SetParentRAII {
|
|
ASTWalker &Walker;
|
|
decltype(ASTWalker::Parent) PriorParent;
|
|
|
|
public:
|
|
template<typename T>
|
|
SetParentRAII(ASTWalker &walker, T *newParent)
|
|
: Walker(walker), PriorParent(walker.Parent) {
|
|
walker.Parent = newParent;
|
|
}
|
|
|
|
~SetParentRAII() {
|
|
Walker.Parent = PriorParent;
|
|
}
|
|
};
|
|
|
|
Expr *visit(Expr *E) {
|
|
SetParentRAII SetParent(Walker, E);
|
|
return inherited::visit(E);
|
|
}
|
|
|
|
Stmt *visit(Stmt *S) {
|
|
SetParentRAII SetParent(Walker, S);
|
|
return inherited::visit(S);
|
|
}
|
|
|
|
Expr *visitErrorExpr(ErrorExpr *E) { return E; }
|
|
Expr *visitLiteralExpr(LiteralExpr *E) { return E; }
|
|
Expr *visitDeclRefExpr(DeclRefExpr *E) { return E; }
|
|
Expr *visitOverloadedDeclRefExpr(OverloadedDeclRefExpr *E) { return E; }
|
|
Expr *visitOverloadedMemberRefExpr(OverloadedMemberRefExpr *E) { return E; }
|
|
Expr *visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E) { return E; }
|
|
Expr *visitUnresolvedMemberExpr(UnresolvedMemberExpr *E) { return E; }
|
|
Expr *visitNewReferenceExpr(NewReferenceExpr *E) { return E; }
|
|
Expr *visitOpaqueValueExpr(OpaqueValueExpr *E) { return E; }
|
|
|
|
Expr *visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E) {
|
|
for (auto &Segment : E->getSegments()) {
|
|
if (Expr *Seg = doIt(Segment))
|
|
Segment = Seg;
|
|
else
|
|
return nullptr;
|
|
}
|
|
return E;
|
|
}
|
|
|
|
Expr *visitMemberRefExpr(MemberRefExpr *E) {
|
|
if (Expr *Base = doIt(E->getBase())) {
|
|
E->setBase(Base);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitExistentialMemberRefExpr(ExistentialMemberRefExpr *E) {
|
|
if (Expr *Base = doIt(E->getBase())) {
|
|
E->setBase(Base);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitArchetypeMemberRefExpr(ArchetypeMemberRefExpr *E) {
|
|
if (Expr *Base = doIt(E->getBase())) {
|
|
E->setBase(Base);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitGenericMemberRefExpr(GenericMemberRefExpr *E) {
|
|
if (Expr *Base = doIt(E->getBase())) {
|
|
E->setBase(Base);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitParenExpr(ParenExpr *E) {
|
|
if (Expr *subExpr = doIt(E->getSubExpr())) {
|
|
E->setSubExpr(subExpr);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
Expr *visitTupleExpr(TupleExpr *E) {
|
|
for (unsigned i = 0, e = E->getNumElements(); i != e; ++i)
|
|
if (E->getElement(i)) {
|
|
if (Expr *Elt = doIt(E->getElement(i)))
|
|
E->setElement(i, Elt);
|
|
else
|
|
return nullptr;
|
|
}
|
|
return E;
|
|
}
|
|
Expr *visitSubscriptExpr(SubscriptExpr *E) {
|
|
if (Expr *Base = doIt(E->getBase()))
|
|
E->setBase(Base);
|
|
else
|
|
return nullptr;
|
|
|
|
if (Expr *Index = doIt(E->getIndex()))
|
|
E->setIndex(Index);
|
|
else
|
|
return nullptr;
|
|
|
|
return E;
|
|
}
|
|
Expr *visitExistentialSubscriptExpr(ExistentialSubscriptExpr *E) {
|
|
if (Expr *Base = doIt(E->getBase()))
|
|
E->setBase(Base);
|
|
else
|
|
return nullptr;
|
|
|
|
if (Expr *Index = doIt(E->getIndex()))
|
|
E->setIndex(Index);
|
|
else
|
|
return nullptr;
|
|
|
|
return E;
|
|
}
|
|
Expr *visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) {
|
|
if (Expr *Base = doIt(E->getBase()))
|
|
E->setBase(Base);
|
|
else
|
|
return nullptr;
|
|
|
|
if (Expr *Index = doIt(E->getIndex()))
|
|
E->setIndex(Index);
|
|
else
|
|
return nullptr;
|
|
|
|
return E;
|
|
}
|
|
Expr *visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
|
|
if (Expr *Base = doIt(E->getBase()))
|
|
E->setBase(Base);
|
|
else
|
|
return nullptr;
|
|
|
|
if (Expr *Index = doIt(E->getIndex()))
|
|
E->setIndex(Index);
|
|
else
|
|
return nullptr;
|
|
|
|
return E;
|
|
}
|
|
Expr *visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) { return E; }
|
|
Expr *visitUnresolvedDotExpr(UnresolvedDotExpr *E) {
|
|
if (!E->getBase())
|
|
return E;
|
|
|
|
if (Expr *E2 = doIt(E->getBase())) {
|
|
E->setBase(E2);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitTupleElementExpr(TupleElementExpr *E) {
|
|
if (Expr *E2 = doIt(E->getBase())) {
|
|
E->setBase(E2);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitImplicitConversionExpr(ImplicitConversionExpr *E) {
|
|
if (Expr *E2 = doIt(E->getSubExpr())) {
|
|
E->setSubExpr(E2);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitAddressOfExpr(AddressOfExpr *E) {
|
|
if (Expr *E2 = doIt(E->getSubExpr())) {
|
|
E->setSubExpr(E2);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitSequenceExpr(SequenceExpr *E) {
|
|
for (unsigned i = 0, e = E->getNumElements(); i != e; ++i)
|
|
if (Expr *Elt = doIt(E->getElement(i)))
|
|
E->setElement(i, Elt);
|
|
else
|
|
return nullptr;
|
|
return E;
|
|
}
|
|
|
|
Expr *visitNewArrayExpr(NewArrayExpr *E) {
|
|
for (auto &bound : E->getBounds()) {
|
|
// Ignore empty bounds.
|
|
if (!bound.Value) continue;
|
|
|
|
Expr *newValue = doIt(bound.Value);
|
|
if (!newValue) return nullptr;
|
|
bound.Value = newValue;
|
|
}
|
|
return E;
|
|
}
|
|
|
|
Expr *visitFuncExpr(FuncExpr *E) {
|
|
if (!E->getBody())
|
|
return E;
|
|
if (BraceStmt *S = cast_or_null<BraceStmt>(doIt(E->getBody()))) {
|
|
E->setBody(S);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitExplicitClosureExpr(ExplicitClosureExpr *E) {
|
|
if (Expr *E2 = doIt(E->getBody())) {
|
|
E->setBody(E2);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitImplicitClosureExpr(ImplicitClosureExpr *E) {
|
|
if (Expr *E2 = doIt(E->getBody())) {
|
|
E->setBody(E2);
|
|
return E;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Expr *visitModuleExpr(ModuleExpr *E) { return E; }
|
|
|
|
Expr *visitApplyExpr(ApplyExpr *E) {
|
|
Expr *E2 = doIt(E->getFn());
|
|
if (E2 == nullptr) return nullptr;
|
|
E->setFn(E2);
|
|
|
|
E2 = doIt(E->getArg());
|
|
if (E2 == nullptr) return nullptr;
|
|
E->setArg(E2);
|
|
return E;
|
|
}
|
|
|
|
Expr *visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *E) {
|
|
Expr *E2 = doIt(E->getLHS());
|
|
if (E2 == nullptr) return nullptr;
|
|
E->setLHS(E2);
|
|
|
|
E2 = doIt(E->getRHS());
|
|
if (E2 == nullptr) return nullptr;
|
|
E->setRHS(E2);
|
|
return E;
|
|
}
|
|
|
|
Expr *visitCoerceExpr(CoerceExpr *E) {
|
|
Expr *LHS = doIt(E->getLHS());
|
|
if (!LHS) return nullptr;
|
|
E->setLHS(LHS);
|
|
|
|
Expr *RHS = doIt(E->getRHS());
|
|
if (!RHS) return nullptr;
|
|
E->setRHS(RHS);
|
|
|
|
return E;
|
|
}
|
|
|
|
Expr *visitConstructExpr(ConstructExpr *E) {
|
|
Expr *Input = doIt(E->getInput());
|
|
if (!Input) return nullptr;
|
|
E->setInput(Input);
|
|
|
|
return E;
|
|
}
|
|
|
|
Stmt *visitSemiStmt(SemiStmt *SS) {
|
|
return SS;
|
|
}
|
|
|
|
Stmt *visitBreakStmt(BreakStmt *BS) {
|
|
return BS;
|
|
}
|
|
|
|
Stmt *visitContinueStmt(ContinueStmt *CS) {
|
|
return CS;
|
|
}
|
|
|
|
Stmt *visitAssignStmt(AssignStmt *AS) {
|
|
if (Expr *E = doIt(AS->getDest()))
|
|
AS->setDest(E);
|
|
else
|
|
return nullptr;
|
|
|
|
if (Expr *E = doIt(AS->getSrc()))
|
|
AS->setSrc(E);
|
|
else
|
|
return nullptr;
|
|
return AS;
|
|
}
|
|
|
|
Stmt *visitBraceStmt(BraceStmt *BS) {
|
|
for (unsigned i = 0, e = BS->getNumElements(); i != e; ++i) {
|
|
if (Expr *SubExpr = BS->getElement(i).dyn_cast<Expr*>()) {
|
|
if (Expr *E2 = doIt(SubExpr))
|
|
BS->setElement(i, E2);
|
|
else
|
|
return nullptr;
|
|
continue;
|
|
}
|
|
|
|
if (Stmt *S = BS->getElement(i).dyn_cast<Stmt*>()) {
|
|
if (Stmt *S2 = doIt(S))
|
|
BS->setElement(i, S2);
|
|
else
|
|
return nullptr;
|
|
continue;
|
|
}
|
|
|
|
if (doIt(BS->getElement(i).get<Decl*>()))
|
|
return nullptr;
|
|
}
|
|
|
|
return BS;
|
|
}
|
|
|
|
Stmt *visitReturnStmt(ReturnStmt *RS) {
|
|
if (!RS->hasResult())
|
|
return RS;
|
|
if (Expr *E = doIt(RS->getResult()))
|
|
RS->setResult(E);
|
|
else
|
|
return nullptr;
|
|
return RS;
|
|
}
|
|
|
|
Stmt *visitIfStmt(IfStmt *IS) {
|
|
if (Expr *E2 = doIt(IS->getCond()))
|
|
IS->setCond(E2);
|
|
else
|
|
return nullptr;
|
|
|
|
if (Stmt *S2 = doIt(IS->getThenStmt()))
|
|
IS->setThenStmt(S2);
|
|
else
|
|
return nullptr;
|
|
|
|
if (IS->getElseStmt()) {
|
|
if (Stmt *S2 = doIt(IS->getElseStmt()))
|
|
IS->setElseStmt(S2);
|
|
else
|
|
return nullptr;
|
|
}
|
|
return IS;
|
|
}
|
|
|
|
Stmt *visitWhileStmt(WhileStmt *WS) {
|
|
if (Expr *E2 = doIt(WS->getCond()))
|
|
WS->setCond(E2);
|
|
else
|
|
return nullptr;
|
|
|
|
if (Stmt *S2 = doIt(WS->getBody()))
|
|
WS->setBody(S2);
|
|
else
|
|
return nullptr;
|
|
return WS;
|
|
}
|
|
|
|
Stmt *visitDoWhileStmt(DoWhileStmt *DWS) {
|
|
if (Stmt *S2 = doIt(DWS->getBody()))
|
|
DWS->setBody(S2);
|
|
else
|
|
return nullptr;
|
|
|
|
if (Expr *E2 = doIt(DWS->getCond()))
|
|
DWS->setCond(E2);
|
|
else
|
|
return nullptr;
|
|
|
|
return DWS;
|
|
}
|
|
|
|
Stmt *visitForStmt(ForStmt *FS) {
|
|
// Visit any var decls in the initializer.
|
|
for (auto D : FS->getInitializerVarDecls())
|
|
if (doIt(D))
|
|
return nullptr;
|
|
|
|
if (Expr *E = FS->getInitializer().dyn_cast<Expr*>()) {
|
|
if ((E = doIt(E)))
|
|
FS->setInitializer(E);
|
|
else
|
|
return nullptr;
|
|
} else if (AssignStmt *S = FS->getInitializer().dyn_cast<AssignStmt*>()) {
|
|
if ((S = cast_or_null<AssignStmt>(doIt(S))))
|
|
FS->setInitializer(S);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
if (FS->getCond().isNonNull()) {
|
|
if (Expr *E2 = doIt(FS->getCond().get()))
|
|
FS->setCond(E2);
|
|
else
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (Expr *E = FS->getIncrement().dyn_cast<Expr*>()) {
|
|
if ((E = doIt(E)))
|
|
FS->setIncrement(E);
|
|
else
|
|
return nullptr;
|
|
} else if (AssignStmt *S = FS->getIncrement().dyn_cast<AssignStmt*>()) {
|
|
if ((S = cast_or_null<AssignStmt>(doIt(S))))
|
|
FS->setIncrement(S);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
if (Stmt *S = doIt(FS->getBody()))
|
|
FS->setBody(S);
|
|
else
|
|
return nullptr;
|
|
return FS;
|
|
}
|
|
|
|
Stmt *visitForEachStmt(ForEachStmt *S) {
|
|
if (Expr *Container = S->getContainer()) {
|
|
if ((Container = doIt(Container)))
|
|
S->setContainer(Container);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
if (Stmt *Body = S->getBody()) {
|
|
if ((Body = doIt(Body)))
|
|
S->setBody(cast<BraceStmt>(Body));
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
return S;
|
|
}
|
|
|
|
bool visitPatternVarGetSet(Pattern *P) {
|
|
switch (P->getKind()) {
|
|
case PatternKind::Paren:
|
|
return visitPatternVarGetSet(cast<ParenPattern>(P)->getSubPattern());
|
|
|
|
case PatternKind::Tuple:
|
|
for (auto &Elt : cast<TuplePattern>(P)->getFields())
|
|
if (visitPatternVarGetSet(Elt.getPattern()))
|
|
return true;
|
|
return false;
|
|
|
|
case PatternKind::Named:
|
|
if (VarDecl *Var = cast<NamedPattern>(P)->getDecl()) {
|
|
if (!Var->isProperty())
|
|
return false;
|
|
|
|
if (FuncDecl *Get = Var->getGetter()) {
|
|
if (doIt(Get))
|
|
return true;
|
|
}
|
|
|
|
if (FuncDecl *Set = Var->getSetter()) {
|
|
if (doIt(Set))
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
|
|
case PatternKind::Any:
|
|
return false;
|
|
|
|
case PatternKind::Typed:
|
|
return visitPatternVarGetSet(cast<TypedPattern>(P)->getSubPattern());
|
|
}
|
|
}
|
|
|
|
public:
|
|
Traversal(ASTWalker &walker) : Walker(walker) {}
|
|
|
|
Expr *doIt(Expr *E) {
|
|
// Do the pre-order visitation. If it returns false, we just
|
|
// skip entering subnodes of this tree.
|
|
if (!Walker.walkToExprPre(E))
|
|
return E;
|
|
|
|
// Otherwise, visit the children.
|
|
E = visit(E);
|
|
|
|
// If we didn't bail out, do post-order visitation.
|
|
if (E) E = Walker.walkToExprPost(E);
|
|
|
|
return E;
|
|
}
|
|
|
|
Stmt *doIt(Stmt *S) {
|
|
// Do the pre-order visitation. If it returns false, we just
|
|
// skip entering subnodes of this tree.
|
|
if (!Walker.walkToStmtPre(S))
|
|
return S;
|
|
|
|
// Otherwise, visit the children.
|
|
S = visit(S);
|
|
|
|
// If we didn't bail out, do post-order visitation.
|
|
if (S) S = Walker.walkToStmtPost(S);
|
|
|
|
return S;
|
|
}
|
|
|
|
/// Returns true on failure.
|
|
bool doIt(Decl *D) {
|
|
// Do the pre-order visitation. If it returns false, we just
|
|
// skip entering subnodes of this tree.
|
|
if (!Walker.walkToDeclPre(D))
|
|
return false;
|
|
|
|
if (PatternBindingDecl *PBD = dyn_cast<PatternBindingDecl>(D)) {
|
|
#if 0
|
|
if (visitPatternVarGetSet(PBD->getPattern()))
|
|
return true;
|
|
#endif
|
|
|
|
if (Expr *Init = PBD->getInit()) {
|
|
#ifndef NDEBUG
|
|
PrettyStackTraceDecl debugStack("walking into initializer for", PBD);
|
|
#endif
|
|
if (Expr *E2 = doIt(Init))
|
|
PBD->setInit(E2);
|
|
else
|
|
return true;
|
|
}
|
|
} else if (FuncDecl *FD = dyn_cast<FuncDecl>(D)) {
|
|
FuncExpr *Body = FD->getBody();
|
|
#ifndef NDEBUG
|
|
PrettyStackTraceDecl debugStack("walking into body of", FD);
|
|
#endif
|
|
if (FuncExpr *E2 = cast_or_null<FuncExpr>(doIt(Body)))
|
|
FD->setBody(E2);
|
|
else
|
|
return true;
|
|
}
|
|
|
|
} else if (ExtensionDecl *ED = dyn_cast<ExtensionDecl>(D)) {
|
|
for (Decl *M : ED->getMembers()) {
|
|
if (doIt(M))
|
|
return true;
|
|
}
|
|
} else if (OneOfDecl *OOD = dyn_cast<OneOfDecl>(D)) {
|
|
for (Decl *Member : OOD->getMembers())
|
|
if (doIt(Member))
|
|
return true;
|
|
} else if (StructDecl *SD = dyn_cast<StructDecl>(D)) {
|
|
for (Decl *Member : SD->getMembers())
|
|
if (doIt(Member))
|
|
return true;
|
|
} else if (ClassDecl *CD = dyn_cast<ClassDecl>(D)) {
|
|
for (Decl *Member : CD->getMembers())
|
|
if (doIt(Member))
|
|
return true;
|
|
} else if (TopLevelCodeDecl *TLCD = dyn_cast<TopLevelCodeDecl>(D)) {
|
|
auto Body = TLCD->getBody();
|
|
if (Body.is<Expr*>()) {
|
|
Expr *E = Body.get<Expr*>();
|
|
E = doIt(E);
|
|
TLCD->setBody(E);
|
|
} else {
|
|
Stmt *S = Body.get<Stmt*>();
|
|
S = doIt(S);
|
|
TLCD->setBody(S);
|
|
}
|
|
} else if (ConstructorDecl *CD = dyn_cast<ConstructorDecl>(D)) {
|
|
Stmt *S = CD->getBody();
|
|
if (S) {
|
|
S = doIt(S);
|
|
CD->setBody(cast<BraceStmt>(S));
|
|
}
|
|
} else if (DestructorDecl *DD = dyn_cast<DestructorDecl>(D)) {
|
|
Stmt *S = DD->getBody();
|
|
S = doIt(S);
|
|
DD->setBody(cast<BraceStmt>(S));
|
|
}
|
|
|
|
return !Walker.walkToDeclPost(D);
|
|
}
|
|
};
|
|
|
|
} // end anonymous namespace.
|
|
|
|
Expr *Expr::walk(ASTWalker &walker) {
|
|
return Traversal(walker).doIt(this);
|
|
}
|
|
|
|
Stmt *Stmt::walk(ASTWalker &walker) {
|
|
return Traversal(walker).doIt(this);
|
|
}
|
|
|
|
bool Decl::walk(ASTWalker &walker) {
|
|
return Traversal(walker).doIt(this);
|
|
}
|