mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Wildcards.
This commit is contained in:
parent
039b2a764f
commit
029b819489
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
Loading…
Reference in New Issue
Block a user