- allow functions in structs. This is needed for several internal data types like players, sectors, lines, etc.

- added a new type 'NativeStruct'. This will be used for types that cannot be instantiated, and is also needed to cleanly handle many internal types that only can exist as reference.
This commit is contained in:
Christoph Oelckers 2016-11-19 12:12:29 +01:00
commit f11f020b6c
11 changed files with 418 additions and 335 deletions

View file

@ -101,7 +101,7 @@ FCompileContext::FCompileContext(PFunction *fnc, PPrototype *ret, bool fromdecor
if (fnc != nullptr) Class = fnc->OwningClass;
}
FCompileContext::FCompileContext(PClass *cls, bool fromdecorate)
FCompileContext::FCompileContext(PStruct *cls, bool fromdecorate)
: ReturnProto(nullptr), Function(nullptr), Class(cls), FromDecorate(fromdecorate), StateIndex(-1), StateCount(0), Lump(-1)
{
}
@ -5335,7 +5335,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
delete this;
return nullptr;
}
if (!ctx.Function->Variants[0].SelfClass->IsDescendantOf(RUNTIME_CLASS(AActor)))
if (!ctx.Function->Variants[0].SelfClass->IsKindOf(RUNTIME_CLASS(PClassActor)))
{
ScriptPosition.Message(MSG_ERROR, "'Default' requires an actor type.");
delete this;
@ -5441,7 +5441,7 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx)
//
//==========================================================================
FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PClass *classctx, FxExpression *&object, PStruct *objtype)
FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PStruct *classctx, FxExpression *&object, PStruct *objtype)
{
PSymbol *sym;
PSymbolTable *symtbl;
@ -6379,7 +6379,15 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction
{
auto callingself = caller->Variants[0].SelfClass;
auto calledself = callee->Variants[0].SelfClass;
if (!callingself->IsDescendantOf(calledself))
bool match = (callingself == calledself);
if (!match)
{
auto callingselfcls = dyn_cast<PClass>(caller->Variants[0].SelfClass);
auto calledselfcls = dyn_cast<PClass>(callee->Variants[0].SelfClass);
match = callingselfcls != nullptr && calledselfcls != nullptr && callingselfcls->IsDescendantOf(calledselfcls);
}
if (!match)
{
ScriptPosition.Message(MSG_ERROR, "Call to member function %s with incompatible self pointer.", callee->SymbolName.GetChars());
return false;
@ -6717,11 +6725,19 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
if (Self->ExprType == EFX_Super)
{
// give the node the proper value type now that we know it's properly used.
cls = ctx.Function->Variants[0].SelfClass->ParentClass;
Self->ValueType = NewPointer(cls);
Self->ExprType = EFX_Self;
novirtual = true; // super calls are always non-virtual
auto clstype = dyn_cast<PClass>(ctx.Function->Variants[0].SelfClass);
if (clstype != nullptr)
{
// give the node the proper value type now that we know it's properly used.
cls = clstype->ParentClass;
Self->ValueType = NewPointer(cls);
Self->ExprType = EFX_Self;
novirtual = true; // super calls are always non-virtual
}
else
{
ScriptPosition.Message(MSG_ERROR, "Super requires a class type");
}
}
if (Self->IsVector())
@ -6775,7 +6791,8 @@ isresolved:
if (staticonly && (afd->Variants[0].Flags & VARF_Method))
{
if (!ctx.Class->IsDescendantOf(cls))
auto clstype = dyn_cast<PClass>(ctx.Class);
if (clstype == nullptr || !clstype->IsDescendantOf(cls))
{
ScriptPosition.Message(MSG_ERROR, "Cannot call non-static function %s::%s from here\n", cls->TypeName.GetChars(), MethodName.GetChars());
delete this;
@ -8876,14 +8893,22 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
CHECKRESOLVED();
ABORT(ctx.Class);
int symlabel;
auto clstype = dyn_cast<PClassActor>(ctx.Class);
if (names[0] == NAME_None)
{
scope = nullptr;
}
else if (clstype == nullptr)
{
// not in an actor, so any further checks are pointless.
ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars());
delete this;
return nullptr;
}
else if (names[0] == NAME_Super)
{
scope = dyn_cast<PClassActor>(ctx.Class->ParentClass);
scope = dyn_cast<PClassActor>(clstype->ParentClass);
}
else
{
@ -8894,7 +8919,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
delete this;
return nullptr;
}
else if (!scope->IsAncestorOf(ctx.Class))
else if (!scope->IsAncestorOf(clstype))
{
ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(), ctx.Class->TypeName.GetChars());
delete this;

View file

@ -75,7 +75,7 @@ struct FCompileContext
FxCompoundStatement *Block = nullptr;
PPrototype *ReturnProto;
PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.)
PClass *Class; // The type of the owning class.
PStruct *Class; // The type of the owning class.
bool FromDecorate; // DECORATE must silence some warnings and demote some errors.
int StateIndex; // index in actor's state table for anonymous functions, otherwise -1 (not used by DECORATE which pre-resolves state indices)
int StateCount; // amount of states an anoymous function is being used on (must be 1 for state indices to be allowed.)
@ -84,7 +84,7 @@ struct FCompileContext
TDeletingArray<FxLocalVariableDeclaration *> FunctionArgs;
FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate, int stateindex, int statecount, int lump);
FCompileContext(PClass *cls, bool fromdecorate); // only to be used to resolve constants!
FCompileContext(PStruct *cls, bool fromdecorate); // only to be used to resolve constants!
PSymbol *FindInClass(FName identifier, PSymbolTable *&symt);
PSymbol *FindInSelfClass(FName identifier, PSymbolTable *&symt);
@ -346,7 +346,7 @@ public:
FxIdentifier(FName i, const FScriptPosition &p);
FxExpression *Resolve(FCompileContext&);
FxExpression *ResolveMember(FCompileContext&, PClass*, FxExpression*&, PStruct*);
FxExpression *ResolveMember(FCompileContext&, PStruct*, FxExpression*&, PStruct*);
};