Skip to content

Commit 7bd569b

Browse files
committed
[Sema] NameAndTypeResolver
1 parent fcbb73d commit 7bd569b

File tree

14 files changed

+769
-7
lines changed

14 files changed

+769
-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/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: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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+
80+
return true;
81+
}
82+
83+
const Decl *conflictingDeclaration(const Decl *D,
84+
llvm::StringRef Name) const {
85+
if (Name.empty())
86+
Name = D->getName();
87+
assert(!Name.empty());
88+
89+
std::vector<Decl const *> Decls;
90+
if (Declarations.count(Name))
91+
Decls += Declarations.at(Name);
92+
93+
if (InvisibleDeclarations.count(Name))
94+
Decls += InvisibleDeclarations.at(Name);
95+
96+
if (dynamic_cast<const FunctionDecl *>(D) ||
97+
dynamic_cast<const EventDecl *>(D) ||
98+
dynamic_cast<const MagicVariableDecl *>(D)) {
99+
for (const Decl *RegDecl : Decls) {
100+
if (dynamic_cast<const FunctionDecl *>(D) &&
101+
!dynamic_cast<const FunctionDecl *>(RegDecl))
102+
return RegDecl;
103+
if (dynamic_cast<const EventDecl *>(D) &&
104+
!dynamic_cast<const EventDecl *>(RegDecl))
105+
return RegDecl;
106+
if (dynamic_cast<const MagicVariableDecl *>(D) &&
107+
!dynamic_cast<const MagicVariableDecl *>(RegDecl))
108+
return RegDecl;
109+
}
110+
} else if (Decls.size() == 1 && Decls.front() == D) {
111+
return nullptr;
112+
} else if (!Decls.empty()) {
113+
return Decls.front();
114+
}
115+
116+
return nullptr;
117+
}
118+
119+
private:
120+
const ASTNode *EnclosingNode = nullptr;
121+
const DeclarationContainer *EnclosingContainer = nullptr;
122+
std::vector<const DeclarationContainer *> InnerContainers;
123+
std::map<llvm::StringRef, std::vector<const Decl *>> Declarations;
124+
std::map<llvm::StringRef, std::vector<const Decl *>> InvisibleDeclarations;
125+
// std::vector<std::tuple<std::string, langutil::SourceLocation const*>>
126+
// m_homonymCandidates;
127+
};
128+
129+
} // 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: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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+
public:
13+
void setScope(const ASTNode *Node) { CurrentScope = Scopes[Node].get(); }
14+
bool resolveNamesAndTypesInternal(ASTNode *Node, bool ResolveCode);
15+
bool updateDeclaration(const Decl *D) {
16+
Scopes[nullptr]->registerDeclaration(D, false, true);
17+
return true;
18+
}
19+
20+
void activateVariable(llvm::StringRef Name) {
21+
cerr << "Find " << Name.str() << endl;
22+
if (CurrentScope == nullptr) {
23+
cerr << "jizz" << endl;
24+
return;
25+
}
26+
if (CurrentScope->isInvisible(Name))
27+
CurrentScope->activateVariable(Name);
28+
}
29+
30+
NameAndTypeResolver(Sema &Action, GlobalContext &GC);
31+
void Register(SourceUnit &SU);
32+
bool Resolve(SourceUnit &SU);
33+
34+
private:
35+
Sema &Action;
36+
GlobalContext &GC;
37+
std::map<const ASTNode *, std::shared_ptr<DeclarationContainer>> Scopes;
38+
DeclarationContainer *CurrentScope = nullptr;
39+
};
40+
} // namespace soll
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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+
void visit(Block &B) override;
25+
void visit(ForStmt &F) override;
26+
void visit(DeclStmt &D) override;
27+
28+
void visit(FunctionDecl &FD) override;
29+
30+
private:
31+
Sema &Action;
32+
NameAndTypeResolver &Resolver;
33+
bool ResolveInsideCode;
34+
bool Status;
35+
};
36+
37+
} // namespace soll

0 commit comments

Comments
 (0)