fxos/lib/semantics.cpp

170 lines
3.6 KiB
C++

#include <fxos/semantics.h>
#include <fxos/util/format.h>
#include <exception>
namespace FxOS {
//---
// Data types
//---
static DataType _u8(IntegerType(1, false));
static DataType _i8(IntegerType(1, true));
static DataType _u16(IntegerType(2, false));
static DataType _i16(IntegerType(2, true));
static DataType _u32(IntegerType(4, false));
static DataType _i32(IntegerType(4, true));
DataType const *IntegerType::u8 = &_u8;
DataType const *IntegerType::i8 = &_i8;
DataType const *IntegerType::u16 = &_u16;
DataType const *IntegerType::i16 = &_i16;
DataType const *IntegerType::u32 = &_u32;
DataType const *IntegerType::i32 = &_i32;
BitfieldType::Field BitfieldType::named_field(std::string name) const
{
for(auto &f: fields) {
if(f.first == name)
return f;
}
throw std::logic_error("no such field name in bit field");
}
DataType::DataKind DataType::kind() const noexcept
{
return (DataKind)v.index();
}
size_t DataType::size() const noexcept
{
switch(kind()) {
case Integer:
return integer().size;
case Bitfield:
return bitfield().size;
case Array:
return array().size;
case String:
return string().size;
case Struct:
return structure().size;
}
return 0;
};
IntegerType const &DataType::integer() const
{
return std::get<IntegerType>(v);
}
BitfieldType const &DataType::bitfield() const
{
return std::get<BitfieldType>(v);
}
ArrayType const &DataType::array() const
{
return std::get<ArrayType>(v);
}
StringType const &DataType::string() const
{
return std::get<StringType>(v);
}
StructType const &DataType::structure() const
{
return std::get<StructType>(v);
}
//---
// Data values
//---
DataValue::DataValue(): type {nullptr}
{
}
DataValue::DataValue(DataType const *type):
type {type}, mem(type->size(), (int16_t)-1)
{
}
void DataValue::access(size_t offset, size_t size) const
{
if(size != 1 && size != 2 && size != 4)
throw std::logic_error("Invalid simulated access size");
if(offset + size > mem.size())
throw std::logic_error("Access overflows from data");
}
uint32_t DataValue::read(size_t offset, size_t size) const
{
access(offset, size);
uint32_t result = 0;
while(size--) {
int16_t byte = mem[offset++];
if(byte == -1)
throw std::logic_error("Read uninitialized value");
result = (result << 8) | byte;
}
return result;
}
void DataValue::write(size_t offset, size_t size, uint32_t contents)
{
access(offset, size);
offset += size;
while(size-- > 0) {
mem[--offset] = contents & 0xff;
contents >>= 8;
}
}
uint32_t DataValue::uinteger() const
{
if(!type || type->kind() != DataType::Integer)
throw std::logic_error("uinteger() on non-int DataValue");
return read(0, type->size());
}
std::string DataValue::str() const noexcept
{
std::string result;
switch(type->kind()) {
/* Format all integers in hexadecimal */
case DataType::Integer:
return format("0x%0*x", 2 * type->size(), read(0, type->size()));
/* TODO: Print data values of complex types */
case DataType::Bitfield:
case DataType::Array:
case DataType::String:
case DataType::Struct:
/* If the type is not supported, use hexadecimal notation */
default:
for(size_t i = 0; i < mem.size(); i++) {
int16_t byte = mem[i];
if(byte == -1)
result += " UND";
else
result += format(" %02x", byte);
}
result[0] = '{';
result += '}';
}
return result;
}
} /* namespace FxOS */