From e3dffb611fe1736e3ffa170e6d8dc4dee17366bd Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 21 Oct 2015 00:21:52 +0200 Subject: File reorganisation. --- libsolidity/ast/AST.cpp | 365 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 libsolidity/ast/AST.cpp (limited to 'libsolidity/ast/AST.cpp') diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp new file mode 100644 index 00000000..71d80a36 --- /dev/null +++ b/libsolidity/ast/AST.cpp @@ -0,0 +1,365 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** + * @author Christian + * @date 2014 + * Solidity abstract syntax tree. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace dev; +using namespace dev::solidity; + +ASTNode::ASTNode(SourceLocation const& _location): + m_location(_location) +{ +} + +ASTNode::~ASTNode() +{ + delete m_annotation; +} + +ASTAnnotation& ASTNode::annotation() const +{ + if (!m_annotation) + m_annotation = new ASTAnnotation(); + return *m_annotation; +} + +Error ASTNode::createTypeError(string const& _description) const +{ + return Error(Error::Type::TypeError) << errinfo_sourceLocation(location()) << errinfo_comment(_description); +} + +map, FunctionTypePointer> ContractDefinition::interfaceFunctions() const +{ + auto exportedFunctionList = interfaceFunctionList(); + + map, FunctionTypePointer> exportedFunctions; + for (auto const& it: exportedFunctionList) + exportedFunctions.insert(it); + + solAssert( + exportedFunctionList.size() == exportedFunctions.size(), + "Hash collision at Function Definition Hash calculation" + ); + + return exportedFunctions; +} + +FunctionDefinition const* ContractDefinition::constructor() const +{ + for (ASTPointer const& f: m_definedFunctions) + if (f->isConstructor()) + return f.get(); + return nullptr; +} + +FunctionDefinition const* ContractDefinition::fallbackFunction() const +{ + for (ContractDefinition const* contract: annotation().linearizedBaseContracts) + for (ASTPointer const& f: contract->definedFunctions()) + if (f->name().empty()) + return f.get(); + return nullptr; +} + +vector> const& ContractDefinition::interfaceEvents() const +{ + if (!m_interfaceEvents) + { + set eventsSeen; + m_interfaceEvents.reset(new vector>()); + for (ContractDefinition const* contract: annotation().linearizedBaseContracts) + for (ASTPointer const& e: contract->events()) + if (eventsSeen.count(e->name()) == 0) + { + eventsSeen.insert(e->name()); + m_interfaceEvents->push_back(e); + } + } + return *m_interfaceEvents; +} + +vector, FunctionTypePointer>> const& ContractDefinition::interfaceFunctionList() const +{ + if (!m_interfaceFunctionList) + { + set functionsSeen; + set signaturesSeen; + m_interfaceFunctionList.reset(new vector, FunctionTypePointer>>()); + for (ContractDefinition const* contract: annotation().linearizedBaseContracts) + { + vector functions; + for (ASTPointer const& f: contract->definedFunctions()) + if (f->isPartOfExternalInterface()) + functions.push_back(make_shared(*f, false)); + for (ASTPointer const& v: contract->stateVariables()) + if (v->isPartOfExternalInterface()) + functions.push_back(make_shared(*v)); + for (FunctionTypePointer const& fun: functions) + { + if (!fun->interfaceFunctionType()) + // Fails hopefully because we already registered the error + continue; + string functionSignature = fun->externalSignature(); + if (signaturesSeen.count(functionSignature) == 0) + { + signaturesSeen.insert(functionSignature); + FixedHash<4> hash(dev::sha3(functionSignature)); + m_interfaceFunctionList->push_back(make_pair(hash, fun)); + } + } + } + } + return *m_interfaceFunctionList; +} + +string const& ContractDefinition::devDocumentation() const +{ + return m_devDocumentation; +} + +string const& ContractDefinition::userDocumentation() const +{ + return m_userDocumentation; +} + +void ContractDefinition::setDevDocumentation(string const& _devDocumentation) +{ + m_devDocumentation = _devDocumentation; +} + +void ContractDefinition::setUserDocumentation(string const& _userDocumentation) +{ + m_userDocumentation = _userDocumentation; +} + + +vector const& ContractDefinition::inheritableMembers() const +{ + if (!m_inheritableMembers) + { + set memberSeen; + m_inheritableMembers.reset(new vector()); + auto addInheritableMember = [&](Declaration const* _decl) + { + if (memberSeen.count(_decl->name()) == 0 && _decl->isVisibleInDerivedContracts()) + { + memberSeen.insert(_decl->name()); + m_inheritableMembers->push_back(_decl); + } + }; + + for (ASTPointer const& f: definedFunctions()) + addInheritableMember(f.get()); + + for (ASTPointer const& v: stateVariables()) + addInheritableMember(v.get()); + + for (ASTPointer const& s: definedStructs()) + addInheritableMember(s.get()); + } + return *m_inheritableMembers; +} + +TypePointer ContractDefinition::type(ContractDefinition const* m_currentContract) const +{ + return make_shared(make_shared(*this), m_currentContract); +} + +ContractDefinitionAnnotation& ContractDefinition::annotation() const +{ + if (!m_annotation) + m_annotation = new ContractDefinitionAnnotation(); + return static_cast(*m_annotation); +} + +TypeNameAnnotation& TypeName::annotation() const +{ + if (!m_annotation) + m_annotation = new TypeNameAnnotation(); + return static_cast(*m_annotation); +} + +TypePointer StructDefinition::type(ContractDefinition const*) const +{ + return make_shared(make_shared(*this)); +} + +TypeDeclarationAnnotation& StructDefinition::annotation() const +{ + if (!m_annotation) + m_annotation = new TypeDeclarationAnnotation(); + return static_cast(*m_annotation); +} + +TypePointer EnumValue::type(ContractDefinition const*) const +{ + auto parentDef = dynamic_cast(scope()); + solAssert(parentDef, "Enclosing Scope of EnumValue was not set"); + return make_shared(*parentDef); +} + +TypePointer EnumDefinition::type(ContractDefinition const*) const +{ + return make_shared(make_shared(*this)); +} + +TypeDeclarationAnnotation& EnumDefinition::annotation() const +{ + if (!m_annotation) + m_annotation = new TypeDeclarationAnnotation(); + return static_cast(*m_annotation); +} + +TypePointer FunctionDefinition::type(ContractDefinition const*) const +{ + return make_shared(*this); +} + +string FunctionDefinition::externalSignature() const +{ + return FunctionType(*this).externalSignature(); +} + +TypePointer ModifierDefinition::type(ContractDefinition const*) const +{ + return make_shared(*this); +} + +TypePointer EventDefinition::type(ContractDefinition const*) const +{ + return make_shared(*this); +} + +UserDefinedTypeNameAnnotation& UserDefinedTypeName::annotation() const +{ + if (!m_annotation) + m_annotation = new UserDefinedTypeNameAnnotation(); + return static_cast(*m_annotation); +} + +bool VariableDeclaration::isLValue() const +{ + // External function parameters and constant declared variables are Read-Only + return !isExternalCallableParameter() && !m_isConstant; +} + +bool VariableDeclaration::isCallableParameter() const +{ + auto const* callable = dynamic_cast(scope()); + if (!callable) + return false; + for (auto const& variable: callable->parameters()) + if (variable.get() == this) + return true; + if (callable->returnParameterList()) + for (auto const& variable: callable->returnParameterList()->parameters()) + if (variable.get() == this) + return true; + return false; +} + +bool VariableDeclaration::isExternalCallableParameter() const +{ + auto const* callable = dynamic_cast(scope()); + if (!callable || callable->visibility() != Declaration::Visibility::External) + return false; + for (auto const& variable: callable->parameters()) + if (variable.get() == this) + return true; + return false; +} + +bool VariableDeclaration::canHaveAutoType() const +{ + auto const* callable = dynamic_cast(scope()); + return (!!callable && !isCallableParameter()); +} + +TypePointer VariableDeclaration::type(ContractDefinition const*) const +{ + return annotation().type; +} + +VariableDeclarationAnnotation& VariableDeclaration::annotation() const +{ + if (!m_annotation) + m_annotation = new VariableDeclarationAnnotation(); + return static_cast(*m_annotation); +} + +ReturnAnnotation& Return::annotation() const +{ + if (!m_annotation) + m_annotation = new ReturnAnnotation(); + return static_cast(*m_annotation); +} + +VariableDeclarationStatementAnnotation& VariableDeclarationStatement::annotation() const +{ + if (!m_annotation) + m_annotation = new VariableDeclarationStatementAnnotation(); + return static_cast(*m_annotation); +} + +ExpressionAnnotation& Expression::annotation() const +{ + if (!m_annotation) + m_annotation = new ExpressionAnnotation(); + return static_cast(*m_annotation); +} + +MemberAccessAnnotation& MemberAccess::annotation() const +{ + if (!m_annotation) + m_annotation = new MemberAccessAnnotation(); + return static_cast(*m_annotation); +} + +BinaryOperationAnnotation& BinaryOperation::annotation() const +{ + if (!m_annotation) + m_annotation = new BinaryOperationAnnotation(); + return static_cast(*m_annotation); +} + +FunctionCallAnnotation& FunctionCall::annotation() const +{ + if (!m_annotation) + m_annotation = new FunctionCallAnnotation(); + return static_cast(*m_annotation); +} + +IdentifierAnnotation& Identifier::annotation() const +{ + if (!m_annotation) + m_annotation = new IdentifierAnnotation(); + return static_cast(*m_annotation); +} -- cgit v1.2.3