Do not store elements of a contract by AST node type.

This commit is contained in:
chriseth
2015-11-26 15:37:55 +01:00
parent 86495dfc57
commit b47d593252
14 changed files with 141 additions and 152 deletions
+7 -31
View File
@@ -84,35 +84,11 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
importInheritedScope(*base);
}
for (ASTPointer<StructDefinition> const& structDef: _contract.definedStructs())
if (!resolver.resolve(*structDef))
success = false;
for (ASTPointer<EnumDefinition> const& enumDef: _contract.definedEnums())
if (!resolver.resolve(*enumDef))
success = false;
for (ASTPointer<VariableDeclaration> const& variable: _contract.stateVariables())
if (!resolver.resolve(*variable))
success = false;
for (ASTPointer<EventDefinition> const& event: _contract.events())
if (!resolver.resolve(*event))
success = false;
// these can contain code, only resolve parameters for now
for (ASTPointer<ModifierDefinition> const& modifier: _contract.functionModifiers())
for (ASTPointer<ASTNode> const& node: _contract.subNodes())
{
m_currentScope = &m_scopes[modifier.get()];
ReferencesResolver resolver(m_errors, *this, nullptr);
if (!resolver.resolve(*modifier))
success = false;
}
for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions())
{
m_currentScope = &m_scopes[function.get()];
if (!ReferencesResolver(
m_errors,
*this,
function->returnParameterList().get()
).resolve(*function))
m_currentScope = &m_scopes[m_scopes.count(node.get()) ? node.get() : &_contract];
if (!resolver.resolve(*node))
success = false;
}
@@ -122,17 +98,17 @@ bool NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
m_currentScope = &m_scopes[&_contract];
// now resolve references inside the code
for (ASTPointer<ModifierDefinition> const& modifier: _contract.functionModifiers())
for (ModifierDefinition const* modifier: _contract.functionModifiers())
{
m_currentScope = &m_scopes[modifier.get()];
m_currentScope = &m_scopes[modifier];
ReferencesResolver resolver(m_errors, *this, nullptr, true);
if (!resolver.resolve(*modifier))
success = false;
}
for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions())
for (FunctionDefinition const* function: _contract.definedFunctions())
{
m_currentScope = &m_scopes[function.get()];
m_currentScope = &m_scopes[function];
if (!ReferencesResolver(
m_errors,
*this,
+1 -1
View File
@@ -53,7 +53,7 @@ bool ReferencesResolver::visit(UserDefinedTypeName const& _typeName)
return true;
}
bool ReferencesResolver::resolve(ASTNode& _root)
bool ReferencesResolver::resolve(ASTNode const& _root)
{
try
{
+1 -1
View File
@@ -55,7 +55,7 @@ public:
{}
/// @returns true if no errors during resolving
bool resolve(ASTNode& _root);
bool resolve(ASTNode const& _root);
private:
virtual bool visit(Block const&) override { return m_resolveInsideCode; }
+15 -17
View File
@@ -63,6 +63,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
m_scope = &_contract;
// We force our own visiting order here.
//@TODO structs will be visited again below, but it is probably fine.
ASTNode::listAccept(_contract.definedStructs(), *this);
ASTNode::listAccept(_contract.baseContracts(), *this);
@@ -76,7 +77,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
typeError(function->returnParameterList()->location(), "Non-empty \"returns\" directive for constructor.");
FunctionDefinition const* fallbackFunction = nullptr;
for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions())
for (FunctionDefinition const* function: _contract.definedFunctions())
{
if (function->name().empty())
{
@@ -88,7 +89,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
}
else
{
fallbackFunction = function.get();
fallbackFunction = function;
if (!fallbackFunction->parameters().empty())
typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
}
@@ -97,10 +98,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
_contract.annotation().isFullyImplemented = false;
}
ASTNode::listAccept(_contract.stateVariables(), *this);
ASTNode::listAccept(_contract.events(), *this);
ASTNode::listAccept(_contract.functionModifiers(), *this);
ASTNode::listAccept(_contract.definedFunctions(), *this);
ASTNode::listAccept(_contract.subNodes(), *this);
checkContractExternalTypeClashes(_contract);
// check for hash collisions in function signatures
@@ -127,8 +125,8 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con
/// Checks that two functions with the same name defined in this contract have different
/// argument types and that there is at most one constructor.
map<string, vector<FunctionDefinition const*>> functions;
for (ASTPointer<FunctionDefinition> const& function: _contract.definedFunctions())
functions[function->name()].push_back(function.get());
for (FunctionDefinition const* function: _contract.definedFunctions())
functions[function->name()].push_back(function);
// Constructor
if (functions[_contract.name()].size() > 1)
@@ -172,7 +170,7 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont
// Search from base to derived
for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts))
for (ASTPointer<FunctionDefinition> const& function: contract->definedFunctions())
for (FunctionDefinition const* function: contract->definedFunctions())
{
auto& overloads = functions[function->name()];
FunctionTypePointer funType = make_shared<FunctionType>(*function);
@@ -248,7 +246,7 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr
// We search from derived to base, so the stored item causes the error.
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
{
for (ASTPointer<FunctionDefinition> const& function: contract->definedFunctions())
for (FunctionDefinition const* function: contract->definedFunctions())
{
if (function->isConstructor())
continue; // constructors can neither be overridden nor override anything
@@ -269,14 +267,14 @@ void TypeChecker::checkContractIllegalOverrides(ContractDefinition const& _contr
)
typeError(overriding->location(), "Override changes extended function signature.");
}
functions[name].push_back(function.get());
functions[name].push_back(function);
}
for (ASTPointer<ModifierDefinition> const& modifier: contract->functionModifiers())
for (ModifierDefinition const* modifier: contract->functionModifiers())
{
string const& name = modifier->name();
ModifierDefinition const*& override = modifiers[name];
if (!override)
override = modifier.get();
override = modifier;
else if (ModifierType(*override) != ModifierType(*modifier))
typeError(override->location(), "Override changes modifier signature.");
if (!functions[name].empty())
@@ -290,20 +288,20 @@ void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _co
map<string, vector<pair<Declaration const*, FunctionTypePointer>>> externalDeclarations;
for (ContractDefinition const* contract: _contract.annotation().linearizedBaseContracts)
{
for (ASTPointer<FunctionDefinition> const& f: contract->definedFunctions())
for (FunctionDefinition const* f: contract->definedFunctions())
if (f->isPartOfExternalInterface())
{
auto functionType = make_shared<FunctionType>(*f);
externalDeclarations[functionType->externalSignature()].push_back(
make_pair(f.get(), functionType)
make_pair(f, functionType)
);
}
for (ASTPointer<VariableDeclaration> const& v: contract->stateVariables())
for (VariableDeclaration const* v: contract->stateVariables())
if (v->isPartOfExternalInterface())
{
auto functionType = make_shared<FunctionType>(*v);
externalDeclarations[functionType->externalSignature()].push_back(
make_pair(v.get(), functionType)
make_pair(v, functionType)
);
}
}