aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/ast/AST.cpp
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-10-22 19:58:50 +0800
committerchriseth <c@ethdev.com>2015-10-22 19:58:50 +0800
commitcb8f6633b237dab7d54904e00fed111c176a812c (patch)
treeb2df13e7c4c16c01b6cdc7cd5c15932031185d95 /libsolidity/ast/AST.cpp
parentd41f8b7ce702c3b25c48d27e2e895ccdcd04e4e0 (diff)
parente3dffb611fe1736e3ffa170e6d8dc4dee17366bd (diff)
downloaddexon-solidity-cb8f6633b237dab7d54904e00fed111c176a812c.tar
dexon-solidity-cb8f6633b237dab7d54904e00fed111c176a812c.tar.gz
dexon-solidity-cb8f6633b237dab7d54904e00fed111c176a812c.tar.bz2
dexon-solidity-cb8f6633b237dab7d54904e00fed111c176a812c.tar.lz
dexon-solidity-cb8f6633b237dab7d54904e00fed111c176a812c.tar.xz
dexon-solidity-cb8f6633b237dab7d54904e00fed111c176a812c.tar.zst
dexon-solidity-cb8f6633b237dab7d54904e00fed111c176a812c.zip
Merge pull request #163 from chriseth/fileReorg
File reorganisation.
Diffstat (limited to 'libsolidity/ast/AST.cpp')
-rw-r--r--libsolidity/ast/AST.cpp365
1 files changed, 365 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @author Christian <c@ethdev.com>
+ * @date 2014
+ * Solidity abstract syntax tree.
+ */
+
+#include <algorithm>
+#include <functional>
+#include <libsolidity/interface/Utils.h>
+#include <libsolidity/ast/AST.h>
+#include <libsolidity/ast/ASTVisitor.h>
+#include <libsolidity/interface/Exceptions.h>
+#include <libsolidity/ast/AST_accept.h>
+
+#include <libdevcore/SHA3.h>
+
+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<FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions() const
+{
+ auto exportedFunctionList = interfaceFunctionList();
+
+ map<FixedHash<4>, 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<FunctionDefinition> 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<FunctionDefinition> const& f: contract->definedFunctions())
+ if (f->name().empty())
+ return f.get();
+ return nullptr;
+}
+
+vector<ASTPointer<EventDefinition>> const& ContractDefinition::interfaceEvents() const
+{
+ if (!m_interfaceEvents)
+ {
+ set<string> eventsSeen;
+ m_interfaceEvents.reset(new vector<ASTPointer<EventDefinition>>());
+ for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
+ for (ASTPointer<EventDefinition> const& e: contract->events())
+ if (eventsSeen.count(e->name()) == 0)
+ {
+ eventsSeen.insert(e->name());
+ m_interfaceEvents->push_back(e);
+ }
+ }
+ return *m_interfaceEvents;
+}
+
+vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::interfaceFunctionList() const
+{
+ if (!m_interfaceFunctionList)
+ {
+ set<string> functionsSeen;
+ set<string> signaturesSeen;
+ m_interfaceFunctionList.reset(new vector<pair<FixedHash<4>, FunctionTypePointer>>());
+ for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
+ {
+ vector<FunctionTypePointer> functions;
+ for (ASTPointer<FunctionDefinition> const& f: contract->definedFunctions())
+ if (f->isPartOfExternalInterface())
+ functions.push_back(make_shared<FunctionType>(*f, false));
+ for (ASTPointer<VariableDeclaration> const& v: contract->stateVariables())
+ if (v->isPartOfExternalInterface())
+ functions.push_back(make_shared<FunctionType>(*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<Declaration const*> const& ContractDefinition::inheritableMembers() const
+{
+ if (!m_inheritableMembers)
+ {
+ set<string> memberSeen;
+ m_inheritableMembers.reset(new vector<Declaration const*>());
+ auto addInheritableMember = [&](Declaration const* _decl)
+ {
+ if (memberSeen.count(_decl->name()) == 0 && _decl->isVisibleInDerivedContracts())
+ {
+ memberSeen.insert(_decl->name());
+ m_inheritableMembers->push_back(_decl);
+ }
+ };
+
+ for (ASTPointer<FunctionDefinition> const& f: definedFunctions())
+ addInheritableMember(f.get());
+
+ for (ASTPointer<VariableDeclaration> const& v: stateVariables())
+ addInheritableMember(v.get());
+
+ for (ASTPointer<StructDefinition> const& s: definedStructs())
+ addInheritableMember(s.get());
+ }
+ return *m_inheritableMembers;
+}
+
+TypePointer ContractDefinition::type(ContractDefinition const* m_currentContract) const
+{
+ return make_shared<TypeType>(make_shared<ContractType>(*this), m_currentContract);
+}
+
+ContractDefinitionAnnotation& ContractDefinition::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new ContractDefinitionAnnotation();
+ return static_cast<ContractDefinitionAnnotation&>(*m_annotation);
+}
+
+TypeNameAnnotation& TypeName::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new TypeNameAnnotation();
+ return static_cast<TypeNameAnnotation&>(*m_annotation);
+}
+
+TypePointer StructDefinition::type(ContractDefinition const*) const
+{
+ return make_shared<TypeType>(make_shared<StructType>(*this));
+}
+
+TypeDeclarationAnnotation& StructDefinition::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new TypeDeclarationAnnotation();
+ return static_cast<TypeDeclarationAnnotation&>(*m_annotation);
+}
+
+TypePointer EnumValue::type(ContractDefinition const*) const
+{
+ auto parentDef = dynamic_cast<EnumDefinition const*>(scope());
+ solAssert(parentDef, "Enclosing Scope of EnumValue was not set");
+ return make_shared<EnumType>(*parentDef);
+}
+
+TypePointer EnumDefinition::type(ContractDefinition const*) const
+{
+ return make_shared<TypeType>(make_shared<EnumType>(*this));
+}
+
+TypeDeclarationAnnotation& EnumDefinition::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new TypeDeclarationAnnotation();
+ return static_cast<TypeDeclarationAnnotation&>(*m_annotation);
+}
+
+TypePointer FunctionDefinition::type(ContractDefinition const*) const
+{
+ return make_shared<FunctionType>(*this);
+}
+
+string FunctionDefinition::externalSignature() const
+{
+ return FunctionType(*this).externalSignature();
+}
+
+TypePointer ModifierDefinition::type(ContractDefinition const*) const
+{
+ return make_shared<ModifierType>(*this);
+}
+
+TypePointer EventDefinition::type(ContractDefinition const*) const
+{
+ return make_shared<FunctionType>(*this);
+}
+
+UserDefinedTypeNameAnnotation& UserDefinedTypeName::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new UserDefinedTypeNameAnnotation();
+ return static_cast<UserDefinedTypeNameAnnotation&>(*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<CallableDeclaration const*>(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<CallableDeclaration const*>(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<CallableDeclaration const*>(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<VariableDeclarationAnnotation&>(*m_annotation);
+}
+
+ReturnAnnotation& Return::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new ReturnAnnotation();
+ return static_cast<ReturnAnnotation&>(*m_annotation);
+}
+
+VariableDeclarationStatementAnnotation& VariableDeclarationStatement::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new VariableDeclarationStatementAnnotation();
+ return static_cast<VariableDeclarationStatementAnnotation&>(*m_annotation);
+}
+
+ExpressionAnnotation& Expression::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new ExpressionAnnotation();
+ return static_cast<ExpressionAnnotation&>(*m_annotation);
+}
+
+MemberAccessAnnotation& MemberAccess::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new MemberAccessAnnotation();
+ return static_cast<MemberAccessAnnotation&>(*m_annotation);
+}
+
+BinaryOperationAnnotation& BinaryOperation::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new BinaryOperationAnnotation();
+ return static_cast<BinaryOperationAnnotation&>(*m_annotation);
+}
+
+FunctionCallAnnotation& FunctionCall::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new FunctionCallAnnotation();
+ return static_cast<FunctionCallAnnotation&>(*m_annotation);
+}
+
+IdentifierAnnotation& Identifier::annotation() const
+{
+ if (!m_annotation)
+ m_annotation = new IdentifierAnnotation();
+ return static_cast<IdentifierAnnotation&>(*m_annotation);
+}