- backend update from GZDoom.

This commit is contained in:
Christoph Oelckers 2022-12-04 16:51:44 +01:00
parent 4666c4a4b5
commit 1061e3e2ca
31 changed files with 2760 additions and 116 deletions

View file

@ -117,6 +117,7 @@ xx(Double)
xx(String)
xx(Vector)
xx(Map)
xx(MapIterator)
xx(Array)
xx(Include)
xx(Sound)
@ -162,6 +163,14 @@ xx(ToVector)
xx(Size)
xx(Push)
xx(Insert)
xx(InsertNew)
xx(Remove)
xx(Get)
xx(GetValue)
xx(GetKey)
xx(SetValue)
xx(CheckKey)
xx(Value)
xx(Copy)
xx(Move)
xx(Voidptr)
@ -174,6 +183,7 @@ xx(IsNull)
xx(Exists)
xx(SetInvalid)
xx(SetNull)
xx(Key)
// color channels
xx(a)

View file

@ -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)));
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
extern bool batchrun;

View file

@ -167,6 +167,7 @@ std2:
'vector2' { RET(TK_Vector2); }
'vector3' { RET(TK_Vector3); }
'map' { RET(TK_Map); }
'mapiterator' { RET(TK_MapIterator); }
'array' { RET(TK_Array); }
'in' { RET(TK_In); }
'sizeof' { RET(TK_SizeOf); }

View file

@ -128,6 +128,7 @@ xx(TK_Replaces, "'replaces'")
xx(TK_Vector2, "'vector2'")
xx(TK_Vector3, "'vector3'")
xx(TK_Map, "'map'")
xx(TK_MapIterator, "'mapiterator'")
xx(TK_Array, "'array'")
xx(TK_In, "'in'")
xx(TK_SizeOf, "'sizeof'")

View file

@ -443,4 +443,5 @@ void LoadHexFont(const char* filename)
auto hexfont = resf->FindLump("newconsolefont.hex");
if (hexfont == nullptr) I_FatalError("Unable to find newconsolefont.hex in %s", filename);
hexdata.ParseDefinition(hexfont);
delete resf;
}

View file

@ -544,7 +544,7 @@ inline FVector3 FOBJModel::RealignVector(FVector3 vecToRealign)
*/
inline FVector2 FOBJModel::FixUV(FVector2 vecToRealign)
{
vecToRealign.Y *= -1;
vecToRealign.Y = 1-vecToRealign.Y;
return vecToRealign;
}

View file

