Started sanity test suite (Non-parsed api)

Made some fixes based on errors found while iterating on first generation
This commit is contained in:
Edward R. Gonzalez 2023-06-28 14:43:21 -04:00
parent e74b498686
commit 0192cd49ef
10 changed files with 192 additions and 108 deletions

4
.vscode/launch.json vendored
View File

@ -10,7 +10,7 @@
"name": "Debug gentime lldb", "name": "Debug gentime lldb",
"program": "${workspaceFolder}/test/gen/build/gencpp.exe", "program": "${workspaceFolder}/test/gen/build/gencpp.exe",
"args": [], "args": [],
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}/test/gen/",
"postRunCommands": [ "postRunCommands": [
"command script import \"${workspaceFolder}/.vscode/gencpp_lldbvis.py\"" "command script import \"${workspaceFolder}/.vscode/gencpp_lldbvis.py\""
] ]
@ -21,7 +21,7 @@
"name": "Debug gentime vsdbg", "name": "Debug gentime vsdbg",
"program": "${workspaceFolder}/test/gen/build/gencpp.exe", "program": "${workspaceFolder}/test/gen/build/gencpp.exe",
"args": [], "args": [],
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}/test/gen/",
"visualizerFile": "${workspaceFolder}/.vscode/gencpp.natvis" "visualizerFile": "${workspaceFolder}/.vscode/gencpp.natvis"
} }
] ]

View File

@ -19,5 +19,6 @@
"limits": "cpp" "limits": "cpp"
}, },
"C_Cpp.intelliSenseEngineFallback": "disabled", "C_Cpp.intelliSenseEngineFallback": "disabled",
"mesonbuild.configureOnOpen": true "mesonbuild.configureOnOpen": true,
"C_Cpp.errorSquiggles": "enabled"
} }

View File

@ -154,47 +154,6 @@ struct ArrayHeader
**Note: The formatting shown here is not how it will look. For your desired formatting its recommended to run a pass through the files with an auto-formatter.** **Note: The formatting shown here is not how it will look. For your desired formatting its recommended to run a pass through the files with an auto-formatter.**
## Gen's DSL
If you don't mind a low amount of macros (~80 sloc), a DSL may be optionally defined with:
```cpp
GEN_DEFINE_DSL
```
Using the previous example to show usage:
```cpp
Code type_ns(uw) = type( uw );
Code type_ns(allocator) = type( allocator );
Code type_ns(string_const) = type( char, specifiers( Const, Ptr ) );
make( struct, ArrayHeader )
{
Code
body = ArrayHeader.body();
body->add( variable( uw, Num ));
body->add( variable( uw, Capacity ));
body->add( variable( allocaotr, Allocator ));
}
// Or using parse!
Code type_ns(uw) = type_code( uw );
Code type_ns(allocator) = type_code( allocator );
Code type_ns(string_const) = type_code( char const* );
Code header = struct_code(
struct ArrayHeader
{
uw Num;
uw Capacity;
allocator Allocator;
};
);
```
`type_ns` is a helper macro for providing refering to a typename if using the c-namespace naming convention.
## Building ## Building
An example of building is provided in the test directory. An example of building is provided in the test directory.

View File

