aboutsummaryrefslogtreecommitdiffstats
path: root/AST.cpp
diff options
context:
space:
mode:
authorLefteris Karapetsas <lefteris@refu.co>2015-03-27 22:15:34 +0800
committerLefteris Karapetsas <lefteris@refu.co>2015-03-27 22:15:34 +0800
commit85bb056993ccb111b7e32e28475b906f75b77aa6 (patch)
treee401f72dd8d2ee621b2908bc24f1428687e6c16e /AST.cpp
parenta7e78fadf5d8fd4d1d4300a4d8064d9bf51af687 (diff)
downloaddexon-solidity-85bb056993ccb111b7e32e28475b906f75b77aa6.tar.gz
dexon-solidity-85bb056993ccb111b7e32e28475b906f75b77aa6.tar.zst
dexon-solidity-85bb056993ccb111b7e32e28475b906f75b77aa6.zip
Abstract contract and inheritance
- Checking the linearized base contracts for abstract functions and handle their existence appropriately - If a contract is abstract it can't be created with new - An abstract contract is not compiled (no backend code is generated) - Of course tests
Diffstat (limited to 'AST.cpp')
-rw-r--r--AST.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/AST.cpp b/AST.cpp
index 52c58170..2ada7362 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -21,6 +21,7 @@
*/
#include <algorithm>
+#include <boost/range/adaptor/reversed.hpp>
#include <libsolidity/Utils.h>
#include <libsolidity/AST.h>
#include <libsolidity/ASTVisitor.h>
@@ -52,6 +53,7 @@ void ContractDefinition::checkTypeRequirements()
baseSpecifier->checkTypeRequirements();
checkIllegalOverrides();
+ checkAbstractFunctions();
FunctionDefinition const* constructor = getConstructor();
if (constructor && !constructor->getReturnParameters().empty())
@@ -128,6 +130,42 @@ FunctionDefinition const* ContractDefinition::getFallbackFunction() const
return nullptr;
}
+void ContractDefinition::checkAbstractFunctions()
+{
+ map<string, bool> functions;
+
+ // Search from base to derived
+ for (ContractDefinition const* contract: boost::adaptors::reverse(getLinearizedBaseContracts()))
+ {
+ for (ASTPointer<FunctionDefinition> const& function: contract->getDefinedFunctions())
+ {
+ string const& name = function->getName();
+ if (!function->isFullyImplemented() && functions.count(name) && functions[name])
+ BOOST_THROW_EXCEPTION(function->createTypeError("Redeclaring an already implemented function as abstract"));
+ // if (functions.count(name) && !functions[name] && function->isFullyImplemented())
+ // functions.insert(make_pair(name, true);
+
+ // if (functions.count(name) && !functions[name] && function->isFullyImplemented)
+ // functions.insert(make_pair(name, true));
+
+ // functions.insert(make_pair(name, function->isFullyImplemented()));
+ functions[name] = function->isFullyImplemented();
+
+ // if (function->isFullyImplemented())
+ // full_functions.insert(make_pair(name, function.get()));
+ // else
+ // abs_functions.insert(make_pair(name, function.get()));
+ }
+ }
+ for (auto const& it: functions)
+ if (!it.second)
+ {
+ setFullyImplemented(false);
+ break;
+ }
+
+}
+
void ContractDefinition::checkIllegalOverrides() const
{
// TODO unify this at a later point. for this we need to put the constness and the access specifier
@@ -643,6 +681,8 @@ void NewExpression::checkTypeRequirements()
m_contract = dynamic_cast<ContractDefinition const*>(m_contractName->getReferencedDeclaration());
if (!m_contract)
BOOST_THROW_EXCEPTION(createTypeError("Identifier is not a contract."));
+ if (!m_contract->isFullyImplemented())
+ BOOST_THROW_EXCEPTION(m_contract->createTypeError("Trying to create an object of an abstract contract."));
shared_ptr<ContractType const> contractType = make_shared<ContractType>(*m_contract);
TypePointers const& parameterTypes = contractType->getConstructorType()->getParameterTypes();
m_type = make_shared<FunctionType>(parameterTypes, TypePointers{contractType},