diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 31 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 51 |
2 files changed, 61 insertions, 21 deletions
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 669a7e4a..3fb7303f 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -783,10 +783,13 @@ bool TypeChecker::visit(Assignment const& _assignment) bool TypeChecker::visit(TupleExpression const& _tuple) { vector<ASTPointer<Expression>> const& components = _tuple.components(); - solAssert(!_tuple.isInlineArray(), "Tuple type not properly declared"); TypePointers types; + TypePointer inlineArrayType; + if (_tuple.annotation().lValueRequested) { + if (_tuple.isInlineArray()) + fatalTypeError(_tuple.location(), "Inline array type cannot be declared as LValue."); for (auto const& component: components) if (component) { @@ -813,18 +816,34 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { components[i]->accept(*this); types.push_back(type(*components[i])); + if (_tuple.isInlineArray()) + solAssert(!!types[i], "Inline array cannot have empty components"); + if (i == 0 && _tuple.isInlineArray()) + inlineArrayType = types[i]->mobileType(); + else if (_tuple.isInlineArray() && inlineArrayType) + inlineArrayType = Type::commonType(inlineArrayType, types[i]->mobileType()); } else types.push_back(TypePointer()); } - if (components.size() == 1) - _tuple.annotation().type = type(*components[0]); + if (_tuple.isInlineArray()) + { + if (!inlineArrayType) + fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements."); + _tuple.annotation().type = make_shared<ArrayType>(DataLocation::Memory, inlineArrayType, types.size()); + } else { - if (components.size() == 2 && !components[1]) - types.pop_back(); - _tuple.annotation().type = make_shared<TupleType>(types); + if (components.size() == 1) + _tuple.annotation().type = type(*components[0]); + else + { + if (components.size() == 2 && !components[1]) + types.pop_back(); + _tuple.annotation().type = make_shared<TupleType>(types); + } } + } return false; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index b0e92b59..f0dab41a 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -219,25 +219,46 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) bool ExpressionCompiler::visit(TupleExpression const& _tuple) { - vector<unique_ptr<LValue>> lvalues; - for (auto const& component: _tuple.components()) - if (component) + if (_tuple.isInlineArray()) + { + ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*_tuple.annotation().type); + + solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); + m_context << max(u256(32u), arrayType.memorySize()); + utils().allocateMemory(); + m_context << eth::Instruction::DUP1; + + for (auto const& component: _tuple.components()) { component->accept(*this); - if (_tuple.annotation().lValueRequested) + utils().convertType(*component->annotation().type, *arrayType.baseType(), true); + utils().storeInMemoryDynamic(*arrayType.baseType(), true); + } + + m_context << eth::Instruction::POP; + } + else + { + vector<unique_ptr<LValue>> lvalues; + for (auto const& component: _tuple.components()) + if (component) { - solAssert(!!m_currentLValue, ""); - lvalues.push_back(move(m_currentLValue)); + component->accept(*this); + if (_tuple.annotation().lValueRequested) + { + solAssert(!!m_currentLValue, ""); + lvalues.push_back(move(m_currentLValue)); + } } + else if (_tuple.annotation().lValueRequested) + lvalues.push_back(unique_ptr<LValue>()); + if (_tuple.annotation().lValueRequested) + { + if (_tuple.components().size() == 1) + m_currentLValue = move(lvalues[0]); + else + m_currentLValue.reset(new TupleObject(m_context, move(lvalues))); } - else if (_tuple.annotation().lValueRequested) - lvalues.push_back(unique_ptr<LValue>()); - if (_tuple.annotation().lValueRequested) - { - if (_tuple.components().size() == 1) - m_currentLValue = move(lvalues[0]); - else - m_currentLValue.reset(new TupleObject(m_context, move(lvalues))); } return false; } @@ -774,7 +795,6 @@ bool ExpressionCompiler::visit(NewExpression const&) void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) { CompilerContext::LocationSetter locationSetter(m_context, _memberAccess); - // Check whether the member is a bound function. ASTString const& member = _memberAccess.memberName(); if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type.get())) @@ -1123,6 +1143,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal) { CompilerContext::LocationSetter locationSetter(m_context, _literal); TypePointer type = _literal.annotation().type; + switch (type->category()) { case Type::Category::IntegerConstant: |