2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
gencpp: A simple staged metaprogramming library for C++.
|
|
|
|
|
|
|
|
This library is intended for small-to midsize projects that want rapid complation times
|
|
|
|
for fast debugging.
|
|
|
|
|
|
|
|
AST type checking supports only a small subset of c++.
|
|
|
|
See the 'ECode' namespace and 'gen API' region to see what is supported.
|
|
|
|
|
|
|
|
There is no support for accessability fields in structs.
|
|
|
|
*/
|
|
|
|
|
2023-04-01 19:21:46 -07:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "Bloat.hpp"
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
// Defined by default.
|
|
|
|
|
|
|
|
#define GEN_ENABLE_READONLY_AST
|
|
|
|
// #define GEN_DEFINE_DSL
|
|
|
|
|
|
|
|
#define gen_time
|
2023-04-01 22:07:44 -07:00
|
|
|
#ifdef gen_time
|
2023-04-01 19:21:46 -07:00
|
|
|
namespace gen
|
|
|
|
{
|
2023-04-03 00:55:28 -07:00
|
|
|
#if 0
|
2023-04-01 19:21:46 -07:00
|
|
|
ct sw ColumnLimit = 256;
|
|
|
|
ct sw MaxLines = kilobytes(256);
|
|
|
|
|
|
|
|
using LineStr = char[ColumnLimit];
|
2023-04-03 00:55:28 -07:00
|
|
|
#endif
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
// Specifier Type
|
2023-04-01 19:21:46 -07:00
|
|
|
enum Specifier : u8
|
|
|
|
{
|
|
|
|
Alignas, // alignas(#)
|
|
|
|
Constexpr, // constexpr
|
|
|
|
Inline, // inline
|
2023-04-03 00:55:28 -07:00
|
|
|
|
2023-04-01 19:21:46 -07:00
|
|
|
C_Linkage, // extern "C"
|
|
|
|
API_Import, // Vendor specific way dynamic import symbol
|
|
|
|
API_Export, // Vendor specific way to dynamic export
|
|
|
|
External_Linkage, // extern
|
|
|
|
Internal_Linkage, // static (within unit file)
|
2023-04-02 09:35:14 -07:00
|
|
|
Static_Member, // static (within sturct/class)
|
2023-04-01 19:21:46 -07:00
|
|
|
Local_Persist, // static (within function)
|
|
|
|
Thread_Local, // thread_local
|
|
|
|
|
|
|
|
Num_Specifiers
|
|
|
|
};
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
// Specifier to string
|
|
|
|
inline
|
2023-04-01 19:21:46 -07:00
|
|
|
char const* specifier_str( Specifier specifier )
|
|
|
|
{
|
2023-04-03 00:55:28 -07:00
|
|
|
static
|
|
|
|
char const* lookup[ Num_Specifiers ] = {
|
2023-04-01 19:21:46 -07:00
|
|
|
"alignas",
|
|
|
|
"constexpr",
|
|
|
|
"inline",
|
2023-04-03 00:55:28 -07:00
|
|
|
|
2023-04-01 19:21:46 -07:00
|
|
|
"extern \"C\"",
|
|
|
|
#if defined(ZPL_SYSTEM_WINDOWS)
|
|
|
|
"__declspec(dllexport)",
|
|
|
|
"__declspec(dllimport)",
|
|
|
|
#elif defined(ZPL_SYSTEM_MACOS)
|
|
|
|
"__attribute__ ((visibility ("default")))",
|
|
|
|
"__attribute__ ((visibility ("default")))",
|
|
|
|
#endif
|
|
|
|
"extern",
|
|
|
|
"static",
|
|
|
|
"static",
|
2023-04-03 00:55:28 -07:00
|
|
|
"static",
|
2023-04-01 19:21:46 -07:00
|
|
|
"thread_local"
|
|
|
|
};
|
|
|
|
|
|
|
|
return lookup[ specifier ];
|
|
|
|
}
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
// Code Type
|
|
|
|
namespace ECode
|
2023-04-01 19:21:46 -07:00
|
|
|
{
|
2023-04-03 00:55:28 -07:00
|
|
|
enum Type : u8
|
2023-04-01 19:21:46 -07:00
|
|
|
{
|
|
|
|
Invalid,
|
|
|
|
|
|
|
|
Untyped, // User provided raw string.
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
Decl_Function, // Forward a function
|
|
|
|
Decl_Type, // Forward a type.
|
|
|
|
Function, // <type> <name>( <parameters> )
|
|
|
|
Function_Body, // { <body> }
|
|
|
|
Namespace,
|
|
|
|
Namespace_Body,
|
2023-04-01 19:21:46 -07:00
|
|
|
Parameters, // Used with functions.
|
2023-04-03 00:55:28 -07:00
|
|
|
Specifiers,
|
2023-04-01 19:21:46 -07:00
|
|
|
Struct,
|
2023-04-02 09:35:14 -07:00
|
|
|
Struct_Body,
|
2023-04-01 19:21:46 -07:00
|
|
|
Variable,
|
2023-04-03 00:55:28 -07:00
|
|
|
Typedef,
|
2023-04-01 19:21:46 -07:00
|
|
|
Typename,
|
2023-04-03 00:55:28 -07:00
|
|
|
Using,
|
2023-04-01 19:21:46 -07:00
|
|
|
|
|
|
|
Num_Types
|
|
|
|
};
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
inline
|
|
|
|
char const* str( Type type )
|
2023-04-01 19:21:46 -07:00
|
|
|
{
|
2023-04-03 00:55:28 -07:00
|
|
|
static
|
|
|
|
char const* lookup[Num_Types] = {
|
|
|
|
"Invalid",
|
|
|
|
|
|
|
|
"Untyped",
|
|
|
|
|
|
|
|
"Decl_Function",
|
|
|
|
"Decl_type",
|
|
|
|
"Function",
|
|
|
|
"Function_Body",
|
|
|
|
"Namespace",
|
|
|
|
"Namespace_Body",
|
|
|
|
"Parameters",
|
|
|
|
"Specifiers",
|
|
|
|
"Struct",
|
|
|
|
"Struct_Body",
|
|
|
|
"Variable",
|
|
|
|
"Typedef",
|
|
|
|
"Typename",
|
|
|
|
"using"
|
|
|
|
};
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
return lookup[ type ];
|
2023-04-01 19:21:46 -07:00
|
|
|
}
|
2023-04-03 00:55:28 -07:00
|
|
|
}
|
|
|
|
using CodeT = ECode::Type;
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
// TODO: If perf needs it, convert layout an SOA format.
|
|
|
|
/*
|
|
|
|
Simple AST POD with functionality to seralize into C++ syntax.
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
ASTs are currently stored as an AOS. They are always reconstructed on demand.
|
|
|
|
Thus redundant AST can easily occur.
|
|
|
|
Not sure if its better to store them in a hashmap.
|
|
|
|
*/
|
|
|
|
struct AST
|
|
|
|
{
|
|
|
|
#pragma region Member API
|
2023-04-01 19:21:46 -07:00
|
|
|
forceinline
|
2023-04-03 00:55:28 -07:00
|
|
|
void add( AST* other )
|
2023-04-01 19:21:46 -07:00
|
|
|
{
|
2023-04-03 00:55:28 -07:00
|
|
|
array_append( Entries, other );
|
|
|
|
|
|
|
|
other->Parent = this;
|
2023-04-01 19:21:46 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
forceinline
|
|
|
|
bool has_entries()
|
|
|
|
{
|
2023-04-03 00:55:28 -07:00
|
|
|
static bool lookup[ ECode::Num_Types] = {
|
2023-04-01 19:21:46 -07:00
|
|
|
false, // Invalid
|
|
|
|
false, // Unused
|
|
|
|
false, // Untyped
|
|
|
|
true, // Decl_Type
|
|
|
|
true, // Decl_Function
|
|
|
|
true, // Parameter
|
|
|
|
true, // Struct
|
|
|
|
true, // Function
|
|
|
|
false, // Specifier
|
|
|
|
true, // Variable
|
|
|
|
true, // Typename
|
|
|
|
};
|
|
|
|
|
|
|
|
return lookup[Type];
|
|
|
|
}
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
forceinline
|
|
|
|
bool is_invalid()
|
|
|
|
{
|
|
|
|
return Type != ECode::Invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
forceinline
|
|
|
|
char const* type_str()
|
|
|
|
{
|
|
|
|
return ECode::str( Type );
|
|
|
|
}
|
|
|
|
|
2023-04-01 19:21:46 -07:00
|
|
|
string to_string();
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
#pragma endregion Member API
|
|
|
|
|
|
|
|
#define Using_Code_POD \
|
|
|
|
CodeT Type; \
|
|
|
|
bool Readonly; \
|
|
|
|
AST* Parent; \
|
|
|
|
string Name; \
|
|
|
|
string Comment; \
|
|
|
|
union { \
|
|
|
|
array(AST*) Entries; \
|
|
|
|
string Content; \
|
|
|
|
};
|
|
|
|
|
|
|
|
Using_Code_POD;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CodePOD
|
|
|
|
{
|
|
|
|
Using_Code_POD;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Its intended for the AST to have equivalent size to its POD.
|
|
|
|
// All extra functionality within the AST namespace should just be syntatic sugar.
|
|
|
|
static_assert( sizeof(AST) == sizeof(CodePOD), "ERROR: AST IS NOT POD" );
|
|
|
|
|
|
|
|
/*
|
|
|
|
AST* typedef as to not constantly have to add the '*' as this is written often..
|
|
|
|
|
|
|
|
If GEN_ENABLE_READONLY_AST is defined, readonly assertions will be done on any member dreference,
|
|
|
|
and the 'gen API' related functions. will set their created ASTs to readonly before returning.
|
|
|
|
|
|
|
|
Casting to AST* will bypass.
|
|
|
|
*/
|
|
|
|
struct Code
|
|
|
|
{
|
|
|
|
AST* ast;
|
|
|
|
|
2023-04-01 19:21:46 -07:00
|
|
|
forceinline
|
|
|
|
operator bool()
|
|
|
|
{
|
2023-04-03 00:55:28 -07:00
|
|
|
return ast->is_invalid();
|
2023-04-01 19:21:46 -07:00
|
|
|
}
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
bool operator ==( Code other )
|
2023-04-01 19:21:46 -07:00
|
|
|
{
|
2023-04-03 00:55:28 -07:00
|
|
|
return ast == other.ast;
|
2023-04-01 19:21:46 -07:00
|
|
|
}
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
operator AST*()
|
|
|
|
{
|
|
|
|
return ast;
|
|
|
|
}
|
|
|
|
|
|
|
|
Code& operator =( Code other )
|
2023-04-01 19:21:46 -07:00
|
|
|
{
|
2023-04-03 00:55:28 -07:00
|
|
|
ast = other.ast;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
#ifdef GEN_ENABLE_READONLY_AST
|
|
|
|
forceinline
|
|
|
|
AST* operator ->()
|
|
|
|
{
|
|
|
|
if ( ast == nullptr )
|
|
|
|
fatal("Attempt to dereference a nullptr!");
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
if ( ast->Readonly )
|
|
|
|
fatal("Attempted to access a member from a readonly ast!");
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
return ast;
|
2023-04-01 19:21:46 -07:00
|
|
|
}
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
Code& operator *() = delete;
|
|
|
|
#endif
|
2023-04-01 19:21:46 -07:00
|
|
|
};
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
// Used when the its desired when omission is allowed in a definition.
|
|
|
|
ct Code UnusedCode = { nullptr };
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
// Used internally for the most part to identify invaidly generated code.
|
|
|
|
ct CodePOD InvalidCode = { ECode::Invalid, false, nullptr, nullptr, nullptr, { nullptr } };
|
|
|
|
|
|
|
|
/*
|
|
|
|
Type registy: Used to store Typename ASTs. Types are registered by their string literal value.
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
Purely used as a memory optimization.
|
|
|
|
Strings made with the Typename ASTs are stored in thier own arena allocator.
|
|
|
|
TODO: Implement and replace usage of def_type.
|
|
|
|
*/
|
|
|
|
// ZPL_TABLE_DECLARE( ZPL_EXTERN, TypeRegistry, type_reg_, Code );
|
2023-04-02 09:35:14 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
#pragma region gen API
|
|
|
|
/*
|
|
|
|
Initialize the library.
|
|
|
|
This currently just initializes the CodePool.
|
|
|
|
*/
|
2023-04-02 09:35:14 -07:00
|
|
|
void init();
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Foward Declare a type:
|
|
|
|
<specifiers> <type> <name>;
|
|
|
|
*/
|
2023-04-02 09:35:14 -07:00
|
|
|
Code decl_type( char const* name, Code type, Code specifiers = UnusedCode );
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Foward Declare a function:
|
|
|
|
<specifiers> <name> ( <params> );
|
|
|
|
*/
|
2023-04-01 19:21:46 -07:00
|
|
|
Code decl_fn( char const* name
|
|
|
|
, Code specifiers
|
|
|
|
, Code params
|
|
|
|
, Code ret_type
|
|
|
|
);
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Define an expression:
|
|
|
|
< c/c++ expression >
|
|
|
|
*/
|
|
|
|
Code def_expression( Code value );
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Define a function:
|
|
|
|
<specifiers> <name> ( <params> )
|
|
|
|
{
|
|
|
|
<body>
|
|
|
|
}
|
|
|
|
*/
|
2023-04-02 09:35:14 -07:00
|
|
|
Code def_function( char const* name
|
2023-04-01 19:21:46 -07:00
|
|
|
, Code specifiers
|
|
|
|
, Code params
|
|
|
|
, Code ret_type
|
|
|
|
, Code body
|
|
|
|
);
|
2023-04-02 09:35:14 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Define a fucntion body:
|
|
|
|
{
|
|
|
|
<entry>
|
|
|
|
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
Each entry is provided an empty line separation.
|
|
|
|
*/
|
|
|
|
Code def_function_body( s32 num, ... );
|
|
|
|
|
|
|
|
/*
|
|
|
|
Define a namespace;
|
|
|
|
namespace <name>
|
|
|
|
{
|
|
|
|
<body>
|
|
|
|
}
|
|
|
|
*/
|
2023-04-02 09:35:14 -07:00
|
|
|
Code def_namespace( char const* name, Code body );
|
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Define a namespace body:
|
|
|
|
{
|
|
|
|
<entry>
|
2023-04-02 09:35:14 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
Each entry is provided an empty line separation.
|
|
|
|
*/
|
|
|
|
Code def_namespace_body( s32 num, ... );
|
|
|
|
|
|
|
|
/*
|
|
|
|
Define a set of parameters for a function:
|
|
|
|
<name> <type>, ...
|
|
|
|
*/
|
|
|
|
Code def_parameters( s32 num, ... );
|
|
|
|
|
|
|
|
/*
|
|
|
|
Define a set of specifiers for a function, struct, type, or varaible
|
|
|
|
*/
|
|
|
|
Code def_specifiers( s32 num , ... );
|
|
|
|
|
|
|
|
/*
|
|
|
|
Define a struct:
|
|
|
|
struct <specifiers> <name> : <parent>
|
|
|
|
{
|
|
|
|
<body>
|
|
|
|
}
|
|
|
|
*/
|
2023-04-02 09:35:14 -07:00
|
|
|
Code def_struct( char const* name, Code body, Code parent = UnusedCode, Code specifiers = UnusedCode );
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Define a struct's body:
|
|
|
|
{
|
|
|
|
<entry>
|
|
|
|
|
|
|
|
...
|
|
|
|
}
|
|
|
|
|
|
|
|
Each entry is provided an empty line separation.
|
|
|
|
*/
|
|
|
|
Code def_struct_body( s32 num, ... );
|
|
|
|
|
|
|
|
/*
|
|
|
|
Define a variable:
|
|
|
|
<specifiers> <type> <name> = <value>;
|
|
|
|
*/
|
2023-04-02 09:35:14 -07:00
|
|
|
Code def_variable( char const* name, Code type, Code value = UnusedCode, Code specifiers = UnusedCode );
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Define a type AST value.
|
|
|
|
Useless by itself, its intended to be used in conjunction with
|
|
|
|
*/
|
2023-04-02 09:35:14 -07:00
|
|
|
Code def_type( char const* name );
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Define a using typedef:
|
|
|
|
using <name> = <type>;
|
|
|
|
*/
|
2023-04-02 09:35:14 -07:00
|
|
|
Code def_using( char const* name, Code type );
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Define a using namespace:
|
|
|
|
using namespace <name>;
|
|
|
|
|
|
|
|
Can only be used in either a
|
|
|
|
*/
|
|
|
|
Code def_using_namespace( char const* name );
|
|
|
|
|
|
|
|
/*
|
|
|
|
Define an untyped code string.
|
|
|
|
|
|
|
|
Untyped code may be used in bodies of functions, namespaces, or structs
|
|
|
|
or the in places where expressions may be placed.
|
|
|
|
|
|
|
|
Because the code within it is untyped, errors will naturally not be provided.
|
|
|
|
Consider this an a preprocessor define.
|
|
|
|
*/
|
|
|
|
Code untyped_str( char const* str );
|
|
|
|
|
|
|
|
/*
|
|
|
|
Define an untyped code string using traditional 'printf'.
|
|
|
|
|
|
|
|
Untyped code may be used in bodies of functions, namespaces, or structs
|
|
|
|
or the in places where expressions may be placed.
|
|
|
|
|
|
|
|
Because the code within it is untyped, errors will naturally not be provided.
|
|
|
|
Consider this an a preprocessor define.
|
|
|
|
*/
|
2023-04-02 09:35:14 -07:00
|
|
|
Code untyped_fmt( char const* fmt, ... );
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Define an untyped code string using token formatting:
|
|
|
|
... { <ID> } ... Will be repalced with value of token ID.
|
|
|
|
|
|
|
|
Values are to provided as: <char const* ID>, <char const* Value>, ...
|
|
|
|
|
|
|
|
num_tokens : The number of ID-Value pairs provided.
|
|
|
|
|
|
|
|
Untyped code may be used in bodies of functions, namespaces, or structs
|
|
|
|
or the in places where expressions may be placed.
|
|
|
|
|
|
|
|
Because the code within it is untyped, errors will naturally not be provided.
|
|
|
|
Consider this an a preprocessor define.
|
|
|
|
*/
|
|
|
|
Code token_fmt( char const* fmt, s32 num_tokens, ... );
|
|
|
|
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
/*
|
|
|
|
Creates a unit file.
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
These represent an encapsulation of a generated file
|
|
|
|
Used this if you need to pass around a group of Code entires at file scope level.
|
|
|
|
|
|
|
|
The name provided is the name of the file.
|
|
|
|
*/
|
|
|
|
Code create_Unit( char const* name );
|
|
|
|
|
|
|
|
/*
|
|
|
|
Used to generate the files.
|
|
|
|
This is inspired by jai's usage of the string_builder with #insert.
|
|
|
|
|
|
|
|
Its expected when using this library that Code ast will be serialized with the:
|
|
|
|
Builder::print() proc
|
|
|
|
|
|
|
|
The seralized content of the Code ast will be appended to Buffer within an empty line
|
|
|
|
prepared for a another definition or to add an empty newline to the end of the file.
|
|
|
|
|
|
|
|
Builder::write() should be called when all Code has been seralized for that file.
|
|
|
|
|
|
|
|
The #insert directive is thus represented by an #include of the generated file at your desired line
|
|
|
|
of any file in the target project.
|
|
|
|
*/
|
2023-04-01 22:07:44 -07:00
|
|
|
struct Builder
|
2023-04-01 19:21:46 -07:00
|
|
|
{
|
2023-04-01 22:07:44 -07:00
|
|
|
zpl_file File;
|
|
|
|
string Buffer;
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-01 22:07:44 -07:00
|
|
|
void print( Code );
|
2023-04-01 19:21:46 -07:00
|
|
|
|
2023-04-01 22:07:44 -07:00
|
|
|
bool open( char const* path );
|
2023-04-01 19:21:46 -07:00
|
|
|
void write();
|
|
|
|
};
|
2023-04-03 00:55:28 -07:00
|
|
|
#pragma endregion gen API
|
2023-04-01 19:21:46 -07:00
|
|
|
}
|
2023-04-01 22:07:44 -07:00
|
|
|
|
2023-04-03 00:55:28 -07:00
|
|
|
#pragma region MACROS
|
|
|
|
# define gen_main main
|
|
|
|
|
|
|
|
# define __ UnusedCode
|
|
|
|
|
|
|
|
/*
|
|
|
|
gen's Domain Specific Langauge.
|
|
|
|
|
|
|
|
Completely optional, makes the code gen syntax less verbose..
|
|
|
|
*/
|
|
|
|
#ifdef GEN_DEFINE_DSL
|
|
|
|
# define type( Name_, Value_ ) Code Name_ = gen::def_type( txt(Value_) )
|
|
|
|
# define type_fmt( Name_, Fmt_, ... ) Code Name_ = gen::def_type( bprintf( Fmt_, __VA_ARGS__ ) )
|
|
|
|
# define value( Name_, Value_ ) Code Name_ = gen::untyped_str( Value_ )
|
|
|
|
# define specifiers( Name_, ... ) Code Name_ = gen::def_specifiers( VA_NARGS( __VA_ARGS__ ), __VA_ARGS__ )
|
|
|
|
# define using( Name_, Type_ ) Code Name_ = gen::def_using( #Name_, Type_ )
|
|
|
|
|
|
|
|
# define var( Name_, Type_, Value_, Specifiers_ ) \
|
|
|
|
Code Name_ = gen::def_variable( #Name_, Type_, untyped_str( #Value_ ), Specifiers_ )
|
|
|
|
|
|
|
|
// # define def ( Name _ ) Code Name_;
|
|
|
|
|
|
|
|
# define params( ... ) gen::def_parameters( VA_NARGS( __VA_ARGS__ ) / 2, __VA_ARGS__ )
|
|
|
|
|
|
|
|
/*
|
|
|
|
Defines scoped symbol.
|
|
|
|
|
|
|
|
Used with:
|
|
|
|
- function
|
|
|
|
- namespace
|
|
|
|
- struct
|
|
|
|
*/
|
|
|
|
# define def( Name_ ) Code Name_;
|
|
|
|
|
|
|
|
# define function( Name_, Specifiers_, ReturnType_, Parameters_, Body_ ) \
|
|
|
|
Name_ = gen::def_function( #Name_, Specifiers_, Parameters_, ReturnType_, Body_ )
|
|
|
|
|
|
|
|
# define function_body( ... ) \
|
|
|
|
gen::def_function_body( VA_NARGS( __VA_ARS__ ), __VA_ARGS__ )
|
|
|
|
|
|
|
|
# define struct( Name_, Parent_, Specifiers_, Body_ ) \
|
|
|
|
Name_ = gen::def_struct( #Name_, Body_, Parent_, Specifiers_ )
|
|
|
|
|
|
|
|
# define struct_body( ... ) \
|
|
|
|
gen::def_struct_body( VA_NARGS( __VA_ARGS__ ), __VA_ARGS__ )
|
|
|
|
#endif
|
|
|
|
#pragma endregion MACROS
|
|
|
|
|
|
|
|
#pragma region CONSTANTS
|
|
|
|
namespace gen
|
|
|
|
{
|
|
|
|
// Predefined typename codes.
|
|
|
|
|
|
|
|
extern const Code t_bool;
|
|
|
|
extern const Code t_sw;
|
|
|
|
extern const Code t_uw;
|
|
|
|
|
|
|
|
extern const Code spec_inline;
|
|
|
|
}
|
|
|
|
#pragma endregion CONSTANTS
|
2023-04-01 19:21:46 -07:00
|
|
|
#endif
|