From 7f645c735754ced7ed00bd813adf71633a8b61a9 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Thu, 29 Jun 2023 00:20:23 -0400 Subject: [PATCH] Finished sanity suite except for operators. Adjusted upfront api a bit, def_using no longer handles the namespace case, a sepearate function: def_using_namespace now does. Mostly fixes to the seralization as I generate more cases to find the bugs. --- project/gen.cpp | 176 +++++++++++++---------- project/gen.hpp | 18 ++- test/NonParsed/Array.NonParsed.hpp | 2 +- test/NonParsed/Sanity.hpp | 221 +++++++++++++++++++++++++++-- test/gen/DummyInclude.hpp | 1 + test/gen/sanity.gen.hpp | 80 ++++++++++- 6 files changed, 403 insertions(+), 95 deletions(-) create mode 100644 test/gen/DummyInclude.hpp diff --git a/project/gen.cpp b/project/gen.cpp index caee9de..ec77d44 100644 --- a/project/gen.cpp +++ b/project/gen.cpp @@ -54,6 +54,9 @@ namespace gen Code access_protected; Code access_private; + Code module_global_fragment; + Code module_private_fragment; + Code spec_const; Code spec_consteval; Code spec_constexpr; @@ -82,7 +85,6 @@ namespace gen case Class_Body: \ case Enum_Body: \ case Extern_Linkage: \ - case Friend: \ case Function_Body: \ case Function_Fwd: \ case Global_Body: \ @@ -511,9 +513,6 @@ namespace gen \ if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Import )) \ result.append( "import " ); \ - \ - if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Private )) \ - result.append( "private " ); String result = String::make( g_allocator, "" ); @@ -639,11 +638,11 @@ namespace gen result.append( "\n{\n" ); } - result.append_fmt( "%s\n%s};\n", body()->to_string(), indent_str ); + result.append_fmt( "%s\n%s};", body()->to_string(), indent_str ); } else { - result.append_fmt( "class %s\n{\n%s\n%s};\n", Name, body()->to_string(), indent_str ); + result.append_fmt( "class %s\n{\n%s\n%s};", Name, body()->to_string(), indent_str ); } } break; @@ -733,7 +732,7 @@ namespace gen if ( entry( idx )->Type == Typename ) { - result.append_fmt( ": %s\n%s{\n" + result.append_fmt( "%s : %s\n%s{\n" , Name , entry( idx )->to_string() , indent_str @@ -770,7 +769,7 @@ namespace gen idx++; } - result.append_fmt( ": %s;\n", Name, entry( idx )->to_string() ); + result.append_fmt( "%s : %s;", Name, entry( idx )->to_string() ); } break; @@ -790,7 +789,7 @@ namespace gen index++; } - result.append_fmt( "%s};\n", indent_str ); + result.append_fmt( "%s};", indent_str ); } break; @@ -799,7 +798,7 @@ namespace gen ProcessModuleFlags(); - result.append_fmt( "extern %s\n%s{\n%s\n%s};\n" + result.append_fmt( "extern \"%s\"\n%s{\n%s\n%s}" , Name , indent_str , body()->to_string() @@ -808,7 +807,7 @@ namespace gen break; case Friend: - result.append_fmt( "%sfriend %s;\n", indent_str, entry( 0 )->to_string() ); + result.append_fmt( "%sfriend %s", indent_str, entry( 0 )->to_string() ); break; case Function: @@ -820,33 +819,44 @@ namespace gen u32 idx = 1; u32 left = num_entries(); - if ( entry( idx )->Type == Attributes ) + AST* Entry = entry( idx ); + + if ( Entry && Entry->Type == Attributes ) { - result.append_fmt( "%s ", entry( idx )->to_string() ); + result.append_fmt( "%s ", Entry->to_string() ); idx++; left--; + Entry = entry( idx ); } - if ( entry( idx )->Type == Specifiers ) + if ( Entry && Entry->Type == Specifiers ) { - result.append_fmt( "%s\n", entry( idx )->to_string() ); + result.append_fmt( "%s\n", Entry->to_string() ); idx++; left--; + Entry = entry( idx ); } - result.append_fmt( "%s %s(", entry( idx )->to_string(), Name ); - idx++; - left--; - - if ( left && entry( idx )->Type == Parameters ) + if ( Entry && Entry->Type == Typename ) { - result.append_fmt( "%s", entry( idx )->to_string() ); + result.append_fmt( "%s ", Entry->to_string() ); idx++; left--; + Entry = entry( idx ); + } + + result.append_fmt( "%s(", Name ); + + if ( left && Entry && Entry->Type == Parameters ) + { + result.append_fmt("%s", Entry->to_string() ); + idx++; + left--; + Entry = entry( idx ); } else { - result.append_fmt( "void" ); + result.append( "void" ); } result.append_fmt( ")\n%s{\n%s\n%s}" @@ -906,24 +916,28 @@ namespace gen result.append( "void" ); } - result.append( ");\n" ); + result.append( ");" ); } break; case Module: result.append( indent ); - ProcessModuleFlags(); + if (((u32(ModuleFlag::Export) & u32(ModuleFlags)) == u32(ModuleFlag::Export))) + result.append("export "); - result.append_fmt( "module %s", Content ); - break; + if (((u32(ModuleFlag::Import) & u32(ModuleFlags)) == u32(ModuleFlag::Import))) + result.append("import "); + + result.append_fmt( "%s;", Name ); + break; case Namespace: result.append( indent ); ProcessModuleFlags(); - result.append_fmt( "namespace %s\n%s{\n%s\n%s};\n" + result.append_fmt( "namespace %s\n%s{\n%s\n%s};" , Name , indent_str , body()->to_string() @@ -993,12 +1007,12 @@ namespace gen if ( entry( idx )->Type == Parameters ) { - result.append_fmt( "%s);\n", entry( idx )->to_string() ); + result.append_fmt( "%s);", entry( idx )->to_string() ); idx++; } else { - result.append_fmt( "void);\n" ); + result.append_fmt( "void);" ); } } break; @@ -1008,7 +1022,7 @@ namespace gen result.append_fmt( "%s %s", entry( 0 )->to_string(), Name ); s32 index = 1; - s32 left = num_entries() - 1; + s32 left = num_entries(); while ( left--, left > 0 ) result.append_fmt( ", %s %s" @@ -1019,7 +1033,7 @@ namespace gen break; case Preprocessor_Include: - result.append_fmt( "#include %s\n", Name ); + result.append_fmt( "#include \"%s\"", Name ); break; case Specifiers: @@ -1056,7 +1070,7 @@ namespace gen result.append_fmt( ": %s %s", access_str, entry( idx )->to_string() ); } - result.append_fmt( "\n{\n%s\n};\n", body()->to_string() ); + result.append_fmt( "\n{\n%s\n};", body()->to_string() ); } break; @@ -1088,16 +1102,23 @@ namespace gen s32 idx = 1; - if ( entry( idx )->Type == Specifiers ) + if ( num_entries() > 1 ) { - result.append_fmt( "%s", entry( idx )->to_string() ); - idx++; + if ( entry( idx )->Type == Specifiers ) + { + result.append_fmt( "%s", entry( idx )->to_string() ); + idx++; + } + + result.append_fmt( "%s %s", entry( 0 )->to_string(), Name ); + + if ( entry( idx ) ) + result.append_fmt( " = %s;", entry( idx )->to_string() ); + + break; } - result.append_fmt( "%s %s", entry( 0 )->to_string(), Name ); - - if ( entry( idx ) ) - result.append_fmt( " = %s", entry( idx )->to_string() ); + result.append_fmt( "%s %s;", entry( 0 )->to_string(), Name ); } break; @@ -1154,7 +1175,7 @@ namespace gen idx++; } - result.append_fmt( "%s\n%s{\n%s\n%s};\n" + result.append_fmt( "%s\n%s{\n%s\n%s};" , Name , indent_str , body()->to_string() @@ -1183,16 +1204,15 @@ namespace gen if ( type->entry( 1 ) ) result.append_fmt( "[%s]", type->entry( 1 )->to_string() ); + result.append( ";" ); } else - result.append_fmt( "using %s", Name ); - - result.append( ";" ); + result.append_fmt( "using %s;", Name ); } break; case Using_Namespace: - result.append_fmt( "%susing namespace %s", indent_str, Name ); + result.append_fmt( "%susing namespace %s;", indent_str, Name ); break; case Class_Body: @@ -1333,6 +1353,18 @@ namespace gen access_public_write->Name = get_cached_string( { sizeof("public"), "public" } ); access_public_write.lock(); + module_global_fragment = make_code(); + module_global_fragment->Type = ECode::Untyped; + module_global_fragment->Name = get_cached_string( StrC::from("module;") ); + module_global_fragment->Content = module_global_fragment->Name; + module_global_fragment.lock(); + + module_private_fragment = make_code(); + module_private_fragment->Type = ECode::Untyped; + module_private_fragment->Name = get_cached_string( StrC::from("module : private;") ); + module_private_fragment->Content = module_private_fragment->Name; + module_private_fragment.lock(); + Code& spec_local_persist_write = ccast( Code, spec_local_persist ); spec_local_persist_write = def_specifiers( 1, ESpecifier::Local_Persist ); @@ -2167,7 +2199,7 @@ namespace gen name_check( def_extern_linkage, name ); null_check( def_extern_linkage, body ); - if ( body->Type != Extern_Linkage_Body || body->Type != Untyped ) + if ( body->Type != Extern_Linkage_Body && body->Type != Untyped ) { log_failure("gen::def_extern_linkage: body is not of extern_linkage or untyped type %s", body->debug_str()); return Code::Invalid; @@ -2324,6 +2356,7 @@ namespace gen result = make_code(); result->Type = ECode::Module; result->Name = get_cached_string( name ); + result->Content = result->Name; result->ModuleFlags = mflags; result.lock(); @@ -2337,7 +2370,7 @@ namespace gen name_check( def_namespace, name ); null_check( def_namespace, body ); - if ( body->Type != Namespace_Body || body->Type != Untyped ) + if ( body->Type != Namespace_Body && body->Type != Untyped ) { log_failure("gen::def_namespace: body is not of namespace or untyped type %s", body->debug_str()); return Code::Invalid; @@ -2584,8 +2617,9 @@ namespace gen Code def_union( StrC name, Code body, Code attributes, ModuleFlag mflags ) { name_check( def_union, name ); + null_check( def_union, body ); - if ( body && body->Type != ECode::Union_Body ) + if ( body->Type != ECode::Union_Body ) { log_failure( "gen::def_union: body was not a Union_Body type" ); return Code::Invalid; @@ -2595,16 +2629,9 @@ namespace gen result = make_code(); result->Name = get_cached_string( name ); result->ModuleFlags = mflags; + result->Type = ECode::Union; - if ( body ) - { - result->Type = ECode::Union; - result->add_entry( body ); - } - else - { - result->Type = ECode::Union_Fwd; - } + result->add_entry( body ); if ( attributes ) result->add_entry( attributes ); @@ -2613,8 +2640,7 @@ namespace gen return result; } - Code def_using( StrC name, UsingT specifier - , Code type + Code def_using( StrC name, Code type , Code attributes , ModuleFlag mflags ) { @@ -2633,20 +2659,10 @@ namespace gen result = make_code(); result->Name = get_cached_string( name ); result->ModuleFlags = mflags; + result->Type = ECode::Using; - switch ( specifier ) - { - case UsingRegular: - result->Type = ECode::Using; - - if ( type ) - result->add_entry( type ); - break; - - case UsingNamespace: - result->Type = ECode::Using_Namespace; - break; - } + if ( type ) + result->add_entry( type ); if ( attributes ) result->add_entry( attributes ); @@ -2655,6 +2671,20 @@ namespace gen return result; } + Code def_using_namespace( StrC name ) + { + name_check( def_using_namespace, name ); + + Code + result = make_code(); + result->Name = get_cached_string( name ); + result->Content = result->Name; + result->Type = ECode::Using_Namespace; + + result.lock(); + return result; + } + Code def_variable( Code type, StrC name, Code value , Code specifiers, Code attributes , ModuleFlag mflags ) @@ -3159,6 +3189,8 @@ namespace gen result->Name = current->Name; result->Type = current->Type; + result->add_entry( current->entry( 0) ); + while( codes++, current = * codes, num--, num > 0 ) { check_current(); @@ -3259,7 +3291,7 @@ namespace gen return Code::Invalid; } - if ( entry->Type != Untyped ) + if ( entry->Type != Untyped && entry->Type != Comment ) { log_failure("gen::def_union_body: Entry type is not allowed - %s. Must be of untyped type.", entry->debug_str() ); \ return Code::Invalid; diff --git a/project/gen.hpp b/project/gen.hpp index 2818ecd..a7b719f 100644 --- a/project/gen.hpp +++ b/project/gen.hpp @@ -77,7 +77,6 @@ namespace gen Entry( Typedef ) \ Entry( Typename ) \ Entry( Union ) \ - Entry( Union_Fwd ) \ Entry( Union_Body) \ Entry( Using ) \ Entry( Using_Namespace ) \ @@ -319,12 +318,17 @@ namespace gen None = 0, Export = bit(0), Import = bit(1), - Private = bit(2), + // Private = bit(2), Num_ModuleFlags, Invalid, }; + ModuleFlag operator|( ModuleFlag A, ModuleFlag B) + { + return (ModuleFlag)( (u32)A | (u32)B ); + } + /* Predefined attributes @@ -818,13 +822,14 @@ namespace gen Code def_typedef( StrC name, Code type, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None ); Code def_type ( StrC name, Code arrayexpr = NoCode, Code specifiers = NoCode ); - Code def_union( StrC name, Code body = NoCode, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None ); + Code def_union( StrC name, Code body, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None ); - Code def_using( StrC name, UsingT specifier = UsingRegular - , Code type = NoCode + Code def_using( StrC name, Code type = NoCode , Code attributess = NoCode , ModuleFlag mflags = ModuleFlag::None ); + Code def_using_namespace( StrC name ); + Code def_variable( Code type, StrC name, Code value = NoCode , Code specifiers = NoCode, Code attributes = NoCode , ModuleFlag mflags = ModuleFlag::None ); @@ -1130,6 +1135,9 @@ namespace gen extern Code access_protected; extern Code access_private; + extern Code module_global_fragment; + extern Code module_private_fragment; + extern Code spec_const; extern Code spec_consteval; extern Code spec_constexpr; diff --git a/test/NonParsed/Array.NonParsed.hpp b/test/NonParsed/Array.NonParsed.hpp index 524f1c1..4bcefd0 100644 --- a/test/NonParsed/Array.NonParsed.hpp +++ b/test/NonParsed/Array.NonParsed.hpp @@ -64,7 +64,7 @@ Code gen__array( StrC type, sw type_size ) Code array; { - Code using_type = def_using( name(Type), UsingRegular, t_type ); + Code using_type = def_using( name(Type), t_type ); Code data = def_variable( t_type_ptr, name(Data) ); Code init; diff --git a/test/NonParsed/Sanity.hpp b/test/NonParsed/Sanity.hpp index 7ed53d8..7932c4b 100644 --- a/test/NonParsed/Sanity.hpp +++ b/test/NonParsed/Sanity.hpp @@ -13,21 +13,25 @@ u32 gen_sanity() // Comment { - Code comment_test = def_comment( StrC::from("Sanity check: def_omment test") ); + Code comment_test = def_comment( StrC::from("Sanity check: def_comment test") ); gen_sanity_file.print(comment_test); - gen_sanity_file.print_fmt("\n"); } + gen_sanity_file.print_fmt("\n"); + gen_sanity_file.print( def_comment( StrC::from( + "The following will show a series of base cases for the gen api.\n" + ))); + // Class { - Code fwd = def_class( StrC::from("Test_EmptyClass") ); + Code fwd = def_class( name(TestEmptyClass) ); Code empty_body; { - Code cmt = def_comment( StrC::from("Empty class") ); + Code cmt = def_comment( StrC::from("Empty class body") ); Code body = def_class_body( 1, cmt ); - empty_body = def_class( StrC::from("Test_EmptyClass"), body ); + empty_body = def_class( name(TestEmptyClass), body ); } gen_sanity_file.print(fwd); @@ -39,8 +43,7 @@ u32 gen_sanity() // Typedef { Code t_unsigned_char = def_type( name(unsigned char) ); - - Code u8_typedef = def_typedef( name(u8), t_unsigned_char ); + Code u8_typedef = def_typedef( name(u8), t_unsigned_char ); gen_sanity_file.print(u8_typedef); } @@ -49,10 +52,9 @@ u32 gen_sanity() // Enum { - Code fwd = def_enum( StrC::from("Test_Enum"), NoCode, t_u8 ); + Code fwd = def_enum( name(ETestEnum), NoCode, t_u8 ); Code def; { - Code body = untyped_str( StrC::from( #define enum_entry( id ) "\t" #id ",\n" enum_entry( A ) @@ -61,13 +63,212 @@ u32 gen_sanity() #undef enum_entry )); - def = def_enum( StrC::from("Test_Enum"), body, t_u8 ); + def = def_enum( name(ETestEnum), body, t_u8 ); + } + + Code fwd_enum_class = def_enum( name(ETestEnumClass), NoCode, t_u8, EnumClass ); + + gen_sanity_file.print(fwd); + gen_sanity_file.print(def); + gen_sanity_file.print(fwd_enum_class); + } + + gen_sanity_file.print_fmt("\n"); + + // External Linkage + { + Code body = def_extern_link_body( 1 + , def_comment( StrC::from("Empty extern body") ) + ); + + Code c_extern = def_extern_link( name(C), body ); + + gen_sanity_file.print(c_extern); + } + + gen_sanity_file.print_fmt("\n"); + + // Friend + { + Code fwd = def_class( name(TestFriendFwd)); + Code body = def_class_body( 1 + , def_friend( fwd ) + ); + + gen_sanity_file.print( def_class( name(TestFriend), body ) ); + } + + gen_sanity_file.print_fmt("\n"); + + // Function + { + Code fwd = def_function( name(test_function) ); + Code def; + { + Code body = def_function_body( 1 + , def_comment( StrC::from("Empty function body") ) + ); + + def = def_function( name(test_function), __, __, body ); } gen_sanity_file.print(fwd); gen_sanity_file.print(def); } + gen_sanity_file.print_fmt("\n"); + + // Include + { + Code include = def_include( StrC::from("DummyInclude.hpp") ); + + gen_sanity_file.print(include); + } + + gen_sanity_file.print_fmt("\n"); + + // Module + if (0) + { + Code module_export = def_module( name(TestModule), ModuleFlag::Export ); + Code module_import = def_module( name(TestModule), ModuleFlag::Import ); + Code module_both = def_module( name(TestModule), ModuleFlag::Export | ModuleFlag::Import ); + + gen_sanity_file.print(module_global_fragment); + gen_sanity_file.print(module_private_fragment); + gen_sanity_file.print(module_export); + gen_sanity_file.print(module_import); + gen_sanity_file.print(module_both); + } + + gen_sanity_file.print_fmt("\n"); + + // Namespace + { + Code namespace_def; + { + Code body = def_namespace_body( 1 + , def_comment( StrC::from("Empty namespace body") ) + ); + + namespace_def = def_namespace( name(TestNamespace), body ); + } + + gen_sanity_file.print(namespace_def); + } + + gen_sanity_file.print_fmt("\n"); + + // Operator + { + // This is nasty... + } + + gen_sanity_file.print_fmt("\n"); + + // Parameters + { + Code fwd; + { + Code params = def_param( t_u8, name(a) ); + + fwd = def_function( name(test_function_wparam), params ); + } + + Code def, def2; + { + Code body = def_function_body( 1 + , def_comment( StrC::from("Empty function body") ) + ); + + Code params = def_params( 2 * 3, t_u8, 1, "a", t_u8, 1, "b" ); + + def = def_function( name(test_function_wparams), params, __, body ); + + Code param_a = def_param( t_u8, name(a)); + Code param_b = def_param( t_u8, name(b)); + Code params_arr[2] = { param_a, param_b }; + + Code params2 = def_params( 2, params_arr ); + + def2 = def_function( name(test_function_wparams2), params2, __, body ); + } + + gen_sanity_file.print(fwd); + gen_sanity_file.print(def); + gen_sanity_file.print(def2); + } + + gen_sanity_file.print_fmt("\n"); + + // Specifiers + { + Code fwd_fn = def_function( name(test_function_specifiers), __, __, __, spec_inline ); + + // Need an op overload here + + Code t_ct_u8 = def_type( name(u8), __, spec_constexpr ); + Code typedef_ConstExprTest = def_typedef( name(ConstExprTest), t_ct_u8 ); + } + + gen_sanity_file.print_fmt("\n"); + + // Struct + { + Code fwd = def_class( name(TestEmptyStruct) ); + Code empty_body; + { + Code cmt = def_comment( StrC::from("Empty class body") ); + Code body = def_class_body( 1, cmt ); + + empty_body = def_class( name(TestEmptyStruct), body ); + } + + gen_sanity_file.print(fwd); + gen_sanity_file.print(empty_body); + } + + gen_sanity_file.print_fmt("\n"); + + // Union + { + Code body = def_union_body( 1 + , def_comment( StrC::from("Empty union body") ) + ); + + Code def = def_union( name(TestEmptyUnion), body ); + + gen_sanity_file.print(def); + } + + gen_sanity_file.print_fmt("\n"); + + // Using + { + Code reg = def_using( name(TestUsing), t_u8 ); + Code nspace = def_using_namespace( name(TestNamespace) ); + + gen_sanity_file.print(reg); + gen_sanity_file.print(nspace); + } + + gen_sanity_file.print_fmt("\n"); + + // Variable + { + Code bss = def_variable( t_u8, name(test_variable) ); + Code data = def_variable( t_u8, name(test_variable2), untyped_str( code( 0x12 )) ); + + gen_sanity_file.print(bss); + gen_sanity_file.print(data); + } + + gen_sanity_file.print_fmt("\n"); + + gen_sanity_file.print( def_comment( StrC::from( + "End of base case tests.\n" + ))); + gen_sanity_file.write(); return 0; } diff --git a/test/gen/DummyInclude.hpp b/test/gen/DummyInclude.hpp new file mode 100644 index 0000000..30e1087 --- /dev/null +++ b/test/gen/DummyInclude.hpp @@ -0,0 +1 @@ +// Only for gen testing. \ No newline at end of file diff --git a/test/gen/sanity.gen.hpp b/test/gen/sanity.gen.hpp index 04fb3e6..ef180dd 100644 --- a/test/gen/sanity.gen.hpp +++ b/test/gen/sanity.gen.hpp @@ -1,19 +1,85 @@ -// Sanity check: def_omment test +// Sanity check: def_comment test -class Test_EmptyClass; -class Test_EmptyClass +// The following will show a series of base cases for the gen api. + +class TestEmptyClass; +class TestEmptyClass { - // Empty class + // Empty class body }; - typedef unsigned char u8; -enum Test_Enum : u8; -enum Test_Enum : u8 +enum ETestEnum : u8; +enum ETestEnum : u8 { A, B, C, }; +enum class ETestEnumClass : u8; + +extern "C" +{ + // Empty extern body + +} + +class TestFriend +{ + friend class TestFriendFwd; + +}; + +void test_function(void); +void test_function(void) +{ + // Empty function body + +} + +#include "DummyInclude.hpp" + + +namespace TestNamespace +{ + // Empty namespace body + +}; + + +void test_function_wparam(u8 a); +void test_function_wparams(u8 a, u8 b) +{ + // Empty function body + +} +void test_function_wparams2(u8 a, u8 b) +{ + // Empty function body + +} + + +class TestEmptyStruct; +class TestEmptyStruct +{ + // Empty class body + +}; + +union TestEmptyUnion +{ + // Empty union body + +}; + +using TestUsing = u8; +using namespace TestNamespace; + +u8 test_variable; +u8 test_variable2 = 0x12; + +// End of base case tests. +