mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 15:54:45 -08:00
test.cpp gen_time compiles (has memory issues though)
This commit is contained in:
parent
f09fe6aa15
commit
d66c1e4eb4
59
Readme.md
Normal file
59
Readme.md
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# gencpp
|
||||||
|
|
||||||
|
An attempt at simple staged metaprogramming for c/c++.
|
||||||
|
|
||||||
|
This project is not minimum feature complete yet.
|
||||||
|
Version 1 will have a most of c and a subset of c++ features available to it.
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|
A metaprogram is built to generate files before the main program is built. We'll term runtime for this program as `gen_time`. The metaprogram's core implementation are within `gen.hpp` and `gen.cpp` in the project directory.
|
||||||
|
|
||||||
|
`gen.cpp` \`s `main()` will expect to call one `gen_main()` which the user will have to define once for their program. There they will dictate everything that should be generated.
|
||||||
|
|
||||||
|
In order to keep the locality of this code within the same files the following pattern may be used:
|
||||||
|
|
||||||
|
Within `program.cpp` :
|
||||||
|
```cpp
|
||||||
|
#ifdef gen_time
|
||||||
|
#include "gen.hpp"
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
u32 gen_main()
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef gen_time
|
||||||
|
#include "program.gen.cpp"
|
||||||
|
|
||||||
|
// Regular runtime dependent on the generated code here.
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
This is ofc entirely optional and the metaprogram can be quite separated from the runtime in file organization.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To fill in.
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
Macros in c/c++ are usually painful to debug, and templates can be unless your on a monsterous IDE (and even then fail often).
|
||||||
|
|
||||||
|
Unfortunately most programming langauges opt the approach of internally processing the generated code immediately within the AST or not expose it to the user in a nice way to even introspect as a text file. Stage metaprogramming doesn't have this problem, since its entire purpose is to create those generated files.
|
||||||
|
|
||||||
|
This is technically what the macro preprocessor does in a basic form, however naturally its easier to deal with for more complex generation.
|
||||||
|
|
||||||
|
The drawback naturally is generation functions at face value harder to grasp than something following a template pattern (for simple generation). This drawback becomes less valid the more complex the code generation becomes.
|
||||||
|
|
||||||
|
Thus a rule of thumb is if its a simple define you can get away with just the preprocessor, or if the templates being used don't break the debugger, this is most likely not neded.
|
||||||
|
|
||||||
|
However, if the code being generated becomes complex, or from a datatable or database, this will be easier to deal with.
|
||||||
|
|
||||||
|
# TODO:
|
||||||
|
|
||||||
|
* Need problably a better name, I found a few repos with this same one...
|
||||||
|
* Actually get to version 1.
|
@ -1,5 +1,5 @@
|
|||||||
#define BLOAT_IMPL
|
#define BLOAT_IMPL
|
||||||
#include "Bloat.refactored.hpp"
|
#include "Bloat.hpp"
|
||||||
|
|
||||||
namespace Global
|
namespace Global
|
||||||
{
|
{
|
||||||
|
@ -84,7 +84,7 @@ namespace Global
|
|||||||
|
|
||||||
namespace Memory
|
namespace Memory
|
||||||
{
|
{
|
||||||
ct uw Initial_Reserve = megabytes(2);
|
ct uw Initial_Reserve = megabytes(10);
|
||||||
|
|
||||||
extern arena Global_Arena;
|
extern arena Global_Arena;
|
||||||
#define g_allocator arena_allocator( & Memory::Global_Arena)
|
#define g_allocator arena_allocator( & Memory::Global_Arena)
|
||||||
|
143
project/gen.cpp
143
project/gen.cpp
@ -1,9 +1,16 @@
|
|||||||
#include "Bloat.hpp"
|
#include "Bloat.hpp"
|
||||||
|
// #define gen_time
|
||||||
#include "gen.hpp"
|
#include "gen.hpp"
|
||||||
|
|
||||||
#ifdef gen_time
|
#ifdef gen_time
|
||||||
namespace gen
|
namespace gen
|
||||||
{
|
{
|
||||||
|
ct Code make()
|
||||||
|
{
|
||||||
|
return { Code::Invalid, nullptr, nullptr, { nullptr } };
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static Code Unused()
|
static Code Unused()
|
||||||
{
|
{
|
||||||
static Code value = {
|
static Code value = {
|
||||||
@ -13,13 +20,16 @@ namespace gen
|
|||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Code decl_type( char const* name, Code specifiers, Code type )
|
Code decl_type( char const* name, Code specifiers, Code type )
|
||||||
{
|
{
|
||||||
Code
|
Code
|
||||||
result;
|
result = make();
|
||||||
result.Type = Code::Decl_Type;
|
result.Type = Code::Decl_Type;
|
||||||
result.Name = string_make( g_allocator, name );
|
result.Name = string_make( g_allocator, name );
|
||||||
|
|
||||||
|
array_init( result.Entries, g_allocator );
|
||||||
result.add( specifiers );
|
result.add( specifiers );
|
||||||
result.add( type );
|
result.add( type );
|
||||||
|
|
||||||
@ -33,11 +43,11 @@ namespace gen
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
Code
|
Code
|
||||||
result;
|
result = make();
|
||||||
result.Type = Code::Decl_Function;
|
result.Type = Code::Decl_Function;
|
||||||
result.Name = string_make( g_allocator, name );
|
result.Name = string_make( g_allocator, name );
|
||||||
|
|
||||||
array_init( result.Content, g_allocator );
|
array_init( result.Entries, g_allocator );
|
||||||
|
|
||||||
if ( specifiers )
|
if ( specifiers )
|
||||||
result.add( specifiers );
|
result.add( specifiers );
|
||||||
@ -55,20 +65,28 @@ namespace gen
|
|||||||
if (num <= 0)
|
if (num <= 0)
|
||||||
fatal("TT::make_paramters: num is %d", num);
|
fatal("TT::make_paramters: num is %d", num);
|
||||||
|
|
||||||
Code result;
|
Code
|
||||||
|
result = make();
|
||||||
|
result.Type = Code::Parameters;
|
||||||
|
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, num);
|
va_start(va, num);
|
||||||
|
|
||||||
result.Name = string_make( g_allocator, va_arg(va, char const*) );
|
result.Name = string_make( g_allocator, va_arg(va, char const*) );
|
||||||
result.add( va_arg(va, Code) );
|
|
||||||
|
|
||||||
while( num -= 2, num % 2 )
|
array_init( result.Entries, g_allocator );
|
||||||
|
|
||||||
|
Code type = va_arg(va, Code);
|
||||||
|
result.add( type );
|
||||||
|
|
||||||
|
while( num -= 2, num && num % 2 == 0 )
|
||||||
{
|
{
|
||||||
Code
|
Code
|
||||||
param;
|
param = make();
|
||||||
param.Name = string_make( g_allocator, va_arg(va, char const*) );
|
param.Name = string_make( g_allocator, va_arg(va, char const*) );
|
||||||
param.add( va_arg(va, Code) );
|
|
||||||
|
type = va_arg(va, Code);
|
||||||
|
param.add( type );
|
||||||
|
|
||||||
result.add(param);
|
result.add(param);
|
||||||
}
|
}
|
||||||
@ -89,12 +107,12 @@ namespace gen
|
|||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
Code
|
Code
|
||||||
code;
|
result = make();
|
||||||
code.Name = string_make( g_allocator, fmt );
|
result.Name = string_make( g_allocator, fmt );
|
||||||
code.Type = Code::Untyped;
|
result.Type = Code::Untyped;
|
||||||
code.Content = string_make( g_allocator, buf );
|
result.Content = string_make( g_allocator, buf );
|
||||||
|
|
||||||
return code;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Code make_function( char const* name
|
Code make_function( char const* name
|
||||||
@ -104,7 +122,7 @@ namespace gen
|
|||||||
, Code body )
|
, Code body )
|
||||||
{
|
{
|
||||||
Code
|
Code
|
||||||
result;
|
result = make();
|
||||||
result.Name = string_make( g_allocator, name );
|
result.Name = string_make( g_allocator, name );
|
||||||
result.Type = Code::Function;
|
result.Type = Code::Function;
|
||||||
|
|
||||||
@ -123,37 +141,51 @@ namespace gen
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Code make_specifier( u32 num, ... )
|
Code make_specifiers( u32 num, ... )
|
||||||
{
|
{
|
||||||
if ( num <= 0 )
|
if ( num <= 0 )
|
||||||
fatal("gen::make_specifier: num cannot be zero.");
|
fatal("gen::make_specifier: num cannot be zero.");
|
||||||
|
|
||||||
Code
|
Code
|
||||||
result;
|
result = make();
|
||||||
|
result.Type = Code::Specifiers;
|
||||||
|
result.Content = string_make( g_allocator, "" );
|
||||||
|
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, num);
|
va_start(va, num);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
Specifier type = va_arg(va, Specifier);
|
Specifier type = (Specifier)va_arg(va, int);
|
||||||
|
|
||||||
switch ( type )
|
switch ( type )
|
||||||
{
|
{
|
||||||
case Alignas:
|
case Alignas:
|
||||||
result.Content = string_sprintf_buf( g_allocator, "%s(%d)", specifier_str(type), va_arg(va, u32) );
|
result.Content = string_append_fmt( result.Content, "%s(%d)", specifier_str(type), va_arg(va, u32) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
result.Content = string_make( g_allocator, specifier_str(type) );
|
const char* str = specifier_str(type);
|
||||||
|
|
||||||
|
result.Content = string_append_fmt( result.Content, "%s", str );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while ( num-- );
|
while ( --num, num );
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Code make_type( char const* name )
|
||||||
|
{
|
||||||
|
Code
|
||||||
|
result = make();
|
||||||
|
result.Name = string_make( g_allocator, name );
|
||||||
|
result.Type = Code::Typename;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
string Code::to_string()
|
string Code::to_string()
|
||||||
{
|
{
|
||||||
string result = string_make( g_allocator, "" );
|
string result = string_make( g_allocator, "" );
|
||||||
@ -173,12 +205,13 @@ namespace gen
|
|||||||
|
|
||||||
case Decl_Type:
|
case Decl_Type:
|
||||||
if ( Entries[0].Type == Specifiers )
|
if ( Entries[0].Type == Specifiers )
|
||||||
result = string_append_fmt("%s\n", Entries[0].to_string());
|
result = string_append_fmt( result, "%s\n", Entries[0].to_string());
|
||||||
|
|
||||||
result = string_append_fmt( result, "%s %s;\n", Entries[1].to_string(), Name );
|
result = string_append_fmt( result, "%s %s;\n", Entries[1].to_string(), Name );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Decl_Function:
|
case Decl_Function:
|
||||||
|
{
|
||||||
u32 index = 0;
|
u32 index = 0;
|
||||||
u32 left = array_count( Entries );
|
u32 left = array_count( Entries );
|
||||||
|
|
||||||
@ -207,16 +240,22 @@ namespace gen
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = string_appendc( result, ");\n" );
|
result = string_appendc( result, ");\n" );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Parameters:
|
case Parameters:
|
||||||
result = string_append_fmt( result, "%s %s", Entries[0], Name );
|
{
|
||||||
|
result = string_append_fmt( result, "%s %s", Entries[0].to_string(), Name );
|
||||||
|
|
||||||
u32 index = 1;
|
u32 index = 1;
|
||||||
u32 left = array_count( Entries ) - 1;
|
u32 left = array_count( Entries ) - 1;
|
||||||
|
|
||||||
while ( left-- )
|
while ( left-- )
|
||||||
result = string_append_fmt( result, ", %s %s", Entries[index].Entries[0], Entries[index].Name );
|
result = string_append_fmt( result, ", %s %s"
|
||||||
|
, Entries[index].Entries[0].to_string()
|
||||||
|
, Entries[index].Name
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Struct:
|
case Struct:
|
||||||
@ -224,31 +263,36 @@ namespace gen
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Function:
|
case Function:
|
||||||
|
{
|
||||||
u32 index = 0;
|
u32 index = 0;
|
||||||
u32 left = array_count( Entries );
|
u32 left = array_count( Entries );
|
||||||
|
|
||||||
if ( left <= 0 )
|
if ( left <= 0 )
|
||||||
fatal( "Code::to_string - Name: %s Type: %s, expected definition", Name, Type );
|
fatal( "Code::to_string - Name: %s Type: %s, expected definition", Name, Type );
|
||||||
|
|
||||||
while ( Entries[index].Type == EType::Specifiers )
|
if ( Entries[index].Type == Specifiers )
|
||||||
{
|
{
|
||||||
result = string_append_fmt( result, "%s ", Entries[index] );
|
result = string_append_fmt( result, "%s\n", Entries[index].to_string() );
|
||||||
index++;
|
index++;
|
||||||
|
left--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( left <= 0 )
|
if ( left <= 0 )
|
||||||
fatal( "Code::to_string - Name: %s Type: %s, expected return type", Name, Type );
|
fatal( "Code::to_string - Name: %s Type: %s, expected return type", Name, Type );
|
||||||
|
|
||||||
result = string_append_fmt( result, "\n%s %s(", Entries[index], Name );
|
result = string_append_fmt( result, "\n%s %s(", Entries[index].to_string(), Name );
|
||||||
index++;
|
index++;
|
||||||
|
left--;
|
||||||
|
|
||||||
while ( left && Entries[index].Type == Parameters )
|
if ( left && Entries[index].Type == Parameters )
|
||||||
{
|
{
|
||||||
result = string_append_fmt( result, "%s, ", Entries[index] );
|
result = string_append_fmt( result, "%s, ", Entries[index].to_string() );
|
||||||
index++;
|
index++;
|
||||||
|
left--;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = string_append_fmt( result, ")\n{\n%s\n}", Entries[index] );
|
result = string_append_fmt( result, ")\n{\n%s\n}", Entries[index].to_string() );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Specifiers:
|
case Specifiers:
|
||||||
@ -260,18 +304,41 @@ namespace gen
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Typename:
|
case Typename:
|
||||||
|
result = string_append_fmt( result, "%s", Name );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Builder::print( Code code )
|
||||||
|
{
|
||||||
|
Buffer = string_append( Buffer, code.to_string() );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Builder::open( char const* path )
|
||||||
|
{
|
||||||
|
file_error error = file_open_mode( & File, ZPL_FILE_MODE_WRITE, path );
|
||||||
|
|
||||||
|
if ( error != ZPL_FILE_ERROR_NONE )
|
||||||
|
{
|
||||||
|
fatal( "gen::File::open - Could not open file: %s", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer = string_make( g_allocator, "" );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Builder::write()
|
||||||
|
{
|
||||||
|
bool result = file_write( & File, Buffer, string_length(Buffer) );
|
||||||
|
|
||||||
|
if ( result == false )
|
||||||
|
fatal("gen::File::write - Failed to write to file: %s", file_name( & File ) );
|
||||||
|
|
||||||
|
file_close( & File );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
gen_main();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif gen_time
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef gen_time
|
|
||||||
#include "Bloat.hpp"
|
#include "Bloat.hpp"
|
||||||
|
|
||||||
|
#ifdef gen_time
|
||||||
namespace gen
|
namespace gen
|
||||||
{
|
{
|
||||||
ct sw ColumnLimit = 256;
|
ct sw ColumnLimit = 256;
|
||||||
@ -119,7 +119,7 @@ namespace gen
|
|||||||
forceinline
|
forceinline
|
||||||
operator bool()
|
operator bool()
|
||||||
{
|
{
|
||||||
return Type == Invalid;
|
return Type != Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator char const*()
|
operator char const*()
|
||||||
@ -153,13 +153,13 @@ namespace gen
|
|||||||
#endif
|
#endif
|
||||||
#pragma endregion Member API
|
#pragma endregion Member API
|
||||||
|
|
||||||
#define Using_Code_POD \
|
#define Using_Code_POD \
|
||||||
Code::EType Type; \
|
Code::EType Type; \
|
||||||
string Name; \
|
string Name; \
|
||||||
string Comment; \
|
string Comment; \
|
||||||
union { \
|
union { \
|
||||||
array(Code) Entries; \
|
array(Code) Entries; \
|
||||||
string Content; \
|
string Content; \
|
||||||
};
|
};
|
||||||
|
|
||||||
Using_Code_POD;
|
Using_Code_POD;
|
||||||
@ -180,7 +180,7 @@ namespace gen
|
|||||||
, Code ret_type
|
, Code ret_type
|
||||||
);
|
);
|
||||||
|
|
||||||
Code make_parameters( u32 num, ... );
|
Code make_parameters( s32 num, ... );
|
||||||
|
|
||||||
Code make_fmt( char const* fmt, ... );
|
Code make_fmt( char const* fmt, ... );
|
||||||
|
|
||||||
@ -197,20 +197,22 @@ namespace gen
|
|||||||
|
|
||||||
// Code make_template( Code subject, u32 num_dependents, ... );
|
// Code make_template( Code subject, u32 num_dependents, ... );
|
||||||
|
|
||||||
// Code make_type( char const* name );
|
Code make_type( char const* name );
|
||||||
|
|
||||||
// Code make_using( char const* name, char const* type );
|
// Code make_using( char const* name, char const* type );
|
||||||
|
|
||||||
|
|
||||||
struct File
|
struct Builder
|
||||||
{
|
{
|
||||||
zpl_file file;
|
zpl_file File;
|
||||||
string Content;
|
string Buffer;
|
||||||
|
|
||||||
s32 print( Code );
|
void print( Code );
|
||||||
|
|
||||||
bool open( char const* Path );
|
bool open( char const* path );
|
||||||
void write();
|
void write();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define gen_main main
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,16 +14,16 @@ foreach ( $arg in $args )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($false)
|
|
||||||
{
|
|
||||||
#region Regular Build
|
|
||||||
write-host "Building project`n"
|
|
||||||
|
|
||||||
$path_root = git rev-parse --show-toplevel
|
$path_root = git rev-parse --show-toplevel
|
||||||
$path_build = Join-Path $path_root build
|
$path_build = Join-Path $path_root build
|
||||||
$path_scripts = Join-Path $path_root scripts
|
$path_scripts = Join-Path $path_root scripts
|
||||||
|
|
||||||
|
|
||||||
|
if ($false)
|
||||||
|
{
|
||||||
|
#region Regular Build
|
||||||
|
write-host "Building project`n"
|
||||||
|
|
||||||
if ( -not( Test-Path $path_build ) )
|
if ( -not( Test-Path $path_build ) )
|
||||||
{
|
{
|
||||||
$args_meson = @()
|
$args_meson = @()
|
||||||
@ -87,7 +87,13 @@ Pop-Location
|
|||||||
$args_ninja += $path_gen_build
|
$args_ninja += $path_gen_build
|
||||||
|
|
||||||
Push-Location $path_root
|
Push-Location $path_root
|
||||||
ninja $args_ninja
|
& ninja $args_ninja
|
||||||
|
Pop-Location
|
||||||
|
|
||||||
|
$gencpp = Join-Path $path_gen_build gencpp.exe
|
||||||
|
|
||||||
|
Push-location $path_gen
|
||||||
|
& $gencpp
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
$path_root = git rev-parse --show-toplevel
|
$path_root = git rev-parse --show-toplevel
|
||||||
$path_build = Join-Path $path_root build
|
$path_build = Join-Path $path_root build
|
||||||
$path_test = Join-Path $path_root test
|
$path_test = Join-Path $path_root test
|
||||||
|
$path_gen = Join-Path $path_test gen
|
||||||
$path_test_build = Join-Path $path_test build
|
$path_test_build = Join-Path $path_test build
|
||||||
|
$path_gen_build = Join-Path $path_gen build
|
||||||
|
|
||||||
if ( Test-Path $path_build )
|
if ( Test-Path $path_build )
|
||||||
{
|
{
|
||||||
@ -13,6 +15,11 @@ if ( Test-Path $path_test_build )
|
|||||||
Remove-Item $path_test_build -Recurse
|
Remove-Item $path_test_build -Recurse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( Test-Path $path_gen_build )
|
||||||
|
{
|
||||||
|
Remove-Item $path_gen_build -Recurse
|
||||||
|
}
|
||||||
|
|
||||||
# [string[]] $include = '*.h', '*.hpp', '*.cpp'
|
# [string[]] $include = '*.h', '*.hpp', '*.cpp'
|
||||||
# [string[]] $exclude =
|
# [string[]] $exclude =
|
||||||
|
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
// Handwritten generated code:
|
|
||||||
|
|
||||||
|
|
||||||
#pragma region gen_array
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma endregion gen_array
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define Array( Type_ ) Array_##Type_
|
|
@ -1,164 +0,0 @@
|
|||||||
#include "gen.hpp"
|
|
||||||
#include "bloat.hpp"
|
|
||||||
|
|
||||||
#if tt
|
|
||||||
#define gen_array( Type_ ) gen__array( #Type_ )
|
|
||||||
Code* gen__array( char const* type )
|
|
||||||
{
|
|
||||||
Code codegen;
|
|
||||||
|
|
||||||
Code
|
|
||||||
data;
|
|
||||||
data.add( "%type* data" );
|
|
||||||
|
|
||||||
Code header;
|
|
||||||
header.define_struct( "Header",
|
|
||||||
"uw Num;"
|
|
||||||
"uw Capacity;"
|
|
||||||
"allocator Allocator;"
|
|
||||||
);
|
|
||||||
|
|
||||||
Code grow_formula;
|
|
||||||
grow_formula.define_function( "grow_formula", "static", "forceinline",
|
|
||||||
"return 2 * value * 8"
|
|
||||||
);
|
|
||||||
|
|
||||||
codegen.define_struct( "Array",
|
|
||||||
data
|
|
||||||
, header
|
|
||||||
, grow_formula
|
|
||||||
);
|
|
||||||
|
|
||||||
codegen.define
|
|
||||||
|
|
||||||
R"(
|
|
||||||
%type* data;
|
|
||||||
|
|
||||||
struct Header
|
|
||||||
{
|
|
||||||
uw Num;
|
|
||||||
uw Capacity;
|
|
||||||
allocator Allocator;
|
|
||||||
};
|
|
||||||
|
|
||||||
static forceinline
|
|
||||||
sw grow_formula ( sw value )
|
|
||||||
{
|
|
||||||
return 2 * value * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
bool init ( %Array& array, allocator mem_handler )
|
|
||||||
{
|
|
||||||
return init_reserve( array, mem_handler, grow_formula(0) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
bool init_reserve( %Array& array, allocator mem_handler, uw capacity )
|
|
||||||
{
|
|
||||||
Header*
|
|
||||||
header = nullptr;
|
|
||||||
header = rcast( Header*, alloc( mem_handler, size_of( Header ) + sizeof(type) * capacity ));
|
|
||||||
|
|
||||||
if (header == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
header->Num = 0;
|
|
||||||
header->Capacity = capacity;
|
|
||||||
header->Allocator = mem_handler;
|
|
||||||
|
|
||||||
array.data = rcast( %type*, header + 1 );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void append( %type value )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type back()
|
|
||||||
{
|
|
||||||
Header& header = get_header();
|
|
||||||
return data[ header.Num - 1 ];
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
get_header().Num = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill( uw begin, uw end, type value )
|
|
||||||
{
|
|
||||||
Header& header = get_header();
|
|
||||||
|
|
||||||
if ( begin < 0 || end >= header.Num )
|
|
||||||
{
|
|
||||||
fatal( "Range out of bounds" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void free()
|
|
||||||
{
|
|
||||||
Header& header = get_header();
|
|
||||||
::free( header.Allocator, & get_header() );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool grow( uw min_capacity )
|
|
||||||
{
|
|
||||||
Header& header = get_header();
|
|
||||||
|
|
||||||
uw new_capacity = grow_formula( header.Capacity );
|
|
||||||
|
|
||||||
if ( new_capacity < min_capacity )
|
|
||||||
new_capacity = min_capacity;
|
|
||||||
|
|
||||||
return set_capacity( new_capacity );
|
|
||||||
}
|
|
||||||
|
|
||||||
forceinline
|
|
||||||
Header& get_header()
|
|
||||||
{
|
|
||||||
return vcast( Header, data - 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void reserve()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void resize()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool set_capacity( uw capacity )
|
|
||||||
{
|
|
||||||
Header& header = get_header();
|
|
||||||
|
|
||||||
if ( capacity == header.Capacity )
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)"
|
|
||||||
, type
|
|
||||||
);
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void tt_run()
|
|
||||||
{
|
|
||||||
gen_array( u32 );
|
|
||||||
}
|
|
||||||
#endif tt
|
|
||||||
|
|
||||||
|
|
||||||
#if !tt
|
|
||||||
#include "array.gen.manual.hpp"
|
|
||||||
#endif
|
|
0
test/gen/math.gen.hpp
Normal file
0
test/gen/math.gen.hpp
Normal file
@ -4,15 +4,14 @@ project( 'test', 'c', 'cpp', default_options : ['buildtype=debug'] )
|
|||||||
|
|
||||||
includes = include_directories(
|
includes = include_directories(
|
||||||
[
|
[
|
||||||
'../test'
|
'../../project',
|
||||||
'../project'
|
'../../thirdparty'
|
||||||
, '../thirdparty'
|
|
||||||
])
|
])
|
||||||
|
|
||||||
# get_sources = files('./get_sources.ps1')
|
# get_sources = files('./get_sources.ps1')
|
||||||
# sources = files(run_command('powershell', get_sources, check: true).stdout().strip().split('\n'))
|
# sources = files(run_command('powershell', get_sources, check: true).stdout().strip().split('\n'))
|
||||||
|
|
||||||
sources = [ 'test.cpp' ]
|
sources = [ '../test.cpp' ]
|
||||||
|
|
||||||
if get_option('buildtype').startswith('debug')
|
if get_option('buildtype').startswith('debug')
|
||||||
|
|
||||||
@ -20,6 +19,6 @@ if get_option('buildtype').startswith('debug')
|
|||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
add_project_arguments('-Dgen_time', langauge : ['c', 'cpp'])
|
add_project_arguments('-Dgen_time', language : ['c', 'cpp'])
|
||||||
|
|
||||||
executable( '', sources, include_directories : includes )
|
executable( 'gencpp', sources, include_directories : includes )
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef gen_time
|
#include "Bloat.hpp"
|
||||||
#include "Bloat.hpp"
|
#include "gen.hpp"
|
||||||
#include "gen.hpp"
|
|
||||||
|
|
||||||
|
#ifdef gen_time
|
||||||
using namespace gen;
|
using namespace gen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -15,8 +15,8 @@
|
|||||||
return value * value;
|
return value * value;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
#define gen_square( Type_ ) gen__squre( #Type_ )
|
#define gen_square( Type_ ) gen__square( #Type_ )
|
||||||
Code gen__squre( char const* type )
|
Code gen__square( char const* type )
|
||||||
{
|
{
|
||||||
Code integral_type = make_type( type );
|
Code integral_type = make_type( type );
|
||||||
|
|
||||||
@ -41,17 +41,17 @@
|
|||||||
u32 gen_math()
|
u32 gen_math()
|
||||||
{
|
{
|
||||||
Code fadd_u8 = gen_square( u8 );
|
Code fadd_u8 = gen_square( u8 );
|
||||||
Code fadd_u16 = gen_square( u16 );
|
// Code fadd_u16 = gen_square( u16 );
|
||||||
Code fadd_u32 = gen_square( u32 );
|
// Code fadd_u32 = gen_square( u32 );
|
||||||
Code fadd_u64 = gen_square( u64 );
|
// Code fadd_u64 = gen_square( u64 );
|
||||||
|
|
||||||
File
|
Builder
|
||||||
mathgen;
|
mathgen;
|
||||||
mathgen.open( "math.gen.hpp" );
|
mathgen.open( "math.gen.hpp" );
|
||||||
mathgen.print( fadd_u8 );
|
mathgen.print( fadd_u8 );
|
||||||
mathgen.print( fadd_u16 );
|
// mathgen.print( fadd_u16 );
|
||||||
mathgen.print( fadd_u32 );
|
// mathgen.print( fadd_u32 );
|
||||||
mathgen.print( fadd_u64 );
|
// mathgen.print( fadd_u64 );
|
||||||
mathgen.write();
|
mathgen.write();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,28 @@
|
|||||||
|
#include "Bloat.cpp"
|
||||||
#include "math.hpp"
|
#include "math.hpp"
|
||||||
|
|
||||||
|
|
||||||
#ifdef gen_time
|
#ifdef gen_time
|
||||||
u32 gen_main()
|
|
||||||
{
|
|
||||||
return gen_math();
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "gen.cpp"
|
#include "gen.cpp"
|
||||||
|
|
||||||
|
int gen_main()
|
||||||
|
{
|
||||||
|
Memory::setup();
|
||||||
|
|
||||||
|
zpl_printf("\nPress any key after attaching to process\n");
|
||||||
|
getchar();
|
||||||
|
|
||||||
|
int result = gen_math();
|
||||||
|
|
||||||
|
Memory::cleanup();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef gen_time
|
#ifndef gen_time
|
||||||
|
#include "math.hpp"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
u32 result = square(5);
|
u32 result = square(5);
|
||||||
|
Loading…
Reference in New Issue
Block a user