-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
848 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
#pragma once | ||
|
||
#include "soll/AST/AST.h" | ||
#include "soll/AST/Decl.h" | ||
#include "soll/Basic/DiagnosticSema.h" | ||
#include "soll/Sema/Sema.h" | ||
|
||
#include <map> | ||
#include <memory> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace soll { | ||
|
||
class DeclarationContainer { | ||
public: | ||
DeclarationContainer() = default; | ||
explicit DeclarationContainer(const ASTNode *EnclosingNode, | ||
DeclarationContainer *EnclosingContainer) | ||
: EnclosingNode(EnclosingNode), EnclosingContainer(EnclosingContainer) { | ||
if (EnclosingContainer) | ||
EnclosingContainer->InnerContainers.emplace_back(this); | ||
} | ||
|
||
ASTNode const *enclosingNode() const { return EnclosingNode; } | ||
|
||
void activateVariable(llvm::StringRef Name) { | ||
assert(InvisibleDeclarations.count(Name) && | ||
InvisibleDeclarations.at(Name).size() == 1); | ||
assert(Declarations.count(Name) == 0 || Declarations.at(Name).empty()); | ||
|
||
Declarations[Name].emplace_back(InvisibleDeclarations.at(Name).front()); | ||
InvisibleDeclarations.erase(Name); | ||
} | ||
|
||
bool isInvisible(llvm::StringRef Name) const { | ||
return InvisibleDeclarations.count(Name); | ||
} | ||
|
||
bool registerDeclaration(const Decl *D, bool Invisible, bool Update) { | ||
return registerDeclaration(D, llvm::StringRef(), nullptr, Invisible, | ||
Update); | ||
} | ||
|
||
bool registerDeclaration(const Decl *D, llvm::StringRef Name, | ||
const SourceRange *Loc, bool Invisible, | ||
bool Update) { | ||
if (Name.empty()) { | ||
Name = D->getName(); | ||
} | ||
|
||
if (Name.empty()) | ||
return true; | ||
|
||
if (Update) { | ||
assert(!dynamic_cast<const FunctionDecl *>(D) && | ||
"Attempt to update function definition."); | ||
Declarations.erase(Name); | ||
InvisibleDeclarations.erase(Name); | ||
return true; | ||
} else { | ||
if (conflictingDeclaration(D, Name)) | ||
return false; | ||
if (EnclosingContainer && D->isVisibleAsUnqualifiedName()) { | ||
// TODO: isVisibleAsUnqualifiedName for struct not merged yet. | ||
// It use old path to handle | ||
} | ||
} | ||
|
||
std::vector<const Decl *> &Decls = | ||
Invisible ? InvisibleDeclarations[Name] : Declarations[Name]; | ||
if (find(Decls.begin(), Decls.end(), D) == Decls.end()) | ||
Decls.emplace_back(D); | ||
return true; | ||
} | ||
|
||
std::vector<const Decl *> | ||
resolveName(llvm::StringRef Name, bool Recursive = false, | ||
bool AlsoInvisible = false, | ||
bool OnlyVisibleAsUnqualifiedNames = false) const { | ||
std::vector<const Decl *> Res; | ||
|
||
if (Declarations.count(Name)) { | ||
for (auto E : Declarations.at(Name)) { | ||
if (OnlyVisibleAsUnqualifiedNames) { | ||
if (!E->isVisibleAsUnqualifiedName()) | ||
continue; | ||
} | ||
Res.emplace_back(E); | ||
} | ||
} | ||
|
||
if (AlsoInvisible && InvisibleDeclarations.count(Name)) { | ||
for (auto E : InvisibleDeclarations.at(Name)) { | ||
if (OnlyVisibleAsUnqualifiedNames) { | ||
if (!E->isVisibleAsUnqualifiedName()) | ||
continue; | ||
} | ||
Res.emplace_back(E); | ||
} | ||
} | ||
|
||
if (Res.empty() && Recursive && EnclosingContainer) | ||
Res = EnclosingContainer->resolveName(Name, true, AlsoInvisible, | ||
OnlyVisibleAsUnqualifiedNames); | ||
|
||
return Res; | ||
} | ||
|
||
const Decl *conflictingDeclaration(const Decl *D, | ||
llvm::StringRef Name) const { | ||
if (Name.empty()) | ||
Name = D->getName(); | ||
assert(!Name.empty()); | ||
|
||
std::vector<Decl const *> Decls; | ||
if (Declarations.count(Name)) | ||
Decls += Declarations.at(Name); | ||
|
||
if (InvisibleDeclarations.count(Name)) | ||
Decls += InvisibleDeclarations.at(Name); | ||
|
||
if (dynamic_cast<const FunctionDecl *>(D) || | ||
dynamic_cast<const EventDecl *>(D) || | ||
dynamic_cast<const MagicVariableDecl *>(D)) { | ||
for (const Decl *RegDecl : Decls) { | ||
if (dynamic_cast<const FunctionDecl *>(D) && | ||
!dynamic_cast<const FunctionDecl *>(RegDecl)) | ||
return RegDecl; | ||
if (dynamic_cast<const EventDecl *>(D) && | ||
!dynamic_cast<const EventDecl *>(RegDecl)) | ||
return RegDecl; | ||
if (dynamic_cast<const MagicVariableDecl *>(D) && | ||
!dynamic_cast<const MagicVariableDecl *>(RegDecl)) | ||
return RegDecl; | ||
} | ||
} else if (Decls.size() == 1 && Decls.front() == D) { | ||
return nullptr; | ||
} else if (!Decls.empty()) { | ||
return Decls.front(); | ||
} | ||
|
||
return nullptr; | ||
} | ||
|
||
private: | ||
const ASTNode *EnclosingNode = nullptr; | ||
const DeclarationContainer *EnclosingContainer = nullptr; | ||
std::vector<const DeclarationContainer *> InnerContainers; | ||
std::map<llvm::StringRef, std::vector<const Decl *>> Declarations; | ||
std::map<llvm::StringRef, std::vector<const Decl *>> InvisibleDeclarations; | ||
}; | ||
|
||
} // namespace soll |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
#pragma once | ||
|
||
#include "soll/AST/AST.h" | ||
#include "soll/AST/Decl.h" | ||
#include "soll/Basic/DiagnosticSema.h" | ||
#include "soll/Sema/Sema.h" | ||
|
||
#include <map> | ||
#include <memory> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace soll { | ||
/// Magic variables get negative ids for easy differentiation | ||
namespace { | ||
int magicVariableToID(std::string const &_name) { | ||
if (_name == "abi") | ||
return -1; | ||
else if (_name == "addmod") | ||
return -2; | ||
else if (_name == "assert") | ||
return -3; | ||
else if (_name == "block") | ||
return -4; | ||
else if (_name == "blockhash") | ||
return -5; | ||
else if (_name == "ecrecover") | ||
return -6; | ||
else if (_name == "gasleft") | ||
return -7; | ||
else if (_name == "keccak256") | ||
return -8; | ||
else if (_name == "msg") | ||
return -15; | ||
else if (_name == "mulmod") | ||
return -16; | ||
else if (_name == "now") | ||
return -17; | ||
else if (_name == "require") | ||
return -18; | ||
else if (_name == "revert") | ||
return -19; | ||
else if (_name == "ripemd160") | ||
return -20; | ||
else if (_name == "selfdestruct") | ||
return -21; | ||
else if (_name == "sha256") | ||
return -22; | ||
else if (_name == "sha3") | ||
return -23; | ||
else if (_name == "suicide") | ||
return -24; | ||
else if (_name == "super") | ||
return -25; | ||
else if (_name == "tx") | ||
return -26; | ||
else if (_name == "type") | ||
return -27; | ||
else if (_name == "this") | ||
return -28; | ||
else | ||
__builtin_unreachable(); | ||
} | ||
} // namespace | ||
|
||
class GlobalContext { | ||
public: | ||
void setCurrentContract(const ContractDecl *Cont) { CurrentContract = Cont; } | ||
void resetCurrentContract() { CurrentContract = nullptr; } | ||
const MagicVariableDecl *currentThis() { | ||
if (!ThisCache[CurrentContract]) { | ||
TypePtr Type = CurrentContract->getType(); | ||
ThisCache[CurrentContract] = std::make_shared<MagicVariableDecl>( | ||
magicVariableToID("this"), "this", Type); | ||
} | ||
return ThisCache[CurrentContract].get(); | ||
} | ||
|
||
const MagicVariableDecl *currentSuper() { | ||
assert(false && "unimp currentSuper"); | ||
return nullptr; | ||
} | ||
|
||
GlobalContext() = default; | ||
GlobalContext(const GlobalContext &) = delete; | ||
~GlobalContext() = default; | ||
|
||
private: | ||
const ContractDecl *CurrentContract = nullptr; | ||
std::map<const ContractDecl *, std::shared_ptr<MagicVariableDecl>> ThisCache; | ||
std::map<const ContractDecl *, std::shared_ptr<MagicVariableDecl>> SuperCache; | ||
}; | ||
} // namespace soll |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
#pragma once | ||
|
||
#include "soll/AST/AST.h" | ||
#include "soll/AST/Decl.h" | ||
#include "soll/Basic/DiagnosticSema.h" | ||
#include "soll/Sema/DeclarationContainer.h" | ||
#include "soll/Sema/Sema.h" | ||
|
||
#include <map> | ||
#include <vector> | ||
|
||
namespace soll { | ||
class NameAndTypeResolver { | ||
public: | ||
void setScope(const ASTNode *Node) { CurrentScope = Scopes[Node].get(); } | ||
bool resolveNamesAndTypesInternal(ASTNode *Node, bool ResolveCode); | ||
bool updateDeclaration(const Decl *D) { | ||
Scopes[nullptr]->registerDeclaration(D, false, true); | ||
return true; | ||
} | ||
|
||
void activateVariable(llvm::StringRef Name) { | ||
if (CurrentScope == nullptr) { | ||
return; | ||
} | ||
if (CurrentScope->isInvisible(Name)) | ||
CurrentScope->activateVariable(Name); | ||
} | ||
|
||
std::vector<const Decl *> resolveName(llvm::StringRef Name, | ||
const ASTNode *Scope) const; | ||
std::vector<const Decl *> | ||
nameFromCurrentScope(llvm::StringRef Name, | ||
bool IncludeInvisibles = false) const; | ||
NameAndTypeResolver(Sema &Action, GlobalContext &GC); | ||
void Register(SourceUnit &SU); | ||
bool Resolve(SourceUnit &SU); | ||
|
||
private: | ||
Sema &Action; | ||
GlobalContext &GC; | ||
std::map<const ASTNode *, std::shared_ptr<DeclarationContainer>> Scopes; | ||
DeclarationContainer *CurrentScope = nullptr; | ||
}; | ||
} // namespace soll |
Oops, something went wrong.