Merge pull request #34 from Ed94/dev

Dev
This commit is contained in:
Edward R. Gonzalez 2023-09-07 23:06:02 -04:00 committed by GitHub
commit 2c893d5e35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 4652 additions and 1856 deletions

6
.gitignore vendored
View File

@ -32,3 +32,9 @@ bld/
[Ll]og/
[Ll]ogs/
vc140.pdb
# Unreal
**/Unreal/*.h
**/Unreal/*.cpp
! **/Unreal/validate.unreal.cpp

View File

@ -10,8 +10,9 @@
"UNICODE",
"_UNICODE",
"GEN_TIME",
"GEN_IMPLEMENTATION"
"GEN_IMPLEMENTATION",
// "GEN_DONT_USE_NAMESPACE"
"GEN_INTELLISENSE_DIRECTIVES"
],
"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",
@ -28,8 +29,9 @@
"UNICODE",
"_UNICODE",
"GEN_TIME",
"GEN_IMPLEMENTATION"
"GEN_IMPLEMENTATION",
// "GEN_DONT_USE_NAMESPACE"
"GEN_INTELLISENSE_DIRECTIVES"
],
"windowsSdkVersion": "10.0.19041.0",
"compilerPath": "C:/Users/Ed/scoop/apps/llvm/current/bin/clang++.exe",

View File

@ -24,7 +24,11 @@
"filesystem": "cpp",
"format": "cpp",
"ratio": "cpp",
"xstring": "cpp"
"xstring": "cpp",
"functional": "cpp",
"vector": "cpp",
"list": "cpp",
"xhash": "cpp"
},
"C_Cpp.intelliSenseEngineFallback": "disabled",
"mesonbuild.configureOnOpen": true,

687
docs/ASTs.md Normal file
View File

@ -0,0 +1,687 @@
# ASTs Documentation
While the Readme for docs covers the data layout per AST, this will focus on the AST types avaialble, and their nuances.
## Body
These are containers representing a scope body of a definition that can be of the following `ECode` type:
* Class_Body
* Enum_Body
* Export_Body
* Extern_Linkage_Body
* Function_Body
* Global_Body
* Namespace_Body
* Struct_Body
* Union_Body
Fields:
```cpp
Code Front;
Code Back;
Code Parent;
StringCached Name;
CodeT Type;
s32 NumEntries;
```
The `Front` member represents the start of the link list and `Back` the end.
NumEntries is the number of entries in the body.
Parent should have a compatible ECode type for the type of defintion used.
Serialization:
Will output only the entries, the braces are handled by the parent.
```cpp
<Front>...
<Back>
```
## Attributes
Represent standard or vendor specific C/C++ attributes.
Fields:
```cpp
StringCached Content;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
```cpp
<Content>
```
While the parser supports the `__declspec` and `__attribute__` syntax, the upfront constructor ( def_attributes ) must have the user specify the entire attribute, including the `[[]]`, `__declspec` or `__attribute__` parts.
## Comment
Stores a comment.
Fields:
```cpp
StringCached Content;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
```cpp
<Content>
```
The parser will perserve comments found if residing with a body or in accepted inline-to-definition locations.
Otherwise they will be skipped by the TokArray::__eat and TokArray::current( skip foramtting enabled ) functions.
The upfront constructor: `def_comment` expects to recieve a comment without the `//` or `/* */` parts. It will add them during construction.
## Class & Struct
Fields:
```cpp
CodeComment InlineCmt; // Only supported by forward declarations
CodeAttributes Attributes;
CodeType ParentType;
CodeBody Body;
CodeType Last; // Used to store references to interfaces
CodeType Next; // Used to store references to interfaces
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
AccessSpec ParentAccess;
```
Serialization:
```cpp
// Class_Fwd
<ModuleFlags> <class/struct> <Name>; <InlineCmt>
// Class
<ModuleFlags> <class/struct> <Attributes> <Name> : <ParentAccess> <ParentType>, public <Next>, ...<Last>
{
<Body>
};
```
You'll notice that only one parent type is supported only with parent access. This library only supports single inheritance, the rest must be done through interfaces.
## Constructor
Fields:
```cpp
CodeComment InlineCmt; // Only supported by forward declarations
Code InitializerList;
CodeParam Params;
Code Body;
Code Prev;
Code Next;
Code Parent;
CodeT Type;
```
Serialization:
```cpp
// Constructor_Fwd
<Specs> <Parent->Name>( <Params> ); <InlineCmt>
// Constructor
<Specs> <Parent->Name>( <Params> ): <InitializerList>
{
<Body>
}
```
## Define
Represents a preprocessor define
Fields:
```cpp
StringCached Content;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
```cpp
#define <Name> <Content>
```
## Destructor
Fields:
```cpp
CodeComment InlineCmt;
CodeSpecifiers Specs;
Code Body;
Code Prev;
Code Next;
Code Parent;
CodeT Type;
```
Serialization:
```cpp
// Destructor_Fwd
<Specs> ~<Parent->Name>( <Params> ) <Specs>; <InlineCmt>
// Destructor
<Specs> ~<Parent->Name>( <Params> ) <Specs>
{
<Body>
}
```
## Enum
Fields:
```cpp
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeType UnderlyingType;
CodeBody Body;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
Serialization:
```cpp
// Enum_Fwd
<ModuleFlags> enum class <Name> : <UnderlyingType>; <InlineCmt>
// Enum
<ModuleFlags> <enum or enum class> <Name> : <UnderlyingType>
{
<Body>
};
```
## Execution
Just represents an execution body. Equivalent to an untyped body.
Will be obsolute when function body parsing is implemented.
Fields:
```cpp
StringCached Content;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
```cpp
<Content>
```
## External Linkage
Fields:
```cpp
CodeBody Body;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
```cpp
extern "<Name>"
{
<Body>
}
```
## Include
Fields:
```cpp
StringCached Content;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
```cpp
#include <Content>
```
## Friend
This library (until its necessary become some third-party library to do otherwise) does not support friend declarations with in-statment function definitions.
Fields:
```cpp
CodeComment InlineCmt;
Code Declaration;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
```cpp
friend <Declaration>; <InlineCmt>
```
## Function
Fields:
```cpp
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ReturnType;
CodeParam Params;
CodeBody Body;
Code Prev;
Code Parent;
Code Next;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
Serialization:
```cpp
// Function_Fwd
<ModuleFlags> <Attributes> <Specs> <ReturnType> <Name>( <Params> ) <Specs>; <InlineCmt>
// Function
<ModuleFlags> <Attributes> <Specs> <ReturnType> <Name>( <Params> ) <Specs>
{
<Body>
}
```
## Module
Fields:
```cpp
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
Serialization:
```cpp
<ModuleFlags> module <Name>;
```
## Namespace
Fields:
```cpp
CodeBody Body;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
Serialization:
```cpp
<ModuleFlags> namespace <Name>
{
<Body>
}
```
## Operator Overload
Fields:
```cpp
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ReturnType;
CodeParam Params;
CodeBody Body;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
OperatorT Op;
```
Serialization:
```cpp
// Operator_Fwd
<ModuleFlags> <Attributes> <Specs> <ReturnType> operator <Op>( <Params> ) <Specs>; <InlineCmt>
// Operator
<ModuleFlags> <Attributes> <Specs> <ReturnType> <Name>operator <Op>( <Params> ) <Specs>
{
<Body>
}
```
## Operator Cast Overload ( User-Defined Type Conversion )
Fields:
```cpp
CodeComment InlineCmt;
CodeSpecifiers Specs;
CodeType ValueType;
CodeBody Body;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
```cpp
// Operator_Cast_Fwd
<Specs> operator <ValueType>() <Specs>; <InlineCmt>
// Operator_Cast
<Specs> <Name>operator <ValueType>() <Specs>
{
<Body>
}
```
## Parameters
Fields:
```cpp
CodeType ValueType;
Code Value;
CodeParam Last;
CodeParam Next;
Code Parent;
StringCached Name;
CodeT Type;
s32 NumEntries;
```
Serialization:
```cpp
<ValueType> <Name>, <Next>... <Last>
```
## Pragma
Fields:
```cpp
StringCached Content;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
```cpp
#pragma <Content>
```
## Preprocessor Conditional
Fields:
```cpp
StringCached Content;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
```
Serialization:
```cpp
#<based off Type> <Content>
```
## Specifiers
Fields:
```cpp
SpecifierT ArrSpecs[ AST::ArrSpecs_Cap ];
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
s32 NumEntries;
```
Serialization:
```cpp
<Spec>, ...
```
## Template
Fields:
```cpp
CodeParam Params;
Code Declaration;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
Serialization:
```cpp
<ModuleFlags>
template< <Params> >
<Declaration>
```
## Typename
Typenames represent the type "symbol".
Fields:
```cpp
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeReturnType ReturnType;
CodeParam Params;
Code ArrExpr;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
b32 IsParamPack;
```
Serialization:
```cpp
<Attributes> <Name> <Specs> <IsParamPack ?: ...>
```
## Typedef
Behave as usual except function or macro typedefs.
Those don't use the underlying type field as everything was serialized under the Name field.
Fields:
```cpp
CodeComment InlineCmt;
Code UnderlyingType;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
b32 IsFunction;
```
Serialization:
```cpp
// Regular
<ModuleFlags> typedef <UnderlyingType> <Name>; <InlineCmt>
// Functions
<ModuleFlags> typedef <Name>; <InlineCmt>
```
## Union
Fields:
```cpp
CodeAttributes Attributes;
CodeBody Body;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
Serialization:
```cpp
<ModuleFlags> union <Attributes> <Name>
{
<Body>
}
```
## Using
Fields:
```cpp
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeType UnderlyingType;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
Serialization:
```cpp
// Regular
<ModuleFlags> using <Attributes> <Name> = <UnderlyingType>; <InlineCmt>
// Namespace
<ModuleFlags> using namespace <Name>; <InlineCmt>
```
## Variable
Fields:
```cpp
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ValueType;
Code BitfieldSize;
Code Value;
Code Prev;
Code Next;
Code Parent;
StringCached Name;
CodeT Type;
ModuleFlag ModuleFlags;
```
Serialization:
```cpp
// Regular
<ModuleFlags> <Attributes> <Specs> <ValueType> <Name> = <Value>; <InlineCmt>
// Bitfield
<ModuleFlags> <Attributes> <Specs> <ValueType> <Name> : <BitfieldSize> = <Value>; <InlineCmt>
```

