- added an accessor to the actor defaults. This might have been possible with less work using a function but that would have necessitated some type casts when using it on subclasses.
- scriptified A_BarrelDestroy to test the above.
This commit is contained in:
parent
24925c88a8
commit
98fa3d2d93
8 changed files with 157 additions and 24 deletions
|
|
@ -5015,6 +5015,27 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
|||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
|
||||
if (Identifier == NAME_Default)
|
||||
{
|
||||
if (ctx.Function->Variants[0].SelfClass == nullptr)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Unable to access class defaults from static function");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
if (!ctx.Function->Variants[0].SelfClass->IsDescendantOf(RUNTIME_CLASS(AActor)))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FxExpression * x = new FxClassDefaults(new FxSelf(ScriptPosition), ScriptPosition);
|
||||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
|
||||
// Ugh, the horror. Constants need to be taken from the owning class, but members from the self class to catch invalid accesses here...
|
||||
// see if the current class (if valid) defines something with this name.
|
||||
PSymbolTable *symtbl;
|
||||
|
|
@ -5348,6 +5369,95 @@ ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxClassDefaults::FxClassDefaults(FxExpression *X, const FScriptPosition &pos)
|
||||
: FxExpression(EFX_ClassDefaults, pos)
|
||||
{
|
||||
obj = X;
|
||||
EmitTail = false;
|
||||
}
|
||||
|
||||
FxClassDefaults::~FxClassDefaults()
|
||||
{
|
||||
SAFE_DELETE(obj);
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
PPrototype *FxClassDefaults::ReturnProto()
|
||||
{
|
||||
EmitTail = true;
|
||||
return FxExpression::ReturnProto();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxClassDefaults::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(obj, ctx);
|
||||
assert(obj->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)));
|
||||
ValueType = NewPointer(static_cast<PPointer*>(obj->ValueType)->PointedType, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int BuiltinGetDefault(VMFrameStack *stack, VMValue *param, TArray<VMValue> &defaultparam, int numparam, VMReturn *ret, int numret)
|
||||
{
|
||||
assert(numparam == 1);
|
||||
PARAM_POINTER_AT(0, obj, DObject);
|
||||
ACTION_RETURN_OBJECT(obj->GetClass()->Defaults);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxClassDefaults::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
EmitParameter(build, obj, ScriptPosition);
|
||||
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinGetDefault, BuiltinGetDefault);
|
||||
|
||||
assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolVMFunction)));
|
||||
assert(((PSymbolVMFunction *)sym)->Function != nullptr);
|
||||
auto callfunc = ((PSymbolVMFunction *)sym)->Function;
|
||||
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
|
||||
build->Emit(opcode, build->GetConstantAddress(callfunc, ATAG_OBJECT), 1, 1);
|
||||
|
||||
if (EmitTail)
|
||||
{
|
||||
ExpEmit call;
|
||||
call.Final = true;
|
||||
return call;
|
||||
}
|
||||
|
||||
ExpEmit out(build, REGT_POINTER);
|
||||
build->Emit(OP_RESULT, 0, REGT_POINTER, out.RegNum);
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
@ -5465,6 +5575,21 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx)
|
|||
CHECKRESOLVED();
|
||||
SAFE_RESOLVE(classx, ctx);
|
||||
|
||||
if (membervar->SymbolName == NAME_Default)
|
||||
{
|
||||
if (!classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))
|
||||
|| !static_cast<PPointer *>(classx->ValueType)->PointedType->IsKindOf(RUNTIME_CLASS(AActor)))
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
FxExpression * x = new FxClassDefaults(classx, ScriptPosition);
|
||||
classx = nullptr;
|
||||
delete this;
|
||||
return x->Resolve(ctx);
|
||||
}
|
||||
|
||||
if (classx->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
{
|
||||
PPointer *ptrtype = dyn_cast<PPointer>(classx->ValueType);
|
||||
|
|
@ -5581,7 +5706,6 @@ FxClassMember::FxClassMember(FxExpression *x, PField* mem, const FScriptPosition
|
|||
: FxStructMember(x, mem, pos)
|
||||
{
|
||||
ExprType = EFX_ClassMember;
|
||||
//if (classx->IsDefaultObject()) Readonly=true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue