Merge remote-tracking branch 'remotes/origin/weapon_scriptification' into asmjit
# Conflicts: # src/g_inventory/a_pickups.cpp
This commit is contained in:
commit
a0c0e8bdfe
96 changed files with 4828 additions and 4759 deletions
|
|
@ -803,7 +803,6 @@ VMFunction *FFunctionBuildList::AddFunction(PNamespace *gnspc, const VersionInfo
|
|||
|
||||
void FFunctionBuildList::Build()
|
||||
{
|
||||
int errorcount = 0;
|
||||
int codesize = 0;
|
||||
int datasize = 0;
|
||||
FILE *dump = nullptr;
|
||||
|
|
@ -912,7 +911,8 @@ void FFunctionBuildList::Build()
|
|||
}
|
||||
VMFunction::CreateRegUseInfo();
|
||||
FScriptPosition::StrictErrors = false;
|
||||
if (Args->CheckParm("-dumpjit")) DumpJit();
|
||||
|
||||
if (FScriptPosition::ErrorCounter == 0 && Args->CheckParm("-dumpjit")) DumpJit();
|
||||
mItems.Clear();
|
||||
mItems.ShrinkToFit();
|
||||
FxAlloc.FreeAllBlocks();
|
||||
|
|
|
|||
|
|
@ -1187,7 +1187,7 @@ static void ParseActor(FScanner &sc, PNamespace *ns)
|
|||
}
|
||||
try
|
||||
{
|
||||
GetDefaultByType(info)->Finalize(bag.statedef);
|
||||
FinalizeClass(info, bag.statedef);
|
||||
}
|
||||
catch (CRecoverableError &err)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -195,6 +195,29 @@ PProperty::PProperty(FName name, TArray<PField *> &fields)
|
|||
Variables = std::move(fields);
|
||||
}
|
||||
|
||||
/* PProperty *****************************************************************/
|
||||
|
||||
IMPLEMENT_CLASS(PPropFlag, false, false)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PField - Default Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PPropFlag::PPropFlag()
|
||||
: PSymbol(NAME_None)
|
||||
{
|
||||
}
|
||||
|
||||
PPropFlag::PPropFlag(FName name, PField * field, int bitValue, bool forDecorate)
|
||||
: PSymbol(name)
|
||||
{
|
||||
Offset = field;
|
||||
bitval = bitValue;
|
||||
decorateOnly = forDecorate;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
|||
|
|
@ -99,10 +99,11 @@ class PPropFlag : public PSymbol
|
|||
{
|
||||
DECLARE_CLASS(PPropFlag, PSymbol);
|
||||
public:
|
||||
PPropFlag(FName name, PField *offset, int bitval);
|
||||
PPropFlag(FName name, PField *offset, int bitval, bool decorateonly);
|
||||
|
||||
PField *Offset;
|
||||
int bitval;
|
||||
bool decorateOnly;
|
||||
|
||||
protected:
|
||||
PPropFlag();
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@
|
|||
#include "v_text.h"
|
||||
#include "backend/codegen.h"
|
||||
#include "stats.h"
|
||||
#include "info.h"
|
||||
#include "thingdef.h"
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
void InitThingdef();
|
||||
|
|
@ -60,6 +62,69 @@ void InitThingdef();
|
|||
static TMap<FState *, FScriptPosition> StateSourceLines;
|
||||
static FScriptPosition unknownstatesource("unknown file", 0);
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PClassActor :: Finalize
|
||||
//
|
||||
// Installs the parsed states and does some sanity checking
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FinalizeClass(PClass *ccls, FStateDefinitions &statedef)
|
||||
{
|
||||
if (!ccls->IsDescendantOf(NAME_Actor)) return;
|
||||
auto cls = static_cast<PClassActor*>(ccls);
|
||||
try
|
||||
{
|
||||
statedef.FinishStates(cls);
|
||||
}
|
||||
catch (CRecoverableError &)
|
||||
{
|
||||
statedef.MakeStateDefines(nullptr);
|
||||
throw;
|
||||
}
|
||||
auto def = GetDefaultByType(cls);
|
||||
statedef.InstallStates(cls, def);
|
||||
statedef.MakeStateDefines(nullptr);
|
||||
|
||||
if (cls->IsDescendantOf(NAME_Inventory))
|
||||
{
|
||||
def->flags |= MF_SPECIAL;
|
||||
}
|
||||
|
||||
if (cls->IsDescendantOf(NAME_Weapon))
|
||||
{
|
||||
FState *ready = def->FindState(NAME_Ready);
|
||||
FState *select = def->FindState(NAME_Select);
|
||||
FState *deselect = def->FindState(NAME_Deselect);
|
||||
FState *fire = def->FindState(NAME_Fire);
|
||||
auto TypeName = cls->TypeName;
|
||||
|
||||
// Consider any weapon without any valid state abstract and don't output a warning
|
||||
// This is for creating base classes for weapon groups that only set up some properties.
|
||||
if (ready || select || deselect || fire)
|
||||
{
|
||||
if (!ready)
|
||||
{
|
||||
I_Error("Weapon %s doesn't define a ready state.", TypeName.GetChars());
|
||||
}
|
||||
if (!select)
|
||||
{
|
||||
I_Error("Weapon %s doesn't define a select state.", TypeName.GetChars());
|
||||
}
|
||||
if (!deselect)
|
||||
{
|
||||
I_Error("Weapon %s doesn't define a deselect state.", TypeName.GetChars());
|
||||
}
|
||||
if (!fire)
|
||||
{
|
||||
I_Error("Weapon %s doesn't define a fire state.", TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Saves the state's source lines for error messages during postprocessing
|
||||
|
|
@ -186,6 +251,7 @@ PFunction *FindClassMemberFunction(PContainerType *selfcls, PContainerType *func
|
|||
auto cls_target = funcsym ? PType::toClass(funcsym->OwningClass) : nullptr;
|
||||
if (funcsym == nullptr)
|
||||
{
|
||||
if (PClass::FindClass(name)) return nullptr; // Special case when a class's member variable hides a global class name. This should still work.
|
||||
sc.Message(MSG_ERROR, "%s is not a member function of %s", name.GetChars(), selfcls->TypeName.GetChars());
|
||||
}
|
||||
else if ((funcsym->Variants[0].Flags & VARF_Private) && symtable != &funccls->Symbols)
|
||||
|
|
@ -244,9 +310,10 @@ static void CheckForUnsafeStates(PClassActor *obj)
|
|||
TMap<FState *, bool> checked;
|
||||
ENamedName *test;
|
||||
|
||||
if (obj->IsDescendantOf(NAME_Weapon))
|
||||
auto cwtype = PClass::FindActor(NAME_Weapon);
|
||||
if (obj->IsDescendantOf(cwtype))
|
||||
{
|
||||
if (obj->Size == RUNTIME_CLASS(AWeapon)->Size) return; // This class cannot have user variables.
|
||||
if (obj->Size == cwtype->Size) return; // This class cannot have user variables.
|
||||
test = weaponstates;
|
||||
}
|
||||
else
|
||||
|
|
@ -257,7 +324,7 @@ static void CheckForUnsafeStates(PClassActor *obj)
|
|||
if (obj->Size == citype->Size) return; // This class cannot have user variables.
|
||||
test = pickupstates;
|
||||
}
|
||||
else return; // something else derived from AStateProvider. We do not know what this may be.
|
||||
else return; // something else derived from StateProvider. We do not know what this may be.
|
||||
}
|
||||
|
||||
for (; *test != NAME_None; test++)
|
||||
|
|
@ -416,7 +483,7 @@ void LoadActors()
|
|||
|
||||
CheckStates(ti);
|
||||
|
||||
if (ti->bDecorateClass && ti->IsDescendantOf(RUNTIME_CLASS(AStateProvider)))
|
||||
if (ti->bDecorateClass && ti->IsDescendantOf(NAME_StateProvider))
|
||||
{
|
||||
// either a DECORATE based weapon or CustomInventory.
|
||||
// These are subject to relaxed rules for user variables in states.
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ struct FFlagDef
|
|||
int varflags;
|
||||
};
|
||||
|
||||
void FinalizeClass(PClass *cls, FStateDefinitions &statedef);
|
||||
FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bool strict = false);
|
||||
void HandleDeprecatedFlags(AActor *defaults, PClassActor *info, bool set, int index);
|
||||
bool CheckDeprecatedFlags(const AActor *actor, PClassActor *info, int index);
|
||||
|
|
|
|||
|
|
@ -442,37 +442,6 @@ static FFlagDef InventoryFlagDefs[] =
|
|||
DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),
|
||||
};
|
||||
|
||||
static FFlagDef WeaponFlagDefs[] =
|
||||
{
|
||||
// Weapon flags
|
||||
DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, READYSNDHALF, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, DONTBOB, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, AXEBLOOD, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NOALERT, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, AMMO_OPTIONAL, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, ALT_AMMO_OPTIONAL, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, PRIMARY_USES_BOTH, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, WIMPY_WEAPON, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, POWERED_UP, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, STAFF2_KICKBACK, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF_BOT, EXPLOSIVE, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, MELEEWEAPON, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF_BOT, BFG, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, CHEATNOTWEAPON, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, AMMO_CHECKBOTH, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NODEATHDESELECT, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NODEATHINPUT, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, ALT_USES_BOTH, AWeapon, WeaponFlags),
|
||||
|
||||
DEFINE_DUMMY_FLAG(NOLMS, false),
|
||||
DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL, false),
|
||||
};
|
||||
|
||||
|
||||
|
||||
static FFlagDef PlayerPawnFlagDefs[] =
|
||||
{
|
||||
// PlayerPawn flags
|
||||
|
|
@ -505,12 +474,13 @@ static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int
|
|||
{ &RUNTIME_CLASS_CASTLESS(AActor), MoreFlagDefs, countof(MoreFlagDefs), 1 },
|
||||
{ &RUNTIME_CLASS_CASTLESS(AActor), InternalActorFlagDefs, countof(InternalActorFlagDefs), 2 },
|
||||
{ &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs), 3 },
|
||||
{ &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs), 3 },
|
||||
{ &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs), 3 },
|
||||
{ &RUNTIME_CLASS_CASTLESS(ADynamicLight),DynLightFlagDefs, countof(DynLightFlagDefs), 3 },
|
||||
};
|
||||
#define NUM_FLAG_LISTS (countof(FlagLists))
|
||||
|
||||
static FFlagDef forInternalFlags;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Find a flag by name using a binary search
|
||||
|
|
@ -548,6 +518,47 @@ static FFlagDef *FindFlag (FFlagDef *flags, int numflags, const char *flag)
|
|||
|
||||
FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bool strict)
|
||||
{
|
||||
|
||||
if (part2 == nullptr)
|
||||
{
|
||||
FStringf internalname("@flagdef@%s", part1);
|
||||
FName name(internalname, true);
|
||||
if (name != NAME_None)
|
||||
{
|
||||
auto field = dyn_cast<PPropFlag>(type->FindSymbol(name, true));
|
||||
if (field != nullptr && (!strict || !field->decorateOnly))
|
||||
{
|
||||
forInternalFlags.fieldsize = 4;
|
||||
forInternalFlags.name = "";
|
||||
forInternalFlags.flagbit = field->Offset? 1 << field->bitval : DEPF_UNUSED;
|
||||
forInternalFlags.structoffset = field->Offset? (int)field->Offset->Offset : -1;
|
||||
forInternalFlags.varflags = 0;
|
||||
return &forInternalFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FStringf internalname("@flagdef@%s.%s", part1, part2);
|
||||
FName name(internalname, true);
|
||||
if (name != NAME_None)
|
||||
{
|
||||
auto field = dyn_cast<PPropFlag>(type->FindSymbol(name, true));
|
||||
if (field != nullptr)
|
||||
{
|
||||
forInternalFlags.fieldsize = 4;
|
||||
forInternalFlags.name = "";
|
||||
forInternalFlags.flagbit = field->Offset ? 1 << field->bitval : DEPF_UNUSED;
|
||||
forInternalFlags.structoffset = field->Offset ? (int)field->Offset->Offset : -1;
|
||||
forInternalFlags.varflags = 0;
|
||||
return &forInternalFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found. Try the internal flag definitions.
|
||||
|
||||
|
||||
FFlagDef *def;
|
||||
|
||||
if (part2 == NULL)
|
||||
|
|
@ -949,6 +960,11 @@ void InitThingdef()
|
|||
fcp->Size = sizeof(FCheckPosition);
|
||||
fcp->Align = alignof(FCheckPosition);
|
||||
|
||||
//This must also have its size set.
|
||||
auto frp = NewStruct("FRailParams", nullptr);
|
||||
frp->Size = sizeof(FRailParams);
|
||||
frp->Align = alignof(FRailParams);
|
||||
|
||||
|
||||
FieldTable.Clear();
|
||||
if (FieldTable.Size() == 0)
|
||||
|
|
@ -967,17 +983,6 @@ void InitThingdef()
|
|||
|
||||
void SynthesizeFlagFields()
|
||||
{
|
||||
// These are needed for inserting the flag symbols
|
||||
/*
|
||||
NewClassType(RUNTIME_CLASS(DObject));
|
||||
NewClassType(RUNTIME_CLASS(DThinker));
|
||||
NewClassType(RUNTIME_CLASS(AActor));
|
||||
NewClassType(RUNTIME_CLASS(AInventory));
|
||||
NewClassType(RUNTIME_CLASS(AStateProvider));
|
||||
NewClassType(RUNTIME_CLASS(AWeapon));
|
||||
NewClassType(RUNTIME_CLASS(APlayerPawn));
|
||||
NewClassType(RUNTIME_CLASS(ADynamicLight));
|
||||
*/
|
||||
// synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them.
|
||||
for (auto &fl : FlagLists)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1181,20 +1181,20 @@ DEFINE_CLASS_PROPERTY(pickupannouncerentry, S, Inventory)
|
|||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY(defaultkickback, 0, Weapon)
|
||||
DEFINE_SCRIPTED_PROPERTY(defaultkickback, 0, Weapon)
|
||||
{
|
||||
defaults->Kickback = gameinfo.defKickback;
|
||||
defaults->IntVar(NAME_Kickback) = gameinfo.defKickback;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY(bobstyle, S, Weapon)
|
||||
DEFINE_SCRIPTED_PROPERTY(bobstyle, S, Weapon)
|
||||
{
|
||||
static const char *names[] = { "Normal", "Inverse", "Alpha", "InverseAlpha", "Smooth", "InverseSmooth", NULL };
|
||||
static const int styles[] = { AWeapon::BobNormal,
|
||||
AWeapon::BobInverse, AWeapon::BobAlpha, AWeapon::BobInverseAlpha,
|
||||
AWeapon::BobSmooth, AWeapon::BobInverseSmooth, };
|
||||
static const EBobStyle styles[] = { EBobStyle::BobNormal,
|
||||
EBobStyle::BobInverse, EBobStyle::BobAlpha, EBobStyle::BobInverseAlpha,
|
||||
EBobStyle::BobSmooth, EBobStyle::BobInverseSmooth, };
|
||||
PROP_STRING_PARM(id, 0);
|
||||
int match = MatchString(id, names);
|
||||
if (match < 0)
|
||||
|
|
@ -1202,22 +1202,13 @@ DEFINE_CLASS_PROPERTY(bobstyle, S, Weapon)
|
|||
I_Error("Unknown bobstyle %s", id);
|
||||
match = 0;
|
||||
}
|
||||
defaults->BobStyle = styles[match];
|
||||
defaults->IntVar(NAME_BobStyle) = (int)styles[match];
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY(slotpriority, F, Weapon)
|
||||
{
|
||||
PROP_DOUBLE_PARM(i, 0);
|
||||
defaults->SlotPriority = int(i*65536);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY(preferredskin, S, Weapon)
|
||||
DEFINE_SCRIPTED_PROPERTY(preferredskin, S, Weapon)
|
||||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
// NoOp - only for Skulltag compatibility
|
||||
|
|
|
|||
|
|
@ -179,6 +179,11 @@ struct VMReturn
|
|||
Location = loc;
|
||||
RegType = REGT_FLOAT;
|
||||
}
|
||||
void Vec2At(DVector2 *loc)
|
||||
{
|
||||
Location = loc;
|
||||
RegType = REGT_FLOAT | REGT_MULTIREG2;
|
||||
}
|
||||
void StringAt(FString *loc)
|
||||
{
|
||||
Location = loc;
|
||||
|
|
@ -192,6 +197,7 @@ struct VMReturn
|
|||
VMReturn() { }
|
||||
VMReturn(int *loc) { IntAt(loc); }
|
||||
VMReturn(double *loc) { FloatAt(loc); }
|
||||
VMReturn(DVector2 *loc) { Vec2At(loc); }
|
||||
VMReturn(FString *loc) { StringAt(loc); }
|
||||
VMReturn(void **loc) { PointerAt(loc); }
|
||||
};
|
||||
|
|
@ -691,6 +697,15 @@ VMFunction *FindVMFunction(PClass *cls, const char *name);
|
|||
|
||||
FString FStringFormat(VM_ARGS, int offset = 0);
|
||||
|
||||
#define IFVM(cls, funcname) \
|
||||
static VMFunction * func = nullptr; \
|
||||
if (func == nullptr) { \
|
||||
PClass::FindFunction(&func, #cls, #funcname); \
|
||||
assert(func); \
|
||||
} \
|
||||
if (func != nullptr)
|
||||
|
||||
|
||||
|
||||
unsigned GetVirtualIndex(PClass *cls, const char *funcname);
|
||||
|
||||
|
|
|
|||
|
|
@ -348,6 +348,17 @@ static void PrintProperty(FLispString &out, ZCC_TreeNode *node)
|
|||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintFlagDef(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_FlagDef *snode = (ZCC_FlagDef *)node;
|
||||
out.Break();
|
||||
out.Open("flagdef");
|
||||
out.AddName(snode->NodeName);
|
||||
out.AddName(snode->RefName);
|
||||
out.AddInt(snode->BitValue);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStaticArrayState(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
auto *snode = (ZCC_StaticArrayStatement *)node;
|
||||
|
|
@ -959,6 +970,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *
|
|||
PrintExprClassCast,
|
||||
PrintStaticArrayState,
|
||||
PrintProperty,
|
||||
PrintFlagDef,
|
||||
};
|
||||
|
||||
FString ZCC_PrintAST(ZCC_TreeNode *root)
|
||||
|
|
|
|||
|
|
@ -313,6 +313,7 @@ class_innards(X) ::= . { X = NULL; }
|
|||
class_innards(X) ::= class_innards(X) class_member(B). { SAFE_APPEND(X,B); }
|
||||
|
||||
%type property_def{ZCC_Property *}
|
||||
%type flag_def{ZCC_FlagDef *}
|
||||
%type struct_def{ZCC_Struct *}
|
||||
%type enum_def {ZCC_Enum *}
|
||||
%type states_def {ZCC_States *}
|
||||
|
|
@ -325,6 +326,7 @@ class_member(X) ::= states_def(A). { X = A; /*X-overwrites-A*/ }
|
|||
class_member(X) ::= default_def(A). { X = A; /*X-overwrites-A*/ }
|
||||
class_member(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ }
|
||||
class_member(X) ::= property_def(A). { X = A; /*X-overwrites-A*/ }
|
||||
class_member(X) ::= flag_def(A). { X = A; /*X-overwrites-A*/ }
|
||||
class_member(X) ::= staticarray_statement(A). { X = A; /*X-overwrites-A*/ }
|
||||
|
||||
|
||||
|
|
@ -344,6 +346,16 @@ property_def(X) ::= PROPERTY(T) IDENTIFIER(A) COLON identifier_list(B) SEMICOLON
|
|||
X = def;
|
||||
}
|
||||
|
||||
flag_def(X) ::= FLAGDEF(T) IDENTIFIER(A) COLON IDENTIFIER(B) COMMA INTCONST(C) SEMICOLON.
|
||||
{
|
||||
NEW_AST_NODE(FlagDef,def,T);
|
||||
def->NodeName = A.Name();
|
||||
def->RefName = B.Name();
|
||||
def->BitValue = C.Int;
|
||||
X = def;
|
||||
}
|
||||
|
||||
|
||||
identifier_list(X) ::= IDENTIFIER(A).
|
||||
{
|
||||
NEW_AST_NODE(Identifier,id,A);
|
||||
|
|
|
|||
|
|
@ -175,6 +175,10 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode)
|
|||
cls->Properties.Push(static_cast<ZCC_Property *>(node));
|
||||
break;
|
||||
|
||||
case AST_FlagDef:
|
||||
cls->FlagDefs.Push(static_cast<ZCC_FlagDef*>(node));
|
||||
break;
|
||||
|
||||
case AST_VarDeclarator:
|
||||
cls->Fields.Push(static_cast<ZCC_VarDeclarator *>(node));
|
||||
break;
|
||||
|
|
@ -1375,6 +1379,10 @@ void ZCCCompiler::CompileAllProperties()
|
|||
{
|
||||
if (c->Properties.Size() > 0)
|
||||
CompileProperties(c->ClassType(), c->Properties, c->Type()->TypeName);
|
||||
|
||||
if (c->FlagDefs.Size() > 0)
|
||||
CompileFlagDefs(c->ClassType(), c->FlagDefs, c->Type()->TypeName);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1415,20 +1423,88 @@ bool ZCCCompiler::CompileProperties(PClass *type, TArray<ZCC_Property *> &Proper
|
|||
fields.Push(f);
|
||||
id = (ZCC_Identifier*)id->SiblingNext;
|
||||
} while (id != p->Body);
|
||||
|
||||
FString qualifiedname;
|
||||
// Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen.
|
||||
// All these will be removed from the symbol table after the compiler finishes to free up the allocated space.
|
||||
FName name = FName(p->NodeName);
|
||||
if (prefix == NAME_None) qualifiedname.Format("@property@%s", name.GetChars());
|
||||
else qualifiedname.Format("@property@%s.%s", prefix.GetChars(), name.GetChars());
|
||||
|
||||
fields.ShrinkToFit();
|
||||
if (!type->VMType->Symbols.AddSymbol(Create<PProperty>(qualifiedname, fields)))
|
||||
{
|
||||
Error(id, "Unable to add property %s to class %s", FName(p->NodeName).GetChars(), type->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FString qualifiedname;
|
||||
// Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen.
|
||||
// All these will be removed from the symbol table after the compiler finishes to free up the allocated space.
|
||||
FName name = FName(p->NodeName);
|
||||
if (prefix == NAME_None) qualifiedname.Format("@property@%s", name.GetChars());
|
||||
else qualifiedname.Format("@property@%s.%s", prefix.GetChars(), name.GetChars());
|
||||
//==========================================================================
|
||||
//
|
||||
// ZCCCompiler :: CompileProperties
|
||||
//
|
||||
// builds the internal structure of a single class or struct
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
fields.ShrinkToFit();
|
||||
if (!type->VMType->Symbols.AddSymbol(Create<PProperty>(qualifiedname, fields)))
|
||||
bool ZCCCompiler::CompileFlagDefs(PClass *type, TArray<ZCC_FlagDef *> &Properties, FName prefix)
|
||||
{
|
||||
if (!type->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
||||
{
|
||||
Error(Properties[0], "Flags can only be defined for actors");
|
||||
return false;
|
||||
}
|
||||
for (auto p : Properties)
|
||||
{
|
||||
PField *field;
|
||||
FName referenced = FName(p->RefName);
|
||||
|
||||
if (FName(p->NodeName) == FName("prefix") && Wads.GetLumpFile(Lump) == 0)
|
||||
{
|
||||
Error(id, "Unable to add property %s to class %s", FName(p->NodeName).GetChars(), type->TypeName.GetChars());
|
||||
// only for internal definitions: Allow setting a prefix. This is only for compatiblity with the old DECORATE property parser, but not for general use.
|
||||
prefix = referenced;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (referenced != NAME_None)
|
||||
{
|
||||
field = dyn_cast<PField>(type->FindSymbol(referenced, true));
|
||||
if (field == nullptr)
|
||||
{
|
||||
Error(p, "Variable %s not found in %s", referenced.GetChars(), type->TypeName.GetChars());
|
||||
}
|
||||
if (!field->Type->isInt() || field->Type->Size != 4)
|
||||
{
|
||||
Error(p, "Variable %s in %s must have a size of 4 bytes for use as flag storage", referenced.GetChars(), type->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
else field = nullptr;
|
||||
|
||||
|
||||
FString qualifiedname;
|
||||
// Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen.
|
||||
// All these will be removed from the symbol table after the compiler finishes to free up the allocated space.
|
||||
FName name = FName(p->NodeName);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (i == 0) qualifiedname.Format("@flagdef@%s", name.GetChars());
|
||||
else
|
||||
{
|
||||
if (prefix == NAME_None) continue;
|
||||
qualifiedname.Format("@flagdef@%s.%s", prefix.GetChars(), name.GetChars());
|
||||
}
|
||||
|
||||
if (!type->VMType->Symbols.AddSymbol(Create<PPropFlag>(qualifiedname, field, p->BitValue, i == 0 && prefix != NAME_None)))
|
||||
{
|
||||
Error(p, "Unable to add flag definition %s to class %s", FName(p->NodeName).GetChars(), type->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
|
||||
if (field != nullptr)
|
||||
type->VMType->AddNativeField(FStringf("b%s", name.GetChars()), TypeSInt32, field->Offset, 0, 1 << p->BitValue);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3105,7 +3181,7 @@ void ZCCCompiler::CompileStates()
|
|||
}
|
||||
try
|
||||
{
|
||||
GetDefaultByType(c->ClassType())->Finalize(statedef);
|
||||
FinalizeClass(c->ClassType(), statedef);
|
||||
}
|
||||
catch (CRecoverableError &err)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ struct ZCC_ClassWork : public ZCC_StructWork
|
|||
TArray<ZCC_Default *> Defaults;
|
||||
TArray<ZCC_States *> States;
|
||||
TArray<ZCC_Property *> Properties;
|
||||
TArray<ZCC_FlagDef *> FlagDefs;
|
||||
|
||||
ZCC_ClassWork(ZCC_Class * s, PSymbolTreeNode *n)
|
||||
{
|
||||
|
|
@ -110,6 +111,7 @@ private:
|
|||
bool CompileFields(PContainerType *type, TArray<ZCC_VarDeclarator *> &Fields, PClass *Outer, PSymbolTable *TreeNodes, bool forstruct, bool hasnativechildren = false);
|
||||
void CompileAllProperties();
|
||||
bool CompileProperties(PClass *type, TArray<ZCC_Property *> &Properties, FName prefix);
|
||||
bool CompileFlagDefs(PClass *type, TArray<ZCC_FlagDef *> &FlagDefs, FName prefix);
|
||||
FString FlagsToString(uint32_t flags);
|
||||
PType *DetermineType(PType *outertype, ZCC_TreeNode *field, FName name, ZCC_Type *ztype, bool allowarraytypes, bool formember);
|
||||
PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PContainerType *cls);
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ static void InitTokenMap()
|
|||
TOKENDEF ('}', ZCC_RBRACE);
|
||||
TOKENDEF (TK_Struct, ZCC_STRUCT);
|
||||
TOKENDEF (TK_Property, ZCC_PROPERTY);
|
||||
TOKENDEF (TK_FlagDef, ZCC_FLAGDEF);
|
||||
TOKENDEF (TK_Transient, ZCC_TRANSIENT);
|
||||
TOKENDEF (TK_Enum, ZCC_ENUM);
|
||||
TOKENDEF2(TK_SByte, ZCC_SBYTE, NAME_sByte);
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ enum EZCCTreeNodeType
|
|||
AST_ClassCast,
|
||||
AST_StaticArrayStatement,
|
||||
AST_Property,
|
||||
AST_FlagDef,
|
||||
|
||||
NUM_AST_NODE_TYPES
|
||||
};
|
||||
|
|
@ -226,6 +227,12 @@ struct ZCC_Property : ZCC_NamedNode
|
|||
ZCC_TreeNode *Body;
|
||||
};
|
||||
|
||||
struct ZCC_FlagDef : ZCC_NamedNode
|
||||
{
|
||||
ENamedName RefName;
|
||||
int BitValue;
|
||||
};
|
||||
|
||||
struct ZCC_Class : ZCC_Struct
|
||||
{
|
||||
ZCC_Identifier *ParentName;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue