mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-29 15:32:54 +00:00
Use PField instead of PSymbolVariable for DECORATE expressions
- The type systems used by PField and FxExpression are completely incompatible, but I think I got the differences taken care of as far as ParseNativeVariable(), ParseUserVariable(), and FxClassMember are concerned. - Support for declaring native bool variables has been removed for the time being. It wasn't used anyway. - Removed PSymbolVariable.
This commit is contained in:
parent
0d1973a659
commit
2f7183b937
6 changed files with 83 additions and 121 deletions
|
@ -425,11 +425,22 @@ void DObject::SerializeUserVars(FArchive &arc)
|
||||||
|
|
||||||
while (it.NextPair(pair))
|
while (it.NextPair(pair))
|
||||||
{
|
{
|
||||||
PSymbolVariable *var = dyn_cast<PSymbolVariable>(pair->Value);
|
PField *var = dyn_cast<PField>(pair->Value);
|
||||||
if (var != NULL && var->bUserVar)
|
if (var != NULL && !(var->Flags & VARF_Native))
|
||||||
{
|
{
|
||||||
count = var->ValueType.Type == VAL_Array ? var->ValueType.size : 1;
|
PType *type = var->Type;
|
||||||
varloc = (int *)(reinterpret_cast<BYTE *>(this) + var->offset);
|
PArray *arraytype = dyn_cast<PArray>(type);
|
||||||
|
if (arraytype == NULL)
|
||||||
|
{
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = arraytype->ElementCount;
|
||||||
|
type = arraytype->ElementType;
|
||||||
|
}
|
||||||
|
assert(type == TypeSInt32);
|
||||||
|
varloc = (int *)(reinterpret_cast<BYTE *>(this) + var->Offset);
|
||||||
|
|
||||||
arc << var->SymbolName;
|
arc << var->SymbolName;
|
||||||
arc.WriteCount(count);
|
arc.WriteCount(count);
|
||||||
|
@ -450,13 +461,24 @@ void DObject::SerializeUserVars(FArchive &arc)
|
||||||
arc << varname;
|
arc << varname;
|
||||||
while (varname != NAME_None)
|
while (varname != NAME_None)
|
||||||
{
|
{
|
||||||
PSymbolVariable *var = dyn_cast<PSymbolVariable>(symt->FindSymbol(varname, true));
|
PField *var = dyn_cast<PField>(symt->FindSymbol(varname, true));
|
||||||
DWORD wanted = 0;
|
DWORD wanted = 0;
|
||||||
|
|
||||||
if (var != NULL && var->bUserVar)
|
if (var != NULL && !(var->Flags & VARF_Native))
|
||||||
{
|
{
|
||||||
wanted = var->ValueType.Type == VAL_Array ? var->ValueType.size : 1;
|
PType *type = var->Type;
|
||||||
varloc = (int *)(reinterpret_cast<BYTE *>(this) + var->offset);
|
PArray *arraytype = dyn_cast<PArray>(type);
|
||||||
|
if (arraytype != NULL)
|
||||||
|
{
|
||||||
|
wanted = arraytype->ElementCount;
|
||||||
|
type = arraytype->ElementType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wanted = 1;
|
||||||
|
}
|
||||||
|
assert(type == TypeSInt32);
|
||||||
|
varloc = (int *)(reinterpret_cast<BYTE *>(this) + var->Offset);
|
||||||
}
|
}
|
||||||
count = arc.ReadCount();
|
count = arc.ReadCount();
|
||||||
for (j = 0; j < MIN(wanted, count); ++j)
|
for (j = 0; j < MIN(wanted, count); ++j)
|
||||||
|
|
|
@ -2287,7 +2287,6 @@ CCMD(typetable)
|
||||||
|
|
||||||
IMPLEMENT_ABSTRACT_CLASS(PSymbol);
|
IMPLEMENT_ABSTRACT_CLASS(PSymbol);
|
||||||
IMPLEMENT_CLASS(PSymbolConst);
|
IMPLEMENT_CLASS(PSymbolConst);
|
||||||
IMPLEMENT_CLASS(PSymbolVariable);
|
|
||||||
IMPLEMENT_POINTY_CLASS(PSymbolVMFunction)
|
IMPLEMENT_POINTY_CLASS(PSymbolVMFunction)
|
||||||
DECLARE_POINTER(Function)
|
DECLARE_POINTER(Function)
|
||||||
END_POINTERS
|
END_POINTERS
|
||||||
|
|
|
@ -49,21 +49,6 @@ public:
|
||||||
PSymbolConst() : PSymbol(NAME_None) {}
|
PSymbolConst() : PSymbol(NAME_None) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// A variable ---------------------------------------------------------
|
|
||||||
|
|
||||||
class PSymbolVariable : public PSymbol
|
|
||||||
{
|
|
||||||
DECLARE_CLASS(PSymbolVariable, PSymbol);
|
|
||||||
public:
|
|
||||||
FExpressionType ValueType;
|
|
||||||
//int size;
|
|
||||||
intptr_t offset;
|
|
||||||
bool bUserVar;
|
|
||||||
|
|
||||||
PSymbolVariable(FName name) : PSymbol(name) {}
|
|
||||||
PSymbolVariable() : PSymbol(NAME_None) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// An action function -------------------------------------------------------
|
// An action function -------------------------------------------------------
|
||||||
|
|
||||||
struct FState;
|
struct FState;
|
||||||
|
|
|
@ -700,10 +700,10 @@ class FxClassMember : public FxExpression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FxExpression *classx;
|
FxExpression *classx;
|
||||||
PSymbolVariable *membervar;
|
PField *membervar;
|
||||||
bool AddressRequested;
|
bool AddressRequested;
|
||||||
|
|
||||||
FxClassMember(FxExpression*, PSymbolVariable*, const FScriptPosition&);
|
FxClassMember(FxExpression*, PField*, const FScriptPosition&);
|
||||||
~FxClassMember();
|
~FxClassMember();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
void RequestAddress();
|
void RequestAddress();
|
||||||
|
|
|
@ -2261,10 +2261,10 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as class constant\n", Identifier.GetChars());
|
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as class constant\n", Identifier.GetChars());
|
||||||
newex = FxConstant::MakeConstant(sym, ScriptPosition);
|
newex = FxConstant::MakeConstant(sym, ScriptPosition);
|
||||||
}
|
}
|
||||||
else if (sym->IsKindOf(RUNTIME_CLASS(PSymbolVariable)))
|
else if (sym->IsKindOf(RUNTIME_CLASS(PField)))
|
||||||
{
|
{
|
||||||
PSymbolVariable *vsym = static_cast<PSymbolVariable*>(sym);
|
PField *vsym = static_cast<PField*>(sym);
|
||||||
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as member variable, index %d\n", Identifier.GetChars(), vsym->offset);
|
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as member variable, index %d\n", Identifier.GetChars(), vsym->Offset);
|
||||||
newex = new FxClassMember((new FxSelf(ScriptPosition))->Resolve(ctx), vsym, ScriptPosition);
|
newex = new FxClassMember((new FxSelf(ScriptPosition))->Resolve(ctx), vsym, ScriptPosition);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2370,7 +2370,7 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FxClassMember::FxClassMember(FxExpression *x, PSymbolVariable* mem, const FScriptPosition &pos)
|
FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition &pos)
|
||||||
: FxExpression(pos)
|
: FxExpression(pos)
|
||||||
{
|
{
|
||||||
classx = x;
|
classx = x;
|
||||||
|
@ -2418,30 +2418,35 @@ FxExpression *FxClassMember::Resolve(FCompileContext &ctx)
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
switch (membervar->ValueType.Type)
|
PType *type = membervar->Type;
|
||||||
|
PArray *arraytype = dyn_cast<PArray>(type);
|
||||||
|
|
||||||
|
if (arraytype != NULL)
|
||||||
|
{
|
||||||
|
type = arraytype->ElementType;
|
||||||
|
}
|
||||||
|
if (type->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||||
|
{
|
||||||
|
ValueType = VAL_Object;
|
||||||
|
}
|
||||||
|
else if (type->IsKindOf(RUNTIME_CLASS(PInt)))
|
||||||
{
|
{
|
||||||
case VAL_Int:
|
|
||||||
case VAL_Bool:
|
|
||||||
ValueType = VAL_Int;
|
ValueType = VAL_Int;
|
||||||
break;
|
}
|
||||||
|
else if (type->IsKindOf(RUNTIME_CLASS(PFloat)))
|
||||||
case VAL_Float:
|
{
|
||||||
case VAL_Fixed:
|
|
||||||
case VAL_Angle:
|
|
||||||
ValueType = VAL_Float;
|
ValueType = VAL_Float;
|
||||||
break;
|
}
|
||||||
|
else
|
||||||
case VAL_Object:
|
{
|
||||||
case VAL_Class:
|
|
||||||
case VAL_Array:
|
|
||||||
ValueType = membervar->ValueType;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ScriptPosition.Message(MSG_ERROR, "Invalid type for member variable %s", membervar->SymbolName.GetChars());
|
ScriptPosition.Message(MSG_ERROR, "Invalid type for member variable %s", membervar->SymbolName.GetChars());
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (arraytype != NULL)
|
||||||
|
{
|
||||||
|
ValueType.MakeArray(arraytype->ElementCount);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2452,17 +2457,17 @@ ExpEmit FxClassMember::Emit(VMFunctionBuilder *build)
|
||||||
|
|
||||||
if (AddressRequested)
|
if (AddressRequested)
|
||||||
{
|
{
|
||||||
if (membervar->offset == 0)
|
if (membervar->Offset == 0)
|
||||||
{
|
{
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
obj.Free(build);
|
obj.Free(build);
|
||||||
ExpEmit out(build, REGT_POINTER);
|
ExpEmit out(build, REGT_POINTER);
|
||||||
build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, build->GetConstantInt((int)membervar->offset));
|
build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, build->GetConstantInt((int)membervar->Offset));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offsetreg = build->GetConstantInt((int)membervar->offset);
|
int offsetreg = build->GetConstantInt((int)membervar->Offset);
|
||||||
ExpEmit loc, tmp;
|
ExpEmit loc, tmp;
|
||||||
|
|
||||||
if (obj.Konst)
|
if (obj.Konst)
|
||||||
|
@ -2476,53 +2481,8 @@ ExpEmit FxClassMember::Emit(VMFunctionBuilder *build)
|
||||||
obj = newobj;
|
obj = newobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (membervar->ValueType.Type)
|
loc = ExpEmit(build, membervar->Type->GetRegType());
|
||||||
{
|
build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, obj.RegNum, offsetreg);
|
||||||
case VAL_Int:
|
|
||||||
case VAL_Sound:
|
|
||||||
case VAL_Name:
|
|
||||||
case VAL_Color:
|
|
||||||
loc = ExpEmit(build, REGT_INT);
|
|
||||||
build->Emit(OP_LW, loc.RegNum, obj.RegNum, offsetreg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VAL_Bool:
|
|
||||||
loc = ExpEmit(build, REGT_INT);
|
|
||||||
// Some implementations have 1 byte bools, and others have
|
|
||||||
// 4 byte bools. For all I know, there might be some with
|
|
||||||
// 2 byte bools, too.
|
|
||||||
build->Emit((sizeof(bool) == 1 ? OP_LBU : sizeof(bool) == 2 ? OP_LHU : OP_LW),
|
|
||||||
loc.RegNum, obj.RegNum, offsetreg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VAL_Float:
|
|
||||||
loc = ExpEmit(build, REGT_FLOAT);
|
|
||||||
build->Emit(OP_LDP, loc.RegNum, obj.RegNum, offsetreg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VAL_Fixed:
|
|
||||||
loc = ExpEmit(build, REGT_FLOAT);
|
|
||||||
build->Emit(OP_LX, loc.RegNum, obj.RegNum, offsetreg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VAL_Angle:
|
|
||||||
loc = ExpEmit(build, REGT_FLOAT);
|
|
||||||
tmp = ExpEmit(build, REGT_INT);
|
|
||||||
build->Emit(OP_LW, tmp.RegNum, obj.RegNum, offsetreg);
|
|
||||||
build->Emit(OP_CAST, loc.RegNum, tmp.RegNum, CAST_I2F);
|
|
||||||
build->Emit(OP_MULF_RK, loc.RegNum, loc.RegNum, build->GetConstantFloat(90.0 / ANGLE_90));
|
|
||||||
tmp.Free(build);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VAL_Object:
|
|
||||||
case VAL_Class:
|
|
||||||
loc = ExpEmit(build, REGT_POINTER);
|
|
||||||
build->Emit(OP_LO, loc.RegNum, obj.RegNum, offsetreg);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
obj.Free(build);
|
obj.Free(build);
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,7 +288,7 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
|
||||||
|
|
||||||
static void ParseNativeVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
|
static void ParseNativeVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
|
||||||
{
|
{
|
||||||
FExpressionType valuetype;
|
PType *valuetype;
|
||||||
|
|
||||||
if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
|
if (sc.LumpNum == -1 || Wads.GetLumpFile(sc.LumpNum) > 0)
|
||||||
{
|
{
|
||||||
|
@ -301,27 +301,23 @@ static void ParseNativeVariable (FScanner &sc, PSymbolTable *symt, PClassActor *
|
||||||
switch (sc.TokenType)
|
switch (sc.TokenType)
|
||||||
{
|
{
|
||||||
case TK_Int:
|
case TK_Int:
|
||||||
valuetype = VAL_Int;
|
valuetype = TypeSInt32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TK_Float:
|
case TK_Float:
|
||||||
valuetype = VAL_Float;
|
valuetype = TypeFloat64;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TK_Angle_t:
|
case TK_Angle_t:
|
||||||
valuetype = VAL_Angle;
|
valuetype = TypeAngle;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TK_Fixed_t:
|
case TK_Fixed_t:
|
||||||
valuetype = VAL_Fixed;
|
valuetype = TypeFixed;
|
||||||
break;
|
|
||||||
|
|
||||||
case TK_Bool:
|
|
||||||
valuetype = VAL_Bool;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TK_Identifier:
|
case TK_Identifier:
|
||||||
valuetype = VAL_Object;
|
valuetype = NULL;
|
||||||
// Todo: Object type
|
// Todo: Object type
|
||||||
sc.ScriptError("Object type variables not implemented yet!");
|
sc.ScriptError("Object type variables not implemented yet!");
|
||||||
break;
|
break;
|
||||||
|
@ -343,7 +339,7 @@ static void ParseNativeVariable (FScanner &sc, PSymbolTable *symt, PClassActor *
|
||||||
int maxelems = static_cast<FxConstant *>(expr)->GetValue().GetInt();
|
int maxelems = static_cast<FxConstant *>(expr)->GetValue().GetInt();
|
||||||
delete expr;
|
delete expr;
|
||||||
sc.MustGetToken(']');
|
sc.MustGetToken(']');
|
||||||
valuetype.MakeArray(maxelems);
|
valuetype = NewArray(valuetype, maxelems);
|
||||||
}
|
}
|
||||||
sc.MustGetToken(';');
|
sc.MustGetToken(';');
|
||||||
|
|
||||||
|
@ -353,18 +349,20 @@ static void ParseNativeVariable (FScanner &sc, PSymbolTable *symt, PClassActor *
|
||||||
sc.ScriptError("Unknown native variable '%s'", symname.GetChars());
|
sc.ScriptError("Unknown native variable '%s'", symname.GetChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
PSymbolVariable *sym = new PSymbolVariable(symname);
|
PField *sym = new PField(symname, valuetype, VARF_Native);
|
||||||
sym->offset = vi->address; // todo
|
sym->Offset = (unsigned)vi->address; // todo
|
||||||
sym->ValueType = valuetype;
|
|
||||||
sym->bUserVar = false;
|
|
||||||
|
|
||||||
if (symt->AddSymbol (sym) == NULL)
|
if (symt->AddSymbol(sym) == NULL)
|
||||||
{
|
{
|
||||||
delete sym;
|
delete sym;
|
||||||
sc.ScriptMessage ("'%s' is already defined in '%s'.",
|
sc.ScriptMessage ("'%s' is already defined in '%s'.",
|
||||||
symname.GetChars(), cls? cls->TypeName.GetChars() : "Global");
|
symname.GetChars(), cls? cls->TypeName.GetChars() : "Global");
|
||||||
FScriptPosition::ErrorCounter++;
|
FScriptPosition::ErrorCounter++;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cls->Fields.Push(sym);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -377,7 +375,8 @@ static void ParseNativeVariable (FScanner &sc, PSymbolTable *symt, PClassActor *
|
||||||
|
|
||||||
static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
|
static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
|
||||||
{
|
{
|
||||||
FExpressionType valuetype;
|
PType *type;
|
||||||
|
int maxelems = 1;
|
||||||
|
|
||||||
// Only non-native classes may have user variables.
|
// Only non-native classes may have user variables.
|
||||||
if (!cls->bRuntimeClass)
|
if (!cls->bRuntimeClass)
|
||||||
|
@ -392,7 +391,7 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl
|
||||||
sc.ScriptMessage("User variables must be of type int");
|
sc.ScriptMessage("User variables must be of type int");
|
||||||
FScriptPosition::ErrorCounter++;
|
FScriptPosition::ErrorCounter++;
|
||||||
}
|
}
|
||||||
valuetype = VAL_Int;
|
type = TypeSInt32;
|
||||||
|
|
||||||
sc.MustGetToken(TK_Identifier);
|
sc.MustGetToken(TK_Identifier);
|
||||||
// For now, restrict user variables to those that begin with "user_" to guarantee
|
// For now, restrict user variables to those that begin with "user_" to guarantee
|
||||||
|
@ -407,7 +406,6 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl
|
||||||
if (sc.CheckToken('['))
|
if (sc.CheckToken('['))
|
||||||
{
|
{
|
||||||
FxExpression *expr = ParseExpression(sc, cls);
|
FxExpression *expr = ParseExpression(sc, cls);
|
||||||
int maxelems;
|
|
||||||
if (!expr->isConstant())
|
if (!expr->isConstant())
|
||||||
{
|
{
|
||||||
sc.ScriptMessage("Array size must be a constant");
|
sc.ScriptMessage("Array size must be a constant");
|
||||||
|
@ -425,14 +423,12 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl
|
||||||
FScriptPosition::ErrorCounter++;
|
FScriptPosition::ErrorCounter++;
|
||||||
maxelems = 1;
|
maxelems = 1;
|
||||||
}
|
}
|
||||||
valuetype.MakeArray(maxelems);
|
type = NewArray(type, maxelems);
|
||||||
}
|
}
|
||||||
sc.MustGetToken(';');
|
sc.MustGetToken(';');
|
||||||
|
|
||||||
PSymbolVariable *sym = new PSymbolVariable(symname);
|
PField *sym = new PField(symname, type, 0);
|
||||||
sym->offset = cls->Extend(sizeof(int) * (valuetype.Type == VAL_Array ? valuetype.size : 1));
|
sym->Offset = cls->Extend(sizeof(int) * maxelems);
|
||||||
sym->ValueType = valuetype;
|
|
||||||
sym->bUserVar = true;
|
|
||||||
if (symt->AddSymbol(sym) == NULL)
|
if (symt->AddSymbol(sym) == NULL)
|
||||||
{
|
{
|
||||||
delete sym;
|
delete sym;
|
||||||
|
|
Loading…
Reference in a new issue