Index access for bytesXX.

This commit is contained in:
chriseth
2016-02-09 17:07:04 +01:00
parent fad2d4df22
commit 29faf1b298
6 changed files with 99 additions and 0 deletions
+18
View File
@@ -1253,6 +1253,8 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
arrayType.isDynamicallySized()
);
}
else if (exprType->category() == Type::Category::FixedBytes)
annotation.isLValue = false;
return false;
}
@@ -1317,6 +1319,22 @@ bool TypeChecker::visit(IndexAccess const& _access)
}
break;
}
case Type::Category::FixedBytes:
{
FixedBytesType const& bytesType = dynamic_cast<FixedBytesType const&>(*baseType);
if (!index)
typeError(_access.location(), "Index expression cannot be omitted.");
else
{
expectType(*index, IntegerType(256));
if (auto integerType = dynamic_cast<IntegerConstantType const*>(type(*index).get()))
if (bytesType.numBytes() <= integerType->literalValue(nullptr))
typeError(_access.location(), "Out of bounds array access.");
}
resultType = make_shared<FixedBytesType>(1);
isLValue = false; // @todo this heavily depends on how it is embedded
break;
}
default:
fatalTypeError(
_access.baseExpression().location(),
+5
View File
@@ -638,6 +638,11 @@ TypePointer FixedBytesType::binaryOperatorResult(Token::Value _operator, TypePoi
return TypePointer();
}
MemberList::MemberMap FixedBytesType::nativeMembers(const ContractDefinition*) const
{
return MemberList::MemberMap{MemberList::Member{"length", make_shared<IntegerType>(8)}};
}
bool FixedBytesType::operator==(Type const& _other) const
{
if (_other.category() != category())
+1
View File
@@ -399,6 +399,7 @@ public:
virtual bool isValueType() const override { return true; }
virtual std::string toString(bool) const override { return "bytes" + dev::toString(m_bytes); }
virtual MemberList::MemberMap nativeMembers(ContractDefinition const*) const override;
virtual TypePointer encodingType() const override { return shared_from_this(); }
virtual TypePointer interfaceType(bool) const override { return shared_from_this(); }
@@ -1004,6 +1004,16 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
solAssert(false, "Illegal array member.");
break;
}
case Type::Category::FixedBytes:
{
auto const& type = dynamic_cast<FixedBytesType const&>(*_memberAccess.expression().annotation().type);
utils().popStackElement(type);
if (member == "length")
m_context << u256(type.numBytes());
else
solAssert(false, "Illegal fixed bytes member.");
break;
}
default:
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to unknown type."));
}
@@ -1085,6 +1095,22 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
break;
}
}
else if (baseType.category() == Type::Category::FixedBytes)
{
FixedBytesType const& fixedBytesType = dynamic_cast<FixedBytesType const&>(baseType);
solAssert(_indexAccess.indexExpression(), "Index expression expected.");
_indexAccess.indexExpression()->accept(*this);
// stack layout: <value> <index>
// check out-of-bounds access
m_context << u256(fixedBytesType.numBytes());
m_context << eth::Instruction::DUP2 << eth::Instruction::LT << eth::Instruction::ISZERO;
// out-of-bounds access throws exception
m_context.appendConditionalJumpTo(m_context.errorTag());
m_context << eth::Instruction::BYTE;
m_context << (u256(1) << (256 - 8)) << eth::Instruction::MUL;
}
else if (baseType.category() == Type::Category::TypeType)
{
solAssert(baseType.sizeOnStack() == 0, "");