Skip to content

Commit c3c0042

Browse files
committed
[Sema] NameAndTypeResolver
1 parent fcbb73d commit c3c0042

File tree

13 files changed

+686
-4
lines changed

13 files changed

+686
-4
lines changed

include/soll/AST/Decl.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class Decl : public ASTNode {
2727
std::string Name;
2828
Visibility Vis;
2929
std::string UniqueName;
30+
const ASTNode *Parent;
3031

3132
protected:
3233
friend class ASTReader;
@@ -35,10 +36,11 @@ class Decl : public ASTNode {
3536
Decl(SourceRange L,
3637
llvm::StringRef Name = llvm::StringRef::withNullAsEmpty(nullptr),
3738
Visibility Vis = Visibility::Default)
38-
: Location(L), Name(Name.str()), Vis(Vis), UniqueName(Name.str()) {}
39+
: Location(L), Name(Name.str()), Vis(Vis), UniqueName(Name.str()),
40+
Parent(nullptr) {}
3941

4042
Decl(SourceRange L, std::string Name, Visibility Vis = Visibility::Default)
41-
: Location(L), Name(Name), Vis(Vis), UniqueName(Name) {}
43+
: Location(L), Name(Name), Vis(Vis), UniqueName(Name), Parent(nullptr) {}
4244

4345
public:
4446
virtual void accept(DeclVisitor &visitor) = 0;
@@ -48,6 +50,15 @@ class Decl : public ASTNode {
4850
llvm::StringRef getUniqueName() const { return UniqueName; }
4951
void setUniqueName(llvm::StringRef NewName) { UniqueName = NewName.str(); }
5052
Visibility getVisibility() const { return Vis; }
53+
54+
void setScope(const ASTNode *D) { Parent = D; }
55+
/// @returns the scope this declaration resides in. Can be nullptr if it is
56+
/// the global scope. Available only after name and type resolution step.
57+
const ASTNode *scope() const { return Parent; }
58+
59+
bool isStructMember() const ;
60+
61+
bool isVisibleAsUnqualifiedName() const ;
5162
};
5263

5364
/**
@@ -414,6 +425,18 @@ class StructDecl : public Decl {
414425
Token getToken() const { return Tok; }
415426
TypePtr getType() const { return Ty; }
416427
TypePtr getConstructorType() const { return ConstructorTy; }
428+
std::vector<Decl *> getMembers() {
429+
std::vector<Decl *> Res;
430+
for (auto &M : Members)
431+
Res.push_back(M.get());
432+
return Res;
433+
}
434+
std::vector<const Decl *> getMembers() const {
435+
std::vector<const Decl *> Res;
436+
for (auto &M : Members)
437+
Res.push_back(M.get());
438+
return Res;
439+
}
417440
};
418441

419442
class ModifierInvocation {
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2+
#pragma once
3+
4+
#include "soll/AST/AST.h"
5+
#include "soll/AST/Decl.h"
6+
#include "soll/Basic/DiagnosticSema.h"
7+
#include "soll/Sema/Sema.h"
8+
9+
#include <iostream>
10+
#include <map>
11+
#include <memory>
12+
#include <string>
13+
#include <vector>
14+
using std::cerr;
15+
using std::endl;
16+
17+
namespace soll {
18+
19+
class DeclarationContainer {
20+
public:
21+
DeclarationContainer() = default;
22+
explicit DeclarationContainer(const ASTNode *EnclosingNode,
23+
DeclarationContainer *EnclosingContainer)
24+
: EnclosingNode(EnclosingNode), EnclosingContainer(EnclosingContainer) {
25+
if (EnclosingContainer)
26+
EnclosingContainer->InnerContainers.emplace_back(this);
27+
}
28+
29+
ASTNode const *enclosingNode() const { return EnclosingNode; }
30+
31+
bool registerDeclaration(const Decl *D, bool Invisible, bool Update) {
32+
return registerDeclaration(D, llvm::StringRef(), nullptr, Invisible,
33+
Update);
34+
}
35+
36+
bool registerDeclaration(const Decl *D, llvm::StringRef Name,
37+
const SourceRange *Loc, bool Invisible, bool Update) {
38+
if (Name.empty()) {
39+
Name = D->getName();
40+
}
41+
42+
if (Name.empty())
43+
return true;
44+
45+
if (Update) {
46+
assert(!dynamic_cast<const FunctionDecl *>(D) &&
47+
"Attempt to update function definition.");
48+
Declarations.erase(Name);
49+
InvisibleDeclarations.erase(Name);
50+
return true;
51+
} else {
52+
if (conflictingDeclaration(D, Name))
53+
return false;
54+
if (EnclosingContainer && D->isVisibleAsUnqualifiedName()) {
55+
// assert(false && "TODO: isVisibleAsUnqualifiedName for struct");
56+
cerr << "TODO: isVisibleAsUnqualifiedName for struct" << endl;
57+
// deal with homonymCandidates
58+
}
59+
}
60+
61+
std::vector<const Decl *> Decls =
62+
Invisible ? InvisibleDeclarations[Name] : Declarations[Name];
63+
if (find(Decls.begin(), Decls.end(), D) != Decls.end())
64+
Decls.emplace_back(D);
65+
66+
return true;
67+
}
68+
69+
const Decl *conflictingDeclaration(const Decl *D,
70+
llvm::StringRef Name) const {
71+
if (Name.empty())
72+
Name = D->getName();
73+
assert(!Name.empty());
74+
75+
std::vector<Decl const *> Decls;
76+
if (Declarations.count(Name))
77+
Decls += Declarations.at(Name);
78+
79+
if (InvisibleDeclarations.count(Name))
80+
Decls += InvisibleDeclarations.at(Name);
81+
82+
if (dynamic_cast<const FunctionDecl *>(D) ||
83+
dynamic_cast<const EventDecl *>(D) ||
84+
dynamic_cast<const MagicVariableDecl *>(D)) {
85+
for (const Decl *RegDecl : Decls) {
86+
if (dynamic_cast<const FunctionDecl *>(D) &&
87+
!dynamic_cast<const FunctionDecl *>(RegDecl))
88+
return RegDecl;
89+
if (dynamic_cast<const EventDecl *>(D) &&
90+
!dynamic_cast<const EventDecl *>(RegDecl))
91+
return RegDecl;
92+
if (dynamic_cast<const MagicVariableDecl *>(D) &&
93+
!dynamic_cast<const MagicVariableDecl *>(RegDecl))
94+
return RegDecl;
95+
}
96+
} else if (Decls.size() == 1 && Decls.front() == D) {
97+
return nullptr;
98+
} else if (!Decls.empty()) {
99+
return Decls.front();
100+
}
101+
102+
return nullptr;
103+
}
104+
105+
private:
106+
const ASTNode *EnclosingNode = nullptr;
107+
const DeclarationContainer *EnclosingContainer = nullptr;
108+
std::vector<const DeclarationContainer *> InnerContainers;
109+
std::map<llvm::StringRef, std::vector<const Decl *>> Declarations;
110+
std::map<llvm::StringRef, std::vector<const Decl *>> InvisibleDeclarations;
111+
// std::vector<std::tuple<std::string, langutil::SourceLocation const*>>
112+
// m_homonymCandidates;
113+
};
114+
115+
} // namespace soll

include/soll/Sema/GlobalContent.h

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2+
#pragma once
3+
4+
#include "soll/AST/AST.h"
5+
#include "soll/AST/Decl.h"
6+
#include "soll/Basic/DiagnosticSema.h"
7+
#include "soll/Sema/Sema.h"
8+
9+
#include <iostream>
10+
#include <map>
11+
#include <memory>
12+
#include <string>
13+
#include <vector>
14+
15+
using std::cerr;
16+
using std::endl;
17+
18+
namespace soll {
19+
/// Magic variables get negative ids for easy differentiation
20+
namespace {
21+
int magicVariableToID(std::string const &_name) {
22+
if (_name == "abi")
23+
return -1;
24+
else if (_name == "addmod")
25+
return -2;
26+
else if (_name == "assert")
27+
return -3;
28+
else if (_name == "block")
29+
return -4;
30+
else if (_name == "blockhash")
31+
return -5;
32+
else if (_name == "ecrecover")
33+
return -6;
34+
else if (_name == "gasleft")
35+
return -7;
36+
else if (_name == "keccak256")
37+
return -8;
38+
else if (_name == "msg")
39+
return -15;
40+
else if (_name == "mulmod")
41+
return -16;
42+
else if (_name == "now")
43+
return -17;
44+
else if (_name == "require")
45+
return -18;
46+
else if (_name == "revert")
47+
return -19;
48+
else if (_name == "ripemd160")
49+
return -20;
50+
else if (_name == "selfdestruct")
51+
return -21;
52+
else if (_name == "sha256")
53+
return -22;
54+
else if (_name == "sha3")
55+
return -23;
56+
else if (_name == "suicide")
57+
return -24;
58+
else if (_name == "super")
59+
return -25;
60+
else if (_name == "tx")
61+
return -26;
62+
else if (_name == "type")
63+
return -27;
64+
else if (_name == "this")
65+
return -28;
66+
else
67+
__builtin_unreachable();
68+
}
69+
} // namespace
70+
71+
class GlobalContext {
72+
public:
73+
void setCurrentContract(const ContractDecl *Cont) { CurrentContract = Cont; }
74+
void resetCurrentContract() { CurrentContract = nullptr; }
75+
const MagicVariableDecl *currentThis() {
76+
if (!ThisCache[CurrentContract]) {
77+
TypePtr Type = CurrentContract->getType();
78+
ThisCache[CurrentContract] = std::make_shared<MagicVariableDecl>(
79+
magicVariableToID("this"), "this", Type);
80+
}
81+
return ThisCache[CurrentContract].get();
82+
}
83+
84+
const MagicVariableDecl *currentSuper() {
85+
assert(false && "unimp currentSuper");
86+
return nullptr;
87+
}
88+
89+
GlobalContext() = default;
90+
GlobalContext(const GlobalContext &) = delete;
91+
~GlobalContext() = default;
92+
93+
private:
94+
const ContractDecl *CurrentContract = nullptr;
95+
std::map<const ContractDecl *, std::shared_ptr<MagicVariableDecl>> ThisCache;
96+
std::map<const ContractDecl *, std::shared_ptr<MagicVariableDecl>> SuperCache;
97+
};
98+
} // namespace soll
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2+
#pragma once
3+
4+
#include "soll/AST/AST.h"
5+
#include "soll/AST/Decl.h"
6+
#include "soll/Basic/DiagnosticSema.h"
7+
#include "soll/Sema/DeclarationContainer.h"
8+
#include "soll/Sema/Sema.h"
9+
10+
namespace soll {
11+
class NameAndTypeResolver {
12+
void setScope(const ASTNode *Node) { CurrentScope = Scopes[Node].get(); }
13+
bool resolveNamesAndTypesInternal(ASTNode *Node, bool ResolveCode);
14+
bool updateDeclaration(const Decl *D) {
15+
Scopes[nullptr]->registerDeclaration(D, false, true);
16+
}
17+
public:
18+
NameAndTypeResolver(Sema &Action, GlobalContext &GC);
19+
void Register(SourceUnit &SU);
20+
bool Resolve(SourceUnit &SU);
21+
22+
23+
private:
24+
Sema &Action;
25+
GlobalContext &GC;
26+
std::map<const ASTNode *, std::shared_ptr<DeclarationContainer>> Scopes;
27+
const DeclarationContainer *CurrentScope = nullptr;
28+
};
29+
} // namespace soll
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2+
#pragma once
3+
4+
#include "soll/AST/AST.h"
5+
#include "soll/AST/Decl.h"
6+
#include "soll/Basic/DiagnosticSema.h"
7+
#include "soll/Sema/DeclarationContainer.h"
8+
#include "soll/Sema/NameAndTypeResolver.h"
9+
#include "soll/Sema/Sema.h"
10+
11+
namespace soll {
12+
class ReferencesResolver : public DeclVisitor, public StmtVisitor {
13+
public:
14+
ReferencesResolver(Sema &Action, NameAndTypeResolver &NTR,
15+
bool ResolveInsideCode);
16+
bool resolve(ASTNode *Node) {
17+
Status = true;
18+
if (auto D = dynamic_cast<Decl *>(Node))
19+
D->accept(*this);
20+
else if (auto S = dynamic_cast<Stmt *>(Node))
21+
S->accept(*this);
22+
return Status;
23+
}
24+
private:
25+
Sema &Action;
26+
NameAndTypeResolver &Resolver;
27+
bool ResolveInsideCode;
28+
bool Status;
29+
};
30+
} // namespace soll

include/soll/Sema/Sema.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "soll/AST/ASTContext.h"
55
#include "soll/AST/ExprAsm.h"
66
#include "soll/Sema/Scope.h"
7+
#include "soll/Sema/GlobalContent.h"
78
#include <memory>
89
#include <vector>
910

@@ -17,6 +18,7 @@ class Lexer;
1718
class Sema;
1819
class SourceManager;
1920
class Token;
21+
class NameAndTypeResolver;
2022

2123
class Sema {
2224
Sema(const Sema &) = delete;
@@ -51,6 +53,8 @@ class Sema {
5153
DiagnosticsEngine &Diags;
5254
SourceManager &SourceMgr;
5355
const llvm::StringMap<llvm::APInt> *LibrariesAddressMap;
56+
std::shared_ptr<NameAndTypeResolver> NTR;
57+
GlobalContext GC;
5458

5559
Sema(Lexer &lexer, ASTContext &ctxt, ASTConsumer &consumer);
5660

@@ -135,6 +139,9 @@ class Sema {
135139
bool AppendChild);
136140

137141
void resolveType(SourceUnit &SU);
142+
void resolveScope(SourceUnit &SU);
143+
void registerDeclarations(SourceUnit &SU);
144+
void resolveNameAndType(SourceUnit &SU);
138145
void resolveInherit(SourceUnit &SU);
139146
void resolveUniqueName(SourceUnit &SU);
140147
void resolveIdentifierDecl(SourceUnit &SU);

lib/AST/Decl.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,25 @@
55

66
namespace soll {
77

8+
bool Decl::isStructMember() const {
9+
if (auto D = dynamic_cast<const Decl*>(scope())) {
10+
return dynamic_cast<const StructDecl *>(D);
11+
}
12+
return false;
13+
}
14+
15+
bool Decl::isVisibleAsUnqualifiedName() const {
16+
if (!scope())
17+
return true;
18+
if (isStructMember())
19+
return false;
20+
if (auto D = dynamic_cast<const Decl*>(scope()))
21+
if (auto F = dynamic_cast<const FunctionDecl*>(D))
22+
if (!F->getBody())
23+
return false; // parameter of a function without body
24+
return true;
25+
}
26+
827
///
928
/// Source Unit
1029
///

0 commit comments

Comments
 (0)