mirror of
https://github.com/DrBeef/Raze.git
synced 2025-01-19 07:31:03 +00:00
- backend update from GZDoom.
This commit is contained in:
parent
4666c4a4b5
commit
1061e3e2ca
31 changed files with 2760 additions and 116 deletions
|
@ -117,6 +117,7 @@ xx(Double)
|
||||||
xx(String)
|
xx(String)
|
||||||
xx(Vector)
|
xx(Vector)
|
||||||
xx(Map)
|
xx(Map)
|
||||||
|
xx(MapIterator)
|
||||||
xx(Array)
|
xx(Array)
|
||||||
xx(Include)
|
xx(Include)
|
||||||
xx(Sound)
|
xx(Sound)
|
||||||
|
@ -162,6 +163,14 @@ xx(ToVector)
|
||||||
xx(Size)
|
xx(Size)
|
||||||
xx(Push)
|
xx(Push)
|
||||||
xx(Insert)
|
xx(Insert)
|
||||||
|
xx(InsertNew)
|
||||||
|
xx(Remove)
|
||||||
|
xx(Get)
|
||||||
|
xx(GetValue)
|
||||||
|
xx(GetKey)
|
||||||
|
xx(SetValue)
|
||||||
|
xx(CheckKey)
|
||||||
|
xx(Value)
|
||||||
xx(Copy)
|
xx(Copy)
|
||||||
xx(Move)
|
xx(Move)
|
||||||
xx(Voidptr)
|
xx(Voidptr)
|
||||||
|
@ -174,6 +183,7 @@ xx(IsNull)
|
||||||
xx(Exists)
|
xx(Exists)
|
||||||
xx(SetInvalid)
|
xx(SetInvalid)
|
||||||
xx(SetNull)
|
xx(SetNull)
|
||||||
|
xx(Key)
|
||||||
|
|
||||||
// color channels
|
// color channels
|
||||||
xx(a)
|
xx(a)
|
||||||
|
|
|
@ -88,7 +88,7 @@ int Printf (const char *format, ...) ATTRIBUTE((format(printf,1,2)));
|
||||||
int DPrintf (int level, const char *format, ...) ATTRIBUTE((format(printf,2,3)));
|
int DPrintf (int level, const char *format, ...) ATTRIBUTE((format(printf,2,3)));
|
||||||
|
|
||||||
void I_DebugPrint(const char* cp);
|
void I_DebugPrint(const char* cp);
|
||||||
void debugprintf(const char* f, ...); // Prints to the debugger's log.
|
void I_DebugPrintf(const char* fmt, ...); // Prints to the debugger's log.
|
||||||
|
|
||||||
// flag to silence non-error output
|
// flag to silence non-error output
|
||||||
extern bool batchrun;
|
extern bool batchrun;
|
||||||
|
|
|
@ -167,6 +167,7 @@ std2:
|
||||||
'vector2' { RET(TK_Vector2); }
|
'vector2' { RET(TK_Vector2); }
|
||||||
'vector3' { RET(TK_Vector3); }
|
'vector3' { RET(TK_Vector3); }
|
||||||
'map' { RET(TK_Map); }
|
'map' { RET(TK_Map); }
|
||||||
|
'mapiterator' { RET(TK_MapIterator); }
|
||||||
'array' { RET(TK_Array); }
|
'array' { RET(TK_Array); }
|
||||||
'in' { RET(TK_In); }
|
'in' { RET(TK_In); }
|
||||||
'sizeof' { RET(TK_SizeOf); }
|
'sizeof' { RET(TK_SizeOf); }
|
||||||
|
|
|
@ -128,6 +128,7 @@ xx(TK_Replaces, "'replaces'")
|
||||||
xx(TK_Vector2, "'vector2'")
|
xx(TK_Vector2, "'vector2'")
|
||||||
xx(TK_Vector3, "'vector3'")
|
xx(TK_Vector3, "'vector3'")
|
||||||
xx(TK_Map, "'map'")
|
xx(TK_Map, "'map'")
|
||||||
|
xx(TK_MapIterator, "'mapiterator'")
|
||||||
xx(TK_Array, "'array'")
|
xx(TK_Array, "'array'")
|
||||||
xx(TK_In, "'in'")
|
xx(TK_In, "'in'")
|
||||||
xx(TK_SizeOf, "'sizeof'")
|
xx(TK_SizeOf, "'sizeof'")
|
||||||
|
|
|
@ -443,4 +443,5 @@ void LoadHexFont(const char* filename)
|
||||||
auto hexfont = resf->FindLump("newconsolefont.hex");
|
auto hexfont = resf->FindLump("newconsolefont.hex");
|
||||||
if (hexfont == nullptr) I_FatalError("Unable to find newconsolefont.hex in %s", filename);
|
if (hexfont == nullptr) I_FatalError("Unable to find newconsolefont.hex in %s", filename);
|
||||||
hexdata.ParseDefinition(hexfont);
|
hexdata.ParseDefinition(hexfont);
|
||||||
|
delete resf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -544,7 +544,7 @@ inline FVector3 FOBJModel::RealignVector(FVector3 vecToRealign)
|
||||||
*/
|
*/
|
||||||
inline FVector2 FOBJModel::FixUV(FVector2 vecToRealign)
|
inline FVector2 FOBJModel::FixUV(FVector2 vecToRealign)
|
||||||
{
|
{
|
||||||
vecToRealign.Y *= -1;
|
vecToRealign.Y = 1-vecToRealign.Y;
|
||||||
return vecToRealign;
|
return vecToRealign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "i_time.h"
|
#include "i_time.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
#include "maps.h"
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -342,6 +343,17 @@ DEFINE_ACTION_FUNCTION(DObject, Destroy)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
template<typename M>
|
||||||
|
static void PropagateMarkMap(M *map)
|
||||||
|
{
|
||||||
|
TMapIterator<typename M::KeyType,DObject*> it(*map);
|
||||||
|
typename M::Pair * p;
|
||||||
|
while(it.NextPair(p))
|
||||||
|
{
|
||||||
|
GC::Mark(&p->Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t DObject::PropagateMark()
|
size_t DObject::PropagateMark()
|
||||||
{
|
{
|
||||||
const PClass *info = GetClass();
|
const PClass *info = GetClass();
|
||||||
|
@ -375,6 +387,27 @@ size_t DObject::PropagateMark()
|
||||||
offsets++;
|
offsets++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const std::pair<size_t,PType *> *maps = info->MapPointers;
|
||||||
|
if (maps == NULL)
|
||||||
|
{
|
||||||
|
const_cast<PClass *>(info)->BuildMapPointers();
|
||||||
|
maps = info->MapPointers;
|
||||||
|
}
|
||||||
|
while (maps->first != ~(size_t)0)
|
||||||
|
{
|
||||||
|
if(maps->second->RegType == REGT_STRING)
|
||||||
|
{ // FString,DObject*
|
||||||
|
PropagateMarkMap((ZSMap<FString,DObject*>*)((uint8_t *)this + maps->first));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // uint32_t,DObject*
|
||||||
|
PropagateMarkMap((ZSMap<uint32_t,DObject*>*)((uint8_t *)this + maps->first));
|
||||||
|
}
|
||||||
|
maps++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return info->Size;
|
return info->Size;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -82,6 +82,8 @@ DEFINE_GLOBAL(WP_NOCHANGE);
|
||||||
// A harmless non-nullptr FlatPointer for classes without pointers.
|
// A harmless non-nullptr FlatPointer for classes without pointers.
|
||||||
static const size_t TheEnd = ~(size_t)0;
|
static const size_t TheEnd = ~(size_t)0;
|
||||||
|
|
||||||
|
static const std::pair<size_t,PType *> TheMapEnd = {~(size_t)0 , nullptr};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PClass :: WriteValue
|
// PClass :: WriteValue
|
||||||
|
@ -877,6 +879,68 @@ void PClass::BuildArrayPointers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PClass :: BuildMapPointers
|
||||||
|
//
|
||||||
|
// same as above, but creates a list to dynamic object arrays
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PClass::BuildMapPointers()
|
||||||
|
{
|
||||||
|
if (MapPointers != nullptr)
|
||||||
|
{ // Already built: Do nothing.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (ParentClass == nullptr)
|
||||||
|
{ // No parent (i.e. DObject: FlatPointers is the same as Pointers.
|
||||||
|
MapPointers = &TheMapEnd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ParentClass->BuildMapPointers();
|
||||||
|
|
||||||
|
TArray<std::pair<size_t,PType *>> ScriptPointers;
|
||||||
|
|
||||||
|
// Collect all arrays to pointers in scripted fields.
|
||||||
|
for (auto field : Fields)
|
||||||
|
{
|
||||||
|
if (!(field->Flags & VARF_Native))
|
||||||
|
{
|
||||||
|
field->Type->SetPointerMap(Defaults, unsigned(field->Offset), &ScriptPointers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ScriptPointers.Size() == 0)
|
||||||
|
{ // No new pointers: Just use the same ArrayPointers as the parent.
|
||||||
|
MapPointers = ParentClass->MapPointers;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // New pointers: Create a new FlatPointers array and add them.
|
||||||
|
int numSuperPointers;
|
||||||
|
|
||||||
|
// Count pointers defined by superclasses.
|
||||||
|
for (numSuperPointers = 0; ParentClass->MapPointers[numSuperPointers].first != ~(size_t)0; numSuperPointers++)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Concatenate them into a new array
|
||||||
|
std::pair<size_t,PType *> *flat = (std::pair<size_t,PType *>*)ClassDataAllocator.Alloc(sizeof(std::pair<size_t,PType *>) * (numSuperPointers + ScriptPointers.Size() + 1));
|
||||||
|
if (numSuperPointers > 0)
|
||||||
|
{
|
||||||
|
memcpy(flat, ParentClass->MapPointers, sizeof(std::pair<size_t,PType *>)*numSuperPointers);
|
||||||
|
}
|
||||||
|
if (ScriptPointers.Size() > 0)
|
||||||
|
{
|
||||||
|
memcpy(flat + numSuperPointers, &ScriptPointers[0], sizeof(std::pair<size_t,PType *>) * ScriptPointers.Size());
|
||||||
|
}
|
||||||
|
flat[numSuperPointers + ScriptPointers.Size()] = TheMapEnd;
|
||||||
|
MapPointers = flat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PClass :: NativeClass
|
// PClass :: NativeClass
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
const size_t *Pointers = nullptr; // object pointers defined by this class *only*
|
const size_t *Pointers = nullptr; // object pointers defined by this class *only*
|
||||||
const size_t *FlatPointers = nullptr; // object pointers defined by this class and all its superclasses; not initialized by default
|
const size_t *FlatPointers = nullptr; // object pointers defined by this class and all its superclasses; not initialized by default
|
||||||
const size_t *ArrayPointers = nullptr; // dynamic arrays containing object pointers.
|
const size_t *ArrayPointers = nullptr; // dynamic arrays containing object pointers.
|
||||||
|
const std::pair<size_t,PType *> *MapPointers = nullptr; // maps containing object pointers.
|
||||||
uint8_t *Defaults = nullptr;
|
uint8_t *Defaults = nullptr;
|
||||||
uint8_t *Meta = nullptr; // Per-class static script data
|
uint8_t *Meta = nullptr; // Per-class static script data
|
||||||
unsigned Size = sizeof(DObject);
|
unsigned Size = sizeof(DObject);
|
||||||
|
@ -84,6 +85,7 @@ public:
|
||||||
void InitializeActorInfo();
|
void InitializeActorInfo();
|
||||||
void BuildFlatPointers();
|
void BuildFlatPointers();
|
||||||
void BuildArrayPointers();
|
void BuildArrayPointers();
|
||||||
|
void BuildMapPointers();
|
||||||
void DestroySpecials(void *addr);
|
void DestroySpecials(void *addr);
|
||||||
void DestroyMeta(void *addr);
|
void DestroyMeta(void *addr);
|
||||||
const PClass *NativeClass() const;
|
const PClass *NativeClass() const;
|
||||||
|
|
|
@ -8205,6 +8205,8 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
PContainerType *ccls = nullptr;
|
PContainerType *ccls = nullptr;
|
||||||
|
|
||||||
|
PFunction * afd_override = nullptr;
|
||||||
|
|
||||||
if (ctx.Class == nullptr)
|
if (ctx.Class == nullptr)
|
||||||
{
|
{
|
||||||
// There's no way that a member function call can resolve to a constant so abort right away.
|
// There's no way that a member function call can resolve to a constant so abort right away.
|
||||||
|
@ -8278,7 +8280,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
if (Self->ValueType->isRealPointer())
|
if (Self->ValueType->isRealPointer())
|
||||||
{
|
{
|
||||||
auto pointedType = Self->ValueType->toPointer()->PointedType;
|
auto pointedType = Self->ValueType->toPointer()->PointedType;
|
||||||
if (pointedType && pointedType->isDynArray())
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
{
|
{
|
||||||
Self = new FxOutVarDereference(Self, Self->ScriptPosition);
|
Self = new FxOutVarDereference(Self, Self->ScriptPosition);
|
||||||
SAFE_RESOLVE(Self, ctx);
|
SAFE_RESOLVE(Self, ctx);
|
||||||
|
@ -8454,7 +8456,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
if (a->ValueType->isRealPointer())
|
if (a->ValueType->isRealPointer())
|
||||||
{
|
{
|
||||||
auto pointedType = a->ValueType->toPointer()->PointedType;
|
auto pointedType = a->ValueType->toPointer()->PointedType;
|
||||||
if (pointedType && pointedType->isDynArray())
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
{
|
{
|
||||||
a = new FxOutVarDereference(a, a->ScriptPosition);
|
a = new FxOutVarDereference(a, a->ScriptPosition);
|
||||||
SAFE_RESOLVE(a, ctx);
|
SAFE_RESOLVE(a, ctx);
|
||||||
|
@ -8561,6 +8563,193 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(Self->IsMap())
|
||||||
|
{
|
||||||
|
PMap * m = static_cast<PMap*>(Self->ValueType);
|
||||||
|
Self->ValueType = m->BackingType;
|
||||||
|
|
||||||
|
auto mapKeyType = m->KeyType;
|
||||||
|
auto mapValueType = m->ValueType;
|
||||||
|
|
||||||
|
bool isObjMap = mapValueType->isObjectPointer();
|
||||||
|
|
||||||
|
if (PFunction **Override; (Override = m->FnOverrides.CheckKey(MethodName)))
|
||||||
|
{
|
||||||
|
afd_override = *Override;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapted from DynArray codegen
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for (auto &a : ArgList)
|
||||||
|
{
|
||||||
|
a = a->Resolve(ctx);
|
||||||
|
if (a == nullptr)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (a->ValueType->isRealPointer())
|
||||||
|
{
|
||||||
|
auto pointedType = a->ValueType->toPointer()->PointedType;
|
||||||
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
|
{
|
||||||
|
a = new FxOutVarDereference(a, a->ScriptPosition);
|
||||||
|
SAFE_RESOLVE(a, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isObjMap && (MethodName == NAME_Insert && idx == 1))
|
||||||
|
{
|
||||||
|
// Null pointers are always valid.
|
||||||
|
if (!a->isConstant() || static_cast<FxConstant*>(a)->GetValue().GetPointer() != nullptr)
|
||||||
|
{
|
||||||
|
if (!a->ValueType->isObjectPointer() ||
|
||||||
|
!static_cast<PObjectPointer*>(mapValueType)->PointedClass()->IsAncestorOf(static_cast<PObjectPointer*>(a->ValueType)->PointedClass()))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->IsMap())
|
||||||
|
{
|
||||||
|
// Copy and Move must turn their parameter into a pointer to the backing struct type.
|
||||||
|
auto o = static_cast<PMap*>(a->ValueType);
|
||||||
|
auto backingtype = o->BackingType;
|
||||||
|
if (mapKeyType != o->KeyType || mapValueType != o->ValueType)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
bool writable;
|
||||||
|
if (!a->RequestAddress(ctx, &writable))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Unable to dereference map variable");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
a->ValueType = NewPointer(backingtype);
|
||||||
|
|
||||||
|
// Also change the field's type so the code generator can work with this (actually this requires swapping out the entire field.)
|
||||||
|
if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_StackVariable)
|
||||||
|
{
|
||||||
|
auto member = static_cast<FxMemberBase*>(Self);
|
||||||
|
auto newfield = Create<PField>(NAME_None, backingtype, 0, member->membervar->Offset);
|
||||||
|
member->membervar = newfield;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (a->IsPointer() && Self->ValueType->isPointer())
|
||||||
|
{
|
||||||
|
// the only case which must be checked up front is for pointer arrays receiving a new element.
|
||||||
|
// Since there is only one native backing class it uses a neutral void pointer as its argument,
|
||||||
|
// meaning that FxMemberFunctionCall is unable to do a proper check. So we have to do it here.
|
||||||
|
if (a->ValueType != mapValueType)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument. Got %s, expected %s", a->ValueType->DescriptiveName(), mapValueType->DescriptiveName());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(Self->IsMapIterator())
|
||||||
|
{
|
||||||
|
PMapIterator * mi = static_cast<PMapIterator*>(Self->ValueType);
|
||||||
|
Self->ValueType = mi->BackingType;
|
||||||
|
|
||||||
|
auto mapKeyType = mi->KeyType;
|
||||||
|
auto mapValueType = mi->ValueType;
|
||||||
|
|
||||||
|
bool isObjMap = mapValueType->isObjectPointer();
|
||||||
|
|
||||||
|
if (PFunction **Override; (Override = mi->FnOverrides.CheckKey(MethodName)))
|
||||||
|
{
|
||||||
|
afd_override = *Override;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adapted from DynArray codegen
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for (auto &a : ArgList)
|
||||||
|
{
|
||||||
|
a = a->Resolve(ctx);
|
||||||
|
if (a == nullptr)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (a->ValueType->isRealPointer())
|
||||||
|
{
|
||||||
|
auto pointedType = a->ValueType->toPointer()->PointedType;
|
||||||
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
|
{
|
||||||
|
a = new FxOutVarDereference(a, a->ScriptPosition);
|
||||||
|
SAFE_RESOLVE(a, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isObjMap && (MethodName == NAME_SetValue && idx == 0))
|
||||||
|
{
|
||||||
|
// Null pointers are always valid.
|
||||||
|
if (!a->isConstant() || static_cast<FxConstant*>(a)->GetValue().GetPointer() != nullptr)
|
||||||
|
{
|
||||||
|
if (!a->ValueType->isObjectPointer() ||
|
||||||
|
!static_cast<PObjectPointer*>(mapValueType)->PointedClass()->IsAncestorOf(static_cast<PObjectPointer*>(a->ValueType)->PointedClass()))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a->IsMap())
|
||||||
|
{
|
||||||
|
// Copy and Move must turn their parameter into a pointer to the backing struct type.
|
||||||
|
auto o = static_cast<PMapIterator*>(a->ValueType);
|
||||||
|
auto backingtype = o->BackingType;
|
||||||
|
if (mapKeyType != o->KeyType || mapValueType != o->ValueType)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
bool writable;
|
||||||
|
if (!a->RequestAddress(ctx, &writable))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Unable to dereference map variable");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
a->ValueType = NewPointer(backingtype);
|
||||||
|
|
||||||
|
// Also change the field's type so the code generator can work with this (actually this requires swapping out the entire field.)
|
||||||
|
if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_StackVariable)
|
||||||
|
{
|
||||||
|
auto member = static_cast<FxMemberBase*>(Self);
|
||||||
|
auto newfield = Create<PField>(NAME_None, backingtype, 0, member->membervar->Offset);
|
||||||
|
member->membervar = newfield;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (a->IsPointer() && Self->ValueType->isPointer())
|
||||||
|
{
|
||||||
|
// the only case which must be checked up front is for pointer arrays receiving a new element.
|
||||||
|
// Since there is only one native backing class it uses a neutral void pointer as its argument,
|
||||||
|
// meaning that FxMemberFunctionCall is unable to do a proper check. So we have to do it here.
|
||||||
|
if (a->ValueType != mapValueType)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument. Got %s, expected %s", a->ValueType->DescriptiveName(), mapValueType->DescriptiveName());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (MethodName == NAME_GetParentClass &&
|
if (MethodName == NAME_GetParentClass &&
|
||||||
|
@ -8635,7 +8824,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
|
|
||||||
isresolved:
|
isresolved:
|
||||||
bool error = false;
|
bool error = false;
|
||||||
PFunction *afd = FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error, ctx.Version, !ctx.FromDecorate);
|
PFunction *afd = afd_override ? afd_override : FindClassMemberFunction(cls, ctx.Class, MethodName, ScriptPosition, &error, ctx.Version, !ctx.FromDecorate);
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -9034,7 +9223,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
if (ArgList[i] && ArgList[i]->ValueType->isRealPointer())
|
if (ArgList[i] && ArgList[i]->ValueType->isRealPointer())
|
||||||
{
|
{
|
||||||
auto pointedType = ArgList[i]->ValueType->toPointer()->PointedType;
|
auto pointedType = ArgList[i]->ValueType->toPointer()->PointedType;
|
||||||
if (pointedType && pointedType->isDynArray())
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
{
|
{
|
||||||
ArgList[i] = new FxOutVarDereference(ArgList[i], ArgList[i]->ScriptPosition);
|
ArgList[i] = new FxOutVarDereference(ArgList[i], ArgList[i]->ScriptPosition);
|
||||||
SAFE_RESOLVE(ArgList[i], ctx);
|
SAFE_RESOLVE(ArgList[i], ctx);
|
||||||
|
@ -11806,7 +11995,7 @@ FxExpression *FxOutVarDereference::Resolve(FCompileContext &ctx)
|
||||||
SelfType = Self->ValueType->toPointer()->PointedType;
|
SelfType = Self->ValueType->toPointer()->PointedType;
|
||||||
ValueType = SelfType;
|
ValueType = SelfType;
|
||||||
|
|
||||||
if (SelfType->GetRegType() == REGT_NIL && !SelfType->isRealPointer() && !SelfType->isDynArray())
|
if (SelfType->GetRegType() == REGT_NIL && !SelfType->isRealPointer() && !SelfType->isDynArray() && !SelfType->isMap() && !SelfType->isMapIterator())
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Cannot dereference pointer");
|
ScriptPosition.Message(MSG_ERROR, "Cannot dereference pointer");
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -11835,7 +12024,7 @@ ExpEmit FxOutVarDereference::Emit(VMFunctionBuilder *build)
|
||||||
regType = REGT_POINTER;
|
regType = REGT_POINTER;
|
||||||
loadOp = OP_LP;
|
loadOp = OP_LP;
|
||||||
}
|
}
|
||||||
else if (SelfType->isDynArray())
|
else if (SelfType->isDynArray() || SelfType->isMap() || SelfType->isMapIterator())
|
||||||
{
|
{
|
||||||
regType = REGT_POINTER;
|
regType = REGT_POINTER;
|
||||||
loadOp = OP_MOVEA;
|
loadOp = OP_MOVEA;
|
||||||
|
|
|
@ -350,6 +350,8 @@ public:
|
||||||
bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); }
|
bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); }
|
||||||
bool isStaticArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->isStaticArray()); } // can only exist in pointer form.
|
bool isStaticArray() const { return (ValueType->isPointer() && ValueType->toPointer()->PointedType->isStaticArray()); } // can only exist in pointer form.
|
||||||
bool IsDynamicArray() const { return (ValueType->isDynArray()); }
|
bool IsDynamicArray() const { return (ValueType->isDynArray()); }
|
||||||
|
bool IsMap() const { return ValueType->isMap(); }
|
||||||
|
bool IsMapIterator() const { return ValueType->isMapIterator(); }
|
||||||
bool IsStruct() const { return ValueType->isStruct(); }
|
bool IsStruct() const { return ValueType->isStruct(); }
|
||||||
bool IsNativeStruct() const { return (ValueType->isStruct() && static_cast<PStruct*>(ValueType)->isNative); }
|
bool IsNativeStruct() const { return (ValueType->isStruct() && static_cast<PStruct*>(ValueType)->isNative); }
|
||||||
|
|
||||||
|
|
483
source/common/scripting/core/maps.cpp
Normal file
483
source/common/scripting/core/maps.cpp
Normal file
|
@ -0,0 +1,483 @@
|
||||||
|
#include "tarray.h"
|
||||||
|
#include "dobject.h"
|
||||||
|
#include "zstring.h"
|
||||||
|
#include "vm.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "v_draw.h"
|
||||||
|
#include "maps.h"
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MAP_GC_WRITE_BARRIER
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
#define MAP_GC_WRITE_BARRIER(x) { \
|
||||||
|
TMapIterator<typename M::KeyType, DObject*> it(*x);\
|
||||||
|
typename M::Pair * p;\
|
||||||
|
while(it.NextPair(p)){\
|
||||||
|
GC::WriteBarrier(p->Value);\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MapCopy
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapCopy(M * self, M * other)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType,DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(other);
|
||||||
|
}
|
||||||
|
*self = *other; // how does this handle self->info? TODO double check.
|
||||||
|
self->info->rev++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MapMove
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapMove(M * self, M * other)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType,DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(other);
|
||||||
|
}
|
||||||
|
self->TransferFrom(*other);
|
||||||
|
self->info->rev++;
|
||||||
|
other->info->rev++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MapSwap
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapSwap(M * self, M * other)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType,DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(other);
|
||||||
|
}
|
||||||
|
self->Swap(*other);
|
||||||
|
self->info->rev++;
|
||||||
|
other->info->rev++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MapClear
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapClear(M * self)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType,DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(self);
|
||||||
|
}
|
||||||
|
self->Clear();
|
||||||
|
self->info->rev++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using expand_types_vm =
|
||||||
|
std::conditional_t<std::is_same_v<T, uint8_t> || std::is_same_v<T, uint16_t>, uint32_t , /* expand 8/16-bit to 32-bit */
|
||||||
|
std::conditional_t<std::is_same_v<T, float> , double , /* expand float to double */
|
||||||
|
std::conditional_t<std::is_same_v<T, FString> , const FString & , T>>>; /* change String to String ref */
|
||||||
|
|
||||||
|
template<typename M> unsigned int MapCountUsed(M * self)
|
||||||
|
{
|
||||||
|
return self->CountUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename M> expand_types_vm<typename M::ValueType> MapGet(M * self,expand_types_vm<typename M::KeyType> key)
|
||||||
|
{
|
||||||
|
typename M::ValueType * v = self->CheckKey(key);
|
||||||
|
if (v) {
|
||||||
|
return *v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
typename M::ValueType n {};
|
||||||
|
self->Insert(key,n);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename M> void MapGetString(M * self,expand_types_vm<typename M::KeyType> key, FString &out)
|
||||||
|
{
|
||||||
|
FString * v = self->CheckKey(key);
|
||||||
|
if (v) {
|
||||||
|
out = *v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out = FString();
|
||||||
|
self->Insert(key,out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename M> int MapCheckKey(M * self, expand_types_vm<typename M::KeyType> key)
|
||||||
|
{
|
||||||
|
return self->CheckKey(key) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// MapInsert
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapInsert(M * self, expand_types_vm<typename M::KeyType> key, expand_types_vm<typename M::ValueType> value)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType, DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(self);
|
||||||
|
GC::WriteBarrier(value);
|
||||||
|
}
|
||||||
|
self->Insert(key, value);
|
||||||
|
self->info->rev++; // invalidate iterators
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M> void MapInsertNew(M * self, expand_types_vm<typename M::KeyType> key)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::ValueType, DObject*>)
|
||||||
|
{
|
||||||
|
MAP_GC_WRITE_BARRIER(self);
|
||||||
|
}
|
||||||
|
self->Insert(key,{});
|
||||||
|
self->info->rev++; // invalidate iterators
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename M> void MapRemove(M * self, expand_types_vm<typename M::KeyType> key)
|
||||||
|
{
|
||||||
|
self->Remove(key);
|
||||||
|
self->info->rev++; // invalidate iterators
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename I, typename M> int MapIteratorInit(I * self, M * other)
|
||||||
|
{
|
||||||
|
return self->Init(*other);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> int MapIteratorReInit(I * self)
|
||||||
|
{
|
||||||
|
return self->ReInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> int MapIteratorValid(I * self)
|
||||||
|
{
|
||||||
|
return self->Valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> int MapIteratorNext(I * self)
|
||||||
|
{
|
||||||
|
return self->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> expand_types_vm<typename I::KeyType> MapIteratorGetKey(I * self)
|
||||||
|
{
|
||||||
|
return self->GetKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> void MapIteratorGetKeyString(I * self, FString &out)
|
||||||
|
{
|
||||||
|
out = self->GetKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> expand_types_vm<typename I::ValueType> MapIteratorGetValue(I * self)
|
||||||
|
{
|
||||||
|
return self->GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> void MapIteratorGetValueString(I * self, FString &out)
|
||||||
|
{
|
||||||
|
out = self->GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename I> void MapIteratorSetValue(I * self, expand_types_vm<typename I::ValueType> value)
|
||||||
|
{
|
||||||
|
auto & val = self->GetValue();
|
||||||
|
if constexpr(std::is_same_v<typename I::ValueType, DObject*>)
|
||||||
|
{
|
||||||
|
GC::WriteBarrier(val);
|
||||||
|
GC::WriteBarrier(value);
|
||||||
|
}
|
||||||
|
val = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
#define PARAM_VOIDPOINTER(X) PARAM_POINTER( X , void )
|
||||||
|
#define PARAM_OBJPOINTER(X) PARAM_OBJECT( X , DObject )
|
||||||
|
|
||||||
|
#define _DEF_MAP( name, key_type, value_type, PARAM_KEY, PARAM_VALUE ) \
|
||||||
|
typedef ZSMap<key_type , value_type> name;\
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Copy , MapCopy< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_POINTER( other, name ); \
|
||||||
|
MapCopy(self , other); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Move , MapMove< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_POINTER( other, name ); \
|
||||||
|
MapMove(self , other); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Swap , MapSwap< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_POINTER( other, name ); \
|
||||||
|
MapSwap(self , other); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Clear , MapClear< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
MapClear(self); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, CountUsed, MapCountUsed< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_INT( MapCountUsed(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, CheckKey, MapCheckKey< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
ACTION_RETURN_BOOL( MapCheckKey(self, key) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, Insert, MapInsert< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
PARAM_VALUE( value ); \
|
||||||
|
MapInsert(self, key, value); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, InsertNew, MapInsertNew< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
MapInsertNew(self, key); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, Remove, MapRemove< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
MapRemove(self, key); \
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_MAP_X_X( name, key_type, value_type, PARAM_KEY, PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
_DEF_MAP( name , key_type , value_type , PARAM_KEY , PARAM_VALUE ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, Get, MapGet< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
ACTION_RETURN_VALUE( MapGet(self, key) ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_MAP_X_S( name, key_type, PARAM_KEY ) \
|
||||||
|
_DEF_MAP( name , key_type , FString , PARAM_KEY , PARAM_STRING ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name, Get, MapGetString< name >) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_KEY( key ); \
|
||||||
|
FString out; \
|
||||||
|
MapGetString(self, key, out); \
|
||||||
|
ACTION_RETURN_STRING( out ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define COMMA ,
|
||||||
|
|
||||||
|
#define _DEF_MAP_IT( map_name , name, key_type, value_type, PARAM_VALUE ) \
|
||||||
|
typedef ZSMapIterator<key_type , value_type> name; \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Init , MapIteratorInit< name COMMA map_name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_POINTER( other, map_name ); \
|
||||||
|
ACTION_RETURN_BOOL( MapIteratorInit(self , other) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , ReInit , MapIteratorReInit< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_BOOL( MapIteratorReInit(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Valid , MapIteratorValid< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_BOOL( MapIteratorValid(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , Next , MapIteratorNext< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_BOOL( MapIteratorNext(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , SetValue , MapIteratorSetValue< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
PARAM_VALUE( value ); \
|
||||||
|
MapIteratorSetValue(self, value); \
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetKey , MapIteratorGetKey< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_KEY( MapIteratorGetKey(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetValue , MapIteratorGetValue< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_VALUE( MapIteratorGetValue(self) ); \
|
||||||
|
} \
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DEF_MAP_IT_I_X( map_name , name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
_DEF_MAP_IT( map_name , name , uint32_t , value_type , PARAM_VALUE ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetKey , MapIteratorGetKey< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_INT( MapIteratorGetKey(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetValue , MapIteratorGetValue< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_VALUE( MapIteratorGetValue(self) ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_MAP_IT_S_X( map_name , name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
_DEF_MAP_IT( map_name , name , FString , value_type , PARAM_VALUE ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetKey , MapIteratorGetKeyString< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
FString out; \
|
||||||
|
MapIteratorGetKeyString(self , out); \
|
||||||
|
ACTION_RETURN_STRING( out ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( name , GetValue , MapIteratorGetValue< name > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||||
|
ACTION_RETURN_VALUE( MapIteratorGetValue(self) ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_MAP_IT_I_S() \
|
||||||
|
_DEF_MAP_IT( FMap_I32_Str , FMapIterator_I32_Str , uint32_t , FString , PARAM_STRING ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_I32_Str , GetKey , MapIteratorGetKey< FMapIterator_I32_Str > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_I32_Str ); \
|
||||||
|
ACTION_RETURN_INT( MapIteratorGetKey(self) ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_I32_Str , GetValue , MapIteratorGetValue< FMapIterator_I32_Str > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_I32_Str ); \
|
||||||
|
ACTION_RETURN_STRING( MapIteratorGetValue(self) ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_MAP_IT_S_S() \
|
||||||
|
_DEF_MAP_IT( FMap_Str_Str , FMapIterator_Str_Str , FString , FString , PARAM_STRING ) \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_Str_Str , GetKey , MapIteratorGetKeyString< FMapIterator_Str_Str > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_Str_Str ); \
|
||||||
|
FString out; \
|
||||||
|
MapIteratorGetKeyString(self , out); \
|
||||||
|
ACTION_RETURN_STRING( out ); \
|
||||||
|
} \
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE( FMapIterator_Str_Str , GetValue , MapIteratorGetValueString< FMapIterator_Str_Str > ) \
|
||||||
|
{ \
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE( FMapIterator_Str_Str ); \
|
||||||
|
FString out; \
|
||||||
|
MapIteratorGetValueString(self , out); \
|
||||||
|
ACTION_RETURN_STRING( out ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFINE_MAP_AND_IT_I_X( name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
DEF_MAP_X_X( FMap_ ## name , uint32_t , value_type , PARAM_INT , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
DEF_MAP_IT_I_X( FMap_ ## name , FMapIterator_ ## name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE )
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFINE_MAP_AND_IT_S_X( name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
DEF_MAP_X_X( FMap_ ## name , FString , value_type , PARAM_STRING , PARAM_VALUE , ACTION_RETURN_VALUE ) \
|
||||||
|
DEF_MAP_IT_S_X( FMap_ ## name , FMapIterator_ ## name , value_type , PARAM_VALUE , ACTION_RETURN_VALUE )
|
||||||
|
|
||||||
|
#define DEFINE_MAP_AND_IT_I_S() \
|
||||||
|
DEF_MAP_X_S( FMap_I32_Str , uint32_t , PARAM_INT ) \
|
||||||
|
DEF_MAP_IT_I_S()
|
||||||
|
|
||||||
|
#define DEFINE_MAP_AND_IT_S_S() \
|
||||||
|
DEF_MAP_X_S( FMap_Str_Str , FString , PARAM_STRING ) \
|
||||||
|
DEF_MAP_IT_S_S()
|
||||||
|
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_I8 , uint8_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_I16 , uint16_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_I32 , uint32_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_F32 , float , PARAM_FLOAT , ACTION_RETURN_FLOAT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_F64 , double , PARAM_FLOAT , ACTION_RETURN_FLOAT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_Obj , DObject* , PARAM_OBJPOINTER , ACTION_RETURN_OBJECT);
|
||||||
|
DEFINE_MAP_AND_IT_I_X(I32_Ptr , void* , PARAM_VOIDPOINTER , ACTION_RETURN_POINTER);
|
||||||
|
DEFINE_MAP_AND_IT_I_S();
|
||||||
|
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_I8 , uint8_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_I16 , uint16_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_I32 , uint32_t , PARAM_INT , ACTION_RETURN_INT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_F32 , float , PARAM_FLOAT , ACTION_RETURN_FLOAT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_F64 , double , PARAM_FLOAT , ACTION_RETURN_FLOAT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_Obj , DObject* , PARAM_OBJPOINTER , ACTION_RETURN_OBJECT);
|
||||||
|
DEFINE_MAP_AND_IT_S_X(Str_Ptr , void* , PARAM_VOIDPOINTER , ACTION_RETURN_POINTER);
|
||||||
|
DEFINE_MAP_AND_IT_S_S();
|
110
source/common/scripting/core/maps.h
Normal file
110
source/common/scripting/core/maps.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "tarray.h"
|
||||||
|
#include "refcounted.h"
|
||||||
|
|
||||||
|
class ZSMapInfo : public RefCountedBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void * self = nullptr;
|
||||||
|
int rev = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZSFMap : FMap {
|
||||||
|
RefCountedPtr<RefCountedBase> info;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class KT, class VT>
|
||||||
|
class ZSMap : public TMap<KT,VT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RefCountedPtr<ZSMapInfo> info;
|
||||||
|
ZSMap() :
|
||||||
|
TMap<KT,VT>(), info(new ZSMapInfo)
|
||||||
|
{
|
||||||
|
info->self = this;
|
||||||
|
}
|
||||||
|
~ZSMap()
|
||||||
|
{
|
||||||
|
info->self = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class KT, class VT>
|
||||||
|
struct ZSMapIterator
|
||||||
|
{
|
||||||
|
RefCountedPtr<ZSMapInfo> info;
|
||||||
|
TMapIterator<KT,VT> *it = nullptr;
|
||||||
|
typename ZSMap<KT,VT>::Pair *p = nullptr;
|
||||||
|
|
||||||
|
typedef KT KeyType;
|
||||||
|
typedef VT ValueType;
|
||||||
|
|
||||||
|
int rev = 0;
|
||||||
|
|
||||||
|
~ZSMapIterator()
|
||||||
|
{
|
||||||
|
if(it) delete it;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Valid()
|
||||||
|
{
|
||||||
|
return it && p && info.get() && info->self && info->rev == rev;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReInit()
|
||||||
|
{
|
||||||
|
if(info.get() && info->self) {
|
||||||
|
if(it) delete it;
|
||||||
|
it = new TMapIterator<KT,VT>(*static_cast<ZSMap<KT,VT>*>(info->self));
|
||||||
|
rev = info->rev;
|
||||||
|
p = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Init(ZSMap<KT,VT> &m)
|
||||||
|
{
|
||||||
|
info = m.info;
|
||||||
|
return ReInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Next()
|
||||||
|
{
|
||||||
|
if(it && info.get() && info->self && info->rev == rev)
|
||||||
|
{
|
||||||
|
p = nullptr;
|
||||||
|
return it->NextPair(p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ThrowAbortException(X_FORMAT_ERROR,"MapIterator::Next called from invalid iterator");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VT& GetValue()
|
||||||
|
{
|
||||||
|
if(p && info.get() && info->self && info->rev == rev)
|
||||||
|
{
|
||||||
|
return p->Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ThrowAbortException(X_FORMAT_ERROR,p ? "MapIterator::GetValue called from invalid iterator" : "MapIterator::GetValue called from invalid position");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const KT& GetKey()
|
||||||
|
{
|
||||||
|
if(p && info.get() && info->self && info->rev == rev)
|
||||||
|
{
|
||||||
|
return p->Key;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ThrowAbortException(X_FORMAT_ERROR,p ? "MapIterator::GetKey called from invalid iterator" : "MapIterator::GetKey called from invalid position");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -33,11 +33,14 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
|
||||||
#include "vmintern.h"
|
#include "vmintern.h"
|
||||||
#include "s_soundinternal.h"
|
#include "s_soundinternal.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "textureid.h"
|
#include "textureid.h"
|
||||||
|
#include "maps.h"
|
||||||
|
|
||||||
|
|
||||||
FTypeTable TypeTable;
|
FTypeTable TypeTable;
|
||||||
|
@ -183,7 +186,7 @@ void PType::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset>
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PType :: SetDefaultValue
|
// PType :: SetPointer*
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
@ -195,6 +198,10 @@ void PType::SetPointerArray(void *base, unsigned offset, TArray<size_t> *stroffs
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PType::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PType :: InitializeValue
|
// PType :: InitializeValue
|
||||||
|
@ -1862,7 +1869,7 @@ void PArray::SetPointer(void *base, unsigned offset, TArray<size_t> *special)
|
||||||
|
|
||||||
void PArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *special)
|
void PArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *special)
|
||||||
{
|
{
|
||||||
if (ElementType->isStruct())
|
if (ElementType->isStruct() || ElementType->isDynArray())
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < ElementCount; ++i)
|
for (unsigned int i = 0; i < ElementCount; ++i)
|
||||||
{
|
{
|
||||||
|
@ -1871,6 +1878,23 @@ void PArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *specia
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PArray :: SetPointerMap
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PArray::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *special)
|
||||||
|
{
|
||||||
|
if(ElementType->isStruct() || ElementType->isMap())
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < ElementCount; ++i)
|
||||||
|
{
|
||||||
|
ElementType->SetPointerMap(base, offset + ElementSize * i, special);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// NewArray
|
// NewArray
|
||||||
|
@ -2202,12 +2226,89 @@ PDynArray *NewDynArray(PType *type)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PMap::PMap(PType *keytype, PType *valtype)
|
enum OverrideFunctionRetType {
|
||||||
: KeyType(keytype), ValueType(valtype)
|
OFN_RET_VOID,
|
||||||
|
OFN_RET_VAL,
|
||||||
|
OFN_RET_KEY,
|
||||||
|
OFN_RET_BOOL,
|
||||||
|
};
|
||||||
|
enum OverrideFunctionArgType {
|
||||||
|
OFN_ARG_VOID,
|
||||||
|
OFN_ARG_KEY,
|
||||||
|
OFN_ARG_VAL,
|
||||||
|
OFN_ARG_KEY_VAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class MT, OverrideFunctionRetType RetType, OverrideFunctionArgType ArgType >
|
||||||
|
void CreateOverrideFunction(MT *self, FName name)
|
||||||
|
{
|
||||||
|
auto Fn = Create<PFunction>(self->BackingType, name);
|
||||||
|
auto NativeFn = FindFunction(self->BackingType, name.GetChars());
|
||||||
|
|
||||||
|
assert(NativeFn);
|
||||||
|
assert(NativeFn->VMPointer);
|
||||||
|
|
||||||
|
|
||||||
|
TArray<PType*> ret;
|
||||||
|
TArray<PType*> args;
|
||||||
|
TArray<uint32_t> argflags;
|
||||||
|
TArray<FName> argnames;
|
||||||
|
|
||||||
|
if constexpr(RetType == OFN_RET_VAL)
|
||||||
|
{
|
||||||
|
ret.Push(self->ValueType);
|
||||||
|
}
|
||||||
|
else if constexpr(RetType == OFN_RET_KEY)
|
||||||
|
{
|
||||||
|
ret.Push(self->KeyType);
|
||||||
|
}
|
||||||
|
else if constexpr(RetType == OFN_RET_BOOL)
|
||||||
|
{
|
||||||
|
ret.Push(TypeBool);
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Push(NewPointer(self->BackingType));
|
||||||
|
argnames.Push(NAME_self);
|
||||||
|
argflags.Push(VARF_Implicit | VARF_ReadOnly);
|
||||||
|
|
||||||
|
if constexpr(ArgType == OFN_ARG_KEY)
|
||||||
|
{
|
||||||
|
args.Push(self->KeyType);
|
||||||
|
argflags.Push(0);
|
||||||
|
argnames.Push(NAME_Key);
|
||||||
|
}
|
||||||
|
else if constexpr(ArgType == OFN_ARG_VAL)
|
||||||
|
{
|
||||||
|
|
||||||
|
args.Push(self->ValueType);
|
||||||
|
argflags.Push(0);
|
||||||
|
argnames.Push(NAME_Value);
|
||||||
|
}
|
||||||
|
else if constexpr(ArgType == OFN_ARG_KEY_VAL)
|
||||||
|
{
|
||||||
|
args.Push(self->KeyType);
|
||||||
|
args.Push(self->ValueType);
|
||||||
|
argflags.Push(0);
|
||||||
|
argflags.Push(0);
|
||||||
|
argnames.Push(NAME_Key);
|
||||||
|
argnames.Push(NAME_Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Fn->AddVariant(NewPrototype(ret, args), argflags, argnames, *NativeFn->VMPointer, VARF_Method | VARF_Native,SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM);
|
||||||
|
self->FnOverrides.Insert(name, Fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
PMap::PMap(PType *keytype, PType *valtype, PStruct *backing, int backing_class)
|
||||||
|
: KeyType(keytype), ValueType(valtype), BackingType(backing), BackingClass((decltype(BackingClass)) backing_class)
|
||||||
{
|
{
|
||||||
mDescriptiveName.Format("Map<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName());
|
mDescriptiveName.Format("Map<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName());
|
||||||
Size = sizeof(FMap);
|
Size = sizeof(ZSFMap);
|
||||||
Align = alignof(FMap);
|
Align = alignof(ZSFMap);
|
||||||
|
CreateOverrideFunction<PMap, OFN_RET_VAL, OFN_ARG_KEY>(this, NAME_Get);
|
||||||
|
CreateOverrideFunction<PMap, OFN_RET_BOOL, OFN_ARG_KEY>(this, NAME_CheckKey);
|
||||||
|
CreateOverrideFunction<PMap, OFN_RET_VOID, OFN_ARG_KEY_VAL>(this, NAME_Insert);
|
||||||
|
CreateOverrideFunction<PMap, OFN_RET_VOID, OFN_ARG_KEY>(this, NAME_InsertNew);
|
||||||
|
CreateOverrideFunction<PMap, OFN_RET_VOID, OFN_ARG_KEY>(this, NAME_Remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2236,6 +2337,345 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
id2 = (intptr_t)ValueType;
|
id2 = (intptr_t)ValueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: InitializeValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMap::Construct(void * addr) const {
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case MAP_I32_I8:
|
||||||
|
new(addr) ZSMap<uint32_t, uint8_t>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_I16:
|
||||||
|
new(addr) ZSMap<uint32_t, uint16_t>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_I32:
|
||||||
|
new(addr) ZSMap<uint32_t, uint32_t>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_F32:
|
||||||
|
new(addr) ZSMap<uint32_t, float>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_F64:
|
||||||
|
new(addr) ZSMap<uint32_t, double>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_OBJ:
|
||||||
|
new(addr) ZSMap<uint32_t, DObject*>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_PTR:
|
||||||
|
new(addr) ZSMap<uint32_t, void*>();
|
||||||
|
break;
|
||||||
|
case MAP_I32_STR:
|
||||||
|
new(addr) ZSMap<uint32_t, FString>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I8:
|
||||||
|
new(addr) ZSMap<FString, uint8_t>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I16:
|
||||||
|
new(addr) ZSMap<FString, uint16_t>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I32:
|
||||||
|
new(addr) ZSMap<FString, uint32_t>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_F32:
|
||||||
|
new(addr) ZSMap<FString, float>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_F64:
|
||||||
|
new(addr) ZSMap<FString, double>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_OBJ:
|
||||||
|
new(addr) ZSMap<FString, DObject*>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_PTR:
|
||||||
|
new(addr) ZSMap<FString, void*>();
|
||||||
|
break;
|
||||||
|
case MAP_STR_STR:
|
||||||
|
new(addr) ZSMap<FString, FString>();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PMap::InitializeValue(void *addr, const void *def) const
|
||||||
|
{
|
||||||
|
if (def != nullptr)
|
||||||
|
{
|
||||||
|
I_Error("Map cannot have default values");
|
||||||
|
}
|
||||||
|
Construct(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: DestroyValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMap::DestroyValue(void *addr) const
|
||||||
|
{
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case MAP_I32_I8:
|
||||||
|
static_cast<ZSMap<uint32_t, uint8_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_I16:
|
||||||
|
static_cast<ZSMap<uint32_t, uint16_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_I32:
|
||||||
|
static_cast<ZSMap<uint32_t, uint32_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_F32:
|
||||||
|
static_cast<ZSMap<uint32_t, float>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_F64:
|
||||||
|
static_cast<ZSMap<uint32_t, double>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_OBJ:
|
||||||
|
static_cast<ZSMap<uint32_t, DObject*>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_PTR:
|
||||||
|
static_cast<ZSMap<uint32_t, void*>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_I32_STR:
|
||||||
|
static_cast<ZSMap<uint32_t, FString>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I8:
|
||||||
|
static_cast<ZSMap<FString, uint8_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I16:
|
||||||
|
static_cast<ZSMap<FString, uint16_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_I32:
|
||||||
|
static_cast<ZSMap<FString, uint32_t>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_F32:
|
||||||
|
static_cast<ZSMap<FString, float>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_F64:
|
||||||
|
static_cast<ZSMap<FString, double>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_OBJ:
|
||||||
|
static_cast<ZSMap<FString, DObject*>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_PTR:
|
||||||
|
static_cast<ZSMap<FString, void*>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
case MAP_STR_STR:
|
||||||
|
static_cast<ZSMap<FString, FString>*>(addr)->~ZSMap();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: SetDefaultValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMap::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special)
|
||||||
|
{
|
||||||
|
assert(!(base && special));
|
||||||
|
if (base != nullptr)
|
||||||
|
{
|
||||||
|
Construct(((uint8_t*)base)+offset); // is this needed? string/dynarray do this initialization if base != nullptr, but their initialization doesn't need to allocate
|
||||||
|
// it might lead to double allocations (and memory leakage) for Map if both base and special != nullptr
|
||||||
|
}
|
||||||
|
if (special != nullptr)
|
||||||
|
{
|
||||||
|
special->Push(std::make_pair(this, offset));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I_Error("null special");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: SetPointer
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMap::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *special)
|
||||||
|
{
|
||||||
|
if (ValueType->isObjectPointer())
|
||||||
|
{
|
||||||
|
// Add to the list of pointer arrays for this class.
|
||||||
|
special->Push(std::make_pair(offset,KeyType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: WriteValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
template<typename M>
|
||||||
|
static void PMapValueWriter(FSerializer &ar, const M *map, const PMap *m)
|
||||||
|
{
|
||||||
|
TMapConstIterator<typename M::KeyType, typename M::ValueType> it(*map);
|
||||||
|
const typename M::Pair * p;
|
||||||
|
while(it.NextPair(p))
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<typename M::KeyType,FString>)
|
||||||
|
{
|
||||||
|
m->ValueType->WriteValue(ar,p->Key.GetChars(),static_cast<const void *>(&p->Value));
|
||||||
|
}
|
||||||
|
else if constexpr(std::is_same_v<typename M::KeyType,uint32_t>)
|
||||||
|
{
|
||||||
|
FString key;
|
||||||
|
key.Format("%u",p->Key);
|
||||||
|
m->ValueType->WriteValue(ar,key.GetChars(),static_cast<const void *>(&p->Value));
|
||||||
|
}
|
||||||
|
//else unknown key type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PMap::WriteValue(FSerializer &ar, const char *key, const void *addr) const
|
||||||
|
{
|
||||||
|
if(ar.BeginObject(key))
|
||||||
|
{
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case MAP_I32_I8:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, uint8_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_I16:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, uint16_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_I32:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, uint32_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_F32:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, float>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_F64:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, double>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_OBJ:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, DObject*>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_PTR:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, void*>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_I32_STR:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<uint32_t, FString>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_I8:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, uint8_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_I16:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, uint16_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_I32:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, uint32_t>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_F32:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, float>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_F64:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, double>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_OBJ:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, DObject*>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_PTR:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, void*>*>(addr), this);
|
||||||
|
break;
|
||||||
|
case MAP_STR_STR:
|
||||||
|
PMapValueWriter(ar, static_cast<const ZSMap<FString, FString>*>(addr), this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ar.EndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap :: ReadValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
template<typename M>
|
||||||
|
static bool PMapValueReader(FSerializer &ar, M *map, const PMap *m)
|
||||||
|
{
|
||||||
|
const char * k;
|
||||||
|
while(k = ar.GetKey())
|
||||||
|
{
|
||||||
|
typename M::ValueType * val;
|
||||||
|
if constexpr(std::is_same_v<typename M::KeyType,FString>)
|
||||||
|
{
|
||||||
|
val = &map->InsertNew(k);
|
||||||
|
}
|
||||||
|
else if constexpr(std::is_same_v<typename M::KeyType,uint32_t>)
|
||||||
|
{
|
||||||
|
FString s(k);
|
||||||
|
if(!s.IsInt())
|
||||||
|
{
|
||||||
|
ar.EndObject();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
val = &map->InsertNew(static_cast<uint32_t>(s.ToULong()));
|
||||||
|
}
|
||||||
|
if (!m->ValueType->ReadValue(ar,nullptr,static_cast<void*>(val)))
|
||||||
|
{
|
||||||
|
ar.EndObject();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ar.EndObject();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PMap::ReadValue(FSerializer &ar, const char *key, void *addr) const
|
||||||
|
{
|
||||||
|
DestroyValue(addr);
|
||||||
|
InitializeValue(addr, nullptr);
|
||||||
|
if(ar.BeginObject(key))
|
||||||
|
{
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case MAP_I32_I8:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, uint8_t>*>(addr), this);
|
||||||
|
case MAP_I32_I16:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, uint16_t>*>(addr), this);
|
||||||
|
case MAP_I32_I32:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, uint32_t>*>(addr), this);
|
||||||
|
case MAP_I32_F32:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, float>*>(addr), this);
|
||||||
|
case MAP_I32_F64:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, double>*>(addr), this);
|
||||||
|
case MAP_I32_OBJ:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, DObject*>*>(addr), this);
|
||||||
|
case MAP_I32_PTR:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, void*>*>(addr), this);
|
||||||
|
case MAP_I32_STR:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<uint32_t, FString>*>(addr), this);
|
||||||
|
case MAP_STR_I8:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, uint8_t>*>(addr), this);
|
||||||
|
case MAP_STR_I16:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, uint16_t>*>(addr), this);
|
||||||
|
case MAP_STR_I32:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, uint32_t>*>(addr), this);
|
||||||
|
case MAP_STR_F32:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, float>*>(addr), this);
|
||||||
|
case MAP_STR_F64:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, double>*>(addr), this);
|
||||||
|
case MAP_STR_OBJ:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, DObject*>*>(addr), this);
|
||||||
|
case MAP_STR_PTR:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, void*>*>(addr), this);
|
||||||
|
case MAP_STR_STR:
|
||||||
|
return PMapValueReader(ar, static_cast<ZSMap<FString, FString>*>(addr), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// NewMap
|
// NewMap
|
||||||
|
@ -2245,16 +2685,330 @@ void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PMap *NewMap(PType *keytype, PType *valuetype)
|
int PMapBackingClass(PType *keytype, PType *valuetype, FString &backingName) {
|
||||||
|
int backingClass;
|
||||||
|
auto key_rtype = keytype->GetRegType();
|
||||||
|
auto value_rtype = valuetype->GetRegType();
|
||||||
|
if (key_rtype == REGT_INT)
|
||||||
|
{
|
||||||
|
if(keytype->Size != 4)
|
||||||
|
{
|
||||||
|
I_Error("Unsupported map requested");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backingName += "I32_";
|
||||||
|
backingClass = PMap::MAP_I32_I8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key_rtype == REGT_STRING)
|
||||||
|
{
|
||||||
|
backingName += "Str_";
|
||||||
|
backingClass = PMap::MAP_STR_I8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I_Error("Unsupported map requested");
|
||||||
|
}
|
||||||
|
switch (valuetype->GetRegType())
|
||||||
|
{
|
||||||
|
case REGT_INT:
|
||||||
|
backingName.AppendFormat("I%d", valuetype->Size * 8);
|
||||||
|
backingClass += (valuetype->Size >> 1);
|
||||||
|
break;
|
||||||
|
case REGT_FLOAT:
|
||||||
|
backingName.AppendFormat("F%d", valuetype->Size * 8);
|
||||||
|
backingClass += PMap::MAP_I32_F32 + (valuetype->Size == 8);
|
||||||
|
break;
|
||||||
|
case REGT_STRING:
|
||||||
|
backingName += "Str";
|
||||||
|
backingClass += PMap::MAP_I32_STR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REGT_POINTER:
|
||||||
|
if (valuetype->isObjectPointer())
|
||||||
|
{
|
||||||
|
backingName += "Obj";
|
||||||
|
backingClass += PMap::MAP_I32_OBJ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backingName += "Ptr";
|
||||||
|
backingClass += PMap::MAP_I32_PTR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
I_Error("Unsupported map requested");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return backingClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
PMap *NewMap(PType *keyType, PType *valueType)
|
||||||
{
|
{
|
||||||
size_t bucket;
|
size_t bucket;
|
||||||
PType *maptype = TypeTable.FindType(NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, &bucket);
|
PType *mapType = TypeTable.FindType(NAME_Map, (intptr_t)keyType, (intptr_t)valueType, &bucket);
|
||||||
if (maptype == nullptr)
|
if (mapType == nullptr)
|
||||||
{
|
{
|
||||||
maptype = new PMap(keytype, valuetype);
|
FString backingName = "Map_";
|
||||||
TypeTable.AddType(maptype, NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, bucket);
|
int backingClass = PMapBackingClass(keyType, valueType, backingName);
|
||||||
|
|
||||||
|
auto backing = NewStruct(backingName, nullptr, true);
|
||||||
|
mapType = new PMap(keyType, valueType, backing, backingClass);
|
||||||
|
TypeTable.AddType(mapType, NAME_Map, (intptr_t)keyType, (intptr_t)valueType, bucket);
|
||||||
|
|
||||||
}
|
}
|
||||||
return (PMap *)maptype;
|
return (PMap *)mapType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PMap *******************************************************************/
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap - Parameterized Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PMapIterator::PMapIterator(PType *keytype, PType *valtype, PStruct *backing, int backing_class)
|
||||||
|
: KeyType(keytype), ValueType(valtype), BackingType(backing), BackingClass((decltype(BackingClass)) backing_class)
|
||||||
|
{
|
||||||
|
mDescriptiveName.Format("MapIterator<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName());
|
||||||
|
Size = sizeof(ZSFMap);
|
||||||
|
Align = alignof(ZSFMap);
|
||||||
|
CreateOverrideFunction<PMapIterator, OFN_RET_KEY, OFN_ARG_VOID>(this, NAME_GetKey);
|
||||||
|
CreateOverrideFunction<PMapIterator, OFN_RET_VAL, OFN_ARG_VOID>(this, NAME_GetValue);
|
||||||
|
CreateOverrideFunction<PMapIterator, OFN_RET_VOID, OFN_ARG_VAL>(this, NAME_SetValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: IsMatch
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool PMapIterator::IsMatch(intptr_t id1, intptr_t id2) const
|
||||||
|
{
|
||||||
|
const PType *keyty = (const PType *)id1;
|
||||||
|
const PType *valty = (const PType *)id2;
|
||||||
|
|
||||||
|
return keyty == KeyType && valty == ValueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: GetTypeIDs
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMapIterator::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
|
{
|
||||||
|
id1 = (intptr_t)KeyType;
|
||||||
|
id2 = (intptr_t)ValueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: InitializeValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMapIterator::Construct(void * addr) const {
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case PMap::MAP_I32_I8:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, uint8_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_I16:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, uint16_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_I32:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, uint32_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_F32:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, float>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_F64:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, double>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_OBJ:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, DObject*>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_PTR:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, void*>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_STR:
|
||||||
|
new(addr) ZSMapIterator<uint32_t, FString>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I8:
|
||||||
|
new(addr) ZSMapIterator<FString, uint8_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I16:
|
||||||
|
new(addr) ZSMapIterator<FString, uint16_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I32:
|
||||||
|
new(addr) ZSMapIterator<FString, uint32_t>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_F32:
|
||||||
|
new(addr) ZSMapIterator<FString, float>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_F64:
|
||||||
|
new(addr) ZSMapIterator<FString, double>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_OBJ:
|
||||||
|
new(addr) ZSMapIterator<FString, DObject*>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_PTR:
|
||||||
|
new(addr) ZSMapIterator<FString, void*>();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_STR:
|
||||||
|
new(addr) ZSMapIterator<FString, FString>();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PMapIterator::InitializeValue(void *addr, const void *def) const
|
||||||
|
{
|
||||||
|
if (def != nullptr)
|
||||||
|
{
|
||||||
|
I_Error("Map cannot have default values");
|
||||||
|
}
|
||||||
|
Construct(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: DestroyValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMapIterator::DestroyValue(void *addr) const
|
||||||
|
{
|
||||||
|
switch(BackingClass)
|
||||||
|
{
|
||||||
|
case PMap::MAP_I32_I8:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, uint8_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_I16:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, uint16_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_I32:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, uint32_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_F32:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, float>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_F64:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, double>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_OBJ:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, DObject*>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_PTR:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, void*>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_I32_STR:
|
||||||
|
static_cast<ZSMapIterator<uint32_t, FString>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I8:
|
||||||
|
static_cast<ZSMapIterator<FString, uint8_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I16:
|
||||||
|
static_cast<ZSMapIterator<FString, uint16_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_I32:
|
||||||
|
static_cast<ZSMapIterator<FString, uint32_t>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_F32:
|
||||||
|
static_cast<ZSMapIterator<FString, float>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_F64:
|
||||||
|
static_cast<ZSMapIterator<FString, double>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_OBJ:
|
||||||
|
static_cast<ZSMapIterator<FString, DObject*>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_PTR:
|
||||||
|
static_cast<ZSMapIterator<FString, void*>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
case PMap::MAP_STR_STR:
|
||||||
|
static_cast<ZSMapIterator<FString, FString>*>(addr)->~ZSMapIterator();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: SetDefaultValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMapIterator::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special)
|
||||||
|
{
|
||||||
|
assert(!(base && special));
|
||||||
|
if (base != nullptr)
|
||||||
|
{
|
||||||
|
Construct(((uint8_t*)base)+offset);
|
||||||
|
}
|
||||||
|
if (special != nullptr)
|
||||||
|
{
|
||||||
|
special->Push(std::make_pair(this, offset));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I_Error("null special");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: WriteValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PMapIterator::WriteValue(FSerializer &ar, const char *key, const void *addr) const
|
||||||
|
{
|
||||||
|
ar.BeginObject(key);
|
||||||
|
ar.EndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMapIterator :: ReadValue
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool PMapIterator::ReadValue(FSerializer &ar, const char *key, void *addr) const
|
||||||
|
{
|
||||||
|
DestroyValue(addr);
|
||||||
|
InitializeValue(addr, nullptr);
|
||||||
|
ar.BeginObject(key);
|
||||||
|
ar.EndObject();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// NewMapIterator
|
||||||
|
//
|
||||||
|
// Returns a PMapIterator for the given key and value types, ensuring not to create
|
||||||
|
// duplicates.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PMapIterator *NewMapIterator(PType *keyType, PType *valueType)
|
||||||
|
{
|
||||||
|
size_t bucket;
|
||||||
|
PType *mapIteratorType = TypeTable.FindType(NAME_MapIterator, (intptr_t)keyType, (intptr_t)valueType, &bucket);
|
||||||
|
if (mapIteratorType == nullptr)
|
||||||
|
{
|
||||||
|
FString backingName = "MapIterator_";
|
||||||
|
int backingClass = PMapBackingClass(keyType, valueType, backingName);
|
||||||
|
|
||||||
|
auto backing = NewStruct(backingName, nullptr, true);
|
||||||
|
mapIteratorType = new PMapIterator(keyType, valueType, backing, backingClass);
|
||||||
|
TypeTable.AddType(mapIteratorType, NAME_MapIterator, (intptr_t)keyType, (intptr_t)valueType, bucket);
|
||||||
|
}
|
||||||
|
return (PMapIterator *)mapIteratorType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PStruct ****************************************************************/
|
/* PStruct ****************************************************************/
|
||||||
|
@ -2333,6 +3087,26 @@ void PStruct::SetPointerArray(void *base, unsigned offset, TArray<size_t> *speci
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PStruct :: SetPointerMap
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void PStruct::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *special)
|
||||||
|
{
|
||||||
|
auto it = Symbols.GetIterator();
|
||||||
|
PSymbolTable::MapType::Pair *pair;
|
||||||
|
while (it.NextPair(pair))
|
||||||
|
{
|
||||||
|
auto field = dyn_cast<PField>(pair->Value);
|
||||||
|
if (field && !(field->Flags & VARF_Transient))
|
||||||
|
{
|
||||||
|
field->Type->SetPointerMap(base, unsigned(offset + field->Offset), special);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PStruct :: WriteValue
|
// PStruct :: WriteValue
|
||||||
|
|
|
@ -129,6 +129,7 @@ public:
|
||||||
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL);
|
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL);
|
||||||
virtual void SetPointer(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL);
|
virtual void SetPointer(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL);
|
||||||
virtual void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL);
|
virtual void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL);
|
||||||
|
virtual void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs = NULL);
|
||||||
|
|
||||||
// Initialize the value, if needed (e.g. strings)
|
// Initialize the value, if needed (e.g. strings)
|
||||||
virtual void InitializeValue(void *addr, const void *def) const;
|
virtual void InitializeValue(void *addr, const void *def) const;
|
||||||
|
@ -200,6 +201,8 @@ public:
|
||||||
bool isArray() const { return !!(Flags & TYPE_Array); }
|
bool isArray() const { return !!(Flags & TYPE_Array); }
|
||||||
bool isStaticArray() const { return TypeTableType == NAME_StaticArray; }
|
bool isStaticArray() const { return TypeTableType == NAME_StaticArray; }
|
||||||
bool isDynArray() const { return TypeTableType == NAME_DynArray; }
|
bool isDynArray() const { return TypeTableType == NAME_DynArray; }
|
||||||
|
bool isMap() const { return TypeTableType == NAME_Map; }
|
||||||
|
bool isMapIterator() const { return TypeTableType == NAME_MapIterator; }
|
||||||
bool isStruct() const { return TypeTableType == NAME_Struct; }
|
bool isStruct() const { return TypeTableType == NAME_Struct; }
|
||||||
bool isClass() const { return TypeTableType == NAME_Object; }
|
bool isClass() const { return TypeTableType == NAME_Object; }
|
||||||
bool isPrototype() const { return TypeTableType == NAME_Prototype; }
|
bool isPrototype() const { return TypeTableType == NAME_Prototype; }
|
||||||
|
@ -489,6 +492,7 @@ public:
|
||||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) override;
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) override;
|
||||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *special) override;
|
void SetPointer(void *base, unsigned offset, TArray<size_t> *special) override;
|
||||||
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) override;
|
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) override;
|
||||||
|
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs = NULL) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PStaticArray : public PArray
|
class PStaticArray : public PArray
|
||||||
|
@ -521,14 +525,72 @@ public:
|
||||||
|
|
||||||
class PMap : public PCompoundType
|
class PMap : public PCompoundType
|
||||||
{
|
{
|
||||||
|
void Construct(void * addr) const;
|
||||||
public:
|
public:
|
||||||
PMap(PType *keytype, PType *valtype);
|
PMap(PType *keytype, PType *valtype, PStruct *backing, int backing_class);
|
||||||
|
|
||||||
PType *KeyType;
|
PType *KeyType;
|
||||||
PType *ValueType;
|
PType *ValueType;
|
||||||
|
|
||||||
|
TMap<FName,PFunction*> FnOverrides;
|
||||||
|
|
||||||
|
PStruct *BackingType;
|
||||||
|
|
||||||
|
enum EBackingClass {
|
||||||
|
MAP_I32_I8,
|
||||||
|
MAP_I32_I16,
|
||||||
|
MAP_I32_I32,
|
||||||
|
MAP_I32_F32,
|
||||||
|
MAP_I32_F64,
|
||||||
|
MAP_I32_OBJ,
|
||||||
|
MAP_I32_PTR,
|
||||||
|
MAP_I32_STR,
|
||||||
|
|
||||||
|
MAP_STR_I8,
|
||||||
|
MAP_STR_I16,
|
||||||
|
MAP_STR_I32,
|
||||||
|
MAP_STR_F32,
|
||||||
|
MAP_STR_F64,
|
||||||
|
MAP_STR_OBJ,
|
||||||
|
MAP_STR_PTR,
|
||||||
|
MAP_STR_STR,
|
||||||
|
} BackingClass;
|
||||||
|
|
||||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
|
||||||
|
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
|
||||||
|
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
||||||
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
||||||
|
void InitializeValue(void *addr, const void *def) const override;
|
||||||
|
void DestroyValue(void *addr) const override;
|
||||||
|
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PMapIterator : public PCompoundType
|
||||||
|
{
|
||||||
|
void Construct(void * addr) const;
|
||||||
|
public:
|
||||||
|
PMapIterator(PType *keytype, PType *valtype, PStruct *backing, int backing_class);
|
||||||
|
|
||||||
|
PType *KeyType;
|
||||||
|
PType *ValueType;
|
||||||
|
|
||||||
|
TMap<FName,PFunction*> FnOverrides;
|
||||||
|
|
||||||
|
PStruct *BackingType;
|
||||||
|
|
||||||
|
PMap::EBackingClass BackingClass;
|
||||||
|
|
||||||
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
|
||||||
|
void WriteValue(FSerializer &ar, const char *key, const void *addr) const override;
|
||||||
|
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
||||||
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
||||||
|
void InitializeValue(void *addr, const void *def) const override;
|
||||||
|
void DestroyValue(void *addr) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PStruct : public PContainerType
|
class PStruct : public PContainerType
|
||||||
|
@ -550,6 +612,7 @@ public:
|
||||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
||||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override;
|
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override;
|
||||||
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *special) override;
|
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *special) override;
|
||||||
|
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPrototype : public PCompoundType
|
class PPrototype : public PCompoundType
|
||||||
|
@ -586,6 +649,7 @@ inline PClass *PObjectPointer::PointedClass() const
|
||||||
|
|
||||||
// Returns a type from the TypeTable. Will create one if it isn't present.
|
// Returns a type from the TypeTable. Will create one if it isn't present.
|
||||||
PMap *NewMap(PType *keytype, PType *valuetype);
|
PMap *NewMap(PType *keytype, PType *valuetype);
|
||||||
|
PMapIterator *NewMapIterator(PType *keytype, PType *valuetype);
|
||||||
PArray *NewArray(PType *type, unsigned int count);
|
PArray *NewArray(PType *type, unsigned int count);
|
||||||
PStaticArray *NewStaticArray(PType *type);
|
PStaticArray *NewStaticArray(PType *type);
|
||||||
PDynArray *NewDynArray(PType *type);
|
PDynArray *NewDynArray(PType *type);
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
class FLispString;
|
class FLispString;
|
||||||
extern void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *);
|
using NodePrinterFunc = void (*)(FLispString &, const ZCC_TreeNode *);
|
||||||
|
|
||||||
static const char *BuiltInTypeNames[] =
|
static const char *BuiltInTypeNames[] =
|
||||||
{
|
{
|
||||||
|
@ -221,24 +221,11 @@ private:
|
||||||
bool NeedSpace;
|
bool NeedSpace;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void PrintNode(FLispString &out, ZCC_TreeNode *node)
|
static void PrintNode(FLispString &out, const ZCC_TreeNode *node);
|
||||||
{
|
|
||||||
assert(TreeNodePrinter[NUM_AST_NODE_TYPES-1] != NULL);
|
|
||||||
if (node->NodeType >= 0 && node->NodeType < NUM_AST_NODE_TYPES)
|
|
||||||
{
|
|
||||||
TreeNodePrinter[node->NodeType](out, node);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out.Open("unknown-node-type");
|
|
||||||
out.AddInt(node->NodeType);
|
|
||||||
out.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void PrintNodes(FLispString &out, ZCC_TreeNode *node, bool newlist=true, bool addbreaks=false)
|
static void PrintNodes(FLispString &out, const ZCC_TreeNode *node, bool newlist=true, bool addbreaks=false)
|
||||||
{
|
{
|
||||||
ZCC_TreeNode *p;
|
const ZCC_TreeNode *p;
|
||||||
|
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
{
|
{
|
||||||
|
@ -269,7 +256,7 @@ static void PrintNodes(FLispString &out, ZCC_TreeNode *node, bool newlist=true,
|
||||||
|
|
||||||
static void PrintBuiltInType(FLispString &out, EZCCBuiltinType type)
|
static void PrintBuiltInType(FLispString &out, EZCCBuiltinType type)
|
||||||
{
|
{
|
||||||
assert(ZCC_NUM_BUILT_IN_TYPES == countof(BuiltInTypeNames));
|
static_assert(ZCC_NUM_BUILT_IN_TYPES == countof(BuiltInTypeNames));
|
||||||
if (unsigned(type) >= unsigned(ZCC_NUM_BUILT_IN_TYPES))
|
if (unsigned(type) >= unsigned(ZCC_NUM_BUILT_IN_TYPES))
|
||||||
{
|
{
|
||||||
char buf[30];
|
char buf[30];
|
||||||
|
@ -282,7 +269,7 @@ static void PrintBuiltInType(FLispString &out, EZCCBuiltinType type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintIdentifier(FLispString &out, ZCC_TreeNode *node)
|
static void PrintIdentifier(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_Identifier *inode = (ZCC_Identifier *)node;
|
ZCC_Identifier *inode = (ZCC_Identifier *)node;
|
||||||
out.Open("identifier");
|
out.Open("identifier");
|
||||||
|
@ -317,7 +304,7 @@ static void PrintStringConst(FLispString &out, FString str)
|
||||||
out.Add(outstr);
|
out.Add(outstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintClass(FLispString &out, ZCC_TreeNode *node)
|
static void PrintClass(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_Class *cnode = (ZCC_Class *)node;
|
ZCC_Class *cnode = (ZCC_Class *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -330,7 +317,7 @@ static void PrintClass(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStruct(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStruct(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_Struct *snode = (ZCC_Struct *)node;
|
ZCC_Struct *snode = (ZCC_Struct *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -340,7 +327,7 @@ static void PrintStruct(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintProperty(FLispString &out, ZCC_TreeNode *node)
|
static void PrintProperty(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_Property *snode = (ZCC_Property *)node;
|
ZCC_Property *snode = (ZCC_Property *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -350,7 +337,7 @@ static void PrintProperty(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintFlagDef(FLispString &out, ZCC_TreeNode *node)
|
static void PrintFlagDef(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_FlagDef *snode = (ZCC_FlagDef *)node;
|
ZCC_FlagDef *snode = (ZCC_FlagDef *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -361,7 +348,7 @@ static void PrintFlagDef(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStaticArrayState(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStaticArrayState(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
auto *snode = (ZCC_StaticArrayStatement *)node;
|
auto *snode = (ZCC_StaticArrayStatement *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -371,7 +358,7 @@ static void PrintStaticArrayState(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintEnum(FLispString &out, ZCC_TreeNode *node)
|
static void PrintEnum(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_Enum *enode = (ZCC_Enum *)node;
|
ZCC_Enum *enode = (ZCC_Enum *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -382,13 +369,13 @@ static void PrintEnum(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintEnumTerminator(FLispString &out, ZCC_TreeNode *node)
|
static void PrintEnumTerminator(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
out.Open("enum-term");
|
out.Open("enum-term");
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStates(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStates(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_States *snode = (ZCC_States *)node;
|
ZCC_States *snode = (ZCC_States *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -398,13 +385,13 @@ static void PrintStates(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStatePart(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStatePart(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
out.Open("state-part");
|
out.Open("state-part");
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStateLabel(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStateLabel(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_StateLabel *snode = (ZCC_StateLabel *)node;
|
ZCC_StateLabel *snode = (ZCC_StateLabel *)node;
|
||||||
out.Open("state-label");
|
out.Open("state-label");
|
||||||
|
@ -412,31 +399,31 @@ static void PrintStateLabel(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStateStop(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStateStop(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
out.Open("state-stop");
|
out.Open("state-stop");
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStateWait(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStateWait(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
out.Open("state-wait");
|
out.Open("state-wait");
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStateFail(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStateFail(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
out.Open("state-fail");
|
out.Open("state-fail");
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStateLoop(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStateLoop(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
out.Open("state-loop");
|
out.Open("state-loop");
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStateGoto(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStateGoto(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_StateGoto *snode = (ZCC_StateGoto *)node;
|
ZCC_StateGoto *snode = (ZCC_StateGoto *)node;
|
||||||
out.Open("state-goto");
|
out.Open("state-goto");
|
||||||
|
@ -446,7 +433,7 @@ static void PrintStateGoto(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStateLine(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStateLine(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_StateLine *snode = (ZCC_StateLine *)node;
|
ZCC_StateLine *snode = (ZCC_StateLine *)node;
|
||||||
out.Open("state-line");
|
out.Open("state-line");
|
||||||
|
@ -463,7 +450,7 @@ static void PrintStateLine(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintVarName(FLispString &out, ZCC_TreeNode *node)
|
static void PrintVarName(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_VarName *vnode = (ZCC_VarName *)node;
|
ZCC_VarName *vnode = (ZCC_VarName *)node;
|
||||||
out.Open("var-name");
|
out.Open("var-name");
|
||||||
|
@ -472,7 +459,7 @@ static void PrintVarName(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintVarInit(FLispString &out, ZCC_TreeNode *node)
|
static void PrintVarInit(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_VarInit *vnode = (ZCC_VarInit *)node;
|
ZCC_VarInit *vnode = (ZCC_VarInit *)node;
|
||||||
out.Open("var-init");
|
out.Open("var-init");
|
||||||
|
@ -483,7 +470,7 @@ static void PrintVarInit(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintType(FLispString &out, ZCC_TreeNode *node)
|
static void PrintType(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_Type *tnode = (ZCC_Type *)node;
|
ZCC_Type *tnode = (ZCC_Type *)node;
|
||||||
out.Open("bad-type");
|
out.Open("bad-type");
|
||||||
|
@ -491,7 +478,7 @@ static void PrintType(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintBasicType(FLispString &out, ZCC_TreeNode *node)
|
static void PrintBasicType(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_BasicType *tnode = (ZCC_BasicType *)node;
|
ZCC_BasicType *tnode = (ZCC_BasicType *)node;
|
||||||
out.Open("basic-type");
|
out.Open("basic-type");
|
||||||
|
@ -505,7 +492,7 @@ static void PrintBasicType(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintMapType(FLispString &out, ZCC_TreeNode *node)
|
static void PrintMapType(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_MapType *tnode = (ZCC_MapType *)node;
|
ZCC_MapType *tnode = (ZCC_MapType *)node;
|
||||||
out.Open("map-type");
|
out.Open("map-type");
|
||||||
|
@ -515,7 +502,17 @@ static void PrintMapType(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintDynArrayType(FLispString &out, ZCC_TreeNode *node)
|
static void PrintMapIteratorType(FLispString &out, const ZCC_TreeNode *node)
|
||||||
|
{
|
||||||
|
ZCC_MapIteratorType *tnode = (ZCC_MapIteratorType *)node;
|
||||||
|
out.Open("map-iterator-type");
|
||||||
|
PrintNodes(out, tnode->ArraySize);
|
||||||
|
PrintNodes(out, tnode->KeyType);
|
||||||
|
PrintNodes(out, tnode->ValueType);
|
||||||
|
out.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrintDynArrayType(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_DynArrayType *tnode = (ZCC_DynArrayType *)node;
|
ZCC_DynArrayType *tnode = (ZCC_DynArrayType *)node;
|
||||||
out.Open("dyn-array-type");
|
out.Open("dyn-array-type");
|
||||||
|
@ -524,7 +521,7 @@ static void PrintDynArrayType(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintClassType(FLispString &out, ZCC_TreeNode *node)
|
static void PrintClassType(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ClassType *tnode = (ZCC_ClassType *)node;
|
ZCC_ClassType *tnode = (ZCC_ClassType *)node;
|
||||||
out.Open("class-type");
|
out.Open("class-type");
|
||||||
|
@ -548,14 +545,14 @@ static void OpenExprType(FLispString &out, EZCCExprType type)
|
||||||
out.Open(buf);
|
out.Open(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExpression(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExpression(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_Expression *enode = (ZCC_Expression *)node;
|
ZCC_Expression *enode = (ZCC_Expression *)node;
|
||||||
OpenExprType(out, enode->Operation);
|
OpenExprType(out, enode->Operation);
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExprID(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExprID(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ExprID *enode = (ZCC_ExprID *)node;
|
ZCC_ExprID *enode = (ZCC_ExprID *)node;
|
||||||
assert(enode->Operation == PEX_ID);
|
assert(enode->Operation == PEX_ID);
|
||||||
|
@ -564,7 +561,7 @@ static void PrintExprID(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExprTypeRef(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExprTypeRef(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ExprTypeRef *enode = (ZCC_ExprTypeRef *)node;
|
ZCC_ExprTypeRef *enode = (ZCC_ExprTypeRef *)node;
|
||||||
assert(enode->Operation == PEX_TypeRef);
|
assert(enode->Operation == PEX_TypeRef);
|
||||||
|
@ -583,7 +580,7 @@ static void PrintExprTypeRef(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExprConstant(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExprConstant(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ExprConstant *enode = (ZCC_ExprConstant *)node;
|
ZCC_ExprConstant *enode = (ZCC_ExprConstant *)node;
|
||||||
assert(enode->Operation == PEX_ConstValue);
|
assert(enode->Operation == PEX_ConstValue);
|
||||||
|
@ -611,7 +608,7 @@ static void PrintExprConstant(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExprFuncCall(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExprFuncCall(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ExprFuncCall *enode = (ZCC_ExprFuncCall *)node;
|
ZCC_ExprFuncCall *enode = (ZCC_ExprFuncCall *)node;
|
||||||
assert(enode->Operation == PEX_FuncCall);
|
assert(enode->Operation == PEX_FuncCall);
|
||||||
|
@ -621,7 +618,7 @@ static void PrintExprFuncCall(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExprClassCast(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExprClassCast(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ClassCast *enode = (ZCC_ClassCast *)node;
|
ZCC_ClassCast *enode = (ZCC_ClassCast *)node;
|
||||||
assert(enode->Operation == PEX_ClassCast);
|
assert(enode->Operation == PEX_ClassCast);
|
||||||
|
@ -631,7 +628,7 @@ static void PrintExprClassCast(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStaticArray(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStaticArray(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_StaticArrayStatement *enode = (ZCC_StaticArrayStatement *)node;
|
ZCC_StaticArrayStatement *enode = (ZCC_StaticArrayStatement *)node;
|
||||||
out.Open("static-array-stmt");
|
out.Open("static-array-stmt");
|
||||||
|
@ -641,7 +638,7 @@ static void PrintStaticArray(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExprMemberAccess(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExprMemberAccess(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ExprMemberAccess *enode = (ZCC_ExprMemberAccess *)node;
|
ZCC_ExprMemberAccess *enode = (ZCC_ExprMemberAccess *)node;
|
||||||
assert(enode->Operation == PEX_MemberAccess);
|
assert(enode->Operation == PEX_MemberAccess);
|
||||||
|
@ -651,7 +648,7 @@ static void PrintExprMemberAccess(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExprUnary(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExprUnary(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ExprUnary *enode = (ZCC_ExprUnary *)node;
|
ZCC_ExprUnary *enode = (ZCC_ExprUnary *)node;
|
||||||
OpenExprType(out, enode->Operation);
|
OpenExprType(out, enode->Operation);
|
||||||
|
@ -659,7 +656,7 @@ static void PrintExprUnary(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExprBinary(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExprBinary(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ExprBinary *enode = (ZCC_ExprBinary *)node;
|
ZCC_ExprBinary *enode = (ZCC_ExprBinary *)node;
|
||||||
OpenExprType(out, enode->Operation);
|
OpenExprType(out, enode->Operation);
|
||||||
|
@ -668,7 +665,7 @@ static void PrintExprBinary(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExprTrinary(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExprTrinary(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ExprTrinary *enode = (ZCC_ExprTrinary *)node;
|
ZCC_ExprTrinary *enode = (ZCC_ExprTrinary *)node;
|
||||||
OpenExprType(out, enode->Operation);
|
OpenExprType(out, enode->Operation);
|
||||||
|
@ -678,7 +675,7 @@ static void PrintExprTrinary(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintVectorInitializer(FLispString &out, ZCC_TreeNode *node)
|
static void PrintVectorInitializer(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_VectorValue *enode = (ZCC_VectorValue *)node;
|
ZCC_VectorValue *enode = (ZCC_VectorValue *)node;
|
||||||
OpenExprType(out, enode->Operation);
|
OpenExprType(out, enode->Operation);
|
||||||
|
@ -689,7 +686,7 @@ static void PrintVectorInitializer(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintFuncParam(FLispString &out, ZCC_TreeNode *node)
|
static void PrintFuncParam(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_FuncParm *pnode = (ZCC_FuncParm *)node;
|
ZCC_FuncParm *pnode = (ZCC_FuncParm *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -699,13 +696,13 @@ static void PrintFuncParam(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintStatement(FLispString &out, ZCC_TreeNode *node)
|
static void PrintStatement(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
out.Open("statement");
|
out.Open("statement");
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintCompoundStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintCompoundStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_CompoundStmt *snode = (ZCC_CompoundStmt *)node;
|
ZCC_CompoundStmt *snode = (ZCC_CompoundStmt *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -714,7 +711,7 @@ static void PrintCompoundStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintDefault(FLispString &out, ZCC_TreeNode *node)
|
static void PrintDefault(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_Default *snode = (ZCC_Default *)node;
|
ZCC_Default *snode = (ZCC_Default *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -723,21 +720,21 @@ static void PrintDefault(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintContinueStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintContinueStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
out.Break();
|
out.Break();
|
||||||
out.Open("continue-stmt");
|
out.Open("continue-stmt");
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintBreakStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintBreakStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
out.Break();
|
out.Break();
|
||||||
out.Open("break-stmt");
|
out.Open("break-stmt");
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintReturnStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintReturnStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ReturnStmt *snode = (ZCC_ReturnStmt *)node;
|
ZCC_ReturnStmt *snode = (ZCC_ReturnStmt *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -746,7 +743,7 @@ static void PrintReturnStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintExpressionStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintExpressionStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ExpressionStmt *snode = (ZCC_ExpressionStmt *)node;
|
ZCC_ExpressionStmt *snode = (ZCC_ExpressionStmt *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -755,7 +752,7 @@ static void PrintExpressionStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintIterationStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintIterationStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_IterationStmt *snode = (ZCC_IterationStmt *)node;
|
ZCC_IterationStmt *snode = (ZCC_IterationStmt *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -770,7 +767,7 @@ static void PrintIterationStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintIfStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintIfStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_IfStmt *snode = (ZCC_IfStmt *)node;
|
ZCC_IfStmt *snode = (ZCC_IfStmt *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -783,7 +780,7 @@ static void PrintIfStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintSwitchStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintSwitchStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_SwitchStmt *snode = (ZCC_SwitchStmt *)node;
|
ZCC_SwitchStmt *snode = (ZCC_SwitchStmt *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -794,7 +791,7 @@ static void PrintSwitchStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintCaseStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintCaseStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_CaseStmt *snode = (ZCC_CaseStmt *)node;
|
ZCC_CaseStmt *snode = (ZCC_CaseStmt *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -810,7 +807,7 @@ static void BadAssignOp(FLispString &out, int op)
|
||||||
out.Add(buf, len);
|
out.Add(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintAssignStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintAssignStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_AssignStmt *snode = (ZCC_AssignStmt *)node;
|
ZCC_AssignStmt *snode = (ZCC_AssignStmt *)node;
|
||||||
out.Open("assign-stmt");
|
out.Open("assign-stmt");
|
||||||
|
@ -819,7 +816,7 @@ static void PrintAssignStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintLocalVarStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintLocalVarStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_LocalVarStmt *snode = (ZCC_LocalVarStmt *)node;
|
ZCC_LocalVarStmt *snode = (ZCC_LocalVarStmt *)node;
|
||||||
out.Open("local-var-stmt");
|
out.Open("local-var-stmt");
|
||||||
|
@ -828,7 +825,7 @@ static void PrintLocalVarStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintFuncParamDecl(FLispString &out, ZCC_TreeNode *node)
|
static void PrintFuncParamDecl(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_FuncParamDecl *dnode = (ZCC_FuncParamDecl *)node;
|
ZCC_FuncParamDecl *dnode = (ZCC_FuncParamDecl *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -840,7 +837,7 @@ static void PrintFuncParamDecl(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintConstantDef(FLispString &out, ZCC_TreeNode *node)
|
static void PrintConstantDef(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ConstantDef *dnode = (ZCC_ConstantDef *)node;
|
ZCC_ConstantDef *dnode = (ZCC_ConstantDef *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -850,7 +847,7 @@ static void PrintConstantDef(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintDeclarator(FLispString &out, ZCC_TreeNode *node)
|
static void PrintDeclarator(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_Declarator *dnode = (ZCC_Declarator *)node;
|
ZCC_Declarator *dnode = (ZCC_Declarator *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -860,7 +857,7 @@ static void PrintDeclarator(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintVarDeclarator(FLispString &out, ZCC_TreeNode *node)
|
static void PrintVarDeclarator(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_VarDeclarator *dnode = (ZCC_VarDeclarator *)node;
|
ZCC_VarDeclarator *dnode = (ZCC_VarDeclarator *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -871,7 +868,7 @@ static void PrintVarDeclarator(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node)
|
static void PrintFuncDeclarator(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_FuncDeclarator *dnode = (ZCC_FuncDeclarator *)node;
|
ZCC_FuncDeclarator *dnode = (ZCC_FuncDeclarator *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -885,7 +882,7 @@ static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintDeclFlags(FLispString &out, ZCC_TreeNode *node)
|
static void PrintDeclFlags(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
auto dnode = (ZCC_DeclFlags *)node;
|
auto dnode = (ZCC_DeclFlags *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -895,7 +892,7 @@ static void PrintDeclFlags(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintFlagStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintFlagStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
auto dnode = (ZCC_FlagStmt *)node;
|
auto dnode = (ZCC_FlagStmt *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -905,7 +902,7 @@ static void PrintFlagStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintPropertyStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintPropertyStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
auto dnode = (ZCC_PropertyStmt *)node;
|
auto dnode = (ZCC_PropertyStmt *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -915,7 +912,7 @@ static void PrintPropertyStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintMixinDef(FLispString &out, ZCC_TreeNode *node)
|
static void PrintMixinDef(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_MixinDef *mdnode = (ZCC_MixinDef *)node;
|
ZCC_MixinDef *mdnode = (ZCC_MixinDef *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -925,7 +922,7 @@ static void PrintMixinDef(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintMixinStmt(FLispString &out, ZCC_TreeNode *node)
|
static void PrintMixinStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_MixinStmt *msnode = (ZCC_MixinStmt *)node;
|
ZCC_MixinStmt *msnode = (ZCC_MixinStmt *)node;
|
||||||
out.Break();
|
out.Break();
|
||||||
|
@ -934,7 +931,20 @@ static void PrintMixinStmt(FLispString &out, ZCC_TreeNode *node)
|
||||||
out.Close();
|
out.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *) =
|
static void PrintArrayIterationStmt(FLispString &out, const ZCC_TreeNode *node)
|
||||||
|
{
|
||||||
|
auto inode = (ZCC_ArrayIterationStmt *)node;
|
||||||
|
out.Break();
|
||||||
|
out.Open("array-iteration-stmt");
|
||||||
|
PrintVarName(out, inode->ItName);
|
||||||
|
out.Break();
|
||||||
|
PrintNodes(out, inode->ItArray);
|
||||||
|
out.Break();
|
||||||
|
PrintNodes(out, inode->LoopStatement);
|
||||||
|
out.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const NodePrinterFunc TreeNodePrinter[] =
|
||||||
{
|
{
|
||||||
PrintIdentifier,
|
PrintIdentifier,
|
||||||
PrintClass,
|
PrintClass,
|
||||||
|
@ -955,6 +965,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *
|
||||||
PrintType,
|
PrintType,
|
||||||
PrintBasicType,
|
PrintBasicType,
|
||||||
PrintMapType,
|
PrintMapType,
|
||||||
|
PrintMapIteratorType,
|
||||||
PrintDynArrayType,
|
PrintDynArrayType,
|
||||||
PrintClassType,
|
PrintClassType,
|
||||||
PrintExpression,
|
PrintExpression,
|
||||||
|
@ -995,11 +1006,27 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *
|
||||||
PrintFlagDef,
|
PrintFlagDef,
|
||||||
PrintMixinDef,
|
PrintMixinDef,
|
||||||
PrintMixinStmt,
|
PrintMixinStmt,
|
||||||
|
PrintArrayIterationStmt,
|
||||||
};
|
};
|
||||||
|
|
||||||
FString ZCC_PrintAST(ZCC_TreeNode *root)
|
FString ZCC_PrintAST(const ZCC_TreeNode *root)
|
||||||
{
|
{
|
||||||
FLispString out;
|
FLispString out;
|
||||||
PrintNodes(out, root);
|
PrintNodes(out, root);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PrintNode(FLispString &out, const ZCC_TreeNode *node)
|
||||||
|
{
|
||||||
|
static_assert(countof(TreeNodePrinter) == NUM_AST_NODE_TYPES, "All AST node types should have printers defined for them");
|
||||||
|
if (node->NodeType >= 0 && node->NodeType < NUM_AST_NODE_TYPES)
|
||||||
|
{
|
||||||
|
TreeNodePrinter[node->NodeType](out, node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.Open("unknown-node-type");
|
||||||
|
out.AddInt(node->NodeType);
|
||||||
|
out.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -932,7 +932,7 @@ type_name(X) ::= DOT dottable_id(A).
|
||||||
/* Type names can also be used as identifiers in contexts where type names
|
/* Type names can also be used as identifiers in contexts where type names
|
||||||
* are not normally allowed. */
|
* are not normally allowed. */
|
||||||
%fallback IDENTIFIER
|
%fallback IDENTIFIER
|
||||||
SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR2 VECTOR3 VECTOR4 NAME MAP ARRAY VOID STATE COLOR SOUND UINT8 INT8 UINT16 INT16 PROPERTY.
|
SBYTE BYTE SHORT USHORT INT UINT BOOL FLOAT DOUBLE STRING VECTOR2 VECTOR3 VECTOR4 NAME MAP MAPITERATOR ARRAY VOID STATE COLOR SOUND UINT8 INT8 UINT16 INT16 PROPERTY.
|
||||||
|
|
||||||
/* Aggregate types */
|
/* Aggregate types */
|
||||||
%type aggregate_type {ZCC_Type *}
|
%type aggregate_type {ZCC_Type *}
|
||||||
|
@ -944,7 +944,7 @@ type_name(X) ::= DOT dottable_id(A).
|
||||||
%type array_size{ZCC_Expression *}
|
%type array_size{ZCC_Expression *}
|
||||||
%type array_size_expr{ZCC_Expression *}
|
%type array_size_expr{ZCC_Expression *}
|
||||||
|
|
||||||
aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* Hash table */
|
aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* ZSMap<K, V> */
|
||||||
{
|
{
|
||||||
NEW_AST_NODE(MapType,map,T);
|
NEW_AST_NODE(MapType,map,T);
|
||||||
map->KeyType = A;
|
map->KeyType = A;
|
||||||
|
@ -952,6 +952,14 @@ aggregate_type(X) ::= MAP(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* H
|
||||||
X = map;
|
X = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aggregate_type(X) ::= MAPITERATOR(T) LT type_or_array(A) COMMA type_or_array(B) GT. /* ZSMapIterator<K, V> */
|
||||||
|
{
|
||||||
|
NEW_AST_NODE(MapIteratorType,map_it,T);
|
||||||
|
map_it->KeyType = A;
|
||||||
|
map_it->ValueType = B;
|
||||||
|
X = map_it;
|
||||||
|
}
|
||||||
|
|
||||||
aggregate_type(X) ::= ARRAY(T) LT type_or_array(A) GT. /* TArray<type> */
|
aggregate_type(X) ::= ARRAY(T) LT type_or_array(A) GT. /* TArray<type> */
|
||||||
{
|
{
|
||||||
NEW_AST_NODE(DynArrayType,arr,T);
|
NEW_AST_NODE(DynArrayType,arr,T);
|
||||||
|
|
|
@ -1853,16 +1853,96 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
||||||
}
|
}
|
||||||
|
|
||||||
case AST_MapType:
|
case AST_MapType:
|
||||||
if (allowarraytypes)
|
{
|
||||||
|
if(AST.ParseVersion < MakeVersion(4, 10, 0))
|
||||||
{
|
{
|
||||||
Error(field, "%s: Map types not implemented yet", name.GetChars());
|
Error(field, "Map not accessible to ZScript version %d.%d.%d", AST.ParseVersion.major, AST.ParseVersion.minor, AST.ParseVersion.revision);
|
||||||
// Todo: Decide what we allow here and if it makes sense to allow more complex constructs.
|
|
||||||
auto mtype = static_cast<ZCC_MapType *>(ztype);
|
|
||||||
retval = NewMap(DetermineType(outertype, field, name, mtype->KeyType, false, false), DetermineType(outertype, field, name, mtype->ValueType, false, false));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
|
// Todo: Decide what we allow here and if it makes sense to allow more complex constructs.
|
||||||
|
auto mtype = static_cast<ZCC_MapType *>(ztype);
|
||||||
|
|
||||||
|
auto keytype = DetermineType(outertype, field, name, mtype->KeyType, false, false);
|
||||||
|
auto valuetype = DetermineType(outertype, field, name, mtype->ValueType, false, false);
|
||||||
|
|
||||||
|
if (keytype->GetRegType() == REGT_INT)
|
||||||
|
{
|
||||||
|
if (keytype->Size != 4)
|
||||||
|
{
|
||||||
|
Error(field, "Map<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (keytype->GetRegType() != REGT_STRING)
|
||||||
|
{
|
||||||
|
Error(field, "Map<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(valuetype->GetRegType())
|
||||||
|
{
|
||||||
|
case REGT_FLOAT:
|
||||||
|
case REGT_INT:
|
||||||
|
case REGT_STRING:
|
||||||
|
case REGT_POINTER:
|
||||||
|
if (valuetype->GetRegCount() > 1)
|
||||||
|
{
|
||||||
|
Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = NewMap(keytype, valuetype);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error(field, "%s: Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AST_MapIteratorType:
|
||||||
|
{
|
||||||
|
if(AST.ParseVersion < MakeVersion(4, 10, 0))
|
||||||
|
{
|
||||||
|
Error(field, "MapIterator not accessible to ZScript version %d.%d.%d", AST.ParseVersion.major, AST.ParseVersion.minor, AST.ParseVersion.revision);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Todo: Decide what we allow here and if it makes sense to allow more complex constructs.
|
||||||
|
auto mtype = static_cast<ZCC_MapIteratorType *>(ztype);
|
||||||
|
|
||||||
|
auto keytype = DetermineType(outertype, field, name, mtype->KeyType, false, false);
|
||||||
|
auto valuetype = DetermineType(outertype, field, name, mtype->ValueType, false, false);
|
||||||
|
|
||||||
|
if (keytype->GetRegType() == REGT_INT)
|
||||||
|
{
|
||||||
|
if (keytype->Size != 4)
|
||||||
|
{
|
||||||
|
Error(field, "MapIterator<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (keytype->GetRegType() != REGT_STRING)
|
||||||
|
{
|
||||||
|
Error(field, "MapIterator<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(valuetype->GetRegType())
|
||||||
|
{
|
||||||
|
case REGT_FLOAT:
|
||||||
|
case REGT_INT:
|
||||||
|
case REGT_STRING:
|
||||||
|
case REGT_POINTER:
|
||||||
|
if (valuetype->GetRegCount() > 1)
|
||||||
|
{
|
||||||
|
Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
retval = NewMapIterator(keytype, valuetype);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error(field, "%s: Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case AST_DynArrayType:
|
case AST_DynArrayType:
|
||||||
{
|
{
|
||||||
auto atype = static_cast<ZCC_DynArrayType *>(ztype);
|
auto atype = static_cast<ZCC_DynArrayType *>(ztype);
|
||||||
|
@ -2357,7 +2437,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
{
|
{
|
||||||
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
|
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if ((type->isStruct() && type != TypeVector2 && type != TypeVector3 && type != TypeVector4 && type != TypeQuaternion && type != TypeFVector2 && type != TypeFVector3 && type != TypeFVector4 && type != TypeFQuaternion) || type->isDynArray())
|
if ((type->isStruct() && type != TypeVector2 && type != TypeVector3 && type != TypeVector4 && type != TypeQuaternion && type != TypeFVector2 && type != TypeFVector3 && type != TypeFVector4 && type != TypeFQuaternion) || type->isDynArray() || type->isMap() || type->isMapIterator())
|
||||||
{
|
{
|
||||||
// Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
|
// Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
|
||||||
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
|
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
|
||||||
|
|
|
@ -220,6 +220,7 @@ static void InitTokenMap()
|
||||||
TOKENDEF2(TK_Vector3, ZCC_VECTOR3, NAME_Vector3);
|
TOKENDEF2(TK_Vector3, ZCC_VECTOR3, NAME_Vector3);
|
||||||
TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name);
|
TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name);
|
||||||
TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map);
|
TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map);
|
||||||
|
TOKENDEF2(TK_MapIterator, ZCC_MAPITERATOR,NAME_MapIterator);
|
||||||
TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array);
|
TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array);
|
||||||
TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include);
|
TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include);
|
||||||
TOKENDEF (TK_Void, ZCC_VOID);
|
TOKENDEF (TK_Void, ZCC_VOID);
|
||||||
|
@ -896,6 +897,19 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AST_MapIteratorType:
|
||||||
|
{
|
||||||
|
TreeNodeDeepCopy_Start(MapIteratorType);
|
||||||
|
|
||||||
|
// ZCC_Type
|
||||||
|
copy->ArraySize = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->ArraySize, true, copiedNodesList));
|
||||||
|
// AST_MapIteratorType
|
||||||
|
copy->KeyType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->KeyType, true, copiedNodesList));
|
||||||
|
copy->ValueType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->ValueType, true, copiedNodesList));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case AST_DynArrayType:
|
case AST_DynArrayType:
|
||||||
{
|
{
|
||||||
TreeNodeDeepCopy_Start(DynArrayType);
|
TreeNodeDeepCopy_Start(DynArrayType);
|
||||||
|
@ -1128,7 +1142,7 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c
|
||||||
{
|
{
|
||||||
TreeNodeDeepCopy_Start(ArrayIterationStmt);
|
TreeNodeDeepCopy_Start(ArrayIterationStmt);
|
||||||
|
|
||||||
// ZCC_IterationStmt
|
// ZCC_ArrayIterationStmt
|
||||||
copy->ItName = static_cast<ZCC_VarName*>(TreeNodeDeepCopy_Internal(ast, origCasted->ItName, true, copiedNodesList));
|
copy->ItName = static_cast<ZCC_VarName*>(TreeNodeDeepCopy_Internal(ast, origCasted->ItName, true, copiedNodesList));
|
||||||
copy->LoopStatement = static_cast<ZCC_Statement*>(TreeNodeDeepCopy_Internal(ast, origCasted->LoopStatement, true, copiedNodesList));
|
copy->LoopStatement = static_cast<ZCC_Statement*>(TreeNodeDeepCopy_Internal(ast, origCasted->LoopStatement, true, copiedNodesList));
|
||||||
copy->ItArray = static_cast<ZCC_Expression*>(TreeNodeDeepCopy_Internal(ast, origCasted->ItArray, true, copiedNodesList));
|
copy->ItArray = static_cast<ZCC_Expression*>(TreeNodeDeepCopy_Internal(ast, origCasted->ItArray, true, copiedNodesList));
|
||||||
|
|
|
@ -98,6 +98,7 @@ enum EZCCTreeNodeType
|
||||||
AST_Type,
|
AST_Type,
|
||||||
AST_BasicType,
|
AST_BasicType,
|
||||||
AST_MapType,
|
AST_MapType,
|
||||||
|
AST_MapIteratorType,
|
||||||
AST_DynArrayType,
|
AST_DynArrayType,
|
||||||
AST_ClassType,
|
AST_ClassType,
|
||||||
AST_Expression,
|
AST_Expression,
|
||||||
|
@ -367,6 +368,12 @@ struct ZCC_MapType : ZCC_Type
|
||||||
ZCC_Type *ValueType;
|
ZCC_Type *ValueType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ZCC_MapIteratorType : ZCC_Type
|
||||||
|
{
|
||||||
|
ZCC_Type *KeyType;
|
||||||
|
ZCC_Type *ValueType;
|
||||||
|
};
|
||||||
|
|
||||||
struct ZCC_DynArrayType : ZCC_Type
|
struct ZCC_DynArrayType : ZCC_Type
|
||||||
{
|
{
|
||||||
ZCC_Type *ElementType;
|
ZCC_Type *ElementType;
|
||||||
|
@ -601,7 +608,7 @@ struct ZCC_MixinStmt : ZCC_Statement
|
||||||
ENamedName MixinName;
|
ENamedName MixinName;
|
||||||
};
|
};
|
||||||
|
|
||||||
FString ZCC_PrintAST(ZCC_TreeNode *root);
|
FString ZCC_PrintAST(const ZCC_TreeNode *root);
|
||||||
|
|
||||||
|
|
||||||
struct ZCC_AST
|
struct ZCC_AST
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
bool gameisdead;
|
bool gameisdead;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#include <cstdarg>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "zstring.h"
|
#include "zstring.h"
|
||||||
void I_DebugPrint(const char *cp)
|
void I_DebugPrint(const char *cp)
|
||||||
|
@ -46,10 +47,31 @@ void I_DebugPrint(const char *cp)
|
||||||
OutputDebugStringW(wstr.c_str());
|
OutputDebugStringW(wstr.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I_DebugPrintf(const char *fmt,...)
|
||||||
|
{
|
||||||
|
if (IsDebuggerPresent())
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
FString s;
|
||||||
|
s.VFormat(fmt, args);
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
auto wstr = WideString(s);
|
||||||
|
OutputDebugStringW(wstr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
void I_DebugPrint(const char *cp)
|
void I_DebugPrint(const char *cp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I_DebugPrintf(const char *fmt,...)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "engineerrors.h"
|
#include "engineerrors.h"
|
||||||
|
|
|
@ -916,6 +916,9 @@ public:
|
||||||
typedef struct { const KT Key; VT Value; } Pair;
|
typedef struct { const KT Key; VT Value; } Pair;
|
||||||
typedef const Pair ConstPair;
|
typedef const Pair ConstPair;
|
||||||
|
|
||||||
|
typedef KT KeyType;
|
||||||
|
typedef VT ValueType;
|
||||||
|
|
||||||
TMap() { NumUsed = 0; SetNodeVector(1); }
|
TMap() { NumUsed = 0; SetNodeVector(1); }
|
||||||
TMap(hash_t size) { NumUsed = 0; SetNodeVector(size); }
|
TMap(hash_t size) { NumUsed = 0; SetNodeVector(size); }
|
||||||
~TMap() { ClearNodeVector(); }
|
~TMap() { ClearNodeVector(); }
|
||||||
|
|
|
@ -1547,6 +1547,16 @@ inline TAngle<T> interpolatedvalue(const TAngle<T> &oang, const TAngle<T> &ang,
|
||||||
return oang + (deltaangle(oang, ang) * interpfrac);
|
return oang + (deltaangle(oang, ang) * interpfrac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline TRotator<T> interpolatedvalue(const TRotator<T> &oang, const TRotator<T> &ang, const double interpfrac)
|
||||||
|
{
|
||||||
|
return TRotator<T>(
|
||||||
|
interpolatedvalue(oang.Pitch, ang.Pitch, interpfrac),
|
||||||
|
interpolatedvalue(oang.Yaw, ang.Yaw, interpfrac),
|
||||||
|
interpolatedvalue(oang.Roll, ang.Roll, interpfrac)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T interpolatedvalue(const T& oval, const T& val, const double interpfrac)
|
inline T interpolatedvalue(const T& oval, const T& val, const double interpfrac)
|
||||||
{
|
{
|
||||||
|
|
|
@ -430,7 +430,7 @@ void initshell(DDukeActor* actj, DDukeActor* act, bool isshell)
|
||||||
ang = ps[snum].angle.ang - mapangle((krand() & 63) + 8); //Fine tune
|
ang = ps[snum].angle.ang - mapangle((krand() & 63) + 8); //Fine tune
|
||||||
|
|
||||||
act->temp_data[0] = krand() & 1;
|
act->temp_data[0] = krand() & 1;
|
||||||
act->spr.pos.Z = 3 + ps[snum].pos.Z + ps[snum].pyoff + (ps[snum].horizon.sum().Tan() * 8.) + (!isshell ? 3 : 0);
|
act->spr.pos.Z = 3 + ps[snum].pos.Z + ps[snum].pyoff + (ps[snum].horizon.sum().Sin() * 8.) + (!isshell ? 3 : 0);
|
||||||
act->vel.Z = -krandf(1);
|
act->vel.Z = -krandf(1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -14,6 +14,7 @@ version "4.10"
|
||||||
#include "zscript/engine/ui/menu/menu.zs"
|
#include "zscript/engine/ui/menu/menu.zs"
|
||||||
#include "zscript/engine/ui/menu/menuitembase.zs"
|
#include "zscript/engine/ui/menu/menuitembase.zs"
|
||||||
#include "zscript/engine/ui/menu/messagebox.zs"
|
#include "zscript/engine/ui/menu/messagebox.zs"
|
||||||
|
#include "zscript/engine/ui/menu/custommessagebox.zs"
|
||||||
#include "zscript/engine/ui/menu/optionmenu.zs"
|
#include "zscript/engine/ui/menu/optionmenu.zs"
|
||||||
#include "zscript/engine/ui/menu/optionmenuitems.zs"
|
#include "zscript/engine/ui/menu/optionmenuitems.zs"
|
||||||
#include "zscript/engine/ui/menu/reverbedit.zs"
|
#include "zscript/engine/ui/menu/reverbedit.zs"
|
||||||
|
|
|
@ -893,3 +893,16 @@ struct Translation version("2.4")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convenient way to attach functions to Quat
|
||||||
|
struct QuatStruct native
|
||||||
|
{
|
||||||
|
native static Quat SLerp(Quat from, Quat to, double t);
|
||||||
|
native static Quat NLerp(Quat from, Quat to, double t);
|
||||||
|
native static Quat FromAngles(double yaw, double pitch, double roll);
|
||||||
|
native static Quat AxisAngle(Vector3 xyz, double angle);
|
||||||
|
native Quat Conjugate();
|
||||||
|
native Quat Inverse();
|
||||||
|
// native double Length();
|
||||||
|
// native double LengthSquared();
|
||||||
|
// native Quat Unit();
|
||||||
|
}
|
||||||
|
|
447
wadsrc/static/zscript/engine/maps.zs
Normal file
447
wadsrc/static/zscript/engine/maps.zs
Normal file
|
@ -0,0 +1,447 @@
|
||||||
|
|
||||||
|
struct Map_I32_I8 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_I8 other);
|
||||||
|
native void Move(Map_I32_I8 other);
|
||||||
|
native void Swap(Map_I32_I8 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,int value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_I8 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_I8 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_I16 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_I16 other);
|
||||||
|
native void Move(Map_I32_I16 other);
|
||||||
|
native void Swap(Map_I32_I16 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,int value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_I16 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_I16 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_I32 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_I32 other);
|
||||||
|
native void Move(Map_I32_I32 other);
|
||||||
|
native void Swap(Map_I32_I32 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,int value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_I32 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_I32 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_F32 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_F32 other);
|
||||||
|
native void Move(Map_I32_F32 other);
|
||||||
|
native void Swap(Map_I32_F32 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native double Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,double value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_F32 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_F32 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native double GetValue();
|
||||||
|
native void SetValue(double value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_F64 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_F64 other);
|
||||||
|
native void Move(Map_I32_F64 other);
|
||||||
|
native void Swap(Map_I32_F64 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native double Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,double value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_F64 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_F64 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native double GetValue();
|
||||||
|
native void SetValue(double value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_Obj native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_Obj other);
|
||||||
|
native void Move(Map_I32_Obj other);
|
||||||
|
native void Swap(Map_I32_Obj other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native Object Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,Object value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_Obj native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_Obj other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native Object GetValue();
|
||||||
|
native void SetValue(Object value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_Ptr native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_Ptr other);
|
||||||
|
native void Move(Map_I32_Ptr other);
|
||||||
|
native void Swap(Map_I32_Ptr other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native voidptr Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,voidptr value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_Ptr native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_Ptr other);
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native voidptr GetValue();
|
||||||
|
native void SetValue(voidptr value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_I32_Str native
|
||||||
|
{
|
||||||
|
native void Copy(Map_I32_Str other);
|
||||||
|
native void Move(Map_I32_Str other);
|
||||||
|
native void Swap(Map_I32_Str other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native String Get(int key);
|
||||||
|
native bool CheckKey(int key);
|
||||||
|
native void Insert(int key,String value);
|
||||||
|
native void InsertNew(int key);
|
||||||
|
native void Remove(int key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_I32_Str native
|
||||||
|
{
|
||||||
|
native bool Init(Map_I32_Str other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native int GetKey();
|
||||||
|
native String GetValue();
|
||||||
|
native void SetValue(String value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------
|
||||||
|
|
||||||
|
struct Map_Str_I8 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_I8 other);
|
||||||
|
native void Move(Map_Str_I8 other);
|
||||||
|
native void Swap(Map_Str_I8 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,int value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_I8 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_I8 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_I16 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_I16 other);
|
||||||
|
native void Move(Map_Str_I16 other);
|
||||||
|
native void Swap(Map_Str_I16 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,int value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_I16 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_I16 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_I32 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_I32 other);
|
||||||
|
native void Move(Map_Str_I32 other);
|
||||||
|
native void Swap(Map_Str_I32 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native int Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,int value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_I32 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_I32 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native int GetValue();
|
||||||
|
native void SetValue(int value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_F32 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_F32 other);
|
||||||
|
native void Move(Map_Str_F32 other);
|
||||||
|
native void Swap(Map_Str_F32 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native double Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,double value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_F32 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_F32 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native double GetValue();
|
||||||
|
native void SetValue(double value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_F64 native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_F64 other);
|
||||||
|
native void Move(Map_Str_F64 other);
|
||||||
|
native void Swap(Map_Str_F64 other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native double Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,double value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_F64 native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_F64 other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native double GetValue();
|
||||||
|
native void SetValue(double value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_Obj native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_Obj other);
|
||||||
|
native void Move(Map_Str_Obj other);
|
||||||
|
native void Swap(Map_Str_Obj other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native Object Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,Object value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_Obj native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_Obj other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native Object GetValue();
|
||||||
|
native void SetValue(Object value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_Ptr native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_Ptr other);
|
||||||
|
native void Move(Map_Str_Ptr other);
|
||||||
|
native void Swap(Map_Str_Ptr other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native voidptr Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,voidptr value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_Ptr native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_Ptr other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native voidptr GetValue();
|
||||||
|
native void SetValue(voidptr value);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map_Str_Str native
|
||||||
|
{
|
||||||
|
native void Copy(Map_Str_Str other);
|
||||||
|
native void Move(Map_Str_Str other);
|
||||||
|
native void Swap(Map_Str_Str other);
|
||||||
|
native void Clear();
|
||||||
|
native uint CountUsed();
|
||||||
|
|
||||||
|
native String Get(String key);
|
||||||
|
native bool CheckKey(String key);
|
||||||
|
native void Insert(String key,String value);
|
||||||
|
native void InsertNew(String key);
|
||||||
|
native void Remove(String key);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapIterator_Str_Str native
|
||||||
|
{
|
||||||
|
native bool Init(Map_Str_Str other);
|
||||||
|
native bool ReInit();
|
||||||
|
|
||||||
|
native bool Valid();
|
||||||
|
native bool Next();
|
||||||
|
|
||||||
|
native String GetKey();
|
||||||
|
native String GetValue();
|
||||||
|
native void SetValue(String value);
|
||||||
|
}
|
264
wadsrc/static/zscript/engine/ui/menu/custommessagebox.zs
Normal file
264
wadsrc/static/zscript/engine/ui/menu/custommessagebox.zs
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2010-2017 Christoph Oelckers
|
||||||
|
** Copyright 2022 Ricardo Luis Vaz Silva
|
||||||
|
**
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CustomMessageBoxMenuBase : Menu abstract
|
||||||
|
{
|
||||||
|
BrokenLines mMessage;
|
||||||
|
uint messageSelection;
|
||||||
|
int mMouseLeft, mMouseRight, mMouseY;
|
||||||
|
|
||||||
|
Font textFont, arrowFont;
|
||||||
|
int destWidth, destHeight;
|
||||||
|
String selector;
|
||||||
|
|
||||||
|
abstract uint OptionCount();
|
||||||
|
abstract String OptionName(uint index);
|
||||||
|
abstract int OptionXOffset(uint index);
|
||||||
|
|
||||||
|
abstract int OptionForShortcut(int char_key, out bool activate); // -1 for no shortcut, activate = true if this executes the option immediately
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
virtual void Init(Menu parent, String message, bool playsound = false)
|
||||||
|
{
|
||||||
|
Super.Init(parent);
|
||||||
|
messageSelection = 0;
|
||||||
|
mMouseLeft = 140;
|
||||||
|
mMouseY = 0x80000000;
|
||||||
|
textFont = null;
|
||||||
|
|
||||||
|
if (!generic_ui)
|
||||||
|
{
|
||||||
|
if (SmallFont && SmallFont.CanPrint(message) && SmallFont.CanPrint("$TXT_YES") && SmallFont.CanPrint("$TXT_NO")) textFont = SmallFont;
|
||||||
|
else if (OriginalSmallFont && OriginalSmallFont.CanPrint(message) && OriginalSmallFont.CanPrint("$TXT_YES") && OriginalSmallFont.CanPrint("$TXT_NO")) textFont = OriginalSmallFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!textFont)
|
||||||
|
{
|
||||||
|
arrowFont = textFont = NewSmallFont;
|
||||||
|
int factor = (CleanXfac+1) / 2;
|
||||||
|
destWidth = screen.GetWidth() / factor;
|
||||||
|
destHeight = screen.GetHeight() / factor;
|
||||||
|
selector = "▶";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arrowFont = ConFont;
|
||||||
|
destWidth = CleanWidth;
|
||||||
|
destHeight = CleanHeight;
|
||||||
|
selector = "\xd";
|
||||||
|
}
|
||||||
|
|
||||||
|
int mr1 = destWidth/2 + 10 + textFont.StringWidth(Stringtable.Localize("$TXT_YES"));
|
||||||
|
int mr2 = destWidth/2 + 10 + textFont.StringWidth(Stringtable.Localize("$TXT_NO"));
|
||||||
|
mMouseRight = MAX(mr1, mr2);
|
||||||
|
mParentMenu = parent;
|
||||||
|
mMessage = textFont.BreakLines(Stringtable.Localize(message), int(300/NotifyFontScale));
|
||||||
|
if (playsound)
|
||||||
|
{
|
||||||
|
MenuSound ("menu/prompt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
override void Drawer ()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
double y;
|
||||||
|
let fontheight = textFont.GetHeight() * NotifyFontScale;
|
||||||
|
|
||||||
|
y = destHeight / 2;
|
||||||
|
|
||||||
|
int c = mMessage.Count();
|
||||||
|
y -= c * fontHeight / 2;
|
||||||
|
|
||||||
|
for (i = 0; i < c; i++)
|
||||||
|
{
|
||||||
|
screen.DrawText (textFont, Font.CR_UNTRANSLATED, destWidth/2 - mMessage.StringWidth(i)*NotifyFontScale/2, y, mMessage.StringAt(i), DTA_VirtualWidth, destWidth, DTA_VirtualHeight, destHeight, DTA_KeepRatio, true,
|
||||||
|
DTA_ScaleX, NotifyFontScale, DTA_ScaleY, NotifyFontScale);
|
||||||
|
y += fontheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
y += fontheight;
|
||||||
|
mMouseY = int(y);
|
||||||
|
|
||||||
|
let n = optionCount();
|
||||||
|
for(uint i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
screen.DrawText(textFont, messageSelection == i? OptionMenuSettings.mFontColorSelection : OptionMenuSettings.mFontColor, (destWidth / 2) + OptionXOffset(i), y + (fontheight * i), Stringtable.Localize(optionName(i)), DTA_VirtualWidth, destWidth, DTA_VirtualHeight, destHeight, DTA_KeepRatio, true, DTA_ScaleX, NotifyFontScale, DTA_ScaleY, NotifyFontScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messageSelection >= 0)
|
||||||
|
{
|
||||||
|
if ((MenuTime() % 8) < 6)
|
||||||
|
{
|
||||||
|
screen.DrawText(arrowFont, OptionMenuSettings.mFontColorSelection,
|
||||||
|
(destWidth/2 - 11) + OptionXOffset(messageSelection), y + fontheight * messageSelection, selector, DTA_VirtualWidth, destWidth, DTA_VirtualHeight, destHeight, DTA_KeepRatio, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
protected void CloseSound()
|
||||||
|
{
|
||||||
|
MenuSound (GetCurrentMenu() != NULL? "menu/backup" : "menu/dismiss");
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
abstract void HandleResult(int index); // -1 = escape
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
override bool OnUIEvent(UIEvent ev)
|
||||||
|
{
|
||||||
|
if (ev.type == UIEvent.Type_KeyDown)
|
||||||
|
{
|
||||||
|
// tolower
|
||||||
|
int ch = ev.KeyChar;
|
||||||
|
ch = ch >= 65 && ch <91? ch + 32 : ch;
|
||||||
|
|
||||||
|
bool activate;
|
||||||
|
int opt = optionForShortcut(ch,activate);
|
||||||
|
|
||||||
|
if(opt >= 0){
|
||||||
|
if(activate || opt == messageSelection) {
|
||||||
|
HandleResult(messageSelection);
|
||||||
|
} else {
|
||||||
|
messageSelection = opt;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Super.OnUIEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
override bool OnInputEvent(InputEvent ev)
|
||||||
|
{
|
||||||
|
if (ev.type == InputEvent.Type_KeyDown)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Super.OnInputEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
override bool MenuEvent(int mkey, bool fromcontroller)
|
||||||
|
{
|
||||||
|
if (mkey == MKEY_Up)
|
||||||
|
{
|
||||||
|
MenuSound("menu/cursor");
|
||||||
|
if (messageSelection == 0) messageSelection = optionCount();
|
||||||
|
messageSelection--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (mkey == MKEY_Down)
|
||||||
|
{
|
||||||
|
MenuSound("menu/cursor");
|
||||||
|
messageSelection++;
|
||||||
|
if (messageSelection == optionCount()) messageSelection = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (mkey == MKEY_Enter)
|
||||||
|
{
|
||||||
|
HandleResult(messageSelection);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (mkey == MKEY_Back)
|
||||||
|
{
|
||||||
|
HandleResult(-1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
override bool MouseEvent(int type, int x, int y)
|
||||||
|
{
|
||||||
|
int fh = textFont.GetHeight() + 1;
|
||||||
|
|
||||||
|
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||||
|
x = x * destWidth / screen.GetWidth();
|
||||||
|
y = y * destHeight / screen.GetHeight();
|
||||||
|
|
||||||
|
int n = OptionCount();
|
||||||
|
|
||||||
|
if (x >= mMouseLeft && x <= mMouseRight && y >= mMouseY && y < mMouseY + (n * fh))
|
||||||
|
{
|
||||||
|
messageSelection = (y - mMouseY) / fh;
|
||||||
|
}
|
||||||
|
if (type == MOUSE_Release)
|
||||||
|
{
|
||||||
|
return MenuEvent(MKEY_Enter, true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -41,6 +41,8 @@ class ImageScrollerDescriptor : MenuDescriptor native
|
||||||
native double textScale;
|
native double textScale;
|
||||||
native bool mAnimatedTransition;
|
native bool mAnimatedTransition;
|
||||||
native bool mAnimated;
|
native bool mAnimated;
|
||||||
|
native bool mDontBlur;
|
||||||
|
native bool mDontDim;
|
||||||
native int virtWidth, virtHeight;
|
native int virtWidth, virtHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,8 +170,10 @@ class ImageScrollerMenu : Menu
|
||||||
mParentMenu = parent;
|
mParentMenu = parent;
|
||||||
index = 0;
|
index = 0;
|
||||||
mDesc = desc;
|
mDesc = desc;
|
||||||
AnimatedTransition = desc.mAnimatedTransition;
|
AnimatedTransition = mDesc.mAnimatedTransition;
|
||||||
Animated = desc.mAnimated;
|
Animated = mDesc.mAnimated;
|
||||||
|
DontBlur = mDesc.mDontBlur;
|
||||||
|
DontDim = mDesc.mDontDim;
|
||||||
current = mDesc.mItems[0];
|
current = mDesc.mItems[0];
|
||||||
current.onStartPage();
|
current.onStartPage();
|
||||||
previous = null;
|
previous = null;
|
||||||
|
|
|
@ -57,6 +57,8 @@ class ListMenuDescriptor : MenuDescriptor native
|
||||||
native bool mCenter;
|
native bool mCenter;
|
||||||
native bool mAnimatedTransition;
|
native bool mAnimatedTransition;
|
||||||
native bool mAnimated;
|
native bool mAnimated;
|
||||||
|
native bool mDontBlur;
|
||||||
|
native bool mDontDim;
|
||||||
native int mVirtWidth, mVirtHeight;
|
native int mVirtWidth, mVirtHeight;
|
||||||
|
|
||||||
native void Reset();
|
native void Reset();
|
||||||
|
@ -89,6 +91,8 @@ class ListMenu : Menu
|
||||||
mDesc = desc;
|
mDesc = desc;
|
||||||
AnimatedTransition = mDesc.mAnimatedTransition;
|
AnimatedTransition = mDesc.mAnimatedTransition;
|
||||||
Animated = mDesc.mAnimated;
|
Animated = mDesc.mAnimated;
|
||||||
|
DontBlur = mDesc.mDontBlur;
|
||||||
|
DontDim = mDesc.mDontDim;
|
||||||
if (desc.mCenter)
|
if (desc.mCenter)
|
||||||
{
|
{
|
||||||
double center = 160;
|
double center = 160;
|
||||||
|
|
|
@ -55,6 +55,9 @@ class OptionMenuDescriptor : MenuDescriptor native
|
||||||
native int mIndent;
|
native int mIndent;
|
||||||
native int mPosition;
|
native int mPosition;
|
||||||
native bool mDontDim;
|
native bool mDontDim;
|
||||||
|
native bool mDontBlur;
|
||||||
|
native bool mAnimatedTransition;
|
||||||
|
native bool mAnimated;
|
||||||
native Font mFont;
|
native Font mFont;
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
|
@ -106,6 +109,9 @@ class OptionMenu : Menu
|
||||||
mParentMenu = parent;
|
mParentMenu = parent;
|
||||||
mDesc = desc;
|
mDesc = desc;
|
||||||
DontDim = desc.mDontDim;
|
DontDim = desc.mDontDim;
|
||||||
|
DontBlur = desc.mDontBlur;
|
||||||
|
AnimatedTransition = desc.mAnimatedTransition;
|
||||||
|
Animated = desc.mAnimated;
|
||||||
|
|
||||||
let itemCount = mDesc.mItems.size();
|
let itemCount = mDesc.mItems.size();
|
||||||
if (itemCount > 0)
|
if (itemCount > 0)
|
||||||
|
|
Loading…
Reference in a new issue