- implemented usage restrictions for action functions.

This commit is contained in:
Christoph Oelckers 2016-11-15 21:38:12 +01:00
commit a2e17c0ab5
8 changed files with 189 additions and 58 deletions

View file

@ -820,6 +820,7 @@ static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node)
out.Break();
out.Open("func-declarator");
out.AddHex(dnode->Flags);
PrintNodes(out, dnode->UseFlags);
PrintNodes(out, dnode->Type);
out.AddName(dnode->Name);
PrintNodes(out, dnode->Params);
@ -827,6 +828,16 @@ static void PrintFuncDeclarator(FLispString &out, ZCC_TreeNode *node)
out.Close();
}
static void PrintDeclFlags(FLispString &out, ZCC_TreeNode *node)
{
auto dnode = (ZCC_DeclFlags *)node;
out.Break();
out.Open("decl-flags");
out.AddHex(dnode->Flags);
PrintNodes(out, dnode->Id);
out.Close();
}
static void PrintFlagStmt(FLispString &out, ZCC_TreeNode *node)
{
auto dnode = (ZCC_FlagStmt *)node;
@ -901,6 +912,7 @@ void (* const TreeNodePrinter[NUM_AST_NODE_TYPES])(FLispString &, ZCC_TreeNode *
PrintFlagStmt,
PrintPropertyStmt,
PrintVectorInitializer,
PrintDeclFlags,
};
FString ZCC_PrintAST(ZCC_TreeNode *root)

View file

@ -814,20 +814,21 @@ declarator(X) ::= decl_flags(A) type_list_or_void(B) variables_or_function(C).
}
else if (C.FuncName != NAME_None)
{ // A function
NEW_AST_NODE(FuncDeclarator, decl, A.SourceLoc);
NEW_AST_NODE(FuncDeclarator, decl, A == nullptr? C.SourceLoc : A->SourceLoc);
decl->Type = B;
decl->Params = C.FuncParams;
decl->Name = C.FuncName;
decl->Flags = A.Int | C.FuncFlags;
decl->UseFlags = A == nullptr? nullptr : A->Id;
decl->Flags = (A == nullptr? 0 : A->Flags) | C.FuncFlags;
decl->Body = C.FuncBody;
X = decl;
}
else if (B != NULL && B->SiblingNext == B)
{ // A variable
NEW_AST_NODE(VarDeclarator, decl, A.SourceLoc);
NEW_AST_NODE(VarDeclarator, decl, A == nullptr? B->SourceLoc : A->SourceLoc);
decl->Type = B;
decl->Names = C.VarNames;
decl->Flags = A.Int;
decl->Flags = (A == nullptr? 0 : A->Flags);
X = decl;
}
else
@ -845,10 +846,10 @@ declarator(X) ::= decl_flags(A) type_list_or_void(B) variables_or_function(C).
}
declarator_no_fun(X) ::= decl_flags(A) type(B) variable_list(C) SEMICOLON.
{
NEW_AST_NODE(VarDeclarator, decl, A.SourceLoc ? A.SourceLoc : B->SourceLoc);
NEW_AST_NODE(VarDeclarator, decl, A != nullptr? A->SourceLoc : B->SourceLoc);
decl->Type = B;
decl->Names = C;
decl->Flags = A.Int;
decl->Flags = A == nullptr? 0 : A->Flags;
X = decl;
}
@ -916,19 +917,52 @@ variable_list(X) ::= variable_list(A) COMMA variable_name(B).
X = A; /*X-overwrites-A*/
}
decl_flags(X) ::= . { X.Int = 0; X.SourceLoc = 0; }
decl_flags(X) ::= decl_flags(A) NATIVE(T). { X.Int = A.Int | ZCC_Native; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) STATIC(T). { X.Int = A.Int | ZCC_Static; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) PRIVATE(T). { X.Int = A.Int | ZCC_Private; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) PROTECTED(T). { X.Int = A.Int | ZCC_Protected; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) LATENT(T). { X.Int = A.Int | ZCC_Latent; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) FINAL(T). { X.Int = A.Int | ZCC_Final; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) META(T). { X.Int = A.Int | ZCC_Meta; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) ACTION(T). { X.Int = A.Int | ZCC_Action; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) READONLY(T). { X.Int = A.Int | ZCC_ReadOnly; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) DEPRECATED(T). { X.Int = A.Int | ZCC_Deprecated; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) VIRTUAL(T). { X.Int = A.Int | ZCC_Virtual; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
decl_flags(X) ::= decl_flags(A) OVERRIDE(T). { X.Int = A.Int | ZCC_Override; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
%type decl_flags { ZCC_DeclFlags * }
decl_flags(X) ::= . { X = NULL; }
decl_flags(X) ::= decl_flags(F) decl_flag(A).
{
if (F == nullptr)
{
NEW_AST_NODE(DeclFlags,nil_f,A);
X = nil_f;
X->Id = nullptr;
X->Flags = A.Int;
}
else
{
X = F;
X->Flags |= A.Int;
}
}
decl_flags(X) ::= decl_flags(F) ACTION(B) states_opts(A).
{
if (F == nullptr)
{
NEW_AST_NODE(DeclFlags,nil_f,B.SourceLoc);
X = nil_f;
X->Flags = ZCC_Action;
}
else
{
X = F;
X->Flags |= ZCC_Action;
}
X->Id = A;
}
decl_flag(X) ::= NATIVE(T). { X.Int = ZCC_Native; X.SourceLoc = T.SourceLoc; }
decl_flag(X) ::= STATIC(T). { X.Int = ZCC_Static; X.SourceLoc = T.SourceLoc; }
decl_flag(X) ::= PRIVATE(T). { X.Int = ZCC_Private; X.SourceLoc = T.SourceLoc; }
decl_flag(X) ::= PROTECTED(T). { X.Int = ZCC_Protected; X.SourceLoc = T.SourceLoc; }
decl_flag(X) ::= LATENT(T). { X.Int = ZCC_Latent; X.SourceLoc = T.SourceLoc; }
decl_flag(X) ::= FINAL(T). { X.Int = ZCC_Final; X.SourceLoc = T.SourceLoc; }
decl_flag(X) ::= META(T). { X.Int = ZCC_Meta; X.SourceLoc = T.SourceLoc; }
decl_flag(X) ::= READONLY(T). { X.Int = ZCC_ReadOnly; X.SourceLoc = T.SourceLoc; }
decl_flag(X) ::= DEPRECATED(T). { X.Int = ZCC_Deprecated; X.SourceLoc = T.SourceLoc; }
decl_flag(X) ::= VIRTUAL(T). { X.Int = ZCC_Virtual; X.SourceLoc = T.SourceLoc; }
decl_flag(X) ::= OVERRIDE(T). { X.Int = ZCC_Override; X.SourceLoc = T.SourceLoc; }
func_const(X) ::= . { X.Int = 0; X.SourceLoc = stat->sc->GetMessageLine(); }
func_const(X) ::= CONST(T). { X.Int = ZCC_FuncConst; X.SourceLoc = T.SourceLoc; }
@ -979,9 +1013,9 @@ func_param(X) ::= func_param_flags(A) type(B) IDENTIFIER(C) EQ expr(D).
}
func_param_flags(X) ::= . { X.Int = 0; X.SourceLoc = 0; }
func_param_flags(X) ::= func_param_flags(A) IN(T). { X.Int = A.Int | ZCC_In; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
func_param_flags(X) ::= func_param_flags(A) OUT(T). { X.Int = A.Int | ZCC_Out; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
func_param_flags(X) ::= func_param_flags(A) OPTIONAL(T). { X.Int = A.Int | ZCC_Optional; X.SourceLoc = A.SourceLoc ? A.SourceLoc : T.SourceLoc; }
func_param_flags(X) ::= func_param_flags(A) IN(T). { X.Int = A.Int | ZCC_In; X.SourceLoc = T.SourceLoc; }
func_param_flags(X) ::= func_param_flags(A) OUT(T). { X.Int = A.Int | ZCC_Out; X.SourceLoc = T.SourceLoc; }
func_param_flags(X) ::= func_param_flags(A) OPTIONAL(T). { X.Int = A.Int | ZCC_Optional; X.SourceLoc = T.SourceLoc; }
/************ Expressions ************/

View file

@ -2051,6 +2051,35 @@ void ZCCCompiler::InitFunctions()
uint32_t varflags = VARF_Method;
int implicitargs = 1;
AFuncDesc *afd = nullptr;
int useflags = SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM;
if (f->UseFlags != nullptr)
{
useflags = 0;
auto p = f->UseFlags;
do
{
switch (p->Id)
{
case NAME_Actor:
useflags |= SUF_ACTOR;
break;
case NAME_Overlay:
useflags |= SUF_OVERLAY;
break;
case NAME_Weapon:
useflags |= SUF_WEAPON;
break;
case NAME_Item:
useflags |= SUF_ITEM;
break;
default:
Error(p, "Unknown Action qualifier %s", FName(p->Id).GetChars());
break;
}
p = static_cast<decltype(p)>(p->SiblingNext);
} while (p != f->UseFlags);
}
// map to implementation flags.
if (f->Flags & ZCC_Private) varflags |= VARF_Private;
@ -2058,9 +2087,22 @@ void ZCCCompiler::InitFunctions()
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_Action) varflags |= VARF_Action|VARF_Final, implicitargs = 3; // Action implies Final.
if (f->Flags & ZCC_Action)
{
varflags |= VARF_Final; // Action implies Final.
if (useflags & (SUF_OVERLAY | SUF_WEAPON | SUF_ITEM))
{
varflags |= VARF_Action;
implicitargs = 3;
}
else
{
implicitargs = 1;
}
}
if (f->Flags & ZCC_Static) varflags = (varflags & ~VARF_Method) | VARF_Final, implicitargs = 0; // Static implies Final.
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 };
@ -2096,9 +2138,7 @@ void ZCCCompiler::InitFunctions()
(*afd->VMPointer)->ImplicitArgs = BYTE(implicitargs);
}
}
// Todo: parse these values from the definition
int tempuseflags = (varflags & VARF_Action) ? SUF_WEAPON | SUF_ITEM | SUF_OVERLAY | SUF_ACTOR : SUF_ACTOR;
SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags, tempuseflags);
SetImplicitArgs(&args, &argflags, &argnames, c->Type(), varflags, useflags);
argdefaults.Resize(argnames.Size());
auto p = f->Params;
bool hasoptionals = false;
@ -2225,7 +2265,7 @@ void ZCCCompiler::InitFunctions()
}
PFunction *sym = new PFunction(c->Type(), f->Name);
sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr? nullptr : *(afd->VMPointer), varflags);
sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr? nullptr : *(afd->VMPointer), varflags, useflags);
c->Type()->Symbols.ReplaceSymbol(sym);
if (!(f->Flags & ZCC_Native))

View file

@ -101,6 +101,7 @@ enum EZCCTreeNodeType
AST_FlagStmt,
AST_PropertyStmt,
AST_VectorValue,
AST_DeclFlags,
NUM_AST_NODE_TYPES
};
@ -473,6 +474,12 @@ struct ZCC_FuncParamDecl : ZCC_TreeNode
int Flags;
};
struct ZCC_DeclFlags : ZCC_TreeNode
{
ZCC_Identifier *Id;
int Flags;
};
struct ZCC_ConstantDef : ZCC_NamedNode
{
ZCC_Expression *Value;
@ -498,6 +505,7 @@ struct ZCC_FuncDeclarator : ZCC_Declarator
ZCC_FuncParamDecl *Params;
ENamedName Name;
ZCC_Statement *Body;
ZCC_Identifier *UseFlags;
};
struct ZCC_Default : ZCC_CompoundStmt