- 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;