mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-05-30 16:40:58 +00:00
- changed order of script files to match the old DECORATE list for easy comparison of the disassembly.
- added a descriptive name to all types for error messages. - added a generic type cast node to the code generator. - added a few more cast operations to the 'cast' VM instruction. - extended FxClassTypeCast to handle all possible input that can be cast to a class pointer, not just names.
This commit is contained in:
parent
2da52cedc9
commit
afd9347087
11 changed files with 723 additions and 15 deletions
|
@ -595,9 +595,9 @@ ExpEmit FxIntCast::Emit(VMFunctionBuilder *build)
|
|||
//==========================================================================
|
||||
|
||||
FxFloatCast::FxFloatCast(FxExpression *x)
|
||||
: FxExpression(x->ScriptPosition)
|
||||
: FxExpression(x->ScriptPosition)
|
||||
{
|
||||
basex=x;
|
||||
basex = x;
|
||||
ValueType = TypeFloat64;
|
||||
}
|
||||
|
||||
|
@ -685,6 +685,519 @@ ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxNameCast::FxNameCast(FxExpression *x)
|
||||
: FxExpression(x->ScriptPosition)
|
||||
{
|
||||
basex = x;
|
||||
ValueType = TypeName;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxNameCast::~FxNameCast()
|
||||
{
|
||||
SAFE_DELETE(basex);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxNameCast::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(basex, ctx);
|
||||
|
||||
if (basex->ValueType == TypeName)
|
||||
{
|
||||
FxExpression *x = basex;
|
||||
basex = NULL;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (basex->ValueType == TypeString)
|
||||
{
|
||||
if (basex->isConstant())
|
||||
{
|
||||
ExpVal constval = static_cast<FxConstant *>(basex)->GetValue();
|
||||
FxExpression *x = new FxConstant(constval.GetName(), ScriptPosition);
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to name");
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxNameCast::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit from = basex->Emit(build);
|
||||
assert(!from.Konst);
|
||||
assert(basex->ValueType == TypeString);
|
||||
from.Free(build);
|
||||
ExpEmit to(build, REGT_INT);
|
||||
build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_S2N);
|
||||
return to;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxStringCast::FxStringCast(FxExpression *x)
|
||||
: FxExpression(x->ScriptPosition)
|
||||
{
|
||||
basex = x;
|
||||
ValueType = TypeString;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxStringCast::~FxStringCast()
|
||||
{
|
||||
SAFE_DELETE(basex);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxStringCast::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(basex, ctx);
|
||||
|
||||
if (basex->ValueType == TypeString)
|
||||
{
|
||||
FxExpression *x = basex;
|
||||
basex = NULL;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (basex->ValueType == TypeName)
|
||||
{
|
||||
if (basex->isConstant())
|
||||
{
|
||||
ExpVal constval = static_cast<FxConstant *>(basex)->GetValue();
|
||||
FxExpression *x = new FxConstant(constval.GetString(), ScriptPosition);
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
else if (basex->ValueType == TypeSound)
|
||||
{
|
||||
if (basex->isConstant())
|
||||
{
|
||||
ExpVal constval = static_cast<FxConstant *>(basex)->GetValue();
|
||||
FxExpression *x = new FxConstant(S_sfx[constval.GetInt()].name, ScriptPosition);
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
// although it could be done, let's not convert colors back to strings.
|
||||
else
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to string");
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxStringCast::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit from = basex->Emit(build);
|
||||
assert(!from.Konst);
|
||||
|
||||
from.Free(build);
|
||||
ExpEmit to(build, REGT_STRING);
|
||||
if (ValueType == TypeName)
|
||||
{
|
||||
build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_N2S);
|
||||
}
|
||||
else if (ValueType == TypeSound)
|
||||
{
|
||||
build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_So2S);
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxColorCast::FxColorCast(FxExpression *x)
|
||||
: FxExpression(x->ScriptPosition)
|
||||
{
|
||||
basex = x;
|
||||
ValueType = TypeColor;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxColorCast::~FxColorCast()
|
||||
{
|
||||
SAFE_DELETE(basex);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxColorCast::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(basex, ctx);
|
||||
|
||||
if (basex->ValueType == TypeColor || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt))
|
||||
{
|
||||
FxExpression *x = basex;
|
||||
x->ValueType = TypeColor;
|
||||
basex = NULL;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (basex->ValueType == TypeString)
|
||||
{
|
||||
if (basex->isConstant())
|
||||
{
|
||||
ExpVal constval = static_cast<FxConstant *>(basex)->GetValue();
|
||||
FxExpression *x = new FxConstant(V_GetColor(nullptr, constval.GetString()), ScriptPosition);
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to color");
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxColorCast::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit from = basex->Emit(build);
|
||||
assert(!from.Konst);
|
||||
assert(basex->ValueType == TypeString);
|
||||
from.Free(build);
|
||||
ExpEmit to(build, REGT_INT);
|
||||
build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_S2Co);
|
||||
return to;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxSoundCast::FxSoundCast(FxExpression *x)
|
||||
: FxExpression(x->ScriptPosition)
|
||||
{
|
||||
basex = x;
|
||||
ValueType = TypeSound;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxSoundCast::~FxSoundCast()
|
||||
{
|
||||
SAFE_DELETE(basex);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxSoundCast::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(basex, ctx);
|
||||
|
||||
if (basex->ValueType == TypeSound || basex->ValueType->GetClass() == RUNTIME_CLASS(PInt))
|
||||
{
|
||||
FxExpression *x = basex;
|
||||
x->ValueType = TypeSound;
|
||||
basex = NULL;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (basex->ValueType == TypeString)
|
||||
{
|
||||
if (basex->isConstant())
|
||||
{
|
||||
ExpVal constval = static_cast<FxConstant *>(basex)->GetValue();
|
||||
FxExpression *x = new FxConstant(FSoundID(constval.GetString()), ScriptPosition);
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to sound");
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxSoundCast::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit from = basex->Emit(build);
|
||||
assert(!from.Konst);
|
||||
assert(basex->ValueType == TypeString);
|
||||
from.Free(build);
|
||||
ExpEmit to(build, REGT_INT);
|
||||
build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_S2So);
|
||||
return to;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// generic type cast operator
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxTypeCast::FxTypeCast(FxExpression *x, PType *type, bool nowarn)
|
||||
: FxExpression(x->ScriptPosition)
|
||||
{
|
||||
basex = x;
|
||||
ValueType = type;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxTypeCast::~FxTypeCast()
|
||||
{
|
||||
SAFE_DELETE(basex);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(basex, ctx);
|
||||
|
||||
// first deal with the simple types
|
||||
if (ValueType == TypeError || basex->ValueType == TypeError)
|
||||
{
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
else if (ValueType == TypeVoid) // this should never happen
|
||||
{
|
||||
goto errormsg;
|
||||
}
|
||||
else if (basex->ValueType == TypeVoid)
|
||||
{
|
||||
goto errormsg;
|
||||
}
|
||||
else if (basex->ValueType == ValueType)
|
||||
{
|
||||
// don't go through the entire list if the types are the same.
|
||||
goto basereturn;
|
||||
}
|
||||
else if (ValueType->GetRegType() == REGT_FLOAT)
|
||||
{
|
||||
FxExpression *x = new FxFloatCast(basex);
|
||||
x = x->Resolve(ctx);
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
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);
|
||||
x = x->Resolve(ctx);
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (ValueType == TypeBool)
|
||||
{
|
||||
FxExpression *x = new FxBoolCast(basex);
|
||||
x = x->Resolve(ctx);
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (ValueType == TypeString)
|
||||
{
|
||||
FxExpression *x = new FxStringCast(basex);
|
||||
x = x->Resolve(ctx);
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (ValueType == TypeName)
|
||||
{
|
||||
FxExpression *x = new FxNameCast(basex);
|
||||
x = x->Resolve(ctx);
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (ValueType == TypeSound)
|
||||
{
|
||||
FxExpression *x = new FxSoundCast(basex);
|
||||
x = x->Resolve(ctx);
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (ValueType == TypeColor)
|
||||
{
|
||||
FxExpression *x = new FxColorCast(basex);
|
||||
x = x->Resolve(ctx);
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
{
|
||||
FxExpression *x = new FxClassTypeCast(static_cast<PClassPointer*>(ValueType), basex);
|
||||
x = x->Resolve(ctx);
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
/* else if (ValueType->IsKindOf(RUNTIME_CLASS(PEnum)))
|
||||
{
|
||||
// this is not yet ready and does not get assigned to actual values.
|
||||
}
|
||||
*/
|
||||
else if (ValueType->IsKindOf(RUNTIME_CLASS(PClass))) // this should never happen because the VM doesn't handle plain class types - just pointers
|
||||
{
|
||||
if (basex->ValueType->IsKindOf(RUNTIME_CLASS(PClass)))
|
||||
{
|
||||
// class types are only compatible if the base type is a descendant of the result type.
|
||||
auto fromtype = static_cast<PClass *>(basex->ValueType);
|
||||
auto totype = static_cast<PClass *>(ValueType);
|
||||
if (fromtype->IsDescendantOf(totype)) goto basereturn;
|
||||
}
|
||||
}
|
||||
else if (ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
{
|
||||
// Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type.
|
||||
if (basex->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
{
|
||||
auto fromtype = static_cast<PPointer *>(basex->ValueType);
|
||||
auto totype = static_cast<PPointer *>(ValueType);
|
||||
if (fromtype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)) && totype->PointedType->IsKindOf(RUNTIME_CLASS(PClass)))
|
||||
{
|
||||
|
||||
auto fromcls = static_cast<PClass *>(fromtype->PointedType);
|
||||
auto tocls = static_cast<PClass *>(totype->PointedType);
|
||||
if (fromcls->IsDescendantOf(tocls)) goto basereturn;
|
||||
}
|
||||
}
|
||||
}
|
||||
// todo: pointers to class objects.
|
||||
// All other types are only compatible to themselves and have already been handled above by the equality check.
|
||||
// Anything that falls through here is not compatible and must print an error.
|
||||
|
||||
errormsg:
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert %s to %s", basex->ValueType->DescriptiveName(), ValueType->DescriptiveName());
|
||||
delete this;
|
||||
return nullptr;
|
||||
|
||||
basereturn:
|
||||
auto x = basex;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxTypeCast::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
assert(false);
|
||||
// This should never be reached
|
||||
return ExpEmit();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxPlusSign::FxPlusSign(FxExpression *operand)
|
||||
: FxExpression(operand->ScriptPosition)
|
||||
{
|
||||
|
@ -5030,10 +5543,11 @@ VMFunction *FxReturnStatement::GetDirectFunction()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxClassTypeCast::FxClassTypeCast(PClass *dtype, FxExpression *x)
|
||||
FxClassTypeCast::FxClassTypeCast(PClassPointer *dtype, FxExpression *x)
|
||||
: FxExpression(x->ScriptPosition)
|
||||
{
|
||||
desttype = dtype;
|
||||
ValueType = dtype;
|
||||
desttype = dtype->ClassRestriction;
|
||||
basex=x;
|
||||
}
|
||||
|
||||
|
@ -5058,8 +5572,25 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(basex, ctx);
|
||||
|
||||
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer))
|
||||
{
|
||||
auto to = static_cast<PClassPointer *>(ValueType);
|
||||
auto from = static_cast<PClassPointer *>(basex->ValueType);
|
||||
if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction))
|
||||
{
|
||||
basex->ValueType = to;
|
||||
auto x = basex;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert from %s to %s: Incompatible class types", from->ClassRestriction->TypeName.GetChars(), to->ClassRestriction->TypeName.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (basex->ValueType != TypeName)
|
||||
if (basex->ValueType != TypeName && basex->ValueType != TypeString)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to class type");
|
||||
delete this;
|
||||
|
@ -5097,6 +5628,10 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
|||
delete this;
|
||||
return x;
|
||||
}
|
||||
if (basex->ValueType == TypeString)
|
||||
{
|
||||
basex = new FxNameCast(basex);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -411,6 +411,78 @@ public:
|
|||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
class FxNameCast : public FxExpression
|
||||
{
|
||||
FxExpression *basex;
|
||||
|
||||
public:
|
||||
|
||||
FxNameCast(FxExpression *x);
|
||||
~FxNameCast();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
class FxStringCast : public FxExpression
|
||||
{
|
||||
FxExpression *basex;
|
||||
|
||||
public:
|
||||
|
||||
FxStringCast(FxExpression *x);
|
||||
~FxStringCast();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
class FxColorCast : public FxExpression
|
||||
{
|
||||
FxExpression *basex;
|
||||
|
||||
public:
|
||||
|
||||
FxColorCast(FxExpression *x);
|
||||
~FxColorCast();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
class FxSoundCast : public FxExpression
|
||||
{
|
||||
FxExpression *basex;
|
||||
|
||||
public:
|
||||
|
||||
FxSoundCast(FxExpression *x);
|
||||
~FxSoundCast();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxTypeCast
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxTypeCast : public FxExpression
|
||||
{
|
||||
FxExpression *basex;
|
||||
bool NoWarn;
|
||||
|
||||
public:
|
||||
|
||||
FxTypeCast(FxExpression *x, PType *type, bool nowarn);
|
||||
~FxTypeCast();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxSign
|
||||
|
@ -1130,7 +1202,7 @@ class FxClassTypeCast : public FxExpression
|
|||
|
||||
public:
|
||||
|
||||
FxClassTypeCast(PClass *dtype, FxExpression *x);
|
||||
FxClassTypeCast(PClassPointer *dtype, FxExpression *x);
|
||||
~FxClassTypeCast();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
|
|
|
@ -207,7 +207,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c
|
|||
sc.SetEscape(true);
|
||||
sc.MustGetString();
|
||||
sc.SetEscape(false);
|
||||
x = new FxClassTypeCast(static_cast<PClassPointer *>(type)->ClassRestriction, new FxConstant(FName(sc.String), sc));
|
||||
x = new FxClassTypeCast(static_cast<PClassPointer *>(type), new FxConstant(FName(sc.String), sc));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -116,6 +116,12 @@ enum
|
|||
CAST_P2S,
|
||||
CAST_S2I,
|
||||
CAST_S2F,
|
||||
CAST_S2N,
|
||||
CAST_N2S,
|
||||
CAST_S2Co,
|
||||
CAST_S2So,
|
||||
CAST_Co2S,
|
||||
CAST_So2S,
|
||||
};
|
||||
|
||||
// Register types for VMParam
|
||||
|
|
|
@ -379,6 +379,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
case CAST_I2F:
|
||||
mode = MODE_AF | MODE_BI | MODE_CUNUSED;
|
||||
break;
|
||||
case CAST_Co2S:
|
||||
case CAST_So2S:
|
||||
case CAST_N2S:
|
||||
case CAST_I2S:
|
||||
mode = MODE_AS | MODE_BI | MODE_CUNUSED;
|
||||
break;
|
||||
|
@ -391,6 +394,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
|||
case CAST_P2S:
|
||||
mode = MODE_AS | MODE_BP | MODE_CUNUSED;
|
||||
break;
|
||||
case CAST_S2Co:
|
||||
case CAST_S2So:
|
||||
case CAST_S2N:
|
||||
case CAST_S2I:
|
||||
mode = MODE_AI | MODE_BS | MODE_CUNUSED;
|
||||
break;
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <v_video.h>
|
||||
#include <s_sound.h>
|
||||
#include "vm.h"
|
||||
#include "xs_Float.h"
|
||||
#include "math/cmath.h"
|
||||
|
|
|
@ -1466,6 +1466,39 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c
|
|||
reg.f[a] = reg.s[b].ToDouble();
|
||||
break;
|
||||
|
||||
case CAST_S2N:
|
||||
ASSERTD(a); ASSERTS(b);
|
||||
reg.d[a] = FName(reg.s[b]);
|
||||
break;
|
||||
|
||||
case CAST_N2S:
|
||||
{
|
||||
ASSERTS(a); ASSERTD(b);
|
||||
FName name = FName(ENamedName(reg.d[b]));
|
||||
reg.s[a] = name.IsValidName() ? name.GetChars() : "";
|
||||
break;
|
||||
}
|
||||
|
||||
case CAST_S2Co:
|
||||
ASSERTD(a); ASSERTS(b);
|
||||
reg.d[a] = V_GetColor(NULL, reg.s[b]);
|
||||
break;
|
||||
|
||||
case CAST_Co2S:
|
||||
ASSERTS(a); ASSERTD(b);
|
||||
reg.s[a].Format("%02x %02x %02x", PalEntry(reg.d[b]).r, PalEntry(reg.d[b]).g, PalEntry(reg.d[b]).b);
|
||||
break;
|
||||
|
||||
case CAST_S2So:
|
||||
ASSERTD(a); ASSERTS(b);
|
||||
reg.d[a] = FSoundID(reg.s[b]);
|
||||
break;
|
||||
|
||||
case CAST_So2S:
|
||||
ASSERTS(a); ASSERTD(b);
|
||||
reg.s[a] = S_sfx[reg.d[b]].name;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
|
|
@ -885,7 +885,7 @@ ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSym
|
|||
if (routelen < 0)
|
||||
{
|
||||
///FIXME: Need real type names
|
||||
Error(callop, "Cannot convert type 1 to type 2");
|
||||
Error(callop, "Cannot convert %s to %s", parm->Value->Type->DescriptiveName(), dest->DescriptiveName());
|
||||
callop->ToErrorNode();
|
||||
}
|
||||
else
|
||||
|
@ -1341,7 +1341,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
|||
//return TypeFloat32;
|
||||
case ZCC_Float64:
|
||||
retval = TypeFloat64;
|
||||
return;
|
||||
break;
|
||||
|
||||
case ZCC_String:
|
||||
retval = TypeString;
|
||||
|
@ -1433,7 +1433,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
|||
}
|
||||
if (retval != TypeError && retval->MemberOnly && !formember)
|
||||
{
|
||||
Error(field, "Invalid type"); // fixme: Types need a descriptive name that can be output here.
|
||||
Error(field, "Invalid type %s", retval->DescriptiveName()); // fixme: Types need a descriptive name that can be output here.
|
||||
return TypeError;
|
||||
}
|
||||
return retval;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue