From 10a1c352b9c274ba24b9915dfe2d6088616a69c2 Mon Sep 17 00:00:00 2001 From: RJ Date: Sun, 10 Jan 2016 01:07:02 -0600 Subject: Update with type resolution tests for arrays --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 84 +++++++++++++++++++--- 1 file changed, 76 insertions(+), 8 deletions(-) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 70c9eb0d..3a865f8c 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2769,15 +2769,83 @@ BOOST_AUTO_TEST_CASE(function_overload_array_type) BOOST_CHECK(success(text)); } -/*BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing) +BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion) +{ + char const* text = R"( + contract C { + function f() returns (uint) { + uint8 x = 7; + uint16 y = 8; + uint32 z = 9; + uint32[3] memory ending = [x, y, z]; + return (ending[1]); + } + } + )"; + BOOST_CHECK(success(text)); + +} + +BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion_strings) { char const* text = R"( contract C { - uint[] a; - function f() returns (uint, uint) { - a = [1,2,3]; - return (a[3], [3,4][0]); - } + function f() returns (string) { + string memory x = "Hello"; + string memory y = "World"; + string[2] memory z = [x, y]; + return (z[0]); + } + } + )"; + BOOST_CHECK(success(text)); +} + +BOOST_AUTO_TEST_CASE(inline_array_declaration_const_int_conversion) +{ + char const* text = R"( + contract C { + function f() returns (uint) { + uint8[4] memory z = [1,2,3,5]; + return (z[0]); + } + } + )"; + BOOST_CHECK(success(text)); +} + +BOOST_AUTO_TEST_CASE(inline_array_declaration_const_string_conversion) +{ + char const* text = R"( + contract C { + function f() returns (string) { + string[2] memory z = ["Hello", "World"]; + return (z[0]); + } + } + )"; + BOOST_CHECK(success(text)); +} + +BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type) +{ + char const* text = R"( + contract C { + function f() returns (uint) { + return ([4,5,6][1]); + } + } + )"; + BOOST_CHECK(success(text)); +} + +BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type_strings) +{ + char const* text = R"( + contract C { + function f() returns (string) { + return (["foo", "man", "choo"][1]); + } } )"; BOOST_CHECK(success(text)); @@ -2788,12 +2856,12 @@ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) char const* text = R"( contract C { function f() { - uint[] x = [45, "foo", true]; + uint[3] x = [45, 'foo', true]; } } )"; BOOST_CHECK(expectError(text) == Error::Type::TypeError); -}*/ +} BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3 From df9dfa8feff8637d786342ca2c33286b72dd2d10 Mon Sep 17 00:00:00 2001 From: RJ Date: Sun, 10 Jan 2016 01:09:58 -0600 Subject: find common type --- libsolidity/analysis/TypeChecker.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index de30dcf7..20b3ad6c 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -780,8 +780,9 @@ bool TypeChecker::visit(Assignment const& _assignment) bool TypeChecker::visit(TupleExpression const& _tuple) { vector> const& components = _tuple.components(); - solAssert(!_tuple.isInlineArray(), "Tuple type not properly declared"); TypePointers types; + TypePointer internalArrayType; + bool isArray = _tuple.isInlineArray(); if (_tuple.annotation().lValueRequested) { for (auto const& component: components) @@ -810,12 +811,20 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { components[i]->accept(*this); types.push_back(type(*components[i])); + if (i == 0 && isArray) + internalArrayType = types[i]->mobileType(); + else if (isArray && internalArrayType && types[i]->mobileType()) + internalArrayType = Type::commonType(internalArrayType, types[i]->mobileType()); } else types.push_back(TypePointer()); } - if (components.size() == 1) + if (components.size() == 1 && !isArray) _tuple.annotation().type = type(*components[0]); + else if (!internalArrayType && isArray) + fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements."); + else if (isArray) + _tuple.annotation().type = make_shared(DataLocation::Memory, internalArrayType, types.size()); else { if (components.size() == 2 && !components[1]) -- cgit v1.2.3 From e18eaa4615382f50d2df800688f4307ef782e779 Mon Sep 17 00:00:00 2001 From: RJ Date: Sun, 10 Jan 2016 01:12:17 -0600 Subject: Update ExpressionCompiler.cpp --- libsolidity/codegen/ExpressionCompiler.cpp | 56 +++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index b0e92b59..c7e2a997 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -186,7 +186,6 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) _assignment.leftHandSide().annotation().type ); utils().convertType(*_assignment.rightHandSide().annotation().type, *type); - _assignment.leftHandSide().accept(*this); solAssert(!!m_currentLValue, "LValue not retrieved."); @@ -219,25 +218,48 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) bool ExpressionCompiler::visit(TupleExpression const& _tuple) { - vector> lvalues; - for (auto const& component: _tuple.components()) - if (component) - { - component->accept(*this); - if (_tuple.annotation().lValueRequested) + if (_tuple.isInlineArray()) + { + ArrayType const& arrayType = dynamic_cast(*_tuple.annotation().type); + auto components = _tuple.components(); + + m_context << max(u256(32u), arrayType.memorySize()); + utils().allocateMemory(); + m_context << eth::Instruction::DUP1; + + for (unsigned i = 0; i < components.size(); ++i) + { + components[i]->accept(*this); + utils().convertType(*components[i]->annotation().type, *arrayType.baseType(), true); + cout << components[i]->annotation().type->toString(true) << endl; + components[i]->annotation().type = arrayType.baseType(); //force conversion + cout << components[i]->annotation().type->toString(true) << endl; + utils().storeInMemoryDynamic(*components[i]->annotation().type, true); + } + m_context << eth::Instruction::POP; + } + else + { + vector> 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()); + 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()); - 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; } -- cgit v1.2.3 From d751b9085cf465b1c0730032f602f375b0b48c04 Mon Sep 17 00:00:00 2001 From: RJ Date: Sun, 10 Jan 2016 01:12:52 -0600 Subject: Update SolidityEndToEndTest.cpp --- test/libsolidity/SolidityEndToEndTest.cpp | 70 +++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 2f627fc2..218d038e 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -6107,6 +6107,76 @@ BOOST_AUTO_TEST_CASE(bound_function_to_string) BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(3))); } +BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_strings) +{ + char const* sourceCode = R"( + contract C { + string s = "aeou"; + function f() returns (string, string) { + string memory t = "abc"; + string[3] memory x = [s, t, "Hello"]; + return (x[0], x[2]); + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x40), u256(0x80), u256(4), string("aeou"), u256(3), string("abc"))); +} + +BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_ints) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint x, uint y) { + x = 3; + y = 6; + uint[2] memory z = [x, y]; + return (z[0], z[1]); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(3, 6)); +} + +BOOST_AUTO_TEST_CASE(inline_array_index_access_ints) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint) { + return ([1, 2, 3, 4][2]); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(3)); +} + +BOOST_AUTO_TEST_CASE(inline_array_index_access_strings) +{ + char const* sourceCode = R"( + contract C { + function f() returns (string) { + return (["abc", "def", "g"][1]); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x40), u256(3), string("def"))); +} + +BOOST_AUTO_TEST_CASE(inline_array_return) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint8[5]) { + return ([1,2,3,4,5]); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(1, 2, 3, 4, 5)); +} BOOST_AUTO_TEST_SUITE_END() } -- cgit v1.2.3 From 5a3b40f802612b3fe18eac2c76fb2c849318807a Mon Sep 17 00:00:00 2001 From: RJ Date: Sun, 10 Jan 2016 21:36:47 -0600 Subject: Update SolidityEndToEndTest.cpp --- test/libsolidity/SolidityEndToEndTest.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 218d038e..8be158fb 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -6111,16 +6111,16 @@ BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_strings) { char const* sourceCode = R"( contract C { - string s = "aeou"; + string s = "doh"; function f() returns (string, string) { - string memory t = "abc"; - string[3] memory x = [s, t, "Hello"]; - return (x[0], x[2]); + string memory t = "ray"; + string[3] memory x = [s, t, "mi"]; + return (x[1], x[2]); } } )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x40), u256(0x80), u256(4), string("aeou"), u256(3), string("abc"))); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x40), u256(0x80), u256(3), string("ray"), u256(2), string("mi"))); } BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_ints) @@ -6156,22 +6156,33 @@ BOOST_AUTO_TEST_CASE(inline_array_index_access_strings) { char const* sourceCode = R"( contract C { + string public tester; function f() returns (string) { - return (["abc", "def", "g"][1]); + return (["abc", "def", "g"][0]); + } + function test() { + tester = f(); } } )"; compileAndRun(sourceCode, 0, "C"); - BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x40), u256(3), string("def"))); + BOOST_CHECK(callContractFunction("test()") == encodeArgs()); + BOOST_CHECK(callContractFunction("tester()") == encodeArgs(u256(0x20), u256(3), string("abc"))); } BOOST_AUTO_TEST_CASE(inline_array_return) { char const* sourceCode = R"( contract C { + uint8[] tester; function f() returns (uint8[5]) { return ([1,2,3,4,5]); } + function test() returns (uint8, uint8, uint8, uint8, uint8) { + tester = f(); + return (tester[0], tester[1], tester[2], tester[3], tester[4]); + } + } )"; compileAndRun(sourceCode, 0, "C"); -- cgit v1.2.3 From 72a641fe9f4f040586c7f563601ddda987df4f0b Mon Sep 17 00:00:00 2001 From: RJ Date: Sun, 10 Jan 2016 21:37:47 -0600 Subject: Update ExpressionCompiler.cpp --- libsolidity/codegen/ExpressionCompiler.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c7e2a997..c930c468 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -231,9 +231,7 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) { components[i]->accept(*this); utils().convertType(*components[i]->annotation().type, *arrayType.baseType(), true); - cout << components[i]->annotation().type->toString(true) << endl; components[i]->annotation().type = arrayType.baseType(); //force conversion - cout << components[i]->annotation().type->toString(true) << endl; utils().storeInMemoryDynamic(*components[i]->annotation().type, true); } m_context << eth::Instruction::POP; @@ -796,7 +794,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(_memberAccess.annotation().type.get())) @@ -1145,6 +1142,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: @@ -1155,7 +1153,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal) break; // will be done during conversion default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer, boolean and string literals implemented for now.")); - } + } } void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryOperation) -- cgit v1.2.3 From c78b9c57375eff644310ca62ce87d07bb576fd28 Mon Sep 17 00:00:00 2001 From: RJ Date: Sun, 10 Jan 2016 21:49:36 -0600 Subject: Update ExpressionCompiler.cpp --- libsolidity/codegen/ExpressionCompiler.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c930c468..c5f0f97e 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -186,6 +186,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) _assignment.leftHandSide().annotation().type ); utils().convertType(*_assignment.rightHandSide().annotation().type, *type); + _assignment.leftHandSide().accept(*this); solAssert(!!m_currentLValue, "LValue not retrieved."); @@ -219,23 +220,24 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) bool ExpressionCompiler::visit(TupleExpression const& _tuple) { if (_tuple.isInlineArray()) - { - ArrayType const& arrayType = dynamic_cast(*_tuple.annotation().type); - auto components = _tuple.components(); - - m_context << max(u256(32u), arrayType.memorySize()); - utils().allocateMemory(); - m_context << eth::Instruction::DUP1; - - for (unsigned i = 0; i < components.size(); ++i) - { - components[i]->accept(*this); + { + ArrayType const& arrayType = dynamic_cast(*_tuple.annotation().type); + auto components = _tuple.components(); + + m_context << max(u256(32u), arrayType.memorySize()); + utils().allocateMemory(); + m_context << eth::Instruction::DUP1; + + for (unsigned i = 0; i < components.size(); ++i) + { + components[i]->accept(*this); utils().convertType(*components[i]->annotation().type, *arrayType.baseType(), true); components[i]->annotation().type = arrayType.baseType(); //force conversion utils().storeInMemoryDynamic(*components[i]->annotation().type, true); - } - m_context << eth::Instruction::POP; - } + } + + m_context << eth::Instruction::POP; + } else { vector> lvalues; -- cgit v1.2.3 From c348791fa164841a8712cced711cdac321c20f62 Mon Sep 17 00:00:00 2001 From: RJ Date: Sun, 10 Jan 2016 21:55:30 -0600 Subject: Update SolidityNameAndTypeResolution.cpp --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 3a865f8c..c63d8297 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2783,7 +2783,6 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion) } )"; BOOST_CHECK(success(text)); - } BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion_strings) -- cgit v1.2.3 From c7df6d03103093356323a3befbcd9d3e9cdfc117 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Mon, 11 Jan 2016 00:48:02 -0600 Subject: one last test for long strings --- test/libsolidity/SolidityEndToEndTest.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 8be158fb..3136d43f 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -6188,6 +6188,21 @@ BOOST_AUTO_TEST_CASE(inline_array_return) compileAndRun(sourceCode, 0, "C"); BOOST_CHECK(callContractFunction("f()") == encodeArgs(1, 2, 3, 4, 5)); } + +BOOST_AUTO_TEST_CASE(inline_long_string_return) +{ + char const* sourceCode = R"( + contract C { + function f() returns (string) { + return (["somethingShort", "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"][1]); + } + } + )"; + + string strLong = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678900123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789001234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeDyn(strLong)); +} BOOST_AUTO_TEST_SUITE_END() } -- cgit v1.2.3 From ac664e7f86593ff3d70576ac475f07f9c91b9ca8 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Mon, 11 Jan 2016 14:25:59 -0600 Subject: final changes to typechecker, the expression compiler, and a couple more tests for good measure --- libsolidity/analysis/TypeChecker.cpp | 40 ++++++++++++++-------- libsolidity/codegen/ExpressionCompiler.cpp | 15 ++++---- test/libsolidity/SolidityNameAndTypeResolution.cpp | 25 ++++++++++++++ 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 20b3ad6c..75a9632e 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -781,10 +781,12 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { vector> const& components = _tuple.components(); TypePointers types; - TypePointer internalArrayType; - bool isArray = _tuple.isInlineArray(); + 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) { @@ -811,26 +813,34 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { components[i]->accept(*this); types.push_back(type(*components[i])); - if (i == 0 && isArray) - internalArrayType = types[i]->mobileType(); - else if (isArray && internalArrayType && types[i]->mobileType()) - internalArrayType = Type::commonType(internalArrayType, types[i]->mobileType()); + 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 && !isArray) - _tuple.annotation().type = type(*components[0]); - else if (!internalArrayType && isArray) - fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements."); - else if (isArray) - _tuple.annotation().type = make_shared(DataLocation::Memory, internalArrayType, types.size()); + if (_tuple.isInlineArray()) + { + if (!inlineArrayType) + fatalTypeError(_tuple.location(), "Unable to deduce common type for array elements."); + _tuple.annotation().type = make_shared(DataLocation::Memory, inlineArrayType, types.size()); + } else { - if (components.size() == 2 && !components[1]) - types.pop_back(); - _tuple.annotation().type = make_shared(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(types); + } } + } return false; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index c5f0f97e..f0dab41a 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -186,7 +186,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment) _assignment.leftHandSide().annotation().type ); utils().convertType(*_assignment.rightHandSide().annotation().type, *type); - + _assignment.leftHandSide().accept(*this); solAssert(!!m_currentLValue, "LValue not retrieved."); @@ -222,18 +222,17 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) if (_tuple.isInlineArray()) { ArrayType const& arrayType = dynamic_cast(*_tuple.annotation().type); - auto components = _tuple.components(); + solAssert(!arrayType.isDynamicallySized(), "Cannot create dynamically sized inline array."); m_context << max(u256(32u), arrayType.memorySize()); utils().allocateMemory(); m_context << eth::Instruction::DUP1; - for (unsigned i = 0; i < components.size(); ++i) + for (auto const& component: _tuple.components()) { - components[i]->accept(*this); - utils().convertType(*components[i]->annotation().type, *arrayType.baseType(), true); - components[i]->annotation().type = arrayType.baseType(); //force conversion - utils().storeInMemoryDynamic(*components[i]->annotation().type, true); + component->accept(*this); + utils().convertType(*component->annotation().type, *arrayType.baseType(), true); + utils().storeInMemoryDynamic(*arrayType.baseType(), true); } m_context << eth::Instruction::POP; @@ -1155,7 +1154,7 @@ void ExpressionCompiler::endVisit(Literal const& _literal) break; // will be done during conversion default: BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Only integer, boolean and string literals implemented for now.")); - } + } } void ExpressionCompiler::appendAndOrOperatorCode(BinaryOperation const& _binaryOperation) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index c63d8297..3909fc6c 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2862,6 +2862,31 @@ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) BOOST_CHECK(expectError(text) == Error::Type::TypeError); } +BOOST_AUTO_TEST_CASE(dynamic_inline_array) +{ + char const* text = R"( + contract C { + function f() { + uint[4][4] memory dyn = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]; + } + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(lvalues_as_inline_array) +{ + char const* text = R"( + contract C { + function f() { + [1, 2, 3]++; + [1, 2, 3] = [4, 5, 6]; + } + } + )"; + BOOST_CHECK(expectError(text) == Error::Type::TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } -- cgit v1.2.3 From 9c29cf79cf404132ec3ab149c492cfa97b677543 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Mon, 11 Jan 2016 15:36:30 -0600 Subject: added documentation and one last test for struct creation inline --- docs/frequently-asked-questions.rst | 4 +++- test/libsolidity/SolidityNameAndTypeResolution.cpp | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index cf037131..bf493167 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -317,7 +317,8 @@ by `msg.data`. Can state variables be initialized in-line? =========================================== -Yes, this is possible for most types (even for structs), but not for arrays. +Yes, this is possible for all types (even for structs). However, for arrays it +should be noted that you must declare them as static memory arrays. Futhermore, multi dimensional arrays cannot be declared inline. Examples:: @@ -325,6 +326,7 @@ Examples:: struct S { uint a; uint b; } S public x = S(1, 2); string name = "Ada"; + string[4] memory AdaArr = ["This", "is", "an", "array"]; } contract D { C c = new C(); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 3909fc6c..2281ac10 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2850,6 +2850,22 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type_strings) BOOST_CHECK(success(text)); } +BOOST_AUTO_TEST_CASE(inline_struct_declaration_arrays) +{ + char const* text = R"( + contract C { + struct S { + uint a; + string b; + } + function f() { + S[2] memory x = [S({a: 1, b: "fish"}), S({a: 2, b: "fish"})]; + } + } + )"; + BOOST_CHECK(success(text)); +} + BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) { char const* text = R"( -- cgit v1.2.3 From b230fe19052307d1b71372599ccaf8e1440e1473 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Mon, 11 Jan 2016 15:48:41 -0600 Subject: forgot to take the auto tabs off...turned into spaces --- docs/frequently-asked-questions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index bf493167..919ee54e 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -326,7 +326,7 @@ Examples:: struct S { uint a; uint b; } S public x = S(1, 2); string name = "Ada"; - string[4] memory AdaArr = ["This", "is", "an", "array"]; + string[4] memory AdaArr = ["This", "is", "an", "array"]; } contract D { C c = new C(); -- cgit v1.2.3 From c45593a44480f846302fdb652e23bd47988fba84 Mon Sep 17 00:00:00 2001 From: RJ Catalano Date: Mon, 11 Jan 2016 23:41:20 -0600 Subject: clarification on dynamic arrays, switcheroo on typepointer, and a documentation test added --- docs/frequently-asked-questions.rst | 2 +- libsolidity/analysis/TypeChecker.cpp | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 17 +++++++++++++++++ test/libsolidity/SolidityNameAndTypeResolution.cpp | 4 ++-- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 919ee54e..f87b785d 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -318,7 +318,7 @@ Can state variables be initialized in-line? =========================================== Yes, this is possible for all types (even for structs). However, for arrays it -should be noted that you must declare them as static memory arrays. Futhermore, multi dimensional arrays cannot be declared inline. +should be noted that you must declare them as static memory arrays. Examples:: diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 3fb7303f..ab1151a1 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -784,7 +784,6 @@ bool TypeChecker::visit(TupleExpression const& _tuple) { vector> const& components = _tuple.components(); TypePointers types; - TypePointer inlineArrayType; if (_tuple.annotation().lValueRequested) { @@ -807,6 +806,7 @@ bool TypeChecker::visit(TupleExpression const& _tuple) } else { + TypePointer inlineArrayType; for (size_t i = 0; i < components.size(); ++i) { // Outside of an lvalue-context, the only situation where a component can be empty is (x,). diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 3136d43f..34c5dffc 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -6123,6 +6123,23 @@ BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_strings) BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x40), u256(0x80), u256(3), string("ray"), u256(2), string("mi"))); } +BOOST_AUTO_TEST_CASE(inline_array_strings_from_document) +{ + char const* sourceCode = R"( + contract C { + function f(uint i) returns (string) { + string[4] memory x = ["This", "is", "an", "array"]; + return (x[i]); + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("f(uint256)", u256(0)) == encodeArgs(u256(0x20), u256(4), string("This"))); + BOOST_CHECK(callContractFunction("f(uint256)", u256(1)) == encodeArgs(u256(0x20), u256(2), string("is"))); + BOOST_CHECK(callContractFunction("f(uint256)", u256(2)) == encodeArgs(u256(0x20), u256(2), string("an"))); + BOOST_CHECK(callContractFunction("f(uint256)", u256(3)) == encodeArgs(u256(0x20), u256(5), string("array"))); +} + BOOST_AUTO_TEST_CASE(inline_array_storage_to_memory_conversion_ints) { char const* sourceCode = R"( diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 2281ac10..4697e756 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2883,11 +2883,11 @@ BOOST_AUTO_TEST_CASE(dynamic_inline_array) char const* text = R"( contract C { function f() { - uint[4][4] memory dyn = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]; + uint8[4][4] memory dyn = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + BOOST_CHECK(success(text)); } BOOST_AUTO_TEST_CASE(lvalues_as_inline_array) -- cgit v1.2.3