mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- actually evaluate the default parameters and store them in the VMFunction.
- disabled the assert in PType::GetRegType. This assert blocks any use to check for types that are incompatible with function parameters. - pass the default parameter constants to the native functions. At the moment this is not used yet. - use the function defaults to complete argument lists to script functions. - fixed all default values that got flagged by the expression evaluator as non-constant. Most were state labels and colors which were defaulted to "". The proper value is null for states and 0 for colors. - also replaced all "" defaults for names with "none".
This commit is contained in:
parent
d32d52c0b9
commit
66b1f36e56
12 changed files with 152 additions and 62 deletions
|
@ -521,7 +521,7 @@ int PType::GetMoveOp() const
|
|||
|
||||
int PType::GetRegType() const
|
||||
{
|
||||
assert(0 && "No register for this type");
|
||||
//assert(0 && "No register for this type"); // wrong place for this assert, it makes it impossible to use this function to check for bad types.
|
||||
return REGT_NIL;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecor
|
|||
if (fnc != nullptr) Class = fnc->OwningClass;
|
||||
}
|
||||
|
||||
FCompileContext::FCompileContext(PClass *cls) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(true) // only used by DECORATE constants.
|
||||
FCompileContext::FCompileContext(PClass *cls, bool fromdecorate) : ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -3745,7 +3745,7 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int DecoRandom(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
|
||||
int DecoRandom(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam >= 1 && numparam <= 3);
|
||||
FRandom *rng = reinterpret_cast<FRandom *>(param[0].a);
|
||||
|
@ -3995,7 +3995,7 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int DecoFRandom(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
|
||||
int DecoFRandom(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam == 1 || numparam == 3);
|
||||
FRandom *rng = reinterpret_cast<FRandom *>(param[0].a);
|
||||
|
@ -5255,7 +5255,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int DecoCallLineSpecial(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
|
||||
int DecoCallLineSpecial(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam > 2 && numparam < 8);
|
||||
assert(param[0].Type == REGT_INT);
|
||||
|
@ -6702,7 +6702,7 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int DecoNameToClass(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
|
||||
int DecoNameToClass(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam == 2);
|
||||
assert(numret == 1);
|
||||
|
@ -6842,7 +6842,7 @@ static bool VerifyJumpTarget(AActor *stateowner, FStateParamInfo *stateinfo, int
|
|||
return false;
|
||||
}
|
||||
|
||||
static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
|
||||
static int DecoHandleRuntimeState(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT(stateowner, AActor);
|
||||
|
@ -7008,7 +7008,7 @@ static int DoFindState(VMFrameStack *stack, VMValue *param, int numparam, VMRetu
|
|||
}
|
||||
|
||||
// Find a state with any number of dots in its name.
|
||||
int BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
|
||||
int BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam > 1);
|
||||
assert(numret == 1);
|
||||
|
@ -7024,7 +7024,7 @@ int BuiltinFindMultiNameState(VMFrameStack *stack, VMValue *param, int numparam,
|
|||
}
|
||||
|
||||
// Find a state without any dots in its name.
|
||||
int BuiltinFindSingleNameState(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret)
|
||||
int BuiltinFindSingleNameState(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam == 2);
|
||||
assert(numret == 1);
|
||||
|
|
|
@ -77,7 +77,7 @@ struct FCompileContext
|
|||
TDeletingArray<FxLocalVariableDeclaration *> FunctionArgs;
|
||||
|
||||
FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate);
|
||||
FCompileContext(PClass *cls); // only to be used to resolve constants!
|
||||
FCompileContext(PClass *cls, bool fromdecorate); // only to be used to resolve constants!
|
||||
|
||||
PSymbol *FindInClass(FName identifier, PSymbolTable *&symt);
|
||||
PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt);
|
||||
|
|
|
@ -87,7 +87,7 @@ FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, bool mustresolve)
|
|||
|
||||
if (mustresolve)
|
||||
{
|
||||
FCompileContext ctx(cls);
|
||||
FCompileContext ctx(cls, true);
|
||||
data = data->Resolve(ctx);
|
||||
}
|
||||
|
||||
|
|
|
@ -667,8 +667,8 @@ void InitThingdef()
|
|||
symt.AddSymbol(new PField(NAME_MomX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.X)));
|
||||
symt.AddSymbol(new PField(NAME_MomY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Y)));
|
||||
symt.AddSymbol(new PField(NAME_MomZ, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Vel.Z)));
|
||||
symt.AddSymbol(new PField(NAME_ScaleX, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Scale.X)));
|
||||
symt.AddSymbol(new PField(NAME_ScaleY, TypeFloat64, VARF_Native|VARF_ReadOnly|VARF_Deprecated, myoffsetof(AActor, Scale.Y)));
|
||||
symt.AddSymbol(new PField(NAME_ScaleX, TypeFloat64, VARF_Native|VARF_Deprecated, myoffsetof(AActor, Scale.X)));
|
||||
symt.AddSymbol(new PField(NAME_ScaleY, TypeFloat64, VARF_Native|VARF_Deprecated, myoffsetof(AActor, Scale.Y)));
|
||||
symt.AddSymbol(new PField(NAME_Score, TypeSInt32, VARF_Native, myoffsetof(AActor, Score)));
|
||||
symt.AddSymbol(new PField(NAME_Accuracy, TypeSInt32, VARF_Native, myoffsetof(AActor, accuracy)));
|
||||
symt.AddSymbol(new PField(NAME_Stamina, TypeSInt32, VARF_Native, myoffsetof(AActor, stamina)));
|
||||
|
|
|
@ -173,20 +173,6 @@ enum EVMAbortException
|
|||
X_BAD_SELF,
|
||||
};
|
||||
|
||||
class VMFunction : public DObject
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(VMFunction, DObject);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
bool Native;
|
||||
BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action
|
||||
FName Name;
|
||||
|
||||
class PPrototype *Proto;
|
||||
|
||||
VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) {}
|
||||
};
|
||||
|
||||
enum EVMOpMode
|
||||
{
|
||||
MODE_ASHIFT = 0,
|
||||
|
@ -642,6 +628,21 @@ do_double: if (inexact)
|
|||
}
|
||||
};
|
||||
|
||||
class VMFunction : public DObject
|
||||
{
|
||||
DECLARE_ABSTRACT_CLASS(VMFunction, DObject);
|
||||
HAS_OBJECT_POINTERS;
|
||||
public:
|
||||
bool Native;
|
||||
BYTE ImplicitArgs = 0; // either 0 for static, 1 for method or 3 for action
|
||||
FName Name;
|
||||
TArray<VMValue> Defaults;
|
||||
|
||||
class PPrototype *Proto;
|
||||
|
||||
VMFunction(FName name = NAME_None) : Native(false), ImplicitArgs(0), Name(name), Proto(NULL) {}
|
||||
};
|
||||
|
||||
// VM frame layout:
|
||||
// VMFrame header
|
||||
// parameter stack - 16 byte boundary, 16 bytes each
|
||||
|
@ -829,7 +830,7 @@ class VMNativeFunction : public VMFunction
|
|||
{
|
||||
DECLARE_CLASS(VMNativeFunction, VMFunction);
|
||||
public:
|
||||
typedef int (*NativeCallType)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret);
|
||||
typedef int (*NativeCallType)(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);
|
||||
|
||||
VMNativeFunction() : NativeCall(NULL) { Native = true; }
|
||||
VMNativeFunction(NativeCallType call) : NativeCall(call) { Native = true; }
|
||||
|
@ -900,8 +901,8 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func);
|
|||
void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction *func);
|
||||
|
||||
// Use this in the prototype for a native function.
|
||||
#define VM_ARGS VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret
|
||||
#define VM_ARGS_NAMES stack, param, numparam, ret, numret
|
||||
#define VM_ARGS VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret
|
||||
#define VM_ARGS_NAMES stack, param, defaultparam, numparam, ret, numret
|
||||
|
||||
// Use these to collect the parameters in a native function.
|
||||
// variable name <x> at position <p>
|
||||
|
@ -924,6 +925,16 @@ 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 ASSERTINT(p) assert((p).Type == REGT_INT)
|
||||
#define ASSERTFLOAT(p) assert((p).Type == REGT_FLOAT)
|
||||
#define ASSERTSTRING(p) assert((p).Type == REGT_STRING)
|
||||
#define ASSERTOBJECT(p) assert((p).Type == REGT_POINTER && (p).atag == ATAG_OBJECT)
|
||||
#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_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
|
||||
#define PARAM_NAME_OPT_AT(p,x) FName x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x = ENamedName(param[p].i); } else
|
||||
|
@ -954,6 +965,20 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_OBJECT(x,type) ++paramnum; PARAM_OBJECT_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS(x,base) ++paramnum; PARAM_CLASS_AT(paramnum,x,base)
|
||||
|
||||
#define PARAM_INT_DEF(x) ++paramnum; PARAM_INT_DEF_AT(paramnum,x)
|
||||
#define PARAM_BOOL_DEF(x) ++paramnum; PARAM_BOOL_DEF_AT(paramnum,x)
|
||||
#define PARAM_NAME_DEF(x) ++paramnum; PARAM_NAME_DEF_AT(paramnum,x)
|
||||
#define PARAM_SOUND_DEF(x) ++paramnum; PARAM_SOUND_DEF_AT(paramnum,x)
|
||||
#define PARAM_COLOR_DEF(x) ++paramnum; PARAM_COLOR_DEF_AT(paramnum,x)
|
||||
#define PARAM_FLOAT_DEF(x) ++paramnum; PARAM_FLOAT_DEF_AT(paramnum,x)
|
||||
#define PARAM_ANGLE_DEF(x) ++paramnum; PARAM_ANGLE_DEF_AT(paramnum,x)
|
||||
#define PARAM_STRING_DEF(x) ++paramnum; PARAM_STRING_DEF_AT(paramnum,x)
|
||||
#define PARAM_STATE_DEF(x) ++paramnum; PARAM_STATE_DEF_AT(paramnum,x)
|
||||
#define PARAM_STATEINFO_DEF(x) ++paramnum; PARAM_STATEINFO_DEF_AT(paramnum,x)
|
||||
#define PARAM_POINTER_DEF(x,type) ++paramnum; PARAM_POINTER_DEF_AT(paramnum,x,type)
|
||||
#define PARAM_OBJECT_DEF(x,type) ++paramnum; PARAM_OBJECT_DEF_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS_DEF(x,base) ++paramnum; PARAM_CLASS_DEF_AT(paramnum,x,base)
|
||||
|
||||
#define PARAM_INT_OPT(x) ++paramnum; PARAM_INT_OPT_AT(paramnum,x)
|
||||
#define PARAM_BOOL_OPT(x) ++paramnum; PARAM_BOOL_OPT_AT(paramnum,x)
|
||||
#define PARAM_NAME_OPT(x) ++paramnum; PARAM_NAME_OPT_AT(paramnum,x)
|
||||
|
@ -968,7 +993,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
#define PARAM_OBJECT_OPT(x,type) ++paramnum; PARAM_OBJECT_OPT_AT(paramnum,x,type)
|
||||
#define PARAM_CLASS_OPT(x,base) ++paramnum; PARAM_CLASS_OPT_AT(paramnum,x,base)
|
||||
|
||||
typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/
|
||||
typedef int(*actionf_p)(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret);/*(VM_ARGS)*/
|
||||
|
||||
struct AFuncDesc
|
||||
{
|
||||
|
|
|
@ -188,13 +188,14 @@ void VMFillParams(VMValue *params, VMFrame *callee, int numparam)
|
|||
const VMRegisters calleereg(callee);
|
||||
|
||||
assert(calleefunc != NULL && !calleefunc->Native);
|
||||
assert(numparam == calleefunc->NumArgs);
|
||||
assert(numparam == calleefunc->NumArgs || ((int)calleefunc->Defaults.Size() == numparam));
|
||||
assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3);
|
||||
|
||||
regd = regf = regs = rega = 0;
|
||||
for (int i = 0; i < numparam; ++i)
|
||||
for (int i = 0; i < calleefunc->NumArgs; ++i)
|
||||
{
|
||||
VMValue &p = params[i];
|
||||
// get all actual parameters and fill the rest from the defaults.
|
||||
VMValue &p = i < numparam? params[i] : calleefunc->Defaults[i];
|
||||
if (p.Type < REGT_STRING)
|
||||
{
|
||||
if (p.Type == REGT_INT)
|
||||
|
|
|
@ -506,7 +506,7 @@ begin:
|
|||
FillReturns(reg, f, returns, pc+1, C);
|
||||
if (call->Native)
|
||||
{
|
||||
numret = static_cast<VMNativeFunction *>(call)->NativeCall(stack, reg.param + f->NumParam - B, B, returns, C);
|
||||
numret = static_cast<VMNativeFunction *>(call)->NativeCall(stack, reg.param + f->NumParam - B, call->Defaults, B, returns, C);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -550,7 +550,7 @@ begin:
|
|||
|
||||
if (call->Native)
|
||||
{
|
||||
return static_cast<VMNativeFunction *>(call)->NativeCall(stack, reg.param + f->NumParam - B, B, ret, numret);
|
||||
return static_cast<VMNativeFunction *>(call)->NativeCall(stack, reg.param + f->NumParam - B, call->Defaults, B, ret, numret);
|
||||
}
|
||||
else
|
||||
{ // FIXME: Not a true tail call
|
||||
|
|
|
@ -415,7 +415,7 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur
|
|||
{
|
||||
if (func->Native)
|
||||
{
|
||||
return static_cast<VMNativeFunction *>(func)->NativeCall(this, params, numparams, results, numresults);
|
||||
return static_cast<VMNativeFunction *>(func)->NativeCall(this, params, func->Defaults, numparams, results, numresults);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1952,6 +1952,7 @@ void ZCCCompiler::InitFunctions()
|
|||
TArray<PType *> rets(1);
|
||||
TArray<PType *> args;
|
||||
TArray<uint32_t> argflags;
|
||||
TArray<VMValue> argdefaults;
|
||||
TArray<FName> argnames;
|
||||
|
||||
for (auto c : Classes)
|
||||
|
@ -1961,6 +1962,7 @@ void ZCCCompiler::InitFunctions()
|
|||
rets.Clear();
|
||||
args.Clear();
|
||||
argflags.Clear();
|
||||
bool hasdefault = false;
|
||||
// For the time being, let's not allow overloading. This may be reconsidered later but really just adds an unnecessary amount of complexity here.
|
||||
if (AddTreeNode(f->Name, f, &c->TreeNodes, false))
|
||||
{
|
||||
|
@ -2018,36 +2020,96 @@ void ZCCCompiler::InitFunctions()
|
|||
}
|
||||
}
|
||||
SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags);
|
||||
argdefaults.Resize(argnames.Size());
|
||||
auto p = f->Params;
|
||||
if (p != nullptr)
|
||||
{
|
||||
do
|
||||
{
|
||||
VMValue vmval; // default is REGT_NIL which means 'no default value' here.
|
||||
if (p->Type != nullptr)
|
||||
{
|
||||
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
|
||||
int flags = 0;
|
||||
if (p->Flags & ZCC_In) flags |= VARF_In;
|
||||
if (p->Flags & ZCC_Out) flags |= VARF_Out;
|
||||
if (p->Default != nullptr)
|
||||
if ((type->IsA(RUNTIME_CLASS(PStruct))) || (flags & VARF_Out))
|
||||
{
|
||||
auto val = Simplify(p->Default, &c->Type()->Symbols, true);
|
||||
flags |= VARF_Optional;
|
||||
if (val->Operation != PEX_ConstValue)
|
||||
// 'out' parameters and all structs except vectors are passed by reference
|
||||
if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3))
|
||||
{
|
||||
Error(c->cls, "Default parameter %s is not constant in %s", FName(p->Name).GetChars(), FName(f->Name).GetChars());
|
||||
type = NewPointer(type);
|
||||
}
|
||||
// Todo: Store and handle the default value (native functions will discard it anyway but for scripted ones this should be done decently.)
|
||||
}
|
||||
if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3)
|
||||
{
|
||||
Error(p, "Invalid type %s for function parameter", type->DescriptiveName());
|
||||
}
|
||||
else if (p->Default != nullptr)
|
||||
{
|
||||
flags |= VARF_Optional;
|
||||
// The simplifier is not suited to convert the constant into something usable.
|
||||
// All it does is reduce the expression to a constant but we still got to do proper type checking and conversion.
|
||||
// It will also lose important type info about enums, once these get implemented
|
||||
// The code generator can do this properly for us.
|
||||
FxExpression *x = new FxTypeCast(ConvertNode(p->Default), type, false);
|
||||
FCompileContext ctx(c->Type(), false);
|
||||
x = x->Resolve(ctx);
|
||||
|
||||
if (x != nullptr)
|
||||
{
|
||||
if (!x->isConstant())
|
||||
{
|
||||
Error(p, "Default parameter %s is not constant in %s", FName(p->Name).GetChars(), FName(f->Name).GetChars());
|
||||
}
|
||||
else if (x->ValueType != type)
|
||||
{
|
||||
Error(p, "Default parameter %s could not be converted to target type %s", FName(p->Name).GetChars(), c->Type()->TypeName.GetChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
auto cnst = static_cast<FxConstant *>(x);
|
||||
hasdefault = true;
|
||||
switch (type->GetRegType())
|
||||
{
|
||||
case REGT_INT:
|
||||
vmval = cnst->GetValue().GetInt();
|
||||
break;
|
||||
|
||||
case REGT_FLOAT:
|
||||
vmval = cnst->GetValue().GetFloat();
|
||||
break;
|
||||
|
||||
case REGT_POINTER:
|
||||
if (type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
vmval = (DObject*)cnst->GetValue().GetPointer();
|
||||
else
|
||||
vmval = cnst->GetValue().GetPointer();
|
||||
break;
|
||||
|
||||
case REGT_STRING:
|
||||
vmval = cnst->GetValue().GetString();
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0 && "no valid type for constant");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x != nullptr) delete x;
|
||||
}
|
||||
// TBD: disallow certain types? For now, let everything pass that isn't an array.
|
||||
args.Push(type);
|
||||
argflags.Push(flags);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Push(nullptr);
|
||||
argflags.Push(0);
|
||||
}
|
||||
argdefaults.Push(vmval);
|
||||
p = static_cast<decltype(p)>(p->SiblingNext);
|
||||
} while (p != f->Params);
|
||||
}
|
||||
|
@ -2064,9 +2126,11 @@ void ZCCCompiler::InitFunctions()
|
|||
sym->Variants[0].Implementation = FunctionBuildList.AddFunction(sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (sym->Variants[0].Implementation != nullptr && hasdefault) // do not copy empty default lists, they only waste space and processing time.
|
||||
{
|
||||
sym->Variants[0].Implementation->Defaults = std::move(argdefaults);
|
||||
}
|
||||
// todo: Check inheritance.
|
||||
// todo: Process function bodies.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ class Actor : Thinker native
|
|||
native void A_NoBlocking();
|
||||
native void A_XScream();
|
||||
native void A_Look();
|
||||
native void A_Chase(state melee = "*", state missile = "none", int flags = 0);
|
||||
native void A_Chase(state melee = null, state missile = null, int flags = 0);
|
||||
native void A_FaceTarget(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0);
|
||||
native void A_FaceTracer(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0);
|
||||
native void A_FaceMaster(float max_turn = 0, float max_pitch = 270, float ang_offset = 0, float pitch_offset = 0, int flags = 0, float z_ofs = 0);
|
||||
|
@ -203,8 +203,8 @@ class Actor : Thinker native
|
|||
native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10);
|
||||
native state A_Jump(int chance = 256, state label, ...);
|
||||
native void A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, float spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0, int ptr = AAPTR_TARGET);
|
||||
native void A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class<Actor> missile = "", float Spawnheight = 32, float Spawnofs_xy = 0);
|
||||
native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, int aim = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0);
|
||||
native void A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0, int ptr = AAPTR_TARGET, class<Actor> missile = null, float Spawnheight = 32, float Spawnofs_xy = 0);
|
||||
native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = 0, color color2 = 0, int flags = 0, int aim = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0);
|
||||
native state A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT);
|
||||
native state A_JumpIfCloser(float distance, state label, bool noz = false);
|
||||
native state A_JumpIfTracerCloser(float distance, state label, bool noz = false);
|
||||
|
@ -217,8 +217,8 @@ class Actor : Thinker native
|
|||
native bool A_TakeInventory(class<Inventory> itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT);
|
||||
action native bool A_SpawnItem(class<Actor> itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false);
|
||||
native bool A_SpawnItemEx(class<Actor> itemtype, float xofs = 0, float yofs = 0, float zofs = 0, float xvel = 0, float yvel = 0, float zvel = 0, float angle = 0, int flags = 0, int failchance = 0, int tid=0);
|
||||
native void A_Print(string whattoprint, float time = 0, name fontname = "");
|
||||
native void A_PrintBold(string whattoprint, float time = 0, name fontname = "");
|
||||
native void A_Print(string whattoprint, float time = 0, name fontname = "none");
|
||||
native void A_PrintBold(string whattoprint, float time = 0, name fontname = "none");
|
||||
native void A_Log(string whattoprint);
|
||||
native void A_LogInt(int whattoprint);
|
||||
native void A_LogFloat(float whattoprint);
|
||||
|
@ -234,7 +234,7 @@ class Actor : Thinker native
|
|||
native state A_CheckSight(state label);
|
||||
native void A_ExtChase(bool usemelee, bool usemissile, bool playactive = true, bool nightmarefast = false);
|
||||
native void A_DropInventory(class<Inventory> itemtype);
|
||||
native void A_SetBlend(color color1, float alpha, int tics, color color2 = "");
|
||||
native void A_SetBlend(color color1, float alpha, int tics, color color2 = 0);
|
||||
deprecated native void A_ChangeFlag(string flagname, bool value);
|
||||
deprecated native state A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT);
|
||||
native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE);
|
||||
|
@ -247,8 +247,8 @@ class Actor : Thinker native
|
|||
native state A_CheckCeiling(state label);
|
||||
native state A_PlayerSkinCheck(state label);
|
||||
deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight);
|
||||
native state, bool A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT);
|
||||
native state, bool A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = "", float heightoffset = 0, float radiusoffset = 0, float pitch = 0);
|
||||
native state, bool A_Teleport(state teleportstate = null, class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT);
|
||||
native state, bool A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = null, float heightoffset = 0, float radiusoffset = 0, float pitch = 0);
|
||||
action native bool A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true);
|
||||
native void A_Weave(int xspeed, int yspeed, float xdist, float ydist);
|
||||
|
||||
|
@ -257,8 +257,8 @@ class Actor : Thinker native
|
|||
native bool A_GiveToTarget(class<Inventory> itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT);
|
||||
native bool A_TakeFromTarget(class<Inventory> itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT);
|
||||
native int A_RadiusGive(class<Inventory> itemtype, float distance, int flags, int amount = 0, class<Actor> filter = "None", name species = "None", float mindist = 0, int limit = 0);
|
||||
native state A_CheckSpecies(state jump, name species = "", int ptr = AAPTR_DEFAULT);
|
||||
native void A_CountdownArg(int argnum, state targstate = "");
|
||||
native state A_CheckSpecies(state jump, name species = 'none', int ptr = AAPTR_DEFAULT);
|
||||
native void A_CountdownArg(int argnum, state targstate = null);
|
||||
native void A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true);
|
||||
native void A_CustomComboAttack(class<Actor> missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);
|
||||
native void A_Burst(class<Actor> chunktype);
|
||||
|
@ -271,7 +271,7 @@ class Actor : Thinker native
|
|||
native void A_BarrelDestroy();
|
||||
native void A_QueueCorpse();
|
||||
native void A_DeQueueCorpse();
|
||||
native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = "");
|
||||
native void A_LookEx(int flags = 0, float minseedist = 0, float maxseedist = 0, float maxheardist = 0, float fov = 0, state label = null);
|
||||
native void A_ClearLastHeard();
|
||||
native void A_ClearTarget();
|
||||
native state A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT, float offsetforward = 0);
|
||||
|
@ -357,7 +357,7 @@ class Actor : Thinker native
|
|||
native void A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0);
|
||||
native void A_CopyFriendliness(int ptr_source = AAPTR_MASTER);
|
||||
|
||||
action native bool A_Overlay(int layer, state start = "", bool nooverride = false);
|
||||
action native bool A_Overlay(int layer, state start = null, bool nooverride = false);
|
||||
native void A_WeaponOffset(float wx = 0, float wy = 32, int flags = 0);
|
||||
action native void A_OverlayOffset(int layer = PSP_WEAPON, float wx = 0, float wy = 32, int flags = 0);
|
||||
action native void A_OverlayFlags(int layer, int flags, bool set);
|
||||
|
|
|
@ -42,10 +42,10 @@ class Inventory : Actor native
|
|||
class StateProvider : Inventory native
|
||||
{
|
||||
action native state A_JumpIfNoAmmo(state label);
|
||||
action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = "", sound MissSound = "");
|
||||
action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, float range = 0, class<Actor> missile = "", float Spawnheight = 32, float Spawnofs_xy = 0);
|
||||
action native void A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", float range = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = "");
|
||||
action native void A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, float range = 0, class<Actor> missile = null, float Spawnheight = 32, float Spawnofs_xy = 0);
|
||||
action native void A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, float spawnofs_xy = 0, float spawnheight = 0, int flags = 0, float pitch = 0);
|
||||
action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0);
|
||||
action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0, int spiraloffset = 270, int limit = 0);
|
||||
native void A_Light(int extralight);
|
||||
native void A_Light0();
|
||||
native void A_Light1();
|
||||
|
@ -71,10 +71,10 @@ class StateProvider : Inventory native
|
|||
native void A_BFGsound();
|
||||
action native void A_FireBFG();
|
||||
action native void A_FireOldBFG();
|
||||
native void A_ReFire(state flash = "");
|
||||
native void A_ReFire(state flash = null);
|
||||
native void A_ClearReFire();
|
||||
native void A_CheckReload();
|
||||
native void A_GunFlash(state flash = "", int flags = 0);
|
||||
native void A_GunFlash(state flash = null, int flags = 0);
|
||||
action native void A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class<Actor> pufftype = "BulletPuff", int flags = 0, float range = 0, float spread_xy = 2.8125, float spread_z = 0, float lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus");
|
||||
native state A_CheckForReload(int counter, state label, bool dontincrement = false);
|
||||
native void A_ResetReloadCounter();
|
||||
|
|
Loading…
Reference in a new issue