From 19793dab093ae36b5f2b4d1cabfbf54bed3125b1 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 21 Jan 2015 11:16:18 +0100 Subject: Function modifier parsing. --- AST.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'AST.cpp') diff --git a/AST.cpp b/AST.cpp index 82667367..a51bbd0c 100644 --- a/AST.cpp +++ b/AST.cpp @@ -183,6 +183,11 @@ string FunctionDefinition::getCanonicalSignature() const return getName() + FunctionType(*this).getCanonicalSignature(); } +void ModifierDefinition::checkTypeRequirements() +{ + m_body->checkTypeRequirements(); +} + void Block::checkTypeRequirements() { for (shared_ptr const& statement: m_statements) -- cgit v1.2.3 From 941c77c8fadd6195809cd2d572feb64478c4fb20 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 22 Jan 2015 01:02:38 +0100 Subject: Type resolution for function modifiers. --- AST.cpp | 123 ++++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 78 insertions(+), 45 deletions(-) (limited to 'AST.cpp') diff --git a/AST.cpp b/AST.cpp index a51bbd0c..85d7db6e 100644 --- a/AST.cpp +++ b/AST.cpp @@ -41,10 +41,15 @@ TypeError ASTNode::createTypeError(string const& _description) const return TypeError() << errinfo_sourceLocation(getLocation()) << errinfo_comment(_description); } +TypePointer ContractDefinition::getType(ContractDefinition const* _currentContract) const +{ + return make_shared(make_shared(*this), _currentContract); +} + void ContractDefinition::checkTypeRequirements() { - for (ASTPointer const& base: getBaseContracts()) - base->checkTypeRequirements(); + for (ASTPointer const& baseSpecifier: getBaseContracts()) + baseSpecifier->checkTypeRequirements(); checkIllegalOverrides(); @@ -53,6 +58,9 @@ void ContractDefinition::checkTypeRequirements() BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError( "Non-empty \"returns\" directive for constructor.")); + for (ASTPointer const& modifier: getFunctionModifiers()) + modifier->checkTypeRequirements(); + for (ASTPointer const& function: getDefinedFunctions()) function->checkTypeRequirements(); @@ -89,15 +97,22 @@ FunctionDefinition const* ContractDefinition::getConstructor() const void ContractDefinition::checkIllegalOverrides() const { + // TODO unify this at a later point. for this we need to put the constness and the access specifier + // into the types map functions; + map modifiers; // We search from derived to base, so the stored item causes the error. for (ContractDefinition const* contract: getLinearizedBaseContracts()) + { for (ASTPointer const& function: contract->getDefinedFunctions()) { if (function->isConstructor()) - continue; // constructors can neither be overriden nor override anything - FunctionDefinition const*& override = functions[function->getName()]; + continue; // constructors can neither be overridden nor override anything + string const& name = function->getName(); + if (modifiers.count(name)) + BOOST_THROW_EXCEPTION(modifiers[name]->createTypeError("Override changes function to modifier.")); + FunctionDefinition const*& override = functions[name]; if (!override) override = function.get(); else if (override->isPublic() != function->isPublic() || @@ -105,6 +120,18 @@ void ContractDefinition::checkIllegalOverrides() const FunctionType(*override) != FunctionType(*function)) BOOST_THROW_EXCEPTION(override->createTypeError("Override changes extended function signature.")); } + for (ASTPointer const& modifier: contract->getFunctionModifiers()) + { + string const& name = modifier->getName(); + if (functions.count(name)) + BOOST_THROW_EXCEPTION(functions[name]->createTypeError("Override changes modifier to function.")); + ModifierDefinition const*& override = modifiers[name]; + if (!override) + override = modifier.get(); + else if (ModifierType(*override) != ModifierType(*modifier)) + BOOST_THROW_EXCEPTION(override->createTypeError("Override changes modifier signature.")); + } + } } vector, FunctionDefinition const*>> const& ContractDefinition::getInterfaceFunctionList() const @@ -141,6 +168,11 @@ void InheritanceSpecifier::checkTypeRequirements() BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in constructer call.")); } +TypePointer StructDefinition::getType(ContractDefinition const*) const +{ + return make_shared(make_shared(*this)); +} + void StructDefinition::checkMemberTypes() const { for (ASTPointer const& member: getMembers()) @@ -169,11 +201,18 @@ void StructDefinition::checkRecursion() const } } +TypePointer FunctionDefinition::getType(ContractDefinition const*) const +{ + return make_shared(*this); +} + void FunctionDefinition::checkTypeRequirements() { for (ASTPointer const& var: getParameters() + getReturnParameters()) if (!var->getType()->canLiveOutsideStorage()) BOOST_THROW_EXCEPTION(var->createTypeError("Type is required to live outside storage.")); + for (ASTPointer const& modifier: m_functionModifiers) + modifier->checkTypeRequirements(); m_body->checkTypeRequirements(); } @@ -183,11 +222,40 @@ string FunctionDefinition::getCanonicalSignature() const return getName() + FunctionType(*this).getCanonicalSignature(); } +Declaration::LValueType VariableDeclaration::getLValueType() const +{ + if (dynamic_cast(getScope())) + return Declaration::LValueType::LOCAL; + else + return Declaration::LValueType::STORAGE; +} + +TypePointer ModifierDefinition::getType(ContractDefinition const*) const +{ + return make_shared(*this); +} + void ModifierDefinition::checkTypeRequirements() { m_body->checkTypeRequirements(); } +void ModifierInvocation::checkTypeRequirements() +{ + m_modifierName->checkTypeRequirements(); + for (ASTPointer const& argument: m_arguments) + argument->checkTypeRequirements(); + + ModifierDefinition const* modifier = dynamic_cast(m_modifierName->getReferencedDeclaration()); + solAssert(modifier, "Function modifier not found."); + vector> const& parameters = modifier->getParameters(); + if (parameters.size() != m_arguments.size()) + BOOST_THROW_EXCEPTION(createTypeError("Wrong argument count for modifier invocation.")); + for (size_t i = 0; i < m_arguments.size(); ++i) + if (!m_arguments[i]->getType()->isImplicitlyConvertibleTo(*parameters[i]->getType())) + BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in modifier invocation.")); +} + void Block::checkTypeRequirements() { for (shared_ptr const& statement: m_statements) @@ -399,7 +467,7 @@ void MemberAccess::checkTypeRequirements() BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found or not " "visible in " + type.toString())); //@todo later, this will not always be STORAGE - m_lvalue = type.getCategory() == Type::Category::STRUCT ? LValueType::STORAGE : LValueType::NONE; + m_lvalue = type.getCategory() == Type::Category::STRUCT ? Declaration::LValueType::STORAGE : Declaration::LValueType::NONE; } void IndexAccess::checkTypeRequirements() @@ -411,52 +479,17 @@ void IndexAccess::checkTypeRequirements() MappingType const& type = dynamic_cast(*m_base->getType()); m_index->expectType(*type.getKeyType()); m_type = type.getValueType(); - m_lvalue = LValueType::STORAGE; + m_lvalue = Declaration::LValueType::STORAGE; } void Identifier::checkTypeRequirements() { solAssert(m_referencedDeclaration, "Identifier not resolved."); - VariableDeclaration const* variable = dynamic_cast(m_referencedDeclaration); - if (variable) - { - if (!variable->getType()) - BOOST_THROW_EXCEPTION(createTypeError("Variable referenced before type could be determined.")); - m_type = variable->getType(); - m_lvalue = variable->isLocalVariable() ? LValueType::LOCAL : LValueType::STORAGE; - return; - } - //@todo can we unify these with TypeName::toType()? - StructDefinition const* structDef = dynamic_cast(m_referencedDeclaration); - if (structDef) - { - // note that we do not have a struct type here - m_type = make_shared(make_shared(*structDef)); - return; - } - FunctionDefinition const* functionDef = dynamic_cast(m_referencedDeclaration); - if (functionDef) - { - // a function reference is not a TypeType, because calling a TypeType converts to the type. - // Calling a function (e.g. function(12), otherContract.function(34)) does not do a type - // conversion. - m_type = make_shared(*functionDef); - return; - } - ContractDefinition const* contractDef = dynamic_cast(m_referencedDeclaration); - if (contractDef) - { - m_type = make_shared(make_shared(*contractDef), m_currentContract); - return; - } - MagicVariableDeclaration const* magicVariable = dynamic_cast(m_referencedDeclaration); - if (magicVariable) - { - m_type = magicVariable->getType(); - return; - } - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Declaration reference of unknown/forbidden type.")); + m_lvalue = m_referencedDeclaration->getLValueType(); + m_type = m_referencedDeclaration->getType(m_currentContract); + if (!m_type) + BOOST_THROW_EXCEPTION(createTypeError("Declaration referenced before type could be determined.")); } void ElementaryTypeNameExpression::checkTypeRequirements() -- cgit v1.2.3 From 7ded95c776717cf96e96dffb7425c86b47ad8b0e Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 23 Jan 2015 02:35:27 +0100 Subject: Compilation of function modifiers. --- AST.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'AST.cpp') diff --git a/AST.cpp b/AST.cpp index 85d7db6e..cc7da715 100644 --- a/AST.cpp +++ b/AST.cpp @@ -224,7 +224,7 @@ string FunctionDefinition::getCanonicalSignature() const Declaration::LValueType VariableDeclaration::getLValueType() const { - if (dynamic_cast(getScope())) + if (dynamic_cast(getScope()) || dynamic_cast(getScope())) return Declaration::LValueType::LOCAL; else return Declaration::LValueType::STORAGE; @@ -291,7 +291,8 @@ void Return::checkTypeRequirements() { if (!m_expression) return; - solAssert(m_returnParameters, "Return parameters not assigned."); + if (!m_returnParameters) + BOOST_THROW_EXCEPTION(createTypeError("Return arguments not allowed.")); if (m_returnParameters->getParameters().size() != 1) BOOST_THROW_EXCEPTION(createTypeError("Different number of arguments in return statement " "than in returns declaration.")); -- cgit v1.2.3