- Implemented ZScript abstract functions

This commit is contained in:
Player701 2020-10-10 11:24:49 +03:00 committed by Christoph Oelckers
commit 761dea8640
9 changed files with 82 additions and 22 deletions

View file

@ -2042,7 +2042,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
} while (t != f->Type);
}
int notallowed = ZCC_Latent | ZCC_Meta | ZCC_ReadOnly | ZCC_Abstract | ZCC_Internal;
int notallowed = ZCC_Latent | ZCC_Meta | ZCC_ReadOnly | ZCC_Internal;
if (f->Flags & notallowed)
{
@ -2088,6 +2088,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
if (f->Flags & ZCC_Deprecated) varflags |= VARF_Deprecated;
if (f->Flags & ZCC_Virtual) varflags |= VARF_Virtual;
if (f->Flags & ZCC_Override) varflags |= VARF_Override;
if (f->Flags & ZCC_Abstract) varflags |= VARF_Abstract;
if (f->Flags & ZCC_VarArg) varflags |= VARF_VarArg;
if (f->Flags & ZCC_FuncConst) varflags |= VARF_ReadOnly; // FuncConst method is internally marked as VARF_ReadOnly
if (mVersion >= MakeVersion(2, 4, 0))
@ -2131,7 +2132,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
if (varflags & VARF_Override) varflags &= ~VARF_Virtual; // allow 'virtual override'.
// Only one of these flags may be used.
static int exclude[] = { ZCC_Virtual, ZCC_Override, ZCC_Action, ZCC_Static };
static int exclude[] = { ZCC_Abstract, ZCC_Virtual, ZCC_Override, ZCC_Action, ZCC_Static };
int excludeflags = 0;
int fc = 0;
for (size_t i = 0; i < countof(exclude); i++)
@ -2147,7 +2148,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
Error(f, "Invalid combination of qualifiers %s on function %s", FlagsToString(excludeflags).GetChars(), FName(f->Name).GetChars());
varflags |= VARF_Method;
}
if (varflags & VARF_Override) varflags |= VARF_Virtual; // Now that the flags are checked, make all override functions virtual as well.
if (varflags & (VARF_Override | VARF_Abstract)) varflags |= VARF_Virtual; // Now that the flags are checked, make all override and abstract functions virtual as well.
// [ZZ] this doesn't make sense either.
if ((varflags&(VARF_ReadOnly | VARF_Method)) == VARF_ReadOnly) // non-method const function
@ -2180,6 +2181,12 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
if (f->Flags & ZCC_Native)
{
if (varflags & VARF_Abstract)
{
Error(f, "Native functions cannot be abstract");
return;
}
varflags |= VARF_Native;
afd = FindFunction(c->Type(), FName(f->Name).GetChars());
if (afd == nullptr)
@ -2371,19 +2378,20 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
if (!(f->Flags & ZCC_Native))
{
if (f->Body == nullptr)
if (f->Body != nullptr && (varflags & VARF_Abstract))
{
Error(f, "Abstract function %s cannot have a body", FName(f->Name).GetChars());
return;
}
if (f->Body == nullptr && !(varflags & VARF_Abstract))
{
Error(f, "Empty function %s", FName(f->Name).GetChars());
return;
}
else
{
auto code = ConvertAST(c->Type(), f->Body);
if (code != nullptr)
{
newfunc = FunctionBuildList.AddFunction(OutNamespace, mVersion, sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false, -1, 0, Lump);
}
}
FxExpression* code = f->Body != nullptr ? ConvertAST(c->Type(), f->Body) : nullptr;
newfunc = FunctionBuildList.AddFunction(OutNamespace, mVersion, sym, code, FStringf("%s.%s", c->Type()->TypeName.GetChars(), FName(f->Name).GetChars()), false, -1, 0, Lump);
}
if (sym->Variants[0].Implementation != nullptr && hasdefault) // do not copy empty default lists, they only waste space and processing time.
{
@ -2408,6 +2416,12 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
if (forclass)
{
if ((varflags & VARF_Abstract) && !clstype->bAbstract)
{
Error(f, "Abstract functions can only be defined in abstract classes");
return;
}
auto parentfunc = clstype->ParentClass? dyn_cast<PFunction>(clstype->ParentClass->VMType->Symbols.FindSymbol(sym->SymbolName, true)) : nullptr;
int vindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc, exactReturnType);
@ -2526,6 +2540,18 @@ void ZCCCompiler::InitFunctions()
{
CompileFunction(c, f, true);
}
// [Player701] Make sure all abstract functions are overridden
if (!c->ClassType()->bAbstract)
{
for (auto v : c->ClassType()->Virtuals)
{
if (v->VarFlags & VARF_Abstract)
{
Error(c->cls, "Non-abstract class %s must override abstract function %s", c->Type()->TypeName.GetChars(), v->PrintableName.GetChars());
}
}
}
}
}