Mapping types.

This commit is contained in:
Christian
2014-11-14 14:08:14 +01:00
parent c4a65cf688
commit 46dd629820
9 changed files with 243 additions and 105 deletions
+33 -7
View File
@@ -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);