diff options
author | Christian <c@ethdev.com> | 2014-11-11 00:31:09 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2014-11-14 21:08:14 +0800 |
commit | 46dd62982084dfe5712292b88047d2a58e0a420e (patch) | |
tree | fda7b3871e7de54cbb4cdab8cf3add6ff6090f42 /AST.cpp | |
parent | c4a65cf6888f6b15fa7740b6db5d9dae8f18b7ba (diff) | |
download | dexon-solidity-46dd62982084dfe5712292b88047d2a58e0a420e.tar.gz dexon-solidity-46dd62982084dfe5712292b88047d2a58e0a420e.tar.zst dexon-solidity-46dd62982084dfe5712292b88047d2a58e0a420e.zip |
Mapping types.
Diffstat (limited to 'AST.cpp')
-rw-r--r-- | AST.cpp | 40 |
1 files changed, 33 insertions, 7 deletions
@@ -278,6 +278,15 @@ vector<FunctionDefinition const*> ContractDefinition::getInterfaceFunctions() co return exportedFunctions; } +void FunctionDefinition::checkTypeRequirements() +{ + for (ASTPointer<VariableDeclaration> const& var: getParameters() + getReturnParameters()) + if (!var->getType()->canLiveOutsideStorage()) + BOOST_THROW_EXCEPTION(var->createTypeError("Type is required to live outside storage.")); + + m_body->checkTypeRequirements(); +} + void Block::checkTypeRequirements() { for (shared_ptr<Statement> const& statement: m_statements) @@ -315,7 +324,7 @@ void Return::checkTypeRequirements() void VariableDefinition::checkTypeRequirements() { // Variables can be declared without type (with "var"), in which case the first assignment - // setsthe type. + // sets the type. // Note that assignments before the first declaration are legal because of the special scoping // rules inherited from JavaScript. if (m_value) @@ -329,13 +338,14 @@ void VariableDefinition::checkTypeRequirements() m_variable->setType(m_value->getType()); } } + if (m_variable->getType() && !m_variable->getType()->canLiveOutsideStorage()) + BOOST_THROW_EXCEPTION(m_variable->createTypeError("Type is required to live outside storage.")); } void Assignment::checkTypeRequirements() { m_leftHandSide->checkTypeRequirements(); - if (!m_leftHandSide->isLvalue()) - BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue.")); + m_leftHandSide->requireLValue(); m_rightHandSide->expectType(*m_leftHandSide->getType()); m_type = m_leftHandSide->getType(); if (m_assigmentOperator != Token::ASSIGN) @@ -359,13 +369,19 @@ void Expression::expectType(Type const& _expectedType) + _expectedType.toString() + ".")); } +void Expression::requireLValue() +{ + if (!isLvalue()) + BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue.")); + m_lvalueRequested = true; +} + void UnaryOperation::checkTypeRequirements() { // INC, DEC, ADD, SUB, NOT, BIT_NOT, DELETE m_subExpression->checkTypeRequirements(); if (m_operator == Token::Value::INC || m_operator == Token::Value::DEC || m_operator == Token::Value::DELETE) - if (!m_subExpression->isLvalue()) - BOOST_THROW_EXCEPTION(createTypeError("Expression has to be an lvalue.")); + m_subExpression->requireLValue(); m_type = m_subExpression->getType(); if (!m_type->acceptsUnaryOperator(m_operator)) BOOST_THROW_EXCEPTION(createTypeError("Unary operator not compatible with type.")); @@ -416,6 +432,8 @@ void FunctionCall::checkTypeRequirements() } else { + m_expression->requireLValue(); + //@todo would be nice to create a struct type from the arguments // and then ask if that is implicitly convertible to the struct represented by the // function parameters @@ -448,8 +466,15 @@ void MemberAccess::checkTypeRequirements() void IndexAccess::checkTypeRequirements() { - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Index access not yet implemented.")); - // m_type = ; + m_base->checkTypeRequirements(); + m_base->requireLValue(); + if (m_base->getType()->getCategory() != Type::Category::MAPPING) + BOOST_THROW_EXCEPTION(m_base->createTypeError("Indexed expression has to be a mapping (is " + + m_base->getType()->toString() + ")")); + MappingType const& type = dynamic_cast<MappingType const&>(*m_base->getType()); + m_index->expectType(*type.getKeyType()); + m_type = type.getValueType(); + m_isLvalue = true; } void Identifier::checkTypeRequirements() @@ -481,6 +506,7 @@ void Identifier::checkTypeRequirements() // Calling a function (e.g. function(12), otherContract.function(34)) does not do a type // conversion. m_type = make_shared<FunctionType>(*functionDef); + m_isLvalue = true; return; } ContractDefinition* contractDef = dynamic_cast<ContractDefinition*>(m_referencedDeclaration); |