From ad43f2bc7ea41211214dc25ccfd166b3deb9af68 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 9 Oct 2016 15:47:31 +0200 Subject: [PATCH] - parse the list of class/struct fields and add the PField entries to their type. - fixed a few issues with trying to access a class's Type before it got initialized. --- src/dobjtype.cpp | 17 + src/dobjtype.h | 18 +- src/namedef.h | 2 + src/zscript/ast.cpp | 2 +- src/zscript/zcc-parse.lemon | 1 + src/zscript/zcc_compile.cpp | 506 ++++++++++++++++++++++++++-- src/zscript/zcc_compile.h | 19 +- src/zscript/zcc_parser.h | 4 +- wadsrc/static/zscript/constants.txt | 9 +- 9 files changed, 528 insertions(+), 50 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 800416612c..78e57c2292 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -82,6 +82,8 @@ PName *TypeName; PSound *TypeSound; PColor *TypeColor; PStatePointer *TypeState; +PStruct *TypeVector2; +PStruct *TypeVector3; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -590,6 +592,19 @@ void PType::StaticInit() TypeTable.AddType(TypeColor = new PColor); TypeTable.AddType(TypeState = new PStatePointer); + TypeVector2 = new PStruct(NAME_Vector2, nullptr); + TypeVector2->AddField(NAME_X, TypeFloat64); + TypeVector2->AddField(NAME_Y, TypeFloat64); + TypeTable.AddType(TypeVector2); + + TypeVector3 = new PStruct(NAME_Vector3, nullptr); + TypeVector3->AddField(NAME_X, TypeFloat64); + TypeVector3->AddField(NAME_Y, TypeFloat64); + TypeVector3->AddField(NAME_Z, TypeFloat64); + TypeTable.AddType(TypeVector3); + + + GlobalSymbols.AddSymbol(new PSymbolType(NAME_sByte, TypeSInt8)); GlobalSymbols.AddSymbol(new PSymbolType(NAME_Byte, TypeUInt8)); GlobalSymbols.AddSymbol(new PSymbolType(NAME_Short, TypeSInt16)); @@ -606,6 +621,8 @@ void PType::StaticInit() GlobalSymbols.AddSymbol(new PSymbolType(NAME_Sound, TypeSound)); GlobalSymbols.AddSymbol(new PSymbolType(NAME_Color, TypeColor)); GlobalSymbols.AddSymbol(new PSymbolType(NAME_State, TypeState)); + GlobalSymbols.AddSymbol(new PSymbolType(NAME_Vector2, TypeVector2)); + GlobalSymbols.AddSymbol(new PSymbolType(NAME_Vector3, TypeVector3)); } diff --git a/src/dobjtype.h b/src/dobjtype.h index 92316107f6..b776fa165d 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -14,11 +14,17 @@ typedef std::pair FTypeAndOffset; // Making all these different storage types use a common set of flags seems // like the simplest thing to do. -#define VARF_Optional (1<<0) // func param is optional -#define VARF_Method (1<<1) // func has an implied self parameter -#define VARF_Action (1<<2) // func has implied owner and state parameters -#define VARF_Native (1<<3) // func is native code/don't auto serialize field -#define VARF_ReadOnly (1<<4) // field is read only, do not write to it +enum +{ + VARF_Optional = (1<<0), // func param is optional + VARF_Method = (1<<1), // func has an implied self parameter + VARF_Action = (1<<2), // func has implied owner and state parameters + VARF_Native = (1<<3), // func is native code/don't auto serialize field + VARF_ReadOnly = (1<<4), // field is read only, do not write to it + VARF_Private = (1<<5), // field is private to containing class + VARF_Protected = (1<<6), // field is only accessible by containing class and children. + VARF_Deprecated = (1<<7), // Deprecated fields should output warnings when used. +}; // Symbol information ------------------------------------------------------- @@ -872,6 +878,8 @@ extern PString *TypeString; extern PName *TypeName; extern PSound *TypeSound; extern PColor *TypeColor; +extern PStruct *TypeVector2; +extern PStruct *TypeVector3; extern PStatePointer *TypeState; // A constant value --------------------------------------------------------- diff --git a/src/namedef.h b/src/namedef.h index 36953e385f..f07db2ce94 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -697,6 +697,8 @@ xx(Array) xx(Sound) xx(State) xx(Fixed) +xx(Vector2) +xx(Vector3) xx(Min) xx(Max) diff --git a/src/zscript/ast.cpp b/src/zscript/ast.cpp index a0a823b130..26601d6582 100644 --- a/src/zscript/ast.cpp +++ b/src/zscript/ast.cpp @@ -65,7 +65,7 @@ public: FLispString() { NestDepth = Column = 0; - WrapWidth = 72; + WrapWidth = 200; NeedSpace = false; ConsecOpens = 0; } diff --git a/src/zscript/zcc-parse.lemon b/src/zscript/zcc-parse.lemon index 7acc392128..564b33b74d 100644 --- a/src/zscript/zcc-parse.lemon +++ b/src/zscript/zcc-parse.lemon @@ -290,6 +290,7 @@ enum_def(X) ::= ENUM(T) IDENTIFIER(A) enum_type(B) LBRACE opt_enum_list(C) RBRAC def->NodeName = A.Name(); def->EnumType = (EZCCBuiltinType)B.Int; def->Elements = C; + def->Symbol = nullptr; // If the first element does not have an explicit value, make it 0. if (C != NULL) diff --git a/src/zscript/zcc_compile.cpp b/src/zscript/zcc_compile.cpp index 0ecd60dee7..10f84b1d38 100644 --- a/src/zscript/zcc_compile.cpp +++ b/src/zscript/zcc_compile.cpp @@ -60,28 +60,47 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) auto node = cnode->Body; PSymbolTreeNode *childnode; + ZCC_Enum *enumType = nullptr; - do + // Need to check if the class actually has a body. + if (node != nullptr) do { switch (node->NodeType) { case AST_Struct: case AST_ConstantDef: - case AST_VarDeclarator: + case AST_Enum: if ((childnode = AddNamedNode(static_cast(node), &treenode->TreeNodes))) { switch (node->NodeType) { - case AST_Struct: cls.Structs.Push(ZCC_StructWork(static_cast(node), childnode)); break; - case AST_ConstantDef: cls.Constants.Push(static_cast(node)); break; - case AST_VarDeclarator: cls.Fields.Push(static_cast(node)); break; - default: assert(0 && "Default case is just here to make GCC happy. It should never be reached"); + case AST_Enum: + enumType = static_cast(node); + cls.Enums.Push(enumType); + break; + + case AST_Struct: + ProcessStruct(static_cast(node), childnode, cls.cls); + break; + + case AST_ConstantDef: + cls.Constants.Push(static_cast(node)); + cls.Constants.Last()->Type = enumType; + break; + + default: + assert(0 && "Default case is just here to make GCC happy. It should never be reached"); } } break; - case AST_Enum: break; - case AST_EnumTerminator:break; + case AST_VarDeclarator: + cls.Fields.Push(static_cast(node)); + break; + + case AST_EnumTerminator: + enumType = nullptr; + break; // todo case AST_States: @@ -100,37 +119,53 @@ void ZCCCompiler::ProcessClass(ZCC_Class *cnode, PSymbolTreeNode *treenode) //========================================================================== // -// ZCCCompiler :: ProcessClass +// ZCCCompiler :: ProcessStruct // //========================================================================== -void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode) +void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode, ZCC_Class *outer) { - Structs.Push(ZCC_StructWork(static_cast(cnode), treenode)); + Structs.Push(ZCC_StructWork(static_cast(cnode), treenode, outer)); ZCC_StructWork &cls = Structs.Last(); auto node = cnode->Body; PSymbolTreeNode *childnode; + ZCC_Enum *enumType = nullptr; - do + // Need to check if the struct actually has a body. + if (node != nullptr) do { switch (node->NodeType) { case AST_ConstantDef: - case AST_VarDeclarator: + case AST_Enum: if ((childnode = AddNamedNode(static_cast(node), &treenode->TreeNodes))) { switch (node->NodeType) { - case AST_ConstantDef: cls.Constants.Push(static_cast(node)); break; - case AST_VarDeclarator: cls.Fields.Push(static_cast(node)); break; - default: assert(0 && "Default case is just here to make GCC happy. It should never be reached"); + case AST_Enum: + enumType = static_cast(node); + cls.Enums.Push(enumType); + break; + + case AST_ConstantDef: + cls.Constants.Push(static_cast(node)); + cls.Constants.Last()->Type = enumType; + break; + + default: + assert(0 && "Default case is just here to make GCC happy. It should never be reached"); } } break; - case AST_Enum: break; - case AST_EnumTerminator:break; + case AST_VarDeclarator: + cls.Fields.Push(static_cast(node)); + break; + + case AST_EnumTerminator: + enumType = nullptr; + break; default: assert(0 && "Unhandled AST node type"); @@ -148,13 +183,16 @@ void ZCCCompiler::ProcessStruct(ZCC_Struct *cnode, PSymbolTreeNode *treenode) //========================================================================== ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, PSymbolTable &_outsymbols) -: Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast), ErrorCount(0), WarnCount(0) + : Outer(_outer), GlobalTreeNodes(&_symbols), OutputSymbols(&_outsymbols), AST(ast), ErrorCount(0), WarnCount(0) { // Group top-level nodes by type if (ast.TopNode != NULL) { ZCC_TreeNode *node = ast.TopNode; PSymbolTreeNode *tnode; + PType *enumType = nullptr; + ZCC_Enum *zenumType = nullptr; + do { switch (node->NodeType) @@ -162,28 +200,46 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, case AST_Class: case AST_Struct: case AST_ConstantDef: + case AST_Enum: if ((tnode = AddNamedNode(static_cast(node), GlobalTreeNodes))) { switch (node->NodeType) { - case AST_Class: ProcessClass(static_cast(node), tnode); break; - case AST_Struct: ProcessStruct(static_cast(node), tnode); break; - case AST_ConstantDef: Constants.Push(static_cast(node)); break; - default: assert(0 && "Default case is just here to make GCC happy. It should never be reached"); + case AST_Enum: + zenumType = static_cast(node); + enumType = NewEnum(zenumType->NodeName, nullptr); + GlobalSymbols.AddSymbol(new PSymbolType(zenumType->NodeName, enumType)); + break; + + case AST_Class: + ProcessClass(static_cast(node), tnode); + break; + + case AST_Struct: + ProcessStruct(static_cast(node), tnode, nullptr); + break; + + case AST_ConstantDef: + Constants.Push(static_cast(node)); + Constants.Last()->Type = zenumType; + break; + + default: + assert(0 && "Default case is just here to make GCC happy. It should never be reached"); } } break; - case AST_Enum: break; - case AST_EnumTerminator:break; + case AST_EnumTerminator: + zenumType = nullptr; + break; default: assert(0 && "Unhandled AST node type"); break; } node = node->SiblingNext; - } - while (node != ast.TopNode); + } while (node != ast.TopNode); } } @@ -285,7 +341,7 @@ int ZCCCompiler::Compile() CreateClassTypes(); CreateStructTypes(); CompileAllConstants(); - //CompileAllFields(); + CompileAllFields(); return ErrorCount; } @@ -301,10 +357,17 @@ void ZCCCompiler::CreateStructTypes() { for(auto s : Structs) { - s->Type = NewStruct(s->NodeName, nullptr); + s.Outer = s.OuterDef == nullptr? nullptr : s.OuterDef->Type; + s->Type = NewStruct(s->NodeName, s.Outer); s->Symbol = new PSymbolType(s->NodeName, s->Type); s->Type->Symbols.SetName(FName(s->NodeName)); GlobalSymbols.AddSymbol(s->Symbol); + + for (auto e : s.Enums) + { + auto etype = NewEnum(e->NodeName, s->Type); + s->Type->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); + } } } @@ -427,6 +490,16 @@ void ZCCCompiler::CreateClassTypes() GlobalSymbols.AddSymbol(c->Symbol); Classes.Push(c); } + + // Last but not least: Now that all classes have been created, we can create the symbols for the internal enums + for (auto cd : Classes) + { + for (auto e : cd.Enums) + { + auto etype = NewEnum(e->NodeName, cd->Type); + cd->Type->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); + } + } } //========================================================================== @@ -464,10 +537,6 @@ void ZCCCompiler::CompileAllConstants() for (auto &c : Classes) { CopyConstants(constantwork, c.Constants, &c->Type->Symbols); - for (auto &s : c.Structs) - { - CopyConstants(constantwork, s.Constants, &s->Type->Symbols); - } } for (auto &s : Structs) { @@ -529,10 +598,16 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) } else if (cval->Type->IsA(RUNTIME_CLASS(PInt))) { + // How do we get an Enum type in here without screwing everything up??? + //auto type = def->Type != nullptr ? def->Type : cval->Type; def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal); } else if (cval->Type->IsA(RUNTIME_CLASS(PFloat))) { + if (def->Type != nullptr) + { + Error(def, "Enum members must be integer values"); + } def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->DoubleVal); } else @@ -974,3 +1049,368 @@ ZCC_ExprTypeRef *ZCCCompiler::NodeFromSymbolType(PSymbolType *sym, ZCC_Expressio ref->Type = NewClassPointer(RUNTIME_CLASS(PType)); return ref; } + +//========================================================================== +// +// ZCCCompiler :: CompileAllFields +// +// builds the internal structure of all classes and structs +// +//========================================================================== + +void ZCCCompiler::CompileAllFields() +{ + // Create copies of the arrays which can be altered + auto Classes = this->Classes; + auto Structs = this->Structs; + + // first step: Look for native classes with native children. + // These may not have any variables added to them because it'd clash with the native definitions. + for (unsigned i = 0; i < Classes.Size(); i++) + { + auto c = Classes[i]; + + if (c->Type->Size != TentativeClass && c.Fields.Size() > 0) + { + // We need to search the global class table here because not all children may have a scripted definition attached. + for (auto ac : PClass::AllClasses) + { + if (ac->ParentClass == c->Type && ac->Size != TentativeClass) + { + Error(c, "Trying to add fields to class '%s' with native children", c->Type->TypeName.GetChars()); + Classes.Delete(i); + i--; + break; + } + } + } + } + bool donesomething = true; + while (donesomething && (Structs.Size() > 0 || Classes.Size() > 0)) + { + donesomething = false; + for (unsigned i = 0; i < Structs.Size(); i++) + { + if (CompileFields(Structs[i]->Type, Structs[i].Fields, Structs[i].Outer, true)) + { + // Remove from the list if all fields got compiled. + Structs.Delete(i); + i--; + donesomething = true; + } + } + for (unsigned i = 0; i < Classes.Size(); i++) + { + if (Classes[i]->Type->Size == TentativeClass) + { + if (Classes[i]->Type->ParentClass->Size == TentativeClass) + { + // we do not know the parent class's size yet, so skip this class for now. + continue; + } + else + { + // Inherit the size of the parent class + Classes[i]->Type->Size = Classes[i]->Type->ParentClass->Size; + } + } + if (CompileFields(Classes[i]->Type, Classes[i].Fields, nullptr, false)) + { + // Remove from the list if all fields got compiled. + Classes.Delete(i); + i--; + donesomething = true; + } + } + } + // report all entries + if (Structs.Size() > 0) + { + } + if (Classes.Size() > 0) + { + } +} + +//========================================================================== +// +// ZCCCompiler :: CompileFields +// +// builds the internal structure of a single class or struct +// +//========================================================================== + +bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fields, PClass *Outer, bool forstruct) +{ + Printf("Adding fields to %s, original size is %d\n", type->TypeName.GetChars(), type->Size); + while (Fields.Size() > 0) + { + auto field = Fields[0]; + + PType *fieldtype = DetermineType(type, field, field->Type, true); + + // For structs only allow 'deprecated', for classes exclude function qualifiers. + int notallowed = forstruct? ~ZCC_Deprecated : ZCC_Latent | ZCC_Final | ZCC_Action | ZCC_Static | ZCC_FuncConst | ZCC_Abstract; + + if (field->Flags & notallowed) + { + Error(field, "Invalid qualifiers for %s (%s not allowed)", FName(field->Names->Name).GetChars(), FlagsToString(field->Flags & notallowed)); + field->Flags &= notallowed; + } + uint32_t varflags; + + // These map directly to implementation flags. + if (field->Flags & ZCC_Private) varflags |= VARF_Private; + if (field->Flags & ZCC_Protected) varflags |= VARF_Protected; + if (field->Flags & ZCC_Deprecated) varflags |= VARF_Deprecated; + if (field->Flags & ZCC_ReadOnly) varflags |= VARF_ReadOnly; + + if (field->Flags & ZCC_Native) + { + // todo: get the native address of this field. + } + if (field->Flags & ZCC_Meta) + { + varflags |= VARF_ReadOnly; // metadata implies readonly + // todo: this needs to go into the metaclass and needs some handling + } + + if (field->Type->ArraySize != nullptr) + { + fieldtype = ResolveArraySize(fieldtype, field->Type->ArraySize, &type->Symbols); + } + + auto name = field->Names; + do + { + auto thisfieldtype = fieldtype; + if (name->ArraySize != nullptr) + { + thisfieldtype = ResolveArraySize(thisfieldtype, name->ArraySize, &type->Symbols); + } + + type->AddField(name->Name, thisfieldtype, varflags); + Printf("Added field %s, new size is %d\n", FName(name->Name).GetChars(), type->Size); + name = static_cast(name->SiblingNext); + } while (name != field->Names); + Fields.Delete(0); + + + + + } + if (Fields.Size() > 0) + { + Printf("%d fields unprocessed\n", Fields.Size()); + } + return Fields.Size() == 0; +} + +//========================================================================== +// +// ZCCCompiler :: FieldFlagsToString +// +// creates a string for a field's flags +// +//========================================================================== + +FString ZCCCompiler::FlagsToString(uint32_t flags) +{ + const char *flagnames[] = { "native", "static", "private", "protected", "latent", "final", "meta", "action", "deprecated", "readonly", "funcconst", "abstract" }; + FString build; + + for (int i = 0; i < 12; i++) + { + if (flags & (1 << i)) + { + if (build.IsNotEmpty()) build += ", "; + build += flagnames[i]; + } + } + return build; +} + +//========================================================================== +// +// ZCCCompiler :: DetermineType +// +// retrieves the type for this field, for arrays the type of a single entry. +// +//========================================================================== + +PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZCC_Type *ztype, bool allowarraytypes) +{ + if (!allowarraytypes && ztype->ArraySize != nullptr) + { + Error(field, "%s: Array type not allowed", FName(field->Names->Name).GetChars()); + return TypeError; + } + switch (ztype->NodeType) + { + case AST_BasicType: + { + auto btype = static_cast(ztype); + switch (btype->Type) + { + case ZCC_SInt8: + return TypeSInt8; + + case ZCC_UInt8: + return TypeUInt8; + + case ZCC_SInt16: + return TypeSInt16; + + case ZCC_UInt16: + return TypeUInt16; + + case ZCC_SInt32: + case ZCC_IntAuto: // todo: for enums, autoselect appropriately sized int + return TypeSInt32; + + case ZCC_UInt32: + return TypeUInt32; + + case ZCC_Bool: + return TypeBool; + + // Do we really want to allow single precision floats, despite all the problems they cause? + // These are nearly guaranteed to desync between MSVC and GCC on x87, because GCC does not implement an IEEE compliant mode + case ZCC_Float32: + case ZCC_FloatAuto: + //return TypeFloat32; + case ZCC_Float64: + return TypeFloat64; + + case ZCC_String: + return TypeString; + + case ZCC_Name: + return TypeName; + + case ZCC_Vector2: + return TypeVector2; + + case ZCC_Vector3: + return TypeVector3; + + case ZCC_Vector4: + // This has almost no use, so we really shouldn't bother. + Error(field, "vector<4> not implemented for %s", FName(field->Names->Name).GetChars()); + return TypeError; + + case ZCC_UserType: + return ResolveUserType(btype, &outertype->Symbols); + break; + } + } + + case AST_MapType: + if (allowarraytypes) + { + Error(field, "%s: Map types not implemented yet", FName(field->Names->Name).GetChars()); + // Todo: Decide what we allow here and if it makes sense to allow more complex constructs. + auto mtype = static_cast(ztype); + return NewMap(DetermineType(outertype, field, mtype->KeyType, false), DetermineType(outertype, field, mtype->ValueType, false)); + } + break; + + case AST_DynArrayType: + if (allowarraytypes) + { + Error(field, "%s: Dynamic array types not implemented yet", FName(field->Names->Name).GetChars()); + auto atype = static_cast(ztype); + return NewDynArray(DetermineType(outertype, field, atype->ElementType, false)); + } + break; + + case AST_ClassType: + { + auto ctype = static_cast(ztype); + if (ctype->Restriction == nullptr) + { + return NewClassPointer(RUNTIME_CLASS(DObject)); + } + else + { + auto sym = outertype->Symbols.FindSymbol(ctype->Restriction->Id, true); + if (sym == nullptr) sym = GlobalSymbols.FindSymbol(ctype->Restriction->Id, false); + if (sym == nullptr) + { + Error(field, "%s: Unknown identifier", FName(ctype->Restriction->Id).GetChars()); + return TypeError; + } + auto typesym = dyn_cast(sym); + if (typesym == nullptr || !typesym->Type->IsKindOf(RUNTIME_CLASS(PClass))) + { + Error(field, "%s does not represent a class type", FName(ctype->Restriction->Id).GetChars()); + return TypeError; + } + return NewClassPointer(static_cast(typesym->Type)); + } + } + } + return TypeError; +} + +//========================================================================== +// +// ZCCCompiler :: ResolveUserType +// +// resolves a user type and returns a matching PType +// +//========================================================================== + +PType *ZCCCompiler::ResolveUserType(ZCC_BasicType *type, PSymbolTable *symt) +{ + Printf("Resolving user type %s\n", FName(type->UserType->Id).GetChars()); + // Check the symbol table for the identifier. + PSymbolTable *table; + PSymbol *sym = symt->FindSymbolInTable(type->UserType->Id, table); + // GlobalSymbols cannot be the parent of a class's symbol table so we have to look for global symbols explicitly. + if (sym == nullptr && symt != &GlobalSymbols) sym = GlobalSymbols.FindSymbolInTable(type->UserType->Id, table); + if (sym != nullptr && sym->IsKindOf(RUNTIME_CLASS(PSymbolType))) + { + auto type = static_cast(sym)->Type; + if (type->IsKindOf(RUNTIME_CLASS(PEnum))) + { + return TypeSInt32; // hack this to an integer until we can resolve the enum mess. + } + return type; + } + return TypeError; +} + + +//========================================================================== +// +// ZCCCompiler :: ResolveArraySize +// +// resolves the array size and returns a matching type. +// +//========================================================================== + +PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PSymbolTable *sym) +{ + // The duplicate Simplify call is necessary because if the head node gets replaced there is no way to detect the end of the list otherwise. + arraysize = Simplify(arraysize, sym); + ZCC_Expression *val; + do + { + val = Simplify(arraysize, sym); + if (val->Operation != PEX_ConstValue || !val->Type->IsA(RUNTIME_CLASS(PInt))) + { + Error(arraysize, "Array index must be an integer constant"); + return TypeError; + } + int size = static_cast(val)->IntVal; + if (size < 1) + { + Error(arraysize, "Array size must be positive"); + return TypeError; + } + baseType = NewArray(baseType, size); + val = static_cast(val->SiblingNext); + } while (val != arraysize); + return baseType; +} diff --git a/src/zscript/zcc_compile.h b/src/zscript/zcc_compile.h index c21aabc2ab..cf871cfaa1 100644 --- a/src/zscript/zcc_compile.h +++ b/src/zscript/zcc_compile.h @@ -4,14 +4,19 @@ struct ZCC_StructWork { ZCC_Struct *strct; + ZCC_Class *OuterDef; + PClass *Outer; PSymbolTreeNode *node; + TArray Enums; TArray Constants; TArray Fields; - ZCC_StructWork(ZCC_Struct * s, PSymbolTreeNode *n) + ZCC_StructWork(ZCC_Struct * s, PSymbolTreeNode *n, ZCC_Class *outer) { strct = s; node = n; + OuterDef = outer; + Outer = nullptr; }; ZCC_Struct *operator->() @@ -31,8 +36,8 @@ struct ZCC_ClassWork { ZCC_Class *cls; PSymbolTreeNode *node; + TArray Enums; TArray Constants; - TArray Structs; TArray Fields; ZCC_ClassWork(ZCC_Class * s, PSymbolTreeNode *n) @@ -67,16 +72,22 @@ public: private: void ProcessClass(ZCC_Class *node, PSymbolTreeNode *tnode); - void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode); + void ProcessStruct(ZCC_Struct *node, PSymbolTreeNode *tnode, ZCC_Class *outer); void CreateStructTypes(); void CreateClassTypes(); void CopyConstants(TArray &dest, TArray &Constants, PSymbolTable *ot); - void CompileAllFields(); void CompileAllConstants(); void AddConstant(ZCC_ConstantWork &constant); int CompileConstants(const TArray &defs, PSymbolTable *Output); bool CompileConstant(ZCC_ConstantDef *def, PSymbolTable *Symbols); + void CompileAllFields(); + bool CompileFields(PStruct *type, TArray &Fields, PClass *Outer, bool forstruct); + FString FlagsToString(uint32_t flags); + PType *DetermineType(PType *outertype, ZCC_VarDeclarator *field, ZCC_Type *ztype, bool allowarraytypes); + PType *ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, PSymbolTable *sym); + PType *ResolveUserType(ZCC_BasicType *type, PSymbolTable *sym); + TArray Constants; TArray Structs; TArray Classes; diff --git a/src/zscript/zcc_parser.h b/src/zscript/zcc_parser.h index 1da9f79cae..8db0221eee 100644 --- a/src/zscript/zcc_parser.h +++ b/src/zscript/zcc_parser.h @@ -179,6 +179,7 @@ struct ZCC_Identifier : ZCC_TreeNode struct ZCC_NamedNode : ZCC_TreeNode { ENamedName NodeName; + PSymbolType *Symbol; }; struct ZCC_Class : ZCC_NamedNode @@ -188,14 +189,12 @@ struct ZCC_Class : ZCC_NamedNode VM_UWORD Flags; ZCC_TreeNode *Body; PClass *Type; - PSymbolType *Symbol; }; struct ZCC_Struct : ZCC_NamedNode { ZCC_TreeNode *Body; PStruct *Type; - PSymbolType *Symbol; }; struct ZCC_Enum : ZCC_NamedNode @@ -444,6 +443,7 @@ struct ZCC_ConstantDef : ZCC_NamedNode { ZCC_Expression *Value; PSymbolConst *Symbol; + ZCC_Enum *Type; // gets set when the constant originates from an enum. }; struct ZCC_Declarator : ZCC_TreeNode diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 62ac81a76f..12604234dd 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -74,6 +74,9 @@ enum EFireBulletsFlags FBF_NOPITCH = 8, FBF_NOFLASH = 16, FBF_NORANDOMPUFFZ = 32, + FBF_PUFFTARGET = 64, + FBF_PUFFMASTER = 128, + FBF_PUFFTRACER = 256, }; // Flags for A_SpawnItemEx @@ -283,15 +286,11 @@ enum ECustomPunchFlags CPF_STEALARMOR = 32, }; -// Flags for A_CustomMissile -enum ECustomMissileFlags +enum EFireCustomMissileFlags { FPF_AIMATANGLE = 1, FPF_TRANSFERTRANSLATION = 2, FPF_NOAUTOAIM = 4, - FBF_PUFFTARGET = 64, - FBF_PUFFMASTER = 128, - FBF_PUFFTRACER = 256, }; // Flags for A_Teleport