- added proper definitions for all exported native fields.

- synthesize native fields for all declared flags, not just for AActor.
This commit is contained in:
Christoph Oelckers 2016-11-22 23:42:32 +01:00
parent e1c4e4939a
commit 099b9970ef
23 changed files with 452 additions and 246 deletions

View file

@ -63,7 +63,7 @@ static TArray<FieldDesc> FieldTable;
#define DEFINE_DUMMY_FLAG(name, deprec) { DEPF_UNUSED, #name, -1, 0, deprec? VARF_Deprecated:0 }
// internal flags. These do not get exposed to actor definitions but scripts need to be able to access them as variables.
FFlagDef InternalActorFlagDefs[]=
static FFlagDef InternalActorFlagDefs[]=
{
DEFINE_FLAG(MF, INCHASE, AActor, flags),
DEFINE_FLAG(MF, UNMORPHED, AActor, flags),
@ -90,11 +90,10 @@ FFlagDef InternalActorFlagDefs[]=
DEFINE_FLAG(MF6, INTRYMOVE, AActor, flags6),
DEFINE_FLAG(MF7, HANDLENODELAY, AActor, flags7),
DEFINE_FLAG(MF7, FLYCHEAT, AActor, flags7),
{ 0xffffffff }
};
FFlagDef ActorFlagDefs[]=
static FFlagDef ActorFlagDefs[]=
{
DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags),
DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags),
@ -328,7 +327,6 @@ FFlagDef ActorFlagDefs[]=
DEFINE_FLAG2(BOUNCE_MBF, MBFBOUNCER, AActor, BounceFlags),
DEFINE_FLAG2(BOUNCE_AutoOffFloorOnly, BOUNCEAUTOOFFFLOORONLY, AActor, BounceFlags),
DEFINE_FLAG2(BOUNCE_UseBounceState, USEBOUNCESTATE, AActor, BounceFlags),
{ 0xffffffff }
};
// These won't be accessible through bitfield variables
@ -387,10 +385,9 @@ static FFlagDef InventoryFlagDefs[] =
DEFINE_DEPRECATED_FLAG(PICKUPFLASH),
DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),
{ 0xffffffff }
};
FFlagDef WeaponFlagDefs[] =
static FFlagDef WeaponFlagDefs[] =
{
// Weapon flags
DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags),
@ -417,7 +414,6 @@ FFlagDef WeaponFlagDefs[] =
DEFINE_DUMMY_FLAG(NOLMS, false),
DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL, false),
{ 0xffffffff }
};
@ -428,24 +424,23 @@ static FFlagDef PlayerPawnFlagDefs[] =
DEFINE_FLAG(PPF, NOTHRUSTWHENINVUL, APlayerPawn, PlayerFlags),
DEFINE_FLAG(PPF, CANSUPERMORPH, APlayerPawn, PlayerFlags),
DEFINE_FLAG(PPF, CROUCHABLEMORPH, APlayerPawn, PlayerFlags),
{ 0xffffffff }
};
static FFlagDef PowerSpeedFlagDefs[] =
{
// PowerSpeed flags
DEFINE_FLAG(PSF, NOTRAIL, APowerSpeed, SpeedFlags),
{ 0xffffffff }
};
static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] =
static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int NumDefs; int Use; } FlagLists[] =
{
{ &RUNTIME_CLASS_CASTLESS(AActor), ActorFlagDefs, countof(ActorFlagDefs)-1 }, // -1 to account for the terminator
{ &RUNTIME_CLASS_CASTLESS(AActor), MoreFlagDefs, countof(MoreFlagDefs) },
{ &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs)-1 },
{ &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs)-1 },
{ &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs)-1 },
{ &RUNTIME_CLASS_CASTLESS(APowerSpeed), PowerSpeedFlagDefs, countof(PowerSpeedFlagDefs)-1 },
{ &RUNTIME_CLASS_CASTLESS(AActor), ActorFlagDefs, countof(ActorFlagDefs), 3 }, // -1 to account for the terminator
{ &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(APowerSpeed), PowerSpeedFlagDefs, countof(PowerSpeedFlagDefs), 3 },
};
#define NUM_FLAG_LISTS (countof(FlagLists))
@ -493,7 +488,7 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2, bo
int max = strict ? 2 : NUM_FLAG_LISTS;
for (int i = 0; i < max; ++i)
{
if (type->IsDescendantOf (*FlagLists[i].Type))
if ((FlagLists[i].Use & 1) && type->IsDescendantOf (*FlagLists[i].Type))
{
def = FindFlag (FlagLists[i].Defs, FlagLists[i].NumDefs, part1);
if (def != NULL)
@ -709,9 +704,35 @@ void InitThingdef()
sstruct->AddNativeField("soundtarget", TypeActor, myoffsetof(sector_t, SoundTarget));
G_InitLevelLocalsForScript();
P_InitPlayerForScript();
P_InitStateForScript();
// set up a variable for the global players array.
PStruct *pstruct = NewNativeStruct("PlayerInfo", nullptr);
pstruct->Size = sizeof(player_t);
pstruct->Align = alignof(player_t);
PArray *parray = NewArray(pstruct, MAXPLAYERS);
PField *playerf = new PField("players", pstruct, VARF_Native | VARF_Static, (intptr_t)&players);
GlobalSymbols.AddSymbol(playerf);
// this needs to be done manually until it can be given a proper type.
RUNTIME_CLASS(AActor)->AddNativeField("DecalGenerator", NewPointer(TypeVoid), myoffsetof(AActor, DecalGenerator));
// synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them.
for (auto &fl : FlagLists)
{
if (fl.Use & 2)
{
for(int i=0;i<fl.NumDefs;i++)
{
if (fl.Defs[i].structoffset > 0) // skip the deprecated entries in this list
{
const_cast<PClass*>(*fl.Type)->AddNativeField(FStringf("b%s", fl.Defs[i].name), (fl.Defs[i].fieldsize == 4 ? TypeSInt32 : TypeSInt16), fl.Defs[i].structoffset, fl.Defs[i].varflags, fl.Defs[i].flagbit);
}
}
}
}
FAutoSegIterator probe(CRegHead, CRegTail);
while (*++probe != NULL)

View file

@ -1061,7 +1061,12 @@ struct AFuncDesc
#define DEFINE_FIELD_X(cls, icls, name) \
static const FieldDesc VMField_##icls##_##name = { "A" #cls, #name, (unsigned)myoffsetof(icls, name), (unsigned)sizeof(icls::name), 0 }; \
extern FieldDesc const *const VMField_##icls##_##name##_HookPtr; \
MSVC_FSEG FieldDesc const *const VMField_##icls##_##name##_HookPtr GCC_FSEG = &VMField_##cls##_##name;
MSVC_FSEG FieldDesc const *const VMField_##icls##_##name##_HookPtr GCC_FSEG = &VMField_##icls##_##name;
#define DEFINE_FIELD_NAMED_X(cls, icls, name, scriptname) \
static const FieldDesc VMField_##icls##_##scriptname = { "A" #cls, #scriptname, (unsigned)myoffsetof(icls, name), (unsigned)sizeof(icls::name), 0 }; \
extern FieldDesc const *const VMField_##icls##_##scriptname##_HookPtr; \
MSVC_FSEG FieldDesc const *const VMField_##icls##_##scriptname##_HookPtr GCC_FSEG = &VMField_##icls##_##scriptname;
#define DEFINE_FIELD_X_BIT(cls, icls, name, bitval) \
static const FieldDesc VMField_##icls##_##name = { "A" #cls, #name, (unsigned)myoffsetof(icls, name), (unsigned)sizeof(icls::name), bitval }; \

View file

@ -295,8 +295,9 @@ struct_flags(X) ::= NATIVE. { X.Flags = ZCC_Native; }
opt_struct_body(X) ::= . { X = NULL; }
opt_struct_body(X) ::= struct_body(X).
opt_struct_body(X) ::= error. { X = NULL; }
struct_body(X) ::= error. { X = NULL; }
struct_body(X) ::= struct_member(X).
struct_body(X) ::= struct_member(A) struct_body(B). { X = A; /*X-overwrites-A*/ X->AppendSibling(B); }

View file

@ -1274,7 +1274,9 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
PType *fieldtype = DetermineType(type, field, field->Names->Name, field->Type, true, true);
// For structs only allow 'deprecated', for classes exclude function qualifiers.
int notallowed = forstruct? ~ZCC_Deprecated : ZCC_Latent | ZCC_Final | ZCC_Action | ZCC_Static | ZCC_FuncConst | ZCC_Abstract | ZCC_Virtual | ZCC_Override;
int notallowed = forstruct?
ZCC_Latent | ZCC_Final | ZCC_Action | ZCC_Static | ZCC_FuncConst | ZCC_Abstract | ZCC_Virtual | ZCC_Override | ZCC_Meta | ZCC_Extension :
ZCC_Latent | ZCC_Final | ZCC_Action | ZCC_Static | ZCC_FuncConst | ZCC_Abstract | ZCC_Virtual | ZCC_Override | ZCC_Extension;
if (field->Flags & notallowed)
{
@ -1323,13 +1325,15 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray<ZCC_VarDeclarator *> &Fiel
{
Error(field, "The member variable '%s.%s' has not been exported from the executable.", type->TypeName.GetChars(), FName(name->Name).GetChars());
}
else if (thisfieldtype->Size != fd->FieldSize)
else if (thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0)
{
Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size);
}
// Q: Should we check alignment, too? A mismatch may be an indicator for bad assumptions.
else
{
// for bit fields the type must point to the source variable.
if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32;
type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue);
}
}
@ -1427,6 +1431,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
case ZCC_FloatAuto:
retval = formember ? TypeFloat32 : TypeFloat64;
break;
case ZCC_Float64:
retval = TypeFloat64;

View file

@ -164,6 +164,11 @@ struct ZCC_TreeNode
// Appends a sibling to this node's sibling list.
void AppendSibling(ZCC_TreeNode *sibling)
{
if (this == nullptr)
{
// Some bad syntax can actually get here, so better abort so that the user can see the error which caused this.
I_FatalError("Internal script compiler error. Execution aborted.");
}
if (sibling == NULL)
{
return;