mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-05-31 00:51:21 +00:00
- use the function defaults from the script instead of explicitly setting them again in the code. This is a needless cause of potential errors and since the values are readily available now it's better to use them in the functions.
- fixed: ZCCCompiler did not process array access nodes. - fixed: Function argument names were not placed in the destination list by the compiler. - scriptified several trivial functions from p_actionfunctions.cpp.
This commit is contained in:
parent
66b1f36e56
commit
948ef62fcd
13 changed files with 707 additions and 996 deletions
|
@ -539,12 +539,13 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxIntCast::FxIntCast(FxExpression *x, bool nowarn)
|
||||
FxIntCast::FxIntCast(FxExpression *x, bool nowarn, bool explicitly)
|
||||
: FxExpression(EFX_IntCast, x->ScriptPosition)
|
||||
{
|
||||
basex=x;
|
||||
ValueType = TypeSInt32;
|
||||
NoWarn = nowarn;
|
||||
Explicit = explicitly;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -571,9 +572,10 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
|
|||
|
||||
if (basex->ValueType->GetRegType() == REGT_INT)
|
||||
{
|
||||
if (basex->ValueType != TypeName)
|
||||
if (basex->ValueType != TypeName || Explicit) // names can be converted to int, but only with an explicit type cast.
|
||||
{
|
||||
FxExpression *x = basex;
|
||||
x->ValueType = ValueType;
|
||||
basex = NULL;
|
||||
delete this;
|
||||
return x;
|
||||
|
@ -582,7 +584,8 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
// Ugh. This should abort, but too many mods fell into this logic hole somewhere, so this seroious error needs to be reduced to a warning. :(
|
||||
// At least in ZScript, MSG_OPTERROR always means to report an error, not a warning so the problem only exists in DECORATE.
|
||||
if (!basex->isConstant()) ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name");
|
||||
if (!basex->isConstant())
|
||||
ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got a name");
|
||||
else ScriptPosition.Message(MSG_OPTERROR, "Numeric type expected, got \"%s\"", static_cast<FxConstant*>(basex)->GetValue().GetName().GetChars());
|
||||
FxExpression * x = new FxConstant(0, ScriptPosition);
|
||||
delete this;
|
||||
|
@ -1062,11 +1065,13 @@ ExpEmit FxSoundCast::Emit(VMFunctionBuilder *build)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxTypeCast::FxTypeCast(FxExpression *x, PType *type, bool nowarn)
|
||||
FxTypeCast::FxTypeCast(FxExpression *x, PType *type, bool nowarn, bool explicitly)
|
||||
: FxExpression(EFX_TypeCast, x->ScriptPosition)
|
||||
{
|
||||
basex = x;
|
||||
ValueType = type;
|
||||
NoWarn = nowarn;
|
||||
Explicit = explicitly;
|
||||
assert(ValueType != nullptr);
|
||||
}
|
||||
|
||||
|
@ -1126,7 +1131,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
|||
else if (ValueType->IsA(RUNTIME_CLASS(PInt)))
|
||||
{
|
||||
// This is only for casting to actual ints. Subtypes representing an int will be handled elsewhere.
|
||||
FxExpression *x = new FxIntCast(basex, NoWarn);
|
||||
FxExpression *x = new FxIntCast(basex, NoWarn, Explicit);
|
||||
x = x->Resolve(ctx);
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
|
@ -4964,12 +4969,31 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
return x->Resolve(ctx);
|
||||
}
|
||||
|
||||
// Last but not least: Check builtins. The random functions can take a named RNG if specified.
|
||||
// Last but not least: Check builtins and type casts. The random functions can take a named RNG if specified.
|
||||
// Note that for all builtins the used arguments have to be nulled in the ArgList so that they won't get deleted before they get used.
|
||||
FxExpression *func = nullptr;
|
||||
|
||||
switch (MethodName)
|
||||
{
|
||||
case NAME_Int:
|
||||
case NAME_uInt:
|
||||
case NAME_Double:
|
||||
case NAME_Name:
|
||||
case NAME_Color:
|
||||
case NAME_Sound:
|
||||
if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition))
|
||||
{
|
||||
PType *type = MethodName == NAME_Int ? TypeSInt32 :
|
||||
MethodName == NAME_uInt ? TypeUInt32 :
|
||||
MethodName == NAME_Double ? TypeFloat64 :
|
||||
MethodName == NAME_Name ? TypeName :
|
||||
MethodName == NAME_Color ? TypeColor : (PType*)TypeSound;
|
||||
|
||||
func = new FxTypeCast((*ArgList)[0], type, true, true);
|
||||
(*ArgList)[0] = nullptr;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Random:
|
||||
if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition))
|
||||
{
|
||||
|
@ -5044,6 +5068,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
break;
|
||||
|
||||
default:
|
||||
// todo: Check for class type casts
|
||||
break;
|
||||
}
|
||||
if (func != nullptr)
|
||||
|
@ -5216,8 +5241,11 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
|||
for (unsigned i = 0; i < ArgList->Size(); i++)
|
||||
{
|
||||
(*ArgList)[i] = (*ArgList)[i]->Resolve(ctx);
|
||||
if ((*ArgList)[i] == NULL) failed = true;
|
||||
if (Special < 0 && i == 0)
|
||||
if ((*ArgList)[i] == NULL)
|
||||
{
|
||||
failed = true;
|
||||
}
|
||||
else if (Special < 0 && i == 0)
|
||||
{
|
||||
if ((*ArgList)[i]->ValueType != TypeName)
|
||||
{
|
||||
|
@ -5409,10 +5437,16 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (ArgList != NULL)
|
||||
if (ArgList != nullptr)
|
||||
{
|
||||
bool foundvarargs = false;
|
||||
PType * type = nullptr;
|
||||
if (ArgList->Size() + implicit > proto->ArgumentTypes.Size())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Too many arguments in call to %s", Function->SymbolName.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
for (unsigned i = 0; i < ArgList->Size(); i++)
|
||||
{
|
||||
// Varargs must all have the same type as the last typed argument. A_Jump is the only function using it.
|
||||
|
@ -5476,24 +5510,23 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
|
|||
assert(selfemit.RegType == REGT_POINTER);
|
||||
build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum);
|
||||
count += 1;
|
||||
}
|
||||
if (Function->Variants[0].Flags & VARF_Action)
|
||||
{
|
||||
static_assert(NAP == 3, "This code needs to be updated if NAP changes");
|
||||
if (build->IsActionFunc)
|
||||
if (Function->Variants[0].Flags & VARF_Action)
|
||||
{
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER, 1);
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER, 2);
|
||||
static_assert(NAP == 3, "This code needs to be updated if NAP changes");
|
||||
if (build->IsActionFunc && selfemit.RegNum == 0) // only pass this function's stateowner and stateinfo if the subfunction is run in self's context.
|
||||
{
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER, 1);
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// pass self as stateowner, otherwise all attempts of the subfunction to retrieve a state from a name would fail.
|
||||
build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum);
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr, ATAG_GENERIC));
|
||||
}
|
||||
count += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int null = build->GetConstantAddress(nullptr, ATAG_GENERIC);
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, null);
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, null);
|
||||
}
|
||||
count += 2;
|
||||
}
|
||||
|
||||
// Emit code to pass explicit parameters
|
||||
if (ArgList != NULL)
|
||||
{
|
||||
|
|
|
@ -474,10 +474,11 @@ class FxIntCast : public FxExpression
|
|||
{
|
||||
FxExpression *basex;
|
||||
bool NoWarn;
|
||||
bool Explicit;
|
||||
|
||||
public:
|
||||
|
||||
FxIntCast(FxExpression *x, bool nowarn);
|
||||
FxIntCast(FxExpression *x, bool nowarn, bool explicitly = false);
|
||||
~FxIntCast();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
|
@ -559,10 +560,11 @@ class FxTypeCast : public FxExpression
|
|||
{
|
||||
FxExpression *basex;
|
||||
bool NoWarn;
|
||||
bool Explicit;
|
||||
|
||||
public:
|
||||
|
||||
FxTypeCast(FxExpression *x, PType *type, bool nowarn);
|
||||
FxTypeCast(FxExpression *x, PType *type, bool nowarn, bool explicitly = false);
|
||||
~FxTypeCast();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
|
|
|
@ -67,8 +67,8 @@ static FFlagDef ActorFlagDefs[]=
|
|||
DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags),
|
||||
DEFINE_FLAG(MF, SOLID, AActor, flags),
|
||||
DEFINE_FLAG(MF, SHOOTABLE, AActor, flags),
|
||||
DEFINE_READONLY_FLAG(MF, NOSECTOR, AActor, flags),
|
||||
DEFINE_READONLY_FLAG(MF, NOBLOCKMAP, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOSECTOR, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOBLOCKMAP, AActor, flags),
|
||||
DEFINE_FLAG(MF, AMBUSH, AActor, flags),
|
||||
DEFINE_FLAG(MF, JUSTHIT, AActor, flags),
|
||||
DEFINE_FLAG(MF, JUSTATTACKED, AActor, flags),
|
||||
|
@ -84,8 +84,8 @@ static FFlagDef ActorFlagDefs[]=
|
|||
DEFINE_FLAG(MF, NOBLOOD, AActor, flags),
|
||||
DEFINE_FLAG(MF, CORPSE, AActor, flags),
|
||||
DEFINE_FLAG(MF, INFLOAT, AActor, flags),
|
||||
DEFINE_READONLY_FLAG(MF, COUNTKILL, AActor, flags),
|
||||
DEFINE_READONLY_FLAG(MF, COUNTITEM, AActor, flags),
|
||||
DEFINE_FLAG(MF, COUNTKILL, AActor, flags),
|
||||
DEFINE_FLAG(MF, COUNTITEM, AActor, flags),
|
||||
DEFINE_FLAG(MF, SKULLFLY, AActor, flags),
|
||||
DEFINE_FLAG(MF, NOTDMATCH, AActor, flags),
|
||||
DEFINE_FLAG(MF, SPAWNSOUNDSOURCE, AActor, flags),
|
||||
|
@ -186,7 +186,7 @@ static FFlagDef ActorFlagDefs[]=
|
|||
DEFINE_FLAG(MF5, GETOWNER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NOFORWARDFALL, AActor, flags5),
|
||||
DEFINE_READONLY_FLAG(MF5, COUNTSECRET, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, COUNTSECRET, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, NODAMAGE, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, BLOODSPLATTER, AActor, flags5),
|
||||
DEFINE_FLAG(MF5, OLDRADIUSDMG, AActor, flags5),
|
||||
|
@ -677,10 +677,20 @@ void InitThingdef()
|
|||
symt.AddSymbol(new PField(NAME_ReactionTime, TypeSInt32, VARF_Native, myoffsetof(AActor, reactiontime)));
|
||||
symt.AddSymbol(new PField(NAME_MeleeRange, TypeFloat64, VARF_Native, myoffsetof(AActor, meleerange)));
|
||||
symt.AddSymbol(new PField(NAME_Speed, TypeFloat64, VARF_Native, myoffsetof(AActor, Speed)));
|
||||
symt.AddSymbol(new PField(NAME_Threshold, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, threshold)));
|
||||
symt.AddSymbol(new PField("FloatSpeed", TypeFloat64, VARF_Native, myoffsetof(AActor, FloatSpeed)));
|
||||
symt.AddSymbol(new PField("PainThreshold", TypeSInt32, VARF_Native, myoffsetof(AActor, PainThreshold)));
|
||||
symt.AddSymbol(new PField("spriteAngle", TypeFloat64, VARF_Native, myoffsetof(AActor, SpriteAngle)));
|
||||
symt.AddSymbol(new PField("spriteRotation", TypeFloat64, VARF_Native, myoffsetof(AActor, SpriteRotation)));
|
||||
symt.AddSymbol(new PField(NAME_Threshold, TypeSInt32, VARF_Native, myoffsetof(AActor, threshold)));
|
||||
symt.AddSymbol(new PField(NAME_DefThreshold, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, DefThreshold)));
|
||||
symt.AddSymbol(new PField(NAME_Damage, TypeSInt32, VARF_Native|VARF_ReadOnly, myoffsetof(AActor, DamageVal)));
|
||||
symt.AddSymbol(new PField("visdir", TypeSInt32, VARF_Native, myoffsetof(AActor, visdir)));
|
||||
symt.AddSymbol(new PField("Gravity", TypeFloat64, VARF_Native, myoffsetof(AActor, Gravity)));
|
||||
symt.AddSymbol(new PField("DamageType", TypeName, VARF_Native, myoffsetof(AActor, DamageType)));
|
||||
symt.AddSymbol(new PField("FloatBobPhase", TypeUInt8, VARF_Native, myoffsetof(AActor, FloatBobPhase)));
|
||||
symt.AddSymbol(new PField("RipperLevel", TypeSInt32, VARF_Native, myoffsetof(AActor, RipperLevel)));
|
||||
symt.AddSymbol(new PField("RipLevelMin", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMin)));
|
||||
symt.AddSymbol(new PField("RipLevelMax", TypeSInt32, VARF_Native, myoffsetof(AActor, RipLevelMax)));
|
||||
symt.AddSymbol(new PField(NAME_VisibleStartAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartAngle)));
|
||||
symt.AddSymbol(new PField(NAME_VisibleStartPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartPitch)));
|
||||
symt.AddSymbol(new PField(NAME_VisibleEndAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndAngle)));
|
||||
|
@ -693,6 +703,8 @@ void InitThingdef()
|
|||
symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target)));
|
||||
symt.AddSymbol(new PField(NAME_Master, TypeActor, VARF_Native, myoffsetof(AActor, master)));
|
||||
symt.AddSymbol(new PField(NAME_Tracer, TypeActor, VARF_Native, myoffsetof(AActor, tracer)));
|
||||
symt.AddSymbol(new PField("LastHeard", TypeActor, VARF_Native, myoffsetof(AActor, LastHeard)));
|
||||
symt.AddSymbol(new PField("LastEnemy", TypeActor, VARF_Native, myoffsetof(AActor, lastenemy)));
|
||||
|
||||
// synthesize a symbol for each flag. The bounce flags are excluded on purpose.
|
||||
for (size_t i = 0; i < countof(ActorFlagDefs); i++)
|
||||
|
|
|
@ -925,7 +925,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
// PARAM_INT_OPT(0,myint) { myint = 55; }
|
||||
// Just make sure to fill it in when using these macros, because the compiler isn't likely
|
||||
// to give useful error messages if you don't.
|
||||
#define PARAM_EXISTS ((p) < numparam && param[p].Type != REGT_NIL)
|
||||
#define PARAM_EXISTS(p) ((p) < numparam && param[p].Type != REGT_NIL)
|
||||
#define ASSERTINT(p) assert((p).Type == REGT_INT)
|
||||
#define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT)
|
||||
#define ASSERTSTRING(p) assert((p).Type == REGT_STRING)
|
||||
|
@ -933,7 +933,18 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define ASSERTPOINTER(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_GENERIC)
|
||||
#define ASSERTSTATE(p) assert((p).Type == REGT_POINTER && ((p).atag == ATAG_GENERIC || (p).atag == ATAG_STATE))
|
||||
|
||||
#define PARAM_INT_DEF_AT(p,x) int x; if (PARAM_EXISTS) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; }
|
||||
#define PARAM_INT_DEF_AT(p,x) int x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; }
|
||||
#define PARAM_BOOL_DEF_AT(p,x) bool x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = !!param[p].i; } else { ASSERTINT(defaultparam[p]); x = !!defaultparam[p].i; }
|
||||
#define PARAM_NAME_DEF_AT(p,x) FName x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = ENamedName(param[p].i); } else { ASSERTINT(defaultparam[p]); x = ENamedName(defaultparam[p].i); }
|
||||
#define PARAM_SOUND_DEF_AT(p,x) FSoundID x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = FSoundID(param[p].i); } else { ASSERTINT(defaultparam[p]); x = FSoundID(defaultparam[p].i); }
|
||||
#define PARAM_COLOR_DEF_AT(p,x) PalEntry x; if (PARAM_EXISTS(p)) { ASSERTINT(param[p]); x = param[p].i; } else { ASSERTINT(defaultparam[p]); x = defaultparam[p].i; }
|
||||
#define PARAM_FLOAT_DEF_AT(p,x) double x; if (PARAM_EXISTS(p)) { ASSERTFLOAT(param[p]); x = param[p].f; } else { ASSERTFLOAT(defaultparam[p]); x = defaultparam[p].f; }
|
||||
#define PARAM_ANGLE_DEF_AT(p,x) DAngle x; if (PARAM_EXISTS(p)) { ASSERTFLOAT(param[p]); x = param[p].f; } else { ASSERTFLOAT(defaultparam[p]); x = defaultparam[p].f; }
|
||||
#define PARAM_STRING_DEF_AT(p,x) FString x; if (PARAM_EXISTS(p)) { ASSERTSTRING(param[p]); x = param[p].s; } else { ASSERTSTRING(defaultparam[p]); x = defaultparam[p].s; }
|
||||
#define PARAM_STATE_DEF_AT(p,x) FState *x; if (PARAM_EXISTS(p)) { ASSERTSTATE(param[p]); x = (FState*)param[p].a; } else { ASSERTSTATE(defaultparam[p]); x = (FState*)defaultparam[p].a; }
|
||||
#define PARAM_POINTER_DEF_AT(p,x,t) t *x; if (PARAM_EXISTS(p)) { ASSERTPOINTER(param[p]); x = (t*)param[p].a; } else { ASSERTPOINTER(defaultparam[p]); x = (t*)defaultparam[p].a; }
|
||||
#define PARAM_OBJECT_DEF_AT(p,x,t) t *x; if (PARAM_EXISTS(p)) { ASSERTOBJECT(param[p]); x = (t*)param[p].a; } else { ASSERTOBJECT(defaultparam[p]); x = (t*)defaultparam[p].a; }
|
||||
#define PARAM_CLASS_DEF_AT(p,x,t) t::MetaClass *x; if (PARAM_EXISTS(p)) { ASSERTOBJECT(param[p]); x = (t::MetaClass*)param[p].a; } else { ASSERTOBJECT(defaultparam[p]); x = (t::MetaClass*)defaultparam[p].a; }
|
||||
|
||||
#define PARAM_INT_OPT_AT(p,x) int x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = param[p].i; } else
|
||||
#define PARAM_BOOL_OPT_AT(p,x) bool x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = !!param[p].i; } else
|
||||
|
@ -1048,6 +1059,24 @@ struct AFuncDesc
|
|||
#define ACTION_CALL_FROM_PSPRITE() (self->player && stateinfo != nullptr && stateinfo->mStateType == STATE_Psprite)
|
||||
#define ACTION_CALL_FROM_INVENTORY() (stateinfo != nullptr && stateinfo->mStateType == STATE_StateChain)
|
||||
|
||||
// Standard parameters for all action functons
|
||||
// self - Actor this action is to operate on (player if a weapon)
|
||||
// stateowner - Actor this action really belongs to (may be an item)
|
||||
// callingstate - State this action was called from
|
||||
#define PARAM_ACTION_PROLOGUE(type) \
|
||||
PARAM_PROLOGUE; \
|
||||
PARAM_OBJECT (self, type); \
|
||||
PARAM_OBJECT_OPT (stateowner, AActor) { stateowner = self; } \
|
||||
PARAM_STATEINFO_OPT (stateinfo) { stateinfo = nullptr; } \
|
||||
|
||||
// Number of action paramaters
|
||||
#define NAP 3
|
||||
|
||||
#define PARAM_SELF_PROLOGUE(type) \
|
||||
PARAM_PROLOGUE; \
|
||||
PARAM_OBJECT(self, type);
|
||||
|
||||
|
||||
class PFunction;
|
||||
|
||||
PFunction *FindGlobalActionFunction(const char *name);
|
||||
|
|
|
@ -175,13 +175,13 @@ begin:
|
|||
OP(LO):
|
||||
ASSERTA(a); ASSERTA(B); ASSERTKD(C);
|
||||
GETADDR(PB,KC,X_READ_NIL);
|
||||
reg.a[a] = *(void **)ptr;
|
||||
reg.a[a] = GC::ReadBarrier(*(DObject **)ptr);
|
||||
reg.atag[a] = ATAG_OBJECT;
|
||||
NEXTOP;
|
||||
OP(LO_R):
|
||||
ASSERTA(a); ASSERTA(B); ASSERTD(C);
|
||||
GETADDR(PB,RC,X_READ_NIL);
|
||||
reg.a[a] = *(void **)ptr;
|
||||
reg.a[a] = GC::ReadBarrier(*(DObject **)ptr);
|
||||
reg.atag[a] = ATAG_OBJECT;
|
||||
NEXTOP;
|
||||
OP(LP):
|
||||
|
|
|
@ -2102,12 +2102,14 @@ void ZCCCompiler::InitFunctions()
|
|||
// TBD: disallow certain types? For now, let everything pass that isn't an array.
|
||||
args.Push(type);
|
||||
argflags.Push(flags);
|
||||
argnames.Push(p->Name);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Push(nullptr);
|
||||
argflags.Push(0);
|
||||
argnames.Push(NAME_None);
|
||||
}
|
||||
argdefaults.Push(vmval);
|
||||
p = static_cast<decltype(p)>(p->SiblingNext);
|
||||
|
@ -2120,7 +2122,7 @@ void ZCCCompiler::InitFunctions()
|
|||
|
||||
if (!(f->Flags & ZCC_Native))
|
||||
{
|
||||
auto code = ConvertAST(f->Body);
|
||||
auto code = ConvertAST(c->Type(), f->Body);
|
||||
if (code != nullptr)
|
||||
{
|
||||
sym->Variants[0].Implementation = FunctionBuildList.AddFunction(sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false);
|
||||
|
@ -2157,7 +2159,7 @@ static bool CheckRandom(ZCC_Expression *duration)
|
|||
// Sets up the action function call
|
||||
//
|
||||
//==========================================================================
|
||||
FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *af)
|
||||
FxExpression *ZCCCompiler::SetupActionFunction(PClass *cls, ZCC_TreeNode *af)
|
||||
{
|
||||
// We have 3 cases to consider here:
|
||||
// 1. An action function without parameters. This can be called directly
|
||||
|
@ -2197,8 +2199,7 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a
|
|||
}
|
||||
}
|
||||
}
|
||||
ConvertClass = cls;
|
||||
return ConvertAST(af);
|
||||
return ConvertAST(cls, af);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2419,8 +2420,9 @@ void ZCCCompiler::CompileStates()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *ZCCCompiler::ConvertAST(ZCC_TreeNode *ast)
|
||||
FxExpression *ZCCCompiler::ConvertAST(PClass *cls, ZCC_TreeNode *ast)
|
||||
{
|
||||
ConvertClass = cls;
|
||||
// there are two possibilities here: either a single function call or a compound statement. For a compound statement we also need to check if the last thing added was a return.
|
||||
if (ast->NodeType == AST_ExprFuncCall)
|
||||
{
|
||||
|
@ -2680,6 +2682,9 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
|||
case PEX_LTGTEQ:
|
||||
return new FxLtGtEq(left, right);
|
||||
|
||||
case PEX_ArrayAccess:
|
||||
return new FxArrayElement(left, right);
|
||||
|
||||
// todo: These do not have representations in DECORATE and no implementation exists yet.
|
||||
case PEX_Concat:
|
||||
case PEX_Is:
|
||||
|
|
|
@ -109,7 +109,7 @@ private:
|
|||
|
||||
void InitFunctions();
|
||||
void CompileStates();
|
||||
FxExpression *SetupActionFunction(PClassActor *cls, ZCC_TreeNode *sl);
|
||||
FxExpression *SetupActionFunction(PClass *cls, ZCC_TreeNode *sl);
|
||||
|
||||
bool SimplifyingConstant;
|
||||
TArray<ZCC_ConstantDef *> Constants;
|
||||
|
@ -140,7 +140,7 @@ private:
|
|||
void Error(ZCC_TreeNode *node, const char *msg, ...);
|
||||
void MessageV(ZCC_TreeNode *node, const char *txtcolor, const char *msg, va_list argptr);
|
||||
|
||||
FxExpression *ConvertAST(ZCC_TreeNode *ast);
|
||||
FxExpression *ConvertAST(PClass *cclass, ZCC_TreeNode *ast);
|
||||
FxExpression *ConvertNode(ZCC_TreeNode *node);
|
||||
FArgumentList *ConvertNodeList(ZCC_TreeNode *head);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue