aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-10-15 06:42:36 +0800
committerchriseth <c@ethdev.com>2015-10-15 23:38:42 +0800
commit029b8194892b6b08ce70075bd66f43f66c40e301 (patch)
tree3cce6cff28599d09ce612633c2d13d76ebe9e7da
parent039b2a764f3944768bb253102f4c4b788f2dca9c (diff)
downloaddexon-solidity-029b8194892b6b08ce70075bd66f43f66c40e301.tar.gz
dexon-solidity-029b8194892b6b08ce70075bd66f43f66c40e301.tar.zst
dexon-solidity-029b8194892b6b08ce70075bd66f43f66c40e301.zip
Wildcards.
-rw-r--r--libsolidity/CompilerUtils.cpp32
-rw-r--r--libsolidity/ExpressionCompiler.cpp4
-rw-r--r--libsolidity/LValue.cpp21
-rw-r--r--libsolidity/Types.cpp2
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp9
5 files changed, 35 insertions, 33 deletions
diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp
index 34bb08ba..f0dea708 100644
--- a/libsolidity/CompilerUtils.cpp
+++ b/libsolidity/CompilerUtils.cpp
@@ -552,29 +552,37 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
}
case Type::Category::Tuple:
{
- //@TODO wildcards
TupleType const& sourceTuple = dynamic_cast<TupleType const&>(_typeOnStack);
TupleType const& targetTuple = dynamic_cast<TupleType const&>(_targetType);
- solAssert(sourceTuple.components().size() == targetTuple.components().size(), "");
+ // fillRight: remove excess values at right side, !fillRight: remove eccess values at left side
+ bool fillRight = !targetTuple.components().empty() && (
+ !targetTuple.components().back() ||
+ targetTuple.components().front()
+ );
unsigned depth = sourceTuple.sizeOnStack();
for (size_t i = 0; i < sourceTuple.components().size(); ++i)
{
- TypePointer const& sourceType = sourceTuple.components()[i];
- TypePointer const& targetType = targetTuple.components()[i];
+ TypePointer sourceType = sourceTuple.components()[i];
+ TypePointer targetType;
+ if (fillRight && i < targetTuple.components().size())
+ targetType = targetTuple.components()[i];
+ else if (!fillRight && targetTuple.components().size() + i >= sourceTuple.components().size())
+ targetType = targetTuple.components()[targetTuple.components().size() - (sourceTuple.components().size() - i)];
if (!sourceType)
{
solAssert(!targetType, "");
continue;
}
unsigned sourceSize = sourceType->sizeOnStack();
- unsigned targetSize = targetType->sizeOnStack();
- if (*sourceType != *targetType || _cleanupNeeded)
+ unsigned targetSize = targetType ? targetType->sizeOnStack() : 0;
+ if (!targetType || *sourceType != *targetType || _cleanupNeeded)
{
- if (sourceSize > 0)
- copyToStackTop(depth, sourceSize);
-
- convertType(*sourceType, *targetType, _cleanupNeeded);
-
+ if (targetType)
+ {
+ if (sourceSize > 0)
+ copyToStackTop(depth, sourceSize);
+ convertType(*sourceType, *targetType, _cleanupNeeded);
+ }
if (sourceSize > 0 || targetSize > 0)
{
// Move it back into its place.
@@ -582,8 +590,6 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
m_context <<
eth::swapInstruction(depth + targetSize - sourceSize) <<
eth::Instruction::POP;
- if (targetSize < sourceSize)
- moveToStackTop(sourceSize - targetSize, depth );
// Value shrank
for (unsigned j = targetSize; j < sourceSize; ++j)
{
diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp
index 8109c03b..909d3fe5 100644
--- a/libsolidity/ExpressionCompiler.cpp
+++ b/libsolidity/ExpressionCompiler.cpp
@@ -177,7 +177,6 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
bool ExpressionCompiler::visit(Assignment const& _assignment)
{
-// cout << "-----Assignment" << endl;
CompilerContext::LocationSetter locationSetter(m_context, _assignment);
_assignment.rightHandSide().accept(*this);
// Perform some conversion already. This will convert storage types to memory and literals
@@ -185,10 +184,8 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
TypePointer type = _assignment.rightHandSide().annotation().type->closestTemporaryType(
_assignment.leftHandSide().annotation().type
);
-// cout << "-----Type conversion" << endl;
utils().convertType(*_assignment.rightHandSide().annotation().type, *type);
-// cout << "-----LHS" << endl;
_assignment.leftHandSide().accept(*this);
solAssert(!!m_currentLValue, "LValue not retrieved.");
@@ -214,7 +211,6 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
m_context << eth::swapInstruction(itemSize + lvalueSize) << eth::Instruction::POP;
}
}
-// cout << "-----Store" << endl;
m_currentLValue->storeValue(*type, _assignment.location());
m_currentLValue.reset();
return false;
diff --git a/libsolidity/LValue.cpp b/libsolidity/LValue.cpp
index 20aa59e1..52441836 100644
--- a/libsolidity/LValue.cpp
+++ b/libsolidity/LValue.cpp
@@ -496,10 +496,8 @@ void TupleObject::storeValue(Type const& _sourceType, SourceLocation const& _loc
{
// values are below the lvalue references
unsigned valuePos = sizeOnStack();
-
- //@TODO wildcards
-
TypePointers const& valueTypes = dynamic_cast<TupleType const&>(_sourceType).components();
+ solAssert(valueTypes.size() == m_lvalues.size(), "");
// valuePos .... refPos ...
// We will assign from right to left to optimize stack layout.
for (size_t i = 0; i < m_lvalues.size(); ++i)
@@ -507,16 +505,15 @@ void TupleObject::storeValue(Type const& _sourceType, SourceLocation const& _loc
unique_ptr<LValue> const& lvalue = m_lvalues[m_lvalues.size() - i - 1];
TypePointer const& valType = valueTypes[valueTypes.size() - i - 1];
unsigned stackHeight = m_context.stackHeight();
- solAssert(!!valType, "");
+ solAssert(!valType == !lvalue, "");
+ if (!lvalue)
+ continue;
valuePos += valType->sizeOnStack();
- if (lvalue)
- {
- // copy value to top
- CompilerUtils(m_context).copyToStackTop(valuePos, valType->sizeOnStack());
- // move lvalue ref above value
- CompilerUtils(m_context).moveToStackTop(valType->sizeOnStack(), lvalue->sizeOnStack());
- lvalue->storeValue(*valType, _location, true);
- }
+ // copy value to top
+ CompilerUtils(m_context).copyToStackTop(valuePos, valType->sizeOnStack());
+ // move lvalue ref above value
+ CompilerUtils(m_context).moveToStackTop(valType->sizeOnStack(), lvalue->sizeOnStack());
+ lvalue->storeValue(*valType, _location, true);
valuePos += m_context.stackHeight() - stackHeight;
}
// As the type of an assignment to a tuple type is the empty tuple, we always move.
diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp
index aca959b3..02b86a7f 100644
--- a/libsolidity/Types.cpp
+++ b/libsolidity/Types.cpp
@@ -1328,7 +1328,7 @@ TypePointer TupleType::closestTemporaryType(TypePointer const& _targetType) cons
size_t si = fillRight ? i : components().size() - i - 1;
size_t ti = fillRight ? i : targetComponents.size() - i - 1;
if (components()[si] && targetComponents[ti])
- tempComponents[ti] = components()[si]->closestTemporaryType(targetComponents[si]);
+ tempComponents[ti] = components()[si]->closestTemporaryType(targetComponents[ti]);
}
return make_shared<TupleType>(tempComponents);
}
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 36114689..75e43b73 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -5699,8 +5699,8 @@ BOOST_AUTO_TEST_CASE(tuples)
if (a != 1 || b != 2 || c[0] != 3) return 2;
(a, b) = (b, a);
if (a != 2 || b != 1) return 3;
-// (a, , b, ) = (8, 9, 10, 11, 12);
-// if (a != 8 || b != 10) return 3;
+ (a, , b, ) = (8, 9, 10, 11, 12);
+ if (a != 8 || b != 10) return 4;
}
}
)";
@@ -5724,7 +5724,7 @@ BOOST_AUTO_TEST_CASE(destructuring_assignment)
}
function f(bytes s) returns (uint) {
uint loc;
- uint[] memArray;
+ uint[] memory memArray;
(loc, x, y, data, arrayData[3]) = (8, 4, returnsArray(), s, 2);
if (loc != 8) return 1;
if (x != 4) return 2;
@@ -5737,6 +5737,9 @@ BOOST_AUTO_TEST_CASE(destructuring_assignment)
(memArray, loc) = (arrayData, 3);
if (loc != 3) return 9;
if (memArray.length != arrayData.length) return 10;
+ bytes memory memBytes;
+ (x, memBytes, y[2], ) = (456, s, 789, 101112, 131415);
+ if (x != 456 || memBytes.length != s.length || y[2] != 789) return 11;
}
}
)";