@ -84,12 +84,12 @@ using zpl::str_fmt_va;
using zpl::str_fmt_out_va; using zpl::str_fmt_out_va;
using zpl::str_fmt_out_err_va; using zpl::str_fmt_out_err_va;
using zpl::str_compare; using zpl::str_compare;
using zpl::string_appendc; // using zpl::string_appendc;
using zpl::string_append_fmt; // using zpl::string_append_fmt;
using zpl::string_append_length; // using zpl::string_append_length;
using zpl::string_make_length; // using zpl::string_make_length;
using zpl::string_length; // using zpl::string_length;
using zpl::string_make; // using zpl::string_make;
using zpl::str_len; using zpl::str_len;
#if __clang__ #if __clang__
@ -198,7 +198,8 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
sw Len; sw Len;
char const* Ptr; char const* Ptr;
static StrC from( char const* str ) static constexpr
StrC from( char const* str )
{ {
return { str_len( str ), str }; return { str_len( str ), str };
} }
@ -210,7 +211,7 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
}; };
// Dynamic String // Dynamic String
// This is directly based off the ZPL string api. // This is directly based off the ZPL string api.
// They used a header pattern // They used a header pattern
// I kept it for simplicty of porting but its not necessary to keep it that way. // I kept it for simplicty of porting but its not necessary to keep it that way.
struct String struct String
@ -268,7 +269,7 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
if ( ! str ) if ( ! str )
mem_set( allocation, 0, alloc_size ); mem_set( allocation, 0, alloc_size );
Header& Header&
header = * rcast(Header*, allocation); header = * rcast(Header*, allocation);
header = { allocator, length, length }; header = { allocator, length, length };
@ -339,7 +340,7 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
// NOTE: Return if there is enough space left // NOTE: Return if there is enough space left
if ( available >= add_len ) if ( available >= add_len )
{ {
return false; return true;
} }
else else
{ {
@ -371,7 +372,6 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
} }
} }
bool append( char const* str ) bool append( char const* str )
{ {
return append( str, str_len( str ) ); return append( str, str_len( str ) );
@ -379,15 +379,15 @@ char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
bool append( char const* str, sw length ) bool append( char const* str, sw length )
{ {
Header& header = get_header();
if ( sptr(str) > 0 ) if ( sptr(str) > 0 )
{ {
sw curr_len = header.Length; sw curr_len = this->length();
if ( make_space_for( str, length ) ) if ( ! make_space_for( str, length ) )
return false; return false;
Header& header = get_header();
mem_copy( Data + curr_len, str, length ); mem_copy( Data + curr_len, str, length );
Data[ curr_len + length ] = '\0'; Data[ curr_len + length ] = '\0';

View File

@ -506,8 +506,8 @@ namespace gen
} }
String AST::to_string() String AST::to_string()
{ {
# define ProcessModuleFlags() \ # define ProcessModuleFlags() \
if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Export )) \ if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Export )) \
result.append( "export " ); \ result.append( "export " ); \
\ \
@ -524,11 +524,33 @@ namespace gen
s32 tab_count = 0; s32 tab_count = 0;
{ {
AST* curr_parent = Parent; AST* curr_parent = Parent;
while ( curr_parent )
while ( Parent )
{ {
switch ( curr_parent->Type )
{
using namespace ECode;
case Class_Body:
case Enum_Body:
case Extern_Linkage_Body:
case Function_Body:
case Global_Body:
case Namespace_Body:
case Struct_Body:
case Union_Body:
break;
default:
{
curr_parent = curr_parent->Parent;
continue;
}
}
indent_str[tab_count] = '\t'; indent_str[tab_count] = '\t';
tab_count++; tab_count++;
curr_parent = curr_parent->Parent;
} }
} }
StrC indent = { tab_count, indent_str }; StrC indent = { tab_count, indent_str };
@ -558,14 +580,17 @@ namespace gen
{ {
s32 length = 0; s32 length = 0;
while ( left && Content[index] != '\n' ) while ( left && Content[index] != '\n' )
{
length++; length++;
left--;
}
str_copy( line, Content, length ); str_copy( line, Content, length );
line[length] = '\0'; line[length] = '\0';
result.append_fmt( "// %s\n", line ); result.append_fmt( "// %s", line );
} }
while ( left--, left ); while ( left--, left > 0 );
} }
break; break;
@ -585,32 +610,43 @@ namespace gen
ProcessModuleFlags(); ProcessModuleFlags();
result.append( "class " ); if ( num_entries() > 1 )
s32 idx = 1;
if ( Entries[idx]->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); result.append( "class " );
idx++;
s32 idx = 1;
if ( Entries[idx]->Type == Attributes )
{
result.append_fmt( "%s ", Entries[idx]->to_string() );
idx++;
}
result.append( Name );
AST* parent = Entries[idx];
if ( parent )
{
char const* access_level = to_str( ParentAccess );
result.append_fmt( ": %s %s\n%s{\n"
, access_level
, parent
, indent_str
);
}
else
{
result.append( "\n{\n" );
}
result.append_fmt( "%s\n%s};\n", body()->to_string(), indent_str );
} }
else
result.append( Name );
AST* parent = Entries[idx];
if ( parent )
{ {
char const* access_level = to_str( ParentAccess ); result.append_fmt( "class %s\n{\n%s\n%s};\n", Name, body()->to_string(), indent_str );
result.append_fmt( ": %s %s\n%s{\n"
, access_level
, parent
, indent_str
);
} }
result.append_fmt( "%s\n%s};\n", body()->to_string(), indent_str );
} }
break; break;
@ -820,31 +856,42 @@ namespace gen
ProcessModuleFlags(); ProcessModuleFlags();
u32 idx = 0; u32 idx = 0;
u32 left = array_count( Entries ); u32 left = num_entries();
if ( Entries[idx]->Type == Attributes ) AST* Entry = Entries[idx];
if ( Entry && Entry->Type == Attributes )
{ {
result.append_fmt( "%s ", Entries[idx]->to_string() ); result.append_fmt( "%s ", Entry->to_string() );
idx++; idx++;
left--; left--;
Entry = Entries[idx];
} }
if ( Entries[idx]->Type == Specifiers ) if ( Entry && Entry->Type == Specifiers )
{ {
result.append_fmt( "%s\n", Entries[idx]->to_string() ); result.append_fmt( "%s\n", Entry->to_string() );
idx++; idx++;
left--; left--;
Entry = Entries[idx];
} }
result.append_fmt( "\n%s %s(", Entries[idx]->to_string(), Name ); if ( Entry && Entry->Type == Typename )
idx++;
left--;
if ( left && Entries[idx]->Type == Parameters )
{ {
result.append_fmt( "%s", Entries[idx]->to_string() ); result.append_fmt( "%s ", Entry->to_string() );
idx++; idx++;
left--; left--;
Entry = Entries[idx];
}
result.append_fmt( "%s(", Name );
if ( left && Entry && Entry->Type == Parameters )
{
result.append_fmt("%s", Entry->to_string() );
idx++;
left--;
Entry = Entries[idx];
} }
else else
{ {
@ -1073,7 +1120,7 @@ namespace gen
break; break;
case Typename: case Typename:
if ( Entries[0] ) if ( num_entries() && Entries[0] )
{ {
result.append_fmt( "%s %s", Name, Entries[0]->to_string() ); result.append_fmt( "%s %s", Name, Entries[0]->to_string() );
} }
@ -1486,6 +1533,7 @@ namespace gen
result->StaticIndex = 0; result->StaticIndex = 0;
result->Readonly = false; result->Readonly = false;
result->DynamicEntries = false; result->DynamicEntries = false;
result->Entries = result->ArrStatic;
return result; return result;
} }
@ -2189,7 +2237,7 @@ namespace gen
return Code::Invalid; return Code::Invalid;
} }
if ( ret_type == nullptr || ret_type->Type != Typename ) if ( ret_type && ret_type->Type != Typename )
{ {
log_failure( "gen::def_function: ret_type was not a Typename: %s", ret_type->debug_str() ); log_failure( "gen::def_function: ret_type was not a Typename: %s", ret_type->debug_str() );
return Code::Invalid; return Code::Invalid;
@ -5738,7 +5786,7 @@ namespace gen
return result; return result;
} }
Code untyped_fmt(char const* fmt, ...) Code untyped_fmt( char const* fmt, ...)
{ {
local_persist thread_local local_persist thread_local
char buf[ZPL_PRINTF_MAXLEN] = { 0 }; char buf[ZPL_PRINTF_MAXLEN] = { 0 };
@ -5783,7 +5831,20 @@ namespace gen
#pragma region Builder #pragma region Builder
void Builder::print( Code code ) void Builder::print( Code code )
{ {
Buffer.append_fmt( "%s\n\n", code.to_string() ); Buffer.append_fmt( "%s\n", code.to_string() );
}
void Builder::print_fmt( char const* fmt, ... )
{
sw res;
char buf[ ZPL_PRINTF_MAXLEN ] = { 0 };
va_list va;
va_start( va, fmt );
res = str_fmt_va( buf, count_of( buf ) - 1, fmt, va ) - 1;
va_end( va );
Buffer.append( buf, res );
} }
bool Builder::open( char const* path ) bool Builder::open( char const* path )
@ -5803,7 +5864,7 @@ namespace gen
void Builder::write() void Builder::write()
{ {
bool result = file_write( & File, Buffer, string_length(Buffer) ); bool result = file_write( & File, Buffer, Buffer.length() );
if ( result == false ) if ( result == false )
log_failure("gen::File::write - Failed to write to file: %s", file_name( & File ) ); log_failure("gen::File::write - Failed to write to file: %s", file_name( & File ) );

View File

@ -14,7 +14,7 @@
// #define GEN_DEFINE_DSL // #define GEN_DEFINE_DSL
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS #define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
// #define GEN_DONT_USE_FATAL // #define GEN_DONT_USE_FATAL
#define GEN_ENFORCE_READONLY_AST // #define GEN_ENFORCE_READONLY_AST
#define GEN_FEATURE_INCREMENTAL #define GEN_FEATURE_INCREMENTAL
// #define GEN_FEATURE_PARSING // #define GEN_FEATURE_PARSING
@ -939,6 +939,7 @@ namespace gen
String Buffer; String Buffer;
void print( Code ); void print( Code );
void print_fmt( char const* fmt, ... );
bool open( char const* path ); bool open( char const* path );
void write(); void write();

View File

@ -307,12 +307,12 @@ struct GenArrayRequest
}; };
Array(GenArrayRequest) GenArrayRequests; Array(GenArrayRequest) GenArrayRequests;
void gen__array_request( StrC type, StrC dep, sw size ) void gen__array_request( StrC type, sw size, StrC dep = {} )
{ {
GenArrayRequest request = { type, dep, size }; GenArrayRequest request = { type, dep, size };
array_append( GenArrayRequests, request ); array_append( GenArrayRequests, request );
} }
#define Gen_Array( type ) gen__array_request( txt_n_len( type ), sizeof(type) ) #define Gen_Array( type ) gen__array_request( { txt_n_len(type) }, sizeof(type) )
u32 gen_array_file() u32 gen_array_file()
{ {

47
test/NonParsed/Sanity.hpp Normal file
View File

@ -0,0 +1,47 @@
#ifdef gen_time
#include "gen.hpp"
using namespace gen;
u32 gen_sanity()
{
Builder
gen_sanity_file;
gen_sanity_file.open("./sanity.gen.hpp");
// Comment
{
Code comment_test = def_comment( StrC::from("Sanity check: def_omment test") );
gen_sanity_file.print(comment_test);
gen_sanity_file.print_fmt("\n");
}
// Class
{
Code fwd = def_class( StrC::from("Test_EmptyClass") );
Code empty_body;
{
Code cmt = def_comment( StrC::from("Empty class") );
Code body = def_class_body( 1, cmt );
empty_body = def_class( StrC::from("Test_EmptyClass"), body );
}
gen_sanity_file.print(fwd);
gen_sanity_file.print(empty_body);
}
gen_sanity_file.print_fmt("\n");
//
{
}
gen_sanity_file.write();
return 0;
}
#endif

12
test/gen/sanity.gen.hpp Normal file
View File

@ -0,0 +1,12 @@
// Sanity check: def_omment test
class Test_EmptyClass;
class Test_EmptyClass
{
// Empty class
};
UFUNCTION( BlueprintCallable, Category = "Test" )
void Test_UFunction(void);

View File

@ -1,4 +1,6 @@
#include "Bloat.cpp" #include "Bloat.cpp"
#include "NonParsed\Array.NonParsed.hpp"
#include "NonParsed\Sanity.hpp"
#ifdef gen_time #ifdef gen_time
@ -9,13 +11,14 @@ using namespace gen;
int gen_main() int gen_main()
{ {
Memory::setup(); Memory::setup();
gen::init(); gen::init();
gen_sanity();
// gen_array_file();
gen::deinit(); gen::deinit();
Memory::cleanup(); Memory::cleanup();
return 0; return 0;