fxos/lib/semantics.cpp

162 lines
3.1 KiB
C++

#include <fxos/semantics.h>
#include <fxos/util.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::domain_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 structs().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::structs() 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;
}
}
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 */