mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 23:32:02 +00:00
- Some abstract syntax tree creation stuff. (Plus some tentative type creation stuff that made
me realize I would be better off creating a type-agnostic AST for the entire input instead of trying to tentatively create types before they're seen.) SVN r2354 (scripting)
This commit is contained in:
parent
50d126e78b
commit
c043627cc1
9 changed files with 1917 additions and 287 deletions
306
src/dobjtype.cpp
306
src/dobjtype.cpp
|
@ -211,7 +211,7 @@ PType::~PType()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool PType::IsMatch(const void *id1, const void *id2) const
|
bool PType::IsMatch(intptr_t id1, intptr_t id2) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ bool PType::IsMatch(const void *id1, const void *id2) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PType::GetTypeIDs(const void *&id1, const void *&id2) const
|
void PType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
{
|
{
|
||||||
id1 = NULL;
|
id1 = NULL;
|
||||||
id2 = NULL;
|
id2 = NULL;
|
||||||
|
@ -313,7 +313,7 @@ END_POINTERS
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool PNamedType::IsMatch(const void *id1, const void *id2) const
|
bool PNamedType::IsMatch(intptr_t id1, intptr_t id2) const
|
||||||
{
|
{
|
||||||
const DObject *outer = (const DObject *)id1;
|
const DObject *outer = (const DObject *)id1;
|
||||||
FName name = (ENamedName)(intptr_t)id2;
|
FName name = (ENamedName)(intptr_t)id2;
|
||||||
|
@ -327,10 +327,10 @@ bool PNamedType::IsMatch(const void *id1, const void *id2) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PNamedType::GetTypeIDs(const void *&id1, const void *&id2) const
|
void PNamedType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
{
|
{
|
||||||
id1 = Outer;
|
id1 = (intptr_t)Outer;
|
||||||
id2 = (void *)(intptr_t)TypeName;
|
id2 = TypeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PInt *******************************************************************/
|
/* PInt *******************************************************************/
|
||||||
|
@ -454,13 +454,37 @@ IMPLEMENT_POINTY_CLASS(PPointer)
|
||||||
DECLARE_POINTER(PointedType)
|
DECLARE_POINTER(PointedType)
|
||||||
END_POINTERS
|
END_POINTERS
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PPointer - Default Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PPointer::PPointer()
|
||||||
|
: PInt(sizeof(void *), true), PointedType(NULL)
|
||||||
|
{
|
||||||
|
Align = __alignof(void *);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PPointer - Parameterized Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PPointer::PPointer(PType *pointsat)
|
||||||
|
: PInt(sizeof(void *), true), PointedType(pointsat)
|
||||||
|
{
|
||||||
|
Align = __alignof(void *);
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PPointer :: IsMatch
|
// PPointer :: IsMatch
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool PPointer::IsMatch(const void *id1, const void *id2) const
|
bool PPointer::IsMatch(intptr_t id1, intptr_t id2) const
|
||||||
{
|
{
|
||||||
assert(id2 == NULL);
|
assert(id2 == NULL);
|
||||||
PType *pointat = (PType *)id1;
|
PType *pointat = (PType *)id1;
|
||||||
|
@ -474,10 +498,10 @@ bool PPointer::IsMatch(const void *id1, const void *id2) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PPointer::GetTypeIDs(const void *&id1, const void *&id2) const
|
void PPointer::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
{
|
{
|
||||||
id1 = PointedType;
|
id1 = (intptr_t)PointedType;
|
||||||
id2 = NULL;
|
id2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -487,13 +511,35 @@ IMPLEMENT_POINTY_CLASS(PClassPointer)
|
||||||
DECLARE_POINTER(ClassRestriction)
|
DECLARE_POINTER(ClassRestriction)
|
||||||
END_POINTERS
|
END_POINTERS
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PClassPointer - Default Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PClassPointer::PClassPointer()
|
||||||
|
: PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PClassPointer - Parameterized Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PClassPointer::PClassPointer(PClass *restrict)
|
||||||
|
: PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(restrict)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PClassPointer :: IsMatch
|
// PClassPointer :: IsMatch
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool PClassPointer::IsMatch(const void *id1, const void *id2) const
|
bool PClassPointer::IsMatch(intptr_t id1, intptr_t id2) const
|
||||||
{
|
{
|
||||||
const PType *pointat = (const PType *)id1;
|
const PType *pointat = (const PType *)id1;
|
||||||
const PClass *classat = (const PClass *)id2;
|
const PClass *classat = (const PClass *)id2;
|
||||||
|
@ -508,11 +554,11 @@ bool PClassPointer::IsMatch(const void *id1, const void *id2) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PClassPointer::GetTypeIDs(const void *&id1, const void *&id2) const
|
void PClassPointer::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
{
|
{
|
||||||
assert(PointedType == RUNTIME_CLASS(PClass));
|
assert(PointedType == RUNTIME_CLASS(PClass));
|
||||||
id1 = PointedType;
|
id1 = (intptr_t)PointedType;
|
||||||
id2 = ClassRestriction;
|
id2 = (intptr_t)ClassRestriction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -528,13 +574,37 @@ IMPLEMENT_POINTY_CLASS(PArray)
|
||||||
DECLARE_POINTER(ElementType)
|
DECLARE_POINTER(ElementType)
|
||||||
END_POINTERS
|
END_POINTERS
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PArray - Default Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PArray::PArray()
|
||||||
|
: ElementType(NULL), ElementCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PArray - Parameterized Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PArray::PArray(PType *etype, unsigned int ecount)
|
||||||
|
: ElementType(etype), ElementCount(ecount)
|
||||||
|
{
|
||||||
|
Align = etype->Align;
|
||||||
|
Size = etype->Size * ecount;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PArray :: IsMatch
|
// PArray :: IsMatch
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool PArray::IsMatch(const void *id1, const void *id2) const
|
bool PArray::IsMatch(intptr_t id1, intptr_t id2) const
|
||||||
{
|
{
|
||||||
const PType *elemtype = (const PType *)id1;
|
const PType *elemtype = (const PType *)id1;
|
||||||
unsigned int count = (unsigned int)(intptr_t)id2;
|
unsigned int count = (unsigned int)(intptr_t)id2;
|
||||||
|
@ -548,29 +618,120 @@ bool PArray::IsMatch(const void *id1, const void *id2) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PArray::GetTypeIDs(const void *&id1, const void *&id2) const
|
void PArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
{
|
{
|
||||||
id1 = ElementType;
|
id1 = (intptr_t)ElementType;
|
||||||
id2 = (void *)(intptr_t)ElementCount;
|
id2 = ElementCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// NewArray
|
||||||
|
//
|
||||||
|
// Returns a PArray for the given type and size, making sure not to create
|
||||||
|
// duplicates.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PArray *NewArray(PType *type, unsigned int count)
|
||||||
|
{
|
||||||
|
size_t bucket;
|
||||||
|
PType *atype = TypeTable.FindType(RUNTIME_CLASS(PArray), (intptr_t)type, count, &bucket);
|
||||||
|
if (atype == NULL)
|
||||||
|
{
|
||||||
|
atype = new PArray(type, count);
|
||||||
|
TypeTable.AddType(type, RUNTIME_CLASS(PArray), (intptr_t)type, count, bucket);
|
||||||
|
}
|
||||||
|
return (PArray *)type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PVector ****************************************************************/
|
/* PVector ****************************************************************/
|
||||||
|
|
||||||
IMPLEMENT_CLASS(PVector)
|
IMPLEMENT_CLASS(PVector)
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PVector - Default Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PVector::PVector()
|
||||||
|
: PArray(TypeFloat32, 3)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PVector - Parameterized Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PVector::PVector(unsigned int size)
|
||||||
|
: PArray(TypeFloat32, size)
|
||||||
|
{
|
||||||
|
assert(size >= 2 && size <= 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// NewVector
|
||||||
|
//
|
||||||
|
// Returns a PVector with the given dimension, making sure not to create
|
||||||
|
// duplicates.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PVector *NewVector(unsigned int size)
|
||||||
|
{
|
||||||
|
size_t bucket;
|
||||||
|
PType *type = TypeTable.FindType(RUNTIME_CLASS(PVector), (intptr_t)TypeFloat32, size, &bucket);
|
||||||
|
if (type == NULL)
|
||||||
|
{
|
||||||
|
type = new PVector(size);
|
||||||
|
TypeTable.AddType(type, RUNTIME_CLASS(PVector), (intptr_t)TypeFloat32, size, bucket);
|
||||||
|
}
|
||||||
|
return (PVector *)type;
|
||||||
|
}
|
||||||
|
|
||||||
/* PDynArray **************************************************************/
|
/* PDynArray **************************************************************/
|
||||||
|
|
||||||
IMPLEMENT_POINTY_CLASS(PDynArray)
|
IMPLEMENT_POINTY_CLASS(PDynArray)
|
||||||
DECLARE_POINTER(ElementType)
|
DECLARE_POINTER(ElementType)
|
||||||
END_POINTERS
|
END_POINTERS
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PDynArray - Default Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PDynArray::PDynArray()
|
||||||
|
: ElementType(NULL)
|
||||||
|
{
|
||||||
|
Size = sizeof(FArray);
|
||||||
|
Align = __alignof(FArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PDynArray - Parameterized Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PDynArray::PDynArray(PType *etype)
|
||||||
|
: ElementType(etype)
|
||||||
|
{
|
||||||
|
Size = sizeof(FArray);
|
||||||
|
Align = __alignof(FArray);
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PDynArray :: IsMatch
|
// PDynArray :: IsMatch
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool PDynArray::IsMatch(const void *id1, const void *id2) const
|
bool PDynArray::IsMatch(intptr_t id1, intptr_t id2) const
|
||||||
{
|
{
|
||||||
assert(id2 == NULL);
|
assert(id2 == NULL);
|
||||||
const PType *elemtype = (const PType *)id1;
|
const PType *elemtype = (const PType *)id1;
|
||||||
|
@ -584,12 +745,32 @@ bool PDynArray::IsMatch(const void *id1, const void *id2) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PDynArray::GetTypeIDs(const void *&id1, const void *&id2) const
|
void PDynArray::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
{
|
{
|
||||||
id1 = ElementType;
|
id1 = (intptr_t)ElementType;
|
||||||
id2 = NULL;
|
id2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// NewDynArray
|
||||||
|
//
|
||||||
|
// Creates a new DynArray of the given type, making sure not to create a
|
||||||
|
// duplicate.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PDynArray *NewDynArray(PType *type)
|
||||||
|
{
|
||||||
|
size_t bucket;
|
||||||
|
PType *atype = TypeTable.FindType(RUNTIME_CLASS(PDynArray), (intptr_t)type, 0, &bucket);
|
||||||
|
if (atype == NULL)
|
||||||
|
{
|
||||||
|
atype = new PDynArray(type);
|
||||||
|
TypeTable.AddType(atype, RUNTIME_CLASS(PDynArray), (intptr_t)type, 0, bucket);
|
||||||
|
}
|
||||||
|
return (PDynArray *)atype;
|
||||||
|
}
|
||||||
|
|
||||||
/* PMap *******************************************************************/
|
/* PMap *******************************************************************/
|
||||||
|
|
||||||
|
@ -598,13 +779,39 @@ IMPLEMENT_POINTY_CLASS(PMap)
|
||||||
DECLARE_POINTER(ValueType)
|
DECLARE_POINTER(ValueType)
|
||||||
END_POINTERS
|
END_POINTERS
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap - Default Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PMap::PMap()
|
||||||
|
: KeyType(NULL), ValueType(NULL)
|
||||||
|
{
|
||||||
|
Size = sizeof(FMap);
|
||||||
|
Align = __alignof(FMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PMap - Parameterized Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PMap::PMap(PType *keytype, PType *valtype)
|
||||||
|
: KeyType(keytype), ValueType(valtype)
|
||||||
|
{
|
||||||
|
Size = sizeof(FMap);
|
||||||
|
Align = __alignof(FMap);
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PMap :: IsMatch
|
// PMap :: IsMatch
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool PMap::IsMatch(const void *id1, const void *id2) const
|
bool PMap::IsMatch(intptr_t id1, intptr_t id2) const
|
||||||
{
|
{
|
||||||
const PType *keyty = (const PType *)id1;
|
const PType *keyty = (const PType *)id1;
|
||||||
const PType *valty = (const PType *)id2;
|
const PType *valty = (const PType *)id2;
|
||||||
|
@ -618,10 +825,31 @@ bool PMap::IsMatch(const void *id1, const void *id2) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PMap::GetTypeIDs(const void *&id1, const void *&id2) const
|
void PMap::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
{
|
{
|
||||||
id1 = KeyType;
|
id1 = (intptr_t)KeyType;
|
||||||
id2 = ValueType;
|
id2 = (intptr_t)ValueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// NewMap
|
||||||
|
//
|
||||||
|
// Returns a PMap for the given key and value types, ensuring not to create
|
||||||
|
// duplicates.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
PMap *NewMap(PType *keytype, PType *valuetype)
|
||||||
|
{
|
||||||
|
size_t bucket;
|
||||||
|
PType *maptype = TypeTable.FindType(RUNTIME_CLASS(PMap), (intptr_t)keytype, (intptr_t)valuetype, &bucket);
|
||||||
|
if (maptype == NULL)
|
||||||
|
{
|
||||||
|
maptype = new PMap(keytype, valuetype);
|
||||||
|
TypeTable.AddType(maptype, RUNTIME_CLASS(PMap), (intptr_t)keytype, (intptr_t)valuetype, bucket);
|
||||||
|
}
|
||||||
|
return (PMap *)maptype;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PStruct ****************************************************************/
|
/* PStruct ****************************************************************/
|
||||||
|
@ -650,7 +878,7 @@ IMPLEMENT_CLASS(PPrototype)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool PPrototype::IsMatch(const void *id1, const void *id2) const
|
bool PPrototype::IsMatch(intptr_t id1, intptr_t id2) const
|
||||||
{
|
{
|
||||||
const TArray<PType *> *args = (const TArray<PType *> *)id1;
|
const TArray<PType *> *args = (const TArray<PType *> *)id1;
|
||||||
const TArray<PType *> *rets = (const TArray<PType *> *)id2;
|
const TArray<PType *> *rets = (const TArray<PType *> *)id2;
|
||||||
|
@ -664,10 +892,10 @@ bool PPrototype::IsMatch(const void *id1, const void *id2) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PPrototype::GetTypeIDs(const void *&id1, const void *&id2) const
|
void PPrototype::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
{
|
{
|
||||||
id1 = &ArgumentTypes;
|
id1 = (intptr_t)&ArgumentTypes;
|
||||||
id2 = &ReturnTypes;
|
id2 = (intptr_t)&ReturnTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -947,7 +1175,7 @@ void PClass::InsertIntoHash ()
|
||||||
size_t bucket;
|
size_t bucket;
|
||||||
PType *found;
|
PType *found;
|
||||||
|
|
||||||
found = TypeTable.FindType(RUNTIME_CLASS(PClass), Outer, (void*)(intptr_t)(int)TypeName, &bucket);
|
found = TypeTable.FindType(RUNTIME_CLASS(PClass), (intptr_t)Outer, TypeName, &bucket);
|
||||||
if (found != NULL)
|
if (found != NULL)
|
||||||
{ // This type has already been inserted
|
{ // This type has already been inserted
|
||||||
// ... but there is no need whatsoever to make it a fatal error!
|
// ... but there is no need whatsoever to make it a fatal error!
|
||||||
|
@ -955,7 +1183,7 @@ void PClass::InsertIntoHash ()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TypeTable.AddType(this, RUNTIME_CLASS(PClass), Outer, (void*)(intptr_t)(int)TypeName, bucket);
|
TypeTable.AddType(this, RUNTIME_CLASS(PClass), (intptr_t)Outer, TypeName, bucket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,7 +1202,7 @@ PClass *PClass::FindClass (FName zaname)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass),
|
return static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass),
|
||||||
/*FIXME:Outer*/NULL, (void*)(intptr_t)(int)zaname, NULL));
|
/*FIXME:Outer*/0, zaname, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1109,7 +1337,7 @@ PClass *PClass::FindClassTentative(FName name)
|
||||||
size_t bucket;
|
size_t bucket;
|
||||||
|
|
||||||
PType *found = TypeTable.FindType(RUNTIME_CLASS(PClass),
|
PType *found = TypeTable.FindType(RUNTIME_CLASS(PClass),
|
||||||
/*FIXME:Outer*/NULL, (void*)(intptr_t)(int)name, &bucket);
|
/*FIXME:Outer*/0, name, &bucket);
|
||||||
|
|
||||||
if (found != NULL)
|
if (found != NULL)
|
||||||
{
|
{
|
||||||
|
@ -1122,7 +1350,7 @@ PClass *PClass::FindClassTentative(FName name)
|
||||||
type->ParentClass = this;
|
type->ParentClass = this;
|
||||||
type->Size = -1;
|
type->Size = -1;
|
||||||
type->bRuntimeClass = true;
|
type->bRuntimeClass = true;
|
||||||
TypeTable.AddType(type, RUNTIME_CLASS(PClass), type->Outer, (void*)(intptr_t)(int)name, bucket);
|
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,7 +1454,7 @@ size_t PClass::PropagateMark()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
PType *FTypeTable::FindType(PClass *metatype, const void *parm1, const void *parm2, size_t *bucketnum)
|
PType *FTypeTable::FindType(PClass *metatype, intptr_t parm1, intptr_t parm2, size_t *bucketnum)
|
||||||
{
|
{
|
||||||
size_t bucket = Hash(metatype, parm1, parm2) % HASH_SIZE;
|
size_t bucket = Hash(metatype, parm1, parm2) % HASH_SIZE;
|
||||||
if (bucketnum != NULL)
|
if (bucketnum != NULL)
|
||||||
|
@ -1249,7 +1477,7 @@ PType *FTypeTable::FindType(PClass *metatype, const void *parm1, const void *par
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FTypeTable::AddType(PType *type, PClass *metatype, const void *parm1, const void *parm2, size_t bucket)
|
void FTypeTable::AddType(PType *type, PClass *metatype, intptr_t parm1, intptr_t parm2, size_t bucket)
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
size_t bucketcheck;
|
size_t bucketcheck;
|
||||||
|
@ -1271,7 +1499,7 @@ void FTypeTable::AddType(PType *type, PClass *metatype, const void *parm1, const
|
||||||
void FTypeTable::AddType(PType *type)
|
void FTypeTable::AddType(PType *type)
|
||||||
{
|
{
|
||||||
PClass *metatype;
|
PClass *metatype;
|
||||||
const void *parm1, *parm2;
|
intptr_t parm1, parm2;
|
||||||
size_t bucket;
|
size_t bucket;
|
||||||
|
|
||||||
metatype = type->GetClass()->TypeTableType;
|
metatype = type->GetClass()->TypeTableType;
|
||||||
|
@ -1290,7 +1518,7 @@ void FTypeTable::AddType(PType *type)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
size_t FTypeTable::Hash(const void *p1, const void *p2, const void *p3)
|
size_t FTypeTable::Hash(const void *p1, intptr_t p2, intptr_t p3)
|
||||||
{
|
{
|
||||||
size_t i1 = (size_t)p1;
|
size_t i1 = (size_t)p1;
|
||||||
size_t i2 = (size_t)p2;
|
size_t i2 = (size_t)p2;
|
||||||
|
|
|
@ -193,10 +193,10 @@ public:
|
||||||
// It is up to the caller to make sure they are the correct types. There is
|
// It is up to the caller to make sure they are the correct types. There is
|
||||||
// only one prototype for this function in order to simplify type table
|
// only one prototype for this function in order to simplify type table
|
||||||
// management.
|
// management.
|
||||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
|
|
||||||
// Get the type IDs used by IsMatch
|
// Get the type IDs used by IsMatch
|
||||||
virtual void GetTypeIDs(const void *&id1, const void *&id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
|
||||||
static void StaticInit();
|
static void StaticInit();
|
||||||
};
|
};
|
||||||
|
@ -226,8 +226,8 @@ public:
|
||||||
|
|
||||||
PNamedType() : Outer(NULL) {}
|
PNamedType() : Outer(NULL) {}
|
||||||
|
|
||||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(const void *&id1, const void *&id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Basic types --------------------------------------------------------------
|
// Basic types --------------------------------------------------------------
|
||||||
|
@ -289,10 +289,14 @@ class PPointer : public PInt
|
||||||
DECLARE_CLASS(PPointer, PInt);
|
DECLARE_CLASS(PPointer, PInt);
|
||||||
HAS_OBJECT_POINTERS;
|
HAS_OBJECT_POINTERS;
|
||||||
public:
|
public:
|
||||||
|
PPointer(PType *pointsat);
|
||||||
|
|
||||||
PType *PointedType;
|
PType *PointedType;
|
||||||
|
|
||||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(const void *&id1, const void *&id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
protected:
|
||||||
|
PPointer();
|
||||||
};
|
};
|
||||||
|
|
||||||
class PClass;
|
class PClass;
|
||||||
|
@ -301,12 +305,16 @@ class PClassPointer : public PPointer
|
||||||
DECLARE_CLASS(PClassPointer, PPointer);
|
DECLARE_CLASS(PClassPointer, PPointer);
|
||||||
HAS_OBJECT_POINTERS;
|
HAS_OBJECT_POINTERS;
|
||||||
public:
|
public:
|
||||||
|
PClassPointer(PClass *restrict);
|
||||||
|
|
||||||
PClass *ClassRestriction;
|
PClass *ClassRestriction;
|
||||||
|
|
||||||
typedef PClass *Type2;
|
typedef PClass *Type2;
|
||||||
|
|
||||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(const void *&id1, const void *&id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
protected:
|
||||||
|
PClassPointer();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Struct/class fields ------------------------------------------------------
|
// Struct/class fields ------------------------------------------------------
|
||||||
|
@ -343,11 +351,15 @@ class PArray : public PCompoundType
|
||||||
DECLARE_CLASS(PArray, PCompoundType);
|
DECLARE_CLASS(PArray, PCompoundType);
|
||||||
HAS_OBJECT_POINTERS;
|
HAS_OBJECT_POINTERS;
|
||||||
public:
|
public:
|
||||||
|
PArray(PType *etype, unsigned int ecount);
|
||||||
|
|
||||||
PType *ElementType;
|
PType *ElementType;
|
||||||
unsigned int ElementCount;
|
unsigned int ElementCount;
|
||||||
|
|
||||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(const void *&id1, const void *&id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
protected:
|
||||||
|
PArray();
|
||||||
};
|
};
|
||||||
|
|
||||||
// A vector is an array with extra operations.
|
// A vector is an array with extra operations.
|
||||||
|
@ -355,6 +367,10 @@ class PVector : public PArray
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(PVector, PArray);
|
DECLARE_CLASS(PVector, PArray);
|
||||||
HAS_OBJECT_POINTERS;
|
HAS_OBJECT_POINTERS;
|
||||||
|
public:
|
||||||
|
PVector(unsigned int size);
|
||||||
|
protected:
|
||||||
|
PVector();
|
||||||
};
|
};
|
||||||
|
|
||||||
class PDynArray : public PCompoundType
|
class PDynArray : public PCompoundType
|
||||||
|
@ -362,10 +378,14 @@ class PDynArray : public PCompoundType
|
||||||
DECLARE_CLASS(PDynArray, PCompoundType);
|
DECLARE_CLASS(PDynArray, PCompoundType);
|
||||||
HAS_OBJECT_POINTERS;
|
HAS_OBJECT_POINTERS;
|
||||||
public:
|
public:
|
||||||
|
PDynArray(PType *etype);
|
||||||
|
|
||||||
PType *ElementType;
|
PType *ElementType;
|
||||||
|
|
||||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(const void *&id1, const void *&id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
protected:
|
||||||
|
PDynArray();
|
||||||
};
|
};
|
||||||
|
|
||||||
class PMap : public PCompoundType
|
class PMap : public PCompoundType
|
||||||
|
@ -373,11 +393,15 @@ class PMap : public PCompoundType
|
||||||
DECLARE_CLASS(PMap, PCompoundType);
|
DECLARE_CLASS(PMap, PCompoundType);
|
||||||
HAS_OBJECT_POINTERS;
|
HAS_OBJECT_POINTERS;
|
||||||
public:
|
public:
|
||||||
|
PMap(PType *keytype, PType *valtype);
|
||||||
|
|
||||||
PType *KeyType;
|
PType *KeyType;
|
||||||
PType *ValueType;
|
PType *ValueType;
|
||||||
|
|
||||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(const void *&id1, const void *&id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
protected:
|
||||||
|
PMap();
|
||||||
};
|
};
|
||||||
|
|
||||||
class PStruct : public PNamedType
|
class PStruct : public PNamedType
|
||||||
|
@ -397,8 +421,8 @@ public:
|
||||||
TArray<PType *> ReturnTypes;
|
TArray<PType *> ReturnTypes;
|
||||||
|
|
||||||
size_t PropagateMark();
|
size_t PropagateMark();
|
||||||
virtual bool IsMatch(const void *id1, const void *id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(const void *&id1, const void *&id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TBD: Should we really support overloading?
|
// TBD: Should we really support overloading?
|
||||||
|
@ -517,6 +541,17 @@ inline PClass::MetaClass *PClass::GetClass() const
|
||||||
return static_cast<MetaClass *>(DObject::GetClass());
|
return static_cast<MetaClass *>(DObject::GetClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A class that hasn't had its parent class defined yet ---------------------
|
||||||
|
|
||||||
|
class PClassWaitingForParent : public PClass
|
||||||
|
{
|
||||||
|
DECLARE_CLASS(PClassWaitingForParent, PClass);
|
||||||
|
public:
|
||||||
|
PClassWaitingForParent(FName myname, FName parentname);
|
||||||
|
|
||||||
|
FName ParentName;
|
||||||
|
};
|
||||||
|
|
||||||
// Type tables --------------------------------------------------------------
|
// Type tables --------------------------------------------------------------
|
||||||
|
|
||||||
struct FTypeTable
|
struct FTypeTable
|
||||||
|
@ -525,16 +560,36 @@ struct FTypeTable
|
||||||
|
|
||||||
PType *TypeHash[HASH_SIZE];
|
PType *TypeHash[HASH_SIZE];
|
||||||
|
|
||||||
PType *FindType(PClass *metatype, const void *parm1, const void *parm2, size_t *bucketnum);
|
PType *FindType(PClass *metatype, intptr_t parm1, intptr_t parm2, size_t *bucketnum);
|
||||||
void AddType(PType *type, PClass *metatype, const void *parm1, const void *parm2, size_t bucket);
|
void AddType(PType *type, PClass *metatype, intptr_t parm1, intptr_t parm2, size_t bucket);
|
||||||
void AddType(PType *type);
|
void AddType(PType *type);
|
||||||
void Mark();
|
void Mark();
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
static size_t Hash(const void *p1, const void *p2, const void *p3);
|
static size_t Hash(const void *p1, intptr_t p2, intptr_t p3);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern FTypeTable TypeTable;
|
extern FTypeTable TypeTable;
|
||||||
|
|
||||||
|
// Returns a type from the TypeTable. Will create one if it isn't present.
|
||||||
|
PVector *NewVector(unsigned int size);
|
||||||
|
PMap *NewMap(PType *keytype, PType *valuetype);
|
||||||
|
PArray *NewArray(PType *type, unsigned int count);
|
||||||
|
PDynArray *NewDynArray(PType *type);
|
||||||
|
PPointer *NewPointer(PType *type);
|
||||||
|
PClassPointer *NewClassPointer(PClass *restrict);
|
||||||
|
PClassWaitingForParent *NewUnknownClass(FName myname, FName parentname);
|
||||||
|
|
||||||
|
// Built-in types -----------------------------------------------------------
|
||||||
|
|
||||||
|
extern PInt *TypeSInt8, *TypeUInt8;
|
||||||
|
extern PInt *TypeSInt16, *TypeUInt16;
|
||||||
|
extern PInt *TypeSInt32, *TypeUInt32;
|
||||||
|
extern PFloat *TypeFloat32, *TypeFloat64;
|
||||||
|
extern PString *TypeString;
|
||||||
|
extern PName *TypeName;
|
||||||
|
extern PSound *TypeSound;
|
||||||
|
extern PColor *TypeColor;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
360
src/memarena.cpp
Normal file
360
src/memarena.cpp
Normal file
|
@ -0,0 +1,360 @@
|
||||||
|
/*
|
||||||
|
** memarena.cpp
|
||||||
|
** Implements memory arenas.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2010 Randy Heit
|
||||||
|
** 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.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
** A memory arena is used for efficient allocation of many small objects that
|
||||||
|
** will all be freed at once. Note that since individual destructors are not
|
||||||
|
** called, you must not use an arena to allocate any objects that use a
|
||||||
|
** destructor, either explicitly or implicitly (because they have members
|
||||||
|
** with destructors).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "doomtype.h"
|
||||||
|
#include "m_alloc.h"
|
||||||
|
#include "memarena.h"
|
||||||
|
#include "zstring.h"
|
||||||
|
|
||||||
|
#define BLOCK_SIZE (10*1024)
|
||||||
|
|
||||||
|
struct FMemArena::Block
|
||||||
|
{
|
||||||
|
Block *NextBlock;
|
||||||
|
void *Limit; // End of this block
|
||||||
|
void *Avail; // Start of free space in this block
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
void *Alloc(size_t size);
|
||||||
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// RoundPointer
|
||||||
|
//
|
||||||
|
// Rounds a pointer up to a pointer-sized boundary.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static inline void *RoundPointer(void *ptr)
|
||||||
|
{
|
||||||
|
return (void *)(((size_t)ptr + sizeof(void*) - 1) & ~(sizeof(void*) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FMemArena::FMemArena()
|
||||||
|
{
|
||||||
|
TopBlock = NULL;
|
||||||
|
FreeBlocks = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena Destructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FMemArena::~FMemArena()
|
||||||
|
{
|
||||||
|
FreeAllBlocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: Alloc
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void *FMemArena::Alloc(size_t size)
|
||||||
|
{
|
||||||
|
Block *block;
|
||||||
|
|
||||||
|
for (block = TopBlock; block != NULL; block = block->NextBlock)
|
||||||
|
{
|
||||||
|
void *res = block->Alloc(size);
|
||||||
|
if (res != NULL)
|
||||||
|
{
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block = AddBlock(size);
|
||||||
|
return block->Alloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: FreeAll
|
||||||
|
//
|
||||||
|
// Moves all blocks to the free list. No system-level deallocation occurs.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FMemArena::FreeAll()
|
||||||
|
{
|
||||||
|
for (Block *next, *block = TopBlock; block != NULL; block = next)
|
||||||
|
{
|
||||||
|
next = block->NextBlock;
|
||||||
|
block->Reset();
|
||||||
|
block->NextBlock = FreeBlocks;
|
||||||
|
FreeBlocks = block;
|
||||||
|
}
|
||||||
|
TopBlock = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: FreeAllBlocks
|
||||||
|
//
|
||||||
|
// Frees all blocks used by this arena.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FMemArena::FreeAllBlocks()
|
||||||
|
{
|
||||||
|
FreeBlockChain(TopBlock);
|
||||||
|
FreeBlockChain(FreeBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: FreeBlockChain
|
||||||
|
//
|
||||||
|
// Frees a chain of blocks.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FMemArena::FreeBlockChain(Block *&top)
|
||||||
|
{
|
||||||
|
for (Block *next, *block = top; block != NULL; block = next)
|
||||||
|
{
|
||||||
|
next = block->NextBlock;
|
||||||
|
M_Free(block);
|
||||||
|
}
|
||||||
|
top = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: AddBlock
|
||||||
|
//
|
||||||
|
// Allocates a block large enough to hold at least <size> bytes and adds it
|
||||||
|
// to the TopBlock chain.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FMemArena::Block *FMemArena::AddBlock(size_t size)
|
||||||
|
{
|
||||||
|
size += sizeof(Block); // Account for header size
|
||||||
|
if (size < BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
size = BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Stick some free space at the end so we can use this block for
|
||||||
|
// other things.
|
||||||
|
size += BLOCK_SIZE/2;
|
||||||
|
}
|
||||||
|
Block *mem = (Block *)M_Malloc(size);
|
||||||
|
mem->Limit = mem + size;
|
||||||
|
mem->Reset();
|
||||||
|
mem->NextBlock = TopBlock;
|
||||||
|
TopBlock = mem;
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: Block :: Reset
|
||||||
|
//
|
||||||
|
// Resets this block's Avail pointer.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FMemArena::Block::Reset()
|
||||||
|
{
|
||||||
|
Avail = RoundPointer(this + sizeof(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FMemArena :: Block :: Alloc
|
||||||
|
//
|
||||||
|
// Allocates memory from the block if it has space. Returns NULL if not.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void *FMemArena::Block::Alloc(size_t size)
|
||||||
|
{
|
||||||
|
if ((char *)Avail + size > Limit)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void *res = Avail;
|
||||||
|
Avail = RoundPointer((char *)Avail + size);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena Constructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FSharedStringArena::FSharedStringArena()
|
||||||
|
{
|
||||||
|
memset(Buckets, 0, sizeof(Buckets));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena Destructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FSharedStringArena::~FSharedStringArena()
|
||||||
|
{
|
||||||
|
FreeAll();
|
||||||
|
// FMemArena destructor will free the blocks.
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena :: Alloc
|
||||||
|
//
|
||||||
|
// Allocates a new string and initializes it with the passed string. This
|
||||||
|
// version takes an FString as a parameter, so it won't need to allocate any
|
||||||
|
// memory for the string text if it already exists in the arena.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString *FSharedStringArena::Alloc(const FString &source)
|
||||||
|
{
|
||||||
|
unsigned int hash;
|
||||||
|
Node *strnode;
|
||||||
|
|
||||||
|
strnode = FindString(source, source.Len(), hash);
|
||||||
|
if (strnode == NULL)
|
||||||
|
{
|
||||||
|
strnode = (Node *)FMemArena::Alloc(sizeof(Node));
|
||||||
|
::new(&strnode->String) FString(source);
|
||||||
|
strnode->Hash = hash;
|
||||||
|
hash %= countof(Buckets);
|
||||||
|
strnode->Next = Buckets[hash];
|
||||||
|
Buckets[hash] = strnode;
|
||||||
|
}
|
||||||
|
return &strnode->String;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena :: Alloc
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString *FSharedStringArena::Alloc(const char *source)
|
||||||
|
{
|
||||||
|
return Alloc(source, strlen(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena :: Alloc
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString *FSharedStringArena::Alloc(const char *source, size_t strlen)
|
||||||
|
{
|
||||||
|
unsigned int hash;
|
||||||
|
Node *strnode;
|
||||||
|
|
||||||
|
strnode = FindString(source, strlen, hash);
|
||||||
|
if (strnode == NULL)
|
||||||
|
{
|
||||||
|
strnode = (Node *)FMemArena::Alloc(sizeof(Node));
|
||||||
|
::new(&strnode->String) FString(source, strlen);
|
||||||
|
strnode->Hash = hash;
|
||||||
|
hash %= countof(Buckets);
|
||||||
|
strnode->Next = Buckets[hash];
|
||||||
|
Buckets[hash] = strnode;
|
||||||
|
}
|
||||||
|
return &strnode->String;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena :: FindString
|
||||||
|
//
|
||||||
|
// Finds the string if it's already in the arena. Returns NULL if not.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FSharedStringArena::Node *FSharedStringArena::FindString(const char *str, size_t strlen, unsigned int &hash)
|
||||||
|
{
|
||||||
|
hash = SuperFastHash(str, strlen);
|
||||||
|
|
||||||
|
for (Node *node = Buckets[hash % countof(Buckets)]; node != NULL; node = node->Next)
|
||||||
|
{
|
||||||
|
if (node->Hash == hash && node->String.Len() == strlen && memcmp(&node->String[0], str, strlen) == 0)
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FSharedStringArena :: FreeAll
|
||||||
|
//
|
||||||
|
// In addition to moving all used blocks onto the free list, all FStrings
|
||||||
|
// they contain will have their destructors called.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FSharedStringArena::FreeAll()
|
||||||
|
{
|
||||||
|
for (Block *next, *block = TopBlock; block != NULL; block = next)
|
||||||
|
{
|
||||||
|
next = block->NextBlock;
|
||||||
|
void *limit = block->Avail;
|
||||||
|
block->Reset();
|
||||||
|
for (Node *string = (Node *)block->Avail; string < limit; ++string)
|
||||||
|
{
|
||||||
|
string->~Node();
|
||||||
|
}
|
||||||
|
block->NextBlock = FreeBlocks;
|
||||||
|
FreeBlocks = block;
|
||||||
|
}
|
||||||
|
memset(Buckets, 0, sizeof(Buckets));
|
||||||
|
}
|
83
src/memarena.h
Normal file
83
src/memarena.h
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
** memarena.h
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2010 Randy Heit
|
||||||
|
** 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.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "zstring.h"
|
||||||
|
|
||||||
|
// A general purpose arena.
|
||||||
|
class FMemArena
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FMemArena();
|
||||||
|
~FMemArena();
|
||||||
|
|
||||||
|
void *Alloc(size_t size);
|
||||||
|
void FreeAll();
|
||||||
|
void FreeAllBlocks();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct Block;
|
||||||
|
|
||||||
|
Block *AddBlock(size_t size);
|
||||||
|
void FreeBlockChain(Block *&top);
|
||||||
|
|
||||||
|
Block *TopBlock;
|
||||||
|
Block *FreeBlocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
// An arena specializing in storage of FStrings. It knows how to free them,
|
||||||
|
// but this means it also should never be used for allocating anything else.
|
||||||
|
// Identical strings all return the same pointer.
|
||||||
|
class FSharedStringArena : public FMemArena
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FSharedStringArena();
|
||||||
|
~FSharedStringArena();
|
||||||
|
void FreeAll();
|
||||||
|
|
||||||
|
class FString *Alloc(const FString &source);
|
||||||
|
class FString *Alloc(const char *source);
|
||||||
|
class FString *Alloc(const char *source, size_t strlen);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct Node
|
||||||
|
{
|
||||||
|
Node *Next;
|
||||||
|
FString String;
|
||||||
|
unsigned int Hash;
|
||||||
|
};
|
||||||
|
Node *Buckets[256];
|
||||||
|
|
||||||
|
Node *FindString(const char *str, size_t strlen, unsigned int &hash);
|
||||||
|
private:
|
||||||
|
void *Alloc(size_t size) { return NULL; } // No access to FMemArena::Alloc for outsiders.
|
||||||
|
};
|
17
src/tarray.h
17
src/tarray.h
|
@ -51,6 +51,14 @@ class FArchive;
|
||||||
|
|
||||||
// TArray -------------------------------------------------------------------
|
// TArray -------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Must match TArray's layout.
|
||||||
|
struct FArray
|
||||||
|
{
|
||||||
|
void *Array;
|
||||||
|
unsigned int Most;
|
||||||
|
unsigned int Count;
|
||||||
|
};
|
||||||
|
|
||||||
// T is the type stored in the array.
|
// T is the type stored in the array.
|
||||||
// TT is the type returned by operator().
|
// TT is the type returned by operator().
|
||||||
template <class T, class TT=T>
|
template <class T, class TT=T>
|
||||||
|
@ -444,6 +452,15 @@ template<class VT> struct TValueTraits
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Must match layout of TMap
|
||||||
|
struct FMap
|
||||||
|
{
|
||||||
|
void *Nodes;
|
||||||
|
void *LastFree;
|
||||||
|
hash_t Size;
|
||||||
|
hash_t NumUsed;
|
||||||
|
};
|
||||||
|
|
||||||
template<class KT, class VT, class MapType> class TMapIterator;
|
template<class KT, class VT, class MapType> class TMapIterator;
|
||||||
template<class KT, class VT, class MapType> class TMapConstIterator;
|
template<class KT, class VT, class MapType> class TMapConstIterator;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,83 +5,8 @@
|
||||||
#include "w_wad.h"
|
#include "w_wad.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "m_alloc.h"
|
#include "m_alloc.h"
|
||||||
|
#include "memarena.h"
|
||||||
class ZCCParser
|
#include "zcc_parser.h"
|
||||||
{
|
|
||||||
public:
|
|
||||||
void PrintError(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list argptr;
|
|
||||||
va_start(argptr, fmt);
|
|
||||||
VPrintf(PRINT_HIGH, fmt, argptr);
|
|
||||||
va_end(argptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
union ZCCToken
|
|
||||||
{
|
|
||||||
int Int;
|
|
||||||
double Float;
|
|
||||||
const char *String;
|
|
||||||
};
|
|
||||||
|
|
||||||
class StringTable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StringTable()
|
|
||||||
{
|
|
||||||
memset(Buckets, 0, sizeof(Buckets));
|
|
||||||
}
|
|
||||||
~StringTable()
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < countof(Buckets); ++i)
|
|
||||||
{
|
|
||||||
Node *node, *next;
|
|
||||||
for (node = Buckets[i]; node != NULL; node = next)
|
|
||||||
{
|
|
||||||
if (node->String != NULL)
|
|
||||||
{
|
|
||||||
delete[] node->String;
|
|
||||||
}
|
|
||||||
next = node->Next;
|
|
||||||
delete node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const char *Get(const char *str, int len)
|
|
||||||
{
|
|
||||||
unsigned int hash = SuperFastHash(str, len);
|
|
||||||
Node *node, **nodep;
|
|
||||||
|
|
||||||
nodep = &Buckets[hash % countof(Buckets)];
|
|
||||||
node = *nodep;
|
|
||||||
// Search for string in the hash table.
|
|
||||||
while (node != NULL)
|
|
||||||
{
|
|
||||||
if (node->Hash == hash && strcmp(str, node->String))
|
|
||||||
{
|
|
||||||
return node->String;
|
|
||||||
}
|
|
||||||
nodep = &node->Next;
|
|
||||||
node = *nodep;
|
|
||||||
}
|
|
||||||
// String is not in the hash table; add it.
|
|
||||||
node = new Node;
|
|
||||||
*nodep = node;
|
|
||||||
node->Hash = hash;
|
|
||||||
node->String = copystring(str);
|
|
||||||
node->Next = NULL;
|
|
||||||
return node->String;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
struct Node
|
|
||||||
{
|
|
||||||
Node *Next;
|
|
||||||
const char *String;
|
|
||||||
unsigned int Hash;
|
|
||||||
};
|
|
||||||
Node *Buckets[256];
|
|
||||||
};
|
|
||||||
|
|
||||||
static FString ZCCTokenName(int terminal);
|
static FString ZCCTokenName(int terminal);
|
||||||
|
|
||||||
|
@ -217,7 +142,6 @@ static void DoParse(const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
FScanner sc;
|
FScanner sc;
|
||||||
StringTable strings;
|
|
||||||
void *parser;
|
void *parser;
|
||||||
int tokentype;
|
int tokentype;
|
||||||
int lump;
|
int lump;
|
||||||
|
@ -245,11 +169,13 @@ static void DoParse(const char *filename)
|
||||||
FILE *f = fopen("trace.txt", "w");
|
FILE *f = fopen("trace.txt", "w");
|
||||||
ZCCParseTrace(f, "");
|
ZCCParseTrace(f, "");
|
||||||
#endif
|
#endif
|
||||||
|
ZCCParseState state(sc);
|
||||||
|
|
||||||
while (sc.GetToken())
|
while (sc.GetToken())
|
||||||
{
|
{
|
||||||
if (sc.TokenType == TK_StringConst)
|
if (sc.TokenType == TK_StringConst)
|
||||||
{
|
{
|
||||||
value.String = strings.Get(sc.String, sc.StringLen);
|
value.String = state.Strings.Alloc(sc.String, sc.StringLen);
|
||||||
tokentype = ZCC_STRCONST;
|
tokentype = ZCC_STRCONST;
|
||||||
}
|
}
|
||||||
else if (sc.TokenType == TK_IntConst)
|
else if (sc.TokenType == TK_IntConst)
|
||||||
|
@ -285,7 +211,7 @@ static void DoParse(const char *filename)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ZCCParse(parser, tokentype, value, &sc);
|
ZCCParse(parser, tokentype, value, &state);
|
||||||
if (failed)
|
if (failed)
|
||||||
{
|
{
|
||||||
sc.ScriptMessage("Parse failed\n");
|
sc.ScriptMessage("Parse failed\n");
|
||||||
|
@ -293,8 +219,8 @@ static void DoParse(const char *filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value.Int = -1;
|
value.Int = -1;
|
||||||
ZCCParse(parser, ZCC_EOF, value, &sc);
|
ZCCParse(parser, ZCC_EOF, value, &state);
|
||||||
ZCCParse(parser, 0, value, &sc);
|
ZCCParse(parser, 0, value, &state);
|
||||||
ZCCParseFree(parser, free);
|
ZCCParseFree(parser, free);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
if (f != NULL)
|
if (f != NULL)
|
||||||
|
|
373
src/zscript/zcc_parser.h
Normal file
373
src/zscript/zcc_parser.h
Normal file
|
@ -0,0 +1,373 @@
|
||||||
|
struct ZCCParseState
|
||||||
|
{
|
||||||
|
ZCCParseState(FScanner &scanner) : sc(scanner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FScanner ≻
|
||||||
|
FSharedStringArena Strings;
|
||||||
|
FMemArena SyntaxArena;
|
||||||
|
};
|
||||||
|
|
||||||
|
union ZCCToken
|
||||||
|
{
|
||||||
|
int Int;
|
||||||
|
double Float;
|
||||||
|
FString *String;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Syntax tree structures.
|
||||||
|
enum EZCCTreeNodeType
|
||||||
|
{
|
||||||
|
AST_Class,
|
||||||
|
AST_Struct,
|
||||||
|
AST_Enum,
|
||||||
|
AST_EnumNode,
|
||||||
|
AST_States,
|
||||||
|
AST_StateLabel,
|
||||||
|
AST_StateGoto,
|
||||||
|
AST_StateLine,
|
||||||
|
AST_VarName,
|
||||||
|
AST_Type,
|
||||||
|
AST_BasicType,
|
||||||
|
AST_MapType,
|
||||||
|
AST_DynArrayType,
|
||||||
|
AST_ClassType,
|
||||||
|
AST_Expression,
|
||||||
|
AST_ExprID,
|
||||||
|
AST_ExprString,
|
||||||
|
AST_ExprInt,
|
||||||
|
AST_ExprFloat,
|
||||||
|
AST_ExprFuncCall,
|
||||||
|
AST_ExprMemberAccess,
|
||||||
|
AST_ExprUnary,
|
||||||
|
AST_ExprBinary,
|
||||||
|
AST_ExprTrinary,
|
||||||
|
AST_FuncParm,
|
||||||
|
AST_Statement,
|
||||||
|
AST_CompoundStmt,
|
||||||
|
AST_ContinueStmt,
|
||||||
|
AST_BreakStmt,
|
||||||
|
AST_ReturnStmt,
|
||||||
|
AST_ExpressionStmt,
|
||||||
|
AST_IterationStmt,
|
||||||
|
AST_IfStmt,
|
||||||
|
AST_SwitchStmt,
|
||||||
|
AST_CaseStmt,
|
||||||
|
AST_AssignStmt,
|
||||||
|
AST_LocalVarStmt,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum EZCCExprType
|
||||||
|
{
|
||||||
|
PEX_ID,
|
||||||
|
PEX_Super,
|
||||||
|
PEX_Self,
|
||||||
|
PEX_StringConst,
|
||||||
|
PEX_IntConst,
|
||||||
|
PEX_UIntConst,
|
||||||
|
PEX_FloatConst,
|
||||||
|
PEX_FuncCall,
|
||||||
|
PEX_ArrayAccess,
|
||||||
|
PEX_MemberAccess,
|
||||||
|
PEX_PostInc,
|
||||||
|
PEX_PostDec,
|
||||||
|
|
||||||
|
PEX_PreInc,
|
||||||
|
PEX_PreDec,
|
||||||
|
PEX_Negate,
|
||||||
|
PEX_AntiNegate,
|
||||||
|
PEX_BitNot,
|
||||||
|
PEX_BoolNot,
|
||||||
|
PEX_SizeOf,
|
||||||
|
PEX_AlignOf,
|
||||||
|
|
||||||
|
PEX_Add,
|
||||||
|
PEX_Sub,
|
||||||
|
PEX_Mul,
|
||||||
|
PEX_Div,
|
||||||
|
PEX_Mod,
|
||||||
|
PEX_Pow,
|
||||||
|
PEX_CrossProduct,
|
||||||
|
PEX_DotProduct,
|
||||||
|
PEX_LeftShift,
|
||||||
|
PEX_RightShift,
|
||||||
|
PEX_Concat,
|
||||||
|
|
||||||
|
PEX_LT,
|
||||||
|
PEX_GT,
|
||||||
|
PEX_LTEQ,
|
||||||
|
PEX_GTEQ,
|
||||||
|
PEX_LTGTEQ,
|
||||||
|
PEX_Is,
|
||||||
|
|
||||||
|
PEX_EQEQ,
|
||||||
|
PEX_NEQ,
|
||||||
|
PEX_APREQ,
|
||||||
|
|
||||||
|
PEX_BitAnd,
|
||||||
|
PEX_BitOr,
|
||||||
|
PEX_BitXor,
|
||||||
|
PEX_BoolAnd,
|
||||||
|
PEX_BoolOr,
|
||||||
|
|
||||||
|
PEX_Scope,
|
||||||
|
|
||||||
|
PEX_Trinary
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_TreeNode
|
||||||
|
{
|
||||||
|
// This tree node's siblings are stored in a circular linked list.
|
||||||
|
// When you get back to this node, you know you've been through
|
||||||
|
// the whole list.
|
||||||
|
ZCC_TreeNode *SiblingNext;
|
||||||
|
ZCC_TreeNode *SiblingPrev;
|
||||||
|
|
||||||
|
// Node type is one of the node types above, which corresponds with
|
||||||
|
// one of the structures below.
|
||||||
|
EZCCTreeNodeType NodeType;
|
||||||
|
|
||||||
|
// Appends a sibling to this node's sibling list.
|
||||||
|
void AppendSibling(ZCC_TreeNode *sibling)
|
||||||
|
{
|
||||||
|
if (sibling == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The new sibling node should only be in a list with itself.
|
||||||
|
assert(sibling->SiblingNext == sibling && sibling->SiblingNext == sibling);
|
||||||
|
|
||||||
|
// Check integrity of our sibling list.
|
||||||
|
assert(SiblingPrev->SiblingNext == this);
|
||||||
|
assert(SiblingNext->SiblingPrev == this);
|
||||||
|
|
||||||
|
SiblingPrev->SiblingNext = sibling;
|
||||||
|
sibling->SiblingPrev = SiblingPrev;
|
||||||
|
SiblingPrev = sibling;
|
||||||
|
sibling->SiblingNext = this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_Class : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
FName ClassName;
|
||||||
|
FName ParentName;
|
||||||
|
VM_UWORD Flags;
|
||||||
|
ZCC_TreeNode *Body;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_Struct : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
FName StructName;
|
||||||
|
ZCC_TreeNode *Body;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_Enum : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
FName EnumName;
|
||||||
|
struct ZCC_EnumNode *Elements;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_EnumNode : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
FName ElemName;
|
||||||
|
ZCC_TreeNode *ElemValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_States : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
ZCC_TreeNode *Body;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_StateLabel : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
FName Label;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_StateGoto : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
ZCC_TreeNode *Label;
|
||||||
|
ZCC_TreeNode *Offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_StateLine : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
char Sprite[4];
|
||||||
|
FString *Frames;
|
||||||
|
BITFIELD bBright:1;
|
||||||
|
BITFIELD bHasOffset:1;
|
||||||
|
int OffsetX;
|
||||||
|
int OffsetY;
|
||||||
|
ZCC_TreeNode *Action;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_Expression : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
EZCCExprType Operation;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_VarName : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
bool bIsArray;
|
||||||
|
ZCC_Expression *ArraySize;
|
||||||
|
ENamedName Name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_Type : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
BITFIELD bIsArray:1;
|
||||||
|
ZCC_Expression *ArraySize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_BasicType : ZCC_Type
|
||||||
|
{
|
||||||
|
PType *Type;
|
||||||
|
FName TypeName;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_MapType : ZCC_Type
|
||||||
|
{
|
||||||
|
ZCC_Type *KeyType;
|
||||||
|
ZCC_Type *ValueType;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_DynArrayType : ZCC_Type
|
||||||
|
{
|
||||||
|
ZCC_Type *ElementType;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ClassType : ZCC_Type
|
||||||
|
{
|
||||||
|
FName Restriction;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ExprID : ZCC_Expression
|
||||||
|
{
|
||||||
|
FName Identifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ExprString : ZCC_Expression
|
||||||
|
{
|
||||||
|
FString *Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ExprInt : ZCC_Expression
|
||||||
|
{
|
||||||
|
int Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ExprFloat : ZCC_Expression
|
||||||
|
{
|
||||||
|
double Value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_FuncParm : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
ZCC_Expression *Value;
|
||||||
|
FName Label;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ExprFuncCall : ZCC_Expression
|
||||||
|
{
|
||||||
|
ZCC_Expression *Function;
|
||||||
|
ZCC_FuncParm *Parameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ExprMemberAccess : ZCC_Expression
|
||||||
|
{
|
||||||
|
ZCC_Expression *Left;
|
||||||
|
FName Right;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ExprUnary : ZCC_Expression
|
||||||
|
{
|
||||||
|
ZCC_Expression *Operand;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ExprBinary : ZCC_Expression
|
||||||
|
{
|
||||||
|
ZCC_Expression *Left;
|
||||||
|
ZCC_Expression *Right;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ExprTrinary : ZCC_Expression
|
||||||
|
{
|
||||||
|
ZCC_Expression *Test;
|
||||||
|
ZCC_Expression *Left;
|
||||||
|
ZCC_Expression *Right;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_Statement : ZCC_TreeNode
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_CompoundStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
ZCC_Statement *Content;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ContinueStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_BreakStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ReturnStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
ZCC_Expression *Values;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_ExpressionStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
ZCC_Expression *Expression;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_IterationStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
ZCC_Expression *LoopCondition;
|
||||||
|
ZCC_Statement *LoopStatement;
|
||||||
|
ZCC_Statement *LoopBumper;
|
||||||
|
|
||||||
|
// Should the loop condition be checked at the
|
||||||
|
// start of the loop (before the LoopStatement)
|
||||||
|
// or at the end (after the LoopStatement)?
|
||||||
|
enum { Start, End } CheckAt;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_IfStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
ZCC_Expression *Condition;
|
||||||
|
ZCC_Statement *TruePath;
|
||||||
|
ZCC_Statement *FalsePath;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_SwitchStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
ZCC_Expression *Condition;
|
||||||
|
ZCC_Statement *Content;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_CaseStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
// A NULL Condition represents the default branch
|
||||||
|
ZCC_Expression *Condition;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_AssignStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
ZCC_Expression *Dests;
|
||||||
|
ZCC_Expression *Sources;
|
||||||
|
int AssignOp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ZCC_LocalVarStmt : ZCC_Statement
|
||||||
|
{
|
||||||
|
ZCC_Type *Type;
|
||||||
|
ZCC_VarName *Vars;
|
||||||
|
ZCC_Expression *Inits;
|
||||||
|
};
|
12
zdoom.vcproj
12
zdoom.vcproj
|
@ -712,6 +712,10 @@
|
||||||
RelativePath=".\src\md5.cpp"
|
RelativePath=".\src\md5.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\memarena.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\mus2midi.cpp"
|
RelativePath=".\src\mus2midi.cpp"
|
||||||
>
|
>
|
||||||
|
@ -1401,6 +1405,10 @@
|
||||||
RelativePath=".\src\md5.h"
|
RelativePath=".\src\md5.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\memarena.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\mscinlines.h"
|
RelativePath=".\src\mscinlines.h"
|
||||||
>
|
>
|
||||||
|
@ -6553,6 +6561,10 @@
|
||||||
RelativePath=".\src\zscript\zcc_parser.cpp"
|
RelativePath=".\src\zscript\zcc_parser.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\zscript\zcc_parser.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Files>
|
</Files>
|
||||||
<Globals>
|
<Globals>
|
||||||
|
|
Loading…
Reference in a new issue