89
docs/Parser_Algo.md Normal file
View File

@ -0,0 +1,89 @@
# Parser's Algorithim
gencpp uses a hand-written recursive descent parser. Both the lexer and parser handle a full C/C++ file in a single pass.
## Notable implementation background
### Lexer
The lex procedure does the lexical pass of content provided as a `StrC` type.
The tokens are stored (for now) in `gen::Parser::Tokens`.
Fields:
```cpp
Array<Token> Arr;
s32 Idx;
```
What token types are supported can be found in [ETokType.csv](../project/enums/ETokType.csv) you can also find the token types in [ETokType.h](../project/components/gen/etoktype.cpp) , which is the generated enum from the csv file.
Tokens are defined with the struct `gen::Parser::Token`:
Fields:
```cpp
char const* Text;
sptr Length;
TokType Type;
s32 Line;
s32 Column;
bool IsAssign;
```
`IsAssign` is a flag that is set when the token is an assignment operator. Which is used for various purposes:
* Using statment assignment
* Parameter argument default value assignment
* Variable declaration initialization assignment
I plan to replace IsAssign with a general flags field and properly keep track of all operator types instead of abstracting it away to `ETokType::Operator`.
Traversing the tokens is done with the following interface macros:
| Macro | Description |
| --- | --- |
| `currtok_noskip` | Get the current token without skipping whitespace |
| `currtok` | Get the current token, skip any whitespace tokens |
| `prevtok` | Get the previous token (does not skip whitespace) |
| `nexttok` | Get the next token (does not skip whitespace) |
| `eat( Token Type )` | Check to see if the current token is of the given type, if so, advance Token's index to the next token |
| `left` | Get the number of tokens left in the token array |
| `check_noskip` | Check to see if the current token is of the given type, without skipping whitespace |
| `check` | Check to see if the current token is of the given type, skip any whitespace tokens |
### Parser
The parser has a limited user interface, only specific types of definitions or statements are expected to be provided by the user directly when using to construct an AST dynamically (See SOA for example). It however does attempt to provide capability to parse a full C/C++ from production codebases.
Each public user interface procedure has the following format:
```cpp
CodeStruct parse_<definition type>( StrC def )
{
check_parse_args( def );
using namespace Parser;
TokArray toks = lex( def );
if ( toks.Arr == nullptr )
return CodeInvalid;
// Parse the tokens and return a constructed AST using internal procedures
...
}
```
The most top-level parsing procedure used for C/C++ file parsing is `parse_global_body`:
It uses a helper procedure called `parse_global_nspace`.
Each internal procedure will be
## parse_global_nspace
1. Make sure the type provided to the helper function is a `Namespace_Body`, `Global_Body`, `Export_Body`, `Extern_Linkage_body`.
2. If its not a `Global_Body` eat the opening brace for the scope.
3.
## parse_type

View File

@ -1,9 +1,12 @@
# Parsing
The library features a naive parser tailored for only what the library needs to construct the supported syntax of C++ into its AST.
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) under 5000 loc.
The library features a naive parser tailored for only what the library needs to construct the supported syntax of C++ into its AST.
The parsing implementation supports the following for the user:
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 5000 loc.
You can think of this parser of a 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.
User exposed interface:
```cpp
CodeClass parse_class ( StrC class_def );
@ -27,10 +30,12 @@ CodeUsing parse_using ( StrC using_def );
CodeVar parse_variable ( StrC var_def );
```
To parse file buffers, use the `parse_global_body` function.
***Parsing will aggregate any tokens within a function body or expression statement to an untyped Code AST.***
Everything is done in one pass for both the preprocessor directives and the rest of the language.
The parser performs no macro expansion as the scope of gencpp feature-set is to only support the preprocessor for the goal of having rudimentary awareness of preprocessor ***conditionals***, ***defines***, and ***includes***, and ***pragmas***.
The parser performs no macro expansion as the scope of gencpp feature-set is to only support the preprocessor for the goal of having rudimentary awareness of preprocessor ***conditionals***, ***defines***, ***includes***, and ***pragmas***.
The keywords supported for the preprocessor are:
@ -51,10 +56,17 @@ Any preprocessor definition abuse that changes the syntax of the core language i
Exceptions:
* function signatures are allowed for a preprocessed macro: `neverinline MACRO() { ... }`
* Disable with: `#define GEN_PARSER_DISABLE_MACRO_FUNCTION_SIGNATURES`
* typedefs allow for a preprocessed macro: `typedef MACRO();`
* Disable with: `#define GEN_PARSER_DISABLE_MACRO_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.
*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.*
The lexing and parsing takes shortcuts from whats expected in the standard.
* Numeric literals are not checked for validity.
@ -64,8 +76,7 @@ The lexing and parsing takes shortcuts from whats expected in the standard.
* Assumed to *come before specifiers* (`const`, `constexpr`, `extern`, `static`, etc) for a function
* Or in the usual spot for class, structs, (*right after the declaration keyword*)
* typedefs have attributes with the type (`parse_type`)
* As a general rule; if its not available from the upfront constructors, its not available in the parsing constructors.
* *Upfront constructors are not necessarily used in the parsing constructors, this is just a good metric to know what can be parsed.*
* Parsing attributes can be extended to support user defined macros by defining `GEN_DEFINE_ATTRIBUTE_TOKENS` (see `gen.hpp` for the formatting)
Empty lines used throughout the file are preserved for formatting purposes during ast serialization.

View File

@ -40,6 +40,7 @@
</AdditionalIncludePaths>
<Defines>
<Define>GEN_TIME</Define>
<Define>GEN_SYSTEM_WINDOWS</Define>
</Defines>
<ConfigProperties>
<ConfigAndPlatform>

View File

@ -1,4 +1,6 @@
#include "builder.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# include "builder.hpp"
#endif
Builder Builder::open( char const* path )
{
@ -26,8 +28,7 @@ void Builder::pad_lines( s32 num )
void Builder::print( Code code )
{
String str = code->to_string();
const sw len = str.length();
// const sw len = str.length();
// log_fmt( "%s - print: %.*s\n", File.filename, len > 80 ? 80 : len, str.Data );
Buffer.append( str );
}

View File

@ -1,5 +1,7 @@
#pragma once
#include "gen.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "gen.hpp"
#endif
struct Builder
{

View File

@ -1,67 +0,0 @@
#pragma once
#include "gen.scanner.hpp"
struct Policy
{
// Nothing for now.
};
enum class SymbolType : u32
{
Code,
Line,
Marker
};
struct Editor
{
enum RequestType : u32
{
Add,
Replace,
Remove
};
struct SymbolData
{
Policy Policy;
SymbolInfo Info;
};
struct RequestEntry
{
union {
SymbolData Symbol;
String Specification;
};
RequestType Type;
};
struct Receipt
{
StringCached File;
Code Found;
Code Written;
bool Result;
};
static AllocatorInfo Allocator;
static void set_allocator( AllocatorInfo allocator );
Array<FileInfo> Files;
String Buffer;
Array<RequestEntry> Requests;
void add_files( s32 num, char const** files );
void add ( SymbolInfo definition, Policy policy, Code to_inject );
void remove ( SymbolInfo definition, Policy policy );
void replace( SymbolInfo definition, Policy policy, Code to_replace);
# ifdef GEN_FEATURE_EDITOR_REFACTOR
void refactor( char const* file_path, char const* specification_path );
# endif
bool process_requests( Array<Receipt> out_receipts );
};

View File

@ -1,10 +1,12 @@
#pragma once
#include "gen.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "gen.hpp"
#endif
// This is a simple file reader that reads the entire file into memory.
// It has an extra option to skip the first few lines for undesired includes.
// This is done so that includes can be kept in dependency and component files so that intellisense works.
Code scan_file( char const* path, bool skip_initial_directives = true )
Code scan_file( char const* path )
{
FileInfo file;
@ -24,63 +26,92 @@ Code scan_file( char const* path, bool skip_initial_directives = true )
file_read( & file, str, fsize );
str.get_header().Length = fsize;
if ( skip_initial_directives )
// Skip GEN_INTELLISENSE_DIRECTIVES preprocessor blocks
// Its designed so that the directive should be the first thing in the file.
// Anything that comes before it will also be omitted.
{
#define current (*scanner)
StrC toks[] {
txt( "pragma once" ),
txt( "include" )
};
#define matched 0
#define move_fwd() do { ++ scanner; -- left; } while (0)
const StrC directive_start = txt( "ifdef" );
const StrC directive_end = txt( "endif" );
const StrC def_intellisense = txt("GEN_INTELLISENSE_DIRECTIVES" );
char* scanner = str;
while ( current != '\r' && current != '\n' )
bool found_directive = false;
char const* scanner = str.Data;
s32 left = fsize;
while ( left )
{
for ( StrC tok : toks )
// Processing directive.
if ( current == '#' )
{
if ( current == '#' )
{
++ scanner;
}
move_fwd();
while ( left && char_is_space( current ) )
move_fwd();
if ( strncmp( scanner, tok.Ptr, tok.Len ) == 0 )
if ( ! found_directive )
{
scanner += tok.Len;
while ( scanner < ( str.Data + str.length() ) && current != '\r' && current != '\n' )
if ( left && str_compare( scanner, directive_start.Ptr, directive_start.Len ) == matched )
{
++ scanner;
scanner += directive_start.Len;
left -= directive_start.Len;
while ( left && char_is_space( current ) )
move_fwd();
if ( left && str_compare( scanner, def_intellisense.Ptr, def_intellisense.Len ) == matched )
{
scanner += def_intellisense.Len;
left -= def_intellisense.Len;
found_directive = true;
}
}
// Skip the line
sptr skip_size = sptr( scanner - str.Data );
if ( (scanner + 2) >= ( str.Data + str.length() ) )
// Skip to end of line
while ( left && current != '\r' && current != '\n' )
move_fwd();
move_fwd();
if ( left && current == '\n' )
move_fwd();
continue;
}
if ( left && str_compare( scanner, directive_end.Ptr, directive_end.Len ) == matched )
{
scanner += directive_end.Len;
left -= directive_end.Len;
// Skip to end of line
while ( left && current != '\r' && current != '\n' )
move_fwd();
move_fwd();
if ( left && current == '\n' )
move_fwd();
// sptr skip_size = fsize - left;
if ( (scanner + 2) >= ( str.Data + fsize ) )
{
sptr new_length = sptr( str.get_header().Length ) - skip_size;
mem_move( str, scanner, new_length );
str.get_header().Length = new_length;
mem_move( str, scanner, left );
str.get_header().Length = left;
break;
}
if ( current == '\r' )
{
skip_size += 2;
scanner += 2;
}
else
{
skip_size += 1;
scanner += 1;
}
mem_move( str, scanner, left );
str.get_header().Length = left;
sptr new_length = sptr( str.get_header().Length ) - skip_size;
mem_move( str, scanner, new_length );
str.get_header().Length = new_length;
scanner = str;
break;
}
}
++ scanner;
move_fwd();
}
#undef move_fwd
#undef matched
#undef current
}

View File

@ -17,21 +17,19 @@ GEN_NS_END
using namespace gen;
constexpr char const* generation_notice =
"// This file was generated automatially by gen.bootstrap.cpp "
"// This file was generated automatially by gencpp's bootstrap.cpp "
"(See: https://github.com/Ed94/gencpp)\n\n";
constexpr bool DontSkipInitialDirectives = false;
int gen_main()
{
gen::init();
Code push_ignores = scan_file( "helpers/push_ignores.inline.hpp", DontSkipInitialDirectives );
Code pop_ignores = scan_file( "helpers/pop_ignores.inline.hpp", DontSkipInitialDirectives );
Code push_ignores = scan_file( "helpers/push_ignores.inline.hpp" );
Code pop_ignores = scan_file( "helpers/pop_ignores.inline.hpp" );
// gen_dep.hpp
{
Code header_start = scan_file( "dependencies/header_start.hpp", DontSkipInitialDirectives );
Code header_start = scan_file( "dependencies/header_start.hpp" );
Code macros = scan_file( "dependencies/macros.hpp" );
Code basic_types = scan_file( "dependencies/basic_types.hpp" );
Code debug = scan_file( "dependencies/debug.hpp" );
@ -147,31 +145,35 @@ int gen_main()
header.print( pop_ignores );
header.write();
CodeBody gen_component_header = def_global_body( args(
def_preprocess_cond( PreprocessCond_IfDef, txt("GEN_INTELLISENSE_DIRECTIVES") ),
pragma_once,
preprocess_endif,
fmt_newline,
untyped_str( to_str(generation_notice) )
));
Builder
header_ecode = Builder::open( "components/gen/ecode.hpp" );
header_ecode.print( pragma_once );
header_ecode.print_fmt( generation_notice );
header_ecode.print( gen_component_header );
header_ecode.print( ecode );
header_ecode.write();
Builder
header_eoperator = Builder::open( "components/gen/eoperator.hpp" );
header_eoperator.print( pragma_once );
header_eoperator.print_fmt( generation_notice );
header_eoperator.print( gen_component_header );
header_eoperator.print( eoperator );
header_eoperator.write();
Builder
header_especifier = Builder::open( "components/gen/especifier.hpp" );
header_especifier.print( pragma_once );
header_especifier.print_fmt( generation_notice );
header_especifier.print( gen_component_header );
header_especifier.print( especifier );
header_especifier.write();
Builder
header_ast_inlines = Builder::open( "components/gen/ast_inlines.hpp" );
header_ast_inlines.print( pragma_once );
header_ast_inlines.print_fmt( generation_notice );
header_ast_inlines.print( gen_component_header );
header_ast_inlines.print( ast_inlines );
header_ast_inlines.write();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,10 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "types.hpp"
#include "gen/ecode.hpp"
#include "gen/eoperator.hpp"
#include "gen/especifier.hpp"
#endif
struct AST;
struct AST_Body;
@ -80,7 +82,7 @@ struct Code
static Code Invalid;
# pragma endregion Statics
#define Using_Code( Typename ) \
# define Using_Code( Typename ) \
char const* debug_str(); \
Code duplicate(); \
bool is_equal( Code other ); \
@ -220,33 +222,39 @@ struct AST
- sizeof(CodeT)
- sizeof(ModuleFlag)
- sizeof(u32)
- sizeof(s32)
)
/ sizeof(SpecifierT) - 1; // -1 for 4 extra bytes
union {
struct
{
AST* Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable
AST* Specs; // Function, Operator, Type symbol, Variable
AST* InlineCmt; // Class, Constructor, Destructor, Enum, Friend, Functon, Operator, OpCast, Struct, Typedef, Using, Variable
AST* Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable
AST* Specs; // Destructor, Function, Operator, Typename, Variable
union {
AST* InitializerList; // Constructor, Destructor
AST* ParentType; // Class, Struct
AST* ReturnType; // Function, Operator
AST* InitializerList; // Constructor
AST* ParentType; // Class, Struct, ParentType->Next has a possible list of interfaces.
AST* ReturnType; // Function, Operator, Typename
AST* UnderlyingType; // Enum, Typedef
AST* ValueType; // Parameter, Variable
};
union {
AST* BitfieldSize; // Varaiable (Class/Struct Data Member)
AST* Params; // Function, Operator, Template
AST* BitfieldSize; // Variable (Class/Struct Data Member)
AST* Params; // Constructor, Function, Operator, Template, Typename
};
union {
AST* ArrExpr; // Type Symbol
AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable
AST* ArrExpr; // Typename
AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable
};
union {
AST* NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value )
AST* SpecsFuncSuffix; // Only used with typenames, to store the function suffix if typename is function signature.
};
};
StringCached Content; // Attributes, Comment, Execution, Include
StringCached Content; // Attributes, Comment, Execution, Include
SpecifierT ArrSpecs[AST::ArrSpecs_Cap]; // Specifiers
};
union {
@ -263,11 +271,13 @@ struct AST
CodeT Type;
ModuleFlag ModuleFlags;
union {
b32 IsFunction; // Used by typedef to not serialize the name field.
b32 IsFunction; // Used by typedef to not serialize the name field.
b32 IsParamPack; // Used by typename to know if type should be considered a parameter pack.
OperatorT Op;
AccessSpec ParentAccess;
s32 NumEntries;
};
s32 Token; // Handle to the token, stored in the CodeFile (Otherwise unretrivable)
};
struct AST_POD
@ -275,27 +285,32 @@ struct AST_POD
union {
struct
{
AST* Attributes; // Class, Enum, Function, Struct, Typename, Union, Using, Variable
AST* Specs; // Function, Operator, Type symbol, Variable
AST* InlineCmt; // Class, Constructor, Destructor, Enum, Friend, Functon, Operator, OpCast, Struct, Typedef, Using, Variable
AST* Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable
AST* Specs; // Destructor, Function, Operator, Typename, Variable
union {
AST* InitializerList; // Constructor, Destructor
AST* ParentType; // Class, Struct
AST* ReturnType; // Function, Operator
AST* InitializerList; // Constructor
AST* ParentType; // Class, Struct, ParentType->Next has a possible list of interfaces.
AST* ReturnType; // Function, Operator, Typename
AST* UnderlyingType; // Enum, Typedef
AST* ValueType; // Parameter, Variable
};
union {
AST* BitfieldSize; // Varaiable (Class/Struct Data Member)
AST* Params; // Function, Operator, Template
AST* BitfieldSize; // Variable (Class/Struct Data Member)
AST* Params; // Constructor, Function, Operator, Template, Typename
};
union {
AST* ArrExpr; // Type Symbol
AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable
AST* ArrExpr; // Typename
AST* Body; // Class, Constructr, Destructor, Enum, Function, Namespace, Struct, Union
AST* Declaration; // Friend, Template
AST* Value; // Parameter, Variable
};
union {
AST* NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value )
AST* SpecsFuncSuffix; // Only used with typenames, to store the function suffix if typename is function signature.
};
};
StringCached Content; // Attributes, Comment, Execution, Include
StringCached Content; // Attributes, Comment, Execution, Include
SpecifierT ArrSpecs[AST::ArrSpecs_Cap]; // Specifiers
};
union {
@ -312,11 +327,13 @@ struct AST_POD
CodeT Type;
ModuleFlag ModuleFlags;
union {
b32 IsFunction; // Used by typedef to not serialize the name field.
b32 IsFunction; // Used by typedef to not serialize the name field.
b32 IsParamPack; // Used by typename to know if type should be considered a parameter pack.
OperatorT Op;
AccessSpec ParentAccess;
s32 NumEntries;
};
s32 Token; // Handle to the token, stored in the CodeFile (Otherwise unretrivable)
};
// Its intended for the AST to have equivalent size to its POD.

View File

@ -1,5 +1,7 @@
#pragma once
#include "ast.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "ast.hpp"
#endif
#pragma region AST Types
/*
@ -18,6 +20,7 @@ struct AST_Body
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) ];
s32 NumEntries;
s32 Token;
};
static_assert( sizeof(AST_Body) == sizeof(AST), "ERROR: AST_Filtered is not the same size as AST");
@ -33,6 +36,7 @@ struct AST_Attributes
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Attributes) == sizeof(AST), "ERROR: AST_Attributes is not the same size as AST");
@ -48,6 +52,7 @@ struct AST_Comment
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Comment) == sizeof(AST), "ERROR: AST_Comment is not the same size as AST");
@ -57,11 +62,13 @@ struct AST_Class
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeComment InlineCmt; // Only supported by forward declarations
CodeAttributes Attributes;
char _PAD_SPECS_ [ sizeof(AST*) ];
CodeType ParentType;
char _PAD_PARAMS_[ sizeof(AST*) ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
};
};
CodeType Last;
@ -71,6 +78,7 @@ struct AST_Class
CodeT Type;
ModuleFlag ModuleFlags;
AccessSpec ParentAccess;
s32 Token;
};
static_assert( sizeof(AST_Class) == sizeof(AST), "ERROR: AST_Class is not the same size as AST");
@ -80,18 +88,22 @@ struct AST_Constructor
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
char _PAD_PROPERTIES_ [ sizeof(AST*) * 3 ];
Code InitializerList;
CodeParam Params;
Code Body;
CodeComment InlineCmt; // Only supported by forward declarations
char _PAD_PROPERTIES_ [ sizeof(AST*) * 1 ];
CodeSpecifiers Specs;
Code InitializerList;
CodeParam Params;
Code Body;
char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 2 ];
};
};
Code Prev;
Code Next;
Code Parent;
StringCached Name;
char _PAD_NAME_[ sizeof(StringCached) ];
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Constructor) == sizeof(AST), "ERROR: AST_Constructor is not the same size as AST");
@ -107,6 +119,7 @@ struct AST_Define
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Define) == sizeof(AST), "ERROR: AST_Define is not the same size as AST");
@ -116,18 +129,21 @@ struct AST_Destructor
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeComment InlineCmt;
char _PAD_PROPERTIES_ [ sizeof(AST*) * 1 ];
CodeSpecifiers Specs;
char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 2 ];
Code Body;
char _PAD_PROPERTIES_3_ [ sizeof(AST*) ];
};
};
Code Prev;
Code Next;
Code Parent;
StringCached Name;
char _PAD_NAME_[ sizeof(StringCached) ];
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Destructor) == sizeof(AST), "ERROR: AST_Destructor is not the same size as AST");
@ -137,11 +153,13 @@ struct AST_Enum
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
char _PAD_SPEC_ [ sizeof(AST*) ];
CodeType UnderlyingType;
char _PAD_PARAMS_[ sizeof(AST*) ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
};
};
Code Prev;
@ -151,6 +169,7 @@ struct AST_Enum
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Enum) == sizeof(AST), "ERROR: AST_Enum is not the same size as AST");
@ -158,10 +177,7 @@ struct AST_Exec
{
union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
char _PAD_PROPERTIES_[ sizeof(AST*) * 5 ];
};
StringCached Content;
};
Code Prev;
Code Next;
@ -169,6 +185,7 @@ struct AST_Exec
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Exec) == sizeof(AST), "ERROR: AST_Exec is not the same size as AST");
@ -178,8 +195,9 @@ struct AST_Extern
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ];
char _PAD_PROPERTIES_[ sizeof(AST*) * 5 ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
};
};
Code Prev;
@ -188,6 +206,7 @@ struct AST_Extern
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Extern) == sizeof(AST), "ERROR: AST_Extern is not the same size as AST");
@ -203,6 +222,7 @@ struct AST_Include
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Include) == sizeof(AST), "ERROR: AST_Include is not the same size as AST");
@ -212,8 +232,10 @@ struct AST_Friend
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ];
Code Declaration;
CodeComment InlineCmt;
char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ];
Code Declaration;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
};
};
Code Prev;
@ -222,6 +244,7 @@ struct AST_Friend
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Friend) == sizeof(AST), "ERROR: AST_Friend is not the same size as AST");
@ -231,11 +254,13 @@ struct AST_Fn
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ReturnType;
CodeParam Params;
CodeBody Body;
char _PAD_PROPERTIES_ [ sizeof(AST*) ];
};
};
Code Prev;
@ -245,6 +270,7 @@ struct AST_Fn
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Fn) == sizeof(AST), "ERROR: AST_Fn is not the same size as AST");
@ -258,6 +284,7 @@ struct AST_Module
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Module) == sizeof(AST), "ERROR: AST_Module is not the same size as AST");
@ -266,8 +293,9 @@ struct AST_NS
union {
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct {
char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ];
char _PAD_PROPERTIES_[ sizeof(AST*) * 5 ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
};
};
Code Prev;
@ -277,6 +305,7 @@ struct AST_NS
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_NS) == sizeof(AST), "ERROR: AST_NS is not the same size as AST");
@ -286,11 +315,13 @@ struct AST_Operator
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ReturnType;
CodeParam Params;
CodeBody Body;
char _PAD_PROPERTIES_ [ sizeof(AST*) ];
};
};
Code Prev;
@ -300,6 +331,7 @@ struct AST_Operator
CodeT Type;
ModuleFlag ModuleFlags;
OperatorT Op;
s32 Token;
};
static_assert( sizeof(AST_Operator) == sizeof(AST), "ERROR: AST_Operator is not the same size as AST");
@ -309,11 +341,13 @@ struct AST_OpCast
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeComment InlineCmt;
char _PAD_PROPERTIES_[ sizeof(AST*) ];
CodeSpecifiers Specs;
CodeType ValueType;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
CodeBody Body;
char _PAD_PROPERTIES_3_[ sizeof(AST*) ];
};
};
Code Prev;
@ -322,6 +356,7 @@ struct AST_OpCast
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_OpCast) == sizeof(AST), "ERROR: AST_OpCast is not the same size as AST");
@ -331,10 +366,11 @@ struct AST_Param
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
char _PAD_PROPERTIES_2_[ sizeof(AST*) * 2 ];
char _PAD_PROPERTIES_2_[ sizeof(AST*) * 3 ];
CodeType ValueType;
char _PAD_PROPERTIES_[ sizeof(AST*) ];
Code Value;
char _PAD_PROPERTIES_3_[ sizeof(AST*) ];
};
};
CodeParam Last;
@ -344,6 +380,7 @@ struct AST_Param
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) ];
s32 NumEntries;
s32 Token;
};
static_assert( sizeof(AST_Param) == sizeof(AST), "ERROR: AST_Param is not the same size as AST");
@ -359,6 +396,7 @@ struct AST_Pragma
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Pragma) == sizeof(AST), "ERROR: AST_Pragma is not the same size as AST");
@ -374,6 +412,7 @@ struct AST_PreprocessCond
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_PreprocessCond) == sizeof(AST), "ERROR: AST_PreprocessCond is not the same size as AST");
@ -387,6 +426,7 @@ struct AST_Specifiers
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) ];
s32 NumEntries;
s32 Token;
};
static_assert( sizeof(AST_Specifiers) == sizeof(AST), "ERROR: AST_Specifier is not the same size as AST");
@ -396,11 +436,13 @@ struct AST_Struct
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
char _PAD_SPECS_ [ sizeof(AST*) ];
CodeType ParentType;
char _PAD_PARAMS_[ sizeof(AST*) ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
};
};
CodeType Last;
@ -410,6 +452,7 @@ struct AST_Struct
CodeT Type;
ModuleFlag ModuleFlags;
AccessSpec ParentAccess;
s32 Token;
};
static_assert( sizeof(AST_Struct) == sizeof(AST), "ERROR: AST_Struct is not the same size as AST");
@ -419,9 +462,10 @@ struct AST_Template
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
char _PAD_PROPERTIES_[ sizeof(AST*) * 3 ];
char _PAD_PROPERTIES_[ sizeof(AST*) * 4 ];
CodeParam Params;
Code Declaration;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
};
};
Code Prev;
@ -431,6 +475,7 @@ struct AST_Template
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Template) == sizeof(AST), "ERROR: AST_Template is not the same size as AST");
@ -440,10 +485,13 @@ struct AST_Type
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
char _PAD_INLINE_CMT_[ sizeof(AST*) ];
CodeAttributes Attributes;
CodeSpecifiers Specs;
char _PAD_PROPERTIES_[ sizeof(AST*) * 2 ];
CodeType ReturnType; // Only used for function signatures
CodeParam Params; // Only used for function signatures
Code ArrExpr;
CodeSpecifiers SpecsFuncSuffix; // Only used for function signatures
};
};
Code Prev;
@ -451,7 +499,9 @@ struct AST_Type
Code Parent;
StringCached Name;
CodeT Type;
char _PAD_UNUSED_[ sizeof(ModuleFlag) + sizeof(u32) ];
char _PAD_UNUSED_[ sizeof(ModuleFlag) ];
b32 IsParamPack;
s32 Token;
};
static_assert( sizeof(AST_Type) == sizeof(AST), "ERROR: AST_Type is not the same size as AST");
@ -461,9 +511,10 @@ struct AST_Typedef
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeComment InlineCmt;
char _PAD_PROPERTIES_[ sizeof(AST*) * 2 ];
Code UnderlyingType;
char _PAD_PROPERTIES_2_[ sizeof(AST*) * 2 ];
char _PAD_PROPERTIES_2_[ sizeof(AST*) * 3 ];
};
};
Code Prev;
@ -473,6 +524,7 @@ struct AST_Typedef
CodeT Type;
ModuleFlag ModuleFlags;
b32 IsFunction;
s32 Token;
};
static_assert( sizeof(AST_Typedef) == sizeof(AST), "ERROR: AST_Typedef is not the same size as AST");
@ -482,9 +534,11 @@ struct AST_Union
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
char _PAD_INLINE_CMT_[ sizeof(AST*) ];
CodeAttributes Attributes;
char _PAD_PROPERTIES_[ sizeof(AST*) * 3 ];
CodeBody Body;
char _PAD_PROPERTIES_2_[ sizeof(AST*) ];
};
};
Code Prev;
@ -494,6 +548,7 @@ struct AST_Union
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Union) == sizeof(AST), "ERROR: AST_Union is not the same size as AST");
@ -503,10 +558,11 @@ struct AST_Using
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
char _PAD_SPECS_ [ sizeof(AST*) ];
CodeType UnderlyingType;
char _PAD_PROPERTIES_[ sizeof(AST*) * 2 ];
char _PAD_PROPERTIES_[ sizeof(AST*) * 3 ];
};
};
Code Prev;
@ -516,6 +572,7 @@ struct AST_Using
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Using) == sizeof(AST), "ERROR: AST_Using is not the same size as AST");
@ -525,11 +582,13 @@ struct AST_Var
char _PAD_[ sizeof(SpecifierT) * AST::ArrSpecs_Cap ];
struct
{
CodeComment InlineCmt;
CodeAttributes Attributes;
CodeSpecifiers Specs;
CodeType ValueType;
Code BitfieldSize;
Code Value;
CodeVar NextVar;
};
};
Code Prev;
@ -539,6 +598,7 @@ struct AST_Var
CodeT Type;
ModuleFlag ModuleFlags;
char _PAD_UNUSED_[ sizeof(u32) ];
s32 Token;
};
static_assert( sizeof(AST_Var) == sizeof(AST), "ERROR: AST_Var is not the same size as AST");

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,8 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#endif
// This file was generated automatially by gen.bootstrap.cpp (See: https://github.com/Ed94/gencpp)
// This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp)
namespace ECode
{

View File

@ -1,6 +1,8 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#endif
// This file was generated automatially by gen.bootstrap.cpp (See: https://github.com/Ed94/gencpp)
// This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp)
namespace EOperator
{

View File

@ -1,6 +1,8 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#endif
// This file was generated automatially by gen.bootstrap.cpp (See: https://github.com/Ed94/gencpp)
// This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp)
namespace ESpecifier
{
@ -29,6 +31,7 @@ namespace ESpecifier
Virtual,
Const,
Final,
NoExceptions,
Override,
Pure,
NumSpecifiers
@ -65,6 +68,7 @@ namespace ESpecifier
{ sizeof( "virtual" ), "virtual" },
{ sizeof( "const" ), "const" },
{ sizeof( "final" ), "final" },
{ sizeof( "noexcept" ), "noexcept" },
{ sizeof( "override" ), "override" },
{ sizeof( "= 0" ), "= 0" },
};

View File

@ -1,4 +1,4 @@
// This file was generated automatially by gen.bootstrap.cpp (See: https://github.com/Ed94/gencpp)
// This file was generated automatially by gencpp's bootstrap.cpp (See: https://github.com/Ed94/gencpp)
#pragma once
@ -128,7 +128,7 @@ namespace Parser
{ sizeof( "]" ), "]" },
{ sizeof( "(" ), "(" },
{ sizeof( ")" ), ")" },
{ sizeof( "__comemnt__" ), "__comemnt__" },
{ sizeof( "__comment__" ), "__comment__" },
{ sizeof( "__comment_end__" ), "__comment_end__" },
{ sizeof( "__comment_start__" ), "__comment_start__" },
{ sizeof( "__character__" ), "__character__" },

View File

@ -1,6 +1,8 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "inlines.hpp"
#include "gen/ast_inlines.hpp"
#endif
#pragma region Constants

View File

@ -1,5 +1,7 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "interface.hpp"
#endif
void AST::append( AST* other )
{
@ -25,43 +27,6 @@ void AST::append( AST* other )
NumEntries++;
}
char const* AST::debug_str()
{
if ( Parent )
{
char const* fmt = stringize(
\nType : %s
\nParent : %s %s
\nName : %s
);
// These should be used immediately in a log.
// Thus if its desired to keep the debug str
// for multiple calls to bprintf,
// allocate this to proper string.
return str_fmt_buf( fmt
, type_str()
, Parent->Name
, Parent->type_str()
, Name ? Name : ""
);
}
char const* fmt = stringize(
\nType : %s
\nName : %s
);
// These should be used immediately in a log.
// Thus if its desired to keep the debug str
// for multiple calls to bprintf,
// allocate this to proper string.
return str_fmt_buf( fmt
, type_str()
, Name ? Name : ""
);
}
Code& AST::entry( u32 idx )
{
AST** current = & Front;
@ -102,15 +67,21 @@ Code& Code::operator ++()
void CodeClass::add_interface( CodeType type )
{
if ( ! ast->Next )
CodeType possible_slot = ast->ParentType;
if ( possible_slot.ast )
{
ast->Next = type;
ast->Last = ast->Next;
return;
// Were adding an interface to parent type, so we need to make sure the parent type is public.
ast->ParentAccess = AccessSpec::Public;
// If your planning on adding a proper parent,
// then you'll need to move this over to ParentType->next and update ParentAccess accordingly.
}
ast->Next->Next = type;
ast->Last = ast->Next->Next;
while ( possible_slot.ast != nullptr )
{
possible_slot.ast = (AST_Type*) possible_slot->Next.ast;
}
possible_slot.ast = type.ast;
}
void CodeParam::append( CodeParam other )
@ -164,14 +135,21 @@ CodeParam& CodeParam::operator ++()
void CodeStruct::add_interface( CodeType type )
{
if ( ! ast->Next )
CodeType possible_slot = ast->ParentType;
if ( possible_slot.ast )
{
ast->Next = type;
ast->Last = ast->Next;
// Were adding an interface to parent type, so we need to make sure the parent type is public.
ast->ParentAccess = AccessSpec::Public;
// If your planning on adding a proper parent,
// then you'll need to move this over to ParentType->next and update ParentAccess accordingly.
}
ast->Next->Next = type;
ast->Last = ast->Next->Next;
while ( possible_slot.ast != nullptr )
{
possible_slot.ast = (AST_Type*) possible_slot->Next.ast;
}
possible_slot.ast = type.ast;
}
CodeBody def_body( CodeT type )

View File

@ -1,5 +1,7 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "ast.cpp"
#endif
internal void init_parser();
internal void deinit_parser();
@ -413,6 +415,8 @@ Code make_code()
}
Code result { rcast( AST*, alloc( * allocator, sizeof(AST) )) };
// mem_set( result.ast, 0, sizeof(AST) );
result->Type = ECode::Invalid;
result->Content = { nullptr };
result->Prev = { nullptr };
@ -422,6 +426,7 @@ Code make_code()
result->Type = ECode::Invalid;
result->ModuleFlags = ModuleFlag::Invalid;
result->NumEntries = 0;
result->Token = -1;
return result;
}

View File

@ -1,5 +1,7 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "ast_types.hpp"
#endif
#pragma region Gen Interface
@ -68,7 +70,7 @@ CodeFn def_function( StrC name
, CodeSpecifiers specifiers = NoCode, CodeAttributes attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
CodeInclude def_include ( StrC content );
CodeInclude def_include ( StrC content, bool foreign = false );
CodeModule def_module ( StrC name, ModuleFlag mflags = ModuleFlag::None );
CodeNS def_namespace( StrC name, Code body, ModuleFlag mflags = ModuleFlag::None );

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "interface.parsing.cpp"
#endif
sw token_fmt_va( char* buf, uw buf_size, s32 num_tokens, va_list va )
{

View File

@ -1,5 +1,7 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "interface.cpp"
#endif
#pragma region Upfront
@ -415,12 +417,42 @@ CodeComment def_comment( StrC content )
return CodeInvalid;
}
static char line[ MaxCommentLineLength ];
String cmt_formatted = String::make_reserve( GlobalAllocator, kilobytes(1) );
char const* end = content.Ptr + content.Len;
char const* scanner = content.Ptr;
s32 curr = 0;
do
{
char const* next = scanner;
s32 length = 0;
while ( next != end && scanner[ length ] != '\n' )
{
next = scanner + length;
length++;
}
length++;
str_copy( line, scanner, length );
cmt_formatted.append_fmt( "//%.*s", length, line );
mem_set( line, 0, MaxCommentLineLength );
scanner += length;
}
while ( scanner <= end );
if ( cmt_formatted.back() != '\n' )
cmt_formatted.append( "\n" );
Code
result = make_code();
result->Type = ECode::Comment;
result->Name = get_cached_string( content );
result->Name = get_cached_string( cmt_formatted );
result->Content = result->Name;
cmt_formatted.free();
return (CodeComment) result;
}
@ -820,7 +852,7 @@ CodeFn def_function( StrC name
return result;
}
CodeInclude def_include ( StrC path )
CodeInclude def_include( StrC path, bool foreign )
{
if ( path.Len <= 0 || path.Ptr == nullptr )
{
@ -828,10 +860,14 @@ CodeInclude def_include ( StrC path )
return CodeInvalid;
}
StrC content = foreign ?
to_str( str_fmt_buf( "<%.*s>\n", path.Len, path.Ptr ))
: to_str( str_fmt_buf( "\"%.*s\"\n", path.Len, path.Ptr ));
Code
result = make_code();
result->Type = ECode::Preprocess_Include;
result->Name = get_cached_string( path );
result->Name = get_cached_string( content );
result->Content = result->Name;
return (CodeInclude) result;

View File

@ -1,5 +1,7 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "gen.hpp"
#endif
#pragma region StaticData

View File

@ -1,5 +1,7 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "header_start.hpp"
#endif
using LogFailType = sw(*)(char const*, ...);

View File

@ -1,5 +1,7 @@
#pragma once
#include "macros.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "macros.hpp"
#endif
#pragma region Basic Types

View File

@ -1,5 +1,7 @@
#pragma once
#include "printing.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "printing.hpp"
#endif
#pragma region Containers

View File

@ -1,4 +1,6 @@
#pragma once
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
#endif
#pragma region Debug

View File

@ -1,5 +1,7 @@
#pragma once
#include "basic_types.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVESj
# pragma once
# include "basic_types.hpp"
#endif
#pragma region Debug

View File

@ -1,5 +1,7 @@
#pragma once
#include "strings.cpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "strings.cpp"
#endif
#pragma region File Handling

View File

@ -1,5 +1,7 @@
#pragma once
#include "strings.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "strings.hpp"
#endif
#pragma region File Handling

View File

@ -1,5 +1,7 @@
#pragma once
#include "memory.cpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "memory.cpp"
#endif
#pragma region Hashing

View File

@ -1,5 +1,7 @@
#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "containers.hpp"
#endif
#pragma region Hashing

View File

@ -1,5 +1,7 @@
#pragma once
#include "header_start.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "header_start.hpp"
#endif
#pragma region Macros

View File

@ -1,5 +1,7 @@
#pragma once
#include "printing.cpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "printing.cpp"
#endif
#pragma region Memory
@ -206,6 +208,132 @@ void* heap_allocator_proc( void* allocator_data, AllocType type, sw size, sw ali
return ptr;
}
#pragma region VirtualMemory
VirtualMemory vm_from_memory( void* data, sw size )
{
VirtualMemory vm;
vm.data = data;
vm.size = size;
return vm;
}
#if defined( GEN_SYSTEM_WINDOWS )
VirtualMemory vm_alloc( void* addr, sw size )
{
VirtualMemory vm;
GEN_ASSERT( size > 0 );
vm.data = VirtualAlloc( addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE );
vm.size = size;
return vm;
}
b32 vm_free( VirtualMemory vm )
{
MEMORY_BASIC_INFORMATION info;
while ( vm.size > 0 )
{
if ( VirtualQuery( vm.data, &info, size_of( info ) ) == 0 )
return false;
if ( info.BaseAddress != vm.data || info.AllocationBase != vm.data || info.State != MEM_COMMIT || info.RegionSize > zpl_cast( uw ) vm.size )
{
return false;
}
if ( VirtualFree( vm.data, 0, MEM_RELEASE ) == 0 )
return false;
vm.data = pointer_add( vm.data, info.RegionSize );
vm.size -= info.RegionSize;
}
return true;
}
VirtualMemory vm_trim( VirtualMemory vm, sw lead_size, sw size )
{
VirtualMemory new_vm = { 0 };
void* ptr;
GEN_ASSERT( vm.size >= lead_size + size );
ptr = pointer_add( vm.data, lead_size );
vm_free( vm );
new_vm = vm_alloc( ptr, size );
if ( new_vm.data == ptr )
return new_vm;
if ( new_vm.data )
vm_free( new_vm );
return new_vm;
}
b32 vm_purge( VirtualMemory vm )
{
VirtualAlloc( vm.data, vm.size, MEM_RESET, PAGE_READWRITE );
// NOTE: Can this really fail?
return true;
}
sw virtual_memory_page_size( sw* alignment_out )
{
SYSTEM_INFO info;
GetSystemInfo( &info );
if ( alignment_out )
*alignment_out = info.dwAllocationGranularity;
return info.dwPageSize;
}
#else
# include <sys/mman.h>
# ifndef MAP_ANONYMOUS
# define MAP_ANONYMOUS MAP_ANON
# endif
VirtualMemory vm_alloc( void* addr, sw size )
{
VirtualMemory vm;
GEN_ASSERT( size > 0 );
vm.data = mmap( addr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0 );
vm.size = size;
return vm;
}
b32 vm_free( VirtualMemory vm )
{
munmap( vm.data, vm.size );
return true;
}
VirtualMemory vm_trim( VirtualMemory vm, sw lead_size, sw size )
{
void* ptr;
sw trail_size;
GEN_ASSERT( vm.size >= lead_size + size );
ptr = pointer_add( vm.data, lead_size );
trail_size = vm.size - lead_size - size;
if ( lead_size != 0 )
vm_free( vm_from_memory(( vm.data, lead_size ) );
if ( trail_size != 0 )
vm_free( vm_from_memory( ptr, trail_size ) );
return vm_from_memory( ptr, size );
}
b32 vm_purge( VirtualMemory vm )
{
int err = madvise( vm.data, vm.size, MADV_DONTNEED );
return err != 0;
}
sw virtual_memory_page_size( sw* alignment_out )
{
// TODO: Is this always true?
sw result = zpl_cast( sw ) sysconf( _SC_PAGE_SIZE );
if ( alignment_out )
*alignment_out = result;
return result;
}
#endif
#pragma endregion VirtualMemory
void* Arena::allocator_proc( void* allocator_data, AllocType type, sw size, sw alignment, void* old_memory, sw old_size, u64 flags )
{
Arena* arena = rcast(Arena*, allocator_data);

View File

@ -1,5 +1,7 @@
#pragma once
#include "debug.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "debug.hpp"
#endif
#pragma region Memory
@ -363,6 +365,33 @@ GEN_IMPL_INLINE void zero_size( void* ptr, sw size )
mem_set( ptr, 0, size );
}
struct VirtualMemory
{
void* data;
sw size;
};
//! Initialize virtual memory from existing data.
VirtualMemory vm_from_memory( void* data, sw size );
//! Allocate virtual memory at address with size.
//! @param addr The starting address of the region to reserve. If NULL, it lets operating system to decide where to allocate it.
//! @param size The size to serve.
VirtualMemory vm_alloc( void* addr, sw size );
//! Release the virtual memory.
b32 vm_free( VirtualMemory vm );
//! Trim virtual memory.
VirtualMemory vm_trim( VirtualMemory vm, sw lead_size, sw size );
//! Purge virtual memory.
b32 gen_vm_purge( VirtualMemory vm );
//! Retrieve VM's page size and alignment.
sw gen_virtual_memory_page_size( sw* alignment_out );
struct Arena
{
static
@ -448,6 +477,45 @@ struct Arena
}
};
// Just a wrapper around using an arena with memory associated with its scope instead of from an allocator.
// Used for static segment or stack allocations.
template< s32 Size >
struct FixedArena
{
static
FixedArena init()
{
FixedArena result = { Arena::init_from_memory( result.memory, Size ), {0} };
return result;
}
sw size_remaining( sw alignment )
{
return arena.size_remaining( alignment );
}
operator AllocatorInfo()
{
return { Arena::allocator_proc, &arena };
}
Arena arena;
char memory[ Size ];
};
using Arena_1KB = FixedArena< kilobytes( 1 ) >;
using Arena_4KB = FixedArena< kilobytes( 4 ) >;
using Arena_8KB = FixedArena< kilobytes( 8 ) >;
using Arena_16KB = FixedArena< kilobytes( 16 ) >;
using Arena_32KB = FixedArena< kilobytes( 32 ) >;
using Arena_64KB = FixedArena< kilobytes( 64 ) >;
using Arena_128KB = FixedArena< kilobytes( 128 ) >;
using Arena_256KB = FixedArena< kilobytes( 256 ) >;
using Arena_512KB = FixedArena< kilobytes( 512 ) >;
using Arena_1MB = FixedArena< megabytes( 1 ) >;
using Arena_2MB = FixedArena< megabytes( 2 ) >;
using Arena_4MB = FixedArena< megabytes( 4 ) >;
struct Pool
{
static

View File

@ -1,4 +1,6 @@
#pragma once
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
#endif
#pragma region ADT

View File

@ -1,4 +1,6 @@
#pragma once
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
#endif
#pragma region ADT

View File

@ -1,5 +1,7 @@
#pragma once
#include "string_ops.cpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "string_ops.cpp"
#endif
#pragma region Printing

View File

@ -1,5 +1,7 @@
#pragma once
#include "string_ops.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "string_ops.hpp"
#endif
#pragma region Printing

View File

@ -1,5 +1,7 @@
#pragma once
#include "debug.cpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "debug.cpp"
#endif
#pragma region String Ops

View File

@ -1,5 +1,7 @@
#pragma once
#include "memory.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "memory.hpp"
#endif
#pragma region String Ops

View File

@ -1,5 +1,7 @@
#pragma once
#include "hashing.cpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "hashing.cpp"
#endif
#pragma region String

View File

@ -1,5 +1,7 @@
#pragma once
#include "hashing.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "hashing.hpp"
#endif
#pragma region Strings
@ -99,6 +101,11 @@ struct String
bool make_space_for( char const* str, sw add_len );
bool append( char c )
{
return append( & c, 1 );
}
bool append( char const* str )
{
return append( str, str_len( str ) );
@ -213,6 +220,27 @@ struct String
#undef current
}
void strip_space()
{
char* write_pos = Data;
char* read_pos = Data;
while ( * read_pos)
{
if ( ! char_is_space( *read_pos ))
{
*write_pos = *read_pos;
write_pos++;
}
read_pos++;
}
write_pos[0] = '\0'; // Null-terminate the modified string
// Update the length if needed
get_header().Length = write_pos - Data;
}
void trim( char const* cut_set )
{
sw len = 0;
@ -241,14 +269,52 @@ struct String
return trim( " \t\r\n\v\f" );
}
// Debug function that provides a copy of the string with whitespace characters visualized.
String visualize_whitespace() const
{
Header* header = (Header*)(Data - sizeof(Header));
String result = make_reserve(header->Allocator, length() * 2); // Assume worst case for space requirements.
for ( char c : *this )
{
switch ( c )
{
case ' ':
result.append( txt("·") );
break;
case '\t':
result.append( txt("") );
break;
case '\n':
result.append( txt("") );
break;
case '\r':
result.append( txt("") );
break;
case '\v':
result.append( txt("") );
break;
case '\f':
result.append( txt("") );
break;
default:
result.append(c);
break;
}
}
return result;
}
// For-range support
char* begin()
char* begin() const
{
return Data;
}
char* end()
char* end() const
{
Header const&
header = * rcast( Header const*, Data - sizeof( Header ));

View File

@ -1,5 +1,7 @@
#pragma once
#include "filesystem.cpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "filesystem.cpp"
#endif
#pragma region Timing

View File

@ -1,5 +1,7 @@
#pragma once
#include "filesystem.hpp"
#ifdef GEN_INTELLISENSE_DIRECTIVES
# pragma once
# include "filesystem.hpp"
#endif
#pragma region Timing

View File

@ -21,5 +21,6 @@ Volatile, volatile
Virtual, virtual
Const, const
Final, final
NoExceptions, noexcept
Override, override
Pure, = 0

1 Invalid INVALID
21 Virtual virtual
22 Const const
23 Final final
24 NoExceptions noexcept
25 Override override
26 Pure = 0

View File

@ -15,7 +15,7 @@ BraceSquare_Open, "["
BraceSquare_Close, "]"
Capture_Start, "("
Capture_End, ")"
Comment, "__comemnt__"
Comment, "__comment__"
Comment_End, "__comment_end__"
Comment_Start, "__comment_start__"
Char, "__character__"

1 Invalid __invalid__
15 BraceSquare_Close ]
16 Capture_Start (
17 Capture_End )
18 Comment __comemnt__ __comment__
19 Comment_End __comment_end__
20 Comment_Start __comment_start__
21 Char __character__

View File

@ -396,6 +396,7 @@ if ( $test )
build-simple $includes $unit $executable
Push-Location $path_test
Write-Host $path_test
if ( Test-Path( $executable ) ) {
write-host "`nRunning test generator"
$time_taken = Measure-Command { & $executable
@ -458,7 +459,7 @@ if ( $singleheader -and (Test-Path (Join-Path $path_singleheader "gen/gen.hpp"))
format-cpp $path_gen $include $exclude
}
if ( $test )
if ( $test -and $false )
{
$path_gen = join-path $path_test gen
$include = @(

View File

@ -1,6 +1,4 @@
# Singleheader
`gen.singleheader.cpp` with its own `meson.build` generates the library as a single header `gen.hpp`.
Following the same convention seen in the gb, stb, and zpl libraries.
( Currently WIP )
Creates a single header file version of the library using `gen.singleheader.cpp`.
Follows the same convention seen in the gb, stb, and zpl libraries.

View File

@ -17,7 +17,7 @@ GEN_NS_END
using namespace gen;
constexpr char const* generation_notice =
"// This file was generated automatially by gen.bootstrap.cpp "
"// This file was generated automatially by gencpp's singleheader.cpp"
"(See: https://github.com/Ed94/gencpp)\n\n";
constexpr StrC implementation_guard_start = txt(R"(
@ -48,8 +48,6 @@ global bool generate_builder = true;
global bool generate_editor = true;
global bool generate_scanner = true;
constexpr bool DontSkipInitialDirectives = false;
int gen_main()
{
#define project_dir "../project/"
@ -57,7 +55,7 @@ int gen_main()
Code push_ignores = scan_file( project_dir "helpers/push_ignores.inline.hpp" );
Code pop_ignores = scan_file( project_dir "helpers/pop_ignores.inline.hpp" );
Code single_header_start = scan_file( "components/header_start.hpp", DontSkipInitialDirectives );
Code single_header_start = scan_file( "components/header_start.hpp" );
Builder
header = Builder::open( "gen/gen.hpp" );
@ -71,7 +69,7 @@ int gen_main()
if ( generate_gen_dep )
{
Code header_start = scan_file( project_dir "dependencies/header_start.hpp", DontSkipInitialDirectives );
Code header_start = scan_file( project_dir "dependencies/header_start.hpp" );
Code macros = scan_file( project_dir "dependencies/macros.hpp" );
Code basic_types = scan_file( project_dir "dependencies/basic_types.hpp" );
Code debug = scan_file( project_dir "dependencies/debug.hpp" );

35
test/CURSED_TYPEDEF.h Normal file
View File

@ -0,0 +1,35 @@
#include <functional>
class MyClass;
enum class MyEnum : short { VAL1, VAL2 };
struct OuterStruct {
union NamedUnion {
struct InnerStruct {
double d;
char c;
} inner;
int i;
} unionInstance;
};
template<typename T, int N = alignof(double)>
struct TemplateStruct {
T member[N];
};
template<>
struct TemplateStruct<int, 10> {
int specialMember[10];
};
typedef decltype(nullptr) (MyClass::*InsaneComplexTypeDef)(
decltype((MyEnum::VAL1 == MyEnum::VAL2) ? 1 : 2.0)
(TemplateStruct<decltype(OuterStruct().unionInstance.inner), 5>::*ptr)[5][alignof(double)],
std::function<void *(TemplateStruct<int, 10>&&,
void (MyClass::*memFnPtr)(TemplateStruct<decltype(OuterStruct().unionInstance.inner)>))>,
int (MyClass::*&refToMemFnPtr)(TemplateStruct<int, 10>),
int (TemplateStruct<int, 10>::*memberPointer)[10],
char&&...
) volatile const && noexcept;

View File

@ -0,0 +1,13 @@
# Test : Eskil Steenberg's Game Pipeline
***Note: This validation test has not been implemented yet.***
Repo : https://github.com/valiet/quel_solaar
This is a AST reconstruction test of the gamepipeline library.
1. Download the library
2. Grab all header and source file paths
3. Generate an ast for each file and serialize it to a file called <name of file>.gen.<h/c>
4. Reconstruct the ast from the generated file
5. Compare the original ast to the reconstructed ast

View File

15
test/Godot/Readme.md Normal file
View File

@ -0,0 +1,15 @@
# Test : Godot full AST reconstruction and compile validation
***Note: This validation test has not been implemented yet.***
Repo : https://github.com/godotengine/godot
* Download the Unreal source code
* Find paths of every header and source file
* Generate an ast for each file and serialize it to a file called `<name of file>.gen.<h/c>`
* Reconstruct the ast from the generated file
* Compare the original ast to the reconstructed ast
* If all ASTs are considered valid, overwrite the original files with the generated files
* Compile the engine.
Currently the most involved test planned for the library.

View File

0
test/Godot/validate.ps1 Normal file
View File

25
test/Unreal/Readme.md Normal file
View File

@ -0,0 +1,25 @@
# Unreal Header & Source reconstruction tests
***Note: This validation test has not been implemented yet.***
Will test the following modules + plugins:
* Kismet
* Slate
* RTTI Bases
* Gameframework
* Actor & Component Bases
* Lyra
In the future I could attempt to do a similar test to that of the godot engine full compilation test.
For now it just does the following:
* Download the Unreal source code
* For each module
1. Grab all header and source file paths
2. Generate an ast for each file and serialize it to a file called `<name of file>.gen.<h/c>`
3. Reconstruct the ast from the generated file
4. Compare the original ast to the reconstructed ast
This wil most likely be the most difficult test along-side godot's full compilation test.

0
test/Unreal/validate.ps1 Normal file
View File

View File

18
test/ZPL-C/Readme.md Normal file
View File

@ -0,0 +1,18 @@
# Test : ZPL-C Reconstruction
***Note: This validation test has not been implemented yet.***
Repo : https://github.com/zpl-c/zpl
This is a AST reconstruction test of the ZPL-C library.
Much of the dependency code used in gencpp is derived from the ZPL-C library.
In the future I could directly generate that related code from the ZPL-C library.
For now it just does the following:
1. Download the ZPL-C library
2. Grab all header and source file paths
3. Generate an ast for each file and serialize it to a file called <name of file>.gen.<h/c>
4. Reconstruct the ast from the generated file
5. Compare the original ast to the reconstructed ast

0
test/ZPL-C/validate.ps1 Normal file
View File

View File

View File

@ -0,0 +1,21 @@
#ifdef GEN_TIME
#define GEN_FEATURE_PARSING
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND
#define GEN_BENCHMARK
#include "gen.hpp"
void check_parsing()
{
using namespace gen;
log_fmt("\nupfront: ");
gen::init();
// TODO
gen::deinit();
log_fmt("Passed!\n");
}
#endif

View File

@ -4,6 +4,11 @@
#define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND
#define GEN_BENCHMARK
#define GEN_GLOBAL_BUCKET_SIZE megabytes(10)
#define GEN_CODE_POOL_BLOCK_SIZE megabytes(32)
#define GEN_STRING_ARENA_SIZE megabytes(1)
#include "gen.hpp"
#include "gen.builder.hpp"

View File

@ -7,7 +7,7 @@
#include "gen.builder.cpp"
#include "sanity.cpp"
#include "SOA.cpp"
#include "test.singleheader_ast.cpp"
#include "validate.singleheader.cpp"
int gen_main()
{
@ -18,8 +18,7 @@ int gen_main()
// check_SOA();
check_singleheader_ast();
check_singleheader_ast();
return 0;
}
#endif

View File

@ -1,33 +0,0 @@
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND
#define GEN_BENCHMARK
#include "gen.hpp"
#include "gen.builder.hpp"
#include "gen.scanner.hpp"
using namespace gen;
void check_singleheader_ast()
{
#define project_dir "../"
gen::init();
log_fmt("\ncheck_singleheader_ast:\n");
FileContents file = file_read_contents( GlobalAllocator, true, project_dir "singleheader/gen/gen.hpp" );
u64 time_start = time_rel_ms();
CodeBody ast = parse_global_body( { file.size, (char const*)file.data } );
log_fmt("\nAst generated. Time taken: %llu ms\n", time_rel_ms() - time_start);
log_fmt("\nSerializng ast:\n");
time_start = time_rel_ms();
Builder
builder = Builder::open( "gen/singleheader_copy.gen.hpp" );
builder.print( ast );
builder.write();
log_fmt("passed!! Time taken: %llu ms\n", time_rel_ms() - time_start);
gen::deinit();
}

View File

@ -12,7 +12,7 @@ void check_upfront()
log_fmt("\nupfront: ");
gen::init();
// TODO
gen::deinit();
log_fmt("Passed!\n");

View File

@ -0,0 +1,65 @@
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES
#define GEN_EXPOSE_BACKEND
#define GEN_BENCHMARK
#include "gen.hpp"
#include "gen.builder.hpp"
#include "gen.scanner.hpp"
using namespace gen;
#ifdef GEN_SYSTEM_WINDOWS
#include <process.h>
#endif
void check_singleheader_ast()
{
#define root_dir "../"
gen::init();
log_fmt("\ncheck_singleheader_ast:\n");
FileContents file = file_read_contents( GlobalAllocator, true, root_dir "singleheader/gen/gen.hpp" );
u64 time_start = time_rel_ms();
CodeBody ast = parse_global_body( { file.size, (char const*)file.data } );
log_fmt("\nAst generated. Time taken: %llu ms\n", time_rel_ms() - time_start);
log_fmt("\nSerializng ast:\n");
time_start = time_rel_ms();
Builder
builder = Builder::open( "gen/singleheader_copy.gen.hpp" );
builder.print( ast );
builder.write();
log_fmt("Serialized. Time taken: %llu ms\n", time_rel_ms() - time_start);
// Need to execute clang format on the generated file to get it to match the original.
#define script_path root_dir "scripts/"
#define clang_format "clang-format "
#define cf_format_inplace "-i "
#define cf_style "-style=file:" "C:/projects/gencpp/scripts/.clang-format "
#define cf_verbose "-verbose "
log_fmt("\nRunning clang-format on generated file:\n");
system( clang_format cf_format_inplace cf_style cf_verbose "gen/singleheader_copy.gen.hpp" );
log_fmt("clang-format finished reformatting.\n");
#undef script_path
#undef cf_cmd
#undef cf_format_inplace
#undef cf_style
#undef cf_verbse
FileContents file_gen = file_read_contents( GlobalAllocator, true, "gen/singleheader_copy.gen.hpp" );
log_fmt("\nReconstructing from generated file:\n");
time_start = time_rel_ms();
CodeBody ast_gen = parse_global_body( { file_gen.size, (char const*)file_gen.data } );
log_fmt("\nAst generated. Time taken: %llu ms\n\n", time_rel_ms() - time_start);
time_start = time_rel_ms();
if ( ast.is_equal( ast_gen ) )
log_fmt( "\nPassed!: AST passed validation!\n" );
else
log_fmt( "\nFailed: AST did not pass validation\n" );
log_fmt( "Time taken: %llu ms\n", time_rel_ms() - time_start );
gen::deinit();
}

View File

@ -1,3 +0,0 @@
// Constructs an AST from the singlheader generated gen files, then serializes it to a set of files.
// Using the new set of serialized files, reconstructs the AST and then serializes it again (to different set of files).
// The two sets of serialized files should be identical. (Verified by comparing the file hashes)