@ -42,6 +42,7 @@
#include "types.h"
#include "i_time.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()
{
const PClass *info = GetClass();
@ -375,6 +387,27 @@ size_t DObject::PropagateMark()
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 0;

View file

@ -82,6 +82,8 @@ DEFINE_GLOBAL(WP_NOCHANGE);
// A harmless non-nullptr FlatPointer for classes without pointers.
static const size_t TheEnd = ~(size_t)0;
static const std::pair<size_t,PType *> TheMapEnd = {~(size_t)0 , nullptr};
//==========================================================================
//
// 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

View file

@ -56,6 +56,7 @@ public:
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 *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 *Meta = nullptr; // Per-class static script data
unsigned Size = sizeof(DObject);
@ -84,6 +85,7 @@ public:
void InitializeActorInfo();
void BuildFlatPointers();
void BuildArrayPointers();
void BuildMapPointers();
void DestroySpecials(void *addr);
void DestroyMeta(void *addr);
const PClass *NativeClass() const;

View file

@ -8205,6 +8205,8 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
PContainerType *ccls = nullptr;
PFunction * afd_override = nullptr;
if (ctx.Class == nullptr)
{
// 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())
{
auto pointedType = Self->ValueType->toPointer()->PointedType;
if (pointedType && pointedType->isDynArray())
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
{
Self = new FxOutVarDereference(Self, Self->ScriptPosition);
SAFE_RESOLVE(Self, ctx);
@ -8454,7 +8456,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (a->ValueType->isRealPointer())
{
auto pointedType = a->ValueType->toPointer()->PointedType;
if (pointedType && pointedType->isDynArray())
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
{
a = new FxOutVarDereference(a, a->ScriptPosition);
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 &&
@ -8635,7 +8824,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
isresolved:
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)
{
delete this;
@ -9034,7 +9223,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
if (ArgList[i] && ArgList[i]->ValueType->isRealPointer())
{
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);
SAFE_RESOLVE(ArgList[i], ctx);
@ -11806,7 +11995,7 @@ FxExpression *FxOutVarDereference::Resolve(FCompileContext &ctx)
SelfType = Self->ValueType->toPointer()->PointedType;
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");
delete this;
@ -11835,7 +12024,7 @@ ExpEmit FxOutVarDereference::Emit(VMFunctionBuilder *build)
regType = REGT_POINTER;
loadOp = OP_LP;
}
else if (SelfType->isDynArray())
else if (SelfType->isDynArray() || SelfType->isMap() || SelfType->isMapIterator())
{
regType = REGT_POINTER;
loadOp = OP_MOVEA;

View file

@ -350,6 +350,8 @@ public:
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 IsDynamicArray() const { return (ValueType->isDynArray()); }
bool IsMap() const { return ValueType->isMap(); }
bool IsMapIterator() const { return ValueType->isMapIterator(); }
bool IsStruct() const { return ValueType->isStruct(); }
bool IsNativeStruct() const { return (ValueType->isStruct() && static_cast<PStruct*>(ValueType)->isNative); }

View 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();

View 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");
}
}
};

View file

@ -33,11 +33,14 @@
**
*/
#include <cinttypes>
#include "vmintern.h"
#include "s_soundinternal.h"
#include "types.h"
#include "printf.h"
#include "textureid.h"
#include "maps.h"
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
@ -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)
{
if (ElementType->isStruct())
if (ElementType->isStruct() || ElementType->isDynArray())
{
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
@ -2202,12 +2226,89 @@ PDynArray *NewDynArray(PType *type)
//
//==========================================================================
PMap::PMap(PType *keytype, PType *valtype)
: KeyType(keytype), ValueType(valtype)
enum OverrideFunctionRetType {
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());
Size = sizeof(FMap);
Align = alignof(FMap);
Size = sizeof(ZSFMap);
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;
}
//==========================================================================
//
// 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
@ -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;
PType *maptype = TypeTable.FindType(NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, &bucket);
if (maptype == nullptr)
PType *mapType = TypeTable.FindType(NAME_Map, (intptr_t)keyType, (intptr_t)valueType, &bucket);
if (mapType == nullptr)
{
maptype = new PMap(keytype, valuetype);
TypeTable.AddType(maptype, NAME_Map, (intptr_t)keytype, (intptr_t)valuetype, bucket);
FString backingName = "Map_";
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 ****************************************************************/
@ -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

View file

@ -129,6 +129,7 @@ public:
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 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)
virtual void InitializeValue(void *addr, const void *def) const;
@ -200,6 +201,8 @@ public:
bool isArray() const { return !!(Flags & TYPE_Array); }
bool isStaticArray() const { return TypeTableType == NAME_StaticArray; }
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 isClass() const { return TypeTableType == NAME_Object; }
bool isPrototype() const { return TypeTableType == NAME_Prototype; }
@ -489,6 +492,7 @@ public:
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *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 SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs = NULL) override;
};
class PStaticArray : public PArray
@ -521,14 +525,72 @@ public:
class PMap : public PCompoundType
{
void Construct(void * addr) const;
public:
PMap(PType *keytype, PType *valtype);
PMap(PType *keytype, PType *valtype, PStruct *backing, int backing_class);
PType *KeyType;
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 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
@ -550,6 +612,7 @@ public:
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *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 SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs) override;
};
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.
PMap *NewMap(PType *keytype, PType *valuetype);
PMapIterator *NewMapIterator(PType *keytype, PType *valuetype);
PArray *NewArray(PType *type, unsigned int count);
PStaticArray *NewStaticArray(PType *type);
PDynArray *NewDynArray(PType *type);

View file

