Merge remote-tracking branch 'gzdoom/master' into merge-gzdoom

This commit is contained in:
Magnus Norddahl 2023-10-19 21:05:17 +02:00
commit e75e5a387b
600 changed files with 40006 additions and 59374 deletions

View file

@ -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,

View file

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

View file

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

View file

@ -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()
{

View file

@ -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)

View file

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

View file

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