mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-14 08:30:50 +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
|
@ -199,6 +199,7 @@ END_POINTERS
|
||||||
PType::PType()
|
PType::PType()
|
||||||
: Size(0), Align(1), HashNext(NULL)
|
: Size(0), Align(1), HashNext(NULL)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Type";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -210,6 +211,7 @@ PType::PType()
|
||||||
PType::PType(unsigned int size, unsigned int align)
|
PType::PType(unsigned int size, unsigned int align)
|
||||||
: Size(size), Align(align), HashNext(NULL)
|
: Size(size), Align(align), HashNext(NULL)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Type";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -533,6 +535,17 @@ void PType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
|
||||||
id2 = 0;
|
id2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PType :: GetTypeIDs
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
const char *PType::DescriptiveName() const
|
||||||
|
{
|
||||||
|
return mDescriptiveName.GetChars();
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// PType :: StaticInit STATIC
|
// PType :: StaticInit STATIC
|
||||||
|
@ -649,6 +662,7 @@ PBasicType::PBasicType()
|
||||||
PBasicType::PBasicType(unsigned int size, unsigned int align)
|
PBasicType::PBasicType(unsigned int size, unsigned int align)
|
||||||
: PType(size, align)
|
: PType(size, align)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "BasicType";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PCompoundType **********************************************************/
|
/* PCompoundType **********************************************************/
|
||||||
|
@ -714,6 +728,7 @@ IMPLEMENT_CLASS(PInt)
|
||||||
PInt::PInt()
|
PInt::PInt()
|
||||||
: PBasicType(4, 4), Unsigned(false)
|
: PBasicType(4, 4), Unsigned(false)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "SInt32";
|
||||||
Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, -0x7FFFFFFF - 1));
|
Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, -0x7FFFFFFF - 1));
|
||||||
Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, 0x7FFFFFFF));
|
Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, 0x7FFFFFFF));
|
||||||
}
|
}
|
||||||
|
@ -727,6 +742,8 @@ PInt::PInt()
|
||||||
PInt::PInt(unsigned int size, bool unsign)
|
PInt::PInt(unsigned int size, bool unsign)
|
||||||
: PBasicType(size, size), Unsigned(unsign)
|
: PBasicType(size, size), Unsigned(unsign)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName.Format("%cInt%d", unsign? 'U':'S', size);
|
||||||
|
|
||||||
MemberOnly = (size < 4);
|
MemberOnly = (size < 4);
|
||||||
if (!unsign)
|
if (!unsign)
|
||||||
{
|
{
|
||||||
|
@ -981,6 +998,8 @@ IMPLEMENT_CLASS(PBool)
|
||||||
PBool::PBool()
|
PBool::PBool()
|
||||||
: PInt(sizeof(bool), true)
|
: PInt(sizeof(bool), true)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Bool";
|
||||||
|
MemberOnly = false;
|
||||||
// Override the default max set by PInt's constructor
|
// Override the default max set by PInt's constructor
|
||||||
PSymbolConstNumeric *maxsym = static_cast<PSymbolConstNumeric *>(Symbols.FindSymbol(NAME_Max, false));
|
PSymbolConstNumeric *maxsym = static_cast<PSymbolConstNumeric *>(Symbols.FindSymbol(NAME_Max, false));
|
||||||
assert(maxsym != NULL && maxsym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric)));
|
assert(maxsym != NULL && maxsym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric)));
|
||||||
|
@ -1000,6 +1019,7 @@ IMPLEMENT_CLASS(PFloat)
|
||||||
PFloat::PFloat()
|
PFloat::PFloat()
|
||||||
: PBasicType(8, 8)
|
: PBasicType(8, 8)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Float";
|
||||||
SetDoubleSymbols();
|
SetDoubleSymbols();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1012,6 +1032,7 @@ PFloat::PFloat()
|
||||||
PFloat::PFloat(unsigned int size)
|
PFloat::PFloat(unsigned int size)
|
||||||
: PBasicType(size, size)
|
: PBasicType(size, size)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName.Format("Float%d", size);
|
||||||
if (size == 8)
|
if (size == 8)
|
||||||
{
|
{
|
||||||
SetDoubleSymbols();
|
SetDoubleSymbols();
|
||||||
|
@ -1274,6 +1295,7 @@ IMPLEMENT_CLASS(PString)
|
||||||
PString::PString()
|
PString::PString()
|
||||||
: PBasicType(sizeof(FString), __alignof(FString))
|
: PBasicType(sizeof(FString), __alignof(FString))
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "String";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1376,6 +1398,7 @@ IMPLEMENT_CLASS(PName)
|
||||||
PName::PName()
|
PName::PName()
|
||||||
: PInt(sizeof(FName), true)
|
: PInt(sizeof(FName), true)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Name";
|
||||||
assert(sizeof(FName) == __alignof(FName));
|
assert(sizeof(FName) == __alignof(FName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1425,6 +1448,7 @@ IMPLEMENT_CLASS(PSound)
|
||||||
PSound::PSound()
|
PSound::PSound()
|
||||||
: PInt(sizeof(FSoundID), true)
|
: PInt(sizeof(FSoundID), true)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Sound";
|
||||||
assert(sizeof(FSoundID) == __alignof(FSoundID));
|
assert(sizeof(FSoundID) == __alignof(FSoundID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1474,6 +1498,7 @@ IMPLEMENT_CLASS(PColor)
|
||||||
PColor::PColor()
|
PColor::PColor()
|
||||||
: PInt(sizeof(PalEntry), true)
|
: PInt(sizeof(PalEntry), true)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Color";
|
||||||
assert(sizeof(PalEntry) == __alignof(PalEntry));
|
assert(sizeof(PalEntry) == __alignof(PalEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1490,6 +1515,7 @@ IMPLEMENT_CLASS(PStatePointer)
|
||||||
PStatePointer::PStatePointer()
|
PStatePointer::PStatePointer()
|
||||||
: PBasicType(sizeof(FState *), __alignof(FState *))
|
: PBasicType(sizeof(FState *), __alignof(FState *))
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "State";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1564,6 +1590,7 @@ END_POINTERS
|
||||||
PPointer::PPointer()
|
PPointer::PPointer()
|
||||||
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL)
|
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(NULL)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Pointer";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1575,6 +1602,7 @@ PPointer::PPointer()
|
||||||
PPointer::PPointer(PType *pointsat)
|
PPointer::PPointer(PType *pointsat)
|
||||||
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(pointsat)
|
: PBasicType(sizeof(void *), __alignof(void *)), PointedType(pointsat)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName.Format("Pointer<%s>", pointsat->DescriptiveName());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1708,6 +1736,7 @@ END_POINTERS
|
||||||
PClassPointer::PClassPointer()
|
PClassPointer::PClassPointer()
|
||||||
: PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(NULL)
|
: PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(NULL)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "ClassPointer";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1719,6 +1748,7 @@ PClassPointer::PClassPointer()
|
||||||
PClassPointer::PClassPointer(PClass *restrict)
|
PClassPointer::PClassPointer(PClass *restrict)
|
||||||
: PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(restrict)
|
: PPointer(RUNTIME_CLASS(PClass)), ClassRestriction(restrict)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName.Format("ClassPointer<%s>", restrict->TypeName.GetChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1784,6 +1814,7 @@ END_POINTERS
|
||||||
PEnum::PEnum()
|
PEnum::PEnum()
|
||||||
: ValueType(NULL)
|
: ValueType(NULL)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Enum";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1795,6 +1826,7 @@ PEnum::PEnum()
|
||||||
PEnum::PEnum(FName name, PTypeBase *outer)
|
PEnum::PEnum(FName name, PTypeBase *outer)
|
||||||
: PNamedType(name, outer), ValueType(NULL)
|
: PNamedType(name, outer), ValueType(NULL)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName.Format("Enum<%s>", name.GetChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1833,6 +1865,7 @@ END_POINTERS
|
||||||
PArray::PArray()
|
PArray::PArray()
|
||||||
: ElementType(NULL), ElementCount(0)
|
: ElementType(NULL), ElementCount(0)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Array";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1844,6 +1877,8 @@ PArray::PArray()
|
||||||
PArray::PArray(PType *etype, unsigned int ecount)
|
PArray::PArray(PType *etype, unsigned int ecount)
|
||||||
: ElementType(etype), ElementCount(ecount)
|
: ElementType(etype), ElementCount(ecount)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName.Format("Array<%s>[%d]", etype->DescriptiveName(), ecount);
|
||||||
|
|
||||||
Align = etype->Align;
|
Align = etype->Align;
|
||||||
// Since we are concatenating elements together, the element size should
|
// Since we are concatenating elements together, the element size should
|
||||||
// also be padded to the nearest alignment.
|
// also be padded to the nearest alignment.
|
||||||
|
@ -1975,6 +2010,7 @@ IMPLEMENT_CLASS(PVector)
|
||||||
PVector::PVector()
|
PVector::PVector()
|
||||||
: PArray(TypeFloat32, 3)
|
: PArray(TypeFloat32, 3)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Vector";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1986,6 +2022,7 @@ PVector::PVector()
|
||||||
PVector::PVector(unsigned int size)
|
PVector::PVector(unsigned int size)
|
||||||
: PArray(TypeFloat32, size)
|
: PArray(TypeFloat32, size)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName.Format("Vector<%d>", size);
|
||||||
assert(size >= 2 && size <= 4);
|
assert(size >= 2 && size <= 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2025,6 +2062,7 @@ END_POINTERS
|
||||||
PDynArray::PDynArray()
|
PDynArray::PDynArray()
|
||||||
: ElementType(NULL)
|
: ElementType(NULL)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "DynArray";
|
||||||
Size = sizeof(FArray);
|
Size = sizeof(FArray);
|
||||||
Align = __alignof(FArray);
|
Align = __alignof(FArray);
|
||||||
}
|
}
|
||||||
|
@ -2038,6 +2076,7 @@ PDynArray::PDynArray()
|
||||||
PDynArray::PDynArray(PType *etype)
|
PDynArray::PDynArray(PType *etype)
|
||||||
: ElementType(etype)
|
: ElementType(etype)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName.Format("DynArray<%s>", etype->DescriptiveName());
|
||||||
Size = sizeof(FArray);
|
Size = sizeof(FArray);
|
||||||
Align = __alignof(FArray);
|
Align = __alignof(FArray);
|
||||||
}
|
}
|
||||||
|
@ -2105,6 +2144,7 @@ END_POINTERS
|
||||||
PMap::PMap()
|
PMap::PMap()
|
||||||
: KeyType(NULL), ValueType(NULL)
|
: KeyType(NULL), ValueType(NULL)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Map";
|
||||||
Size = sizeof(FMap);
|
Size = sizeof(FMap);
|
||||||
Align = __alignof(FMap);
|
Align = __alignof(FMap);
|
||||||
}
|
}
|
||||||
|
@ -2118,6 +2158,7 @@ PMap::PMap()
|
||||||
PMap::PMap(PType *keytype, PType *valtype)
|
PMap::PMap(PType *keytype, PType *valtype)
|
||||||
: KeyType(keytype), ValueType(valtype)
|
: KeyType(keytype), ValueType(valtype)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName.Format("Map<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName());
|
||||||
Size = sizeof(FMap);
|
Size = sizeof(FMap);
|
||||||
Align = __alignof(FMap);
|
Align = __alignof(FMap);
|
||||||
}
|
}
|
||||||
|
@ -2181,6 +2222,7 @@ IMPLEMENT_CLASS(PStruct)
|
||||||
|
|
||||||
PStruct::PStruct()
|
PStruct::PStruct()
|
||||||
{
|
{
|
||||||
|
mDescriptiveName = "Struct";
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2192,6 +2234,7 @@ PStruct::PStruct()
|
||||||
PStruct::PStruct(FName name, PTypeBase *outer)
|
PStruct::PStruct(FName name, PTypeBase *outer)
|
||||||
: PNamedType(name, outer)
|
: PNamedType(name, outer)
|
||||||
{
|
{
|
||||||
|
mDescriptiveName.Format("Struct<%s>", name.GetChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2804,6 +2847,7 @@ PClass::PClass()
|
||||||
Defaults = NULL;
|
Defaults = NULL;
|
||||||
bRuntimeClass = false;
|
bRuntimeClass = false;
|
||||||
ConstructNative = NULL;
|
ConstructNative = NULL;
|
||||||
|
mDescriptiveName = "Class";
|
||||||
|
|
||||||
PClass::AllClasses.Push(this);
|
PClass::AllClasses.Push(this);
|
||||||
}
|
}
|
||||||
|
@ -2896,6 +2940,7 @@ void ClassReg::SetupClass(PClass *cls)
|
||||||
cls->Size = SizeOf;
|
cls->Size = SizeOf;
|
||||||
cls->Pointers = Pointers;
|
cls->Pointers = Pointers;
|
||||||
cls->ConstructNative = ConstructNative;
|
cls->ConstructNative = ConstructNative;
|
||||||
|
cls->mDescriptiveName.Format("Class<%s>", cls->TypeName.GetChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -3108,6 +3153,7 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
|
||||||
type->TypeName = name;
|
type->TypeName = name;
|
||||||
type->Size = size;
|
type->Size = size;
|
||||||
type->bRuntimeClass = true;
|
type->bRuntimeClass = true;
|
||||||
|
type->mDescriptiveName.Format("Class<%s>", name.GetChars());
|
||||||
Derive(type);
|
Derive(type);
|
||||||
DeriveData(type);
|
DeriveData(type);
|
||||||
if (!notnew)
|
if (!notnew)
|
||||||
|
@ -3185,6 +3231,7 @@ PClass *PClass::FindClassTentative(FName name, bool fatal)
|
||||||
type->ConstructNative = ConstructNative;
|
type->ConstructNative = ConstructNative;
|
||||||
type->Size = TentativeClass;
|
type->Size = TentativeClass;
|
||||||
type->bRuntimeClass = true;
|
type->bRuntimeClass = true;
|
||||||
|
type->mDescriptiveName.Format("Class<%s>", name.GetChars());
|
||||||
type->Symbols.SetParentTable(&Symbols);
|
type->Symbols.SetParentTable(&Symbols);
|
||||||
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket);
|
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket);
|
||||||
return type;
|
return type;
|
||||||
|
|
|
@ -222,6 +222,7 @@ public:
|
||||||
PType *HashNext; // next type in this type table
|
PType *HashNext; // next type in this type table
|
||||||
PSymbolTable Symbols;
|
PSymbolTable Symbols;
|
||||||
bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument.
|
bool MemberOnly = false; // type may only be used as a struct/class member but not as a local variable or function argument.
|
||||||
|
FString mDescriptiveName;
|
||||||
|
|
||||||
PType();
|
PType();
|
||||||
PType(unsigned int size, unsigned int align);
|
PType(unsigned int size, unsigned int align);
|
||||||
|
@ -285,6 +286,8 @@ public:
|
||||||
// Get the type IDs used by IsMatch
|
// Get the type IDs used by IsMatch
|
||||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
|
||||||
|
const char *DescriptiveName() const;
|
||||||
|
|
||||||
size_t PropagateMark();
|
size_t PropagateMark();
|
||||||
|
|
||||||
static void StaticInit();
|
static void StaticInit();
|
||||||
|
@ -377,8 +380,12 @@ public:
|
||||||
PTypeBase *Outer; // object this type is contained within
|
PTypeBase *Outer; // object this type is contained within
|
||||||
FName TypeName; // this type's name
|
FName TypeName; // this type's name
|
||||||
|
|
||||||
PNamedType() : Outer(NULL) {}
|
PNamedType() : Outer(NULL) {
|
||||||
PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {}
|
mDescriptiveName = "NamedType";
|
||||||
|
}
|
||||||
|
PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {
|
||||||
|
mDescriptiveName = name.GetChars();
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
|
||||||
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
|
||||||
|
|
|
@ -595,9 +595,9 @@ ExpEmit FxIntCast::Emit(VMFunctionBuilder *build)
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FxFloatCast::FxFloatCast(FxExpression *x)
|
FxFloatCast::FxFloatCast(FxExpression *x)
|
||||||
: FxExpression(x->ScriptPosition)
|
: FxExpression(x->ScriptPosition)
|
||||||
{
|
{
|
||||||
basex=x;
|
basex = x;
|
||||||
ValueType = TypeFloat64;
|
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)
|
FxPlusSign::FxPlusSign(FxExpression *operand)
|
||||||
: FxExpression(operand->ScriptPosition)
|
: 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)
|
: FxExpression(x->ScriptPosition)
|
||||||
{
|
{
|
||||||
desttype = dtype;
|
ValueType = dtype;
|
||||||
|
desttype = dtype->ClassRestriction;
|
||||||
basex=x;
|
basex=x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5059,7 +5573,24 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
SAFE_RESOLVE(basex, ctx);
|
SAFE_RESOLVE(basex, ctx);
|
||||||
|
|
||||||
if (basex->ValueType != TypeName)
|
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 && basex->ValueType != TypeString)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Cannot convert to class type");
|
ScriptPosition.Message(MSG_ERROR, "Cannot convert to class type");
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -5097,6 +5628,10 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
if (basex->ValueType == TypeString)
|
||||||
|
{
|
||||||
|
basex = new FxNameCast(basex);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -411,6 +411,78 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
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
|
// FxSign
|
||||||
|
@ -1130,7 +1202,7 @@ class FxClassTypeCast : public FxExpression
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FxClassTypeCast(PClass *dtype, FxExpression *x);
|
FxClassTypeCast(PClassPointer *dtype, FxExpression *x);
|
||||||
~FxClassTypeCast();
|
~FxClassTypeCast();
|
||||||
FxExpression *Resolve(FCompileContext&);
|
FxExpression *Resolve(FCompileContext&);
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
|
|
@ -207,7 +207,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c
|
||||||
sc.SetEscape(true);
|
sc.SetEscape(true);
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
sc.SetEscape(false);
|
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
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -116,6 +116,12 @@ enum
|
||||||
CAST_P2S,
|
CAST_P2S,
|
||||||
CAST_S2I,
|
CAST_S2I,
|
||||||
CAST_S2F,
|
CAST_S2F,
|
||||||
|
CAST_S2N,
|
||||||
|
CAST_N2S,
|
||||||
|
CAST_S2Co,
|
||||||
|
CAST_S2So,
|
||||||
|
CAST_Co2S,
|
||||||
|
CAST_So2S,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Register types for VMParam
|
// Register types for VMParam
|
||||||
|
|
|
@ -379,6 +379,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
||||||
case CAST_I2F:
|
case CAST_I2F:
|
||||||
mode = MODE_AF | MODE_BI | MODE_CUNUSED;
|
mode = MODE_AF | MODE_BI | MODE_CUNUSED;
|
||||||
break;
|
break;
|
||||||
|
case CAST_Co2S:
|
||||||
|
case CAST_So2S:
|
||||||
|
case CAST_N2S:
|
||||||
case CAST_I2S:
|
case CAST_I2S:
|
||||||
mode = MODE_AS | MODE_BI | MODE_CUNUSED;
|
mode = MODE_AS | MODE_BI | MODE_CUNUSED;
|
||||||
break;
|
break;
|
||||||
|
@ -391,6 +394,9 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
||||||
case CAST_P2S:
|
case CAST_P2S:
|
||||||
mode = MODE_AS | MODE_BP | MODE_CUNUSED;
|
mode = MODE_AS | MODE_BP | MODE_CUNUSED;
|
||||||
break;
|
break;
|
||||||
|
case CAST_S2Co:
|
||||||
|
case CAST_S2So:
|
||||||
|
case CAST_S2N:
|
||||||
case CAST_S2I:
|
case CAST_S2I:
|
||||||
mode = MODE_AI | MODE_BS | MODE_CUNUSED;
|
mode = MODE_AI | MODE_BS | MODE_CUNUSED;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <v_video.h>
|
||||||
|
#include <s_sound.h>
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "xs_Float.h"
|
#include "xs_Float.h"
|
||||||
#include "math/cmath.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();
|
reg.f[a] = reg.s[b].ToDouble();
|
||||||
break;
|
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:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -885,7 +885,7 @@ ZCC_Expression *ZCCCompiler::SimplifyFunctionCall(ZCC_ExprFuncCall *callop, PSym
|
||||||
if (routelen < 0)
|
if (routelen < 0)
|
||||||
{
|
{
|
||||||
///FIXME: Need real type names
|
///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();
|
callop->ToErrorNode();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1341,7 +1341,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
||||||
//return TypeFloat32;
|
//return TypeFloat32;
|
||||||
case ZCC_Float64:
|
case ZCC_Float64:
|
||||||
retval = TypeFloat64;
|
retval = TypeFloat64;
|
||||||
return;
|
break;
|
||||||
|
|
||||||
case ZCC_String:
|
case ZCC_String:
|
||||||
retval = TypeString;
|
retval = TypeString;
|
||||||
|
@ -1433,7 +1433,7 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
||||||
}
|
}
|
||||||
if (retval != TypeError && retval->MemberOnly && !formember)
|
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 TypeError;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
@ -7,9 +7,7 @@ zscript/shared/morph.txt
|
||||||
zscript/shared/botstuff.txt
|
zscript/shared/botstuff.txt
|
||||||
zscript/shared/sharedmisc.txt
|
zscript/shared/sharedmisc.txt
|
||||||
zscript/shared/blood.txt
|
zscript/shared/blood.txt
|
||||||
zscript/shared/ice.txt
|
|
||||||
zscript/shared/debris.txt
|
zscript/shared/debris.txt
|
||||||
zscript/shared/specialspot.txt
|
|
||||||
zscript/shared/decal.txt
|
zscript/shared/decal.txt
|
||||||
zscript/shared/splashes.txt
|
zscript/shared/splashes.txt
|
||||||
zscript/shared/pickups.txt
|
zscript/shared/pickups.txt
|
||||||
|
@ -18,6 +16,7 @@ zscript/shared/spark.txt
|
||||||
zscript/shared/soundsequence.txt
|
zscript/shared/soundsequence.txt
|
||||||
zscript/shared/soundenvironment.txt
|
zscript/shared/soundenvironment.txt
|
||||||
zscript/shared/bridge.txt
|
zscript/shared/bridge.txt
|
||||||
|
zscript/shared/specialspot.txt
|
||||||
zscript/shared/teleport.txt
|
zscript/shared/teleport.txt
|
||||||
zscript/shared/camera.txt
|
zscript/shared/camera.txt
|
||||||
zscript/shared/movingcamera.txt
|
zscript/shared/movingcamera.txt
|
||||||
|
@ -28,6 +27,7 @@ zscript/shared/hatetarget.txt
|
||||||
zscript/shared/secrettrigger.txt
|
zscript/shared/secrettrigger.txt
|
||||||
zscript/shared/setcolor.txt
|
zscript/shared/setcolor.txt
|
||||||
zscript/shared/sectoraction.txt
|
zscript/shared/sectoraction.txt
|
||||||
|
zscript/shared/ice.txt
|
||||||
zscript/shared/dog.txt
|
zscript/shared/dog.txt
|
||||||
|
|
||||||
zscript/doom/doomplayer.txt
|
zscript/doom/doomplayer.txt
|
||||||
|
@ -59,5 +59,5 @@ zscript/doom/doomweapons.txt
|
||||||
zscript/doom/stealthmonsters.txt
|
zscript/doom/stealthmonsters.txt
|
||||||
zscript/doom/scriptedmarine.txt
|
zscript/doom/scriptedmarine.txt
|
||||||
|
|
||||||
//zscript/test1.txt
|
zscript/heretic/beast.txt
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue