#include #include #include #include "DataType.h" #define ARRAY_NAME 256 static int typeNameIndex = 0; static int typeNameSwap = 0; static char typeName[2][ARRAY_NAME]; static bool useGlobals = false; static Structs globalStructs; const char* vtGetName(ValueType vt) { switch(vt) { case VT_INVALID: return "invalid"; case VT_NOT_SET: return "?"; case VT_INT: return "int"; case VT_FLOAT: return "float"; case VT_POINTER: return "pointer"; case VT_ARRAY: return "array"; case VT_LAST: return "invalid"; } return "invalid"; } #define VALUE_TYPE_MASK ((1u << VALUE_TYPE_BIT_SIZE) - 1u) #define VALUE_MAX_OFFSET ((1 << (32 - VALUE_TYPE_BIT_SIZE)) - 1) ValueType vGetType(Value v) { uint32 type = v.typeAndOffset & VALUE_TYPE_MASK; if(type >= VT_LAST) { return VT_INVALID; } return (ValueType)type; } bool vSetType(Value* v, ValueType vt) { if(v == NULL || vt < 0 || vt >= VT_LAST) { return true; } v->typeAndOffset = (v->typeAndOffset & ~VALUE_TYPE_MASK) | vt; return false; } int32 vGetOffset(Value v) { return (int32)(v.typeAndOffset >> VALUE_TYPE_BIT_SIZE); } bool vSetOffset(Value* v, int32 offset) { if(v == NULL || offset < 0 || offset > VALUE_MAX_OFFSET) { return true; } v->typeAndOffset = (v->typeAndOffset & VALUE_TYPE_MASK) | ((uint32)offset << VALUE_TYPE_BIT_SIZE); return false; } static void dtAppend(const char* s) { int index = 0; while(typeNameIndex < (ARRAY_NAME - 1) && s[index] != '\0') { typeName[typeNameSwap][typeNameIndex] = s[index]; index++; typeNameIndex++; } typeName[typeNameSwap][typeNameIndex] = '\0'; } const char* dtGetName(const Structs* sts, DataType dt) { typeNameSwap = !typeNameSwap; typeNameIndex = 0; switch(dtGetType(dt)) { case RDT_INT: dtAppend("int"); break; case RDT_FLOAT: dtAppend("float"); break; case RDT_STRUCT: { Struct* s = dtGetStruct(sts, dt); if(s != NULL) { dtAppend(s->name); } else { dtAppend("?-struct"); } break; } case RDT_VOID: dtAppend("void"); break; case RDT_INVALID: dtAppend("invalid"); break; default: dtAppend("?"); } if(dtIsArray(dt)) { dtAppend("[]"); } if(dtIsPointer(dt)) { dtAppend("*"); } return typeName[typeNameSwap]; } bool dtGetSize(DataType dt, const Structs* sts, int* size) { if(dtIsPointer(dt)) { *size = 1; return false; } switch(dtGetType(dt)) { case RDT_INT: *size = 1; return false; case RDT_FLOAT: *size = 1; return false; case RDT_STRUCT: { *size = 0; Struct* st = dtGetStruct(sts, dt); if(st == NULL) { return true; } for(int i = 0; i < st->amount; i++) { int add = 0; if(dtGetSize(st->vars[i].type, sts, &add)) { return true; } *size += add; } return false; } case RDT_LAST: case RDT_VOID: case RDT_INVALID: return true; } return true; } static DataType dtBuild(RawDataType rdt, bool isPointer, bool isArray, int32 structId) { if(rdt < 0 || rdt >= RDT_LAST || structId < 0 || structId > DT_MAX_STRUCT_ID) { return (DataType){RDT_INVALID}; } return (DataType){((uint32)rdt << DT_TYPE_OFFSET) | ((uint32)isPointer << DT_IS_POINTER_OFFSET) | ((uint32)isArray << DT_IS_ARRAY_OFFSET) | ((uint32)structId << DT_STRUCT_ID_OFFSET)}; } DataType dtInt(void) { return dtBuild(RDT_INT, false, false, 0); } DataType dtFloat(void) { return dtBuild(RDT_FLOAT, false, false, 0); } DataType dtVoid(void) { return dtBuild(RDT_VOID, false, false, 0); } DataType dtStruct(const Struct* st) { return dtBuild(RDT_STRUCT, false, false, st->id); } DataType dtText(void) { return dtBuild(RDT_INT, false, true, 0); } DataType dtToArray(DataType dt) { dt.data |= 1 << DT_IS_ARRAY_OFFSET; return dt; } DataType dtRemoveArray(DataType dt) { dt.data &= ~(((1u << DT_IS_ARRAY_BIT_SIZE) - 1u) << DT_IS_ARRAY_OFFSET); return dt; } DataType dtToPointer(DataType dt) { dt.data |= 1 << DT_IS_POINTER_OFFSET; return dt; } bool dtRemovePointer(DataType* dt) { if(dtIsPointer(*dt)) { dt->data &= ~(((1u << DT_IS_POINTER_BIT_SIZE) - 1u) << DT_IS_POINTER_OFFSET); return true; } return false; } RawDataType dtGetType(DataType dt) { uint32 type = dt.data & (((1u << DT_TYPE_BIT_SIZE) - 1u) << DT_TYPE_OFFSET); if(type >= RDT_LAST) { return RDT_INVALID; } return (RawDataType)type; } bool dtCompare(DataType a, DataType b) { return a.data == b.data; } bool dtIsInt(DataType dt) { return dtCompare(dt, dtInt()); } bool dtIsFloat(DataType dt) { return dtCompare(dt, dtFloat()); } bool dtIsVoid(DataType dt) { return dtCompare(dt, dtVoid()); } bool dtIsArray(DataType dt) { return dt.data & (((1u << DT_IS_ARRAY_BIT_SIZE) - 1u) << DT_IS_ARRAY_OFFSET); } bool dtIsStruct(DataType dt) { return dtGetType(dt) == RDT_STRUCT; } bool dtIsPointer(DataType dt) { return dt.data & (((1u << DT_IS_POINTER_BIT_SIZE) - 1u) << DT_IS_POINTER_OFFSET); } Struct* dtGetStruct(const Structs* sts, DataType dt) { if(!dtIsStruct(dt)) { return NULL; } int32 structId = (int32)((dt.data >> DT_STRUCT_ID_OFFSET) & ((1u << DT_STRUCT_ID_BIT_SIZE) - 1u)); if(structId & 1) { if(!useGlobals) { return NULL; } structId >>= 1; if(structId < 0 || structId >= globalStructs.entries) { return NULL; } return globalStructs.data + structId; } structId >>= 1; if(structId < 0 || structId >= sts->entries) { return NULL; } return sts->data + structId; } void stAddVariable(Struct* st, const char* name, DataType type) { int index = st->amount; st->amount++; st->vars = (StructVariable*)realloc(st->vars, sizeof(StructVariable) * (size_t)st->amount); st->vars[index].name = name; st->vars[index].type = type; } void stsInit(Structs* sts) { sts->capacity = 4; sts->entries = 0; sts->data = (Struct*)malloc(sizeof(Struct) * (size_t)sts->capacity); } void stsDelete(Structs* sts) { for(int i = 0; i < sts->entries; i++) { free(sts->data[i].vars); } free(sts->data); } static Struct* stsInternSearch(Structs* sts, const char* name) { for(int i = 0; i < sts->entries; i++) { if(strcmp(sts->data[i].name, name) == 0) { return sts->data + i; } } return NULL; } Struct* stsSearch(Structs* sts, const char* name) { if(useGlobals) { Struct* st = stsInternSearch(&globalStructs, name); if(st != NULL) { return st; } } return stsInternSearch(sts, name); } Struct* stsAdd(Structs* sts, const char* name) { if(sts->entries >= sts->capacity) { sts->capacity *= 2; sts->data = (Struct*)realloc(sts->data, sizeof(Struct) * (size_t)sts->capacity); } uint16 index = (uint16)sts->entries++; sts->data[index].id = (uint16)(index << 1); sts->data[index].amount = 0; sts->data[index].name = name; sts->data[index].vars = NULL; return sts->data + index; } void gstsInit(void) { stsInit(&globalStructs); useGlobals = true; } void gstsDelete(void) { stsDelete(&globalStructs); useGlobals = false; } Structs* gstsGet(void) { return &globalStructs; } Struct* gstsAdd(const char* name) { Struct* st = stsAdd(&globalStructs, name); st->id |= 1; return st; }