mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 07:11:54 +00:00
added class pointer casts. Due to grammar problems the type has to be put into parentheses to get the class token out of the global parsing namespace:
class<Actor> myclass = (class<Actor>)(GetClass());
This commit is contained in:
parent
022228d8a9
commit
3bcd85eb8a
8 changed files with 167 additions and 0 deletions
|
@ -683,6 +683,7 @@ xx(BuiltinFindMultiNameState)
|
|||
xx(BuiltinFindSingleNameState)
|
||||
xx(BuiltinHandleRuntimeState)
|
||||
xx(BuiltinGetDefault)
|
||||
xx(BuiltinClassCast)
|
||||
xx(Damage)
|
||||
|
||||
// basic type names
|
||||
|
|
|
@ -8382,6 +8382,107 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
|||
return dest;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxClassPtrCast::FxClassPtrCast(PClass *dtype, FxExpression *x)
|
||||
: FxExpression(EFX_ClassPtrCast, x->ScriptPosition)
|
||||
{
|
||||
ValueType = NewClassPointer(dtype);
|
||||
desttype = dtype;
|
||||
basex = x;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxClassPtrCast::~FxClassPtrCast()
|
||||
{
|
||||
SAFE_DELETE(basex);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxClassPtrCast::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(basex, ctx);
|
||||
|
||||
if (basex->ValueType == TypeNullPtr)
|
||||
{
|
||||
basex->ValueType = ValueType;
|
||||
auto x = basex;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
auto to = static_cast<PClassPointer *>(ValueType);
|
||||
if (basex->ValueType->GetClass() == RUNTIME_CLASS(PClassPointer))
|
||||
{
|
||||
auto from = static_cast<PClassPointer *>(basex->ValueType);
|
||||
// Downcast is always ok.
|
||||
if (from->ClassRestriction->IsDescendantOf(to->ClassRestriction))
|
||||
{
|
||||
basex->ValueType = to;
|
||||
auto x = basex;
|
||||
basex = nullptr;
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
// Upcast needs a runtime check.
|
||||
else if (to->ClassRestriction->IsDescendantOf(from->ClassRestriction))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
// Everything else is an error.
|
||||
ScriptPosition.Message(MSG_ERROR, "Cannot cast %s to %s. The types are incompatible.", basex->ValueType->DescriptiveName(), to->DescriptiveName());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinClassCast(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_CLASS(from, DObject);
|
||||
PARAM_CLASS(to, DObject);
|
||||
ACTION_RETURN_OBJECT(from->IsDescendantOf(to) ? from : nullptr);
|
||||
}
|
||||
|
||||
ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit clsname = basex->Emit(build);
|
||||
|
||||
build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum);
|
||||
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(desttype, ATAG_OBJECT));
|
||||
|
||||
VMFunction *callfunc;
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
clsname.Free(build);
|
||||
ExpEmit dest(build, REGT_POINTER);
|
||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
|
||||
build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum);
|
||||
return dest;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Symbolic state labels.
|
||||
|
|
|
@ -258,6 +258,7 @@ enum EFxType
|
|||
EFX_JumpStatement,
|
||||
EFX_ReturnStatement,
|
||||
EFX_ClassTypeCast,
|
||||
EFX_ClassPtrCast,
|
||||
EFX_StateByIndex,
|
||||
EFX_RuntimeStateIndex,
|
||||
EFX_MultiNameState,
|
||||
|
@ -1668,6 +1669,25 @@ public:
|
|||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxClassPtrCast : public FxExpression
|
||||
{
|
||||
PClass *desttype;
|
||||
FxExpression *basex;
|
||||
|
||||
public:
|
||||
|
||||
FxClassPtrCast(PClass *dtype, FxExpression *x);
|
||||
~FxClassPtrCast();
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Only used to resolve the old jump by index feature of DECORATE
|
||||
|
|
|
@ -585,6 +585,16 @@ static void PrintExprFuncCall(FLispString &out, ZCC_TreeNode *node)
|
|||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprClassCast(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ClassCast *enode = (ZCC_ClassCast *)node;
|
||||
assert(enode->Operation == PEX_ClassCast);
|
||||
out.Open("expr-class-cast");
|
||||
out.AddName(enode->ClassName);
|
||||
PrintNodes(out, enode->Parameters, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprMemberAccess(FLispString &out, ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ExprMemberAccess *enode = (ZCC_ExprMemberAccess *)node;
|
||||
|
@ -913,6 +923,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *
|
|||
PrintPropertyStmt,
|
||||
PrintVectorInitializer,
|
||||
PrintDeclFlags,
|
||||
PrintExprClassCast,
|
||||
};
|
||||
|
||||
FString ZCC_PrintAST(ZCC_TreeNode *root)
|
||||
|
|
|
@ -1080,6 +1080,14 @@ primary(X) ::= primary(A) LPAREN func_expr_list(B) RPAREN. [DOT] // Function ca
|
|||
expr->Parameters = B;
|
||||
X = expr;
|
||||
}
|
||||
primary(X) ::= LPAREN CLASS LT IDENTIFIER(A) GT RPAREN LPAREN func_expr_list(B) RPAREN. [DOT] // class type cast
|
||||
{
|
||||
NEW_AST_NODE(ClassCast, expr, A);
|
||||
expr->Operation = PEX_ClassCast;
|
||||
expr->ClassName = ENamedName(A.Int);
|
||||
expr->Parameters = B;
|
||||
X = expr;
|
||||
}
|
||||
primary(X) ::= primary(A) LBRACKET expr(B) RBRACKET. [DOT] // Array access
|
||||
{
|
||||
NEW_AST_NODE(ExprBinary, expr, B);
|
||||
|
|
|
@ -2766,6 +2766,24 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
|||
break;
|
||||
}
|
||||
|
||||
case AST_ClassCast:
|
||||
{
|
||||
auto cc = static_cast<ZCC_ClassCast *>(ast);
|
||||
if (cc->Parameters == nullptr || cc->Parameters->SiblingNext != cc->Parameters)
|
||||
{
|
||||
Error(cc, "Class type cast requires exactly one parameter");
|
||||
return new FxNop(*ast); // return something so that the compiler can continue.
|
||||
}
|
||||
auto cls = PClass::FindClass(cc->ClassName);
|
||||
if (cls == nullptr)
|
||||
{
|
||||
Error(cc, "Unknown class %s", FName(cc->ClassName).GetChars());
|
||||
return new FxNop(*ast); // return something so that the compiler can continue.
|
||||
}
|
||||
return new FxClassPtrCast(cls, ConvertNode(cc->Parameters));
|
||||
}
|
||||
|
||||
|
||||
case AST_ExprMemberAccess:
|
||||
{
|
||||
auto memaccess = static_cast<ZCC_ExprMemberAccess *>(ast);
|
||||
|
|
|
@ -8,6 +8,7 @@ xx(ConstValue, TK_Const)
|
|||
xx(FuncCall, '(')
|
||||
xx(ArrayAccess, TK_Array)
|
||||
xx(MemberAccess, '.')
|
||||
xx(ClassCast, TK_Class)
|
||||
xx(TypeRef, TK_Class)
|
||||
xx(Vector, TK_Vector2)
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@ enum EZCCTreeNodeType
|
|||
AST_PropertyStmt,
|
||||
AST_VectorValue,
|
||||
AST_DeclFlags,
|
||||
AST_ClassCast,
|
||||
|
||||
NUM_AST_NODE_TYPES
|
||||
};
|
||||
|
@ -366,6 +367,12 @@ struct ZCC_ExprFuncCall : ZCC_Expression
|
|||
ZCC_FuncParm *Parameters;
|
||||
};
|
||||
|
||||
struct ZCC_ClassCast : ZCC_Expression
|
||||
{
|
||||
ENamedName ClassName;
|
||||
ZCC_FuncParm *Parameters;
|
||||
};
|
||||
|
||||
struct ZCC_ExprMemberAccess : ZCC_Expression
|
||||
{
|
||||
ZCC_Expression *Left;
|
||||
|
|
Loading…
Reference in a new issue