Merge remote-tracking branch 'gzdoom/master' into merge-gzdoom
This commit is contained in:
commit
e75e5a387b
600 changed files with 40006 additions and 59374 deletions
|
|
@ -521,6 +521,26 @@ static void PrintDynArrayType(FLispString &out, const ZCC_TreeNode *node)
|
|||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintFuncPtrParamDecl(FLispString &out, const ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_FuncPtrParamDecl *dnode = (ZCC_FuncPtrParamDecl *)node;
|
||||
out.Break();
|
||||
out.Open("func-ptr-param-decl");
|
||||
PrintNodes(out, dnode->Type);
|
||||
out.AddHex(dnode->Flags);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintFuncPtrType(FLispString &out, const ZCC_TreeNode *node){
|
||||
ZCC_FuncPtrType *dnode = (ZCC_FuncPtrType *)node;
|
||||
out.Break();
|
||||
out.Open("func-ptr-type");
|
||||
PrintNodes(out, dnode->RetType);
|
||||
PrintNodes(out, dnode->Params);
|
||||
out.AddHex(dnode->Scope);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintClassType(FLispString &out, const ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_ClassType *tnode = (ZCC_ClassType *)node;
|
||||
|
|
@ -628,6 +648,16 @@ static void PrintExprClassCast(FLispString &out, const ZCC_TreeNode *node)
|
|||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintExprFunctionPtrCast(FLispString &out, const ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_FunctionPtrCast *enode = (ZCC_FunctionPtrCast *)node;
|
||||
assert(enode->Operation == PEX_FunctionPtrCast);
|
||||
out.Open("expr-func-ptr-cast");
|
||||
PrintNodes(out, enode->PtrType, false);
|
||||
PrintNodes(out, enode->Expr, false);
|
||||
out.Close();
|
||||
}
|
||||
|
||||
static void PrintStaticArray(FLispString &out, const ZCC_TreeNode *node)
|
||||
{
|
||||
ZCC_StaticArrayStatement *enode = (ZCC_StaticArrayStatement *)node;
|
||||
|
|
@ -976,6 +1006,8 @@ static const NodePrinterFunc TreeNodePrinter[] =
|
|||
PrintMapType,
|
||||
PrintMapIteratorType,
|
||||
PrintDynArrayType,
|
||||
PrintFuncPtrParamDecl,
|
||||
PrintFuncPtrType,
|
||||
PrintClassType,
|
||||
PrintExpression,
|
||||
PrintExprID,
|
||||
|
|
@ -1011,6 +1043,7 @@ static const NodePrinterFunc TreeNodePrinter[] =
|
|||
PrintVectorInitializer,
|
||||
PrintDeclFlags,
|
||||
PrintExprClassCast,
|
||||
PrintExprFunctionPtrCast,
|
||||
PrintStaticArrayState,
|
||||
PrintProperty,
|
||||
PrintFlagDef,
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ static void SetNodeLine(ZCC_TreeNode *name, int line)
|
|||
struct ClassFlagsBlock {
|
||||
VM_UWORD Flags;
|
||||
ZCC_Identifier *Replaces;
|
||||
ZCC_Identifier *Sealed;
|
||||
VersionInfo Version;
|
||||
};
|
||||
|
||||
|
|
@ -242,6 +243,7 @@ class_head(X) ::= CLASS(T) IDENTIFIER(A) class_ancestry(B) class_flags(C).
|
|||
head->ParentName = B;
|
||||
head->Flags = C.Flags;
|
||||
head->Replaces = C.Replaces;
|
||||
head->Sealed = C.Sealed;
|
||||
head->Version = C.Version;
|
||||
head->Type = nullptr;
|
||||
head->Symbol = nullptr;
|
||||
|
|
@ -253,13 +255,15 @@ class_ancestry(X) ::= . { X = NULL; }
|
|||
class_ancestry(X) ::= COLON dottable_id(A). { X = A; /*X-overwrites-A*/ }
|
||||
|
||||
%type class_flags{ClassFlagsBlock}
|
||||
class_flags(X) ::= . { X.Flags = 0; X.Replaces = NULL; X.Version = {0,0}; }
|
||||
class_flags(X) ::= class_flags(A) ABSTRACT. { X.Flags = A.Flags | ZCC_Abstract; X.Replaces = A.Replaces; }
|
||||
class_flags(X) ::= class_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; X.Replaces = A.Replaces; }
|
||||
class_flags(X) ::= class_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; X.Replaces = A.Replaces; }
|
||||
class_flags(X) ::= class_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; X.Replaces = A.Replaces; }
|
||||
class_flags(X) ::= class_flags(A) REPLACES dottable_id(B). { X.Flags = A.Flags; X.Replaces = B; }
|
||||
class_flags(X) ::= class_flags(A) VERSION LPAREN STRCONST(C) RPAREN. { X.Flags = A.Flags | ZCC_Version; X.Replaces = A.Replaces; X.Version = C.String->GetChars(); }
|
||||
class_flags(X) ::= . { X.Flags = 0; X.Replaces = NULL; X.Version = {0,0}; X.Sealed = NULL; }
|
||||
class_flags(X) ::= class_flags(A) ABSTRACT. { X.Flags = A.Flags | ZCC_Abstract; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = A.Sealed; }
|
||||
class_flags(X) ::= class_flags(A) FINAL. { X.Flags = A.Flags | ZCC_Final; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = A.Sealed;}
|
||||
class_flags(X) ::= class_flags(A) NATIVE. { X.Flags = A.Flags | ZCC_Native; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = A.Sealed; }
|
||||
class_flags(X) ::= class_flags(A) UI. { X.Flags = A.Flags | ZCC_UIFlag; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = A.Sealed; }
|
||||
class_flags(X) ::= class_flags(A) PLAY. { X.Flags = A.Flags | ZCC_Play; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = A.Sealed; }
|
||||
class_flags(X) ::= class_flags(A) REPLACES dottable_id(B). { X.Flags = A.Flags; X.Replaces = B; X.Version = A.Version; X.Sealed = A.Sealed; }
|
||||
class_flags(X) ::= class_flags(A) VERSION LPAREN STRCONST(C) RPAREN. { X.Flags = A.Flags | ZCC_Version; X.Replaces = A.Replaces; X.Version = C.String->GetChars(); X.Sealed = A.Sealed; }
|
||||
class_flags(X) ::= class_flags(A) SEALED LPAREN states_opt(B) RPAREN. { X.Flags = A.Flags | ZCC_Sealed; X.Replaces = A.Replaces; X.Version = A.Version; X.Sealed = B; }
|
||||
|
||||
/*----- Dottable Identifier -----*/
|
||||
// This can be either a single identifier or two identifiers connected by a .
|
||||
|
|
@ -374,6 +378,15 @@ flag_def(X) ::= FLAGDEF(T) IDENTIFIER(A) COLON IDENTIFIER(B) COMMA INTCONST(C) S
|
|||
X = def;
|
||||
}
|
||||
|
||||
flag_def(X) ::= FLAGDEF(T) INTERNAL IDENTIFIER(A) COLON IDENTIFIER(B) COMMA INTCONST(C) SEMICOLON.
|
||||
{
|
||||
NEW_AST_NODE(FlagDef,def,T);
|
||||
def->NodeName = A.Name();
|
||||
def->RefName = B.Name();
|
||||
def->BitValue = C.Int | 0x10000;
|
||||
X = def;
|
||||
}
|
||||
|
||||
|
||||
identifier_list(X) ::= IDENTIFIER(A).
|
||||
{
|
||||
|
|
@ -433,6 +446,7 @@ struct_member(X) ::= declarator(A). { X = A; /*X-overwrites-A*/ }
|
|||
struct_member(X) ::= enum_def(A). { X = A; /*X-overwrites-A*/ }
|
||||
struct_member(X) ::= const_def(A). { X = A; /*X-overwrites-A*/ }
|
||||
struct_member(X) ::= staticarray_statement(A). { X = A; /*X-overwrites-A*/ }
|
||||
struct_member(X) ::= flag_def(A). { X = A; /*X-overwrites-A*/ }
|
||||
|
||||
/*----- Constant Definition ------*/
|
||||
/* Like UnrealScript, a constant's type is implied by its value's type. */
|
||||
|
|
@ -974,6 +988,71 @@ aggregate_type(X) ::= ARRAY(T) LT type_or_array(A) GT. /* TArray<type> */
|
|||
X = arr;
|
||||
}
|
||||
|
||||
aggregate_type(X) ::= func_ptr_type(A). { X = A; /*X-overwrites-A*/ }
|
||||
|
||||
%type func_ptr_type {ZCC_FuncPtrType *}
|
||||
%type func_ptr_params {ZCC_FuncPtrParamDecl *}
|
||||
%type func_ptr_param_list {ZCC_FuncPtrParamDecl *}
|
||||
%type func_ptr_param {ZCC_FuncPtrParamDecl *}
|
||||
|
||||
//fn_ptr_flag(X) ::= . { X.Int = 0; } //implicit scope not allowed
|
||||
fn_ptr_flag(X) ::= UI. { X.Int = ZCC_UIFlag; }
|
||||
fn_ptr_flag(X) ::= PLAY. { X.Int = ZCC_Play; }
|
||||
fn_ptr_flag(X) ::= CLEARSCOPE. { X.Int = ZCC_ClearScope; }
|
||||
//fn_ptr_flag(X) ::= VIRTUALSCOPE. { X.Int = ZCC_VirtualScope; } //virtual scope not allowed
|
||||
|
||||
|
||||
func_ptr_type(X) ::= FNTYPE(T) LT fn_ptr_flag(F) type_list_or_void(A) LPAREN func_ptr_params(B) RPAREN GT. /* Function<...(...)> */
|
||||
{
|
||||
NEW_AST_NODE(FuncPtrType,fn_ptr,T);
|
||||
fn_ptr->RetType = A;
|
||||
fn_ptr->Params = B;
|
||||
fn_ptr->Scope = F.Int;
|
||||
X = fn_ptr;
|
||||
}
|
||||
|
||||
func_ptr_type(X) ::= FNTYPE(T) LT VOID GT. /* Function<void> */
|
||||
{
|
||||
NEW_AST_NODE(FuncPtrType,fn_ptr,T);
|
||||
fn_ptr->RetType = nullptr;
|
||||
fn_ptr->Params = nullptr;
|
||||
fn_ptr->Scope = -1;
|
||||
X = fn_ptr;
|
||||
}
|
||||
|
||||
func_ptr_params(X) ::= . /* empty */ { X = NULL; }
|
||||
func_ptr_params(X) ::= VOID. { X = NULL; }
|
||||
func_ptr_params(X) ::= func_ptr_param_list(X).
|
||||
|
||||
// varargs function pointers not currently supported
|
||||
//func_ptr_params(X) ::= func_ptr_param_list(A) COMMA ELLIPSIS.
|
||||
//{
|
||||
// NEW_AST_NODE(FuncPtrParamDecl,parm,stat->sc->GetMessageLine());
|
||||
// parm->Type = nullptr;
|
||||
// parm->Flags = 0;
|
||||
// X = A; /*X-overwrites-A*/
|
||||
// AppendTreeNodeSibling(X, parm);
|
||||
//}
|
||||
|
||||
func_ptr_param_list(X) ::= func_ptr_param(X).
|
||||
func_ptr_param_list(X) ::= func_ptr_param_list(A) COMMA func_ptr_param(B). { X = A; /*X-overwrites-A*/ AppendTreeNodeSibling(X, B); }
|
||||
|
||||
func_ptr_param(X) ::= func_param_flags(A) type(B).
|
||||
{
|
||||
NEW_AST_NODE(FuncPtrParamDecl,parm,A.SourceLoc ? A.SourceLoc : B->SourceLoc);
|
||||
parm->Type = B;
|
||||
parm->Flags = A.Int;
|
||||
X = parm;
|
||||
}
|
||||
|
||||
func_ptr_param(X) ::= func_param_flags(A) type(B) AND.
|
||||
{
|
||||
NEW_AST_NODE(FuncPtrParamDecl,parm,A.SourceLoc ? A.SourceLoc : B->SourceLoc);
|
||||
parm->Type = B;
|
||||
parm->Flags = A.Int | ZCC_Out;
|
||||
X = parm;
|
||||
}
|
||||
|
||||
aggregate_type(X) ::= CLASS(T) class_restrictor(A). /* class<type> */
|
||||
{
|
||||
NEW_AST_NODE(ClassType,cls,T);
|
||||
|
|
@ -1285,6 +1364,26 @@ func_param(X) ::= func_param_flags(A) type(B) IDENTIFIER(C) EQ expr(D).
|
|||
X = parm;
|
||||
}
|
||||
|
||||
func_param(X) ::= func_param_flags(A) type(B) AND IDENTIFIER(C).
|
||||
{
|
||||
NEW_AST_NODE(FuncParamDecl,parm,A.SourceLoc ? A.SourceLoc : B->SourceLoc);
|
||||
parm->Type = B;
|
||||
parm->Name = C.Name();
|
||||
parm->Flags = A.Int | ZCC_Out;
|
||||
parm->Default = nullptr;
|
||||
X = parm;
|
||||
}
|
||||
|
||||
func_param(X) ::= func_param_flags(A) type(B) AND IDENTIFIER(C) EQ expr(D).
|
||||
{
|
||||
NEW_AST_NODE(FuncParamDecl,parm,A.SourceLoc ? A.SourceLoc : B->SourceLoc);
|
||||
parm->Type = B;
|
||||
parm->Name = C.Name();
|
||||
parm->Flags = A.Int | ZCC_Out;
|
||||
parm->Default = D;
|
||||
X = parm;
|
||||
}
|
||||
|
||||
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 = T.SourceLoc; }
|
||||
func_param_flags(X) ::= func_param_flags(A) OUT(T). { X.Int = A.Int | ZCC_Out; X.SourceLoc = T.SourceLoc; }
|
||||
|
|
@ -1374,6 +1473,17 @@ primary(X) ::= LPAREN CLASS LT IDENTIFIER(A) GT RPAREN LPAREN func_expr_list(B)
|
|||
expr->Parameters = B;
|
||||
X = expr;
|
||||
}
|
||||
|
||||
primary(X) ::= LPAREN func_ptr_type(A) RPAREN LPAREN expr(B) RPAREN. [DOT] // function pointer type cast
|
||||
{
|
||||
NEW_AST_NODE(FunctionPtrCast, expr, A);
|
||||
expr->Operation = PEX_FunctionPtrCast;
|
||||
A->ArraySize = NULL;
|
||||
expr->PtrType = A;
|
||||
expr->Expr = B;
|
||||
X = expr;
|
||||
}
|
||||
|
||||
primary(X) ::= primary(A) LBRACKET expr(B) RBRACKET. [DOT] // Array access
|
||||
{
|
||||
NEW_AST_NODE(ExprBinary, expr, B);
|
||||
|
|
@ -1383,6 +1493,7 @@ primary(X) ::= primary(A) LBRACKET expr(B) RBRACKET. [DOT] // Array access
|
|||
expr->Right = B;
|
||||
X = expr;
|
||||
}
|
||||
|
||||
primary(X) ::= primary(A) DOT IDENTIFIER(B). // Member access
|
||||
{
|
||||
NEW_AST_NODE(ExprMemberAccess, expr, B);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,13 @@ double GetFloatConst(FxExpression *ex, FCompileContext &ctx)
|
|||
return ex ? static_cast<FxConstant*>(ex)->GetValue().GetFloat() : 0;
|
||||
}
|
||||
|
||||
VMFunction* GetFuncConst(FxExpression* ex, FCompileContext& ctx)
|
||||
{
|
||||
ex = new FxTypeCast(ex, TypeVMFunction, false);
|
||||
ex = ex->Resolve(ctx);
|
||||
return static_cast<VMFunction*>(ex ? static_cast<FxConstant*>(ex)->GetValue().GetPointer() : nullptr);
|
||||
}
|
||||
|
||||
const char * ZCCCompiler::GetStringConst(FxExpression *ex, FCompileContext &ctx)
|
||||
{
|
||||
ex = new FxStringCast(ex);
|
||||
|
|
@ -452,6 +459,11 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZC
|
|||
}
|
||||
break;
|
||||
|
||||
case AST_FlagDef:
|
||||
cls->FlagDefs.Push(static_cast<ZCC_FlagDef*>(node));
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
assert(0 && "Unhandled AST node type");
|
||||
break;
|
||||
|
|
@ -662,7 +674,7 @@ void ZCCCompiler::MessageV(ZCC_TreeNode *node, const char *txtcolor, const char
|
|||
composed.Format("%s%s, line %d: ", txtcolor, node->SourceName->GetChars(), node->SourceLoc);
|
||||
composed.VAppendFormat(msg, argptr);
|
||||
composed += '\n';
|
||||
PrintString(PRINT_HIGH, composed);
|
||||
PrintString(PRINT_HIGH, composed.GetChars());
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
@ -792,8 +804,14 @@ void ZCCCompiler::CreateClassTypes()
|
|||
PClass *parent;
|
||||
auto ParentName = c->cls->ParentName;
|
||||
|
||||
if (ParentName != nullptr && ParentName->SiblingNext == ParentName) parent = PClass::FindClass(ParentName->Id);
|
||||
else if (ParentName == nullptr) parent = RUNTIME_CLASS(DObject);
|
||||
if (ParentName != nullptr && ParentName->SiblingNext == ParentName)
|
||||
{
|
||||
parent = PClass::FindClass(ParentName->Id);
|
||||
}
|
||||
else if (ParentName == nullptr)
|
||||
{
|
||||
parent = RUNTIME_CLASS(DObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The parent is a dotted name which the type system currently does not handle.
|
||||
|
|
@ -813,6 +831,15 @@ void ZCCCompiler::CreateClassTypes()
|
|||
|
||||
if (parent != nullptr && (parent->VMType != nullptr || c->NodeName() == NAME_Object))
|
||||
{
|
||||
if(parent->bFinal)
|
||||
{
|
||||
Error(c->cls, "Class '%s' cannot extend final class '%s'", FName(c->NodeName()).GetChars(), parent->TypeName.GetChars());
|
||||
}
|
||||
else if(parent->bSealed && !parent->SealedRestriction.Contains(c->NodeName()))
|
||||
{
|
||||
Error(c->cls, "Class '%s' cannot extend sealed class '%s'", FName(c->NodeName()).GetChars(), parent->TypeName.GetChars());
|
||||
}
|
||||
|
||||
// The parent exists, we may create a type for this class
|
||||
if (c->cls->Flags & ZCC_Native)
|
||||
{
|
||||
|
|
@ -874,6 +901,25 @@ void ZCCCompiler::CreateClassTypes()
|
|||
{
|
||||
c->Type()->mVersion = c->cls->Version;
|
||||
}
|
||||
|
||||
|
||||
if (c->cls->Flags & ZCC_Final)
|
||||
{
|
||||
c->ClassType()->bFinal = true;
|
||||
}
|
||||
|
||||
if (c->cls->Flags & ZCC_Sealed)
|
||||
{
|
||||
PClass * ccls = c->ClassType();
|
||||
ccls->bSealed = true;
|
||||
ZCC_Identifier * it = c->cls->Sealed;
|
||||
if(it) do
|
||||
{
|
||||
ccls->SealedRestriction.Push(FName(it->Id));
|
||||
it = (ZCC_Identifier*) it->SiblingNext;
|
||||
}
|
||||
while(it != c->cls->Sealed);
|
||||
}
|
||||
//
|
||||
if (mVersion >= MakeVersion(2, 4, 0))
|
||||
{
|
||||
|
|
@ -1866,19 +1912,17 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
|||
auto keytype = DetermineType(outertype, field, name, mtype->KeyType, false, false);
|
||||
auto valuetype = DetermineType(outertype, field, name, mtype->ValueType, false, false);
|
||||
|
||||
if (keytype->GetRegType() == REGT_INT)
|
||||
if (keytype->GetRegType() != REGT_STRING && !(keytype->GetRegType() == REGT_INT && keytype->Size == 4))
|
||||
{
|
||||
if (keytype->Size != 4)
|
||||
if(name != NAME_None)
|
||||
{
|
||||
Error(field, "%s : Map<%s , ...> not implemented yet", name.GetChars(), keytype->DescriptiveName());
|
||||
}
|
||||
else
|
||||
{
|
||||
Error(field, "Map<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (keytype->GetRegType() != REGT_STRING)
|
||||
{
|
||||
Error(field, "Map<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||
break;
|
||||
}
|
||||
|
||||
switch(valuetype->GetRegType())
|
||||
{
|
||||
|
|
@ -1888,14 +1932,20 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
|||
case REGT_POINTER:
|
||||
if (valuetype->GetRegCount() > 1)
|
||||
{
|
||||
Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||
default:
|
||||
if(name != NAME_None)
|
||||
{
|
||||
Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||
}
|
||||
else
|
||||
{
|
||||
Error(field, "Base type for map value types must be integral, but got %s", valuetype->DescriptiveName());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
retval = NewMap(keytype, valuetype);
|
||||
break;
|
||||
default:
|
||||
Error(field, "%s: Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -1913,17 +1963,17 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
|||
auto keytype = DetermineType(outertype, field, name, mtype->KeyType, false, false);
|
||||
auto valuetype = DetermineType(outertype, field, name, mtype->ValueType, false, false);
|
||||
|
||||
if (keytype->GetRegType() == REGT_INT)
|
||||
if (keytype->GetRegType() != REGT_STRING && !(keytype->GetRegType() == REGT_INT && keytype->Size == 4))
|
||||
{
|
||||
if (keytype->Size != 4)
|
||||
if(name != NAME_None)
|
||||
{
|
||||
Error(field, "%s : MapIterator<%s , ...> not implemented yet", name.GetChars(), keytype->DescriptiveName());
|
||||
}
|
||||
else
|
||||
{
|
||||
Error(field, "MapIterator<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||
}
|
||||
}
|
||||
else if (keytype->GetRegType() != REGT_STRING)
|
||||
{
|
||||
Error(field, "MapIterator<%s , ...> not implemented yet", keytype->DescriptiveName());
|
||||
}
|
||||
|
||||
switch(valuetype->GetRegType())
|
||||
{
|
||||
|
|
@ -1933,13 +1983,19 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
|||
case REGT_POINTER:
|
||||
if (valuetype->GetRegCount() > 1)
|
||||
{
|
||||
Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||
default:
|
||||
if(name != NAME_None)
|
||||
{
|
||||
Error(field, "%s : Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||
}
|
||||
else
|
||||
{
|
||||
Error(field, "Base type for map value types must be integral, but got %s", valuetype->DescriptiveName());
|
||||
}
|
||||
break;
|
||||
}
|
||||
retval = NewMapIterator(keytype, valuetype);
|
||||
break;
|
||||
default:
|
||||
Error(field, "%s: Base type for map value types must be integral, but got %s", name.GetChars(), valuetype->DescriptiveName());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1968,6 +2024,52 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
|||
}
|
||||
break;
|
||||
}
|
||||
case AST_FuncPtrType:
|
||||
{
|
||||
auto fn = static_cast<ZCC_FuncPtrType*>(ztype);
|
||||
|
||||
if(fn->Scope == -1)
|
||||
{ // Function<void>
|
||||
retval = NewFunctionPointer(nullptr, {}, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
TArray<PType*> returns;
|
||||
TArray<PType*> args;
|
||||
TArray<uint32_t> argflags;
|
||||
|
||||
if(auto *t = fn->RetType; t != nullptr) do {
|
||||
returns.Push(DetermineType(outertype, field, name, t, false, false));
|
||||
} while( (t = (ZCC_Type *)t->SiblingNext) != fn->RetType);
|
||||
|
||||
if(auto *t = fn->Params; t != nullptr) do {
|
||||
args.Push(DetermineType(outertype, field, name, t->Type, false, false));
|
||||
argflags.Push(t->Flags == ZCC_Out ? VARF_Out : 0);
|
||||
} while( (t = (ZCC_FuncPtrParamDecl *) t->SiblingNext) != fn->Params);
|
||||
|
||||
auto proto = NewPrototype(returns,args);
|
||||
switch(fn->Scope)
|
||||
{ // only play/ui/clearscope functions are allowed, no data or virtual scope functions
|
||||
case ZCC_Play:
|
||||
fn->Scope = FScopeBarrier::Side_Play;
|
||||
break;
|
||||
case ZCC_UIFlag:
|
||||
fn->Scope = FScopeBarrier::Side_UI;
|
||||
break;
|
||||
case ZCC_ClearScope:
|
||||
fn->Scope = FScopeBarrier::Side_PlainData;
|
||||
break;
|
||||
case 0:
|
||||
fn->Scope = -1;
|
||||
break;
|
||||
default:
|
||||
Error(field, "Invalid Scope for Function Pointer");
|
||||
break;
|
||||
}
|
||||
retval = NewFunctionPointer(proto, std::move(argflags), fn->Scope);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AST_ClassType:
|
||||
{
|
||||
auto ctype = static_cast<ZCC_ClassType *>(ztype);
|
||||
|
|
@ -2244,6 +2346,11 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
|||
Error(f, "The return type of a function cannot be a dynamic array");
|
||||
break;
|
||||
}
|
||||
else if (type->isMap())
|
||||
{
|
||||
Error(f, "The return type of a function cannot be a map");
|
||||
break;
|
||||
}
|
||||
else if (type == TypeFVector2)
|
||||
{
|
||||
type = TypeVector2;
|
||||
|
|
@ -2931,6 +3038,17 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast, bool substitute)
|
|||
return new FxClassPtrCast(cls, ConvertNode(cc->Parameters));
|
||||
}
|
||||
|
||||
case AST_FunctionPtrCast:
|
||||
{
|
||||
auto cast = static_cast<ZCC_FunctionPtrCast *>(ast);
|
||||
|
||||
auto type = DetermineType(ConvertClass, cast, NAME_None, cast->PtrType, false, false);
|
||||
assert(type->isFunctionPointer());
|
||||
auto ptrType = static_cast<PFunctionPointer*>(type);
|
||||
|
||||
return new FxFunctionPtrCast(ptrType, ConvertNode(cast->Expr));
|
||||
}
|
||||
|
||||
case AST_StaticArrayStatement:
|
||||
{
|
||||
auto sas = static_cast<ZCC_StaticArrayStatement *>(ast);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
struct Baggage;
|
||||
struct FPropertyInfo;
|
||||
class AActor;
|
||||
class FxExpression;
|
||||
typedef TDeletingArray<FxExpression*> FArgumentList;
|
||||
|
||||
|
|
@ -23,6 +22,7 @@ struct ZCC_StructWork
|
|||
TArray<ZCC_VarDeclarator *> Fields;
|
||||
TArray<ZCC_FuncDeclarator *> Functions;
|
||||
TArray<ZCC_StaticArrayStatement *> Arrays;
|
||||
TArray<ZCC_FlagDef*> FlagDefs;
|
||||
|
||||
ZCC_StructWork()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ xx(FuncCall, '(')
|
|||
xx(ArrayAccess, TK_Array)
|
||||
xx(MemberAccess, '.')
|
||||
xx(ClassCast, TK_Class)
|
||||
xx(FunctionPtrCast, TK_FunctionType)
|
||||
xx(TypeRef, TK_Class)
|
||||
xx(Vector, TK_Vector2)
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static FString ResolveIncludePath(const FString &path,const FString &lumpname){
|
|||
|
||||
auto end = lumpname.LastIndexOf("/"); // find last '/'
|
||||
|
||||
// it's a top-level file, if it's a folder being loaded ( /xxx/yyy/:whatever.zs ) end is before than start, or if it's a zip ( xxx.zip/whatever.zs ) end would be -1
|
||||
// it's a top-level file, if it's a folder being loaded ( /xxx/yyy/:whatever.zs ) end is before than start, or if it's a zip ( xxx.zip:whatever.zs ) end would be -1
|
||||
bool topLevelFile = start > end ;
|
||||
|
||||
FString fullPath = topLevelFile ? FString {} : lumpname.Mid(start + 1, end - start - 1); // get path from lumpname (format 'wad:filepath/filename')
|
||||
|
|
@ -222,6 +222,7 @@ static void InitTokenMap()
|
|||
TOKENDEF2(TK_Map, ZCC_MAP, NAME_Map);
|
||||
TOKENDEF2(TK_MapIterator, ZCC_MAPITERATOR,NAME_MapIterator);
|
||||
TOKENDEF2(TK_Array, ZCC_ARRAY, NAME_Array);
|
||||
TOKENDEF2(TK_FunctionType, ZCC_FNTYPE, NAME_Function);
|
||||
TOKENDEF2(TK_Include, ZCC_INCLUDE, NAME_Include);
|
||||
TOKENDEF (TK_Void, ZCC_VOID);
|
||||
TOKENDEF (TK_True, ZCC_TRUE);
|
||||
|
|
@ -232,6 +233,7 @@ static void InitTokenMap()
|
|||
TOKENDEF (TK_Out, ZCC_OUT);
|
||||
TOKENDEF (TK_Super, ZCC_SUPER);
|
||||
TOKENDEF (TK_Null, ZCC_NULLPTR);
|
||||
TOKENDEF (TK_Sealed, ZCC_SEALED);
|
||||
TOKENDEF ('~', ZCC_TILDE);
|
||||
TOKENDEF ('!', ZCC_BANG);
|
||||
TOKENDEF (TK_SizeOf, ZCC_SIZEOF);
|
||||
|
|
@ -407,8 +409,6 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state)
|
|||
int lumpnum = baselump;
|
||||
auto fileno = fileSystem.GetFileContainer(lumpnum);
|
||||
|
||||
FString file = fileSystem.GetFileFullPath(lumpnum);
|
||||
|
||||
state.FileNo = fileno;
|
||||
|
||||
if (TokenMap.CountUsed() == 0)
|
||||
|
|
@ -473,7 +473,7 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state)
|
|||
ParseSingleFile(&sc, nullptr, lumpnum, parser, state);
|
||||
for (unsigned i = 0; i < Includes.Size(); i++)
|
||||
{
|
||||
lumpnum = fileSystem.CheckNumForFullName(Includes[i], true);
|
||||
lumpnum = fileSystem.CheckNumForFullName(Includes[i].GetChars(), true);
|
||||
if (lumpnum == -1)
|
||||
{
|
||||
IncludeLocs[i].Message(MSG_ERROR, "Include script lump %s not found", Includes[i].GetChars());
|
||||
|
|
@ -503,7 +503,7 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state)
|
|||
// If the parser fails, there is no point starting the compiler, because it'd only flood the output with endless errors.
|
||||
if (FScriptPosition::ErrorCounter > 0)
|
||||
{
|
||||
I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, fileSystem.GetFileFullPath(baselump).GetChars());
|
||||
I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, fileSystem.GetFileFullPath(baselump).c_str());
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
@ -517,10 +517,10 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state)
|
|||
if (Args->CheckParm("-dumpast"))
|
||||
{
|
||||
FString ast = ZCC_PrintAST(state.TopNode);
|
||||
FString filename = fileSystem.GetFileFullPath(baselump);
|
||||
FString filename = fileSystem.GetFileFullPath(baselump).c_str();
|
||||
filename.ReplaceChars(":\\/?|", '.');
|
||||
filename << ".ast";
|
||||
FileWriter *ff = FileWriter::Open(filename);
|
||||
FileWriter *ff = FileWriter::Open(filename.GetChars());
|
||||
if (ff != NULL)
|
||||
{
|
||||
ff->Write(ast.GetChars(), ast.Len());
|
||||
|
|
@ -926,6 +926,29 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c
|
|||
break;
|
||||
}
|
||||
|
||||
case AST_FuncPtrParamDecl:
|
||||
{
|
||||
TreeNodeDeepCopy_Start(FuncPtrParamDecl);
|
||||
|
||||
// ZCC_FuncPtrParamDecl
|
||||
copy->Type = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->Type, true, copiedNodesList));
|
||||
copy->Flags = origCasted->Flags;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AST_FuncPtrType:
|
||||
{
|
||||
TreeNodeDeepCopy_Start(FuncPtrType);
|
||||
|
||||
// ZCC_FuncPtrType
|
||||
copy->RetType = static_cast<ZCC_Type *>(TreeNodeDeepCopy_Internal(ast, origCasted->RetType, true, copiedNodesList));
|
||||
copy->Params = static_cast<ZCC_FuncPtrParamDecl *>(TreeNodeDeepCopy_Internal(ast, origCasted->Params, true, copiedNodesList));
|
||||
copy->Scope = origCasted->Scope;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AST_ClassType:
|
||||
{
|
||||
TreeNodeDeepCopy_Start(ClassType);
|
||||
|
|
@ -1372,7 +1395,21 @@ ZCC_TreeNode *TreeNodeDeepCopy_Internal(ZCC_AST *ast, ZCC_TreeNode *orig, bool c
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case AST_FunctionPtrCast:
|
||||
{
|
||||
TreeNodeDeepCopy_Start(FunctionPtrCast);
|
||||
|
||||
// ZCC_Expression
|
||||
copy->Operation = origCasted->Operation;
|
||||
copy->Type = origCasted->Type;
|
||||
// ZCC_FunctionPtrCast
|
||||
copy->PtrType = static_cast<ZCC_FuncPtrType *>(TreeNodeDeepCopy_Internal(ast, origCasted->PtrType, true, copiedNodesList));
|
||||
copy->Expr = static_cast<ZCC_Expression *>(TreeNodeDeepCopy_Internal(ast, origCasted->Expr, true, copiedNodesList));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AST_StaticArrayStatement:
|
||||
{
|
||||
TreeNodeDeepCopy_Start(StaticArrayStatement);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ enum
|
|||
ZCC_VirtualScope = 1 << 20,
|
||||
ZCC_Version = 1 << 21,
|
||||
ZCC_Internal = 1 << 22,
|
||||
ZCC_Sealed = 1 << 23,
|
||||
};
|
||||
|
||||
// Function parameter modifiers
|
||||
|
|
@ -100,6 +101,8 @@ enum EZCCTreeNodeType
|
|||
AST_MapType,
|
||||
AST_MapIteratorType,
|
||||
AST_DynArrayType,
|
||||
AST_FuncPtrParamDecl,
|
||||
AST_FuncPtrType,
|
||||
AST_ClassType,
|
||||
AST_Expression,
|
||||
AST_ExprID,
|
||||
|
|
@ -135,6 +138,7 @@ enum EZCCTreeNodeType
|
|||
AST_VectorValue,
|
||||
AST_DeclFlags,
|
||||
AST_ClassCast,
|
||||
AST_FunctionPtrCast,
|
||||
AST_StaticArrayStatement,
|
||||
AST_Property,
|
||||
AST_FlagDef,
|
||||
|
|
@ -251,6 +255,7 @@ struct ZCC_Class : ZCC_Struct
|
|||
{
|
||||
ZCC_Identifier *ParentName;
|
||||
ZCC_Identifier *Replaces;
|
||||
ZCC_Identifier *Sealed;
|
||||
|
||||
PClass *CType() { return static_cast<PClassType *>(Type)->Descriptor; }
|
||||
};
|
||||
|
|
@ -380,6 +385,19 @@ struct ZCC_DynArrayType : ZCC_Type
|
|||
ZCC_Type *ElementType;
|
||||
};
|
||||
|
||||
struct ZCC_FuncPtrParamDecl : ZCC_TreeNode
|
||||
{
|
||||
ZCC_Type *Type;
|
||||
int Flags;
|
||||
};
|
||||
|
||||
struct ZCC_FuncPtrType : ZCC_Type
|
||||
{
|
||||
ZCC_Type *RetType;
|
||||
ZCC_FuncPtrParamDecl *Params;
|
||||
int Scope;
|
||||
};
|
||||
|
||||
struct ZCC_ClassType : ZCC_Type
|
||||
{
|
||||
ZCC_Identifier *Restriction;
|
||||
|
|
@ -426,6 +444,12 @@ struct ZCC_ClassCast : ZCC_Expression
|
|||
ZCC_FuncParm *Parameters;
|
||||
};
|
||||
|
||||
struct ZCC_FunctionPtrCast : ZCC_Expression
|
||||
{
|
||||
ZCC_FuncPtrType *PtrType;
|
||||
ZCC_Expression *Expr;
|
||||
};
|
||||
|
||||
struct ZCC_ExprMemberAccess : ZCC_Expression
|
||||
{
|
||||
ZCC_Expression *Left;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue