mirror of
https://github.com/Ed94/gencpp.git
synced 2025-07-04 04:41:02 -07:00
Compare commits
27 Commits
7946954017
...
Ed94-patch
Author | SHA1 | Date | |
---|---|---|---|
3133977b0f | |||
e4088185af | |||
c55151886f | |||
6689235691 | |||
6533a3be29 | |||
adbcb2a83b | |||
15847f10b9 | |||
8952cf5f1b | |||
2bdd49fd19 | |||
0f95c916dd | |||
527fb3b132 | |||
abffa74ad8 | |||
772d0de5c1 | |||
cb50f93af5 | |||
e4f564b165 | |||
0b78b74fbc | |||
5d8883ec45 | |||
c90c210e04 | |||
980d1d7134 | |||
b027778328 | |||
a6143e12b4 | |||
868b93cdd0 | |||
0b03b3cd92 | |||
572e957c17 | |||
63bc3bebed | |||
70872c29d1 | |||
e9752cb906 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -39,3 +39,5 @@ gen_c_library/gen
|
|||||||
**/*.vcxproj
|
**/*.vcxproj
|
||||||
**/*.vcxproj.filters
|
**/*.vcxproj.filters
|
||||||
**/*.vcxproj.user
|
**/*.vcxproj.user
|
||||||
|
test/c_library/gen
|
||||||
|
test/cpp_library/gen
|
||||||
|
67
.vscode/c_cpp_properties.json
vendored
67
.vscode/c_cpp_properties.json
vendored
@ -28,27 +28,6 @@
|
|||||||
"/FC"
|
"/FC"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Win32 msvc c_library",
|
|
||||||
"includePath": [
|
|
||||||
"${workspaceFolder}/gen_c_library/**"
|
|
||||||
],
|
|
||||||
"defines": [
|
|
||||||
"_DEBUG",
|
|
||||||
"UNICODE",
|
|
||||||
"_UNICODE",
|
|
||||||
"GEN_TIME",
|
|
||||||
"GEN_IMPLEMENTATION",
|
|
||||||
// "GEN_DONT_USE_NAMESPACE"
|
|
||||||
"GEN_INTELLISENSE_DIRECTIVES",
|
|
||||||
"INTELLISENSE_DIRECTIVES"
|
|
||||||
],
|
|
||||||
"cppStandard": "c++17",
|
|
||||||
"windowsSdkVersion": "10.0.19041.0",
|
|
||||||
"compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.29.30133/bin/HostX64/x64/cl.exe",
|
|
||||||
"intelliSenseMode": "msvc-x64",
|
|
||||||
"compileCommands": "${workspaceFolder}/.vscode/tasks.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Win32 clang",
|
"name": "Win32 clang",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
@ -64,10 +43,56 @@
|
|||||||
"GEN_INTELLISENSE_DIRECTIVES",
|
"GEN_INTELLISENSE_DIRECTIVES",
|
||||||
"INTELLISENSE_DIRECTIVES"
|
"INTELLISENSE_DIRECTIVES"
|
||||||
],
|
],
|
||||||
|
"cStandard": "c11",
|
||||||
|
"cppStandard": "c++17",
|
||||||
"windowsSdkVersion": "10.0.19041.0",
|
"windowsSdkVersion": "10.0.19041.0",
|
||||||
"compilerPath": "clang++.exe",
|
"compilerPath": "clang++.exe",
|
||||||
"intelliSenseMode": "windows-clang-x64",
|
"intelliSenseMode": "windows-clang-x64",
|
||||||
"compileCommands": "${workspaceFolder}/.vscode/tasks.json"
|
"compileCommands": "${workspaceFolder}/.vscode/tasks.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Win32 msvc c_library",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/gen_c_library/**"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"_DEBUG",
|
||||||
|
"UNICODE",
|
||||||
|
"_UNICODE",
|
||||||
|
"GEN_TIME",
|
||||||
|
"GEN_IMPLEMENTATION",
|
||||||
|
// "GEN_DONT_USE_NAMESPACE"
|
||||||
|
"GEN_INTELLISENSE_DIRECTIVES",
|
||||||
|
"INTELLISENSE_DIRECTIVES"
|
||||||
|
],
|
||||||
|
"cStandard": "c11",
|
||||||
|
"cppStandard": "c++17",
|
||||||
|
"windowsSdkVersion": "10.0.19041.0",
|
||||||
|
"compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.29.30133/bin/HostX64/x64/cl.exe",
|
||||||
|
"intelliSenseMode": "msvc-x64",
|
||||||
|
"compileCommands": "${workspaceFolder}/.vscode/tasks.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Win32 msvc c_library test",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/test/c_library/**",
|
||||||
|
"${workspaceFolder}/gen_c_library/gen/**"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"_DEBUG",
|
||||||
|
"UNICODE",
|
||||||
|
"_UNICODE",
|
||||||
|
"GEN_TIME",
|
||||||
|
"GEN_IMPLEMENTATION",
|
||||||
|
// "GEN_DONT_USE_NAMESPACE"
|
||||||
|
"GEN_INTELLISENSE_DIRECTIVES",
|
||||||
|
"INTELLISENSE_DIRECTIVES"
|
||||||
|
],
|
||||||
|
"cStandard": "c11",
|
||||||
|
"windowsSdkVersion": "10.0.19041.0",
|
||||||
|
"compilerPath": "C:/Program Files/Microsoft Visual Studio/2022/Professional/VC/Tools/MSVC/14.29.30133/bin/HostX64/x64/cl.exe",
|
||||||
|
"intelliSenseMode": "msvc-x64",
|
||||||
|
"compileCommands": "${workspaceFolder}/.vscode/tasks.json"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 4
|
"version": 4
|
||||||
|
16
LICENSE
16
LICENSE
@ -26,3 +26,19 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Source URL: https://github.com/Ed94/gencpp
|
||||||
|
|
||||||
|
Acknowledgements
|
||||||
|
|
||||||
|
* The dependencies for gencpp source are derived from the zpl library: https://github.com/zpl-c/zpl
|
||||||
|
|
||||||
|
Special thanks to:
|
||||||
|
|
||||||
|
* The Handmade Community.
|
||||||
|
|
||||||
|
* Casey Muratori, Ginger Bill (Bill Hall), Mr. 4th (Allen Webster), Ryan Fluery: Influnced conceptually how to handle staged metaprograming.
|
||||||
|
|
||||||
|
* Jonathan Blow: Jai's metaprogramming influenced the design of this library.
|
||||||
|
|
||||||
|
* My friends for putting up with discord spam on this library.
|
||||||
|
19
Readme.md
19
Readme.md
@ -1,6 +1,9 @@
|
|||||||
# gencpp
|
# gencpp
|
||||||
|
|
||||||
An attempt at simple staged metaprogramming for C/C++.
|
An attempt at simple staged metaprogramming for C/C++. Reflect and generate code for your codebase at runtime!
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
The library API is a composition of code element constructors, and a non-standards-compliant single-pass C/C++ parser.
|
The library API is a composition of code element constructors, and a non-standards-compliant single-pass C/C++ parser.
|
||||||
These build up a code AST to then serialize with a file builder, or can be traversed for staged-reflection of C/C++ code.
|
These build up a code AST to then serialize with a file builder, or can be traversed for staged-reflection of C/C++ code.
|
||||||
@ -49,7 +52,11 @@ Within `program.cpp` :
|
|||||||
|
|
||||||
u32 gen_main()
|
u32 gen_main()
|
||||||
{
|
{
|
||||||
|
gen::Context ctx;
|
||||||
|
gen::init(& ctx);
|
||||||
...
|
...
|
||||||
|
gen::deinit(& ctx);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -140,3 +147,13 @@ struct ArrayHeader
|
|||||||
## Building
|
## Building
|
||||||
|
|
||||||
See the [scripts directory](scripts/).
|
See the [scripts directory](scripts/).
|
||||||
|
|
||||||
|
## Gallery
|
||||||
|
|
||||||
|
### Listing definitions in the Cuik Compiler
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Unreal: Generating a UAttributeSet from a UDataTable
|
||||||
|
|
||||||
|
https://github.com/user-attachments/assets/2a07b743-825d-4f9f-beaf-3559e8748a4d
|
||||||
|
@ -8,7 +8,13 @@
|
|||||||
|
|
||||||
The library is fragmented into a series of headers and source files meant to be scanned in and then generated to a standard target format, or a user's desires.
|
The library is fragmented into a series of headers and source files meant to be scanned in and then generated to a standard target format, or a user's desires.
|
||||||
|
|
||||||
Standard formats:
|
If using the library's provided build scripts:
|
||||||
|
|
||||||
|
```ps1
|
||||||
|
.\build.ps1 <compiler> <debug or omit> base
|
||||||
|
```
|
||||||
|
|
||||||
|
## Content Overview
|
||||||
|
|
||||||
* **base**: Files are in granular pieces separated into four directories:
|
* **base**: Files are in granular pieces separated into four directories:
|
||||||
* **dependencies**: Originally from the c-zpl library and modified thereafter.
|
* **dependencies**: Originally from the c-zpl library and modified thereafter.
|
||||||
@ -27,7 +33,7 @@ Standard formats:
|
|||||||
* **gen_segemetned**: Dependencies go into gen.dep.{hpp/cpp} and components into gen.{hpp/cpp}
|
* **gen_segemetned**: Dependencies go into gen.dep.{hpp/cpp} and components into gen.{hpp/cpp}
|
||||||
* **gen_singleheader**: Everything into a single file: gen.hpp
|
* **gen_singleheader**: Everything into a single file: gen.hpp
|
||||||
* **gen_unreal_engine**: Like gen_segemented but the library is modified slightly to compile as a thirdparty library within an Unreal Engine plugin or module.
|
* **gen_unreal_engine**: Like gen_segemented but the library is modified slightly to compile as a thirdparty library within an Unreal Engine plugin or module.
|
||||||
* **gen_c_library**: The library is heavily modifed into C11 compliant code. A segemented and single-header set of variants are generatd.
|
* **gen_c_library**: The library is heavily modifed into C11 compliant code. A segemented and single-header set of variants are generated.
|
||||||
|
|
||||||
Code not making up the core library is located in `auxiliary/<auxiliary_name>.<hpp/cpp>`. These are optional extensions or tools for the library.
|
Code not making up the core library is located in `auxiliary/<auxiliary_name>.<hpp/cpp>`. These are optional extensions or tools for the library.
|
||||||
|
|
||||||
@ -117,15 +123,15 @@ The vast majority of macros should be single-line subsitutions that either add:
|
|||||||
|
|
||||||
There are ***five*** header files which are automatically generated using [base_codegen.hpp](./helpers/base_codegen.hpp) by [base.cpp](./base.cpp). They are all located in [components/gen](./components/gen/).
|
There are ***five*** header files which are automatically generated using [base_codegen.hpp](./helpers/base_codegen.hpp) by [base.cpp](./base.cpp). They are all located in [components/gen](./components/gen/).
|
||||||
|
|
||||||
* [`ecodetypes.hpp`](./components/gen/ecode.hpp): `CodeType` enum definition and related implementaiton. Generation is based off of [`ECodeType.csv](./enums/ECodeTypes.csv).
|
* [ecodetypes.hpp](./components/gen/ecode.hpp): `CodeType` enum definition and related implementaiton. Generation is based off of [ECodeType.csv](./enums/ECodeTypes.csv).
|
||||||
* [`especifier.hpp`](./components/gen/especifier.hpp): `Specifier` enum definition, etc. Generated using [`ESpecifier.csv`](./enums/ESpecifier.csv).
|
* [especifier.hpp](./components/gen/especifier.hpp): `Specifier` enum definition, etc. Generated using [ESpecifier.csv](./enums/ESpecifier.csv).
|
||||||
* [`eoperator.hpp`](./components/gen/eoperator.hpp): `Operator` enum definition, etc. Generated using [`EOperator.hpp`](./enums/EOperator.csv).
|
* [eoperator.hpp](./components/gen/eoperator.hpp): `Operator` enum definition, etc. Generated using [EOperator.hpp](./enums/EOperator.csv).
|
||||||
* [`etoktype.cpp`](./components/gen/etoktype.cpp): `TokType` enum defininition, etc. Used by the lexer and parser backend. Uses two csvs:
|
* [etoktype.cpp](./components/gen/etoktype.cpp): `TokType` enum defininition, etc. Used by the lexer and parser backend. Uses two csvs:
|
||||||
* [`ETokType.csv`](./enums/ETokType.csv): Provides the enum entries and their strinng ids.
|
* [ETokType.csv](./enums/ETokType.csv): Provides the enum entries and their strinng ids.
|
||||||
* [`AttributeTokens.csv`](./enums/AttributeTokens.csv): Provides tokens entries that should be considered as attributes by the lexer and parser. Sspecfiically macro attributes such as those use for exporting symbols.
|
* [AttributeTokens.csv](./enums/AttributeTokens.csv): Provides tokens entries that should be considered as attributes by the lexer and parser. Sspecfiically macro attributes such as those use for exporting symbols.
|
||||||
* [`ast_inlines.hpp`](./components/gen/ast_inlines.hpp): Member trivial `operator` definitions for C++ code types. Does not use a csv.
|
* [ast_inlines.hpp](./components/gen/ast_inlines.hpp): Member trivial `operator` definitions for C++ code types. Does not use a csv.
|
||||||
|
|
||||||
[`misc.hpp`](./helpers/misc.hpp): Has shared functions used by the library generation meta-programs throughout this codebase.
|
[misc.hpp](./helpers/misc.hpp): Has shared functions used by the library generation meta-programs throughout this codebase.
|
||||||
|
|
||||||
If using the library's provided build scripts:
|
If using the library's provided build scripts:
|
||||||
|
|
||||||
@ -154,9 +160,53 @@ Names or Content fields are interned strings and thus showed be cached using `ca
|
|||||||
|
|
||||||
`def_operator` is the most sophisticated upfront constructor as it has multiple permutations of definitions that could be created that are not trivial to determine if valid.
|
`def_operator` is the most sophisticated upfront constructor as it has multiple permutations of definitions that could be created that are not trivial to determine if valid.
|
||||||
|
|
||||||
The parser is documented under [`docs/Parsing.md`](../docs/Parsing.md) and [`docs/Parser_Algo.md`](../docs/Parser_Algo.md).
|
The parser is documented under [`docs/Parsing.md`](../docs/Parsing.md) and [`docs/Parser_Algo.md`](../docs/Parser_Algo.md). Read that and the entire library if you want to extend it.
|
||||||
|
|
||||||
|
### Attributes
|
||||||
|
|
||||||
|
To add additional macro attributes, all that has to be done is modifying [`AttributeTokens.csv`](./enums/AttributeTokens.csv).
|
||||||
|
|
||||||
|
### Specifiers
|
||||||
|
|
||||||
|
To add additional macro specifiers, the following needs to be done:
|
||||||
|
|
||||||
|
1. Adjust [especifier.hpp](./components/gen/especifier.hpp)
|
||||||
|
2. Adjust [etoktype.cpp](./components/gen/etoktype.cpp)
|
||||||
|
3. Adjust [parser_case_macros.cpp](./components/parser_case_macros.cpp)
|
||||||
|
|
||||||
|
If the specifier is a new trailing specifier on function definitions:
|
||||||
|
|
||||||
|
Head into [base_codegen.hpp](./helpers/base_codegen.hpp): `gen_especifier`. There will be an `is_trailing` function that needs to be adjusted with an additional case for the user's new trailing specifier.
|
||||||
|
|
||||||
|
### Code Types
|
||||||
|
|
||||||
|
These require the following to be handled to the equivalent extent as the other types:
|
||||||
|
|
||||||
|
1. Adjust [ECodeTypes.csv](./enums/ECodeTypes.csv) with the new types
|
||||||
|
2. Define a new `AST_<Name>` and `Code<Name>`. See
|
||||||
|
* [ast.hpp](./components/ast.hpp): Initial forwards and user defined conversion for Code.
|
||||||
|
* [ast_types.hpp](./components/ast_types.hpp): Define the `AST_<Name>` struct.
|
||||||
|
* [code_types.hpp](./components/code_types.hpp): Defne the `CodeType` struct. If its needs an iterator see: `struct CodeBody` & `struct CodeParams`.
|
||||||
|
3. [ast_case_macros.cpp](./components/ast_case_macros.cpp): Review cases here if the new code type needs to be considered.
|
||||||
|
4. [ast.cpp](./components/ast.cpp): Need to review
|
||||||
|
* `code_debug_str`
|
||||||
|
* `code_is_equal`
|
||||||
|
* `code_to_strbuilder_ptr`
|
||||||
|
* `code_validate_body`
|
||||||
|
5. [code_serialization.cpp](./components/code_serialization.cpp): Define serialization here.
|
||||||
|
6. [inlines.hpp](./components/inlines.hpp): Any inline definitions for the `struct Code<Name>` are defined here.
|
||||||
|
7. [interface.cpp](./components/interface.hpp): Define the `Code<Name>` upfront and parsing interface.
|
||||||
|
8. [interface.upfront.cpp](./components/interface.upfront.cpp): Define the upfront constructor implementation.
|
||||||
|
9. [interface.parsing.cpp](./components/interface.parsing.cpp): Define the parsing interface implementation.
|
||||||
|
10. [lexer.cpp](./components/lexer.cpp): Adjust the lexer as needed.
|
||||||
|
11. [parser.cpp](./components/parser.cpp): Adjust the parser as needed.
|
||||||
|
|
||||||
## A note on compilation and runtime generation speed
|
## A note on compilation and runtime generation speed
|
||||||
|
|
||||||
The library is designed to be fast to compile and generate code at runtime as fast as resonable possible on a debug build.
|
The library is designed to be fast to compile and generate code at runtime as fast as possible on a debug build.
|
||||||
Its recommended that your metaprogam be compiled using a single translation unit (unity build).
|
Its recommended that your metaprogam be compiled using a single translation unit (unity build).
|
||||||
|
|
||||||
|
## Whats with the expression / executions support #ifd and enums?
|
||||||
|
|
||||||
|
The library is a *work in progress* and those are unfinished hypotheticals for adding the ability to manage or parse the AST of expresions or execution scope code.
|
||||||
|
They are entirely untested and not meant to be used yet, futher there is no parsing support or an upfront interface for what CodeTypes are defined so far.
|
||||||
|
@ -15,7 +15,9 @@ Builder builder_open( char const* path )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Buffer = strbuilder_make_reserve( _ctx->Allocator_Temp, _ctx->InitSize_BuilderBuffer );
|
Context* ctx = get_context();
|
||||||
|
GEN_ASSERT_NOT_NULL(ctx);
|
||||||
|
result.Buffer = strbuilder_make_reserve( ctx->Allocator_Temp, ctx->InitSize_BuilderBuffer );
|
||||||
|
|
||||||
// log_fmt("$Builder - Opened file: %s\n", result.File.filename );
|
// log_fmt("$Builder - Opened file: %s\n", result.File.filename );
|
||||||
return result;
|
return result;
|
||||||
|
@ -25,13 +25,14 @@ Builder builder_open ( char const* path );
|
|||||||
void builder_pad_lines ( Builder* builder, s32 num );
|
void builder_pad_lines ( Builder* builder, s32 num );
|
||||||
void builder_print ( Builder* builder, Code code );
|
void builder_print ( Builder* builder, Code code );
|
||||||
void builder_print_fmt_va( Builder* builder, char const* fmt, va_list va );
|
void builder_print_fmt_va( Builder* builder, char const* fmt, va_list va );
|
||||||
void builder_print_fmt ( Builder* builder, char const* fmt, ... ) {
|
void builder_write ( Builder* builder );
|
||||||
|
|
||||||
|
forceinline void builder_print_fmt ( Builder* builder, char const* fmt, ... ) {
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start( va, fmt );
|
va_start( va, fmt );
|
||||||
builder_print_fmt_va( builder, fmt, va );
|
builder_print_fmt_va( builder, fmt, va );
|
||||||
va_end( va );
|
va_end( va );
|
||||||
}
|
}
|
||||||
void builder_write( Builder* builder );
|
|
||||||
|
|
||||||
struct Builder
|
struct Builder
|
||||||
{
|
{
|
||||||
@ -56,10 +57,10 @@ struct Builder
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if GEN_COMPILER_CPP && ! GEN_C_LIKE_CPP
|
#if GEN_COMPILER_CPP && ! GEN_C_LIKE_CPP
|
||||||
void builder_pad_lines( Builder& builder, s32 num ) { return builder_pad_lines(& builder, num); }
|
forceinline void builder_pad_lines( Builder& builder, s32 num ) { return builder_pad_lines(& builder, num); }
|
||||||
void builder_print ( Builder& builder, Code code ) { return builder_print(& builder, code); }
|
forceinline void builder_print ( Builder& builder, Code code ) { return builder_print(& builder, code); }
|
||||||
void builder_write ( Builder& builder ) { return builder_write(& builder ); }
|
forceinline void builder_write ( Builder& builder ) { return builder_write(& builder ); }
|
||||||
void builder_print_fmt( Builder& builder, char const* fmt, ...) {
|
forceinline void builder_print_fmt( Builder& builder, char const* fmt, ...) {
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start( va, fmt );
|
va_start( va, fmt );
|
||||||
builder_print_fmt_va( & builder, fmt, va );
|
builder_print_fmt_va( & builder, fmt, va );
|
||||||
|
@ -20,7 +20,7 @@ Code scan_file( char const* path )
|
|||||||
GEN_FATAL("scan_file: %s is empty", path );
|
GEN_FATAL("scan_file: %s is empty", path );
|
||||||
}
|
}
|
||||||
|
|
||||||
StrBuilder str = strbuilder_make_reserve( _ctx->Allocator_Temp, fsize );
|
StrBuilder str = strbuilder_make_reserve( get_context()->Allocator_Temp, fsize );
|
||||||
file_read( & file, str, fsize );
|
file_read( & file, str, fsize );
|
||||||
strbuilder_get_header(str)->Length = fsize;
|
strbuilder_get_header(str)->Length = fsize;
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ Code scan_file( char const* path )
|
|||||||
}
|
}
|
||||||
|
|
||||||
CodeBody parse_file( const char* path ) {
|
CodeBody parse_file( const char* path ) {
|
||||||
FileContents file = file_read_contents( _ctx->Allocator_Temp, true, path );
|
FileContents file = file_read_contents( get_context()->Allocator_Temp, true, path );
|
||||||
Str content = { (char const*)file.data, file.size };
|
Str content = { (char const*)file.data, file.size };
|
||||||
CodeBody code = parse_global_body( content );
|
CodeBody code = parse_global_body( content );
|
||||||
log_fmt("\nParsed: %s\n", path);
|
log_fmt("\nParsed: %s\n", path);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||||
#define GEN_EXPOSE_BACKEND
|
|
||||||
#define GEN_C_LIKE_CPP 1
|
#define GEN_C_LIKE_CPP 1
|
||||||
#include "gen.cpp"
|
#include "gen.cpp"
|
||||||
#include "helpers/push_ignores.inline.hpp"
|
#include "helpers/push_ignores.inline.hpp"
|
||||||
|
@ -43,7 +43,7 @@ struct AST_Pragma;
|
|||||||
struct AST_PreprocessCond;
|
struct AST_PreprocessCond;
|
||||||
struct AST_Specifiers;
|
struct AST_Specifiers;
|
||||||
|
|
||||||
#if GEN_EXECUTION_EXPRESSION_SUPPORT
|
#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT
|
||||||
struct AST_Expr;
|
struct AST_Expr;
|
||||||
struct AST_Expr_Assign;
|
struct AST_Expr_Assign;
|
||||||
struct AST_Expr_Alignof;
|
struct AST_Expr_Alignof;
|
||||||
@ -140,7 +140,7 @@ struct CodePragma;
|
|||||||
struct CodeSpecifiers;
|
struct CodeSpecifiers;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GEN_EXECUTION_EXPRESSION_SUPPORT
|
#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT
|
||||||
|
|
||||||
#if GEN_COMPILER_C
|
#if GEN_COMPILER_C
|
||||||
typedef AST_Expr* CodeExpr;
|
typedef AST_Expr* CodeExpr;
|
||||||
|
@ -42,6 +42,7 @@ struct AST_Body
|
|||||||
};
|
};
|
||||||
static_assert( sizeof(AST_Body) == sizeof(AST), "ERROR: AST_Body is not the same size as AST");
|
static_assert( sizeof(AST_Body) == sizeof(AST), "ERROR: AST_Body is not the same size as AST");
|
||||||
|
|
||||||
|
// TODO(Ed): Support chaining attributes (Use parameter linkage pattern)
|
||||||
struct AST_Attributes
|
struct AST_Attributes
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
@ -246,7 +247,7 @@ struct AST_Exec
|
|||||||
};
|
};
|
||||||
static_assert( sizeof(AST_Exec) == sizeof(AST), "ERROR: AST_Exec is not the same size as AST");
|
static_assert( sizeof(AST_Exec) == sizeof(AST), "ERROR: AST_Exec is not the same size as AST");
|
||||||
|
|
||||||
#if GEN_EXECUTION_EXPRESSION_SUPPORT
|
#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT
|
||||||
struct AST_Expr
|
struct AST_Expr
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
@ -749,7 +750,7 @@ struct AST_Specifiers
|
|||||||
};
|
};
|
||||||
static_assert( sizeof(AST_Specifiers) == sizeof(AST), "ERROR: AST_Specifier is not the same size as AST");
|
static_assert( sizeof(AST_Specifiers) == sizeof(AST), "ERROR: AST_Specifier is not the same size as AST");
|
||||||
|
|
||||||
#if GEN_EXECUTION_EXPRESSION_SUPPORT
|
#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT
|
||||||
struct AST_Stmt
|
struct AST_Stmt
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
|
@ -1036,12 +1036,24 @@ void specifiers_to_strbuilder_ref( CodeSpecifiers self, StrBuilder* result )
|
|||||||
GEN_ASSERT(result);
|
GEN_ASSERT(result);
|
||||||
s32 idx = 0;
|
s32 idx = 0;
|
||||||
s32 left = self->NumEntries;
|
s32 left = self->NumEntries;
|
||||||
while ( left-- )
|
while ( left -- )
|
||||||
{
|
{
|
||||||
Str spec = spec_to_str( self->ArrSpecs[idx] );
|
Specifier spec = self->ArrSpecs[idx];
|
||||||
strbuilder_append_fmt( result, "%.*s ", spec.Len, spec.Ptr );
|
Str spec_str = spec_to_str( spec );
|
||||||
|
if ( idx > 0 ) switch (spec) {
|
||||||
|
case Spec_Ptr:
|
||||||
|
case Spec_Ref:
|
||||||
|
case Spec_RValue:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
strbuilder_append_str(result, txt(" "));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strbuilder_append_fmt( result, "%S", spec_str );
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
strbuilder_append_str(result, txt(" "));
|
||||||
}
|
}
|
||||||
|
|
||||||
StrBuilder struct_to_strbuilder(CodeStruct self)
|
StrBuilder struct_to_strbuilder(CodeStruct self)
|
||||||
@ -1445,7 +1457,7 @@ void var_to_strbuilder_ref(CodeVar self, StrBuilder* result )
|
|||||||
strbuilder_append_fmt( result, "%SB ", attributes_to_strbuilder(self->Attributes) );
|
strbuilder_append_fmt( result, "%SB ", attributes_to_strbuilder(self->Attributes) );
|
||||||
|
|
||||||
if ( self->Specs )
|
if ( self->Specs )
|
||||||
strbuilder_append_fmt( result, "%SB\n", specifiers_to_strbuilder(self->Specs) );
|
strbuilder_append_fmt( result, "%SB", specifiers_to_strbuilder(self->Specs) );
|
||||||
|
|
||||||
strbuilder_append_fmt( result, "%SB %S", typename_to_strbuilder(self->ValueType), self->Name );
|
strbuilder_append_fmt( result, "%SB %S", typename_to_strbuilder(self->ValueType), self->Name );
|
||||||
|
|
||||||
|
@ -362,7 +362,7 @@ struct CodeExec
|
|||||||
AST_Exec *ast;
|
AST_Exec *ast;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if GEN_EXECUTION_EXPRESSION_SUPPORT
|
#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT
|
||||||
struct CodeExpr
|
struct CodeExpr
|
||||||
{
|
{
|
||||||
#if ! GEN_C_LIKE_CPP
|
#if ! GEN_C_LIKE_CPP
|
||||||
@ -689,7 +689,7 @@ struct CodePreprocessCond
|
|||||||
AST_PreprocessCond* ast;
|
AST_PreprocessCond* ast;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if GEN_EXECUTION_EXPRESSION_SUPPORT
|
#ifdef GEN_EXECUTION_EXPRESSION_SUPPORT
|
||||||
struct CodeStmt
|
struct CodeStmt
|
||||||
{
|
{
|
||||||
#if ! GEN_C_LIKE_CPP
|
#if ! GEN_C_LIKE_CPP
|
||||||
|
@ -39,7 +39,7 @@ enum Specifier : u32
|
|||||||
|
|
||||||
inline Str spec_to_str( Specifier type )
|
inline Str spec_to_str( Specifier type )
|
||||||
{
|
{
|
||||||
local_persist Str lookup[26] = {
|
local_persist Str lookup[] = {
|
||||||
{ "INVALID", sizeof( "INVALID" ) - 1 },
|
{ "INVALID", sizeof( "INVALID" ) - 1 },
|
||||||
{ "consteval", sizeof( "consteval" ) - 1 },
|
{ "consteval", sizeof( "consteval" ) - 1 },
|
||||||
{ "constexpr", sizeof( "constexpr" ) - 1 },
|
{ "constexpr", sizeof( "constexpr" ) - 1 },
|
||||||
@ -72,7 +72,18 @@ inline Str spec_to_str( Specifier type )
|
|||||||
|
|
||||||
inline bool spec_is_trailing( Specifier specifier )
|
inline bool spec_is_trailing( Specifier specifier )
|
||||||
{
|
{
|
||||||
return specifier > Spec_Virtual;
|
switch ( specifier )
|
||||||
|
{
|
||||||
|
case Spec_Const :
|
||||||
|
case Spec_Final :
|
||||||
|
case Spec_NoExceptions :
|
||||||
|
case Spec_Override :
|
||||||
|
case Spec_Pure :
|
||||||
|
case Spec_Volatile :
|
||||||
|
return true;
|
||||||
|
default :
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Specifier str_to_specifier( Str str )
|
inline Specifier str_to_specifier( Str str )
|
||||||
|
@ -24,8 +24,8 @@ enum TokType : u32
|
|||||||
Tok_BraceCurly_Close,
|
Tok_BraceCurly_Close,
|
||||||
Tok_BraceSquare_Open,
|
Tok_BraceSquare_Open,
|
||||||
Tok_BraceSquare_Close,
|
Tok_BraceSquare_Close,
|
||||||
Tok_Capture_Start,
|
Tok_Paren_Open,
|
||||||
Tok_Capture_End,
|
Tok_Paren_Close,
|
||||||
Tok_Comment,
|
Tok_Comment,
|
||||||
Tok_Comment_End,
|
Tok_Comment_End,
|
||||||
Tok_Comment_Start,
|
Tok_Comment_Start,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#pragma region Constants
|
#pragma region Constants
|
||||||
|
|
||||||
extern PreprocessorMacro enum_underlying_macro;
|
extern Macro enum_underlying_macro;
|
||||||
|
|
||||||
extern Code access_public;
|
extern Code access_public;
|
||||||
extern Code access_protected;
|
extern Code access_protected;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
| \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l |
|
| \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l |
|
||||||
| | | | | __} | |
|
| | | | | __} | |
|
||||||
| l_l l_l {___/ |
|
| l_l l_l {___/ |
|
||||||
! ----------------------------------------------------------------------- VERSION: v0.20-Alpha |
|
! ----------------------------------------------------------------------- VERSION: v0.23-Alpha |
|
||||||
! ============================================================================================ |
|
! ============================================================================================ |
|
||||||
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
|
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
|
||||||
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |
|
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |
|
||||||
|
@ -262,9 +262,9 @@ forceinline void define_params_append (CodeDefineParams appendee
|
|||||||
forceinline CodeDefineParams define_params_get (CodeDefineParams self, s32 idx ) { return (CodeDefineParams) (Code) params_get( cast(CodeParams, self), idx); }
|
forceinline CodeDefineParams define_params_get (CodeDefineParams self, s32 idx ) { return (CodeDefineParams) (Code) params_get( cast(CodeParams, self), idx); }
|
||||||
forceinline bool define_params_has_entries(CodeDefineParams self) { return params_has_entries( cast(CodeParams, self)); }
|
forceinline bool define_params_has_entries(CodeDefineParams self) { return params_has_entries( cast(CodeParams, self)); }
|
||||||
|
|
||||||
CodeDefineParams begin_CodeDefineParams(CodeDefineParams params) { return (CodeDefineParams) (Code) begin_CodeParams( cast(CodeParams, (Code)params)); }
|
forceinline CodeDefineParams begin_CodeDefineParams(CodeDefineParams params) { return (CodeDefineParams) (Code) begin_CodeParams( cast(CodeParams, (Code)params)); }
|
||||||
CodeDefineParams end_CodeDefineParams (CodeDefineParams params) { return (CodeDefineParams) (Code) end_CodeParams ( cast(CodeParams, (Code)params)); }
|
forceinline CodeDefineParams end_CodeDefineParams (CodeDefineParams params) { return (CodeDefineParams) (Code) end_CodeParams ( cast(CodeParams, (Code)params)); }
|
||||||
CodeDefineParams next_CodeDefineParams (CodeDefineParams params, CodeDefineParams entry_iter) { return (CodeDefineParams) (Code) next_CodeParams ( cast(CodeParams, (Code)params), cast(CodeParams, (Code)entry_iter)); }
|
forceinline CodeDefineParams next_CodeDefineParams (CodeDefineParams params, CodeDefineParams entry_iter) { return (CodeDefineParams) (Code) next_CodeParams ( cast(CodeParams, (Code)params), cast(CodeParams, (Code)entry_iter)); }
|
||||||
|
|
||||||
#if GEN_COMPILER_CPP
|
#if GEN_COMPILER_CPP
|
||||||
forceinline
|
forceinline
|
||||||
|
@ -179,28 +179,28 @@ void define_constants()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
spec_const = def_specifier( Spec_Const); code_set_global( cast(Code, spec_const ));
|
spec_const = def_specifier( Spec_Const); code_set_global( cast(Code, spec_const ));
|
||||||
spec_consteval = def_specifier( Spec_Consteval); code_set_global( cast(Code, spec_consteval ));;
|
spec_consteval = def_specifier( Spec_Consteval); code_set_global( cast(Code, spec_consteval ));
|
||||||
spec_constexpr = def_specifier( Spec_Constexpr); code_set_global( cast(Code, spec_constexpr ));;
|
spec_constexpr = def_specifier( Spec_Constexpr); code_set_global( cast(Code, spec_constexpr ));
|
||||||
spec_constinit = def_specifier( Spec_Constinit); code_set_global( cast(Code, spec_constinit ));;
|
spec_constinit = def_specifier( Spec_Constinit); code_set_global( cast(Code, spec_constinit ));
|
||||||
spec_extern_linkage = def_specifier( Spec_External_Linkage); code_set_global( cast(Code, spec_extern_linkage ));;
|
spec_extern_linkage = def_specifier( Spec_External_Linkage); code_set_global( cast(Code, spec_extern_linkage ));
|
||||||
spec_final = def_specifier( Spec_Final); code_set_global( cast(Code, spec_final ));;
|
spec_final = def_specifier( Spec_Final); code_set_global( cast(Code, spec_final ));
|
||||||
spec_forceinline = def_specifier( Spec_ForceInline); code_set_global( cast(Code, spec_forceinline ));;
|
spec_forceinline = def_specifier( Spec_ForceInline); code_set_global( cast(Code, spec_forceinline ));
|
||||||
spec_global = def_specifier( Spec_Global); code_set_global( cast(Code, spec_global ));;
|
spec_global = def_specifier( Spec_Global); code_set_global( cast(Code, spec_global ));
|
||||||
spec_inline = def_specifier( Spec_Inline); code_set_global( cast(Code, spec_inline ));;
|
spec_inline = def_specifier( Spec_Inline); code_set_global( cast(Code, spec_inline ));
|
||||||
spec_internal_linkage = def_specifier( Spec_Internal_Linkage); code_set_global( cast(Code, spec_internal_linkage ));;
|
spec_internal_linkage = def_specifier( Spec_Internal_Linkage); code_set_global( cast(Code, spec_internal_linkage ));
|
||||||
spec_local_persist = def_specifier( Spec_Local_Persist); code_set_global( cast(Code, spec_local_persist ));;
|
spec_local_persist = def_specifier( Spec_Local_Persist); code_set_global( cast(Code, spec_local_persist ));
|
||||||
spec_mutable = def_specifier( Spec_Mutable); code_set_global( cast(Code, spec_mutable ));;
|
spec_mutable = def_specifier( Spec_Mutable); code_set_global( cast(Code, spec_mutable ));
|
||||||
spec_neverinline = def_specifier( Spec_NeverInline); code_set_global( cast(Code, spec_neverinline ));;
|
spec_neverinline = def_specifier( Spec_NeverInline); code_set_global( cast(Code, spec_neverinline ));
|
||||||
spec_noexcept = def_specifier( Spec_NoExceptions); code_set_global( cast(Code, spec_noexcept ));;
|
spec_noexcept = def_specifier( Spec_NoExceptions); code_set_global( cast(Code, spec_noexcept ));
|
||||||
spec_override = def_specifier( Spec_Override); code_set_global( cast(Code, spec_override ));;
|
spec_override = def_specifier( Spec_Override); code_set_global( cast(Code, spec_override ));
|
||||||
spec_ptr = def_specifier( Spec_Ptr); code_set_global( cast(Code, spec_ptr ));;
|
spec_ptr = def_specifier( Spec_Ptr); code_set_global( cast(Code, spec_ptr ));
|
||||||
spec_pure = def_specifier( Spec_Pure); code_set_global( cast(Code, spec_pure ));
|
spec_pure = def_specifier( Spec_Pure); code_set_global( cast(Code, spec_pure ));
|
||||||
spec_ref = def_specifier( Spec_Ref); code_set_global( cast(Code, spec_ref ));;
|
spec_ref = def_specifier( Spec_Ref); code_set_global( cast(Code, spec_ref ));
|
||||||
spec_register = def_specifier( Spec_Register); code_set_global( cast(Code, spec_register ));;
|
spec_register = def_specifier( Spec_Register); code_set_global( cast(Code, spec_register ));
|
||||||
spec_rvalue = def_specifier( Spec_RValue); code_set_global( cast(Code, spec_rvalue ));;
|
spec_rvalue = def_specifier( Spec_RValue); code_set_global( cast(Code, spec_rvalue ));
|
||||||
spec_static_member = def_specifier( Spec_Static); code_set_global( cast(Code, spec_static_member ));;
|
spec_static_member = def_specifier( Spec_Static); code_set_global( cast(Code, spec_static_member ));
|
||||||
spec_thread_local = def_specifier( Spec_Thread_Local); code_set_global( cast(Code, spec_thread_local ));;
|
spec_thread_local = def_specifier( Spec_Thread_Local); code_set_global( cast(Code, spec_thread_local ));
|
||||||
spec_virtual = def_specifier( Spec_Virtual); code_set_global( cast(Code, spec_virtual ));;
|
spec_virtual = def_specifier( Spec_Virtual); code_set_global( cast(Code, spec_virtual ));
|
||||||
spec_volatile = def_specifier( Spec_Volatile); code_set_global( cast(Code, spec_volatile ));
|
spec_volatile = def_specifier( Spec_Volatile); code_set_global( cast(Code, spec_volatile ));
|
||||||
|
|
||||||
spec_local_persist = def_specifiers( 1, Spec_Local_Persist );
|
spec_local_persist = def_specifiers( 1, Spec_Local_Persist );
|
||||||
@ -211,7 +211,7 @@ void define_constants()
|
|||||||
enum_underlying_macro.Type = MT_Expression;
|
enum_underlying_macro.Type = MT_Expression;
|
||||||
enum_underlying_macro.Flags = MF_Functional;
|
enum_underlying_macro.Flags = MF_Functional;
|
||||||
}
|
}
|
||||||
register_preprocess_macro(enum_underlying_macro);
|
register_macro(enum_underlying_macro);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(Context* ctx)
|
void init(Context* ctx)
|
||||||
@ -315,8 +315,8 @@ void init(Context* ctx)
|
|||||||
if ( ctx->StrCache.Entries == nullptr )
|
if ( ctx->StrCache.Entries == nullptr )
|
||||||
GEN_FATAL( "gen::init: Failed to initialize the StringCache");
|
GEN_FATAL( "gen::init: Failed to initialize the StringCache");
|
||||||
|
|
||||||
ctx->PreprocessorMacros = hashtable_init(PreprocessorMacro, ctx->Allocator_DyanmicContainers);
|
ctx->Macros = hashtable_init(Macro, ctx->Allocator_DyanmicContainers);
|
||||||
if (ctx->PreprocessorMacros.Hashes == nullptr || ctx->PreprocessorMacros.Entries == nullptr) {
|
if (ctx->Macros.Hashes == nullptr || ctx->Macros.Entries == nullptr) {
|
||||||
GEN_FATAL( "gen::init: Failed to initialize the PreprocessMacros table" );
|
GEN_FATAL( "gen::init: Failed to initialize the PreprocessMacros table" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -356,7 +356,7 @@ void deinit(Context* ctx)
|
|||||||
array_free( ctx->CodePools);
|
array_free( ctx->CodePools);
|
||||||
array_free( ctx->StringArenas);
|
array_free( ctx->StringArenas);
|
||||||
|
|
||||||
hashtable_destroy(ctx->PreprocessorMacros);
|
hashtable_destroy(ctx->Macros);
|
||||||
|
|
||||||
left = array_num( ctx->Fallback_AllocatorBuckets);
|
left = array_num( ctx->Fallback_AllocatorBuckets);
|
||||||
if (left)
|
if (left)
|
||||||
@ -376,6 +376,13 @@ void deinit(Context* ctx)
|
|||||||
if (_ctx == ctx)
|
if (_ctx == ctx)
|
||||||
_ctx = nullptr;
|
_ctx = nullptr;
|
||||||
-- context_counter;
|
-- context_counter;
|
||||||
|
|
||||||
|
Context wipe = {};
|
||||||
|
* ctx = wipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context* get_context() {
|
||||||
|
return _ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(Context* ctx)
|
void reset(Context* ctx)
|
||||||
@ -401,7 +408,7 @@ void reset(Context* ctx)
|
|||||||
while ( left--, left );
|
while ( left--, left );
|
||||||
|
|
||||||
hashtable_clear(ctx->StrCache);
|
hashtable_clear(ctx->StrCache);
|
||||||
hashtable_clear(ctx->PreprocessorMacros);
|
hashtable_clear(ctx->Macros);
|
||||||
define_constants();
|
define_constants();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,47 +471,50 @@ Code make_code()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PreprocessorMacro* lookup_preprocess_macro( Str name ) {
|
Macro* lookup_macro( Str name ) {
|
||||||
u32 key = crc32( name.Ptr, name.Len );
|
u32 key = crc32( name.Ptr, name.Len );
|
||||||
return hashtable_get( _ctx->PreprocessorMacros, key );
|
return hashtable_get( _ctx->Macros, key );
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_preprocess_macro( PreprocessorMacro macro ) {
|
void register_macro( Macro macro ) {
|
||||||
GEN_ASSERT_NOT_NULL(macro.Name.Ptr);
|
GEN_ASSERT_NOT_NULL(macro.Name.Ptr);
|
||||||
GEN_ASSERT(macro.Name.Len > 0);
|
GEN_ASSERT(macro.Name.Len > 0);
|
||||||
u32 key = crc32( macro.Name.Ptr, macro.Name.Len );
|
u32 key = crc32( macro.Name.Ptr, macro.Name.Len );
|
||||||
hashtable_set( _ctx->PreprocessorMacros, key, macro );
|
macro.Name = cache_str(macro.Name);
|
||||||
|
hashtable_set( _ctx->Macros, key, macro );
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_preprocess_macros( s32 num, ... )
|
void register_macros( s32 num, ... )
|
||||||
{
|
{
|
||||||
GEN_ASSERT(num > 0);
|
GEN_ASSERT(num > 0);
|
||||||
va_list va;
|
va_list va;
|
||||||
va_start(va, num);
|
va_start(va, num);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
PreprocessorMacro macro = va_arg(va, PreprocessorMacro);
|
Macro macro = va_arg(va, Macro);
|
||||||
GEN_ASSERT_NOT_NULL(macro.Name.Ptr);
|
GEN_ASSERT_NOT_NULL(macro.Name.Ptr);
|
||||||
GEN_ASSERT(macro.Name.Len > 0);
|
GEN_ASSERT(macro.Name.Len > 0);
|
||||||
|
macro.Name = cache_str(macro.Name);
|
||||||
|
|
||||||
u32 key = crc32( macro.Name.Ptr, macro.Name.Len );
|
u32 key = crc32( macro.Name.Ptr, macro.Name.Len );
|
||||||
hashtable_set( _ctx->PreprocessorMacros, key, macro );
|
hashtable_set( _ctx->Macros, key, macro );
|
||||||
}
|
}
|
||||||
while (num--, num > 0);
|
while (num--, num > 0);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_preprocess_macros( s32 num, PreprocessorMacro* macros )
|
void register_macros_arr( s32 num, Macro* macros )
|
||||||
{
|
{
|
||||||
GEN_ASSERT(num > 0);
|
GEN_ASSERT(num > 0);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
PreprocessorMacro macro = * macros;
|
Macro macro = * macros;
|
||||||
GEN_ASSERT_NOT_NULL(macro.Name.Ptr);
|
GEN_ASSERT_NOT_NULL(macro.Name.Ptr);
|
||||||
GEN_ASSERT(macro.Name.Len > 0);
|
GEN_ASSERT(macro.Name.Len > 0);
|
||||||
|
macro.Name = cache_str(macro.Name);
|
||||||
|
|
||||||
u32 key = crc32( macro.Name.Ptr, macro.Name.Len );
|
u32 key = crc32( macro.Name.Ptr, macro.Name.Len );
|
||||||
hashtable_set( _ctx->PreprocessorMacros, key, macro );
|
hashtable_set( _ctx->Macros, key, macro );
|
||||||
++ macros;
|
++ macros;
|
||||||
}
|
}
|
||||||
while (num--, num > 0);
|
while (num--, num > 0);
|
||||||
|
@ -71,7 +71,7 @@ struct Context
|
|||||||
// Used by the lexer to persistently treat all these identifiers as preprocessor defines.
|
// Used by the lexer to persistently treat all these identifiers as preprocessor defines.
|
||||||
// Populate with strings via gen::cache_str.
|
// Populate with strings via gen::cache_str.
|
||||||
// Functional defines must have format: id( ;at minimum to indicate that the define is only valid with arguments.
|
// Functional defines must have format: id( ;at minimum to indicate that the define is only valid with arguments.
|
||||||
HashTable(PreprocessorMacro) PreprocessorMacros;
|
MacroTable Macros;
|
||||||
|
|
||||||
// Backend
|
// Backend
|
||||||
|
|
||||||
@ -79,6 +79,8 @@ struct Context
|
|||||||
u32 InitSize_Fallback_Allocator_Bucket_Size;
|
u32 InitSize_Fallback_Allocator_Bucket_Size;
|
||||||
Array(Arena) Fallback_AllocatorBuckets;
|
Array(Arena) Fallback_AllocatorBuckets;
|
||||||
|
|
||||||
|
StringTable token_fmt_map;
|
||||||
|
|
||||||
// Array(Token) LexerTokens;
|
// Array(Token) LexerTokens;
|
||||||
|
|
||||||
Array(Pool) CodePools;
|
Array(Pool) CodePools;
|
||||||
@ -91,6 +93,9 @@ struct Context
|
|||||||
|
|
||||||
// TODO(Ed): Active parse context vs a parse result need to be separated conceptually
|
// TODO(Ed): Active parse context vs a parse result need to be separated conceptually
|
||||||
ParseContext parser;
|
ParseContext parser;
|
||||||
|
|
||||||
|
// TODO(Ed): Formatting - This will eventually be in a separate struct when in the process of serialization of the builder.
|
||||||
|
s32 temp_serialize_indent;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize the library. There first ctx initialized must exist for lifetime of other contextes that come after as its the one that
|
// Initialize the library. There first ctx initialized must exist for lifetime of other contextes that come after as its the one that
|
||||||
@ -100,6 +105,9 @@ GEN_API void init(Context* ctx);
|
|||||||
// However on Windows at least, it doesn't need to occur as the OS will clean up after the process.
|
// However on Windows at least, it doesn't need to occur as the OS will clean up after the process.
|
||||||
GEN_API void deinit(Context* ctx);
|
GEN_API void deinit(Context* ctx);
|
||||||
|
|
||||||
|
// Retrieves the active context (not usually needed, but here in case...)
|
||||||
|
GEN_API Context* get_context();
|
||||||
|
|
||||||
// Clears the allocations, but doesn't free the memoery, then calls init() again.
|
// Clears the allocations, but doesn't free the memoery, then calls init() again.
|
||||||
// Ease of use.
|
// Ease of use.
|
||||||
GEN_API void reset(Context* ctx);
|
GEN_API void reset(Context* ctx);
|
||||||
@ -107,16 +115,20 @@ GEN_API void reset(Context* ctx);
|
|||||||
GEN_API void set_context(Context* ctx);
|
GEN_API void set_context(Context* ctx);
|
||||||
|
|
||||||
// Mostly intended for the parser
|
// Mostly intended for the parser
|
||||||
GEN_API PreprocessorMacro* lookup_preprocess_macro( Str Name );
|
GEN_API Macro* lookup_macro( Str Name );
|
||||||
|
|
||||||
// Alternative way to add a preprocess define entry for the lexer & parser to utilize
|
// Alternative way to add a preprocess define entry for the lexer & parser to utilize
|
||||||
// if the user doesn't want to use def_define
|
// if the user doesn't want to use def_define
|
||||||
// Macros are tracked by name so if the name already exists the entry will be overwritten.
|
// Macros are tracked by name so if the name already exists the entry will be overwritten.
|
||||||
GEN_API void register_preprocess_macro( PreprocessorMacro macro );
|
GEN_API void register_macro( Macro macro );
|
||||||
|
|
||||||
// Ease of use batch registration
|
// Ease of use batch registration
|
||||||
GEN_API void register_preprocess_macros( s32 num, ... );
|
GEN_API void register_macros( s32 num, ... );
|
||||||
GEN_API void register_preprocess_macros( s32 num, PreprocessorMacro* macros );
|
GEN_API void register_macros_arr( s32 num, Macro* macros );
|
||||||
|
|
||||||
|
#if GEN_COMPILER_CPP
|
||||||
|
forceinline void register_macros( s32 num, Macro* macros ) { return register_macros_arr(num, macros); }
|
||||||
|
#endif
|
||||||
|
|
||||||
// Used internally to retrive or make string allocations.
|
// Used internally to retrive or make string allocations.
|
||||||
// Strings are stored in a series of string arenas of fixed size (SizePer_StringArena)
|
// Strings are stored in a series of string arenas of fixed size (SizePer_StringArena)
|
||||||
@ -272,36 +284,49 @@ GEN_API CodeBody def_body( CodeType type );
|
|||||||
/// or provide as an array of Code objects.
|
/// or provide as an array of Code objects.
|
||||||
|
|
||||||
GEN_API CodeBody def_class_body ( s32 num, ... );
|
GEN_API CodeBody def_class_body ( s32 num, ... );
|
||||||
GEN_API CodeBody def_class_body ( s32 num, Code* codes );
|
GEN_API CodeBody def_class_body_arr ( s32 num, Code* codes );
|
||||||
GEN_API CodeDefineParams def_define_params ( s32 num, ... );
|
GEN_API CodeDefineParams def_define_params ( s32 num, ... );
|
||||||
GEN_API CodeDefineParams def_define_params ( s32 num, CodeDefineParams* codes );
|
GEN_API CodeDefineParams def_define_params_arr ( s32 num, CodeDefineParams* codes );
|
||||||
GEN_API CodeBody def_enum_body ( s32 num, ... );
|
GEN_API CodeBody def_enum_body ( s32 num, ... );
|
||||||
GEN_API CodeBody def_enum_body ( s32 num, Code* codes );
|
GEN_API CodeBody def_enum_body_arr ( s32 num, Code* codes );
|
||||||
GEN_API CodeBody def_export_body ( s32 num, ... );
|
GEN_API CodeBody def_export_body ( s32 num, ... );
|
||||||
GEN_API CodeBody def_export_body ( s32 num, Code* codes);
|
GEN_API CodeBody def_export_body_arr ( s32 num, Code* codes);
|
||||||
GEN_API CodeBody def_extern_link_body( s32 num, ... );
|
GEN_API CodeBody def_extern_link_body ( s32 num, ... );
|
||||||
GEN_API CodeBody def_extern_link_body( s32 num, Code* codes );
|
GEN_API CodeBody def_extern_link_body_arr ( s32 num, Code* codes );
|
||||||
GEN_API CodeBody def_function_body ( s32 num, ... );
|
GEN_API CodeBody def_function_body ( s32 num, ... );
|
||||||
GEN_API CodeBody def_function_body ( s32 num, Code* codes );
|
GEN_API CodeBody def_function_body_arr ( s32 num, Code* codes );
|
||||||
GEN_API CodeBody def_global_body ( s32 num, ... );
|
GEN_API CodeBody def_global_body ( s32 num, ... );
|
||||||
GEN_API CodeBody def_global_body ( s32 num, Code* codes );
|
GEN_API CodeBody def_global_body_arr ( s32 num, Code* codes );
|
||||||
GEN_API CodeBody def_namespace_body ( s32 num, ... );
|
GEN_API CodeBody def_namespace_body ( s32 num, ... );
|
||||||
GEN_API CodeBody def_namespace_body ( s32 num, Code* codes );
|
GEN_API CodeBody def_namespace_body_arr ( s32 num, Code* codes );
|
||||||
GEN_API CodeParams def_params ( s32 num, ... );
|
GEN_API CodeParams def_params ( s32 num, ... );
|
||||||
GEN_API CodeParams def_params ( s32 num, CodeParams* params );
|
GEN_API CodeParams def_params_arr ( s32 num, CodeParams* params );
|
||||||
GEN_API CodeSpecifiers def_specifiers ( s32 num, ... );
|
GEN_API CodeSpecifiers def_specifiers ( s32 num, ... );
|
||||||
GEN_API CodeSpecifiers def_specifiers ( s32 num, Specifier* specs );
|
GEN_API CodeSpecifiers def_specifiers_arr ( s32 num, Specifier* specs );
|
||||||
GEN_API CodeBody def_struct_body ( s32 num, ... );
|
GEN_API CodeBody def_struct_body ( s32 num, ... );
|
||||||
GEN_API CodeBody def_struct_body ( s32 num, Code* codes );
|
GEN_API CodeBody def_struct_body_arr ( s32 num, Code* codes );
|
||||||
GEN_API CodeBody def_union_body ( s32 num, ... );
|
GEN_API CodeBody def_union_body ( s32 num, ... );
|
||||||
GEN_API CodeBody def_union_body ( s32 num, Code* codes );
|
GEN_API CodeBody def_union_body_arr ( s32 num, Code* codes );
|
||||||
|
|
||||||
|
#if GEN_COMPILER_CPP
|
||||||
|
forceinline CodeBody def_class_body ( s32 num, Code* codes ) { return def_class_body_arr(num, codes); }
|
||||||
|
forceinline CodeDefineParams def_define_params ( s32 num, CodeDefineParams* codes ) { return def_define_params_arr(num, codes); }
|
||||||
|
forceinline CodeBody def_enum_body ( s32 num, Code* codes ) { return def_enum_body_arr(num, codes); }
|
||||||
|
forceinline CodeBody def_export_body ( s32 num, Code* codes) { return def_export_body_arr(num, codes); }
|
||||||
|
forceinline CodeBody def_extern_link_body( s32 num, Code* codes ) { return def_extern_link_body_arr(num, codes); }
|
||||||
|
forceinline CodeBody def_function_body ( s32 num, Code* codes ) { return def_function_body_arr(num, codes); }
|
||||||
|
forceinline CodeBody def_global_body ( s32 num, Code* codes ) { return def_global_body_arr(num, codes); }
|
||||||
|
forceinline CodeBody def_namespace_body ( s32 num, Code* codes ) { return def_namespace_body_arr(num, codes); }
|
||||||
|
forceinline CodeParams def_params ( s32 num, CodeParams* params ) { return def_params_arr(num, params); }
|
||||||
|
forceinline CodeSpecifiers def_specifiers ( s32 num, Specifier* specs ) { return def_specifiers_arr(num, specs); }
|
||||||
|
forceinline CodeBody def_struct_body ( s32 num, Code* codes ) { return def_struct_body_arr(num, codes); }
|
||||||
|
forceinline CodeBody def_union_body ( s32 num, Code* codes ) { return def_union_body_arr(num, codes); }
|
||||||
|
#endif
|
||||||
|
|
||||||
#pragma endregion Upfront
|
#pragma endregion Upfront
|
||||||
|
|
||||||
#pragma region Parsing
|
#pragma region Parsing
|
||||||
|
|
||||||
// TODO(Ed) : Implmeent the new parser API design.
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
struct StackNode
|
struct StackNode
|
||||||
{
|
{
|
||||||
@ -378,12 +403,20 @@ GEN_API Code untyped_token_fmt( s32 num_tokens, char const* fmt, ... );
|
|||||||
#ifndef name
|
#ifndef name
|
||||||
// Convienence for defining any name used with the gen api.
|
// Convienence for defining any name used with the gen api.
|
||||||
// Lets you provide the length and string literal to the functions without the need for the DSL.
|
// Lets you provide the length and string literal to the functions without the need for the DSL.
|
||||||
#define name( Id_ ) { stringize(Id_), sizeof(stringize( Id_ )) - 1 }
|
# if GEN_COMPILER_C
|
||||||
|
# define name( Id_ ) (Str){ stringize(Id_), sizeof(stringize( Id_ )) - 1 }
|
||||||
|
# else
|
||||||
|
# define name( Id_ ) Str { stringize(Id_), sizeof(stringize( Id_ )) - 1 }
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef code
|
#ifndef code
|
||||||
// Same as name just used to indicate intention of literal for code instead of names.
|
// Same as name just used to indicate intention of literal for code instead of names.
|
||||||
#define code( ... ) { stringize( __VA_ARGS__ ), sizeof(stringize(__VA_ARGS__)) - 1 }
|
# if GEN_COMPILER_C
|
||||||
|
# define code( ... ) (Str){ stringize( __VA_ARGS__ ), sizeof(stringize(__VA_ARGS__)) - 1 }
|
||||||
|
# else
|
||||||
|
# define code( ... ) Str { stringize( __VA_ARGS__ ), sizeof(stringize(__VA_ARGS__)) - 1 }
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef args
|
#ifndef args
|
||||||
|
@ -73,7 +73,7 @@ CodeConstructor parse_constructor( Str def )
|
|||||||
|
|
||||||
if ( NumSpecifiers )
|
if ( NumSpecifiers )
|
||||||
{
|
{
|
||||||
specifiers = def_specifiers( NumSpecifiers, specs_found );
|
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
// <specifiers> ...
|
// <specifiers> ...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,9 +8,8 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va )
|
|||||||
char const* buf_begin = buf;
|
char const* buf_begin = buf;
|
||||||
ssize remaining = buf_size;
|
ssize remaining = buf_size;
|
||||||
|
|
||||||
local_persist StringTable tok_map;
|
if (_ctx->token_fmt_map.Hashes == nullptr) {
|
||||||
do_once() {
|
_ctx->token_fmt_map = hashtable_init(Str, _ctx->Allocator_DyanmicContainers );
|
||||||
tok_map = hashtable_init(Str, _ctx->Allocator_DyanmicContainers );
|
|
||||||
}
|
}
|
||||||
// Populate token pairs
|
// Populate token pairs
|
||||||
{
|
{
|
||||||
@ -22,7 +21,7 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va )
|
|||||||
Str value = va_arg( va, Str );
|
Str value = va_arg( va, Str );
|
||||||
|
|
||||||
u32 key = crc32( token, c_str_len(token) );
|
u32 key = crc32( token, c_str_len(token) );
|
||||||
hashtable_set( tok_map, key, value );
|
hashtable_set( _ctx->token_fmt_map, key, value );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va )
|
|||||||
char const* token = fmt + 1;
|
char const* token = fmt + 1;
|
||||||
|
|
||||||
u32 key = crc32( token, tok_len );
|
u32 key = crc32( token, tok_len );
|
||||||
Str* value = hashtable_get(tok_map, key );
|
Str* value = hashtable_get(_ctx->token_fmt_map, key );
|
||||||
|
|
||||||
if ( value )
|
if ( value )
|
||||||
{
|
{
|
||||||
@ -87,7 +86,7 @@ ssize token_fmt_va( char* buf, usize buf_size, s32 num_tokens, va_list va )
|
|||||||
current = * fmt;
|
current = * fmt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hashtable_clear(tok_map);
|
hashtable_clear(_ctx->token_fmt_map);
|
||||||
ssize result = buf_size - remaining;
|
ssize result = buf_size - remaining;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -578,8 +578,8 @@ CodeDefine def_define( Str name, MacroType type, Opts_def_define p )
|
|||||||
|
|
||||||
b32 register_define = ! p.dont_register_to_preprocess_macros;
|
b32 register_define = ! p.dont_register_to_preprocess_macros;
|
||||||
if ( register_define ) {
|
if ( register_define ) {
|
||||||
PreprocessorMacro macro_entry = { result->Name, type, p.flags };
|
Macro macro_entry = { result->Name, type, p.flags };
|
||||||
register_preprocess_macro(macro_entry);
|
register_macro(macro_entry);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1274,7 +1274,7 @@ CodeUsing def_using_namespace( Str name )
|
|||||||
|
|
||||||
CodeVar def_variable( CodeTypename type, Str name, Opts_def_variable p )
|
CodeVar def_variable( CodeTypename type, Str name, Opts_def_variable p )
|
||||||
{
|
{
|
||||||
if ( ! name_check( def_variable, name ) || null_check( def_variable, type ) ) {
|
if ( ! name_check( def_variable, name ) || ! null_check( def_variable, type ) ) {
|
||||||
GEN_DEBUG_TRAP();
|
GEN_DEBUG_TRAP();
|
||||||
return InvalidCode;
|
return InvalidCode;
|
||||||
}
|
}
|
||||||
@ -1369,7 +1369,7 @@ CodeBody def_class_body( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBody def_class_body( s32 num, Code* codes )
|
CodeBody def_class_body_arr( s32 num, Code* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_class_body );
|
def_body_code_array_start( def_class_body );
|
||||||
|
|
||||||
@ -1432,7 +1432,7 @@ CodeDefineParams def_define_params( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeDefineParams def_define_params( s32 num, CodeDefineParams* codes )
|
CodeDefineParams def_define_params_arr( s32 num, CodeDefineParams* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_define_params );
|
def_body_code_array_start( def_define_params );
|
||||||
|
|
||||||
@ -1491,7 +1491,7 @@ CodeBody def_enum_body( s32 num, ... )
|
|||||||
return (CodeBody) result;
|
return (CodeBody) result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBody def_enum_body( s32 num, Code* codes )
|
CodeBody def_enum_body_arr( s32 num, Code* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_enum_body );
|
def_body_code_array_start( def_enum_body );
|
||||||
|
|
||||||
@ -1552,7 +1552,7 @@ CodeBody def_export_body( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBody def_export_body( s32 num, Code* codes )
|
CodeBody def_export_body_arr( s32 num, Code* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_export_body );
|
def_body_code_array_start( def_export_body );
|
||||||
|
|
||||||
@ -1618,7 +1618,7 @@ CodeBody def_extern_link_body( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBody def_extern_link_body( s32 num, Code* codes )
|
CodeBody def_extern_link_body_arr( s32 num, Code* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_extern_linkage_body );
|
def_body_code_array_start( def_extern_linkage_body );
|
||||||
|
|
||||||
@ -1685,7 +1685,7 @@ CodeBody def_function_body( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBody def_function_body( s32 num, Code* codes )
|
CodeBody def_function_body_arr( s32 num, Code* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_function_body );
|
def_body_code_array_start( def_function_body );
|
||||||
|
|
||||||
@ -1756,7 +1756,7 @@ CodeBody def_global_body( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBody def_global_body( s32 num, Code* codes )
|
CodeBody def_global_body_arr( s32 num, Code* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_global_body );
|
def_body_code_array_start( def_global_body );
|
||||||
|
|
||||||
@ -1827,7 +1827,7 @@ CodeBody def_namespace_body( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBody def_namespace_body( s32 num, Code* codes )
|
CodeBody def_namespace_body_arr( s32 num, Code* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_namespace_body );
|
def_body_code_array_start( def_namespace_body );
|
||||||
|
|
||||||
@ -1889,7 +1889,7 @@ CodeParams def_params( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeParams def_params( s32 num, CodeParams* codes )
|
CodeParams def_params_arr( s32 num, CodeParams* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_params );
|
def_body_code_array_start( def_params );
|
||||||
|
|
||||||
@ -1945,7 +1945,7 @@ CodeSpecifiers def_specifiers( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeSpecifiers def_specifiers( s32 num, Specifier* specs )
|
CodeSpecifiers def_specifiers_arr( s32 num, Specifier* specs )
|
||||||
{
|
{
|
||||||
if ( num <= 0 ) {
|
if ( num <= 0 ) {
|
||||||
log_failure("gen::def_specifiers: num cannot be zero or less");
|
log_failure("gen::def_specifiers: num cannot be zero or less");
|
||||||
@ -2004,7 +2004,7 @@ CodeBody def_struct_body( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBody def_struct_body( s32 num, Code* codes )
|
CodeBody def_struct_body_arr( s32 num, Code* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_struct_body );
|
def_body_code_array_start( def_struct_body );
|
||||||
|
|
||||||
@ -2065,7 +2065,7 @@ CodeBody def_union_body( s32 num, ... )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeBody def_union_body( s32 num, Code* codes )
|
CodeBody def_union_body_arr( s32 num, Code* codes )
|
||||||
{
|
{
|
||||||
def_body_code_array_start( def_union_body );
|
def_body_code_array_start( def_union_body );
|
||||||
|
|
||||||
|
@ -128,8 +128,8 @@ s32 lex_preprocessor_define( LexContext* ctx )
|
|||||||
b32 not_specifier = spec == Spec_Invalid;
|
b32 not_specifier = spec == Spec_Invalid;
|
||||||
b32 not_attribute = attrib <= Tok___Attributes_Start;
|
b32 not_attribute = attrib <= Tok___Attributes_Start;
|
||||||
|
|
||||||
PreprocessorMacro macro = { name.Text, MT_Expression, (MacroFlags)0 };
|
Macro macro = { name.Text, MT_Expression, (MacroFlags)0 };
|
||||||
PreprocessorMacro* registered_macro = lookup_preprocess_macro(name.Text);
|
Macro* registered_macro = lookup_macro(name.Text);
|
||||||
|
|
||||||
if ( registered_macro == nullptr && not_specifier && not_attribute ) {
|
if ( registered_macro == nullptr && not_specifier && not_attribute ) {
|
||||||
log_fmt("Warning: '%S' was not registered before the lexer processed its #define directive, it will be registered as a expression macro\n"
|
log_fmt("Warning: '%S' was not registered before the lexer processed its #define directive, it will be registered as a expression macro\n"
|
||||||
@ -151,11 +151,11 @@ s32 lex_preprocessor_define( LexContext* ctx )
|
|||||||
macro.Flags |= MF_Functional;
|
macro.Flags |= MF_Functional;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token opening_paren = { { ctx->scanner, 1 }, Tok_Capture_Start, ctx->line, ctx->column, TF_Preprocess };
|
Token opening_paren = { { ctx->scanner, 1 }, Tok_Paren_Open, ctx->line, ctx->column, TF_Preprocess };
|
||||||
array_append( _ctx->Lexer_Tokens, opening_paren );
|
array_append( _ctx->Lexer_Tokens, opening_paren );
|
||||||
move_forward();
|
move_forward();
|
||||||
|
|
||||||
Token last_parameter;
|
Token last_parameter = {};
|
||||||
// We need to tokenize the define's arguments now:
|
// We need to tokenize the define's arguments now:
|
||||||
while( ctx->left && * ctx->scanner != ')')
|
while( ctx->left && * ctx->scanner != ')')
|
||||||
{
|
{
|
||||||
@ -242,7 +242,7 @@ s32 lex_preprocessor_define( LexContext* ctx )
|
|||||||
);
|
);
|
||||||
return Lex_ReturnNull;
|
return Lex_ReturnNull;
|
||||||
}
|
}
|
||||||
Token closing_paren = { { ctx->scanner, 1 }, Tok_Capture_End, ctx->line, ctx->column, TF_Preprocess };
|
Token closing_paren = { { ctx->scanner, 1 }, Tok_Paren_Close, ctx->line, ctx->column, TF_Preprocess };
|
||||||
array_append(_ctx->Lexer_Tokens, closing_paren);
|
array_append(_ctx->Lexer_Tokens, closing_paren);
|
||||||
move_forward();
|
move_forward();
|
||||||
}
|
}
|
||||||
@ -256,7 +256,7 @@ s32 lex_preprocessor_define( LexContext* ctx )
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( registered_macro == nullptr ) {
|
if ( registered_macro == nullptr ) {
|
||||||
register_preprocess_macro(macro);
|
register_macro(macro);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define's content handled by lex_preprocessor_directive (the original caller of this)
|
// Define's content handled by lex_preprocessor_directive (the original caller of this)
|
||||||
@ -525,52 +525,31 @@ void lex_found_token( LexContext* ctx )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PreprocessorMacro* macro = lookup_preprocess_macro( ctx->token.Text );
|
Macro* macro = lookup_macro( ctx->token.Text );
|
||||||
b32 has_args = ctx->left && (* ctx->scanner) == '(';
|
b32 has_args = ctx->left && (* ctx->scanner) == '(';
|
||||||
b32 resolved_to_macro = false;
|
b32 resolved_to_macro = false;
|
||||||
if (macro) {
|
if (macro) {
|
||||||
ctx->token.Type = macrotype_to_toktype(macro->Type);
|
ctx->token.Type = macrotype_to_toktype(macro->Type);
|
||||||
b32 is_functional = macro_is_functional(* macro);
|
b32 is_functional = macro_is_functional(* macro);
|
||||||
resolved_to_macro = has_args ? is_functional : ! is_functional;
|
resolved_to_macro = has_args ? is_functional : ! is_functional;
|
||||||
|
if ( ! resolved_to_macro && GEN_BUILD_DEBUG ) {
|
||||||
|
log_fmt("Info(%d, %d): %S identified as a macro but usage here does not resolve to one (interpreting as identifier)\n"
|
||||||
|
, ctx->token.Line
|
||||||
|
, ctx->token.Line
|
||||||
|
, macro->Name
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( resolved_to_macro )
|
if ( resolved_to_macro )
|
||||||
{
|
{
|
||||||
// TODO(Ed): When we introduce a macro AST (and expression support), we'll properly lex this section.
|
// TODO(Ed): When we introduce a macro AST (and expression support), we'll properly lex this section.
|
||||||
// Want to ignore any arguments the define may have as they can be execution expressions.
|
// Want to ignore any arguments the define may have as they can be execution expressions.
|
||||||
if ( has_args )
|
if ( has_args ) {
|
||||||
{
|
|
||||||
ctx->token.Flags |= TF_Macro_Functional;
|
ctx->token.Flags |= TF_Macro_Functional;
|
||||||
|
|
||||||
// move_forward();
|
|
||||||
// ctx->token.Text.Len++;
|
|
||||||
|
|
||||||
// s32 level = 0;
|
|
||||||
// while ( ctx->left && ((* ctx->scanner) != ')' || level > 0) )
|
|
||||||
// {
|
|
||||||
// if ( (* ctx->scanner) == '(' )
|
|
||||||
// level++;
|
|
||||||
|
|
||||||
// else if ( (* ctx->scanner) == ')' && level > 0 )
|
|
||||||
// level--;
|
|
||||||
|
|
||||||
// move_forward();
|
|
||||||
// ctx->token.Text.Len++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// move_forward();
|
|
||||||
// ctx->token.Text.Len++;
|
|
||||||
}
|
}
|
||||||
|
if ( bitfield_is_set(MacroFlags, macro->Flags, MF_Allow_As_Attribute) ) {
|
||||||
//if ( (* ctx->scanner) == '\r' && ctx->scanner[1] == '\n' )
|
ctx->token.Flags |= TF_Attribute;
|
||||||
//{
|
}
|
||||||
// move_forward();
|
|
||||||
// ctx->token..Text.Length++;
|
|
||||||
//}
|
|
||||||
//else if ( (* ctx->scanner) == '\n' )
|
|
||||||
//{
|
|
||||||
// move_forward();
|
|
||||||
// ctx->token..Text.Length++;
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -818,7 +797,7 @@ TokArray lex( Str content )
|
|||||||
{
|
{
|
||||||
Str text = { c.scanner, 1 };
|
Str text = { c.scanner, 1 };
|
||||||
c.token.Text = text;
|
c.token.Text = text;
|
||||||
c.token.Type = Tok_Capture_Start;
|
c.token.Type = Tok_Paren_Open;
|
||||||
|
|
||||||
if (c.left)
|
if (c.left)
|
||||||
move_forward();
|
move_forward();
|
||||||
@ -828,7 +807,7 @@ TokArray lex( Str content )
|
|||||||
{
|
{
|
||||||
Str text = { c.scanner, 1 };
|
Str text = { c.scanner, 1 };
|
||||||
c.token.Text = text;
|
c.token.Text = text;
|
||||||
c.token.Type = Tok_Capture_End;
|
c.token.Type = Tok_Paren_Close;
|
||||||
|
|
||||||
if (c.left)
|
if (c.left)
|
||||||
move_forward();
|
move_forward();
|
||||||
|
@ -97,7 +97,7 @@ bool lex__eat(TokArray* self, TokType type )
|
|||||||
b32 is_identifier = at_idx.Type == Tok_Identifier;
|
b32 is_identifier = at_idx.Type == Tok_Identifier;
|
||||||
if ( not_accepted )
|
if ( not_accepted )
|
||||||
{
|
{
|
||||||
PreprocessorMacro* macro = lookup_preprocess_macro(at_idx.Text);
|
Macro* macro = lookup_macro(at_idx.Text);
|
||||||
b32 accept_as_identifier = macro && bitfield_is_set(MacroFlags, macro->Flags, MF_Allow_As_Identifier );
|
b32 accept_as_identifier = macro && bitfield_is_set(MacroFlags, macro->Flags, MF_Allow_As_Identifier );
|
||||||
not_accepted = type == Tok_Identifier && accept_as_identifier ? false : true;
|
not_accepted = type == Tok_Identifier && accept_as_identifier ? false : true;
|
||||||
}
|
}
|
||||||
@ -196,7 +196,6 @@ internal CodeComment parse_comment ();
|
|||||||
internal Code parse_complicated_definition ( TokType which );
|
internal Code parse_complicated_definition ( TokType which );
|
||||||
internal CodeBody parse_class_struct_body ( TokType which, Token name );
|
internal CodeBody parse_class_struct_body ( TokType which, Token name );
|
||||||
internal Code parse_class_struct ( TokType which, bool inplace_def );
|
internal Code parse_class_struct ( TokType which, bool inplace_def );
|
||||||
internal CodeDefine parser_parse_define ();
|
|
||||||
internal Code parse_expression ();
|
internal Code parse_expression ();
|
||||||
internal Code parse_forward_or_definition ( TokType which, bool is_inplace );
|
internal Code parse_forward_or_definition ( TokType which, bool is_inplace );
|
||||||
internal CodeFn parse_function_after_name ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeTypename ret_type, Token name );
|
internal CodeFn parse_function_after_name ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeTypename ret_type, Token name );
|
||||||
@ -205,6 +204,7 @@ internal CodeBody parse_global_nspace ( CodeType which
|
|||||||
internal Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers );
|
internal Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers );
|
||||||
internal Token parse_identifier ( bool* possible_member_function );
|
internal Token parse_identifier ( bool* possible_member_function );
|
||||||
internal CodeInclude parse_include ();
|
internal CodeInclude parse_include ();
|
||||||
|
internal Code parse_macro_as_definiton ( CodeAttributes attributes, CodeSpecifiers specifiers );
|
||||||
internal CodeOperator parse_operator_after_ret_type ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeTypename ret_type );
|
internal CodeOperator parse_operator_after_ret_type ( ModuleFlag mflags, CodeAttributes attributes, CodeSpecifiers specifiers, CodeTypename ret_type );
|
||||||
internal Code parse_operator_function_or_variable( bool expects_function, CodeAttributes attributes, CodeSpecifiers specifiers );
|
internal Code parse_operator_function_or_variable( bool expects_function, CodeAttributes attributes, CodeSpecifiers specifiers );
|
||||||
internal CodePragma parse_pragma ();
|
internal CodePragma parse_pragma ();
|
||||||
@ -218,6 +218,7 @@ internal CodeVar parse_variable_declaration_list ();
|
|||||||
|
|
||||||
internal CodeClass parser_parse_class ( bool inplace_def );
|
internal CodeClass parser_parse_class ( bool inplace_def );
|
||||||
internal CodeConstructor parser_parse_constructor ( CodeSpecifiers specifiers );
|
internal CodeConstructor parser_parse_constructor ( CodeSpecifiers specifiers );
|
||||||
|
internal CodeDefine parser_parse_define ();
|
||||||
internal CodeDestructor parser_parse_destructor ( CodeSpecifiers specifiers );
|
internal CodeDestructor parser_parse_destructor ( CodeSpecifiers specifiers );
|
||||||
internal CodeEnum parser_parse_enum ( bool inplace_def );
|
internal CodeEnum parser_parse_enum ( bool inplace_def );
|
||||||
internal CodeBody parser_parse_export_body ();
|
internal CodeBody parser_parse_export_body ();
|
||||||
@ -578,7 +579,7 @@ CodeAttributes parse_attributes()
|
|||||||
s32 len = 0;
|
s32 len = 0;
|
||||||
|
|
||||||
// There can be more than one attribute. If there is flatten them to a single string.
|
// There can be more than one attribute. If there is flatten them to a single string.
|
||||||
// TODO(Ed): Support keeping an linked list of attributes similar to parameters
|
// TODO(Ed): Support chaining attributes (Use parameter linkage pattern)
|
||||||
while ( left && tok_is_attribute(currtok) )
|
while ( left && tok_is_attribute(currtok) )
|
||||||
{
|
{
|
||||||
if ( check( Tok_Attribute_Open ) )
|
if ( check( Tok_Attribute_Open ) )
|
||||||
@ -600,18 +601,18 @@ CodeAttributes parse_attributes()
|
|||||||
else if ( check( Tok_Decl_GNU_Attribute ) )
|
else if ( check( Tok_Decl_GNU_Attribute ) )
|
||||||
{
|
{
|
||||||
eat( Tok_Decl_GNU_Attribute );
|
eat( Tok_Decl_GNU_Attribute );
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
// __attribute__((
|
// __attribute__((
|
||||||
|
|
||||||
while ( left && currtok.Type != Tok_Capture_End )
|
while ( left && currtok.Type != Tok_Paren_Close )
|
||||||
{
|
{
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
// __attribute__(( <Content>
|
// __attribute__(( <Content>
|
||||||
|
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
// __attribute__(( <Content> ))
|
// __attribute__(( <Content> ))
|
||||||
|
|
||||||
len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr;
|
len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr;
|
||||||
@ -619,16 +620,16 @@ CodeAttributes parse_attributes()
|
|||||||
else if ( check( Tok_Decl_MSVC_Attribute ) )
|
else if ( check( Tok_Decl_MSVC_Attribute ) )
|
||||||
{
|
{
|
||||||
eat( Tok_Decl_MSVC_Attribute );
|
eat( Tok_Decl_MSVC_Attribute );
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
// __declspec(
|
// __declspec(
|
||||||
|
|
||||||
while ( left && currtok.Type != Tok_Capture_End )
|
while ( left && currtok.Type != Tok_Paren_Close )
|
||||||
{
|
{
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
// __declspec( <Content>
|
// __declspec( <Content>
|
||||||
|
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
// __declspec( <Content> )
|
// __declspec( <Content> )
|
||||||
|
|
||||||
len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr;
|
len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr;
|
||||||
@ -639,20 +640,20 @@ CodeAttributes parse_attributes()
|
|||||||
// <Attribute>
|
// <Attribute>
|
||||||
|
|
||||||
// If its a macro based attribute, this could be a functional macro such as Unreal's UE_DEPRECATED(...)
|
// If its a macro based attribute, this could be a functional macro such as Unreal's UE_DEPRECATED(...)
|
||||||
if ( check( Tok_Capture_Start))
|
if ( check( Tok_Paren_Open))
|
||||||
{
|
{
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
|
|
||||||
s32 level = 0;
|
s32 level = 0;
|
||||||
while (left && currtok.Type != Tok_Capture_End && level == 0)
|
while (left && currtok.Type != Tok_Paren_Close && level == 0)
|
||||||
{
|
{
|
||||||
if (currtok.Type == Tok_Capture_Start)
|
if (currtok.Type == Tok_Paren_Open)
|
||||||
++ level;
|
++ level;
|
||||||
if (currtok.Type == Tok_Capture_End)
|
if (currtok.Type == Tok_Paren_Close)
|
||||||
--level;
|
--level;
|
||||||
eat(currtok.Type);
|
eat(currtok.Type);
|
||||||
}
|
}
|
||||||
eat(Tok_Capture_End);
|
eat(Tok_Paren_Close);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr;
|
len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )start.Text.Ptr;
|
||||||
@ -986,7 +987,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
|
|||||||
// <Attributes>
|
// <Attributes>
|
||||||
}
|
}
|
||||||
//! Fallthrough intended
|
//! Fallthrough intended
|
||||||
GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIERS_CASES:
|
GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIER_CASES:
|
||||||
{
|
{
|
||||||
Specifier specs_found[16] = { Spec_NumSpecifiers };
|
Specifier specs_found[16] = { Spec_NumSpecifiers };
|
||||||
s32 NumSpecifiers = 0;
|
s32 NumSpecifiers = 0;
|
||||||
@ -999,7 +1000,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
|
|||||||
|
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIERS_CASES:
|
GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIER_CASES:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Spec_Consteval:
|
case Spec_Consteval:
|
||||||
@ -1027,7 +1028,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
|
|||||||
|
|
||||||
if ( NumSpecifiers )
|
if ( NumSpecifiers )
|
||||||
{
|
{
|
||||||
specifiers = def_specifiers( NumSpecifiers, specs_found );
|
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
}
|
}
|
||||||
// <Attributes> <Specifiers>
|
// <Attributes> <Specifiers>
|
||||||
|
|
||||||
@ -1077,7 +1078,7 @@ CodeBody parse_class_struct_body( TokType which, Token name )
|
|||||||
case Tok_Type_int:
|
case Tok_Type_int:
|
||||||
case Tok_Type_double:
|
case Tok_Type_double:
|
||||||
{
|
{
|
||||||
if ( nexttok.Type == Tok_Capture_Start && name.Text.Len && currtok.Type == Tok_Identifier )
|
if ( nexttok.Type == Tok_Paren_Open && name.Text.Len && currtok.Type == Tok_Identifier )
|
||||||
{
|
{
|
||||||
if ( c_str_compare_len( name.Text.Ptr, currtok.Text.Ptr, name.Text.Len ) == 0 )
|
if ( c_str_compare_len( name.Text.Ptr, currtok.Text.Ptr, name.Text.Len ) == 0 )
|
||||||
{
|
{
|
||||||
@ -1182,7 +1183,7 @@ Code parse_complicated_definition( TokType which )
|
|||||||
spec = tokens.Arr[spec_idx];
|
spec = tokens.Arr[spec_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( tokens.Arr[spec_idx].Type == Tok_Capture_End )
|
if ( tokens.Arr[spec_idx].Type == Tok_Paren_Close )
|
||||||
{
|
{
|
||||||
// Forward declaration with trailing specifiers for a procedure
|
// Forward declaration with trailing specifiers for a procedure
|
||||||
tok = tokens.Arr[spec_idx];
|
tok = tokens.Arr[spec_idx];
|
||||||
@ -1293,89 +1294,6 @@ Code parse_complicated_definition( TokType which )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal inline
|
|
||||||
CodeDefine parser_parse_define()
|
|
||||||
{
|
|
||||||
push_scope();
|
|
||||||
if ( check(Tok_Preprocess_Hash)) {
|
|
||||||
// If parse_define is called by the user the hash reach here.
|
|
||||||
eat(Tok_Preprocess_Hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
eat( Tok_Preprocess_Define );
|
|
||||||
// #define
|
|
||||||
|
|
||||||
CodeDefine
|
|
||||||
define = (CodeDefine) make_code();
|
|
||||||
define->Type = CT_Preprocess_Define;
|
|
||||||
if ( ! check( Tok_Identifier ) ) {
|
|
||||||
log_failure( "Error, expected identifier after #define\n%s", parser_to_strbuilder(_ctx->parser) );
|
|
||||||
parser_pop(& _ctx->parser);
|
|
||||||
return InvalidCode;
|
|
||||||
}
|
|
||||||
_ctx->parser.Scope->Name = currtok.Text;
|
|
||||||
define->Name = cache_str( tok_to_str(currtok) );
|
|
||||||
eat( Tok_Identifier );
|
|
||||||
// #define <Name>
|
|
||||||
|
|
||||||
PreprocessorMacro* macro = lookup_preprocess_macro(define->Name);
|
|
||||||
if (macro_is_functional(* macro)) {
|
|
||||||
eat( Tok_Capture_Start );
|
|
||||||
// #define <Name> (
|
|
||||||
CodeDefineParams params;
|
|
||||||
if ( left && currtok.Type != Tok_Capture_End ) {
|
|
||||||
params = (CodeDefineParams) make_code();
|
|
||||||
params->Type = CT_Parameters_Define;
|
|
||||||
params->Name = currtok.Text;
|
|
||||||
params->NumEntries ++;
|
|
||||||
|
|
||||||
define->Params = params;
|
|
||||||
eat( Tok_Preprocess_Define_Param );
|
|
||||||
// #define <Name> ( <param>
|
|
||||||
}
|
|
||||||
|
|
||||||
while( left && currtok.Type != Tok_Capture_End ) {
|
|
||||||
eat( Tok_Comma );
|
|
||||||
// #define <Name> ( <param>,
|
|
||||||
|
|
||||||
CodeDefineParams next_param = (CodeDefineParams) make_code();
|
|
||||||
next_param->Type = CT_Parameters_Define;
|
|
||||||
next_param->Name = currtok.Text;
|
|
||||||
define_params_append(params, next_param);
|
|
||||||
|
|
||||||
// #define <Name> ( <param>, <next_param> ...
|
|
||||||
eat( Tok_Preprocess_Define_Param );
|
|
||||||
}
|
|
||||||
|
|
||||||
eat( Tok_Capture_End );
|
|
||||||
// #define <Name> ( <params> )
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! check( Tok_Preprocess_Content ))
|
|
||||||
{
|
|
||||||
log_failure( "Error, expected content after #define %s\n%s", define->Name, parser_to_strbuilder(_ctx->parser) );
|
|
||||||
parser_pop(& _ctx->parser);
|
|
||||||
return InvalidCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( currtok.Text.Len == 0 )
|
|
||||||
{
|
|
||||||
define->Body = untyped_str( txt("\n") );
|
|
||||||
eat( Tok_Preprocess_Content );
|
|
||||||
// #define <Name> ( <params> ) <Content>
|
|
||||||
|
|
||||||
parser_pop(& _ctx->parser);
|
|
||||||
return define;
|
|
||||||
}
|
|
||||||
|
|
||||||
define->Body = untyped_str( strbuilder_to_str( parser_strip_formatting( tok_to_str(currtok), parser_strip_formatting_dont_preserve_newlines )) );
|
|
||||||
eat( Tok_Preprocess_Content );
|
|
||||||
// #define <Name> ( <params> ) <Content>
|
|
||||||
|
|
||||||
parser_pop(& _ctx->parser);
|
|
||||||
return define;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal inline
|
internal inline
|
||||||
Code parse_assignment_expression()
|
Code parse_assignment_expression()
|
||||||
{
|
{
|
||||||
@ -1400,9 +1318,9 @@ Code parse_assignment_expression()
|
|||||||
level++;
|
level++;
|
||||||
if (currtok.Type == Tok_BraceCurly_Close )
|
if (currtok.Type == Tok_BraceCurly_Close )
|
||||||
level--;
|
level--;
|
||||||
if (currtok.Type == Tok_Capture_Start)
|
if (currtok.Type == Tok_Paren_Open)
|
||||||
level++;
|
level++;
|
||||||
else if (currtok.Type == Tok_Capture_End)
|
else if (currtok.Type == Tok_Paren_Close)
|
||||||
level--;
|
level--;
|
||||||
|
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
@ -1835,7 +1753,7 @@ CodeBody parse_global_nspace( CodeType which )
|
|||||||
|
|
||||||
if ( NumSpecifiers )
|
if ( NumSpecifiers )
|
||||||
{
|
{
|
||||||
specifiers = def_specifiers( NumSpecifiers, specs_found );
|
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
}
|
}
|
||||||
// <Attributes> <Specifiers>
|
// <Attributes> <Specifiers>
|
||||||
}
|
}
|
||||||
@ -1955,7 +1873,7 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers )
|
|||||||
if (nav.Type == Tok_Operator && nav.Text.Ptr[1] == '>')
|
if (nav.Type == Tok_Operator && nav.Text.Ptr[1] == '>')
|
||||||
-- template_level;
|
-- template_level;
|
||||||
|
|
||||||
if ( nav.Type == Tok_Capture_Start)
|
if ( nav.Type == Tok_Paren_Open)
|
||||||
{
|
{
|
||||||
if (template_level != 0 )
|
if (template_level != 0 )
|
||||||
++ capture_level;
|
++ capture_level;
|
||||||
@ -1963,12 +1881,12 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( template_level != 0 && nav.Type == Tok_Capture_End)
|
if ( template_level != 0 && nav.Type == Tok_Paren_Close)
|
||||||
-- capture_level;
|
-- capture_level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( nav.Type == Tok_Capture_Start )
|
if ( nav.Type == Tok_Paren_Open )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2014,10 +1932,10 @@ Code parse_global_nspace_constructor_destructor( CodeSpecifiers specifiers )
|
|||||||
if (tok_left.Type == Tok_Operator && tok_left.Text.Ptr[1] == '>')
|
if (tok_left.Type == Tok_Operator && tok_left.Text.Ptr[1] == '>')
|
||||||
-- template_level;
|
-- template_level;
|
||||||
|
|
||||||
if ( template_level != 0 && tok_left.Type == Tok_Capture_Start)
|
if ( template_level != 0 && tok_left.Type == Tok_Paren_Open)
|
||||||
++ capture_level;
|
++ capture_level;
|
||||||
|
|
||||||
if ( template_level != 0 && tok_left.Type == Tok_Capture_End)
|
if ( template_level != 0 && tok_left.Type == Tok_Paren_Close)
|
||||||
-- capture_level;
|
-- capture_level;
|
||||||
|
|
||||||
if ( capture_level == 0 && template_level == 0 && tok_left.Type == Tok_Identifier )
|
if ( capture_level == 0 && template_level == 0 && tok_left.Type == Tok_Identifier )
|
||||||
@ -2517,6 +2435,12 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
|
|||||||
|
|
||||||
Code result = InvalidCode;
|
Code result = InvalidCode;
|
||||||
|
|
||||||
|
Code macro_stmt = parse_macro_as_definiton(attributes, specifiers);
|
||||||
|
if (macro_stmt) {
|
||||||
|
parser_pop(& _ctx->parser);
|
||||||
|
return macro_stmt;
|
||||||
|
}
|
||||||
|
|
||||||
CodeTypename type = parser_parse_type( parser_not_from_template, nullptr );
|
CodeTypename type = parser_parse_type( parser_not_from_template, nullptr );
|
||||||
// <Attributes> <Specifiers> <ReturnType/ValueType>
|
// <Attributes> <Specifiers> <ReturnType/ValueType>
|
||||||
|
|
||||||
@ -2559,14 +2483,47 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
|
|||||||
Token name = parse_identifier(nullptr);
|
Token name = parse_identifier(nullptr);
|
||||||
_ctx->parser.Scope->Name = name.Text;
|
_ctx->parser.Scope->Name = name.Text;
|
||||||
|
|
||||||
bool detected_capture = check( Tok_Capture_Start );
|
bool detected_capture = check( Tok_Paren_Open );
|
||||||
|
|
||||||
// Check three tokens ahead to make sure that were not dealing with a constructor initialization...
|
// Check three tokens ahead to make sure that were not dealing with a constructor initialization...
|
||||||
// ( 350.0f , <--- Could be the scenario
|
// ( 350.0f , <--- Could be the scenario
|
||||||
// Example : <Capture_Start> <Value> <Comma>
|
// Example : <Capture_Start> <Value> <Comma>
|
||||||
// idx +1 +2
|
// idx +1 +2
|
||||||
bool detected_comma = _ctx->parser.Tokens.Arr[ _ctx->parser.Tokens.Idx + 2 ].Type == Tok_Comma;
|
bool detected_comma = _ctx->parser.Tokens.Arr[ _ctx->parser.Tokens.Idx + 2 ].Type == Tok_Comma;
|
||||||
if ( detected_capture && ! detected_comma )
|
|
||||||
|
b32 detected_non_varadic_unpaired_param = detected_comma && nexttok.Type != Tok_Varadic_Argument;
|
||||||
|
if (! detected_non_varadic_unpaired_param && nexttok.Type == Tok_Preprocess_Macro_Expr) for( s32 break_scope = 0; break_scope == 0; ++ break_scope)
|
||||||
|
{
|
||||||
|
Macro* macro = lookup_macro( nexttok.Text );
|
||||||
|
if (macro == nullptr || ! macro_is_functional(* macro))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ( <Macro_Expr> (
|
||||||
|
// Idx +1 +2
|
||||||
|
s32 idx = _ctx->parser.Tokens.Idx + 1;
|
||||||
|
s32 level = 0;
|
||||||
|
|
||||||
|
// Find end of the token expression
|
||||||
|
for ( ; idx < array_num(_ctx->parser.Tokens.Arr); idx++ )
|
||||||
|
{
|
||||||
|
Token tok = _ctx->parser.Tokens.Arr[ idx ];
|
||||||
|
|
||||||
|
if ( tok.Type == Tok_Paren_Open )
|
||||||
|
level++;
|
||||||
|
else if ( tok.Type == Tok_Paren_Close && level > 0 )
|
||||||
|
level--;
|
||||||
|
if (level == 0 && tok.Type == Tok_Paren_Close)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++ idx; // Will incremnt to possible comma position
|
||||||
|
|
||||||
|
if ( _ctx->parser.Tokens.Arr[ idx ].Type != Tok_Comma )
|
||||||
|
break;
|
||||||
|
|
||||||
|
detected_non_varadic_unpaired_param = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( detected_capture && ! detected_non_varadic_unpaired_param )
|
||||||
{
|
{
|
||||||
// Dealing with a function
|
// Dealing with a function
|
||||||
result = cast(Code, parse_function_after_name( ModuleFlag_None, attributes, specifiers, type, name ));
|
result = cast(Code, parse_function_after_name( ModuleFlag_None, attributes, specifiers, type, name ));
|
||||||
@ -2589,6 +2546,36 @@ Code parse_operator_function_or_variable( bool expects_function, CodeAttributes
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
Code parse_macro_as_definiton( CodeAttributes attributes, CodeSpecifiers specifiers )
|
||||||
|
{
|
||||||
|
push_scope();
|
||||||
|
|
||||||
|
if (currtok.Type != Tok_Preprocess_Macro_Stmt ) {
|
||||||
|
parser_pop(& _ctx->parser);
|
||||||
|
return NullCode;
|
||||||
|
}
|
||||||
|
Macro* macro = lookup_macro(currtok.Text);
|
||||||
|
b32 can_resolve_to_definition = macro && bitfield_is_set(MacroFlags, macro->Flags, MF_Allow_As_Definition);
|
||||||
|
if ( ! can_resolve_to_definition) {
|
||||||
|
parser_pop(& _ctx->parser);
|
||||||
|
return NullCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(Ed): When AST_Macro is made, have it support attributs and specifiers for when its behaving as a declaration/definition.
|
||||||
|
Code code = parse_simple_preprocess( Tok_Preprocess_Macro_Stmt );
|
||||||
|
|
||||||
|
// Attributes and sepcifiers will be collapsed into the macro's serialization.
|
||||||
|
StrBuilder resolved_definition = strbuilder_fmt_buf(_ctx->Allocator_Temp, "%S %S %S"
|
||||||
|
, attributes ? strbuilder_to_str( attributes_to_strbuilder(attributes)) : txt("")
|
||||||
|
, specifiers ? strbuilder_to_str( specifiers_to_strbuilder(specifiers)) : txt("")
|
||||||
|
, code->Content
|
||||||
|
);
|
||||||
|
Code result = untyped_str( strbuilder_to_str(resolved_definition) );
|
||||||
|
parser_pop(& _ctx->parser);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
CodePragma parse_pragma()
|
CodePragma parse_pragma()
|
||||||
{
|
{
|
||||||
@ -2622,7 +2609,7 @@ CodeParams parse_params( bool use_template_capture )
|
|||||||
push_scope();
|
push_scope();
|
||||||
|
|
||||||
if ( ! use_template_capture ) {
|
if ( ! use_template_capture ) {
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
// (
|
// (
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2631,9 +2618,9 @@ CodeParams parse_params( bool use_template_capture )
|
|||||||
// <
|
// <
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! use_template_capture && check( Tok_Capture_End ) )
|
if ( ! use_template_capture && check( Tok_Paren_Close ) )
|
||||||
{
|
{
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
// )
|
// )
|
||||||
parser_pop(& _ctx->parser);
|
parser_pop(& _ctx->parser);
|
||||||
return NullCode;
|
return NullCode;
|
||||||
@ -2664,7 +2651,7 @@ CodeParams parse_params( bool use_template_capture )
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define CheckEndParams() \
|
#define CheckEndParams() \
|
||||||
(use_template_capture ? (currtok.Text.Ptr[ 0 ] != '>') : (currtok.Type != Tok_Capture_End))
|
(use_template_capture ? (currtok.Text.Ptr[ 0 ] != '>') : (currtok.Type != Tok_Paren_Close))
|
||||||
|
|
||||||
// TODO(Ed): Use expression macros or this? macro as attribute?
|
// TODO(Ed): Use expression macros or this? macro as attribute?
|
||||||
// Ex: Unreal has this type of macro: vvvvvvvvv
|
// Ex: Unreal has this type of macro: vvvvvvvvv
|
||||||
@ -2732,10 +2719,10 @@ CodeParams parse_params( bool use_template_capture )
|
|||||||
if (currtok.Type == Tok_Operator && currtok.Text.Ptr[1] == '>')
|
if (currtok.Type == Tok_Operator && currtok.Text.Ptr[1] == '>')
|
||||||
-- template_level;
|
-- template_level;
|
||||||
|
|
||||||
if ( currtok.Type == Tok_Capture_Start)
|
if ( currtok.Type == Tok_Paren_Open)
|
||||||
++ capture_level;
|
++ capture_level;
|
||||||
|
|
||||||
if ( currtok.Type == Tok_Capture_End)
|
if ( currtok.Type == Tok_Paren_Close)
|
||||||
-- capture_level;
|
-- capture_level;
|
||||||
|
|
||||||
value_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )value_tok.Text.Ptr;
|
value_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )value_tok.Text.Ptr;
|
||||||
@ -2846,10 +2833,10 @@ CodeParams parse_params( bool use_template_capture )
|
|||||||
if (currtok.Type == Tok_Operator && currtok.Text.Ptr[1] == '>')
|
if (currtok.Type == Tok_Operator && currtok.Text.Ptr[1] == '>')
|
||||||
-- template_level;
|
-- template_level;
|
||||||
|
|
||||||
if ( currtok.Type == Tok_Capture_Start)
|
if ( currtok.Type == Tok_Paren_Open)
|
||||||
++ capture_level;
|
++ capture_level;
|
||||||
|
|
||||||
if ( currtok.Type == Tok_Capture_End)
|
if ( currtok.Type == Tok_Paren_Close)
|
||||||
-- capture_level;
|
-- capture_level;
|
||||||
|
|
||||||
value_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )value_tok.Text.Ptr;
|
value_tok.Text.Len = ( ( sptr )currtok.Text.Ptr + currtok.Text.Len ) - ( sptr )value_tok.Text.Ptr;
|
||||||
@ -2881,7 +2868,7 @@ CodeParams parse_params( bool use_template_capture )
|
|||||||
|
|
||||||
if ( ! use_template_capture )
|
if ( ! use_template_capture )
|
||||||
{
|
{
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
// ( <Macro> <ValueType> <Name> <PostNameMacro> = <Expression>, <Macro> <ValueType> <Name> <PostNameMacro> = <Expression>, .. )
|
// ( <Macro> <ValueType> <Name> <PostNameMacro> = <Expression>, <Macro> <ValueType> <Name> <PostNameMacro> = <Expression>, .. )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2945,7 +2932,7 @@ Code parse_simple_preprocess( TokType which )
|
|||||||
eat( which );
|
eat( which );
|
||||||
// <Macro>
|
// <Macro>
|
||||||
|
|
||||||
PreprocessorMacro* macro = lookup_preprocess_macro( full_macro.Text );
|
Macro* macro = lookup_macro( full_macro.Text );
|
||||||
if ( which != Tok_Preprocess_Unsupported && macro == nullptr ) {
|
if ( which != Tok_Preprocess_Unsupported && macro == nullptr ) {
|
||||||
log_failure("Expected the macro %S to be registered\n%S", full_macro, parser_to_strbuilder(_ctx->parser));
|
log_failure("Expected the macro %S to be registered\n%S", full_macro, parser_to_strbuilder(_ctx->parser));
|
||||||
return NullCode;
|
return NullCode;
|
||||||
@ -2954,20 +2941,20 @@ Code parse_simple_preprocess( TokType which )
|
|||||||
// TODO(Ed) : Parse this properly later (expression and statement support)
|
// TODO(Ed) : Parse this properly later (expression and statement support)
|
||||||
if ( macro && macro_is_functional(* macro) )
|
if ( macro && macro_is_functional(* macro) )
|
||||||
{
|
{
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
|
|
||||||
s32 level = 0;
|
s32 level = 0;
|
||||||
while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) )
|
while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) )
|
||||||
{
|
{
|
||||||
if ( currtok.Type == Tok_Capture_Start )
|
if ( currtok.Type == Tok_Paren_Open )
|
||||||
level++;
|
level++;
|
||||||
|
|
||||||
else if ( currtok.Type == Tok_Capture_End && level > 0 )
|
else if ( currtok.Type == Tok_Paren_Close && level > 0 )
|
||||||
level--;
|
level--;
|
||||||
|
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
// <Macro> ( <params> )
|
// <Macro> ( <params> )
|
||||||
|
|
||||||
full_macro.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)full_macro.Text.Ptr;
|
full_macro.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)full_macro.Text.Ptr;
|
||||||
@ -3048,7 +3035,7 @@ Code parse_simple_preprocess( TokType which )
|
|||||||
|| str_contains(calling_proc, txt("parse_class_struct_body"))
|
|| str_contains(calling_proc, txt("parse_class_struct_body"))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (peektok.Type == Tok_Statement_End)
|
if (left && peektok.Type == Tok_Statement_End)
|
||||||
{
|
{
|
||||||
Token stmt_end = currtok;
|
Token stmt_end = currtok;
|
||||||
eat( Tok_Statement_End );
|
eat( Tok_Statement_End );
|
||||||
@ -3080,21 +3067,21 @@ Code parse_static_assert()
|
|||||||
_ctx->parser.Scope->Name = content.Text;
|
_ctx->parser.Scope->Name = content.Text;
|
||||||
|
|
||||||
eat( Tok_StaticAssert );
|
eat( Tok_StaticAssert );
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
// static_assert(
|
// static_assert(
|
||||||
|
|
||||||
// TODO(Ed) : Parse this properly.
|
// TODO(Ed) : Parse this properly.
|
||||||
s32 level = 0;
|
s32 level = 0;
|
||||||
while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) )
|
while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) )
|
||||||
{
|
{
|
||||||
if ( currtok.Type == Tok_Capture_Start )
|
if ( currtok.Type == Tok_Paren_Open )
|
||||||
level++;
|
level++;
|
||||||
else if ( currtok.Type == Tok_Capture_End )
|
else if ( currtok.Type == Tok_Paren_Close )
|
||||||
level--;
|
level--;
|
||||||
|
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
eat( Tok_Statement_End );
|
eat( Tok_Statement_End );
|
||||||
// static_assert( <Content> );
|
// static_assert( <Content> );
|
||||||
|
|
||||||
@ -3196,9 +3183,9 @@ CodeVar parse_variable_after_name(
|
|||||||
// <Attributes> <Specifiers> <ValueType> <Name> = { <Expression> }
|
// <Attributes> <Specifiers> <ValueType> <Name> = { <Expression> }
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( currtok.Type == Tok_Capture_Start )
|
if ( currtok.Type == Tok_Paren_Open )
|
||||||
{
|
{
|
||||||
eat( Tok_Capture_Start);
|
eat( Tok_Paren_Open);
|
||||||
// <Attributes> <Specifiers> <ValueType> <Name> (
|
// <Attributes> <Specifiers> <ValueType> <Name> (
|
||||||
|
|
||||||
Token expr_token = currtok;
|
Token expr_token = currtok;
|
||||||
@ -3206,12 +3193,12 @@ CodeVar parse_variable_after_name(
|
|||||||
using_constructor_initializer = true;
|
using_constructor_initializer = true;
|
||||||
|
|
||||||
s32 level = 0;
|
s32 level = 0;
|
||||||
while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) )
|
while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) )
|
||||||
{
|
{
|
||||||
if ( currtok.Type == Tok_Capture_Start )
|
if ( currtok.Type == Tok_Paren_Open )
|
||||||
level++;
|
level++;
|
||||||
|
|
||||||
else if ( currtok.Type == Tok_Capture_End && level > 0 )
|
else if ( currtok.Type == Tok_Paren_Close && level > 0 )
|
||||||
level--;
|
level--;
|
||||||
|
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
@ -3219,7 +3206,7 @@ CodeVar parse_variable_after_name(
|
|||||||
|
|
||||||
expr_token.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_token.Text.Ptr;
|
expr_token.Text.Len = ( (sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (sptr)expr_token.Text.Ptr;
|
||||||
expr = untyped_str( tok_to_str(expr_token) );
|
expr = untyped_str( tok_to_str(expr_token) );
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
// <Attributes> <Specifiers> <ValueType> <Name> ( <Expression> )
|
// <Attributes> <Specifiers> <ValueType> <Name> ( <Expression> )
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3419,9 +3406,9 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers )
|
|||||||
s32 level = 0;
|
s32 level = 0;
|
||||||
while ( left && ( currtok.Type != Tok_BraceCurly_Open || level > 0 ) )
|
while ( left && ( currtok.Type != Tok_BraceCurly_Open || level > 0 ) )
|
||||||
{
|
{
|
||||||
if (currtok.Type == Tok_Capture_Start)
|
if (currtok.Type == Tok_Paren_Open)
|
||||||
level++;
|
level++;
|
||||||
else if ( currtok.Type == Tok_Capture_End )
|
else if ( currtok.Type == Tok_Paren_Close )
|
||||||
level--;
|
level--;
|
||||||
|
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
@ -3484,6 +3471,93 @@ CodeConstructor parser_parse_constructor( CodeSpecifiers specifiers )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal inline
|
||||||
|
CodeDefine parser_parse_define()
|
||||||
|
{
|
||||||
|
push_scope();
|
||||||
|
if ( check(Tok_Preprocess_Hash)) {
|
||||||
|
// If parse_define is called by the user the hash reach here.
|
||||||
|
eat(Tok_Preprocess_Hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
eat( Tok_Preprocess_Define );
|
||||||
|
// #define
|
||||||
|
|
||||||
|
CodeDefine
|
||||||
|
define = (CodeDefine) make_code();
|
||||||
|
define->Type = CT_Preprocess_Define;
|
||||||
|
if ( ! check( Tok_Identifier ) ) {
|
||||||
|
log_failure( "Error, expected identifier after #define\n%s", parser_to_strbuilder(_ctx->parser) );
|
||||||
|
parser_pop(& _ctx->parser);
|
||||||
|
return InvalidCode;
|
||||||
|
}
|
||||||
|
_ctx->parser.Scope->Name = currtok.Text;
|
||||||
|
define->Name = cache_str( tok_to_str(currtok) );
|
||||||
|
eat( Tok_Identifier );
|
||||||
|
// #define <Name>
|
||||||
|
|
||||||
|
Macro* macro = lookup_macro(define->Name);
|
||||||
|
if (macro_is_functional(* macro)) {
|
||||||
|
eat( Tok_Paren_Open );
|
||||||
|
// #define <Name> (
|
||||||
|
|
||||||
|
// We provide the define params even if empty to make sure '()' are serialized.
|
||||||
|
CodeDefineParams
|
||||||
|
params = (CodeDefineParams) make_code();
|
||||||
|
params->Type = CT_Parameters_Define;
|
||||||
|
|
||||||
|
if ( left && currtok.Type != Tok_Paren_Close ) {
|
||||||
|
params->Name = currtok.Text;
|
||||||
|
params->NumEntries ++;
|
||||||
|
|
||||||
|
eat( Tok_Preprocess_Define_Param );
|
||||||
|
// #define <Name> ( <param>
|
||||||
|
}
|
||||||
|
|
||||||
|
while( left && currtok.Type != Tok_Paren_Close ) {
|
||||||
|
eat( Tok_Comma );
|
||||||
|
// #define <Name> ( <param>,
|
||||||
|
|
||||||
|
CodeDefineParams next_param = (CodeDefineParams) make_code();
|
||||||
|
next_param->Type = CT_Parameters_Define;
|
||||||
|
next_param->Name = currtok.Text;
|
||||||
|
define_params_append(params, next_param);
|
||||||
|
|
||||||
|
// #define <Name> ( <param>, <next_param> ...
|
||||||
|
eat( Tok_Preprocess_Define_Param );
|
||||||
|
}
|
||||||
|
|
||||||
|
eat( Tok_Paren_Close );
|
||||||
|
// #define <Name> ( <params> )
|
||||||
|
|
||||||
|
define->Params = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! check( Tok_Preprocess_Content ))
|
||||||
|
{
|
||||||
|
log_failure( "Error, expected content after #define %s\n%s", define->Name, parser_to_strbuilder(_ctx->parser) );
|
||||||
|
parser_pop(& _ctx->parser);
|
||||||
|
return InvalidCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( currtok.Text.Len == 0 )
|
||||||
|
{
|
||||||
|
define->Body = untyped_str( txt("\n") );
|
||||||
|
eat( Tok_Preprocess_Content );
|
||||||
|
// #define <Name> ( <params> ) <Content>
|
||||||
|
|
||||||
|
parser_pop(& _ctx->parser);
|
||||||
|
return define;
|
||||||
|
}
|
||||||
|
|
||||||
|
define->Body = untyped_str( strbuilder_to_str( parser_strip_formatting( tok_to_str(currtok), parser_strip_formatting_dont_preserve_newlines )) );
|
||||||
|
eat( Tok_Preprocess_Content );
|
||||||
|
// #define <Name> ( <params> ) <Content>
|
||||||
|
|
||||||
|
parser_pop(& _ctx->parser);
|
||||||
|
return define;
|
||||||
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers )
|
CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers )
|
||||||
{
|
{
|
||||||
@ -3521,8 +3595,8 @@ CodeDestructor parser_parse_destructor( CodeSpecifiers specifiers )
|
|||||||
CodeComment inline_cmt = NullCode;
|
CodeComment inline_cmt = NullCode;
|
||||||
// <Virtual Specifier> ~<Name>
|
// <Virtual Specifier> ~<Name>
|
||||||
|
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
// <Virtual Specifier> ~<Name>()
|
// <Virtual Specifier> ~<Name>()
|
||||||
|
|
||||||
bool pure_virtual = false;
|
bool pure_virtual = false;
|
||||||
@ -3610,9 +3684,6 @@ CodeEnum parser_parse_enum( bool inplace_def )
|
|||||||
Code array_expr = { nullptr };
|
Code array_expr = { nullptr };
|
||||||
CodeTypename type = { nullptr };
|
CodeTypename type = { nullptr };
|
||||||
|
|
||||||
char entries_code[ kilobytes(128) ] = { 0 };
|
|
||||||
s32 entries_length = 0;
|
|
||||||
|
|
||||||
bool is_enum_class = false;
|
bool is_enum_class = false;
|
||||||
|
|
||||||
eat( Tok_Decl_Enum );
|
eat( Tok_Decl_Enum );
|
||||||
@ -3757,8 +3828,11 @@ CodeEnum parser_parse_enum( bool inplace_def )
|
|||||||
|
|
||||||
// Unreal UMETA macro support
|
// Unreal UMETA macro support
|
||||||
if ( currtok.Type == Tok_Preprocess_Macro_Expr ) {
|
if ( currtok.Type == Tok_Preprocess_Macro_Expr ) {
|
||||||
eat( Tok_Preprocess_Macro_Expr );
|
Code macro = parse_simple_preprocess( Tok_Preprocess_Macro_Expr );
|
||||||
// <Name> = <Expression> <Macro>
|
// <Name> = <Expression> <Macro>
|
||||||
|
|
||||||
|
// We're intentially ignoring this code as its going to be serialized as an untyped string with the rest of the enum "entry".
|
||||||
|
// TODO(Ed): We need a CodeEnumEntry, AST_EnumEntry types
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( currtok.Type == Tok_Comma )
|
if ( currtok.Type == Tok_Comma )
|
||||||
@ -3916,7 +3990,7 @@ CodeFriend parser_parse_friend()
|
|||||||
|
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
GEN_PARSER_FRIEND_ALLOWED_SPECIFIERS_CASES:
|
GEN_PARSER_FRIEND_ALLOWED_SPECIFIER_CASES:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default :
|
default :
|
||||||
@ -3935,7 +4009,7 @@ CodeFriend parser_parse_friend()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( NumSpecifiers ) {
|
if ( NumSpecifiers ) {
|
||||||
specifiers = def_specifiers( NumSpecifiers, specs_found );
|
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
}
|
}
|
||||||
// <friend> <specifiers>
|
// <friend> <specifiers>
|
||||||
}
|
}
|
||||||
@ -4034,7 +4108,7 @@ CodeFn parser_parse_function()
|
|||||||
|
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
GEN_PARSER_FUNCTION_ALLOWED_SPECIFIERS_CASES:
|
GEN_PARSER_FUNCTION_ALLOWED_SPECIFIER_CASES:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -4052,7 +4126,7 @@ CodeFn parser_parse_function()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( NumSpecifiers ) {
|
if ( NumSpecifiers ) {
|
||||||
specifiers = def_specifiers( NumSpecifiers, specs_found );
|
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
}
|
}
|
||||||
// <export> <Attributes> <Specifiers>
|
// <export> <Attributes> <Specifiers>
|
||||||
|
|
||||||
@ -4135,7 +4209,7 @@ CodeOperator parser_parse_operator()
|
|||||||
|
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
GEN_PARSER_OPERATOR_ALLOWED_SPECIFIERS_CASES:
|
GEN_PARSER_OPERATOR_ALLOWED_SPECIFIER_CASES:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -4153,7 +4227,7 @@ CodeOperator parser_parse_operator()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( NumSpecifiers ) {
|
if ( NumSpecifiers ) {
|
||||||
specifiers = def_specifiers( NumSpecifiers, specs_found );
|
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
}
|
}
|
||||||
// <export> <Attributes> <Specifiers>
|
// <export> <Attributes> <Specifiers>
|
||||||
|
|
||||||
@ -4202,8 +4276,8 @@ CodeOpCast parser_parse_operator_cast( CodeSpecifiers specifiers )
|
|||||||
Token scope_name_tok = { scope_name, Tok_Identifier, 0, 0, TF_Null };
|
Token scope_name_tok = { scope_name, Tok_Identifier, 0, 0, TF_Null };
|
||||||
_ctx->parser.Scope->Name = scope_name_tok.Text;
|
_ctx->parser.Scope->Name = scope_name_tok.Text;
|
||||||
|
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
// <Specifiers> <Qualifier> :: ... operator <UnderlyingType>()
|
// <Specifiers> <Qualifier> :: ... operator <UnderlyingType>()
|
||||||
|
|
||||||
// TODO(Ed) : operator cast can have const, volatile, l-value, r-value noexecept qualifying specifiers.
|
// TODO(Ed) : operator cast can have const, volatile, l-value, r-value noexecept qualifying specifiers.
|
||||||
@ -4368,7 +4442,7 @@ CodeTemplate parser_parse_template()
|
|||||||
|
|
||||||
switch ( spec )
|
switch ( spec )
|
||||||
{
|
{
|
||||||
GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIERS_CASES:
|
GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIER_CASES:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Spec_Consteval :
|
case Spec_Consteval :
|
||||||
@ -4391,7 +4465,7 @@ CodeTemplate parser_parse_template()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( NumSpecifiers ) {
|
if ( NumSpecifiers ) {
|
||||||
specifiers = def_specifiers( NumSpecifiers, specs_found );
|
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
}
|
}
|
||||||
// <export> template< <Parameters> > <Attributes> <Specifiers>
|
// <export> template< <Parameters> > <Attributes> <Specifiers>
|
||||||
}
|
}
|
||||||
@ -4554,18 +4628,18 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
eat( Tok_DeclType );
|
eat( Tok_DeclType );
|
||||||
// <Attributes> <Specifiers> decltype
|
// <Attributes> <Specifiers> decltype
|
||||||
|
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
while ( left && currtok.Type != Tok_Capture_End )
|
while ( left && currtok.Type != Tok_Paren_Close )
|
||||||
{
|
{
|
||||||
if ( currtok.Type == Tok_Capture_Start )
|
if ( currtok.Type == Tok_Paren_Open )
|
||||||
level++;
|
level++;
|
||||||
|
|
||||||
if ( currtok.Type == Tok_Capture_End )
|
if ( currtok.Type == Tok_Paren_Close )
|
||||||
level--;
|
level--;
|
||||||
|
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
|
|
||||||
name.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)name.Text;
|
name.Length = ( (sptr)currtok.Text + currtok.Length ) - (sptr)name.Text;
|
||||||
_ctx->parser.Scope->Name = name;
|
_ctx->parser.Scope->Name = name;
|
||||||
@ -4607,11 +4681,12 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO(Ed): This needs updating
|
|
||||||
else if ( currtok.Type == Tok_Preprocess_Macro_Typename ) {
|
else if ( currtok.Type == Tok_Preprocess_Macro_Typename ) {
|
||||||
// Typename is a macro
|
// Typename is a macro
|
||||||
name = currtok;
|
// name = currtok;
|
||||||
eat(Tok_Preprocess_Macro_Typename);
|
// eat(Tok_Preprocess_Macro_Typename);
|
||||||
|
Code macro = parse_simple_preprocess(Tok_Preprocess_Macro_Typename);
|
||||||
|
name.Text = macro->Content;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The usual Identifier type signature that may have namespace qualifiers
|
// The usual Identifier type signature that may have namespace qualifiers
|
||||||
@ -4649,7 +4724,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
#ifdef GEN_USE_NEW_TYPENAME_PARSING
|
#ifdef GEN_USE_NEW_TYPENAME_PARSING
|
||||||
if ( NumSpecifiers )
|
if ( NumSpecifiers )
|
||||||
{
|
{
|
||||||
specifiers = def_specifiers( NumSpecifiers, specs_found );
|
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
NumSpecifiers = 0;
|
NumSpecifiers = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -4674,7 +4749,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
is_function_typename = true;
|
is_function_typename = true;
|
||||||
++scanner;
|
++scanner;
|
||||||
}
|
}
|
||||||
is_function_typename = scanner->Type == Tok_Capture_Start;
|
is_function_typename = scanner->Type == Tok_Paren_Open;
|
||||||
|
|
||||||
Token* first_capture = scanner;
|
Token* first_capture = scanner;
|
||||||
if ( is_function_typename )
|
if ( is_function_typename )
|
||||||
@ -4684,7 +4759,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
++scanner;
|
++scanner;
|
||||||
|
|
||||||
// Go back to the first capture start found
|
// Go back to the first capture start found
|
||||||
while ( scanner->Type != Tok_Capture_Start )
|
while ( scanner->Type != Tok_Paren_Open )
|
||||||
--scanner;
|
--scanner;
|
||||||
|
|
||||||
last_capture = scanner;
|
last_capture = scanner;
|
||||||
@ -4729,7 +4804,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
if ( NumSpecifiers )
|
if ( NumSpecifiers )
|
||||||
return_type->Specs = def_specifiers( NumSpecifiers, ( Specifier* )specs_found );
|
return_type->Specs = def_specifiers_arr( NumSpecifiers, ( Specifier* )specs_found );
|
||||||
|
|
||||||
// Reset specifiers, the function itself will have its own suffix specifiers possibly.
|
// Reset specifiers, the function itself will have its own suffix specifiers possibly.
|
||||||
NumSpecifiers = 0;
|
NumSpecifiers = 0;
|
||||||
@ -4738,7 +4813,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
name = NullToken;
|
name = NullToken;
|
||||||
|
|
||||||
// The next token can either be a capture for the identifier or it could be the identifier exposed.
|
// The next token can either be a capture for the identifier or it could be the identifier exposed.
|
||||||
if ( ! check( Tok_Capture_Start ) )
|
if ( ! check( Tok_Paren_Open ) )
|
||||||
{
|
{
|
||||||
// Started with an identifier immeidately, which means its of the format: <ReturnType> <identifier> <capture>;
|
// Started with an identifier immeidately, which means its of the format: <ReturnType> <identifier> <capture>;
|
||||||
name = parse_identifier(nullptr);
|
name = parse_identifier(nullptr);
|
||||||
@ -4758,7 +4833,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
// Parse immeidate capture which would be with parse_params()
|
// Parse immeidate capture which would be with parse_params()
|
||||||
// Eat Capture End
|
// Eat Capture End
|
||||||
#ifdef GEN_USE_NEW_TYPENAME_PARSING
|
#ifdef GEN_USE_NEW_TYPENAME_PARSING
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
// <Attributes> <ReturnType> (
|
// <Attributes> <ReturnType> (
|
||||||
|
|
||||||
// Binding specifiers
|
// Binding specifiers
|
||||||
@ -4780,7 +4855,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
|
|
||||||
if ( NumSpecifiers )
|
if ( NumSpecifiers )
|
||||||
{
|
{
|
||||||
specifiers = def_specifiers( NumSpecifiers, specs_found );
|
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
}
|
}
|
||||||
NumSpecifiers = 0;
|
NumSpecifiers = 0;
|
||||||
// <Attributes> <ReturnType> ( <Specifiers>
|
// <Attributes> <ReturnType> ( <Specifiers>
|
||||||
@ -4791,11 +4866,11 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
|
|
||||||
// Immeidate parameters
|
// Immeidate parameters
|
||||||
|
|
||||||
if ( check( Tok_Capture_Start ) )
|
if ( check( Tok_Paren_Open ) )
|
||||||
params_nested = parse_params();
|
params_nested = parse_params();
|
||||||
// <Attributes> <ReturnType> ( <Specifiers> <Identifier> ( <Parameters> )
|
// <Attributes> <ReturnType> ( <Specifiers> <Identifier> ( <Parameters> )
|
||||||
|
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
// <Attributes> <ReturnType> ( <Specifiers> <Identifier> ( <Parameters> ) )
|
// <Attributes> <ReturnType> ( <Specifiers> <Identifier> ( <Parameters> ) )
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -4803,21 +4878,21 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
// Everything within this capture will just be shoved into the name field including the capture tokens themselves.
|
// Everything within this capture will just be shoved into the name field including the capture tokens themselves.
|
||||||
name = currtok;
|
name = currtok;
|
||||||
|
|
||||||
eat( Tok_Capture_Start );
|
eat( Tok_Paren_Open );
|
||||||
// <Attributes> <ReturnType> (
|
// <Attributes> <ReturnType> (
|
||||||
|
|
||||||
s32 level = 0;
|
s32 level = 0;
|
||||||
while ( left && ( currtok.Type != Tok_Capture_End || level > 0 ) )
|
while ( left && ( currtok.Type != Tok_Paren_Close || level > 0 ) )
|
||||||
{
|
{
|
||||||
if ( currtok.Type == Tok_Capture_Start )
|
if ( currtok.Type == Tok_Paren_Open )
|
||||||
level++;
|
level++;
|
||||||
|
|
||||||
if ( currtok.Type == Tok_Capture_End )
|
if ( currtok.Type == Tok_Paren_Close )
|
||||||
level--;
|
level--;
|
||||||
|
|
||||||
eat( currtok.Type );
|
eat( currtok.Type );
|
||||||
}
|
}
|
||||||
eat( Tok_Capture_End );
|
eat( Tok_Paren_Close );
|
||||||
// <Attributes> <ReturnType> ( <Expression> )
|
// <Attributes> <ReturnType> ( <Expression> )
|
||||||
|
|
||||||
name.Text.Len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )name.Text.Ptr;
|
name.Text.Len = ( ( sptr )prevtok.Text.Ptr + prevtok.Text.Len ) - ( sptr )name.Text.Ptr;
|
||||||
@ -4851,7 +4926,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
#ifdef GEN_USE_NEW_TYPENAME_PARSING
|
#ifdef GEN_USE_NEW_TYPENAME_PARSING
|
||||||
if ( NumSpecifiers )
|
if ( NumSpecifiers )
|
||||||
{
|
{
|
||||||
func_suffix_specs = def_specifiers( NumSpecifiers, specs_found );
|
func_suffix_specs = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
NumSpecifiers = 0;
|
NumSpecifiers = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -4901,7 +4976,7 @@ else if ( currtok.Type == Tok_DeclType )
|
|||||||
#else
|
#else
|
||||||
if ( NumSpecifiers )
|
if ( NumSpecifiers )
|
||||||
{
|
{
|
||||||
CodeSpecifiers specifiers = def_specifiers( NumSpecifiers, ( Specifier* )specs_found );
|
CodeSpecifiers specifiers = def_specifiers_arr( NumSpecifiers, ( Specifier* )specs_found );
|
||||||
result->Specs = specifiers;
|
result->Specs = specifiers;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -4960,11 +5035,10 @@ CodeTypedef parser_parse_typedef()
|
|||||||
valid_macro |= left && currtok.Type == Tok_Preprocess_Macro_Stmt;
|
valid_macro |= left && currtok.Type == Tok_Preprocess_Macro_Stmt;
|
||||||
// if (currtok.Type == Tok_Preprocess_Macro_Stmt)
|
// if (currtok.Type == Tok_Preprocess_Macro_Stmt)
|
||||||
// {
|
// {
|
||||||
// PreprocessMacro* macro = lookup_preprocess_macro(currtok.Text);
|
// PreprocessMacro* macro = lookup_macro(currtok.Text);
|
||||||
// valid_macro |= macro && macro_expects_body(* macro));
|
// valid_macro |= macro && macro_expects_body(* macro));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Code macro;
|
|
||||||
if ( valid_macro )
|
if ( valid_macro )
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -5440,10 +5514,17 @@ CodeVar parser_parse_variable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( NumSpecifiers ) {
|
if ( NumSpecifiers ) {
|
||||||
specifiers = def_specifiers( NumSpecifiers, specs_found );
|
specifiers = def_specifiers_arr( NumSpecifiers, specs_found );
|
||||||
}
|
}
|
||||||
// <ModuleFlags> <Attributes> <Specifiers>
|
// <ModuleFlags> <Attributes> <Specifiers>
|
||||||
|
|
||||||
|
// Note(Ed): We're enforcing that using this codepath requires non-macro jank.
|
||||||
|
// Code macro_stmt = parse_macro_as_definiton(attributes, specifiers);
|
||||||
|
// if (macro_stmt) {
|
||||||
|
// parser_pop(& _ctx->parser);
|
||||||
|
// return macro_stmt;
|
||||||
|
// }
|
||||||
|
|
||||||
CodeTypename type = parser_parse_type(parser_not_from_template, nullptr);
|
CodeTypename type = parser_parse_type(parser_not_from_template, nullptr);
|
||||||
// <ModuleFlags> <Attributes> <Specifiers> <ValueType>
|
// <ModuleFlags> <Attributes> <Specifiers> <ValueType>
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// These macros are used in the swtich cases within parser.cpp
|
// These macros are used in the swtich cases within parser.cpp
|
||||||
|
|
||||||
#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIERS_CASES \
|
#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIER_CASES \
|
||||||
case Tok_Spec_Consteval: \
|
case Tok_Spec_Consteval: \
|
||||||
case Tok_Spec_Constexpr: \
|
case Tok_Spec_Constexpr: \
|
||||||
case Tok_Spec_Constinit: \
|
case Tok_Spec_Constinit: \
|
||||||
@ -13,7 +13,7 @@ case Tok_Spec_Static: \
|
|||||||
case Tok_Spec_Volatile: \
|
case Tok_Spec_Volatile: \
|
||||||
case Tok_Spec_Virtual
|
case Tok_Spec_Virtual
|
||||||
|
|
||||||
#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIERS_CASES \
|
#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIER_CASES \
|
||||||
case Spec_Constexpr: \
|
case Spec_Constexpr: \
|
||||||
case Spec_Constinit: \
|
case Spec_Constinit: \
|
||||||
case Spec_Explicit: \
|
case Spec_Explicit: \
|
||||||
@ -50,12 +50,12 @@ case Spec_NeverInline: \
|
|||||||
case Spec_Static: \
|
case Spec_Static: \
|
||||||
case Spec_Volatile
|
case Spec_Volatile
|
||||||
|
|
||||||
#define GEN_PARSER_FRIEND_ALLOWED_SPECIFIERS_CASES \
|
#define GEN_PARSER_FRIEND_ALLOWED_SPECIFIER_CASES \
|
||||||
case Spec_Const: \
|
case Spec_Const: \
|
||||||
case Spec_Inline: \
|
case Spec_Inline: \
|
||||||
case Spec_ForceInline
|
case Spec_ForceInline
|
||||||
|
|
||||||
#define GEN_PARSER_FUNCTION_ALLOWED_SPECIFIERS_CASES \
|
#define GEN_PARSER_FUNCTION_ALLOWED_SPECIFIER_CASES \
|
||||||
case Spec_Const: \
|
case Spec_Const: \
|
||||||
case Spec_Consteval: \
|
case Spec_Consteval: \
|
||||||
case Spec_Constexpr: \
|
case Spec_Constexpr: \
|
||||||
@ -66,7 +66,7 @@ case Spec_Inline: \
|
|||||||
case Spec_NeverInline: \
|
case Spec_NeverInline: \
|
||||||
case Spec_Static
|
case Spec_Static
|
||||||
|
|
||||||
#define GEN_PARSER_OPERATOR_ALLOWED_SPECIFIERS_CASES \
|
#define GEN_PARSER_OPERATOR_ALLOWED_SPECIFIER_CASES \
|
||||||
case Spec_Const: \
|
case Spec_Const: \
|
||||||
case Spec_Constexpr: \
|
case Spec_Constexpr: \
|
||||||
case Spec_ForceInline: \
|
case Spec_ForceInline: \
|
||||||
@ -74,7 +74,7 @@ case Spec_Inline: \
|
|||||||
case Spec_NeverInline: \
|
case Spec_NeverInline: \
|
||||||
case Spec_Static
|
case Spec_Static
|
||||||
|
|
||||||
#define GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIERS_CASES \
|
#define GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIER_CASES \
|
||||||
case Spec_Const: \
|
case Spec_Const: \
|
||||||
case Spec_Constexpr: \
|
case Spec_Constexpr: \
|
||||||
case Spec_Constinit: \
|
case Spec_Constinit: \
|
||||||
|
@ -132,8 +132,6 @@ enum MacroType : u16
|
|||||||
MT_Expression, // A macro is assumed to be a expression if not resolved.
|
MT_Expression, // A macro is assumed to be a expression if not resolved.
|
||||||
MT_Statement,
|
MT_Statement,
|
||||||
MT_Typename,
|
MT_Typename,
|
||||||
MT_Attribute, // More of a note to the parser than anythign else (attributes should be defined in the user attribues def).
|
|
||||||
MT_Specifier, // More of a note to the parser than anythign else (specifiers should be defined in the user attribues def).
|
|
||||||
MT_Block_Start, // Not Supported yet
|
MT_Block_Start, // Not Supported yet
|
||||||
MT_Block_End, // Not Supported yet
|
MT_Block_End, // Not Supported yet
|
||||||
MT_Case_Statement, // Not Supported yet
|
MT_Case_Statement, // Not Supported yet
|
||||||
@ -152,6 +150,7 @@ TokType macrotype_to_toktype( MacroType type ) {
|
|||||||
return Tok_Invalid;
|
return Tok_Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
Str macrotype_to_str( MacroType type )
|
Str macrotype_to_str( MacroType type )
|
||||||
{
|
{
|
||||||
local_persist
|
local_persist
|
||||||
@ -159,8 +158,6 @@ Str macrotype_to_str( MacroType type )
|
|||||||
{ "Statement", sizeof("Statement") - 1 },
|
{ "Statement", sizeof("Statement") - 1 },
|
||||||
{ "Expression", sizeof("Expression") - 1 },
|
{ "Expression", sizeof("Expression") - 1 },
|
||||||
{ "Typename", sizeof("Typename") - 1 },
|
{ "Typename", sizeof("Typename") - 1 },
|
||||||
{ "Attribute(Macro)", sizeof("Attribute(Macro)") - 1 },
|
|
||||||
{ "Specifier(Macro)", sizeof("Specifier(Macro)") - 1 },
|
|
||||||
{ "Block_Start", sizeof("Block_Start") - 1 },
|
{ "Block_Start", sizeof("Block_Start") - 1 },
|
||||||
{ "Block_End", sizeof("Block_End") - 1 },
|
{ "Block_End", sizeof("Block_End") - 1 },
|
||||||
{ "Case_Statement", sizeof("Case_Statement") - 1 },
|
{ "Case_Statement", sizeof("Case_Statement") - 1 },
|
||||||
@ -177,15 +174,29 @@ enum EMacroFlags : u16
|
|||||||
{
|
{
|
||||||
MF_Functional = bit(0), // Macro has parameters (args expected to be passed)
|
MF_Functional = bit(0), // Macro has parameters (args expected to be passed)
|
||||||
MF_Expects_Body = bit(1), // Expects to assign a braced scope to its body.
|
MF_Expects_Body = bit(1), // Expects to assign a braced scope to its body.
|
||||||
MF_Allow_As_Identifier = bit(2), // lex__eat wil treat this macro as an identifier if the parser attempts to consume it as one.
|
|
||||||
// ^^^ This is a sort of kludge because we don't support push/pop macro programs rn. ^^^
|
// lex__eat wil treat this macro as an identifier if the parser attempts to consume it as one.
|
||||||
|
// ^^^ This is a kludge because we don't support push/pop macro pragmas rn.
|
||||||
|
MF_Allow_As_Identifier = bit(2),
|
||||||
|
|
||||||
|
// lex__eat wil treat this macro as an attribute if the parser attempts to consume it as one.
|
||||||
|
// ^^^ This a kludge because unreal has a macro that behaves as both a 'statement' and an attribute (UE_DEPRECATED, PRAGMA_ENABLE_DEPRECATION_WARNINGS, etc)
|
||||||
|
// TODO(Ed): We can keep the MF_Allow_As_Attribute flag for macros, however, we need to add the ability of AST_Attributes to chain themselves.
|
||||||
|
// Its thats already a thing in the standard language anyway
|
||||||
|
// & it would allow UE_DEPRECATED, (UE_PROPERTY / UE_FUNCTION) to chain themselves as attributes of a resolved member function/varaible definition
|
||||||
|
MF_Allow_As_Attribute = bit(3),
|
||||||
|
|
||||||
|
// When a macro is encountered after attributs and specifiers while parsing a function, or variable:
|
||||||
|
// It will consume the macro and treat it as resolving the definition. (Yes this is for Unreal Engine)
|
||||||
|
// (MUST BE OF MT_Statement TYPE)
|
||||||
|
MF_Allow_As_Definition = bit(4),
|
||||||
|
|
||||||
MF_Null = 0,
|
MF_Null = 0,
|
||||||
MF_UnderlyingType = GEN_U16_MAX,
|
MF_UnderlyingType = GEN_U16_MAX,
|
||||||
};
|
};
|
||||||
typedef u16 MacroFlags;
|
typedef u16 MacroFlags;
|
||||||
|
|
||||||
struct PreprocessorMacro
|
struct Macro
|
||||||
{
|
{
|
||||||
StrCached Name;
|
StrCached Name;
|
||||||
MacroType Type;
|
MacroType Type;
|
||||||
@ -193,11 +204,18 @@ struct PreprocessorMacro
|
|||||||
};
|
};
|
||||||
|
|
||||||
forceinline
|
forceinline
|
||||||
b32 macro_is_functional( PreprocessorMacro macro ) {
|
b32 macro_is_functional( Macro macro ) {
|
||||||
return bitfield_is_set( b16, macro.Flags, MF_Functional );
|
return bitfield_is_set( b16, macro.Flags, MF_Functional );
|
||||||
}
|
}
|
||||||
|
|
||||||
forceinline
|
forceinline
|
||||||
b32 macro_expects_body( PreprocessorMacro macro ) {
|
b32 macro_expects_body( Macro macro ) {
|
||||||
return bitfield_is_set( b16, macro.Flags, MF_Expects_Body );
|
return bitfield_is_set( b16, macro.Flags, MF_Expects_Body );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GEN_COMPILER_CPP && ! GEN_C_LIKE_CPP
|
||||||
|
forceinline b32 is_functional( Macro macro ) { return bitfield_is_set( b16, macro.Flags, MF_Functional ); }
|
||||||
|
forceinline b32 expects_body ( Macro macro ) { return bitfield_is_set( b16, macro.Flags, MF_Expects_Body ); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef HashTable(Macro) MacroTable;
|
||||||
|
@ -5,11 +5,10 @@
|
|||||||
|
|
||||||
#pragma region StaticData
|
#pragma region StaticData
|
||||||
global Context* _ctx;
|
global Context* _ctx;
|
||||||
|
|
||||||
#pragma region Constants
|
|
||||||
global u32 context_counter;
|
global u32 context_counter;
|
||||||
|
|
||||||
global PreprocessorMacro enum_underlying_macro;
|
#pragma region Constants
|
||||||
|
global Macro enum_underlying_macro;
|
||||||
|
|
||||||
global Code Code_Global;
|
global Code Code_Global;
|
||||||
global Code Code_Invalid;
|
global Code Code_Invalid;
|
||||||
|
@ -143,6 +143,7 @@ Array<Type> array_init_reserve(AllocatorInfo allocator, ssize capacity)
|
|||||||
return {rcast(Type*, header + 1)};
|
return {rcast(Type*, header + 1)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forceinline
|
||||||
usize array_grow_formula(ssize value) {
|
usize array_grow_formula(ssize value) {
|
||||||
return 2 * value + 8;
|
return 2 * value + 8;
|
||||||
}
|
}
|
||||||
@ -202,7 +203,7 @@ bool array_append_at(Array<Type>* array, Type item, usize idx)
|
|||||||
ArrayHeader* header = array_get_header(* array);
|
ArrayHeader* header = array_get_header(* array);
|
||||||
|
|
||||||
ssize slot = idx;
|
ssize slot = idx;
|
||||||
if (slot >= header->Num)
|
if (slot >= (ssize)(header->Num))
|
||||||
slot = header->Num - 1;
|
slot = header->Num - 1;
|
||||||
|
|
||||||
if (slot < 0)
|
if (slot < 0)
|
||||||
@ -283,8 +284,7 @@ bool array_fill(Array<Type> array, usize begin, usize end, Type value)
|
|||||||
if (begin < 0 || end > header->Num)
|
if (begin < 0 || end > header->Num)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (ssize idx = ssize(begin); idx < ssize(end); idx++)
|
for (ssize idx = ssize(begin); idx < ssize(end); idx++) {
|
||||||
{
|
|
||||||
array[idx] = value;
|
array[idx] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +354,6 @@ bool array_reserve(Array<Type>* array, usize new_capacity)
|
|||||||
{
|
{
|
||||||
GEN_ASSERT( array != nullptr);
|
GEN_ASSERT( array != nullptr);
|
||||||
GEN_ASSERT(* array != nullptr);
|
GEN_ASSERT(* array != nullptr);
|
||||||
GEN_ASSERT(num > 0)
|
|
||||||
ArrayHeader* header = array_get_header(array);
|
ArrayHeader* header = array_get_header(array);
|
||||||
|
|
||||||
if (header->Capacity < new_capacity)
|
if (header->Capacity < new_capacity)
|
||||||
@ -763,7 +762,7 @@ HashTableFindResult hashtable__find(HashTable<Type> table, u64 key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type> forceinline
|
template<typename Type> forceinline
|
||||||
bool hashtable_full(HashTable<Type> table) {
|
b32 hashtable_full(HashTable<Type> table) {
|
||||||
GEN_ASSERT_NOT_NULL(table.Hashes);
|
GEN_ASSERT_NOT_NULL(table.Hashes);
|
||||||
GEN_ASSERT_NOT_NULL(table.Entries);
|
GEN_ASSERT_NOT_NULL(table.Entries);
|
||||||
usize critical_load = usize(HashTable_CriticalLoadScale * f32(array_num(table.Hashes)));
|
usize critical_load = usize(HashTable_CriticalLoadScale * f32(array_num(table.Hashes)));
|
||||||
|
@ -11,10 +11,10 @@
|
|||||||
#if GEN_BUILD_DEBUG
|
#if GEN_BUILD_DEBUG
|
||||||
# if defined( GEN_COMPILER_MSVC )
|
# if defined( GEN_COMPILER_MSVC )
|
||||||
# if _MSC_VER < 1300
|
# if _MSC_VER < 1300
|
||||||
#pragma message("GEN_BUILD_DEBUG: __asm int 3")
|
// #pragma message("GEN_BUILD_DEBUG: __asm int 3")
|
||||||
# define GEN_DEBUG_TRAP() __asm int 3 /* Trap to debugger! */
|
# define GEN_DEBUG_TRAP() __asm int 3 /* Trap to debugger! */
|
||||||
# else
|
# else
|
||||||
#pragma message("GEN_BUILD_DEBUG: __debugbreak()")
|
// #pragma message("GEN_BUILD_DEBUG: __debugbreak()")
|
||||||
# define GEN_DEBUG_TRAP() __debugbreak()
|
# define GEN_DEBUG_TRAP() __debugbreak()
|
||||||
# endif
|
# endif
|
||||||
# elif defined( GEN_COMPILER_TINYC )
|
# elif defined( GEN_COMPILER_TINYC )
|
||||||
@ -23,7 +23,7 @@
|
|||||||
# define GEN_DEBUG_TRAP() __builtin_trap()
|
# define GEN_DEBUG_TRAP() __builtin_trap()
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
#pragma message("GEN_BUILD_DEBUG: omitted")
|
// #pragma message("GEN_BUILD_DEBUG: omitted")
|
||||||
# define GEN_DEBUG_TRAP()
|
# define GEN_DEBUG_TRAP()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -44,7 +44,7 @@
|
|||||||
// NOTE: Things that shouldn't happen with a message!
|
// NOTE: Things that shouldn't happen with a message!
|
||||||
#define GEN_PANIC( msg, ... ) GEN_ASSERT_MSG( 0, msg, ##__VA_ARGS__ )
|
#define GEN_PANIC( msg, ... ) GEN_ASSERT_MSG( 0, msg, ##__VA_ARGS__ )
|
||||||
|
|
||||||
#if GEN_BULD_DEBUG
|
#if GEN_BUILD_DEBUG
|
||||||
#define GEN_FATAL( ... ) \
|
#define GEN_FATAL( ... ) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
|
@ -86,14 +86,16 @@
|
|||||||
#define stringize( ... ) stringize_va( __VA_ARGS__ )
|
#define stringize( ... ) stringize_va( __VA_ARGS__ )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define src_line_str stringize(__LINE__)
|
||||||
|
|
||||||
#ifndef do_once
|
#ifndef do_once
|
||||||
#define do_once() \
|
#define do_once() \
|
||||||
static int __do_once_counter_##__LINE__ = 0; \
|
local_persist int __do_once_counter_##src_line_str = 0; \
|
||||||
for(; __do_once_counter_##__LINE__ != 1; __do_once_counter_##__LINE__ = 1 ) \
|
for(; __do_once_counter_##src_line_str != 1; __do_once_counter_##src_line_str = 1 ) \
|
||||||
|
|
||||||
#define do_once_defer( expression ) \
|
#define do_once_defer( expression ) \
|
||||||
static int __do_once_counter_##__LINE__ = 0; \
|
local_persist int __do_once_counter_##src_line_str = 0; \
|
||||||
for(; __do_once_counter_##__LINE__ != 1; __do_once_counter_##__LINE__ = 1, (expression)) \
|
for(;__do_once_counter_##src_line_str != 1; __do_once_counter_##src_line_str = 1, (expression)) \
|
||||||
|
|
||||||
#define do_once_start \
|
#define do_once_start \
|
||||||
do \
|
do \
|
||||||
|
@ -355,9 +355,9 @@ void* arena_allocator_proc( void* allocator_data, AllocType type, ssize size, ss
|
|||||||
{
|
{
|
||||||
// zpl__printf_err("%s", "Arena out of memory\n");
|
// zpl__printf_err("%s", "Arena out of memory\n");
|
||||||
GEN_FATAL("Arena out of memory! (Possibly could not fit for the largest size Arena!!)");
|
GEN_FATAL("Arena out of memory! (Possibly could not fit for the largest size Arena!!)");
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ptr = align_forward( end, alignment );
|
ptr = align_forward( end, alignment );
|
||||||
arena->TotalUsed += total_size;
|
arena->TotalUsed += total_size;
|
||||||
|
|
||||||
|
@ -229,7 +229,6 @@ forceinline void check(Arena& arena) { return arena_check(& arena); }
|
|||||||
#pragma pop_macro("check")
|
#pragma pop_macro("check")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
AllocatorInfo arena_allocator_info( Arena* arena ) {
|
AllocatorInfo arena_allocator_info( Arena* arena ) {
|
||||||
GEN_ASSERT(arena != nullptr);
|
GEN_ASSERT(arena != nullptr);
|
||||||
@ -392,9 +391,9 @@ void pool_clear(Pool* pool);
|
|||||||
void pool_free(Pool* pool);
|
void pool_free(Pool* pool);
|
||||||
|
|
||||||
#if GEN_COMPILER_CPP && ! GEN_C_LIKE_CPP
|
#if GEN_COMPILER_CPP && ! GEN_C_LIKE_CPP
|
||||||
AllocatorInfo allocator_info(Pool& pool) { return pool_allocator_info(& pool); }
|
forceinline AllocatorInfo allocator_info(Pool& pool) { return pool_allocator_info(& pool); }
|
||||||
void clear(Pool& pool) { return pool_clear(& pool); }
|
forceinline void clear(Pool& pool) { return pool_clear(& pool); }
|
||||||
void free(Pool& pool) { return pool_free(& pool); }
|
forceinline void free(Pool& pool) { return pool_free(& pool); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct Pool
|
struct Pool
|
||||||
|
@ -40,9 +40,9 @@ struct Str
|
|||||||
|
|
||||||
#ifndef txt
|
#ifndef txt
|
||||||
# if GEN_COMPILER_CPP
|
# if GEN_COMPILER_CPP
|
||||||
# define txt( text ) Str { ( text ), sizeof( text ) - 1 }
|
# define txt( text ) GEN_NS Str { ( text ), sizeof( text ) - 1 }
|
||||||
# else
|
# else
|
||||||
# define txt( text ) (Str){ ( text ), sizeof( text ) - 1 }
|
# define txt( text ) (GEN_NS Str){ ( text ), sizeof( text ) - 1 }
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -392,6 +392,7 @@ bool strbuilder_append_string(StrBuilder* str, StrBuilder const other) {
|
|||||||
return strbuilder_append_c_str_len(str, (char const*)other, strbuilder_length(other));
|
return strbuilder_append_c_str_len(str, (char const*)other, strbuilder_length(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
bool strbuilder_append_fmt(StrBuilder* str, char const* fmt, ...) {
|
bool strbuilder_append_fmt(StrBuilder* str, char const* fmt, ...) {
|
||||||
GEN_ASSERT(str != nullptr);
|
GEN_ASSERT(str != nullptr);
|
||||||
ssize res;
|
ssize res;
|
||||||
|
@ -13,8 +13,8 @@ BraceCurly_Open, "{"
|
|||||||
BraceCurly_Close, "}"
|
BraceCurly_Close, "}"
|
||||||
BraceSquare_Open, "["
|
BraceSquare_Open, "["
|
||||||
BraceSquare_Close, "]"
|
BraceSquare_Close, "]"
|
||||||
Capture_Start, "("
|
Paren_Open, "("
|
||||||
Capture_End, ")"
|
Paren_Close, ")"
|
||||||
Comment, "__comment__"
|
Comment, "__comment__"
|
||||||
Comment_End, "__comment_end__"
|
Comment_End, "__comment_end__"
|
||||||
Comment_Start, "__comment_start__"
|
Comment_Start, "__comment_start__"
|
||||||
|
|
@ -214,7 +214,18 @@ CodeBody gen_especifier( char const* path, bool use_c_definition = false )
|
|||||||
inline
|
inline
|
||||||
bool spec_is_trailing( Specifier specifier )
|
bool spec_is_trailing( Specifier specifier )
|
||||||
{
|
{
|
||||||
return specifier > Spec_Virtual;
|
switch (specifier) {
|
||||||
|
case Spec_Const:
|
||||||
|
case Spec_Final:
|
||||||
|
case Spec_NoExceptions:
|
||||||
|
case Spec_Override:
|
||||||
|
case Spec_Pure:
|
||||||
|
case Spec_Volatile:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)));
|
)));
|
||||||
|
|
||||||
@ -237,7 +248,7 @@ CodeBody gen_especifier( char const* path, bool use_c_definition = false )
|
|||||||
Str spec_to_str( Specifier type )
|
Str spec_to_str( Specifier type )
|
||||||
{
|
{
|
||||||
local_persist
|
local_persist
|
||||||
Str lookup[<num>] = {
|
Str lookup[] = {
|
||||||
<entries>
|
<entries>
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -283,7 +294,7 @@ CodeBody gen_especifier( char const* path, bool use_c_definition = false )
|
|||||||
body_append(result, enum_code);
|
body_append(result, enum_code);
|
||||||
if (use_c_definition)
|
if (use_c_definition)
|
||||||
{
|
{
|
||||||
CodeTypedef specifier_t = parse_typedef( code(typedef u32 Specifier; ));
|
CodeTypedef specifier_t = parse_typedef( code(typedef enum Specifier Specifier; ));
|
||||||
body_append(result, specifier_t);
|
body_append(result, specifier_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,60 +510,60 @@ CodeBody gen_ast_inlines()
|
|||||||
#pragma pop_macro("GEN_NS")
|
#pragma pop_macro("GEN_NS")
|
||||||
#pragma pop_macro("CodeInvalid")
|
#pragma pop_macro("CodeInvalid")
|
||||||
|
|
||||||
CodeBody impl_code = parse_global_body( token_fmt( "typename", Str name(Code), code_impl_tmpl ));
|
CodeBody impl_code = parse_global_body( token_fmt( "typename", name(Code), code_impl_tmpl ));
|
||||||
CodeBody impl_code_body = parse_global_body( token_fmt( "typename", Str name(CodeBody), code_impl_tmpl ));
|
CodeBody impl_code_body = parse_global_body( token_fmt( "typename", name(CodeBody), code_impl_tmpl ));
|
||||||
CodeBody impl_code_attr = parse_global_body( token_fmt( "typename", Str name(CodeAttributes), code_impl_tmpl ));
|
CodeBody impl_code_attr = parse_global_body( token_fmt( "typename", name(CodeAttributes), code_impl_tmpl ));
|
||||||
CodeBody impl_code_cmt = parse_global_body( token_fmt( "typename", Str name(CodeComment), code_impl_tmpl ));
|
CodeBody impl_code_cmt = parse_global_body( token_fmt( "typename", name(CodeComment), code_impl_tmpl ));
|
||||||
CodeBody impl_code_constr = parse_global_body( token_fmt( "typename", Str name(CodeConstructor), code_impl_tmpl ));
|
CodeBody impl_code_constr = parse_global_body( token_fmt( "typename", name(CodeConstructor), code_impl_tmpl ));
|
||||||
CodeBody impl_code_class = parse_global_body( token_fmt( "typename", Str name(CodeClass), code_impl_tmpl ));
|
CodeBody impl_code_class = parse_global_body( token_fmt( "typename", name(CodeClass), code_impl_tmpl ));
|
||||||
CodeBody impl_code_define = parse_global_body( token_fmt( "typename", Str name(CodeDefine), code_impl_tmpl ));
|
CodeBody impl_code_define = parse_global_body( token_fmt( "typename", name(CodeDefine), code_impl_tmpl ));
|
||||||
CodeBody impl_code_define_params = parse_global_body( token_fmt( "typename", Str name(CodeDefineParams), code_impl_tmpl ));
|
CodeBody impl_code_define_params = parse_global_body( token_fmt( "typename", name(CodeDefineParams), code_impl_tmpl ));
|
||||||
CodeBody impl_code_destruct = parse_global_body( token_fmt( "typename", Str name(CodeDestructor), code_impl_tmpl ));
|
CodeBody impl_code_destruct = parse_global_body( token_fmt( "typename", name(CodeDestructor), code_impl_tmpl ));
|
||||||
CodeBody impl_code_enum = parse_global_body( token_fmt( "typename", Str name(CodeEnum), code_impl_tmpl ));
|
CodeBody impl_code_enum = parse_global_body( token_fmt( "typename", name(CodeEnum), code_impl_tmpl ));
|
||||||
CodeBody impl_code_exec = parse_global_body( token_fmt( "typename", Str name(CodeExec), code_impl_tmpl ));
|
CodeBody impl_code_exec = parse_global_body( token_fmt( "typename", name(CodeExec), code_impl_tmpl ));
|
||||||
CodeBody impl_code_extern = parse_global_body( token_fmt( "typename", Str name(CodeExtern), code_impl_tmpl ));
|
CodeBody impl_code_extern = parse_global_body( token_fmt( "typename", name(CodeExtern), code_impl_tmpl ));
|
||||||
CodeBody impl_code_include = parse_global_body( token_fmt( "typename", Str name(CodeInclude), code_impl_tmpl ));
|
CodeBody impl_code_include = parse_global_body( token_fmt( "typename", name(CodeInclude), code_impl_tmpl ));
|
||||||
CodeBody impl_code_friend = parse_global_body( token_fmt( "typename", Str name(CodeFriend), code_impl_tmpl ));
|
CodeBody impl_code_friend = parse_global_body( token_fmt( "typename", name(CodeFriend), code_impl_tmpl ));
|
||||||
CodeBody impl_code_fn = parse_global_body( token_fmt( "typename", Str name(CodeFn), code_impl_tmpl ));
|
CodeBody impl_code_fn = parse_global_body( token_fmt( "typename", name(CodeFn), code_impl_tmpl ));
|
||||||
CodeBody impl_code_module = parse_global_body( token_fmt( "typename", Str name(CodeModule), code_impl_tmpl ));
|
CodeBody impl_code_module = parse_global_body( token_fmt( "typename", name(CodeModule), code_impl_tmpl ));
|
||||||
CodeBody impl_code_ns = parse_global_body( token_fmt( "typename", Str name(CodeNS), code_impl_tmpl ));
|
CodeBody impl_code_ns = parse_global_body( token_fmt( "typename", name(CodeNS), code_impl_tmpl ));
|
||||||
CodeBody impl_code_op = parse_global_body( token_fmt( "typename", Str name(CodeOperator), code_impl_tmpl ));
|
CodeBody impl_code_op = parse_global_body( token_fmt( "typename", name(CodeOperator), code_impl_tmpl ));
|
||||||
CodeBody impl_code_opcast = parse_global_body( token_fmt( "typename", Str name(CodeOpCast), code_impl_tmpl ));
|
CodeBody impl_code_opcast = parse_global_body( token_fmt( "typename", name(CodeOpCast), code_impl_tmpl ));
|
||||||
CodeBody impl_code_params = parse_global_body( token_fmt( "typename", Str name(CodeParams), code_impl_tmpl ));
|
CodeBody impl_code_params = parse_global_body( token_fmt( "typename", name(CodeParams), code_impl_tmpl ));
|
||||||
CodeBody impl_code_pragma = parse_global_body( token_fmt( "typename", Str name(CodePragma), code_impl_tmpl ));
|
CodeBody impl_code_pragma = parse_global_body( token_fmt( "typename", name(CodePragma), code_impl_tmpl ));
|
||||||
CodeBody impl_code_precond = parse_global_body( token_fmt( "typename", Str name(CodePreprocessCond), code_impl_tmpl ));
|
CodeBody impl_code_precond = parse_global_body( token_fmt( "typename", name(CodePreprocessCond), code_impl_tmpl ));
|
||||||
CodeBody impl_code_specs = parse_global_body( token_fmt( "typename", Str name(CodeSpecifiers), code_impl_tmpl ));
|
CodeBody impl_code_specs = parse_global_body( token_fmt( "typename", name(CodeSpecifiers), code_impl_tmpl ));
|
||||||
CodeBody impl_code_struct = parse_global_body( token_fmt( "typename", Str name(CodeStruct), code_impl_tmpl ));
|
CodeBody impl_code_struct = parse_global_body( token_fmt( "typename", name(CodeStruct), code_impl_tmpl ));
|
||||||
CodeBody impl_code_tmpl = parse_global_body( token_fmt( "typename", Str name(CodeTemplate), code_impl_tmpl ));
|
CodeBody impl_code_tmpl = parse_global_body( token_fmt( "typename", name(CodeTemplate), code_impl_tmpl ));
|
||||||
CodeBody impl_code_type = parse_global_body( token_fmt( "typename", Str name(CodeTypename), code_impl_tmpl ));
|
CodeBody impl_code_type = parse_global_body( token_fmt( "typename", name(CodeTypename), code_impl_tmpl ));
|
||||||
CodeBody impl_code_typedef = parse_global_body( token_fmt( "typename", Str name(CodeTypedef), code_impl_tmpl ));
|
CodeBody impl_code_typedef = parse_global_body( token_fmt( "typename", name(CodeTypedef), code_impl_tmpl ));
|
||||||
CodeBody impl_code_union = parse_global_body( token_fmt( "typename", Str name(CodeUnion), code_impl_tmpl ));
|
CodeBody impl_code_union = parse_global_body( token_fmt( "typename", name(CodeUnion), code_impl_tmpl ));
|
||||||
CodeBody impl_code_using = parse_global_body( token_fmt( "typename", Str name(CodeUsing), code_impl_tmpl ));
|
CodeBody impl_code_using = parse_global_body( token_fmt( "typename", name(CodeUsing), code_impl_tmpl ));
|
||||||
CodeBody impl_code_var = parse_global_body( token_fmt( "typename", Str name(CodeVar), code_impl_tmpl ));
|
CodeBody impl_code_var = parse_global_body( token_fmt( "typename", name(CodeVar), code_impl_tmpl ));
|
||||||
|
|
||||||
body_append(impl_code_attr, parse_global_body( token_fmt( "typename", Str name(Attributes), codetype_impl_tmpl )));
|
body_append(impl_code_attr, parse_global_body( token_fmt( "typename", name(Attributes), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_cmt, parse_global_body( token_fmt( "typename", Str name(Comment), codetype_impl_tmpl )));
|
body_append(impl_code_cmt, parse_global_body( token_fmt( "typename", name(Comment), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_constr, parse_global_body( token_fmt( "typename", Str name(Constructor), codetype_impl_tmpl )));
|
body_append(impl_code_constr, parse_global_body( token_fmt( "typename", name(Constructor), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_define, parse_global_body( token_fmt( "typename", Str name(Define), codetype_impl_tmpl )));
|
body_append(impl_code_define, parse_global_body( token_fmt( "typename", name(Define), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_destruct, parse_global_body( token_fmt( "typename", Str name(Destructor), codetype_impl_tmpl )));
|
body_append(impl_code_destruct, parse_global_body( token_fmt( "typename", name(Destructor), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_enum, parse_global_body( token_fmt( "typename", Str name(Enum), codetype_impl_tmpl )));
|
body_append(impl_code_enum, parse_global_body( token_fmt( "typename", name(Enum), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_exec, parse_global_body( token_fmt( "typename", Str name(Exec), codetype_impl_tmpl )));
|
body_append(impl_code_exec, parse_global_body( token_fmt( "typename", name(Exec), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_extern, parse_global_body( token_fmt( "typename", Str name(Extern), codetype_impl_tmpl )));
|
body_append(impl_code_extern, parse_global_body( token_fmt( "typename", name(Extern), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_include, parse_global_body( token_fmt( "typename", Str name(Include), codetype_impl_tmpl )));
|
body_append(impl_code_include, parse_global_body( token_fmt( "typename", name(Include), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_friend, parse_global_body( token_fmt( "typename", Str name(Friend), codetype_impl_tmpl )));
|
body_append(impl_code_friend, parse_global_body( token_fmt( "typename", name(Friend), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_fn, parse_global_body( token_fmt( "typename", Str name(Fn), codetype_impl_tmpl )));
|
body_append(impl_code_fn, parse_global_body( token_fmt( "typename", name(Fn), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_module, parse_global_body( token_fmt( "typename", Str name(Module), codetype_impl_tmpl )));
|
body_append(impl_code_module, parse_global_body( token_fmt( "typename", name(Module), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_ns, parse_global_body( token_fmt( "typename", Str name(NS), codetype_impl_tmpl )));
|
body_append(impl_code_ns, parse_global_body( token_fmt( "typename", name(NS), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_op, parse_global_body( token_fmt( "typename", Str name(Operator), codetype_impl_tmpl )));
|
body_append(impl_code_op, parse_global_body( token_fmt( "typename", name(Operator), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_opcast, parse_global_body( token_fmt( "typename", Str name(OpCast), codetype_impl_tmpl )));
|
body_append(impl_code_opcast, parse_global_body( token_fmt( "typename", name(OpCast), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_pragma, parse_global_body( token_fmt( "typename", Str name(Pragma), codetype_impl_tmpl )));
|
body_append(impl_code_pragma, parse_global_body( token_fmt( "typename", name(Pragma), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_precond, parse_global_body( token_fmt( "typename", Str name(PreprocessCond), codetype_impl_tmpl )));
|
body_append(impl_code_precond, parse_global_body( token_fmt( "typename", name(PreprocessCond), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_tmpl, parse_global_body( token_fmt( "typename", Str name(Template), codetype_impl_tmpl )));
|
body_append(impl_code_tmpl, parse_global_body( token_fmt( "typename", name(Template), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_type, parse_global_body( token_fmt( "typename", Str name(Typename), codetype_impl_tmpl )));
|
body_append(impl_code_type, parse_global_body( token_fmt( "typename", name(Typename), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_typedef, parse_global_body( token_fmt( "typename", Str name(Typedef), codetype_impl_tmpl )));
|
body_append(impl_code_typedef, parse_global_body( token_fmt( "typename", name(Typedef), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_union, parse_global_body( token_fmt( "typename", Str name(Union), codetype_impl_tmpl )));
|
body_append(impl_code_union, parse_global_body( token_fmt( "typename", name(Union), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_using, parse_global_body( token_fmt( "typename", Str name(Using), codetype_impl_tmpl )));
|
body_append(impl_code_using, parse_global_body( token_fmt( "typename", name(Using), codetype_impl_tmpl )));
|
||||||
body_append(impl_code_var, parse_global_body( token_fmt( "typename", Str name(Var), codetype_impl_tmpl )));
|
body_append(impl_code_var, parse_global_body( token_fmt( "typename", name(Var), codetype_impl_tmpl )));
|
||||||
|
|
||||||
#pragma push_macro("forceinline")
|
#pragma push_macro("forceinline")
|
||||||
#undef forceinline
|
#undef forceinline
|
||||||
@ -564,35 +575,35 @@ CodeBody gen_ast_inlines()
|
|||||||
);
|
);
|
||||||
#pragma pop_macro("forceinline")
|
#pragma pop_macro("forceinline")
|
||||||
|
|
||||||
CodeBody impl_cast_body = parse_global_body( token_fmt( "typename", Str name(Body), cast_tmpl ));
|
CodeBody impl_cast_body = parse_global_body( token_fmt( "typename", name(Body), cast_tmpl ));
|
||||||
CodeBody impl_cast_attribute = parse_global_body( token_fmt( "typename", Str name(Attributes), cast_tmpl ));
|
CodeBody impl_cast_attribute = parse_global_body( token_fmt( "typename", name(Attributes), cast_tmpl ));
|
||||||
CodeBody impl_cast_cmt = parse_global_body( token_fmt( "typename", Str name(Comment), cast_tmpl ));
|
CodeBody impl_cast_cmt = parse_global_body( token_fmt( "typename", name(Comment), cast_tmpl ));
|
||||||
CodeBody impl_cast_constr = parse_global_body( token_fmt( "typename", Str name(Constructor), cast_tmpl ));
|
CodeBody impl_cast_constr = parse_global_body( token_fmt( "typename", name(Constructor), cast_tmpl ));
|
||||||
CodeBody impl_cast_class = parse_global_body( token_fmt( "typename", Str name(Class), cast_tmpl ));
|
CodeBody impl_cast_class = parse_global_body( token_fmt( "typename", name(Class), cast_tmpl ));
|
||||||
CodeBody impl_cast_define = parse_global_body( token_fmt( "typename", Str name(Define), cast_tmpl ));
|
CodeBody impl_cast_define = parse_global_body( token_fmt( "typename", name(Define), cast_tmpl ));
|
||||||
CodeBody impl_cast_define_params = parse_global_body( token_fmt( "typename", Str name(DefineParams), cast_tmpl ));
|
CodeBody impl_cast_define_params = parse_global_body( token_fmt( "typename", name(DefineParams), cast_tmpl ));
|
||||||
CodeBody impl_cast_destruct = parse_global_body( token_fmt( "typename", Str name(Destructor), cast_tmpl ));
|
CodeBody impl_cast_destruct = parse_global_body( token_fmt( "typename", name(Destructor), cast_tmpl ));
|
||||||
CodeBody impl_cast_enum = parse_global_body( token_fmt( "typename", Str name(Enum), cast_tmpl ));
|
CodeBody impl_cast_enum = parse_global_body( token_fmt( "typename", name(Enum), cast_tmpl ));
|
||||||
CodeBody impl_cast_exec = parse_global_body( token_fmt( "typename", Str name(Exec), cast_tmpl ));
|
CodeBody impl_cast_exec = parse_global_body( token_fmt( "typename", name(Exec), cast_tmpl ));
|
||||||
CodeBody impl_cast_extern = parse_global_body( token_fmt( "typename", Str name(Extern), cast_tmpl ));
|
CodeBody impl_cast_extern = parse_global_body( token_fmt( "typename", name(Extern), cast_tmpl ));
|
||||||
CodeBody impl_cast_friend = parse_global_body( token_fmt( "typename", Str name(Friend), cast_tmpl ));
|
CodeBody impl_cast_friend = parse_global_body( token_fmt( "typename", name(Friend), cast_tmpl ));
|
||||||
CodeBody impl_cast_fn = parse_global_body( token_fmt( "typename", Str name(Fn), cast_tmpl ));
|
CodeBody impl_cast_fn = parse_global_body( token_fmt( "typename", name(Fn), cast_tmpl ));
|
||||||
CodeBody impl_cast_include = parse_global_body( token_fmt( "typename", Str name(Include), cast_tmpl ));
|
CodeBody impl_cast_include = parse_global_body( token_fmt( "typename", name(Include), cast_tmpl ));
|
||||||
CodeBody impl_cast_module = parse_global_body( token_fmt( "typename", Str name(Module), cast_tmpl ));
|
CodeBody impl_cast_module = parse_global_body( token_fmt( "typename", name(Module), cast_tmpl ));
|
||||||
CodeBody impl_cast_ns = parse_global_body( token_fmt( "typename", Str name(NS), cast_tmpl ));
|
CodeBody impl_cast_ns = parse_global_body( token_fmt( "typename", name(NS), cast_tmpl ));
|
||||||
CodeBody impl_cast_op = parse_global_body( token_fmt( "typename", Str name(Operator), cast_tmpl ));
|
CodeBody impl_cast_op = parse_global_body( token_fmt( "typename", name(Operator), cast_tmpl ));
|
||||||
CodeBody impl_cast_opcast = parse_global_body( token_fmt( "typename", Str name(OpCast), cast_tmpl ));
|
CodeBody impl_cast_opcast = parse_global_body( token_fmt( "typename", name(OpCast), cast_tmpl ));
|
||||||
CodeBody impl_cast_params = parse_global_body( token_fmt( "typename", Str name(Params), cast_tmpl ));
|
CodeBody impl_cast_params = parse_global_body( token_fmt( "typename", name(Params), cast_tmpl ));
|
||||||
CodeBody impl_cast_pragma = parse_global_body( token_fmt( "typename", Str name(Pragma), cast_tmpl ));
|
CodeBody impl_cast_pragma = parse_global_body( token_fmt( "typename", name(Pragma), cast_tmpl ));
|
||||||
CodeBody impl_cast_precond = parse_global_body( token_fmt( "typename", Str name(PreprocessCond), cast_tmpl ));
|
CodeBody impl_cast_precond = parse_global_body( token_fmt( "typename", name(PreprocessCond), cast_tmpl ));
|
||||||
CodeBody impl_cast_specs = parse_global_body( token_fmt( "typename", Str name(Specifiers), cast_tmpl ));
|
CodeBody impl_cast_specs = parse_global_body( token_fmt( "typename", name(Specifiers), cast_tmpl ));
|
||||||
CodeBody impl_cast_struct = parse_global_body( token_fmt( "typename", Str name(Struct), cast_tmpl ));
|
CodeBody impl_cast_struct = parse_global_body( token_fmt( "typename", name(Struct), cast_tmpl ));
|
||||||
CodeBody impl_cast_tmpl = parse_global_body( token_fmt( "typename", Str name(Template), cast_tmpl ));
|
CodeBody impl_cast_tmpl = parse_global_body( token_fmt( "typename", name(Template), cast_tmpl ));
|
||||||
CodeBody impl_cast_type = parse_global_body( token_fmt( "typename", Str name(Typename), cast_tmpl ));
|
CodeBody impl_cast_type = parse_global_body( token_fmt( "typename", name(Typename), cast_tmpl ));
|
||||||
CodeBody impl_cast_typedef = parse_global_body( token_fmt( "typename", Str name(Typedef), cast_tmpl ));
|
CodeBody impl_cast_typedef = parse_global_body( token_fmt( "typename", name(Typedef), cast_tmpl ));
|
||||||
CodeBody impl_cast_union = parse_global_body( token_fmt( "typename", Str name(Union), cast_tmpl ));
|
CodeBody impl_cast_union = parse_global_body( token_fmt( "typename", name(Union), cast_tmpl ));
|
||||||
CodeBody impl_cast_using = parse_global_body( token_fmt( "typename", Str name(Using), cast_tmpl ));
|
CodeBody impl_cast_using = parse_global_body( token_fmt( "typename", name(Using), cast_tmpl ));
|
||||||
CodeBody impl_cast_var = parse_global_body( token_fmt( "typename", Str name(Var), cast_tmpl ));
|
CodeBody impl_cast_var = parse_global_body( token_fmt( "typename", name(Var), cast_tmpl ));
|
||||||
|
|
||||||
CodeBody result = def_global_body( args(
|
CodeBody result = def_global_body( args(
|
||||||
def_pragma( txt("region generated code inline implementation")),
|
def_pragma( txt("region generated code inline implementation")),
|
||||||
|
@ -53,6 +53,7 @@ StrBuilder <prefix>_to_strbuilder(Code code);
|
|||||||
|
|
||||||
Where the first generates strings allocated using Allocator_StringArena and the other appends an existing strings with their backed allocator.
|
Where the first generates strings allocated using Allocator_StringArena and the other appends an existing strings with their backed allocator.
|
||||||
|
|
||||||
Serialization of for the AST is defined for `Code` in [`ast.chpp`](../base/components/ast.cpp) with `code_to_strbuilder_ptr` & `code_to_strbuilder`.
|
Serialization of for the AST is defined for `Code` in [`ast.cpp`](../base/components/ast.cpp) with `code_to_strbuilder_ptr` & `code_to_strbuilder`.
|
||||||
Serializtion for the rest of the code types is within [`code_serialization.cpp`](../base/components/code_serialization.cpp).
|
Serializtion for the rest of the code types is within [`code_serialization.cpp`](../base/components/code_serialization.cpp).
|
||||||
|
|
||||||
Gencpp's serialization does not provide coherent formatting of the code. The user should use a formatter after serializing.
|
Gencpp's serialization does not provide coherent formatting of the code. The user should use a formatter after serializing.
|
||||||
|
@ -30,7 +30,7 @@ Code Front;
|
|||||||
Code Back;
|
Code Back;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
s32 NumEntries;
|
s32 NumEntries;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -86,7 +86,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -114,7 +114,7 @@ CodeType Prev;
|
|||||||
CodeType Next;
|
CodeType Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
AccessSpec ParentAccess;
|
AccessSpec ParentAccess;
|
||||||
```
|
```
|
||||||
@ -148,7 +148,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -178,13 +178,14 @@ Represents a preprocessor define
|
|||||||
Fields:
|
Fields:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
StrCached Content;
|
CodeDefineParams Params;
|
||||||
|
Code Body;
|
||||||
StrCached Name;
|
StrCached Name;
|
||||||
Code Prev;
|
Code Prev;
|
||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -193,6 +194,28 @@ Serialization:
|
|||||||
#define <Name> <Content>
|
#define <Name> <Content>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## DefineParams
|
||||||
|
|
||||||
|
Preprocessor define's parameters.
|
||||||
|
|
||||||
|
Fields:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
StrCached Name;
|
||||||
|
Code Last;
|
||||||
|
Code Next;
|
||||||
|
Token* Tok;
|
||||||
|
Code Parent;
|
||||||
|
CodeType Type;
|
||||||
|
s32 NumEntries;
|
||||||
|
```
|
||||||
|
|
||||||
|
Serialization:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
<Name>, <Next> ...
|
||||||
|
```
|
||||||
|
|
||||||
## Destructor
|
## Destructor
|
||||||
|
|
||||||
Fields:
|
Fields:
|
||||||
@ -206,7 +229,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -243,7 +266,7 @@ Code Next;
|
|||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
StrCached Name;
|
StrCached Name;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -277,7 +300,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -286,7 +309,7 @@ Serialization:
|
|||||||
<Content>
|
<Content>
|
||||||
```
|
```
|
||||||
|
|
||||||
## External Linkage
|
## External Linkage (Extern)
|
||||||
|
|
||||||
Fields:
|
Fields:
|
||||||
|
|
||||||
@ -297,7 +320,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -320,7 +343,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -343,7 +366,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -368,7 +391,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -395,7 +418,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -416,7 +439,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -445,7 +468,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
OperatorT Op;
|
OperatorT Op;
|
||||||
```
|
```
|
||||||
@ -477,7 +500,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -507,7 +530,7 @@ CodeParams Last;
|
|||||||
CodeParams Next;
|
CodeParams Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
s32 NumEntries;
|
s32 NumEntries;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -530,7 +553,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -550,7 +573,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
```
|
```
|
||||||
|
|
||||||
Serialization:
|
Serialization:
|
||||||
@ -571,7 +594,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
s32 NumEntries;
|
s32 NumEntries;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -593,7 +616,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -622,7 +645,7 @@ Code Next;
|
|||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
StrCached Name;
|
StrCached Name;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
b32 IsParamPack;
|
b32 IsParamPack;
|
||||||
ETypenameTag TypeTag;
|
ETypenameTag TypeTag;
|
||||||
```
|
```
|
||||||
@ -654,7 +677,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok
|
Token* Tok
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
b32 IsFunction;
|
b32 IsFunction;
|
||||||
```
|
```
|
||||||
@ -687,7 +710,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -713,7 +736,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -746,7 +769,7 @@ Code Prev;
|
|||||||
Code Next;
|
Code Next;
|
||||||
Token* Tok;
|
Token* Tok;
|
||||||
Code Parent;
|
Code Parent;
|
||||||
CodeT Type;
|
CodeType Type;
|
||||||
ModuleFlag ModuleFlags;
|
ModuleFlag ModuleFlags;
|
||||||
s32 VarParenthesizedInit;
|
s32 VarParenthesizedInit;
|
||||||
```
|
```
|
||||||
|
1155
docs/Parser_Algo.md
1155
docs/Parser_Algo.md
File diff suppressed because it is too large
Load Diff
@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
# Parsing
|
# Parsing
|
||||||
|
|
||||||
The library features a naive single-pass parser tailored for only what the library needs to construct the supported syntax of C++ into its AST for *"front-end"* meta-programming purposes.
|
The library features a naive single-pass parser, tailored for only what the library needs; for construction of C++ code into gencpp's AST for *"front-end"* meta-programming purposes.
|
||||||
|
|
||||||
This parser does not, and should not do the compiler's job. By only supporting this minimal set of features, the parser is kept (so far) around ~7000 loc. I hope to keep it under 10k loc worst case.
|
This parser does not, and should not do the compiler's job. By only supporting this minimal set of features, the parser is kept (so far) around ~7000 loc. I hope to keep it under 10-15k loc worst case.
|
||||||
|
|
||||||
You can think of this parser as *frontend parser* vs a *semantic parser*. Its intuitively similar to WYSIWYG. What you ***precerive*** as the syntax from the user-side before the compiler gets a hold of it, is what you get.
|
You can think of this parser as *frontend parser* vs a *semantic parser*. Its intuitively similar to WYSIWYG. What you ***precerive*** as the syntax from the user-side before the compiler gets a hold of it, is what you get.
|
||||||
|
|
||||||
@ -17,6 +17,7 @@ User exposed interface:
|
|||||||
```cpp
|
```cpp
|
||||||
CodeClass parse_class ( Str class_def );
|
CodeClass parse_class ( Str class_def );
|
||||||
CodeConstructor parse_constructor ( Str constructor_def );
|
CodeConstructor parse_constructor ( Str constructor_def );
|
||||||
|
CodeDefine parse_define ( Str define_def );
|
||||||
CodeDestructor parse_destructor ( Str destructor_def );
|
CodeDestructor parse_destructor ( Str destructor_def );
|
||||||
CodeEnum parse_enum ( Str enum_def );
|
CodeEnum parse_enum ( Str enum_def );
|
||||||
CodeBody parse_export_body ( Str export_def );
|
CodeBody parse_export_body ( Str export_def );
|
||||||
@ -53,38 +54,98 @@ The keywords supported for the preprocessor are:
|
|||||||
* endif
|
* endif
|
||||||
* pragma
|
* pragma
|
||||||
|
|
||||||
Each directive `#` line is considered one preproecessor unit, and will be treated as one Preprocessor AST.
|
Each directive `#` line is considered one preproecessor unit, and will be treated as one Preprocessor AST node.
|
||||||
If a directive is used with an unsupported keyword its will be processed as an untyped AST.
|
If a directive is used with an unsupported keyword its will be processed as an untyped AST.
|
||||||
|
|
||||||
The preprocessor lines are stored as members of their associated scope they are parsed within. ( Global, Namespace, Class/Struct )
|
The preprocessor lines are stored as members of their associated scope they are parsed within ( Global, Namespace, Class/Struct ).
|
||||||
***Again (Its not standard): These ASTs will be considered members or entries of braced scope they reside within***
|
***Again: These ASTs will be considered members or entries of braced scope they reside within***
|
||||||
|
|
||||||
Any preprocessor definition abuse that changes the syntax of the core language is unsupported and will fail to parse if not kept within an execution scope (function body, or expression assignment).
|
Any preprocessor definition abuse that changes the syntax of the core language is unsupported and will fail to parse if not kept within an execution scope (function body, or expression assignment).
|
||||||
Exceptions:
|
Exceptions:
|
||||||
|
|
||||||
* function signatures are allowed for a preprocessed macro: `neverinline MACRO() { ... }`
|
* varaible definitions are allowed for a preprocessed macro `extern MACRO();`
|
||||||
|
* function definitions are allowed for a preprocessed macro: `neverinline MACRO() { ... }`
|
||||||
* Disable with: `#define GEN_PARSER_DISABLE_MACRO_FUNCTION_SIGNATURES`
|
* Disable with: `#define GEN_PARSER_DISABLE_MACRO_FUNCTION_SIGNATURES`
|
||||||
* typedefs allow for a preprocessed macro: `typedef MACRO();`
|
* typedefs allow for a preprocessed macro: `typedef MACRO();`
|
||||||
* Disable with: `#define GEN_PARSER_DISABLE_MACRO_TYPEDEF`
|
* Disable with: `#define GEN_PARSER_DISABLE_MACRO_TYPEDEF`
|
||||||
* Macros can behave as typenames
|
* Macros can behave as typenames
|
||||||
* There is some macro support in paramters for functions or templates *(Specifically added to support parsing Unreal Engine source)*.
|
* There is some macro support in parameters for functions or templates *(Specifically added to support parsing Unreal Engine source)*.
|
||||||
|
|
||||||
*(Exceptions are added on an on-demand basis)*
|
*(Exceptions are added on an on-demand basis)*
|
||||||
*(See functions `parse_operator_function_or_variable` and `parse_typedef` )*
|
*(See functions `parse_operator_function_or_variable` and `parse_typedef` )*
|
||||||
|
|
||||||
Adding your own exceptions is possible by simply modifying the parser to allow for the syntax you need.
|
Adding your own exceptions is possible by simply modifying the parser to allow for the syntax you need.
|
||||||
|
|
||||||
*Note: You could interpret this strictness as a feature. This would allow the user to see if their codebase or a third-party's codebase some some egregious preprocessor abuse.*
|
*Note: You could interpret this strictness as a feature. This would allow the user to see if their codebase or a third-party's codebase contains some egregious preprocessor abuse.*
|
||||||
|
|
||||||
If a macro is not defined withint e scope of parsing a set of files, it can be defined beforehand by:
|
Macros used within a file should be registered by the user before parsing. This can be done two ways:
|
||||||
|
|
||||||
* Appending the [`PreprocessorDefines`](https://github.com/Ed94/gencpp/blob/a18b5b97aa5cfd20242065cbf53462a623cd18fa/base/components/header_end.hpp#L137) array.
|
1. The register macro interface within [interface.hpp](../base/components/interface.hpp).
|
||||||
* For functional macros a "(" just needs to be added after the name like: `<name>(` so that it will tokenize its arguments as part of the token during lexing.
|
2. Using `def_define` to create a CodeDefine and making sure to not set `opts.dont_register_to_preprocess_macros` to `true`.
|
||||||
* Defining a CodeDefine using `def_define`. The definition will be processed by the interface for user into `PreprocessorDefines`.
|
|
||||||
* This can be prevented by setting the optional prameter `dont_append_preprocess_defines`.
|
|
||||||
|
|
||||||
The lexing and parsing takes shortcuts from whats expected in the standard.
|
## Registering macros
|
||||||
|
|
||||||
|
While the registeration of macros in the meta-program's side for parsing can be considered tedius, its necessary for the parser to accurately resolve the macros intent in one pass (and it provides some hygenics by verifying that they are used as intended).
|
||||||
|
|
||||||
|
The following can be used to register a macro:
|
||||||
|
|
||||||
|
```c
|
||||||
|
GEN_API void register_macro( Macro macro );
|
||||||
|
GEN_API void register_macros( s32 num, ... );
|
||||||
|
GEN_API void register_macros_arr( s32 num, Macro* macros );
|
||||||
|
```
|
||||||
|
|
||||||
|
The Macro typename is defined with the following in [parser_types.hpp](../base/components/parser_types.hpp):
|
||||||
|
|
||||||
|
```c
|
||||||
|
struct Macro
|
||||||
|
{
|
||||||
|
StrCached Name;
|
||||||
|
MacroType Type;
|
||||||
|
MacroFlags Flags;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The macro can be designated one of the following types:
|
||||||
|
|
||||||
|
* `MT_Expression`: Intended to resolve to an expression expansion.
|
||||||
|
* `MT_Statement`: Intended to resolve an statement expansion.
|
||||||
|
* `MT_Typename`: Intended to resolve to a typename.
|
||||||
|
|
||||||
|
Additioonally tthe following flags may be set:
|
||||||
|
|
||||||
|
* `MF_Functional`: The macro intended to be passed arguments are at least have the calling `()` as part of its usage.
|
||||||
|
* `MF_Expects_Body`: The parser should expect a braced-body `{ ... }` after the macro signature `<name> <params>`
|
||||||
|
* `MF_Allow_As_Identifier`: Will allow the macro to be an acceptable token/s when an `Tok_Identifier` is expected.
|
||||||
|
* `MF_Allow_As_Attribute`: Will allow the macro to be an acceptable token/s when an attribute token/s is expected.
|
||||||
|
* `MF_Allow_As_Definition`: Will allow the macro be an acceptable token/s when the parser expects a declartion or definition to resolve after attributes or specifiers have been identified beforehand.
|
||||||
|
* This flag requires that the macro is of type `MT_Statement` to make any sense of usage.
|
||||||
|
|
||||||
|
If a macro is not defined the following warning will be issued if `GEN_BUILD_DEBUG=1` during lexing within [lexer.cpp](../base/components/lexer.cpp) - `lex_preprocessor_define`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
log_fmt("Warning: '%S' was not registered before the lexer processed its #define directive, it will be registered as a expression macro\n"
|
||||||
|
, name.Text
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Further within the same scope, the lexer will issue a warning if it detects a macro was not flagged as function but has an open parenthesis `(` token right after is name with no whitespace:
|
||||||
|
|
||||||
|
```c
|
||||||
|
log_fmt("Warning: %S registered macro is not flagged as functional yet the definition detects opening parenthesis '(' for arguments\n"
|
||||||
|
, name.Text
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Macros are tracked using a `MacroTable Macros;` defined as a member of the library's `Context`.
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef HashTable(Macro) MacroTable;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
* Empty lines used throughout the file are preserved for formatting purposes during ast serialization (they have a dedicated Token: `Tok_NewLine`).
|
||||||
* Numeric literals are not checked for validity.
|
* Numeric literals are not checked for validity.
|
||||||
* The parse API treats any execution scope definitions with no validation and are turned into untyped Code ASTs. (There is a [todo](https://github.com/Ed94/gencpp/issues/49) to add support)
|
* The parse API treats any execution scope definitions with no validation and are turned into untyped Code ASTs. (There is a [todo](https://github.com/Ed94/gencpp/issues/49) to add support)
|
||||||
* *This includes the assignment of variables.*
|
* *This includes the assignment of variables.*
|
||||||
@ -95,4 +156,4 @@ The lexing and parsing takes shortcuts from whats expected in the standard.
|
|||||||
* Parsing attributes can be extended to support user defined macros by defining `GEN_DEFINE_ATTRIBUTE_TOKENS` (see `gen.hpp` for the formatting)
|
* Parsing attributes can be extended to support user defined macros by defining `GEN_DEFINE_ATTRIBUTE_TOKENS` (see `gen.hpp` for the formatting)
|
||||||
* This is useful for example: parsing Unreal `Module_API` macros.
|
* This is useful for example: parsing Unreal `Module_API` macros.
|
||||||
|
|
||||||
Empty lines used throughout the file are preserved for formatting purposes during ast serialization.
|
**The lexer & parser do not gracefully attempt to continue when it comes across incorrect code, and doesn't properly track errors into a listing (yet).**
|
||||||
|
110
docs/Readme.md
110
docs/Readme.md
@ -26,7 +26,7 @@ This means that the typename entry for the parameter AST would be either:
|
|||||||
***Concepts and Constraints are not supported***
|
***Concepts and Constraints are not supported***
|
||||||
Its a [todo](https://github.com/Ed94/gencpp/issues/21)
|
Its a [todo](https://github.com/Ed94/gencpp/issues/21)
|
||||||
|
|
||||||
### Feature Macros:
|
### Feature Macros
|
||||||
|
|
||||||
* `GEN_DEFINE_ATTRIBUTE_TOKENS` : Allows user to define their own attribute macros for use in parsing.
|
* `GEN_DEFINE_ATTRIBUTE_TOKENS` : Allows user to define their own attribute macros for use in parsing.
|
||||||
* This can be generated using base.cpp.
|
* This can be generated using base.cpp.
|
||||||
@ -36,10 +36,41 @@ Its a [todo](https://github.com/Ed94/gencpp/issues/21)
|
|||||||
* `GEN_EXPOSE_BACKEND` : Will expose symbols meant for internal use only.
|
* `GEN_EXPOSE_BACKEND` : Will expose symbols meant for internal use only.
|
||||||
* `GEN_ROLL_OWN_DEPENDENCIES` : Optional override so that user may define the dependencies themselves.
|
* `GEN_ROLL_OWN_DEPENDENCIES` : Optional override so that user may define the dependencies themselves.
|
||||||
* `GEN_DONT_ALLOW_INVALID_CODE` (Not implemented yet) : Will fail when an invalid code is constructed, parsed, or serialized.
|
* `GEN_DONT_ALLOW_INVALID_CODE` (Not implemented yet) : Will fail when an invalid code is constructed, parsed, or serialized.
|
||||||
* `GEN_C_LIKE_PP` : Setting to `<true or 1>` Will prevent usage of function defnitions using references and structs with member functions. Structs will still have user-defined operator conversions, for-range support, and other operator overloads
|
* `GEN_C_LIKE_CPP` : Setting to `<true or 1>` Will prevent usage of function defnitions using references and structs with member functions. Structs will still have user-defined operator conversions, for-range support, and other operator overloads
|
||||||
|
|
||||||
### The Data & Interface
|
### The Data & Interface
|
||||||
|
|
||||||
|
The library's persistent state is managed tracked by a context struct: `global Context* _ctx;` defined within [static_data.cpp](../base/components/static_data.cpp)
|
||||||
|
|
||||||
|
https://github.com/Ed94/gencpp/blob/967a044637f1615c709cb723dc61118fcc08dcdb/base/components/interface.hpp#L39-L97
|
||||||
|
|
||||||
|
The interface for the context:
|
||||||
|
|
||||||
|
* `init`: Initializtion
|
||||||
|
* `deinit`: De-initialization.
|
||||||
|
* `reset`: Clears the allocations, but doesn't free the memoery, then calls `init()` on `_ctx` again.
|
||||||
|
* `get_context`: Retreive the currently tracked context.
|
||||||
|
* `set_context`: Swap out the current tracked context.
|
||||||
|
|
||||||
|
|
||||||
|
#### Allocato usage
|
||||||
|
|
||||||
|
* `Allocator_DyanmicContainers`: Growing arrays, hash tables. (Unbounded sized containers)
|
||||||
|
* `Allocator_Pool`: Fixed-sized object allocations (ASTs, etc)
|
||||||
|
* `Allocator_StrCache`: StrCached allocations
|
||||||
|
* `Allocator_Temp`: Temporary alloations mostly intended for StrBuilder usage. Manually cleared by the user by their own discretion.
|
||||||
|
|
||||||
|
The allocator definitions used are exposed to the user incase they want to dictate memory usage
|
||||||
|
|
||||||
|
* Allocators are defined with the `AllocatorInfo` structure found in [`memory.hpp`](../base/dependencies/memory.hpp)
|
||||||
|
* Most of the work is just defining the allocation procedure:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void* ( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags );
|
||||||
|
```
|
||||||
|
|
||||||
|
For any allocator above that the user does not define before `init`, a fallback allocator will be assigned that utiizes the `fallback_allocator_proc` wtihin [interface.cpp](../base/components/interface.cpp).
|
||||||
|
|
||||||
As mentioned in root readme, the user is provided Code objects by calling the constructor's functions to generate them or find existing matches.
|
As mentioned in root readme, the user is provided Code objects by calling the constructor's functions to generate them or find existing matches.
|
||||||
|
|
||||||
The AST is managed by the library and provided to the user via its interface.
|
The AST is managed by the library and provided to the user via its interface.
|
||||||
@ -47,14 +78,14 @@ However, the user may specifiy memory configuration.
|
|||||||
|
|
||||||
[Data layout of AST struct (Subject to heavily change with upcoming todos)](../base/components/ast.hpp#L396-461)
|
[Data layout of AST struct (Subject to heavily change with upcoming todos)](../base/components/ast.hpp#L396-461)
|
||||||
|
|
||||||
https://github.com/Ed94/gencpp/blob/eea4ebf5c40d5d87baa465abfb1be30845b2377e/base/components/ast.hpp#L396-L461
|
https://github.com/Ed94/gencpp/blob/967a044637f1615c709cb723dc61118fcc08dcdb/base/components/ast.hpp#L369-L435
|
||||||
|
|
||||||
*`StringCahced` is a typedef for `Str` (a string slice), to denote it is an interned string*
|
*`StringCahced` is a typedef for `Str` (a string slice), to denote it is an interned string*
|
||||||
*`CodeType` is enum taggin the type of code. Has an underlying type of `u32`*
|
*`CodeType` is enum taggin the type of code. Has an underlying type of `u32`*
|
||||||
*`OperatorT` is a typedef for `EOperator::Type` which has an underlying type of `u32`*
|
*`OperatorT` is a typedef for `EOperator::Type` which has an underlying type of `u32`*
|
||||||
*`StrBuilder` is the dynamically allocated string type for the library*
|
*`StrBuilder` is the dynamically allocating string builder type for the library*
|
||||||
|
|
||||||
AST widths are setup to be AST_POD_Size.
|
AST widths are setup to be AST_POD_Size (128 bytes by default).
|
||||||
The width dictates how much the static array can hold before it must give way to using an allocated array:
|
The width dictates how much the static array can hold before it must give way to using an allocated array:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
@ -73,41 +104,16 @@ int AST_ArrSpecs_Cap =
|
|||||||
)
|
)
|
||||||
/ sizeof(Specifier) - 1;
|
/ sizeof(Specifier) - 1;
|
||||||
```
|
```
|
||||||
|
|
||||||
*Ex: If the AST_POD_Size is 128 the capacity of the static array is 20.*
|
|
||||||
|
|
||||||
Data Notes:
|
Data Notes:
|
||||||
|
|
||||||
* The allocator definitions used are exposed to the user incase they want to dictate memory usage
|
|
||||||
* You'll find the memory handling in `init`, `deinit`, `reset`, `gen_strbuilder_allocator`, `cache_str`, `make_code`.
|
|
||||||
* Allocators are defined with the `AllocatorInfo` structure found in [`memory.hpp`](../base/dependencies/memory.hpp)
|
|
||||||
* Most of the work is just defining the allocation procedure:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void* ( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags );
|
|
||||||
```
|
|
||||||
|
|
||||||
* ASTs are wrapped for the user in a Code struct which is a wrapper for a AST* type.
|
* ASTs are wrapped for the user in a Code struct which is a wrapper for a AST* type.
|
||||||
* Code types have member symbols but their data layout is enforced to be POD types.
|
* Code types have member symbols but their data layout is enforced to be POD types.
|
||||||
* This library treats memory failures as fatal.
|
* This library treats memory failures as fatal.
|
||||||
* Cached Strings are stored in their own set of arenas. AST constructors use cached strings for names, and content.
|
* Cached Strings are stored in their own set of arenas. AST constructors use cached strings for names, and content.
|
||||||
* `StringArenas`, `StringCache`, `Allocator_StringArena`, and `Allocator_StringTable` are the associated containers or allocators.
|
|
||||||
* Strings used for serialization and file buffers are not contained by those used for cached strings.
|
* Strings used for serialization and file buffers are not contained by those used for cached strings.
|
||||||
* They are currently using `FallbackAllocator`, which are tracked array of arenas that grows as needed (adds buckets when one runs out).
|
* `_ctx->Allocator_Temp` is used.
|
||||||
* Memory within the buckets is not reused, so its inherently wasteful.
|
|
||||||
* I will be augmenting the default allocator with virtual memory & a slab allocator in the [future](https://github.com/Ed94/gencpp/issues/12)
|
|
||||||
* Intrusive linked lists used children nodes on bodies, and parameters.
|
|
||||||
* Its intended to generate the AST in one go and serialize after. The constructors and serializer are designed to be a "one pass, front to back" setup.
|
* Its intended to generate the AST in one go and serialize after. The constructors and serializer are designed to be a "one pass, front to back" setup.
|
||||||
* Allocations can be tuned by defining the folloiwng macros (will be moved to runtime configuration in the future):
|
* Any modifcations to an existing AST should be to just construct another with the modifications done on-demand while traversing the AST (non-destructive).
|
||||||
* `GEN_GLOBAL_BUCKET_SIZE` : Size of each bucket area for the global allocator
|
|
||||||
* `GEN_CODEPOOL_NUM_BLOCKS` : Number of blocks per code pool in the code allocator
|
|
||||||
* `GEN_SIZE_PER_STRING_ARENA` : Size per arena used with string caching.
|
|
||||||
* `GEN_MAX_COMMENT_LINE_LENGTH` : Longest length a comment can have per line.
|
|
||||||
* `GEN_MAX_NAME_LENGTH` : Max length of any identifier.
|
|
||||||
* `GEN_MAX_UNTYPED_STR_LENGTH` : Max content length for any untyped code.
|
|
||||||
* `TokenMap_FixedArena` : token_fmt_va uses local_persit memory of this arena type for the hashtable.
|
|
||||||
* `GEN_LEX_ALLOCATOR_SIZE`
|
|
||||||
* `GEN_BUILDER_STR_BUFFER_RESERVE`
|
|
||||||
|
|
||||||
The following CodeTypes are used which the user may optionally use strong typing with if they enable: `GEN_ENFORCE_STRONG_CODE_TYPES`
|
The following CodeTypes are used which the user may optionally use strong typing with if they enable: `GEN_ENFORCE_STRONG_CODE_TYPES`
|
||||||
|
|
||||||
@ -117,6 +123,7 @@ The following CodeTypes are used which the user may optionally use strong typing
|
|||||||
* CodeClass
|
* CodeClass
|
||||||
* CodeConstructor
|
* CodeConstructor
|
||||||
* CodeDefine
|
* CodeDefine
|
||||||
|
* CodeDefineParams
|
||||||
* CodeDestructor
|
* CodeDestructor
|
||||||
* CodeEnum
|
* CodeEnum
|
||||||
* CodeExec
|
* CodeExec
|
||||||
@ -127,7 +134,7 @@ The following CodeTypes are used which the user may optionally use strong typing
|
|||||||
* CodeModule
|
* CodeModule
|
||||||
* CodeNS
|
* CodeNS
|
||||||
* CodeOperator
|
* CodeOperator
|
||||||
* CodeOpCast
|
* CodeOpCast : User defined member operator conversion
|
||||||
* CodeParams : Has support for `for : range` iterating across parameters.
|
* CodeParams : Has support for `for : range` iterating across parameters.
|
||||||
* CodePreprocessCond
|
* CodePreprocessCond
|
||||||
* CodePragma
|
* CodePragma
|
||||||
@ -140,11 +147,15 @@ The following CodeTypes are used which the user may optionally use strong typing
|
|||||||
* CodeUsing
|
* CodeUsing
|
||||||
* CodeVar
|
* CodeVar
|
||||||
|
|
||||||
Each Code boy has an associated "filtered AST" with the naming convention: `AST_<CodeName>`
|
Each `struct Code<Name>` has an associated "filtered AST" with the naming convention: `AST_<CodeName>`
|
||||||
Unrelated fields of the AST for that node type are omitted and only necessary padding members are defined otherwise.
|
Unrelated fields of the AST for that node type are omitted and only necessary padding members are defined otherwise.
|
||||||
Retrieving a raw version of the ast can be done using the `raw()` function defined in each AST.
|
|
||||||
|
|
||||||
## There are three sets of interfaces for Code AST generation the library provides
|
For the interface related to these code types see:
|
||||||
|
|
||||||
|
* [ast.hpp](../base/components/ast.hpp): Under the region pragma `Code C-Interface`
|
||||||
|
* [code_types.hpp](../base/components/code_types.hpp): Under the region pragma `Code C-Interface`. Additional functionlity for c++ will be within the struct definitions or at the end of the file.
|
||||||
|
|
||||||
|
## There are three categories of interfaces for Code AST generation & reflection
|
||||||
|
|
||||||
* Upfront
|
* Upfront
|
||||||
* Parsing
|
* Parsing
|
||||||
@ -164,6 +175,7 @@ Interface :``
|
|||||||
* def_class
|
* def_class
|
||||||
* def_constructor
|
* def_constructor
|
||||||
* def_define
|
* def_define
|
||||||
|
* def_define_params
|
||||||
* def_destructor
|
* def_destructor
|
||||||
* def_enum
|
* def_enum
|
||||||
* def_execution
|
* def_execution
|
||||||
@ -218,6 +230,27 @@ Code <name>
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
All optional parmeters are defined within `struct Opts_def_<functon name>`. This was done to setup a [macro trick](https://x.com/vkrajacic/status/1749816169736073295) for default optional parameers in the C library:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct gen_Opts_def_struct
|
||||||
|
{
|
||||||
|
gen_CodeBody body;
|
||||||
|
gen_CodeTypename parent;
|
||||||
|
gen_AccessSpec parent_access;
|
||||||
|
gen_CodeAttributes attributes;
|
||||||
|
gen_CodeTypename* interfaces;
|
||||||
|
gen_s32 num_interfaces;
|
||||||
|
gen_ModuleFlag mflags;
|
||||||
|
};
|
||||||
|
typedef struct gen_Opts_def_struct gen_Opts_def_struct;
|
||||||
|
|
||||||
|
GEN_API gen_CodeClass gen_def__struct( gen_Str name, gen_Opts_def_struct opts GEN_PARAM_DEFAULT );
|
||||||
|
#define gen_def_struct( name, ... ) gen_def__struct( name, ( gen_Opts_def_struct ) { __VA_ARGS__ } )
|
||||||
|
```
|
||||||
|
|
||||||
|
In the C++ library, the `def_<funtion name>` is not wrapped in a macro.
|
||||||
|
|
||||||
When using the body functions, its recommended to use the args macro to auto determine the number of arguments for the varadic:
|
When using the body functions, its recommended to use the args macro to auto determine the number of arguments for the varadic:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
@ -228,7 +261,7 @@ def_global_body( 3, ht_entry, array_ht_entry, hashtable );
|
|||||||
```
|
```
|
||||||
|
|
||||||
If a more incremental approach is desired for the body ASTs, `Code def_body( CodeT type )` can be used to create an empty body.
|
If a more incremental approach is desired for the body ASTs, `Code def_body( CodeT type )` can be used to create an empty body.
|
||||||
When the members have been populated use: `AST::validate_body` to verify that the members are valid entires for that type.
|
When the members have been populated use: `code_validate_body` to verify that the members are valid entires for that type.
|
||||||
|
|
||||||
### Parse construction
|
### Parse construction
|
||||||
|
|
||||||
@ -238,12 +271,12 @@ Interface :
|
|||||||
|
|
||||||
* parse_class
|
* parse_class
|
||||||
* parse_constructor
|
* parse_constructor
|
||||||
|
* parse_define
|
||||||
* parse_destructor
|
* parse_destructor
|
||||||
* parse_enum
|
* parse_enum
|
||||||
* parse_export_body
|
* parse_export_body
|
||||||
* parse_extern_link
|
* parse_extern_link
|
||||||
* parse_friend
|
* parse_friend
|
||||||
* Purposefully are only support forward declares with this constructor.
|
|
||||||
* parse_function
|
* parse_function
|
||||||
* parse_global_body
|
* parse_global_body
|
||||||
* parse_namespace
|
* parse_namespace
|
||||||
@ -322,6 +355,7 @@ Code <name> = parse_<function name>( gen_code_str );
|
|||||||
|
|
||||||
The following are provided predefined by the library as they are commonly used:
|
The following are provided predefined by the library as they are commonly used:
|
||||||
|
|
||||||
|
* `enum_underlying_macro`
|
||||||
* `access_public`
|
* `access_public`
|
||||||
* `access_protected`
|
* `access_protected`
|
||||||
* `access_private`
|
* `access_private`
|
||||||
|
BIN
docs/assets/Code_-_Insiders_2024-12-15_22-52-13.gif
Normal file
BIN
docs/assets/Code_-_Insiders_2024-12-15_22-52-13.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 150 KiB |
BIN
docs/assets/Code_-_Insiders_2024-12-15_22-57-58.gif
Normal file
BIN
docs/assets/Code_-_Insiders_2024-12-15_22-57-58.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 250 KiB |
BIN
docs/assets/Code_-_Insiders_2024-12-15_23-04-07.gif
Normal file
BIN
docs/assets/Code_-_Insiders_2024-12-15_23-04-07.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 175 KiB |
BIN
docs/assets/rider64_2024-12-16_17-22-16.mp4
Normal file
BIN
docs/assets/rider64_2024-12-16_17-22-16.mp4
Normal file
Binary file not shown.
@ -1,7 +1,5 @@
|
|||||||
## Navigation
|
## Navigation
|
||||||
|
|
||||||
# base
|
|
||||||
|
|
||||||
[Top](../Readme.md)
|
[Top](../Readme.md)
|
||||||
|
|
||||||
* [docs](../docs/Readme.md)
|
* [docs](../docs/Readme.md)
|
||||||
@ -15,9 +13,133 @@ The output will be in the `gen_segmented/gen` directory (if the directory does n
|
|||||||
If using the library's provided build scripts:
|
If using the library's provided build scripts:
|
||||||
|
|
||||||
```ps1
|
```ps1
|
||||||
.\build.ps1 <compiler> <debug or omit> c_library
|
.\build.ps1 <compiler> <debug or omit> c_lib
|
||||||
|
```
|
||||||
|
|
||||||
|
To generate a static or dynamic library:
|
||||||
|
|
||||||
|
```ps1
|
||||||
|
.\build.ps1 <compiler> <debug or omit> c_lib_static c_lib_dyn
|
||||||
```
|
```
|
||||||
|
|
||||||
All free from tag identifiers will be prefixed with `gen_` or `GEN_` as the namespace. This can either be changed after generation with a `.refactor` script (or your preferred subst method), OR by modifying [c_library.refactor](./c_library.refactor).
|
All free from tag identifiers will be prefixed with `gen_` or `GEN_` as the namespace. This can either be changed after generation with a `.refactor` script (or your preferred subst method), OR by modifying [c_library.refactor](./c_library.refactor).
|
||||||
|
|
||||||
**If c_library.refactor is modified you may need to modify c_library.cpp and its [components](./components/). As some of the container generation relies on that prefix.**
|
**If c_library.refactor is modified you may need to modify c_library.cpp and its [components](./components/). As some of the container generation relies on that prefix.**
|
||||||
|
|
||||||
|
## Generation structure
|
||||||
|
|
||||||
|
1. Files are scanned in or parsed.
|
||||||
|
* If they are parsed, its dude to requiring some changes to either naming, or adding additonal definitions (container generation, typedefs, etc).
|
||||||
|
2. All scanned or parsed code is refactored (identifiers substs) and/or formatted.
|
||||||
|
3. Singleheader generated.
|
||||||
|
4. Segemented headers and source generated.
|
||||||
|
|
||||||
|
## Templated container generation
|
||||||
|
|
||||||
|
The array and hashtable containers used across this library are generated using the following implementatioon:
|
||||||
|
|
||||||
|
* [containers.array.hpp](./components/containers.array.hpp)
|
||||||
|
* [containers.hashtable.hpp](./components/containers.hashtable.hpp)
|
||||||
|
|
||||||
|
These are functionally (and interface wise) equivalent to the library's `Array<Type>` `HashTable<Type>` within [containers.hpp](../base/dependencies/containers.hpp)
|
||||||
|
|
||||||
|
Both files follow the same patter of providing three procedures:
|
||||||
|
|
||||||
|
* `gen_<container>_base` : Intended to be called once, defines universal "base" definitions.
|
||||||
|
* `gen_<container>` : Called per instatiation of the container for a given set of dependent args.
|
||||||
|
* `gen_<container>_generic_selection_interface` : Intended to be called once after all of the instantiated containers have finished generating. It will generate a set of generic selection macros as described by Macro Usage section below.
|
||||||
|
|
||||||
|
A simple `<container>_DefinitionCounter` is used to know how many instantiations of the template have occured. This is used to determine how to define `GENERIC_SLOT_<ID>_<functionID>` for the generic interface along with how many slots the `_Generic` macro will need to have generated.
|
||||||
|
|
||||||
|
## Macro Usage
|
||||||
|
|
||||||
|
For the most part macros are kept minimal with exception to `_Generic`...
|
||||||
|
*(I will be explaining this thing for the rest of this seciton along with gencpp c library's usage of it)*
|
||||||
|
|
||||||
|
The `_Generic` macro plays a key role in reducing direct need of the user to wrangle with mangled definition identifiers of 'templated' containers or for type coercion to map distinct data types to a common code path.
|
||||||
|
|
||||||
|
Because of its lack of use in many C11 libraries.. and, of those that do; they usually end up obfuscating it with excessive preprocessor abuse; Effort was put into minimizing how much of these macros are handled by the preprocessor vs gencpp itself.
|
||||||
|
|
||||||
|
The usual presentation (done bare) is the following:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define macro_that_selects_typeof_arg(arg, y) \
|
||||||
|
_Generic( (arg), \
|
||||||
|
int : some expression, \
|
||||||
|
double : some other expression, \
|
||||||
|
struct Whatnot : something else again, \
|
||||||
|
default : fallback expression \
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Where `_Generic` can be considered the follwoing (psuedo-C):
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define type_expr_pair(type, expr) type: expr
|
||||||
|
|
||||||
|
C_Expression _Generic( selector_arg, a_type_expr_pair, ... ) {
|
||||||
|
switch( typeof(selector_arg)) {
|
||||||
|
case a_type_expr_pair:
|
||||||
|
return a_type_expr_pari.expr;
|
||||||
|
...
|
||||||
|
default:
|
||||||
|
return default.expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The first `arg` of _Generic behaves as the "controlling expression" or the expression that resolves to a type which will dictate which of the following expressions provided after to `_Generic` will be resolved as the one used inline for the implemenation.
|
||||||
|
|
||||||
|
|
||||||
|
For this library's purposes we'll be using the functional macro equivalent *(if there is an exception I'll link it at the end of this section)*:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define macro_that_uses_selector_arg_for_resolving_a_fucntion( selecting_exp) \
|
||||||
|
_Generic( (arg), \
|
||||||
|
int : func_use_int, \
|
||||||
|
double : func_use_double, \
|
||||||
|
struct Whatnot : func_use_Whatnot, \
|
||||||
|
default : struct SIGNALS_FAILURE \
|
||||||
|
) (selecting_exp)
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, we directly added `(selecting_exp)` to the end there.. as we want to directly have the macro resolve to calling a resolved procedure. A default has been set to a struct as that leads to a neat compiler message that would otherwise be impossible beause static_assert is a statement and thus cannot be used within a slot.
|
||||||
|
|
||||||
|
Now, even with gencpp generating this type-expression table, we still need wrapper macros to achieve function 'overloading' for the templated containers as _Generic has a [significant drawback](https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/):
|
||||||
|
|
||||||
|
> Discarded expressions still have to be semantically valid.
|
||||||
|
|
||||||
|
The only way to absolve this issue [(without resorting to nasty preprocessor hacks)](https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md) is with wrapping expressions in 'slot' resolving macros that do not expand if the slot is not defined:
|
||||||
|
|
||||||
|
```c
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__function_sig )
|
||||||
|
```
|
||||||
|
|
||||||
|
`GENERIC_SLOT_1__function_sig` is our warpper of a "`int, func_use_int`" pair. The `GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT` is a verbse named macro to indicate that that pair will be expanded ***ONLY IF*** its defined.
|
||||||
|
|
||||||
|
So for any given templated container interface. Expect the follwoing (taken straight from generation, and just cleaned up formatting):
|
||||||
|
|
||||||
|
```c
|
||||||
|
#define gen_array_append( selector_arg, ... ) _Generic( \
|
||||||
|
(selector_arg ), \
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_1__array_append ) \
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_2__array_append ) \
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_3__array_append ) \
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_4__array_append ) \
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_5__array_append ) \
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_6__array_append ) \
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_7__array_append ) \
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_8__array_append ) \
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_9__array_append ) \
|
||||||
|
GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GEN_GENERIC_SLOT_10__array_append ) \
|
||||||
|
default: gen_generic_selection_fail \
|
||||||
|
) GEN_RESOLVED_FUNCTION_CALL( &selector_arg, __VA_ARGS__ )
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
*Note(Ed): Unfortunately I cannot get clang-format to output these macros sanely like the above..*
|
||||||
|
*Eventually I'll add some basic builtin formatting but if the user has suggestions for something better I'm open ears...*
|
||||||
|
|
||||||
|
`GEN_RESOLVED_FUNCTION_CALL` is an empty define, its just to indicate that its intended to expand to a function call.
|
||||||
|
|
||||||
|
To see the the actual macro definitions used - see: [generic_macros.h](./components/generic_macros.h). They'll be injected right after the usual macros in the generated header file.
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||||
#define GEN_EXPOSE_BACKEND
|
|
||||||
#include "gen.cpp"
|
#include "gen.cpp"
|
||||||
#include "helpers/push_ignores.inline.hpp"
|
#include "helpers/push_ignores.inline.hpp"
|
||||||
|
|
||||||
@ -65,122 +64,122 @@ int gen_main()
|
|||||||
Context ctx {};
|
Context ctx {};
|
||||||
gen::init(& ctx);
|
gen::init(& ctx);
|
||||||
|
|
||||||
register_preprocess_macros( args(
|
register_macros( args(
|
||||||
(PreprocessorMacro { txt("bit"), MT_Expression, MF_Functional }),
|
(Macro { txt("bit"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("bitfield_is_set"), MT_Expression, MF_Functional }),
|
(Macro { txt("bitfield_is_set"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("GEN_C_LIKE_CPP"), MT_Expression, MF_Null }),
|
(Macro { txt("GEN_C_LIKE_CPP"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("cast"), MT_Expression, MF_Functional }),
|
(Macro { txt("cast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("ccast"), MT_Expression, MF_Functional }),
|
(Macro { txt("ccast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("rcast"), MT_Expression, MF_Functional }),
|
(Macro { txt("rcast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("pcast"), MT_Expression, MF_Functional }),
|
(Macro { txt("pcast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("scast"), MT_Expression, MF_Functional }),
|
(Macro { txt("scast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("stringize_va"), MT_Expression, MF_Functional }),
|
(Macro { txt("stringize_va"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("stringize"), MT_Expression, MF_Functional }),
|
(Macro { txt("stringize"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("do_once"), MT_Expression, MF_Functional }),
|
(Macro { txt("do_once"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("do_once_defer"), MT_Expression, MF_Functional }),
|
(Macro { txt("do_once_defer"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("do_once_start"), MT_Statement, MF_Null }),
|
(Macro { txt("do_once_start"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("do_once_end"), MT_Statement, MF_Null }),
|
(Macro { txt("do_once_end"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("labeled_scope_start"), MT_Statement, MF_Null }),
|
(Macro { txt("labeled_scope_start"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("labeled_scope_end"), MT_Statement, MF_Null }),
|
(Macro { txt("labeled_scope_end"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("compiler_decorated_func_name"), MT_Expression, MF_Null }),
|
(Macro { txt("compiler_decorated_func_name"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("num_args_impl"), MT_Expression, MF_Functional }),
|
(Macro { txt("num_args_impl"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("num_args"), MT_Expression, MF_Functional }),
|
(Macro { txt("num_args"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("count_of"), MT_Expression, MF_Functional }),
|
(Macro { txt("count_of"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("clamp"), MT_Expression, MF_Functional }),
|
(Macro { txt("clamp"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("is_between"), MT_Expression, MF_Functional }),
|
(Macro { txt("is_between"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("size_of"), MT_Expression, MF_Functional }),
|
(Macro { txt("size_of"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("min"), MT_Expression, MF_Functional }),
|
(Macro { txt("min"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("max"), MT_Expression, MF_Functional }),
|
(Macro { txt("max"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("offset_of"), MT_Expression, MF_Functional }),
|
(Macro { txt("offset_of"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("static_assert"), MT_Statement, MF_Functional }),
|
(Macro { txt("static_assert"), MT_Statement, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("typeof"), MT_Expression, MF_Null }),
|
(Macro { txt("typeof"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN_API_C_BEGIN"), MT_Statement, MF_Null }),
|
(Macro { txt("GEN_API_C_BEGIN"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN_API_C_END"), MT_Statement, MF_Null }),
|
(Macro { txt("GEN_API_C_END"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("nullptr"), MT_Expression, MF_Null }),
|
(Macro { txt("nullptr"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN_REMOVE_PTR"), MT_Expression, MF_Functional }),
|
(Macro { txt("GEN_REMOVE_PTR"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("GEN_PARAM_DEFAULT"), MT_Expression, MF_Null }),
|
(Macro { txt("GEN_PARAM_DEFAULT"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("struct_init"), MT_Expression, MF_Functional }),
|
(Macro { txt("struct_init"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("GEN_OPTIMIZE_MAPPINGS_BEGIN"), MT_Statement, MF_Null }),
|
(Macro { txt("GEN_OPTIMIZE_MAPPINGS_BEGIN"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN_OPITMIZE_MAPPINGS_END"), MT_Statement, MF_Null }),
|
(Macro { txt("GEN_OPITMIZE_MAPPINGS_END"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("Array"), MT_Typename, MF_Functional }),
|
(Macro { txt("Array"), MT_Typename, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("HashTable"), MT_Typename, MF_Functional }),
|
(Macro { txt("HashTable"), MT_Typename, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("Using_Code"), MT_Statement, MF_Functional }),
|
(Macro { txt("Using_Code"), MT_Statement, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("Using_CodeOps"), MT_Statement, MF_Functional }),
|
(Macro { txt("Using_CodeOps"), MT_Statement, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("kilobytes"), MT_Expression, MF_Functional }),
|
(Macro { txt("kilobytes"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("megabytes"), MT_Expression, MF_Functional }),
|
(Macro { txt("megabytes"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("gigabytes"), MT_Expression, MF_Functional }),
|
(Macro { txt("gigabytes"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("terabytes"), MT_Expression, MF_Functional }),
|
(Macro { txt("terabytes"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("GEN__ONES"), MT_Expression, MF_Null }),
|
(Macro { txt("GEN__ONES"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN__HIGHS"), MT_Expression, MF_Null }),
|
(Macro { txt("GEN__HIGHS"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN__HAS_ZERO"), MT_Expression, MF_Functional }),
|
(Macro { txt("GEN__HAS_ZERO"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("zero_item"), MT_Expression, MF_Functional }),
|
(Macro { txt("zero_item"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("zero_array"), MT_Expression, MF_Functional }),
|
(Macro { txt("zero_array"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("GEN_DEFAULT_MEMORY_ALIGNMENT"), MT_Expression, MF_Null }),
|
(Macro { txt("GEN_DEFAULT_MEMORY_ALIGNMENT"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN_DEFAULT_ALLOCATOR_FLAGS"), MT_Expression, MF_Null }),
|
(Macro { txt("GEN_DEFAULT_ALLOCATOR_FLAGS"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("alloc_item"), MT_Expression, MF_Functional }),
|
(Macro { txt("alloc_item"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("alloc_array"), MT_Expression, MF_Functional }),
|
(Macro { txt("alloc_array"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("malloc"), MT_Expression, MF_Functional }),
|
(Macro { txt("malloc"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("mfree"), MT_Expression, MF_Functional }),
|
(Macro { txt("mfree"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("GEN_PRINTF_MAXLEN"), MT_Expression, MF_Null }),
|
(Macro { txt("GEN_PRINTF_MAXLEN"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("cast_to_str"), MT_Expression, MF_Functional }),
|
(Macro { txt("cast_to_str"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("current"), MT_Expression, MF_Null }),
|
(Macro { txt("current"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("txt"), MT_Expression, MF_Functional }),
|
(Macro { txt("txt"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("GEN_FILE_OPEN_PROC"), MT_Statement, MF_Functional | MF_Expects_Body }),
|
(Macro { txt("GEN_FILE_OPEN_PROC"), MT_Statement, MF_Functional | MF_Expects_Body }),
|
||||||
(PreprocessorMacro { txt("GEN_FILE_READ_AT_PROC"), MT_Statement, MF_Functional | MF_Expects_Body }),
|
(Macro { txt("GEN_FILE_READ_AT_PROC"), MT_Statement, MF_Functional | MF_Expects_Body }),
|
||||||
(PreprocessorMacro { txt("GEN_FILE_WRITE_AT_PROC"), MT_Statement, MF_Functional | MF_Expects_Body }),
|
(Macro { txt("GEN_FILE_WRITE_AT_PROC"), MT_Statement, MF_Functional | MF_Expects_Body }),
|
||||||
(PreprocessorMacro { txt("GEN_FILE_SEEK_PROC"), MT_Statement, MF_Functional | MF_Expects_Body }),
|
(Macro { txt("GEN_FILE_SEEK_PROC"), MT_Statement, MF_Functional | MF_Expects_Body }),
|
||||||
(PreprocessorMacro { txt("GEN_FILE_CLOSE_PROC"), MT_Statement, MF_Functional | MF_Expects_Body }),
|
(Macro { txt("GEN_FILE_CLOSE_PROC"), MT_Statement, MF_Functional | MF_Expects_Body }),
|
||||||
(PreprocessorMacro { txt("log_failure"), MT_Expression, MF_Null }),
|
(Macro { txt("log_failure"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("operator"), MT_Expression, MF_Null }),
|
(Macro { txt("operator"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("InvalidCode"), MT_Expression, MF_Null }),
|
(Macro { txt("InvalidCode"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("NullCode"), MT_Expression, MF_Null }),
|
(Macro { txt("NullCode"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("Verify_POD"), MT_Expression, MF_Functional }),
|
(Macro { txt("Verify_POD"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("gen_main"), MT_Statement, MF_Null })
|
(Macro { txt("gen_main"), MT_Statement, MF_Null })
|
||||||
));
|
));
|
||||||
register_preprocess_macros( args(
|
register_macros( args(
|
||||||
(PreprocessorMacro { txt("name"), MT_Expression, MF_Functional }),
|
(Macro { txt("name"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("code"), MT_Expression, MF_Functional }),
|
(Macro { txt("code"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("args"), MT_Expression, MF_Functional }),
|
(Macro { txt("args"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("code_str"), MT_Expression, MF_Functional }),
|
(Macro { txt("code_str"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("code_fmt"), MT_Expression, MF_Functional }),
|
(Macro { txt("code_fmt"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("parse_fmt"), MT_Expression, MF_Functional }),
|
(Macro { txt("parse_fmt"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("token_fmt"), MT_Expression, MF_Functional }),
|
(Macro { txt("token_fmt"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("check_member_val"), MT_Expression, MF_Functional }),
|
(Macro { txt("check_member_val"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("check_member_str"), MT_Expression, MF_Functional }),
|
(Macro { txt("check_member_str"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("check_member_content"), MT_Expression, MF_Functional }),
|
(Macro { txt("check_member_content"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("check_member_ast"), MT_Expression, MF_Functional }),
|
(Macro { txt("check_member_ast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("check_params"), MT_Expression, MF_Functional }),
|
(Macro { txt("check_params"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("check_param_eq_ret"), MT_Expression, MF_Functional }),
|
(Macro { txt("check_param_eq_ret"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("specs"), MT_Expression, MF_Functional | MF_Allow_As_Identifier }),
|
(Macro { txt("specs"), MT_Expression, MF_Functional | MF_Allow_As_Identifier }),
|
||||||
(PreprocessorMacro { txt("name_check"), MT_Expression, MF_Functional }),
|
(Macro { txt("name_check"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("null_check"), MT_Expression, MF_Functional }),
|
(Macro { txt("null_check"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("def_body_start"), MT_Expression, MF_Functional }),
|
(Macro { txt("def_body_start"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("def_body_code_array_start"), MT_Expression, MF_Functional }),
|
(Macro { txt("def_body_code_array_start"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("move_forward"), MT_Expression, MF_Functional }),
|
(Macro { txt("move_forward"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("skip_whitespace"), MT_Expression, MF_Functional }),
|
(Macro { txt("skip_whitespace"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("end_line"), MT_Expression, MF_Functional }),
|
(Macro { txt("end_line"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("check_parse_args"), MT_Expression, MF_Functional }),
|
(Macro { txt("check_parse_args"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("currtok_noskip"), MT_Expression, MF_Null }),
|
(Macro { txt("currtok_noskip"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("currtok"), MT_Expression, MF_Null }),
|
(Macro { txt("currtok"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("peektok"), MT_Expression, MF_Null }),
|
(Macro { txt("peektok"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("prevtok"), MT_Expression, MF_Null }),
|
(Macro { txt("prevtok"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("nexttok"), MT_Expression, MF_Null }),
|
(Macro { txt("nexttok"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("nexttok_noskip"), MT_Expression, MF_Null }),
|
(Macro { txt("nexttok_noskip"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("eat"), MT_Expression, MF_Functional }),
|
(Macro { txt("eat"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("left"), MT_Expression, MF_Null | MF_Allow_As_Identifier }),
|
(Macro { txt("left"), MT_Expression, MF_Null | MF_Allow_As_Identifier }),
|
||||||
(PreprocessorMacro { txt("def_assign"), MT_Expression, MF_Functional }),
|
(Macro { txt("def_assign"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("CHECK_WAS_DEFINED"), MT_Expression, MF_Null }),
|
(Macro { txt("CHECK_WAS_DEFINED"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("check_noskip"), MT_Expression, MF_Functional }),
|
(Macro { txt("check_noskip"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("check"), MT_Expression, MF_Functional | MF_Allow_As_Identifier }),
|
(Macro { txt("check"), MT_Expression, MF_Functional | MF_Allow_As_Identifier }),
|
||||||
(PreprocessorMacro { txt("push_scope"), MT_Expression, MF_Functional }),
|
(Macro { txt("push_scope"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("cut_length"), MT_Expression, MF_Null }),
|
(Macro { txt("cut_length"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("cut_ptr"), MT_Expression, MF_Null }),
|
(Macro { txt("cut_ptr"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("pos"), MT_Expression, MF_Null }),
|
(Macro { txt("pos"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("move_fwd"), MT_Expression, MF_Functional }),
|
(Macro { txt("move_fwd"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("Entry"), MT_Expression, MF_Functional }),
|
(Macro { txt("Entry"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("CheckEndParams"), MT_Expression, MF_Functional }),
|
(Macro { txt("CheckEndParams"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("UseTemplateCapture"), MT_Expression, MF_Null }),
|
(Macro { txt("UseTemplateCapture"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("check_current"), MT_Expression, MF_Functional })
|
(Macro { txt("check_current"), MT_Expression, MF_Functional })
|
||||||
));
|
));
|
||||||
|
|
||||||
Code push_ignores = scan_file( path_base "helpers/push_ignores.inline.hpp" );
|
Code push_ignores = scan_file( path_base "helpers/push_ignores.inline.hpp" );
|
||||||
@ -243,7 +242,7 @@ int gen_main()
|
|||||||
CodeTemplate tmpl = cast(CodeTemplate, entry);
|
CodeTemplate tmpl = cast(CodeTemplate, entry);
|
||||||
if ( tmpl->Declaration->Name.contains(txt("swap")))
|
if ( tmpl->Declaration->Name.contains(txt("swap")))
|
||||||
{
|
{
|
||||||
register_preprocess_macro({ txt("swap"), MT_Expression, MF_Functional });
|
register_macro({ txt("swap"), MT_Expression, MF_Functional });
|
||||||
CodeDefine macro_swap = parse_define( txt(R"(
|
CodeDefine macro_swap = parse_define( txt(R"(
|
||||||
#define swap( a, b ) \
|
#define swap( a, b ) \
|
||||||
do \
|
do \
|
||||||
@ -801,6 +800,9 @@ do \
|
|||||||
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_ast, ast );
|
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_ast, ast );
|
||||||
if (found) break;
|
if (found) break;
|
||||||
|
|
||||||
|
found = ignore_preprocess_cond_block(txt("GEN_EXECUTION_EXPRESSION_SUPPORT"), entry, parsed_ast, ast );
|
||||||
|
if (found) break;
|
||||||
|
|
||||||
ast.append(entry);
|
ast.append(entry);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -979,6 +981,9 @@ R"(#define AST_ArrSpecs_Cap \
|
|||||||
found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_code_types, code_types );
|
found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_code_types, code_types );
|
||||||
if (found) break;
|
if (found) break;
|
||||||
|
|
||||||
|
found = ignore_preprocess_cond_block(txt("GEN_EXECUTION_EXPRESSION_SUPPORT"), entry, parsed_code_types, code_types);
|
||||||
|
if (found) break;
|
||||||
|
|
||||||
code_types.append(entry);
|
code_types.append(entry);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1073,7 +1078,10 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
|||||||
case CT_Preprocess_If:
|
case CT_Preprocess_If:
|
||||||
case CT_Preprocess_IfDef:
|
case CT_Preprocess_IfDef:
|
||||||
{
|
{
|
||||||
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_code_types, code_types );
|
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_ast_types, ast_types );
|
||||||
|
if (found) break;
|
||||||
|
|
||||||
|
found = ignore_preprocess_cond_block(txt("GEN_EXECUTION_EXPRESSION_SUPPORT"), entry, parsed_ast_types, ast_types);
|
||||||
if (found) break;
|
if (found) break;
|
||||||
|
|
||||||
ast_types.append(entry);
|
ast_types.append(entry);
|
||||||
@ -1115,16 +1123,24 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
|||||||
|
|
||||||
CodeBody array_arena = gen_array(txt("gen_Arena"), txt("Array_gen_Arena"));
|
CodeBody array_arena = gen_array(txt("gen_Arena"), txt("Array_gen_Arena"));
|
||||||
CodeBody array_pool = gen_array(txt("gen_Pool"), txt("Array_gen_Pool"));
|
CodeBody array_pool = gen_array(txt("gen_Pool"), txt("Array_gen_Pool"));
|
||||||
|
CodeBody ht_preprocessor_macro = gen_hashtable(txt("gen_Macro"), txt("MacroTable"));
|
||||||
|
|
||||||
CodeBody parsed_interface = parse_file( path_base "components/interface.hpp" );
|
CodeBody parsed_interface = parse_file( path_base "components/interface.hpp" );
|
||||||
CodeBody interface = def_body(CT_Global_Body);
|
CodeBody interface = def_body(CT_Global_Body);
|
||||||
for ( Code entry = parsed_interface.begin(); entry != parsed_interface.end(); ++ entry ) switch( entry->Type )
|
for ( Code entry = parsed_interface.begin(); entry != parsed_interface.end(); ++ entry ) switch( entry->Type )
|
||||||
{
|
{
|
||||||
|
case CT_Preprocess_If:
|
||||||
case CT_Preprocess_IfDef:
|
case CT_Preprocess_IfDef:
|
||||||
{
|
{
|
||||||
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_interface, interface );
|
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_interface, interface );
|
||||||
if (found) break;
|
if (found) break;
|
||||||
|
|
||||||
|
found = ignore_preprocess_cond_block(txt("GEN_COMPILER_CPP"), entry, parsed_interface, interface);
|
||||||
|
if (found) break;
|
||||||
|
|
||||||
|
found = ignore_preprocess_cond_block(txt("0"), entry, parsed_interface, interface);
|
||||||
|
if (found) break;
|
||||||
|
|
||||||
interface.append(entry);
|
interface.append(entry);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1135,13 +1151,6 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
|||||||
CodeFn fn = cast(CodeFn, entry);
|
CodeFn fn = cast(CodeFn, entry);
|
||||||
Code prev = entry->Prev;
|
Code prev = entry->Prev;
|
||||||
|
|
||||||
if (prev && prev->Name.is_equal(entry->Name)) {
|
|
||||||
// rename second definition so there isn't a symbol conflict
|
|
||||||
StrBuilder postfix_arr = StrBuilder::fmt_buf(_ctx->Allocator_Temp, "%S_arr", entry->Name);
|
|
||||||
entry->Name = cache_str(postfix_arr.to_str());
|
|
||||||
postfix_arr.free();
|
|
||||||
}
|
|
||||||
|
|
||||||
b32 handled= false;
|
b32 handled= false;
|
||||||
for ( CodeParams opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
|
for ( CodeParams opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
|
||||||
{
|
{
|
||||||
@ -1209,11 +1218,18 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
|||||||
CodeBody inlines = def_body(CT_Global_Body);
|
CodeBody inlines = def_body(CT_Global_Body);
|
||||||
for ( Code entry = parsed_inlines.begin(); entry != parsed_inlines.end(); ++ entry ) switch( entry->Type )
|
for ( Code entry = parsed_inlines.begin(); entry != parsed_inlines.end(); ++ entry ) switch( entry->Type )
|
||||||
{
|
{
|
||||||
|
case CT_Preprocess_If:
|
||||||
case CT_Preprocess_IfDef:
|
case CT_Preprocess_IfDef:
|
||||||
{
|
{
|
||||||
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_inlines, inlines );
|
b32 found = ignore_preprocess_cond_block(txt("GEN_INTELLISENSE_DIRECTIVES"), entry, parsed_inlines, inlines );
|
||||||
if (found) break;
|
if (found) break;
|
||||||
|
|
||||||
|
found = ignore_preprocess_cond_block(txt("GEN_COMPILER_CPP"), entry, parsed_interface, interface);
|
||||||
|
if (found) break;
|
||||||
|
|
||||||
|
found = ignore_preprocess_cond_block(txt("0"), entry, parsed_interface, interface);
|
||||||
|
if (found) break;
|
||||||
|
|
||||||
inlines.append(entry);
|
inlines.append(entry);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1354,11 +1370,28 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
|||||||
Code src_static_data = scan_file( path_base "components/static_data.cpp" );
|
Code src_static_data = scan_file( path_base "components/static_data.cpp" );
|
||||||
Code src_ast_case_macros = scan_file( path_base "components/ast_case_macros.cpp" );
|
Code src_ast_case_macros = scan_file( path_base "components/ast_case_macros.cpp" );
|
||||||
Code src_code_serialization = scan_file( path_base "components/code_serialization.cpp" );
|
Code src_code_serialization = scan_file( path_base "components/code_serialization.cpp" );
|
||||||
Code src_interface = scan_file( path_base "components/interface.cpp" );
|
|
||||||
Code src_parsing_interface = scan_file( path_base "components/interface.parsing.cpp" );
|
Code src_parsing_interface = scan_file( path_base "components/interface.parsing.cpp" );
|
||||||
Code src_untyped = scan_file( path_base "components/interface.untyped.cpp" );
|
Code src_untyped = scan_file( path_base "components/interface.untyped.cpp" );
|
||||||
Code src_parser_case_macros = scan_file( path_base "components/parser_case_macros.cpp" );
|
Code src_parser_case_macros = scan_file( path_base "components/parser_case_macros.cpp" );
|
||||||
|
|
||||||
|
CodeBody parsed_src_interface = parse_file( path_base "components/interface.cpp" );
|
||||||
|
CodeBody src_interface = def_body(CT_Global_Body);
|
||||||
|
for ( Code entry = parsed_src_interface.begin(); entry != parsed_src_interface.end(); ++ entry ) switch( entry ->Type )
|
||||||
|
{
|
||||||
|
case CT_Function:
|
||||||
|
{
|
||||||
|
CodeFn fn = cast(CodeFn, entry);
|
||||||
|
Code prev = entry->Prev;
|
||||||
|
src_interface.append(fn);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
src_interface.append(entry);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
CodeBody parsed_src_ast = parse_file( path_base "components/ast.cpp" );
|
CodeBody parsed_src_ast = parse_file( path_base "components/ast.cpp" );
|
||||||
CodeBody src_ast = def_body(CT_Global_Body);
|
CodeBody src_ast = def_body(CT_Global_Body);
|
||||||
for ( Code entry = parsed_src_ast.begin(); entry != parsed_src_ast.end(); ++ entry ) switch( entry ->Type )
|
for ( Code entry = parsed_src_ast.begin(); entry != parsed_src_ast.end(); ++ entry ) switch( entry ->Type )
|
||||||
@ -1416,28 +1449,14 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
|||||||
{
|
{
|
||||||
CodeFn fn = cast(CodeFn, entry);
|
CodeFn fn = cast(CodeFn, entry);
|
||||||
Code prev = entry->Prev;
|
Code prev = entry->Prev;
|
||||||
|
|
||||||
for ( CodeParams arr_param : fn->Params )
|
|
||||||
if ( fn->Name.starts_with(txt("def_"))
|
|
||||||
&& ( (arr_param->ValueType->Name.starts_with(txt("Specifier")) && fn->Params->NumEntries > 1)
|
|
||||||
|| arr_param->ValueType->Name.starts_with(txt("Code")) )
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// rename second definition so there isn't a symbol conflict
|
|
||||||
StrBuilder postfix_arr = StrBuilder::fmt_buf(_ctx->Allocator_Temp, "%S_arr", fn->Name);
|
|
||||||
fn->Name = cache_str(postfix_arr.to_str());
|
|
||||||
postfix_arr.free();
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( CodeParams opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
|
for ( CodeParams opt_param : fn->Params ) if (opt_param->ValueType->Name.starts_with(txt("Opts_")))
|
||||||
{
|
{
|
||||||
|
// The frontend names are warapped in macros so we need to give it the intenral symbol name
|
||||||
Str prefix = txt("def_");
|
Str prefix = txt("def_");
|
||||||
Str actual_name = { fn->Name.Ptr + prefix.Len, fn->Name.Len - prefix.Len };
|
Str actual_name = { fn->Name.Ptr + prefix.Len, fn->Name.Len - prefix.Len };
|
||||||
Str new_name = StrBuilder::fmt_buf(_ctx->Allocator_Temp, "def__%S", actual_name ).to_str();
|
Str new_name = StrBuilder::fmt_buf(_ctx->Allocator_Temp, "def__%S", actual_name ).to_str();
|
||||||
|
|
||||||
fn->Name = cache_str(new_name);
|
fn->Name = cache_str(new_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
src_upfront.append(fn);
|
src_upfront.append(fn);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1588,6 +1607,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
|||||||
Code rf_interface = refactor_and_format(interface);
|
Code rf_interface = refactor_and_format(interface);
|
||||||
Code rf_inlines = refactor_and_format(inlines);
|
Code rf_inlines = refactor_and_format(inlines);
|
||||||
|
|
||||||
|
Code rf_ht_preprocessor_macro = refactor_and_format(ht_preprocessor_macro);
|
||||||
Code rf_array_string_cached = refactor_and_format(array_string_cached);
|
Code rf_array_string_cached = refactor_and_format(array_string_cached);
|
||||||
Code rf_header_end = refactor_and_format(header_end);
|
Code rf_header_end = refactor_and_format(header_end);
|
||||||
Code rf_header_builder = refactor_and_format(header_builder);
|
Code rf_header_builder = refactor_and_format(header_builder);
|
||||||
@ -1613,7 +1633,7 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
|||||||
Code r_src_code_serialization = refactor(src_code_serialization);
|
Code r_src_code_serialization = refactor(src_code_serialization);
|
||||||
Code r_src_parser_case_macros = refactor(src_parser_case_macros);
|
Code r_src_parser_case_macros = refactor(src_parser_case_macros);
|
||||||
|
|
||||||
Code r_src_interface = refactor(src_interface);
|
Code r_src_interface = refactor_and_format(src_interface);
|
||||||
Code r_src_upfront = refactor_and_format(src_upfront);
|
Code r_src_upfront = refactor_and_format(src_upfront);
|
||||||
Code r_src_lexer = refactor_and_format(src_lexer);
|
Code r_src_lexer = refactor_and_format(src_lexer);
|
||||||
Code rf_array_code_typename = refactor_and_format(array_code_typename);
|
Code rf_array_code_typename = refactor_and_format(array_code_typename);
|
||||||
@ -1696,6 +1716,8 @@ R"(#define <interface_name>( code ) _Generic( (code), \
|
|||||||
header.print( rf_array_pool);
|
header.print( rf_array_pool);
|
||||||
header.print( fmt_newline);
|
header.print( fmt_newline);
|
||||||
header.print( rf_array_string_cached );
|
header.print( rf_array_string_cached );
|
||||||
|
header.print( fmt_newline);
|
||||||
|
header.print( rf_ht_preprocessor_macro );
|
||||||
|
|
||||||
header.print( rf_interface );
|
header.print( rf_interface );
|
||||||
header.print(fmt_newline);
|
header.print(fmt_newline);
|
||||||
|
@ -310,6 +310,14 @@ word spec_to_str, gen_spec_to_str
|
|||||||
word spec_is_trailing, gen_spec_is_trailing
|
word spec_is_trailing, gen_spec_is_trailing
|
||||||
// word str_to_specifier, gen_str_to_specifier
|
// word str_to_specifier, gen_str_to_specifier
|
||||||
|
|
||||||
|
word MacroType, gen_MacroType
|
||||||
|
word EMacroFlags, gen_EMacroFlags
|
||||||
|
word MacroFlags, gen_MacroFlags
|
||||||
|
word Macro, gen_Macro
|
||||||
|
|
||||||
|
namespace macro_, gen_macro_
|
||||||
|
namespace macrotype, gen_macrotype_
|
||||||
|
|
||||||
// AST
|
// AST
|
||||||
|
|
||||||
word AST, gen_AST
|
word AST, gen_AST
|
||||||
@ -400,6 +408,8 @@ namespace var_, gen_var_
|
|||||||
|
|
||||||
// Gen Interface
|
// Gen Interface
|
||||||
|
|
||||||
|
word _ctx, gen__ctx
|
||||||
|
|
||||||
word init, gen_init
|
word init, gen_init
|
||||||
word deinit, gen_deinit
|
word deinit, gen_deinit
|
||||||
word reset, gen_reset
|
word reset, gen_reset
|
||||||
@ -410,6 +420,8 @@ word make_code, gen_make_code
|
|||||||
|
|
||||||
namespace set_allocator_, gen_set_allocator_
|
namespace set_allocator_, gen_set_allocator_
|
||||||
|
|
||||||
|
namespace Opts_, gen_Opts_
|
||||||
|
|
||||||
namespace def_, gen_def_
|
namespace def_, gen_def_
|
||||||
namespace parse_, gen_parse_
|
namespace parse_, gen_parse_
|
||||||
namespace token_, gen_token_
|
namespace token_, gen_token_
|
||||||
|
@ -238,10 +238,10 @@ CodeBody gen_array( Str type, Str array_name )
|
|||||||
GEN_ASSERT(begin <= end);
|
GEN_ASSERT(begin <= end);
|
||||||
ArrayHeader* header = array_get_header( self );
|
ArrayHeader* header = array_get_header( self );
|
||||||
|
|
||||||
if ( begin < 0 || end >= header->Num )
|
if ( begin < 0 || end > header->Num )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for ( ssize idx = begin; idx < end; idx ++ )
|
for ( ssize idx = (ssize)begin; idx < (ssize)end; idx ++ )
|
||||||
self[ idx ] = value;
|
self[ idx ] = value;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -19,7 +19,7 @@ CodeBody gen_hashtable_base()
|
|||||||
));
|
));
|
||||||
|
|
||||||
Code define_type = untyped_str(txt(
|
Code define_type = untyped_str(txt(
|
||||||
R"(#define HashTable(_type) struct _type
|
R"(#define HashTable(_type) struct gen_HashTable_##_type
|
||||||
)"
|
)"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
| \_____|\___}_l |_|\___} .__/| .__/ {_____/ \__\__/_l\__. |\___/\__,_l \____}{_____}{_____} |
|
| \_____|\___}_l |_|\___} .__/| .__/ {_____/ \__\__/_l\__. |\___/\__,_l \____}{_____}{_____} |
|
||||||
| | | | | __} | |
|
| | | | | __} | |
|
||||||
| l_l l_l {___/ |
|
| l_l l_l {___/ |
|
||||||
! ----------------------------------------------------------------------- VERSION: v0.20-Alpha |
|
! ----------------------------------------------------------------------- VERSION: v0.23-Alpha |
|
||||||
! ============================================================================================= |
|
! ============================================================================================= |
|
||||||
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
|
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
|
||||||
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |
|
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |
|
||||||
|
@ -89,11 +89,11 @@ CodeBody gen_fixed_arenas()
|
|||||||
result.append(arena_interface_2mb);
|
result.append(arena_interface_2mb);
|
||||||
result.append(arena_interface_4mb);
|
result.append(arena_interface_4mb);
|
||||||
|
|
||||||
register_preprocess_macros( args(
|
register_macros( args(
|
||||||
( PreprocessorMacro { txt("fixed_arena_allocator_info"), MT_Expression, MF_Functional }),
|
( Macro { txt("fixed_arena_allocator_info"), MT_Expression, MF_Functional }),
|
||||||
( PreprocessorMacro { txt("fixed_arena_init"), MT_Expression, MF_Functional }),
|
( Macro { txt("fixed_arena_init"), MT_Expression, MF_Functional }),
|
||||||
( PreprocessorMacro { txt("fixed_arena_free"), MT_Expression, MF_Functional }),
|
( Macro { txt("fixed_arena_free"), MT_Expression, MF_Functional }),
|
||||||
( PreprocessorMacro { txt("fixed_arena_size_remaining"), MT_Expression, MF_Functional })
|
( Macro { txt("fixed_arena_size_remaining"), MT_Expression, MF_Functional })
|
||||||
));
|
));
|
||||||
|
|
||||||
CodeDefine def = parse_define(txt("#define fixed_arena_allocator_info(fixed_arena) ( (AllocatorInfo) { arena_allocator_proc, & (fixed_arena)->arena } )\n"));
|
CodeDefine def = parse_define(txt("#define fixed_arena_allocator_info(fixed_arena) ( (AllocatorInfo) { arena_allocator_proc, & (fixed_arena)->arena } )\n"));
|
||||||
|
@ -28,10 +28,9 @@ b32 ignore_preprocess_cond_block( Str cond_sig, Code& entry_iter, CodeBody& pars
|
|||||||
//log_fmt("Preprocess cond found: %S\n", cond->Content);
|
//log_fmt("Preprocess cond found: %S\n", cond->Content);
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
s32 depth = 1;
|
s32 depth = 0;
|
||||||
++ entry_iter;
|
for(b32 continue_for = true; continue_for && entry_iter != parsed_body.end(); ) switch (entry_iter->Type)
|
||||||
for(b32 continue_for = true; continue_for && entry_iter != parsed_body.end(); ) switch
|
{
|
||||||
(entry_iter->Type) {
|
|
||||||
case CT_Preprocess_If:
|
case CT_Preprocess_If:
|
||||||
case CT_Preprocess_IfDef:
|
case CT_Preprocess_IfDef:
|
||||||
case CT_Preprocess_IfNotDef:
|
case CT_Preprocess_IfNotDef:
|
||||||
@ -41,20 +40,18 @@ b32 ignore_preprocess_cond_block( Str cond_sig, Code& entry_iter, CodeBody& pars
|
|||||||
|
|
||||||
case CT_Preprocess_Else:
|
case CT_Preprocess_Else:
|
||||||
++ entry_iter;
|
++ entry_iter;
|
||||||
for(; continue_for && entry_iter != parsed_body.end(); ++ entry_iter)
|
if (depth == 1) for(; entry_iter != parsed_body.end(); ++ entry_iter)
|
||||||
{
|
{
|
||||||
if (entry_iter->Type == CT_Preprocess_EndIf)
|
if ( entry_iter->Type == CT_Preprocess_EndIf)
|
||||||
{
|
|
||||||
continue_for = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
body.append(entry_iter);
|
body.append(entry_iter);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CT_Preprocess_EndIf:
|
case CT_Preprocess_EndIf:
|
||||||
{
|
{
|
||||||
depth --;
|
-- depth;
|
||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
continue_for = false;
|
continue_for = false;
|
||||||
break;
|
break;
|
||||||
|
@ -8,11 +8,13 @@
|
|||||||
|
|
||||||
# Segemented Library Generation
|
# Segemented Library Generation
|
||||||
|
|
||||||
|
Create a segemented library using `segemented.cpp`
|
||||||
|
|
||||||
The principal (user) files are `gen.hpp` and `gen.cpp`.
|
The principal (user) files are `gen.hpp` and `gen.cpp`.
|
||||||
They contain includes for its various components: `components/<component_name>.<hpp/cpp>`
|
They contain includes for its various components: `components/<component_name>.<hpp/cpp>`
|
||||||
|
|
||||||
Dependencies are bundled into `gen.dep.<hpp/cpp>`. They are included in `gen.<hpp/cpp>` before component includes.
|
Dependencies are bundled into `gen.dep.<hpp/cpp>`. They are included in `gen.<hpp/cpp>` before component includes.
|
||||||
Just like the `gen.<hpp/cpp>` they include their components: `dependencies/<dependency_name>.<hpp/cpp>`
|
Just like the `gen.<hpp/cpp>` they include their components: `dependencies/<dependency_name>.<hpp/cpp>`. The auxillary content (builder & scanner) is given their own files.
|
||||||
|
|
||||||
If using the library's provided build scripts:
|
If using the library's provided build scripts:
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||||
#define GEN_EXPOSE_BACKEND
|
|
||||||
#define GEN_C_LIKE_CPP 1
|
#define GEN_C_LIKE_CPP 1
|
||||||
#include "gen.cpp"
|
#include "gen.cpp"
|
||||||
#include "helpers/push_ignores.inline.hpp"
|
#include "helpers/push_ignores.inline.hpp"
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
| \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l |
|
| \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l |
|
||||||
| Singleheader | | | | __} | |
|
| Singleheader | | | | __} | |
|
||||||
| l_l l_l {___/ |
|
| l_l l_l {___/ |
|
||||||
! ----------------------------------------------------------------------- VERSION: v0.20-Alpha |
|
! ----------------------------------------------------------------------- VERSION: v0.23-Alpha |
|
||||||
! ============================================================================================ |
|
! ============================================================================================ |
|
||||||
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
|
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
|
||||||
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |
|
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||||
#define GEN_EXPOSE_BACKEND
|
|
||||||
#include "gen.cpp"
|
#include "gen.cpp"
|
||||||
#include "helpers/push_ignores.inline.hpp"
|
#include "helpers/push_ignores.inline.hpp"
|
||||||
|
|
||||||
|
@ -15,3 +15,20 @@ If using the library's provided build scripts:
|
|||||||
```ps1
|
```ps1
|
||||||
.\build.ps1 <compiler> <debug or omit> unreal
|
.\build.ps1 <compiler> <debug or omit> unreal
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Notables
|
||||||
|
|
||||||
|
For the most part this follows the same conventions as `gen_segmented`.
|
||||||
|
|
||||||
|
This generator uses a separate enumeration definitions for the following:
|
||||||
|
|
||||||
|
* [AttributeTokens.csv](./enums/AttributeTokens.csv) : Add your own <MODULE>_API attributes, etc here that are encountered within the Engine.
|
||||||
|
* [ESpecifier.csv](./enums/ESpecifier.csv) : Adds the `FORCEINLINE` & `FORCEINLINE_DEBUGGABLE` specfiers (additions are made as they are encountered)
|
||||||
|
* [ETokType.csv](./enums/ETokType.csv) : Same modifications as ESpecifier.csv.
|
||||||
|
|
||||||
|
A separate [parser_case_macros.cpp](./components/parser_case_macros.cpp) is used to accomodate for the new forceinline specifiers.
|
||||||
|
|
||||||
|
The `global` macro the library uses is redefined as an empty substiution.
|
||||||
|
|
||||||
|
|
||||||
|
The expected usage of this library is to put into into a third-party plugin module to then use either in editor modules or in shell script done in some stage of hot-reloading or building the Unreal Engine or Project.
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
| \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l |
|
| \_____|\___}_l |_|\___} ,__/| ,__/ (_____/ \__\__/_|\__, |\___}\__,_l |
|
||||||
| Unreal Engine | | | | __} | |
|
| Unreal Engine | | | | __} | |
|
||||||
| l_l l_l {___/ |
|
| l_l l_l {___/ |
|
||||||
! ----------------------------------------------------------------------- VERSION: v0.20-Alpha |
|
! ----------------------------------------------------------------------- VERSION: v0.23-Alpha |
|
||||||
! ============================================================================================ |
|
! ============================================================================================ |
|
||||||
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
|
! WARNING: THIS IS AN ALPHA VERSION OF THE LIBRARY, USE AT YOUR OWN DISCRETION |
|
||||||
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |
|
! NEVER DO CODE GENERATION WITHOUT AT LEAST HAVING CONTENT IN A CODEBASE UNDER VERSION CONTROL |
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// These macros are used in the swtich cases within parser.cpp
|
// These macros are used in the swtich cases within parser.cpp
|
||||||
|
|
||||||
#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIERS_CASES \
|
#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIER_CASES \
|
||||||
case Tok_Spec_Consteval: \
|
case Tok_Spec_Consteval: \
|
||||||
case Tok_Spec_Constexpr: \
|
case Tok_Spec_Constexpr: \
|
||||||
case Tok_Spec_Constinit: \
|
case Tok_Spec_Constinit: \
|
||||||
@ -14,7 +14,7 @@ case Tok_Spec_Static: \
|
|||||||
case Tok_Spec_Volatile: \
|
case Tok_Spec_Volatile: \
|
||||||
case Tok_Spec_Virtual
|
case Tok_Spec_Virtual
|
||||||
|
|
||||||
#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIERS_CASES \
|
#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIER_CASES \
|
||||||
case Spec_Constexpr: \
|
case Spec_Constexpr: \
|
||||||
case Spec_Constinit: \
|
case Spec_Constinit: \
|
||||||
case Spec_Explicit: \
|
case Spec_Explicit: \
|
||||||
@ -54,12 +54,12 @@ case Spec_NeverInline: \
|
|||||||
case Spec_Static: \
|
case Spec_Static: \
|
||||||
case Spec_Volatile
|
case Spec_Volatile
|
||||||
|
|
||||||
#define GEN_PARSER_FRIEND_ALLOWED_SPECIFIERS_CASES \
|
#define GEN_PARSER_FRIEND_ALLOWED_SPECIFIER_CASES \
|
||||||
case Spec_Const: \
|
case Spec_Const: \
|
||||||
case Spec_Inline: \
|
case Spec_Inline: \
|
||||||
case Spec_ForceInline
|
case Spec_ForceInline
|
||||||
|
|
||||||
#define GEN_PARSER_FUNCTION_ALLOWED_SPECIFIERS_CASES \
|
#define GEN_PARSER_FUNCTION_ALLOWED_SPECIFIER_CASES \
|
||||||
case Spec_Const: \
|
case Spec_Const: \
|
||||||
case Spec_Consteval: \
|
case Spec_Consteval: \
|
||||||
case Spec_Constexpr: \
|
case Spec_Constexpr: \
|
||||||
@ -71,7 +71,7 @@ case Spec_Inline: \
|
|||||||
case Spec_NeverInline: \
|
case Spec_NeverInline: \
|
||||||
case Spec_Static
|
case Spec_Static
|
||||||
|
|
||||||
#define GEN_PARSER_OPERATOR_ALLOWED_SPECIFIERS_CASES \
|
#define GEN_PARSER_OPERATOR_ALLOWED_SPECIFIER_CASES \
|
||||||
case Spec_Const: \
|
case Spec_Const: \
|
||||||
case Spec_Constexpr: \
|
case Spec_Constexpr: \
|
||||||
case Spec_ForceInline: \
|
case Spec_ForceInline: \
|
||||||
@ -79,7 +79,7 @@ case Spec_Inline: \
|
|||||||
case Spec_NeverInline: \
|
case Spec_NeverInline: \
|
||||||
case Spec_Static
|
case Spec_Static
|
||||||
|
|
||||||
#define GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIERS_CASES \
|
#define GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIER_CASES \
|
||||||
case Spec_Const: \
|
case Spec_Const: \
|
||||||
case Spec_Constexpr: \
|
case Spec_Constexpr: \
|
||||||
case Spec_Constinit: \
|
case Spec_Constinit: \
|
||||||
|
@ -4,4 +4,4 @@ COREUOBJECT_API, COREUOBJECT_API
|
|||||||
ENGINE_API, ENGINE_API
|
ENGINE_API, ENGINE_API
|
||||||
GAMEPLAYABILITIES_API, GAMEPLAYABILITIES_API
|
GAMEPLAYABILITIES_API, GAMEPLAYABILITIES_API
|
||||||
UMG_API, UMG_API
|
UMG_API, UMG_API
|
||||||
UE_DEPRECATED, UE_DEPRECATED
|
GASA_API, GASA_API
|
|
@ -13,8 +13,8 @@ BraceCurly_Open, "{"
|
|||||||
BraceCurly_Close, "}"
|
BraceCurly_Close, "}"
|
||||||
BraceSquare_Open, "["
|
BraceSquare_Open, "["
|
||||||
BraceSquare_Close, "]"
|
BraceSquare_Close, "]"
|
||||||
Capture_Start, "("
|
Paren_Open, "("
|
||||||
Capture_End, ")"
|
Paren_Close, ")"
|
||||||
Comment, "__comment__"
|
Comment, "__comment__"
|
||||||
Comment_End, "__comment_end__"
|
Comment_End, "__comment_end__"
|
||||||
Comment_Start, "__comment_start__"
|
Comment_Start, "__comment_start__"
|
||||||
@ -42,6 +42,7 @@ Number, "__number__"
|
|||||||
Operator, "__operator__"
|
Operator, "__operator__"
|
||||||
Preprocess_Hash, "#"
|
Preprocess_Hash, "#"
|
||||||
Preprocess_Define, "define"
|
Preprocess_Define, "define"
|
||||||
|
Preprocess_Define_Param, "__define_param__"
|
||||||
Preprocess_If, "if"
|
Preprocess_If, "if"
|
||||||
Preprocess_IfDef, "ifdef"
|
Preprocess_IfDef, "ifdef"
|
||||||
Preprocess_IfNotDef, "ifndef"
|
Preprocess_IfNotDef, "ifndef"
|
||||||
|
|
@ -1,6 +1,5 @@
|
|||||||
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||||
#define GEN_EXPOSE_BACKEND
|
|
||||||
#include "gen.cpp"
|
#include "gen.cpp"
|
||||||
#include "helpers/push_ignores.inline.hpp"
|
#include "helpers/push_ignores.inline.hpp"
|
||||||
|
|
||||||
@ -64,43 +63,44 @@ int gen_main()
|
|||||||
Code ue_forceinline = code_str(FORCEINLINE);
|
Code ue_forceinline = code_str(FORCEINLINE);
|
||||||
// Code
|
// Code
|
||||||
|
|
||||||
register_preprocess_macros( args(
|
register_macros( args(
|
||||||
(PreprocessorMacro { txt("bit"), MT_Expression, MF_Functional }),
|
(Macro { txt("bit"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("bitfield_is_set"), MT_Expression, MF_Functional }),
|
(Macro { txt("bitfield_is_set"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("GEN_C_LIKE_CPP"), MT_Expression, MF_Null }),
|
(Macro { txt("GEN_C_LIKE_CPP"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("cast"), MT_Expression, MF_Functional }),
|
(Macro { txt("cast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("ccast"), MT_Expression, MF_Functional }),
|
(Macro { txt("ccast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("rcast"), MT_Expression, MF_Functional }),
|
(Macro { txt("rcast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("pcast"), MT_Expression, MF_Functional }),
|
(Macro { txt("pcast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("scast"), MT_Expression, MF_Functional }),
|
(Macro { txt("scast"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("stringize_va"), MT_Expression, MF_Functional }),
|
(Macro { txt("stringize_va"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("stringize"), MT_Expression, MF_Functional }),
|
(Macro { txt("stringize"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("do_once"), MT_Expression, MF_Functional }),
|
(Macro { txt("do_once"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("do_once_defer"), MT_Expression, MF_Functional }),
|
(Macro { txt("do_once_defer"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("do_once_start"), MT_Statement, MF_Null }),
|
(Macro { txt("do_once_start"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("do_once_end"), MT_Statement, MF_Null }),
|
(Macro { txt("do_once_end"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("labeled_scope_start"), MT_Statement, MF_Null }),
|
(Macro { txt("labeled_scope_start"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("labeled_scope_end"), MT_Statement, MF_Null }),
|
(Macro { txt("labeled_scope_end"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("compiler_decorated_func_name"), MT_Expression, MF_Null }),
|
(Macro { txt("compiler_decorated_func_name"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("num_args_impl"), MT_Expression, MF_Functional }),
|
(Macro { txt("num_args_impl"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("num_args"), MT_Expression, MF_Functional }),
|
(Macro { txt("num_args"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("count_of"), MT_Expression, MF_Functional }),
|
(Macro { txt("count_of"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("clamp"), MT_Expression, MF_Functional }),
|
(Macro { txt("clamp"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("is_between"), MT_Expression, MF_Functional }),
|
(Macro { txt("is_between"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("size_of"), MT_Expression, MF_Functional }),
|
(Macro { txt("size_of"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("min"), MT_Expression, MF_Functional }),
|
(Macro { txt("min"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("max"), MT_Expression, MF_Functional }),
|
(Macro { txt("max"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("offset_of"), MT_Expression, MF_Functional }),
|
(Macro { txt("offset_of"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("static_assert"), MT_Statement, MF_Functional }),
|
(Macro { txt("static_assert"), MT_Statement, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("typeof"), MT_Expression, MF_Null }),
|
(Macro { txt("typeof"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN_API_C_BEGIN"), MT_Statement, MF_Null }),
|
(Macro { txt("GEN_API_C_BEGIN"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN_API_C_END"), MT_Statement, MF_Null }),
|
(Macro { txt("GEN_API_C_END"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("nullptr"), MT_Expression, MF_Null }),
|
(Macro { txt("nullptr"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN_REMOVE_PTR"), MT_Expression, MF_Functional }),
|
(Macro { txt("GEN_REMOVE_PTR"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("GEN_PARAM_DEFAULT"), MT_Expression, MF_Null }),
|
(Macro { txt("GEN_PARAM_DEFAULT"), MT_Expression, MF_Null }),
|
||||||
(PreprocessorMacro { txt("struct_init"), MT_Expression, MF_Functional }),
|
(Macro { txt("struct_init"), MT_Expression, MF_Functional }),
|
||||||
(PreprocessorMacro { txt("GEN_OPTIMIZE_MAPPINGS_BEGIN"), MT_Statement, MF_Null }),
|
(Macro { txt("GEN_OPTIMIZE_MAPPINGS_BEGIN"), MT_Statement, MF_Null }),
|
||||||
(PreprocessorMacro { txt("GEN_OPITMIZE_MAPPINGS_END"), MT_Statement, MF_Null })
|
(Macro { txt("GEN_OPITMIZE_MAPPINGS_END"), MT_Statement, MF_Null }),
|
||||||
|
(Macro { txt("src_line_str"), MT_Expression, MF_Null })
|
||||||
));
|
));
|
||||||
|
|
||||||
// gen_dep.hpp
|
// gen_dep.hpp
|
||||||
@ -147,6 +147,7 @@ int gen_main()
|
|||||||
Code strings = scan_file( path_base "dependencies/strings.hpp" );
|
Code strings = scan_file( path_base "dependencies/strings.hpp" );
|
||||||
Code filesystem = scan_file( path_base "dependencies/filesystem.hpp" );
|
Code filesystem = scan_file( path_base "dependencies/filesystem.hpp" );
|
||||||
Code timing = scan_file( path_base "dependencies/timing.hpp" );
|
Code timing = scan_file( path_base "dependencies/timing.hpp" );
|
||||||
|
Code parsing = scan_file( path_base "dependencies/parsing.hpp" );
|
||||||
|
|
||||||
Builder
|
Builder
|
||||||
header = Builder::open("gen/gen.dep.hpp");
|
header = Builder::open("gen/gen.dep.hpp");
|
||||||
@ -168,6 +169,7 @@ int gen_main()
|
|||||||
header.print( strings );
|
header.print( strings );
|
||||||
header.print( filesystem );
|
header.print( filesystem );
|
||||||
header.print( timing );
|
header.print( timing );
|
||||||
|
header.print(parsing);
|
||||||
|
|
||||||
header.print_fmt( "\nGEN_NS_END\n" );
|
header.print_fmt( "\nGEN_NS_END\n" );
|
||||||
header.print( fmt_newline );
|
header.print( fmt_newline );
|
||||||
@ -186,6 +188,7 @@ int gen_main()
|
|||||||
Code strings = scan_file( path_base "dependencies/strings.cpp" );
|
Code strings = scan_file( path_base "dependencies/strings.cpp" );
|
||||||
Code filesystem = scan_file( path_base "dependencies/filesystem.cpp" );
|
Code filesystem = scan_file( path_base "dependencies/filesystem.cpp" );
|
||||||
Code timing = scan_file( path_base "dependencies/timing.cpp" );
|
Code timing = scan_file( path_base "dependencies/timing.cpp" );
|
||||||
|
Code parsing = scan_file( path_base "dependencies/parsing.cpp" );
|
||||||
|
|
||||||
Builder
|
Builder
|
||||||
src = Builder::open( "gen/gen.dep.cpp" );
|
src = Builder::open( "gen/gen.dep.cpp" );
|
||||||
@ -204,6 +207,7 @@ int gen_main()
|
|||||||
src.print( strings );
|
src.print( strings );
|
||||||
src.print( filesystem );
|
src.print( filesystem );
|
||||||
src.print( timing );
|
src.print( timing );
|
||||||
|
src.print( parsing );
|
||||||
|
|
||||||
src.print_fmt( "\nGEN_NS_END\n" );
|
src.print_fmt( "\nGEN_NS_END\n" );
|
||||||
src.print( fmt_newline );
|
src.print( fmt_newline );
|
||||||
@ -310,14 +314,20 @@ int gen_main()
|
|||||||
|
|
||||||
src.print_fmt( "\n#pragma region Interface\n" );
|
src.print_fmt( "\n#pragma region Interface\n" );
|
||||||
src.print( interface );
|
src.print( interface );
|
||||||
|
|
||||||
src.print( upfront );
|
src.print( upfront );
|
||||||
|
|
||||||
src.print_fmt( "\n#pragma region Parsing\n\n" );
|
src.print_fmt( "\n#pragma region Parsing\n\n" );
|
||||||
src.print( lexer );
|
src.print( lexer );
|
||||||
src.print( parser_case_macros );
|
src.print( parser_case_macros );
|
||||||
src.print( parser );
|
src.print( parser );
|
||||||
src.print( parsing_interface );
|
src.print( parsing_interface );
|
||||||
src.print( untyped );
|
|
||||||
src.print_fmt( "\n#pragma endregion Parsing\n\n" );
|
src.print_fmt( "\n#pragma endregion Parsing\n\n" );
|
||||||
|
|
||||||
|
src.print_fmt( "\n#pragma region Untyped\n\n" );
|
||||||
|
src.print( untyped );
|
||||||
|
src.print_fmt( "#pragma endregion \n\n" );
|
||||||
|
|
||||||
src.print_fmt( "#pragma endregion Interface\n\n" );
|
src.print_fmt( "#pragma endregion Interface\n\n" );
|
||||||
|
|
||||||
src.print_fmt( "GEN_NS_END\n\n");
|
src.print_fmt( "GEN_NS_END\n\n");
|
||||||
@ -364,7 +374,6 @@ int gen_main()
|
|||||||
|
|
||||||
// gen_scanner.hpp
|
// gen_scanner.hpp
|
||||||
{
|
{
|
||||||
Code parsing = scan_file( path_base "dependencies/parsing.hpp" );
|
|
||||||
Code scanner = scan_file( path_base "auxillary/scanner.hpp" );
|
Code scanner = scan_file( path_base "auxillary/scanner.hpp" );
|
||||||
|
|
||||||
Builder
|
Builder
|
||||||
@ -375,7 +384,6 @@ int gen_main()
|
|||||||
header.print( fmt_newline );
|
header.print( fmt_newline );
|
||||||
header.print( def_include( txt("gen.hpp") ) );
|
header.print( def_include( txt("gen.hpp") ) );
|
||||||
header.print_fmt( "\nGEN_NS_BEGIN\n" );
|
header.print_fmt( "\nGEN_NS_BEGIN\n" );
|
||||||
header.print( parsing );
|
|
||||||
header.print( scanner );
|
header.print( scanner );
|
||||||
header.print_fmt( "\nGEN_NS_END\n" );
|
header.print_fmt( "\nGEN_NS_END\n" );
|
||||||
header.print( fmt_newline );
|
header.print( fmt_newline );
|
||||||
@ -385,7 +393,6 @@ int gen_main()
|
|||||||
|
|
||||||
// gen.scanner.cpp
|
// gen.scanner.cpp
|
||||||
{
|
{
|
||||||
Code parsing = scan_file( path_base "dependencies/parsing.cpp" );
|
|
||||||
Code scanner = scan_file( path_base "auxillary/scanner.cpp" );
|
Code scanner = scan_file( path_base "auxillary/scanner.cpp" );
|
||||||
|
|
||||||
Builder
|
Builder
|
||||||
@ -395,8 +402,7 @@ int gen_main()
|
|||||||
src.print( fmt_newline );
|
src.print( fmt_newline );
|
||||||
src.print( def_include( txt("gen.scanner.hpp") ) );
|
src.print( def_include( txt("gen.scanner.hpp") ) );
|
||||||
src.print_fmt( "\nGEN_NS_BEGIN\n" );
|
src.print_fmt( "\nGEN_NS_BEGIN\n" );
|
||||||
src.print( parsing );
|
src.print( scanner );
|
||||||
// src.print( scanner );
|
|
||||||
src.print_fmt( "\nGEN_NS_END\n" );
|
src.print_fmt( "\nGEN_NS_END\n" );
|
||||||
src.print( fmt_newline );
|
src.print( fmt_newline );
|
||||||
src.print( pop_ignores );
|
src.print( pop_ignores );
|
||||||
|
@ -15,11 +15,13 @@ Its main uage is the [c_library generation](../gen_c_library/).
|
|||||||
Remove any generated content from the repository.
|
Remove any generated content from the repository.
|
||||||
|
|
||||||
**`build.ps1`**
|
**`build.ps1`**
|
||||||
Build c_library, segmented, singleheader, unreal. Supports msvc or clang, release or debug.
|
Build c library (segmented, singleheader, static, or dynamic), cpp library (segmented, singleheader, or unreal). Supports msvc or clang, release or debug.
|
||||||
|
|
||||||
```
|
```erlang
|
||||||
args:
|
args:
|
||||||
c_library
|
c_lib : Build c11 library (singleheader & segmented)
|
||||||
|
c_lib_static : Build static c11 library
|
||||||
|
c_lib_dyn : Buidl dyanmic c11
|
||||||
segemented
|
segemented
|
||||||
singleheader
|
singleheader
|
||||||
unreal
|
unreal
|
||||||
|
@ -325,18 +325,23 @@ if ( $unreal )
|
|||||||
. $refactor_unreal
|
. $refactor_unreal
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $test )
|
# C Library testing
|
||||||
|
if ( $test -and $true )
|
||||||
{
|
{
|
||||||
$path_test_c_lib = join-path $path_test c_library
|
$path_test_c = join-path $path_test c_library
|
||||||
$path_build = join-path $path_test_c_lib build
|
$path_build = join-path $path_test_c build
|
||||||
|
$path_gen = join-path $path_test_c gen
|
||||||
if ( -not(Test-Path($path_build) )) {
|
if ( -not(Test-Path($path_build) )) {
|
||||||
New-Item -ItemType Directory -Path $path_build
|
New-Item -ItemType Directory -Path $path_build
|
||||||
}
|
}
|
||||||
|
if ( -not(Test-Path($path_gen) )) {
|
||||||
|
New-Item -ItemType Directory -Path $path_gen
|
||||||
|
}
|
||||||
|
|
||||||
$includes = @( $path_c_library )
|
$path_singleheader_include = join-path $path_c_library gen
|
||||||
$unit = join-path $path_test_c_lib "gen.c"
|
$includes = @( $path_singleheader_include )
|
||||||
$executable = join-path $path_build "gen_c_library_test.exe"
|
$unit = join-path $path_test_c "test.c"
|
||||||
|
$executable = join-path $path_build "test.exe"
|
||||||
|
|
||||||
$compiler_args = @()
|
$compiler_args = @()
|
||||||
$compiler_args += ( $flag_define + 'GEN_TIME' )
|
$compiler_args += ( $flag_define + 'GEN_TIME' )
|
||||||
@ -350,7 +355,7 @@ if ( $test )
|
|||||||
|
|
||||||
$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable
|
$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable
|
||||||
|
|
||||||
Push-Location $path_test_c_lib
|
Push-Location $path_test_c
|
||||||
if ( Test-Path( $executable ) ) {
|
if ( Test-Path( $executable ) ) {
|
||||||
write-host "`nRunning c_library test"
|
write-host "`nRunning c_library test"
|
||||||
$time_taken = Measure-Command { & $executable
|
$time_taken = Measure-Command { & $executable
|
||||||
@ -362,6 +367,45 @@ if ( $test )
|
|||||||
}
|
}
|
||||||
Pop-Location
|
Pop-Location
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($test -and $true)
|
||||||
|
{
|
||||||
|
$path_test_cpp = join-path $path_test cpp_library
|
||||||
|
$path_build = join-path $path_test_cpp build
|
||||||
|
$path_gen = join-path $path_test_cpp gen
|
||||||
|
if ( -not(Test-Path($path_build) )) {
|
||||||
|
New-Item -ItemType Directory -Path $path_build
|
||||||
|
}
|
||||||
|
if ( -not(Test-Path($path_gen) )) {
|
||||||
|
New-Item -ItemType Directory -Path $path_gen
|
||||||
|
}
|
||||||
|
|
||||||
|
$path_singleheader_include = join-path $path_singleheader gen
|
||||||
|
$includes = @( $path_singleheader_include )
|
||||||
|
$unit = join-path $path_test_cpp "test.cpp"
|
||||||
|
$executable = join-path $path_build "test.exe"
|
||||||
|
|
||||||
|
$compiler_args = @()
|
||||||
|
$compiler_args += ( $flag_define + 'GEN_TIME' )
|
||||||
|
|
||||||
|
$linker_args = @(
|
||||||
|
$flag_link_win_subsystem_console
|
||||||
|
)
|
||||||
|
|
||||||
|
$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable
|
||||||
|
|
||||||
|
Push-Location $path_test_cpp
|
||||||
|
if ( Test-Path( $executable ) ) {
|
||||||
|
write-host "`nRunning cpp_library test"
|
||||||
|
$time_taken = Measure-Command { & $executable
|
||||||
|
| ForEach-Object {
|
||||||
|
write-host `t $_ -ForegroundColor Green
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write-host "`nc_library generator completed in $($time_taken.TotalMilliseconds) ms"
|
||||||
|
}
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
#endregion Building
|
#endregion Building
|
||||||
|
|
||||||
Pop-Location # $path_root
|
Pop-Location # $path_root
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
#define GEN_IMPLEMENTATION
|
|
||||||
#include "gen/gen_singleheader.h"
|
|
||||||
|
|
||||||
int gen_main()
|
|
||||||
{
|
|
||||||
// init();
|
|
||||||
__debugbreak();
|
|
||||||
return 0;
|
|
||||||
}
|
|
32
test/c_library/test.c
Normal file
32
test/c_library/test.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#define GEN_IMPLEMENTATION
|
||||||
|
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
|
#include "gen_singleheader.h"
|
||||||
|
|
||||||
|
#define gen_iterator( Type, container, iter ) \
|
||||||
|
gen_begin_ ## Type(container); \
|
||||||
|
iter != gen_end_ ## Type(container); \
|
||||||
|
code = gen_next_ ## Type(container, iter)
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
gen_Context ctx = {0};
|
||||||
|
gen_init(& ctx);
|
||||||
|
|
||||||
|
gen_Builder src_hello = gen_builder_open("gen/hello.c");
|
||||||
|
gen_CodeVar hello_var = gen_parse_variable(code(
|
||||||
|
char const* hello_gencpp_str = "HELLO GENCPP C11 !";
|
||||||
|
));
|
||||||
|
gen_builder_print( & src_hello, (gen_Code)hello_var );
|
||||||
|
gen_builder_write(& src_hello);
|
||||||
|
|
||||||
|
gen_CodeBody body = gen_parse_file("gen/hello.c");
|
||||||
|
for (gen_Code code = gen_iterator(CodeBody, body, code)) switch (code->Type) {
|
||||||
|
case CT_Variable:
|
||||||
|
gen_CodeVar var = (gen_CodeVar) code;
|
||||||
|
gen_log_fmt("%S", var->Value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_deinit(& ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
29
test/cpp_library/test.cpp
Normal file
29
test/cpp_library/test.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#define GEN_IMPLEMENTATION
|
||||||
|
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
|
||||||
|
#define GEN_ENFORCE_STRONG_CODE_TYPES
|
||||||
|
#include "gen.hpp"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace gen;
|
||||||
|
Context ctx = {};
|
||||||
|
gen::init( & ctx);
|
||||||
|
|
||||||
|
Builder src_hello = builder_open("gen/hello.cpp");
|
||||||
|
CodeVar hello_var = parse_variable( code(
|
||||||
|
constexpr char const* hello_gencpp_str = "HELLO GENCPP !";
|
||||||
|
));
|
||||||
|
src_hello.print(hello_var);
|
||||||
|
src_hello.write();
|
||||||
|
|
||||||
|
CodeBody body = parse_file("gen/hello.cpp");
|
||||||
|
for ( Code code : body ) switch (code->Type) {
|
||||||
|
case CT_Variable:
|
||||||
|
CodeVar var = cast(CodeVar, code);
|
||||||
|
log_fmt("%S", var->Value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gen::deinit(& ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue
Block a user