mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
for these functions. And now that it's actually type-checked, build the getter's AST properly. Swift SVN r1416
415 lines
10 KiB
C++
415 lines
10 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 *visitIntegerLiteralExpr(IntegerLiteralExpr *E) { return E; }
|
|
Expr *visitFloatLiteralExpr(FloatLiteralExpr *E) { return E; }
|
|
Expr *visitStringLiteralExpr(StringLiteralExpr *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 *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 *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 *visitFuncExpr(FuncExpr *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 *visitBinaryExpr(BinaryExpr *E) {
|
|
// Visit the arguments to the tuple, but visit the operator in
|
|
// infix order.
|
|
MutableArrayRef<Expr *> Elements;
|
|
if (TupleExpr *Tuple = dyn_cast<TupleExpr>(E->getArg())) {
|
|
Elements = Tuple->getElements();
|
|
assert(Elements.size() == 2 && "Binary expression with wrong arguments");
|
|
} else {
|
|
llvm_unreachable("Binary expression without a tuple?");
|
|
}
|
|
|
|
Expr *E2 = doIt(Elements[0]);
|
|
if (E2 == nullptr) return nullptr;
|
|
Elements[0] = E2;
|
|
|
|
E2 = doIt(E->getFn());
|
|
if (E2 == 0) return 0;
|
|
E->setFn(E2);
|
|
|
|
E2 = doIt(Elements[1]);
|
|
if (E2 == 0) return 0;
|
|
Elements[1] = 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;
|
|
}
|
|
|
|
Stmt *visitErrorStmt(ErrorStmt *S) {
|
|
return S;
|
|
}
|
|
|
|
Stmt *visitSemiStmt(SemiStmt *SS) {
|
|
return SS;
|
|
}
|
|
|
|
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 (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;
|
|
}
|
|
|
|
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 (visitPatternVarGetSet(PBD->getPattern()))
|
|
return true;
|
|
|
|
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)) {
|
|
if (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;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|