Skip to content

Commit d748632

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

17 files changed

+848
-11
lines changed

include/soll/ADT/STLExtras.h

Lines changed: 5 additions & 4 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

@@ -29,8 +29,9 @@ template <class Type> struct cond_const<false, Type> { typedef Type type; };
2929
/// Concatenate the contents of a container onto a vector
3030
template <class T, class U>
3131
std::vector<T> &operator+=(std::vector<T> &A, U &B) {
32-
for (auto const &I : B)
32+
for (auto const &I : B) {
3333
A.push_back(T(I));
34+
}
3435
return A;
3536
}
3637
/// Concatenate the contents of a container onto a vector, move variant.

include/soll/AST/ASTBase.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class ASTNode {
77
public:
88
enum class ASTNodeType { DECL, STMT };
99
ASTNode() = default;
10+
virtual ~ASTNode() = default;
1011
virtual ASTNodeType getASTType() = 0;
1112
};
1213

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 {

include/soll/Basic/DiagnosticSemaKinds.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,6 @@ DIAG(err_visibility_not_match, CLASS_ERROR, (unsigned)diag::Severity::Error, "vi
3333
DIAG(err_private_function_can_not_be_virtual, CLASS_ERROR, (unsigned)diag::Severity::Error, "private funtcion %0 can not be virtual", 0, false, 1)
3434
DIAG(err_mutability_overriding_not_allow, CLASS_ERROR, (unsigned)diag::Severity::Error, "can not change function %0 mutability", 0, false, 1)
3535
DIAG(err_func_to_var_overrided_unsoupport, CLASS_ERROR, (unsigned)diag::Severity::Error, "function to state variables override is unsupport", 0, false, 1)
36+
DIAG(err_use_illegalnames, CLASS_WARNING, (unsigned)diag::Severity::Warning, "Use of illegal identifier name: '%0'", 0, false, 0)
37+
DIAG(err_already_declared, CLASS_WARNING, (unsigned)diag::Severity::Warning, "identifier '%0' already declared", 0, false, 0)
38+
DIAG(err_declaration_not_found, CLASS_ERROR, (unsigned)diag::Severity::Error, "identifier '%0' not found", 0, false, 0)
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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 <map>
10+
#include <memory>
11+
#include <string>
12+
#include <vector>
13+
14+
namespace soll {
15+
16+
class DeclarationContainer {
17+
public:
18+
DeclarationContainer() = default;
19+
explicit DeclarationContainer(const ASTNode *EnclosingNode,
20+
DeclarationContainer *EnclosingContainer)
21+
: EnclosingNode(EnclosingNode), EnclosingContainer(EnclosingContainer) {
22+
if (EnclosingContainer)
23+
EnclosingContainer->InnerContainers.emplace_back(this);
24+
}
25+
26+
ASTNode const *enclosingNode() const { return EnclosingNode; }
27+
28+
void activateVariable(llvm::StringRef Name) {
29+
assert(InvisibleDeclarations.count(Name) &&
30+
InvisibleDeclarations.at(Name).size() == 1);
31+
assert(Declarations.count(Name) == 0 || Declarations.at(Name).empty());
32+
33+
Declarations[Name].emplace_back(InvisibleDeclarations.at(Name).front());
34+
InvisibleDeclarations.erase(Name);
35+
}
36+
37+
bool isInvisible(llvm::StringRef Name) const {
38+
return InvisibleDeclarations.count(Name);
39+
}
40+
41+
bool registerDeclaration(const Decl *D, bool Invisible, bool Update) {
42+
return registerDeclaration(D, llvm::StringRef(), nullptr, Invisible,
43+
Update);
44+
}
45+
46+
bool registerDeclaration(const Decl *D, llvm::StringRef Name,
47+
const SourceRange *Loc, bool Invisible,
48+
bool Update) {
49+
if (Name.empty()) {
50+
Name = D->getName();
51+
}
52+
53+
if (Name.empty())
54+
return true;
55+
56+
if (Update) {
57+
assert(!dynamic_cast<const FunctionDecl *>(D) &&
58+
"Attempt to update function definition.");
59+
Declarations.erase(Name);
60+
InvisibleDeclarations.erase(Name);
61+
return true;
62+
} else {
63+
if (conflictingDeclaration(D, Name))
64+
return false;
65+
if (EnclosingContainer && D->isVisibleAsUnqualifiedName()) {
66+
// TODO: isVisibleAsUnqualifiedName for struct not merged yet.
67+
// It use old path to handle
68+
}
69+
}
70+
71+
std::vector<const Decl *> &Decls =
72+
Invisible ? InvisibleDeclarations[Name] : Declarations[Name];
73+
if (find(Decls.begin(), Decls.end(), D) == Decls.end())
74+
Decls.emplace_back(D);
75+
return true;
76+
}
77+
78+
std::vector<const Decl *>
79+
resolveName(llvm::StringRef Name, bool Recursive = false,
80+
bool AlsoInvisible = false,
81+
bool OnlyVisibleAsUnqualifiedNames = false) const {
82+
std::vector<const Decl *> Res;
83+
84+
if (Declarations.count(Name)) {
85+
for (auto E : Declarations.at(Name)) {
86+
if (OnlyVisibleAsUnqualifiedNames) {
87+
if (!E->isVisibleAsUnqualifiedName())
88+
continue;
89+
}
90+
Res.emplace_back(E);
91+
}
92+
}
93+
94+
if (AlsoInvisible && InvisibleDeclarations.count(Name)) {
95+
for (auto E : InvisibleDeclarations.at(Name)) {
96+
if (OnlyVisibleAsUnqualifiedNames) {
97+
if (!E->isVisibleAsUnqualifiedName())
98+
continue;
99+
}
100+
Res.emplace_back(E);
101+
}
102+
}
103+
104+
if (Res.empty() && Recursive && EnclosingContainer)
105+
Res = EnclosingContainer->resolveName(Name, true, AlsoInvisible,
106+
OnlyVisibleAsUnqualifiedNames);
107+
108+
return Res;
109+
}
110+
111+
const Decl *conflictingDeclaration(const Decl *D,
112+
llvm::StringRef Name) const {
113+
if (Name.empty())
114+
Name = D->getName();
115+
assert(!Name.empty());
116+
117+
std::vector<Decl const *> Decls;
118+
if (Declarations.count(Name))
119+
Decls += Declarations.at(Name);
120+
121+
if (InvisibleDeclarations.count(Name))
122+
Decls += InvisibleDeclarations.at(Name);
123+
124+
if (dynamic_cast<const FunctionDecl *>(D) ||
125+
dynamic_cast<const EventDecl *>(D) ||
126+
dynamic_cast<const MagicVariableDecl *>(D)) {
127+
for (const Decl *RegDecl : Decls) {
128+
if (dynamic_cast<const FunctionDecl *>(D) &&
129+
!dynamic_cast<const FunctionDecl *>(RegDecl))
130+
return RegDecl;
131+
if (dynamic_cast<const EventDecl *>(D) &&
132+
!dynamic_cast<const EventDecl *>(RegDecl))
133+
return RegDecl;
134+
if (dynamic_cast<const MagicVariableDecl *>(D) &&
135+
!dynamic_cast<const MagicVariableDecl *>(RegDecl))
136+
return RegDecl;
137+
}
138+
} else if (Decls.size() == 1 && Decls.front() == D) {
139+
return nullptr;
140+
} else if (!Decls.empty()) {
141+
return Decls.front();
142+
}
143+
144+
return nullptr;
145+
}
146+
147+
private:
148+
const ASTNode *EnclosingNode = nullptr;
149+
const DeclarationContainer *EnclosingContainer = nullptr;
150+
std::vector<const DeclarationContainer *> InnerContainers;
151+
std::map<llvm::StringRef, std::vector<const Decl *>> Declarations;
152+
std::map<llvm::StringRef, std::vector<const Decl *>> InvisibleDeclarations;
153+
};
154+
155+
} // namespace soll

include/soll/Sema/GlobalContent.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
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 <map>
10+
#include <memory>
11+
#include <string>
12+
#include <vector>
13+
14+
namespace soll {
15+
/// Magic variables get negative ids for easy differentiation
16+
namespace {
17+
int magicVariableToID(std::string const &_name) {
18+
if (_name == "abi")
19+
return -1;
20+
else if (_name == "addmod")
21+
return -2;
22+
else if (_name == "assert")
23+
return -3;
24+
else if (_name == "block")
25+
return -4;
26+
else if (_name == "blockhash")
27+
return -5;
28+
else if (_name == "ecrecover")
29+
return -6;
30+
else if (_name == "gasleft")
31+
return -7;
32+
else if (_name == "keccak256")
33+
return -8;
34+
else if (_name == "msg")
35+
return -15;
36+
else if (_name == "mulmod")
37+
return -16;
38+
else if (_name == "now")
39+
return -17;
40+
else if (_name == "require")
41+
return -18;
42+
else if (_name == "revert")
43+
return -19;
44+
else if (_name == "ripemd160")
45+
return -20;
46+
else if (_name == "selfdestruct")
47+
return -21;
48+
else if (_name == "sha256")
49+
return -22;
50+
else if (_name == "sha3")
51+
return -23;
52+
else if (_name == "suicide")
53+
return -24;
54+
else if (_name == "super")
55+
return -25;
56+
else if (_name == "tx")
57+
return -26;
58+
else if (_name == "type")
59+
return -27;
60+
else if (_name == "this")
61+
return -28;
62+
else
63+
__builtin_unreachable();
64+
}
65+
} // namespace
66+
67+
class GlobalContext {
68+
public:
69+
void setCurrentContract(const ContractDecl *Cont) { CurrentContract = Cont; }
70+
void resetCurrentContract() { CurrentContract = nullptr; }
71+
const MagicVariableDecl *currentThis() {
72+
if (!ThisCache[CurrentContract]) {
73+
TypePtr Type = CurrentContract->getType();
74+
ThisCache[CurrentContract] = std::make_shared<MagicVariableDecl>(
75+
magicVariableToID("this"), "this", Type);
76+
}
77+
return ThisCache[CurrentContract].get();
78+
}
79+
80+
const MagicVariableDecl *currentSuper() {
81+
assert(false && "unimp currentSuper");
82+
return nullptr;
83+
}
84+
85+
GlobalContext() = default;
86+
GlobalContext(const GlobalContext &) = delete;
87+
~GlobalContext() = default;
88+
89+
private:
90+
const ContractDecl *CurrentContract = nullptr;
91+
std::map<const ContractDecl *, std::shared_ptr<MagicVariableDecl>> ThisCache;
92+
std::map<const ContractDecl *, std::shared_ptr<MagicVariableDecl>> SuperCache;
93+
};
94+
} // 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)