mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-25 21:51:09 +00:00
- implemented class member access for variables. (Struct members and functions not done yet.)
This commit is contained in:
parent
f5e4c4b109
commit
5bed0a2b39
5 changed files with 153 additions and 36 deletions
|
@ -436,6 +436,7 @@ xx(Scale)
|
||||||
xx(ScaleX)
|
xx(ScaleX)
|
||||||
xx(ScaleY)
|
xx(ScaleY)
|
||||||
xx(Floatbobphase)
|
xx(Floatbobphase)
|
||||||
|
xx(Target)
|
||||||
|
|
||||||
xx(Blocking)
|
xx(Blocking)
|
||||||
xx(Blockmonsters)
|
xx(Blockmonsters)
|
||||||
|
|
|
@ -4019,7 +4019,12 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
else if (sym->IsKindOf(RUNTIME_CLASS(PField)))
|
else if (sym->IsKindOf(RUNTIME_CLASS(PField)))
|
||||||
{
|
{
|
||||||
ABORT(ctx.Function); // only valid when resolving a function.
|
if (!ctx.Function)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Cannot resolve class member outside a function", sym->SymbolName.GetChars());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
PField *vsym = static_cast<PField*>(sym);
|
PField *vsym = static_cast<PField*>(sym);
|
||||||
|
|
||||||
// We have 4 cases to consider here:
|
// We have 4 cases to consider here:
|
||||||
|
@ -4029,11 +4034,11 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
// 4. This is a normal member or unrestricted action function.
|
// 4. This is a normal member or unrestricted action function.
|
||||||
if (vsym->Flags & VARF_Deprecated)
|
if (vsym->Flags & VARF_Deprecated)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars());
|
ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", sym->SymbolName.GetChars());
|
||||||
}
|
}
|
||||||
if ((vsym->Flags & VARF_Private) && symtbl != &ctx.Class->Symbols)
|
if ((vsym->Flags & VARF_Private) && symtbl != &ctx.Class->Symbols)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars());
|
ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", sym->SymbolName.GetChars());
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -4041,6 +4046,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
if (vsym->Flags & VARF_Static)
|
if (vsym->Flags & VARF_Static)
|
||||||
{
|
{
|
||||||
// todo. For now these cannot be defined so let's just exit.
|
// todo. For now these cannot be defined so let's just exit.
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Static members not implemented yet.");
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -4051,29 +4057,29 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (ctx.Function->Variants[0].SelfClass != ctx.Class)
|
||||||
{
|
{
|
||||||
if (ctx.Function->Variants[0].SelfClass != ctx.Class)
|
// Check if the restricted class can access it.
|
||||||
|
PSymbol *sym2;
|
||||||
|
if ((sym2 = ctx.FindInSelfClass(Identifier, symtbl)) != nullptr)
|
||||||
{
|
{
|
||||||
// Check if the restricted class can access it.
|
if (sym != sym2)
|
||||||
PSymbol *sym2;
|
|
||||||
if ((sym2 = ctx.FindInSelfClass(Identifier, symtbl)) != nullptr)
|
|
||||||
{
|
{
|
||||||
if (sym != sym2)
|
ScriptPosition.Message(MSG_ERROR, "Member variable of %s not accessible through restricted self pointer", ctx.Class->TypeName.GetChars());
|
||||||
{
|
delete this;
|
||||||
ScriptPosition.Message(MSG_ERROR, "Member variable of %s not accessible through restricted self pointer", ctx.Class->TypeName.GetChars());
|
return nullptr;
|
||||||
delete this;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as member variable, index %d\n", Identifier.GetChars(), vsym->Offset);
|
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as member variable, index %d\n", Identifier.GetChars(), vsym->Offset);
|
||||||
newex = new FxClassMember((new FxSelf(ScriptPosition))->Resolve(ctx), vsym, ScriptPosition);
|
newex = new FxClassMember((new FxSelf(ScriptPosition))->Resolve(ctx), vsym, ScriptPosition);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars());
|
ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4100,10 +4106,109 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars());
|
ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars());
|
||||||
newex = new FxConstant(0, ScriptPosition);
|
delete this;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
delete this;
|
delete this;
|
||||||
return newex? newex->Resolve(ctx) : NULL;
|
return newex? newex->Resolve(ctx) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FxMemberIdentifier::FxMemberIdentifier(FxExpression *left, FName name, const FScriptPosition &pos)
|
||||||
|
: FxIdentifier(name, pos)
|
||||||
|
{
|
||||||
|
Object = left;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
|
||||||
|
{
|
||||||
|
PSymbol * sym;
|
||||||
|
FxExpression *newex = nullptr;
|
||||||
|
|
||||||
|
CHECKRESOLVED();
|
||||||
|
|
||||||
|
SAFE_RESOLVE(Object, ctx);
|
||||||
|
|
||||||
|
if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||||
|
{
|
||||||
|
PSymbolTable *symtbl;
|
||||||
|
PClass *cls = static_cast<PClassPointer *>(Object->ValueType)->ClassRestriction;
|
||||||
|
if ((sym = cls->Symbols.FindSymbolInTable(Identifier, symtbl)) != nullptr)
|
||||||
|
{
|
||||||
|
if (sym->IsKindOf(RUNTIME_CLASS(PSymbolConst)))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_DEBUGLOG, "Resolving name '%s' as class constant\n", Identifier.GetChars());
|
||||||
|
newex = FxConstant::MakeConstant(sym, ScriptPosition);
|
||||||
|
}
|
||||||
|
else if (sym->IsKindOf(RUNTIME_CLASS(PField)))
|
||||||
|
{
|
||||||
|
PField *vsym = static_cast<PField*>(sym);
|
||||||
|
|
||||||
|
// We have 4 cases to consider here:
|
||||||
|
// 1. The symbol is a static/meta member (not implemented yet) which is always accessible.
|
||||||
|
// 2. This is a static function
|
||||||
|
// 3. This is an action function with a restricted self pointer
|
||||||
|
// 4. This is a normal member or unrestricted action function.
|
||||||
|
if (vsym->Flags & VARF_Deprecated)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s", vsym->SymbolName.GetChars());
|
||||||
|
}
|
||||||
|
if ((vsym->Flags & VARF_Private) && symtbl != &ctx.Class->Symbols)
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Private member %s not accessible", vsym->SymbolName.GetChars());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vsym->Flags & VARF_Static)
|
||||||
|
{
|
||||||
|
// todo. For now these cannot be defined so let's just exit.
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Static members not implemented yet.");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto x = new FxClassMember(Object, vsym, ScriptPosition);
|
||||||
|
delete this;
|
||||||
|
return x->Resolve(ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Invalid member identifier '%s'\n", Identifier.GetChars());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Unknown identifier '%s'", Identifier.GetChars());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Object->ValueType->IsA(RUNTIME_CLASS(PStruct)))
|
||||||
|
{
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
else if (Object->ValueType->IsA(RUNTIME_CLASS(PPointer)))
|
||||||
|
{
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Left side of %s is not a struct or class", Identifier.GetChars());
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4248,19 +4353,6 @@ FxExpression *FxClassMember::Resolve(FCompileContext &ctx)
|
||||||
|
|
||||||
ExpEmit FxClassMember::Emit(VMFunctionBuilder *build)
|
ExpEmit FxClassMember::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
if (build->IsActionFunc && ~membervar->Flags & VARF_Native)
|
|
||||||
{ // Check if this is a user-defined variable.
|
|
||||||
// As of right now, FxClassMember is only ever used with FxSelf.
|
|
||||||
// This very user variable was defined in stateowner so if
|
|
||||||
// self (a0) != stateowner (a1) then the offset is most likely
|
|
||||||
// going to end up being totally wrong even if the variable was
|
|
||||||
// redefined in self which means we have to abort to avoid reading
|
|
||||||
// or writing to a random address and possibly crash.
|
|
||||||
build->Emit(OP_EQA_R, 1, 0, 1);
|
|
||||||
build->Emit(OP_JMP, 1);
|
|
||||||
build->Emit(OP_THROW, 2, X_BAD_SELF);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpEmit obj = classx->Emit(build);
|
ExpEmit obj = classx->Emit(build);
|
||||||
assert(obj.RegType == REGT_POINTER);
|
assert(obj.RegType == REGT_POINTER);
|
||||||
|
|
||||||
|
|
|
@ -245,6 +245,7 @@ public:
|
||||||
|
|
||||||
class FxIdentifier : public FxExpression
|
class FxIdentifier : public FxExpression
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
FName Identifier;
|
FName Identifier;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -253,6 +254,22 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FxIdentifier
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxMemberIdentifier : public FxIdentifier
|
||||||
|
{
|
||||||
|
FxExpression *Object;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FxMemberIdentifier(FxExpression *obj, FName i, const FScriptPosition &p);
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// FxDotIdentifier
|
// FxDotIdentifier
|
||||||
|
|
|
@ -636,6 +636,7 @@ void InitThingdef()
|
||||||
// Define some member variables we feel like exposing to the user
|
// Define some member variables we feel like exposing to the user
|
||||||
PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols;
|
PSymbolTable &symt = RUNTIME_CLASS(AActor)->Symbols;
|
||||||
PType *array5 = NewArray(TypeSInt32, 5);
|
PType *array5 = NewArray(TypeSInt32, 5);
|
||||||
|
PType *TypeActor = NewClassPointer(RUNTIME_CLASS(AActor));
|
||||||
symt.AddSymbol(new PField(NAME_Alpha, TypeFloat64, VARF_Native, myoffsetof(AActor, Alpha)));
|
symt.AddSymbol(new PField(NAME_Alpha, TypeFloat64, VARF_Native, myoffsetof(AActor, Alpha)));
|
||||||
symt.AddSymbol(new PField(NAME_Angle, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Yaw)));
|
symt.AddSymbol(new PField(NAME_Angle, TypeFloat64, VARF_Native, myoffsetof(AActor, Angles.Yaw)));
|
||||||
symt.AddSymbol(new PField(NAME_Args, array5, VARF_Native, myoffsetof(AActor, args)));
|
symt.AddSymbol(new PField(NAME_Args, array5, VARF_Native, myoffsetof(AActor, args)));
|
||||||
|
@ -675,4 +676,5 @@ void InitThingdef()
|
||||||
symt.AddSymbol(new PField(NAME_VisibleStartPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartPitch)));
|
symt.AddSymbol(new PField(NAME_VisibleStartPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleStartPitch)));
|
||||||
symt.AddSymbol(new PField(NAME_VisibleEndAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndAngle)));
|
symt.AddSymbol(new PField(NAME_VisibleEndAngle, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndAngle)));
|
||||||
symt.AddSymbol(new PField(NAME_VisibleEndPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndPitch)));
|
symt.AddSymbol(new PField(NAME_VisibleEndPitch, TypeFloat64, VARF_Native, myoffsetof(AActor, VisibleEndPitch)));
|
||||||
|
symt.AddSymbol(new PField(NAME_Target, TypeActor, VARF_Native, myoffsetof(AActor, target)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2372,13 +2372,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
// The function name is a simple identifier.
|
// The function name is a simple identifier.
|
||||||
return new FxFunctionCall(static_cast<ZCC_ExprID *>(fcall->Function)->Identifier, NAME_None, ConvertNodeList(fcall->Parameters), *ast);
|
return new FxFunctionCall(static_cast<ZCC_ExprID *>(fcall->Function)->Identifier, NAME_None, ConvertNodeList(fcall->Parameters), *ast);
|
||||||
|
|
||||||
// not yet done
|
|
||||||
case AST_ExprTypeRef:
|
|
||||||
case AST_SwitchStmt:
|
|
||||||
case AST_CaseStmt:
|
|
||||||
case AST_ExprMemberAccess:
|
case AST_ExprMemberAccess:
|
||||||
// calling a class member through its pointer
|
|
||||||
// todo.
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AST_ExprBinary:
|
case AST_ExprBinary:
|
||||||
|
@ -2400,6 +2394,12 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case AST_ExprMemberAccess:
|
||||||
|
{
|
||||||
|
auto memaccess = static_cast<ZCC_ExprMemberAccess *>(ast);
|
||||||
|
return new FxMemberIdentifier(ConvertNode(memaccess->Left), memaccess->Right, *ast);
|
||||||
|
}
|
||||||
|
|
||||||
case AST_FuncParm:
|
case AST_FuncParm:
|
||||||
{
|
{
|
||||||
auto fparm = static_cast<ZCC_FuncParm *>(ast);
|
auto fparm = static_cast<ZCC_FuncParm *>(ast);
|
||||||
|
@ -2660,6 +2660,11 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// not yet done
|
||||||
|
case AST_SwitchStmt:
|
||||||
|
case AST_CaseStmt:
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case AST_CompoundStmt:
|
case AST_CompoundStmt:
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue