Skip to content

Commit 0d0d5a2

Browse files
committed
[Sema] NameAndTypeResolver
1 parent fcbb73d commit 0d0d5a2

File tree

15 files changed

+832
-7
lines changed

15 files changed

+832
-7
lines changed

include/soll/ADT/STLExtras.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
namespace soll {
1111

1212
template <typename T, typename... Args>
13-
std::vector<std::unique_ptr<T>> make_unique_vector(Args &&...args) {
13+
std::vector<std::unique_ptr<T>> make_unique_vector(Args &&... As) {
1414
std::vector<std::unique_ptr<T>> result;
15-
result.reserve(sizeof...(args));
16-
(result.emplace_back(std::forward<Args>(args)), ...);
15+
result.reserve(sizeof...(As));
16+
(result.emplace_back(std::forward<Args>(As)), ...);
1717
return result;
1818
}
1919

include/soll/AST/ASTBase.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ class ASTNode {
77
public:
88
enum class ASTNodeType { DECL, STMT };
99
ASTNode() = default;
10+
virtual ~ASTNode() = default;
1011
virtual ASTNodeType getASTType() = 0;
12+
1113
};
1214

1315
} // namespace soll

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: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
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+
void activateVariable(llvm::StringRef Name) {
32+
assert(InvisibleDeclarations.count(Name) &&
33+
InvisibleDeclarations.at(Name).size() == 1);
34+
assert(Declarations.count(Name) == 0 || Declarations.at(Name).empty());
35+
36+
Declarations[Name].emplace_back(InvisibleDeclarations.at(Name).front());
37+
InvisibleDeclarations.erase(Name);
38+
}
39+
40+
bool isInvisible(llvm::StringRef Name) const {
41+
return InvisibleDeclarations.count(Name);
42+
}
43+
44+
bool registerDeclaration(const Decl *D, bool Invisible, bool Update) {
45+
return registerDeclaration(D, llvm::StringRef(), nullptr, Invisible,
46+
Update);
47+
}
48+
49+
bool registerDeclaration(const Decl *D, llvm::StringRef Name,
50+
const SourceRange *Loc, bool Invisible,
51+
bool Update) {
52+
if (Name.empty()) {
53+
Name = D->getName();
54+
}
55+
56+
if (Name.empty())
57+
return true;
58+
59+
if (Update) {
60+
assert(!dynamic_cast<const FunctionDecl *>(D) &&
61+
"Attempt to update function definition.");
62+
Declarations.erase(Name);
63+
InvisibleDeclarations.erase(Name);
64+
return true;
65+
} else {
66+
if (conflictingDeclaration(D, Name))
67+
return false;
68+
if (EnclosingContainer && D->isVisibleAsUnqualifiedName()) {
69+
// assert(false && "TODO: isVisibleAsUnqualifiedName for struct");
70+
cerr << "TODO: isVisibleAsUnqualifiedName for struct" << endl;
71+
// deal with homonymCandidates
72+
}
73+
}
74+
75+
std::vector<const Decl *> &Decls =
76+
Invisible ? InvisibleDeclarations[Name] : Declarations[Name];
77+
if (find(Decls.begin(), Decls.end(), D) == Decls.end())
78+
Decls.emplace_back(D);
79+
return true;
80+
}
81+
82+
std::vector<const Decl *>
83+
resolveName(llvm::StringRef Name, bool Recursive = false,
84+
bool AlsoInvisible = false,
85+
bool OnlyVisibleAsUnqualifiedNames = false) const {
86+
std::vector<const Decl *> Res;
87+
88+
if (Declarations.count(Name)) {
89+
for (auto E : Declarations.at(Name)) {
90+
if (OnlyVisibleAsUnqualifiedNames) {
91+
if (!E->isVisibleAsUnqualifiedName())
92+
continue;
93+
}
94+
Res.emplace_back(E);
95+
}
96+
}
97+
98+
if (AlsoInvisible && InvisibleDeclarations.count(Name)) {
99+
for (auto E : InvisibleDeclarations.at(Name)) {
100+
if (OnlyVisibleAsUnqualifiedNames) {
101+
if (!E->isVisibleAsUnqualifiedName())
102+
continue;
103+
}
104+
Res.emplace_back(E);
105+
}
106+
}
107+
108+
if (Res.empty() && Recursive && EnclosingContainer)
109+
Res = EnclosingContainer->resolveName(Name, true, AlsoInvisible,
110+
OnlyVisibleAsUnqualifiedNames);
111+
112+
return Res;
113+
}
114+
115+
const Decl *conflictingDeclaration(const Decl *D,
116+
llvm::StringRef Name) const {
117+
if (Name.empty())
118+
Name = D->getName();
119+
assert(!Name.empty());
120+
121+
std::vector<Decl const *> Decls;
122+
if (Declarations.count(Name))
123+
Decls += Declarations.at(Name);
124+
125+
if (InvisibleDeclarations.count(Name))
126+
Decls += InvisibleDeclarations.at(Name);
127+
128+
if (dynamic_cast<const FunctionDecl *>(D) ||
129+
dynamic_cast<const EventDecl *>(D) ||
130+
dynamic_cast<const MagicVariableDecl *>(D)) {
131+
for (const Decl *RegDecl : Decls) {
132+
if (dynamic_cast<const FunctionDecl *>(D) &&
133+
!dynamic_cast<const FunctionDecl *>(RegDecl))
134+
return RegDecl;
135+
if (dynamic_cast<const EventDecl *>(D) &&
136+
!dynamic_cast<const EventDecl *>(RegDecl))
137+
return RegDecl;
138+
if (dynamic_cast<const MagicVariableDecl *>(D) &&
139+
!dynamic_cast<const MagicVariableDecl *>(RegDecl))
140+
return RegDecl;
141+
}
142+
} else if (Decls.size() == 1 && Decls.front() == D) {
143+
return nullptr;
144+
} else if (!Decls.empty()) {
145+
return Decls.front();
146+
}
147+
148+
return nullptr;
149+
}
150+
151+
private:
152+
const ASTNode *EnclosingNode = nullptr;
153+
const DeclarationContainer *EnclosingContainer = nullptr;
154+
std::vector<const DeclarationContainer *> InnerContainers;
155+
std::map<llvm::StringRef, std::vector<const Decl *>> Declarations;
156+
std::map<llvm::StringRef, std::vector<const Decl *>> InvisibleDeclarations;
157+
// std::vector<std::tuple<std::string, langutil::SourceLocation const*>>
158+
// m_homonymCandidates;
159+
};
160+
161+
} // 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: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
#include <map>
11+
#include <vector>
12+
13+
namespace soll {
14+
class NameAndTypeResolver {
15+
public:
16+
void setScope(const ASTNode *Node) { CurrentScope = Scopes[Node].get(); }
17+
bool resolveNamesAndTypesInternal(ASTNode *Node, bool ResolveCode);
18+
bool updateDeclaration(const Decl *D) {
19+
Scopes[nullptr]->registerDeclaration(D, false, true);
20+
return true;
21+
}
22+
23+
void activateVariable(llvm::StringRef Name) {
24+
if (CurrentScope == nullptr) {
25+
return;
26+
}
27+
if (CurrentScope->isInvisible(Name))
28+
CurrentScope->activateVariable(Name);
29+
}
30+
31+
std::vector<const Decl *> resolveName(llvm::StringRef Name,
32+
const ASTNode *Scope) const;
33+
std::vector<const Decl *>
34+
nameFromCurrentScope(llvm::StringRef Name,
35+
bool IncludeInvisibles = false) const;
36+
NameAndTypeResolver(Sema &Action, GlobalContext &GC);
37+
void Register(SourceUnit &SU);
38+
bool Resolve(SourceUnit &SU);
39+
40+
private:
41+
Sema &Action;
42+
GlobalContext &GC;
43+
std::map<const ASTNode *, std::shared_ptr<DeclarationContainer>> Scopes;
44+
DeclarationContainer *CurrentScope = nullptr;
45+
};
46+
} // namespace soll

0 commit comments

Comments
 (0)