@ -39,7 +39,7 @@
#include "printf.h"
class FLispString;
extern void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *);
using NodePrinterFunc = void (*)(FLispString &, const ZCC_TreeNode *);
static const char *BuiltInTypeNames[] =
{
@ -221,24 +221,11 @@ private:
bool NeedSpace;
};
static void PrintNode(FLispString &out, 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 PrintNode(FLispString &out, const ZCC_TreeNode *node);
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)
{
@ -269,7 +256,7 @@ static void PrintNodes(FLispString &out, ZCC_TreeNode *node, bool newlist=true,
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))
{
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;
out.Open("identifier");
@ -317,7 +304,7 @@ static void PrintStringConst(FLispString &out, FString str)
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;
out.Break();
@ -330,7 +317,7 @@ static void PrintClass(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -340,7 +327,7 @@ static void PrintStruct(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -350,7 +337,7 @@ static void PrintProperty(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -361,7 +348,7 @@ static void PrintFlagDef(FLispString &out, ZCC_TreeNode *node)
out.Close();
}
static void PrintStaticArrayState(FLispString &out, ZCC_TreeNode *node)
static void PrintStaticArrayState(FLispString &out, const ZCC_TreeNode *node)
{
auto *snode = (ZCC_StaticArrayStatement *)node;
out.Break();
@ -371,7 +358,7 @@ static void PrintStaticArrayState(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -382,13 +369,13 @@ static void PrintEnum(FLispString &out, ZCC_TreeNode *node)
out.Close();
}
static void PrintEnumTerminator(FLispString &out, ZCC_TreeNode *node)
static void PrintEnumTerminator(FLispString &out, const ZCC_TreeNode *node)
{
out.Open("enum-term");
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;
out.Break();
@ -398,13 +385,13 @@ static void PrintStates(FLispString &out, ZCC_TreeNode *node)
out.Close();
}
static void PrintStatePart(FLispString &out, ZCC_TreeNode *node)
static void PrintStatePart(FLispString &out, const ZCC_TreeNode *node)
{
out.Open("state-part");
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;
out.Open("state-label");
@ -412,31 +399,31 @@ static void PrintStateLabel(FLispString &out, ZCC_TreeNode *node)
out.Close();
}
static void PrintStateStop(FLispString &out, ZCC_TreeNode *node)
static void PrintStateStop(FLispString &out, const ZCC_TreeNode *node)
{
out.Open("state-stop");
out.Close();
}
static void PrintStateWait(FLispString &out, ZCC_TreeNode *node)
static void PrintStateWait(FLispString &out, const ZCC_TreeNode *node)
{
out.Open("state-wait");
out.Close();
}
static void PrintStateFail(FLispString &out, ZCC_TreeNode *node)
static void PrintStateFail(FLispString &out, const ZCC_TreeNode *node)
{
out.Open("state-fail");
out.Close();
}
static void PrintStateLoop(FLispString &out, ZCC_TreeNode *node)
static void PrintStateLoop(FLispString &out, const ZCC_TreeNode *node)
{
out.Open("state-loop");
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;
out.Open("state-goto");
@ -446,7 +433,7 @@ static void PrintStateGoto(FLispString &out, ZCC_TreeNode *node)
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;
out.Open("state-line");
@ -463,7 +450,7 @@ static void PrintStateLine(FLispString &out, ZCC_TreeNode *node)
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;
out.Open("var-name");
@ -472,7 +459,7 @@ static void PrintVarName(FLispString &out, ZCC_TreeNode *node)
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;
out.Open("var-init");
@ -483,7 +470,7 @@ static void PrintVarInit(FLispString &out, ZCC_TreeNode *node)
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;
out.Open("bad-type");
@ -491,7 +478,7 @@ static void PrintType(FLispString &out, ZCC_TreeNode *node)
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;
out.Open("basic-type");
@ -505,7 +492,7 @@ static void PrintBasicType(FLispString &out, ZCC_TreeNode *node)
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;
out.Open("map-type");
@ -515,7 +502,17 @@ static void PrintMapType(FLispString &out, ZCC_TreeNode *node)
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;
out.Open("dyn-array-type");
@ -524,7 +521,7 @@ static void PrintDynArrayType(FLispString &out, ZCC_TreeNode *node)
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;
out.Open("class-type");
@ -548,14 +545,14 @@ static void OpenExprType(FLispString &out, EZCCExprType type)
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;
OpenExprType(out, enode->Operation);
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;
assert(enode->Operation == PEX_ID);
@ -564,7 +561,7 @@ static void PrintExprID(FLispString &out, ZCC_TreeNode *node)
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;
assert(enode->Operation == PEX_TypeRef);
@ -583,7 +580,7 @@ static void PrintExprTypeRef(FLispString &out, ZCC_TreeNode *node)
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;
assert(enode->Operation == PEX_ConstValue);
@ -611,7 +608,7 @@ static void PrintExprConstant(FLispString &out, ZCC_TreeNode *node)
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;
assert(enode->Operation == PEX_FuncCall);
@ -621,7 +618,7 @@ static void PrintExprFuncCall(FLispString &out, ZCC_TreeNode *node)
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;
assert(enode->Operation == PEX_ClassCast);
@ -631,7 +628,7 @@ static void PrintExprClassCast(FLispString &out, ZCC_TreeNode *node)
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;
out.Open("static-array-stmt");
@ -641,7 +638,7 @@ static void PrintStaticArray(FLispString &out, ZCC_TreeNode *node)
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;
assert(enode->Operation == PEX_MemberAccess);
@ -651,7 +648,7 @@ static void PrintExprMemberAccess(FLispString &out, ZCC_TreeNode *node)
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;
OpenExprType(out, enode->Operation);
@ -659,7 +656,7 @@ static void PrintExprUnary(FLispString &out, ZCC_TreeNode *node)
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;
OpenExprType(out, enode->Operation);
@ -668,7 +665,7 @@ static void PrintExprBinary(FLispString &out, ZCC_TreeNode *node)
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;
OpenExprType(out, enode->Operation);
@ -678,7 +675,7 @@ static void PrintExprTrinary(FLispString &out, ZCC_TreeNode *node)
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;
OpenExprType(out, enode->Operation);
@ -689,7 +686,7 @@ static void PrintVectorInitializer(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -699,13 +696,13 @@ static void PrintFuncParam(FLispString &out, ZCC_TreeNode *node)
out.Close();
}
static void PrintStatement(FLispString &out, ZCC_TreeNode *node)
static void PrintStatement(FLispString &out, const ZCC_TreeNode *node)
{
out.Open("statement");
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;
out.Break();
@ -714,7 +711,7 @@ static void PrintCompoundStmt(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -723,21 +720,21 @@ static void PrintDefault(FLispString &out, ZCC_TreeNode *node)
out.Close();
}
static void PrintContinueStmt(FLispString &out, ZCC_TreeNode *node)
static void PrintContinueStmt(FLispString &out, const ZCC_TreeNode *node)
{
out.Break();
out.Open("continue-stmt");
out.Close();
}
static void PrintBreakStmt(FLispString &out, ZCC_TreeNode *node)
static void PrintBreakStmt(FLispString &out, const ZCC_TreeNode *node)
{
out.Break();
out.Open("break-stmt");
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;
out.Break();
@ -746,7 +743,7 @@ static void PrintReturnStmt(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -755,7 +752,7 @@ static void PrintExpressionStmt(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -770,7 +767,7 @@ static void PrintIterationStmt(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -783,7 +780,7 @@ static void PrintIfStmt(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -794,7 +791,7 @@ static void PrintSwitchStmt(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -810,7 +807,7 @@ static void BadAssignOp(FLispString &out, int op)
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;
out.Open("assign-stmt");
@ -819,7 +816,7 @@ static void PrintAssignStmt(FLispString &out, ZCC_TreeNode *node)
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;
out.Open("local-var-stmt");
@ -828,7 +825,7 @@ static void PrintLocalVarStmt(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -840,7 +837,7 @@ static void PrintFuncParamDecl(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -850,7 +847,7 @@ static void PrintConstantDef(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -860,7 +857,7 @@ static void PrintDeclarator(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -871,7 +868,7 @@ static void PrintVarDeclarator(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -885,7 +882,7 @@ static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node)
out.Close();
}
static void PrintDeclFlags(FLispString &out, ZCC_TreeNode *node)
static void PrintDeclFlags(FLispString &out, const ZCC_TreeNode *node)
{
auto dnode = (ZCC_DeclFlags *)node;
out.Break();
@ -895,7 +892,7 @@ static void PrintDeclFlags(FLispString &out, ZCC_TreeNode *node)
out.Close();
}
static void PrintFlagStmt(FLispString &out, ZCC_TreeNode *node)
static void PrintFlagStmt(FLispString &out, const ZCC_TreeNode *node)
{
auto dnode = (ZCC_FlagStmt *)node;
out.Break();
@ -905,7 +902,7 @@ static void PrintFlagStmt(FLispString &out, ZCC_TreeNode *node)
out.Close();
}
static void PrintPropertyStmt(FLispString &out, ZCC_TreeNode *node)
static void PrintPropertyStmt(FLispString &out, const ZCC_TreeNode *node)
{
auto dnode = (ZCC_PropertyStmt *)node;
out.Break();
@ -915,7 +912,7 @@ static void PrintPropertyStmt(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -925,7 +922,7 @@ static void PrintMixinDef(FLispString &out, ZCC_TreeNode *node)
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;
out.Break();
@ -934,7 +931,20 @@ static void PrintMixinStmt(FLispString &out, ZCC_TreeNode *node)
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,
PrintClass,
@ -955,6 +965,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *
PrintType,
PrintBasicType,
PrintMapType,
PrintMapIteratorType,
PrintDynArrayType,
PrintClassType,
PrintExpression,
@ -995,11 +1006,27 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *
PrintFlagDef,
PrintMixinDef,
PrintMixinStmt,
PrintArrayIterationStmt,
};
FString ZCC_PrintAST(ZCC_TreeNode *root)
FString ZCC_PrintAST(const ZCC_TreeNode *root)
{
FLispString out;
PrintNodes(out, root);
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();
}
}

View file

@ -932,7 +932,7 @@ type_name(X) ::= DOT dottable_id(A).
/* Type names can also be used as identifiers in contexts where type names
* are not normally allowed. */
%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 */
%type aggregate_type {ZCC_Type *}
@ -944,7 +944,7 @@ type_name(X) ::= DOT dottable_id(A).
%type array_size{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);
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;
}
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> */
{
NEW_AST_NODE(DynArrayType,arr,T);

View file

@ -1853,16 +1853,96 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
}
case AST_MapType:
if (allowarraytypes)
{
if(AST.ParseVersion < MakeVersion(4, 10, 0))
{
Error(field, "%s: Map types not implemented yet", name.GetChars());
// 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));
Error(field, "Map not accessible to ZScript version %d.%d.%d", AST.ParseVersion.major, AST.ParseVersion.minor, AST.ParseVersion.revision);
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:
{
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);
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.
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);

View file

@ -220,6 +220,7 @@ static void InitTokenMap()
TOKENDEF2(TK_Vector3, ZCC_VECTOR3, NAME_Vector3);
TOKENDEF2(TK_Name, ZCC_NAME, NAME_Name);
TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map);
TOKENDEF2(TK_MapIterator, ZCC_MAPITERATOR,NAME_MapIterator);
TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array);
TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include);
TOKENDEF (TK_Void, ZCC_VOID);
@ -896,6 +897,19 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c
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:
{
TreeNodeDeepCopy_Start(DynArrayType);
@ -1128,7 +1142,7 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c
{
TreeNodeDeepCopy_Start(ArrayIterationStmt);
// ZCC_IterationStmt
// ZCC_ArrayIterationStmt
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->ItArray = static_cast<ZCC_Expression*>(TreeNodeDeepCopy_Internal(ast, origCasted->ItArray, true, copiedNodesList));

View file

@ -98,6 +98,7 @@ enum EZCCTreeNodeType
AST_Type,
AST_BasicType,
AST_MapType,
AST_MapIteratorType,
AST_DynArrayType,
AST_ClassType,
AST_Expression,
@ -367,6 +368,12 @@ struct ZCC_MapType : ZCC_Type
ZCC_Type *ValueType;
};
struct ZCC_MapIteratorType : ZCC_Type
{
ZCC_Type *KeyType;
ZCC_Type *ValueType;
};
struct ZCC_DynArrayType : ZCC_Type
{
ZCC_Type *ElementType;
@ -601,7 +608,7 @@ struct ZCC_MixinStmt : ZCC_Statement
ENamedName MixinName;
};
FString ZCC_PrintAST(ZCC_TreeNode *root);
FString ZCC_PrintAST(const ZCC_TreeNode *root);
struct ZCC_AST

View file

@ -36,6 +36,7 @@
bool gameisdead;
#ifdef _WIN32
#include <cstdarg>
#include <windows.h>
#include "zstring.h"
void I_DebugPrint(const char *cp)
@ -46,10 +47,31 @@ void I_DebugPrint(const char *cp)
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
void I_DebugPrint(const char *cp)
{
}
}
void I_DebugPrintf(const char *fmt,...)
{
}
#endif
#include "engineerrors.h"

View file

@ -916,6 +916,9 @@ public:
typedef struct { const KT Key; VT Value; } Pair;
typedef const Pair ConstPair;
typedef KT KeyType;
typedef VT ValueType;
TMap() { NumUsed = 0; SetNodeVector(1); }
TMap(hash_t size) { NumUsed = 0; SetNodeVector(size); }
~TMap() { ClearNodeVector(); }

View file

@ -1547,6 +1547,16 @@ inline TAngle<T> interpolatedvalue(const TAngle<T> &oang, const TAngle<T> &ang,
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>
inline T interpolatedvalue(const T& oval, const T& val, const double interpfrac)
{

View file

@ -430,7 +430,7 @@ void initshell(DDukeActor* actj, DDukeActor* act, bool isshell)
ang = ps[snum].angle.ang - mapangle((krand() & 63) + 8); //Fine tune
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);
}
else

View file

@ -14,6 +14,7 @@ version "4.10"
#include "zscript/engine/ui/menu/menu.zs"
#include "zscript/engine/ui/menu/menuitembase.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/optionmenuitems.zs"
#include "zscript/engine/ui/menu/reverbedit.zs"

View file

@ -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();
}

View 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);
}

View 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;
}
}

View file

@ -41,6 +41,8 @@ class ImageScrollerDescriptor : MenuDescriptor native
native double textScale;
native bool mAnimatedTransition;
native bool mAnimated;
native bool mDontBlur;
native bool mDontDim;
native int virtWidth, virtHeight;
}
@ -168,8 +170,10 @@ class ImageScrollerMenu : Menu
mParentMenu = parent;
index = 0;
mDesc = desc;
AnimatedTransition = desc.mAnimatedTransition;
Animated = desc.mAnimated;
AnimatedTransition = mDesc.mAnimatedTransition;
Animated = mDesc.mAnimated;
DontBlur = mDesc.mDontBlur;
DontDim = mDesc.mDontDim;
current = mDesc.mItems[0];
current.onStartPage();
previous = null;

View file

@ -57,6 +57,8 @@ class ListMenuDescriptor : MenuDescriptor native
native bool mCenter;
native bool mAnimatedTransition;
native bool mAnimated;
native bool mDontBlur;
native bool mDontDim;
native int mVirtWidth, mVirtHeight;
native void Reset();
@ -89,6 +91,8 @@ class ListMenu : Menu
mDesc = desc;
AnimatedTransition = mDesc.mAnimatedTransition;
Animated = mDesc.mAnimated;
DontBlur = mDesc.mDontBlur;
DontDim = mDesc.mDontDim;
if (desc.mCenter)
{
double center = 160;

View file

@ -55,6 +55,9 @@ class OptionMenuDescriptor : MenuDescriptor native
native int mIndent;
native int mPosition;
native bool mDontDim;
native bool mDontBlur;
native bool mAnimatedTransition;
native bool mAnimated;
native Font mFont;
void Reset()
@ -106,6 +109,9 @@ class OptionMenu : Menu
mParentMenu = parent;
mDesc = desc;
DontDim = desc.mDontDim;
DontBlur = desc.mDontBlur;
AnimatedTransition = desc.mAnimatedTransition;
Animated = desc.mAnimated;
let itemCount = mDesc.mItems.size();
if (itemCount > 0)