aboutsummaryrefslogtreecommitdiffstats
path: root/AST.cpp
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2014-11-11 00:31:09 +0800
committerChristian <c@ethdev.com>2014-11-14 21:08:14 +0800
commit46dd62982084dfe5712292b88047d2a58e0a420e (patch)
treefda7b3871e7de54cbb4cdab8cf3add6ff6090f42 /AST.cpp
parentc4a65cf6888f6b15fa7740b6db5d9dae8f18b7ba (diff)
downloaddexon-solidity-46dd62982084dfe5712292b88047d2a58e0a420e.tar.gz
dexon-solidity-46dd62982084dfe5712292b88047d2a58e0a420e.tar.zst
dexon-solidity-46dd62982084dfe5712292b88047d2a58e0a420e.zip
Mapping types.
Diffstat (limited to 'AST.cpp')
-rw-r--r--AST.cpp40
1 files changed, 33 insertions, 7 deletions
diff --git a/AST.cpp b/AST.cpp
index 70af8f98..d5f856df 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -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);