mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +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(BuiltinFindSingleNameState)
|
||||||
xx(BuiltinHandleRuntimeState)
|
xx(BuiltinHandleRuntimeState)
|
||||||
xx(BuiltinGetDefault)
|
xx(BuiltinGetDefault)
|
||||||
|
xx(BuiltinClassCast)
|
||||||
xx(Damage)
|
xx(Damage)
|
||||||
|
|
||||||
// basic type names
|
// basic type names
|
||||||
|
|
|
@ -8382,6 +8382,107 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
||||||
return dest;
|
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.
|
// Symbolic state labels.
|
||||||
|
|
|
@ -258,6 +258,7 @@ enum EFxType
|
||||||
EFX_JumpStatement,
|
EFX_JumpStatement,
|
||||||
EFX_ReturnStatement,
|
EFX_ReturnStatement,
|
||||||
EFX_ClassTypeCast,
|
EFX_ClassTypeCast,
|
||||||
|
EFX_ClassPtrCast,
|
||||||
EFX_StateByIndex,
|
EFX_StateByIndex,
|
||||||
EFX_RuntimeStateIndex,
|
EFX_RuntimeStateIndex,
|
||||||
EFX_MultiNameState,
|
EFX_MultiNameState,
|
||||||
|
@ -1668,6 +1669,25 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
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
|
// 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();
|
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)
|
static void PrintExprMemberAccess(FLispString &out, ZCC_TreeNode *node)
|
||||||
{
|
{
|
||||||
ZCC_ExprMemberAccess *enode = (ZCC_ExprMemberAccess *)node;
|
ZCC_ExprMemberAccess *enode = (ZCC_ExprMemberAccess *)node;
|
||||||
|
@ -913,6 +923,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *
|
||||||
PrintPropertyStmt,
|
PrintPropertyStmt,
|
||||||
PrintVectorInitializer,
|
PrintVectorInitializer,
|
||||||
PrintDeclFlags,
|
PrintDeclFlags,
|
||||||
|
PrintExprClassCast,
|
||||||
};
|
};
|
||||||
|
|
||||||
FString ZCC_PrintAST(ZCC_TreeNode *root)
|
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;
|
expr->Parameters = B;
|
||||||
X = expr;
|
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
|
primary(X) ::= primary(A) LBRACKET expr(B) RBRACKET. [DOT] // Array access
|
||||||
{
|
{
|
||||||
NEW_AST_NODE(ExprBinary, expr, B);
|
NEW_AST_NODE(ExprBinary, expr, B);
|
||||||
|
|
|
@ -2766,6 +2766,24 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
break;
|
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:
|
case AST_ExprMemberAccess:
|
||||||
{
|
{
|
||||||
auto memaccess = static_cast<ZCC_ExprMemberAccess *>(ast);
|
auto memaccess = static_cast<ZCC_ExprMemberAccess *>(ast);
|
||||||
|
|
|
@ -8,6 +8,7 @@ xx(ConstValue, TK_Const)
|
||||||
xx(FuncCall, '(')
|
xx(FuncCall, '(')
|
||||||
xx(ArrayAccess, TK_Array)
|
xx(ArrayAccess, TK_Array)
|
||||||
xx(MemberAccess, '.')
|
xx(MemberAccess, '.')
|
||||||
|
xx(ClassCast, TK_Class)
|
||||||
xx(TypeRef, TK_Class)
|
xx(TypeRef, TK_Class)
|
||||||
xx(Vector, TK_Vector2)
|
xx(Vector, TK_Vector2)
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,7 @@ enum EZCCTreeNodeType
|
||||||
AST_PropertyStmt,
|
AST_PropertyStmt,
|
||||||
AST_VectorValue,
|
AST_VectorValue,
|
||||||
AST_DeclFlags,
|
AST_DeclFlags,
|
||||||
|
AST_ClassCast,
|
||||||
|
|
||||||
NUM_AST_NODE_TYPES
|
NUM_AST_NODE_TYPES
|
||||||
};
|
};
|
||||||
|
@ -366,6 +367,12 @@ struct ZCC_ExprFuncCall : ZCC_Expression
|
||||||
ZCC_FuncParm *Parameters;
|
ZCC_FuncParm *Parameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ZCC_ClassCast : ZCC_Expression
|
||||||
|
{
|
||||||
|
ENamedName ClassName;
|
||||||
|
ZCC_FuncParm *Parameters;
|
||||||
|
};
|
||||||
|
|
||||||
struct ZCC_ExprMemberAccess : ZCC_Expression
|
struct ZCC_ExprMemberAccess : ZCC_Expression
|
||||||
{
|
{
|
||||||
ZCC_Expression *Left;
|
ZCC_Expression *Left;
|
||||||
|
|
Loading…
Reference in a new issue