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:
Randy Heit 2013-08-23 22:02:51 -05:00
parent 0d1973a659
commit 2f7183b937
6 changed files with 83 additions and 121 deletions

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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;
} }

View file

@ -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,10 +349,8 @@ 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)
{ {
@ -365,6 +359,10 @@ static void ParseNativeVariable (FScanner &sc, PSymbolTable *symt, PClassActor *
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;