diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index b9f72e7..7e6e06e 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -9,10 +9,12 @@ "_DEBUG", "UNICODE", "_UNICODE", - "MD_INTELLISENSE_DIRECTIVES" + "INTELLISENSE_DIRECTIVES" ], "windowsSdkVersion": "10.0.22621.0", - "compilerPath": "cl.exe" + "compilerPath": "cl.exe", + "cStandard": "c11", + "cppStandard": "c++17" } ], "version": 4 diff --git a/Readme.md b/Readme.md index aeb17a2..211d915 100644 --- a/Readme.md +++ b/Readme.md @@ -6,7 +6,7 @@ This is a fork that aims to make the latest version of metadesk available from t The library will be provided in 3 forms: -* As-is: (the way its laid out in this repo) +* default: (the way its laid out in this repo) * c11: Setup ergonomically as a c11 library (both segregtated and as a single-header) * cpp17: Setup ergonoically for usage as a C++ 17 library (both segregated and as a single-header) diff --git a/code/base/arena.c b/code/base/arena.c index ac134cc..6b651df 100644 --- a/code/base/arena.c +++ b/code/base/arena.c @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "arena.h" #endif diff --git a/code/base/arena.h b/code/base/arena.h index 501826b..d8c086d 100644 --- a/code/base/arena.h +++ b/code/base/arena.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "macros.h" # include "base_types.h" @@ -63,20 +63,20 @@ internal Arena* arena_alloc_(ArenaParams *params); internal void arena_release(Arena *arena); //- rjf: arena push/pop/pos core functions -internal void *arena_push(Arena *arena, U64 size, U64 align); -internal U64 arena_pos(Arena *arena); +internal void *arena_push (Arena *arena, U64 size, U64 align); +internal U64 arena_pos (Arena *arena); internal void arena_pop_to(Arena *arena, U64 pos); //- rjf: arena push/pop helpers internal void arena_clear(Arena *arena); -internal void arena_pop(Arena *arena, U64 amt); +internal void arena_pop (Arena *arena, U64 amt); //- rjf: temporary arena scopes internal TempArena temp_arena_begin(Arena *arena); internal void temp_arena_end(TempArena temp); //- rjf: push helper macros -#define push_array_no_zero_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T)*(c), (align)) -#define push_array_aligned(a, T, c, align) (T *)memory_zero(push_array_no_zero_aligned(a, T, c, align), sizeof(T)*(c)) +#define push_array_no_zero_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T) * (c), (align)) +#define push_array_aligned(a, T, c, align) (T *)memory_zero(push_array_no_zero_aligned(a, T, c, align), sizeof(T) * (c)) #define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, max(8, align_of(T))) -#define push_array(a, T, c) push_array_aligned(a, T, c, max(8, align_of(T))) +#define push_array(a, T, c) push_array_aligned (a, T, c, max(8, align_of(T))) diff --git a/code/base/base_types.h b/code/base/base_types.h index 8f7876c..b4fd10a 100644 --- a/code/base/base_types.h +++ b/code/base/base_types.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" # include "linkage.h" diff --git a/code/base/command_line.c b/code/base/command_line.c index fc97857..c3b3d65 100644 --- a/code/base/command_line.c +++ b/code/base/command_line.c @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # include "command_line.h" #endif diff --git a/code/base/command_line.h b/code/base/command_line.h index 8e55f84..c2569d6 100644 --- a/code/base/command_line.h +++ b/code/base/command_line.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "strings.h" #endif diff --git a/code/base/constants.h b/code/base/constants.h index e70d41e..e22a8eb 100644 --- a/code/base/constants.h +++ b/code/base/constants.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" # include "linkage.h" diff --git a/code/base/context_cracking.h b/code/base/context_cracking.h index bb3f5cc..8e23ba2 100644 --- a/code/base/context_cracking.h +++ b/code/base/context_cracking.h @@ -1,4 +1,4 @@ -#if MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once #endif diff --git a/code/base/entry_point.c b/code/base/entry_point.c index c4e035e..873df2c 100644 --- a/code/base/entry_point.c +++ b/code/base/entry_point.c @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # include "entry_point.h" # include "arena.h" # include "thread_context.h" diff --git a/code/base/entry_point.h b/code/base/entry_point.h index 386b3c5..50ea760 100644 --- a/code/base/entry_point.h +++ b/code/base/entry_point.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" # include "linkage.h" diff --git a/code/base/linkage.h b/code/base/linkage.h index 4b96633..513cecc 100644 --- a/code/base/linkage.h +++ b/code/base/linkage.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" #endif @@ -36,7 +36,7 @@ #endif #ifndef global // Global variables -# ifdef MD_DYN_EXPORT +# if defined(MD_DYN_EXPORT) || defined(MD_STATIC_LINK) # define global # else # define global static diff --git a/code/base/logger.h b/code/base/logger.h index 9180dc0..f3c30fe 100644 --- a/code/base/logger.h +++ b/code/base/logger.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "base_types.h" # include "strings.h" diff --git a/code/base/macros.h b/code/base/macros.h index 83d07ca..729ec68 100644 --- a/code/base/macros.h +++ b/code/base/macros.h @@ -1,4 +1,4 @@ -#if MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" # include "linkage.h" @@ -23,8 +23,8 @@ # define expect(expr, val) (expr) #endif -#define likely(expr) expect(expr,1) -#define unlikely(expr) expect(expr,0) +#define likely(expr) expect(expr, 1) +#define unlikely(expr) expect(expr, 0) //////////////////////////////// //~ erg: type casting diff --git a/code/base/markup.c b/code/base/markup.c index c83195c..1fe985d 100644 --- a/code/base/markup.c +++ b/code/base/markup.c @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # include "markup.h" #endif diff --git a/code/base/markup.h b/code/base/markup.h index 65a27ca..5b97e03 100644 --- a/code/base/markup.h +++ b/code/base/markup.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "linkage.h" # include "strings.h" diff --git a/code/base/math.h b/code/base/math.h index f563f17..95ff6f9 100644 --- a/code/base/math.h +++ b/code/base/math.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" # include "linkage.h" diff --git a/code/base/memory.h b/code/base/memory.h index 14b8243..1923385 100644 --- a/code/base/memory.h +++ b/code/base/memory.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" # include "linkage.h" @@ -112,12 +112,6 @@ //~ rjf: Atomic Operations #if MD_OS_WINDOWS - -// # include -// # include -// # include -// # include - # if MD_ARCH_X64 # define ins_atomic_u64_eval(x) InterlockedAdd64((volatile __int64 *)(x), 0) # define ins_atomic_u64_inc_eval(x) InterlockedIncrement64((volatile __int64 *)(x)) @@ -146,16 +140,19 @@ //~ rjf: Linked List Building Macros //- rjf: linked list macro helpers + #define check_nil(nil,p) ((p) == 0 || (p) == nil) #define set_nil(nil,p) ((p) = nil) //- rjf: doubly-linked-lists + +// insert next-previous with nil #define dll_insert_npz(nil, f, l, p, n, next, prev) ( \ check_nil(nil, f) ? ( \ - (f) = (l) = (n), \ - set_nil(nil, (n)->next), \ - set_nil(nil, (n)->prev) \ - ) \ + (f) = (l) = (n), \ + set_nil(nil, (n)->next), \ + set_nil(nil, (n)->prev) \ + ) \ : ( \ check_nil(nil,p) ? ( \ (n)->next = (f), \ @@ -164,11 +161,11 @@ set_nil(nil,(n)->prev) \ ) \ : ((p) == (l)) ? ( \ - (l)->next = (n), \ - (n)->prev = (l), \ - (l) = (n), \ - set_nil(nil, (n)->next) \ - ) \ + (l)->next = (n), \ + (n)->prev = (l), \ + (l) = (n), \ + set_nil(nil, (n)->next) \ + ) \ : ( \ ( \ ( ! check_nil(nil, p) && check_nil(nil, (p)->next) ) ? \ @@ -180,83 +177,116 @@ ((n)->prev = (p)) \ ) \ ) \ -) \ - +) +// push-back next-previous with nil #define dll_push_back_npz(nil, f, l, n, next, prev) dll_insert_npz(nil, f, l, l, n, next, prev) +// push-fornt next-previous with nil #define dll_push_front_npz(nil, f, l, n, next, prev) dll_insert_npz(nil, l, f, f, n, prev, next) -#define dll_remove_npz(nil,f,l,n,next,prev) \ -( \ - ( \ - (n) == (f) ? \ - (f) = (n)->next \ - : (0) \ - ), \ - ( \ - (n) == (l) ? \ - (l) = (l)->prev \ - : (0) \ - ), \ - ( \ - CheckNil(nil,(n)->prev) ? \ - (0) \ - : ((n)->prev->next = (n)->next) \ - ), \ - ( \ - CheckNil(nil,(n)->next) ? \ - (0) \ - : ((n)->next->prev = (n)->prev) \ - ) \ +// remove next-previous with nil +#define dll_remove_npz(nil, f, l, n, next, prev) \ +( \ + ( \ + (n) == (f) ? \ + (f) = (n)->next \ + : (0) \ + ), \ + ( \ + (n) == (l) ? \ + (l) = (l)->prev \ + : (0) \ + ), \ + ( \ + check_nil(nil,(n)->prev) ? \ + (0) \ + : ((n)->prev->next = (n)->next) \ + ), \ + ( \ + check_nil(nil,(n)->next) ? \ + (0) \ + : ((n)->next->prev = (n)->prev) \ + ) \ ) //- rjf: singly-linked, doubly-headed lists (queues) -#define SLLQueuePush_NZ(nil,f,l,n,next) ( \ - CheckNil(nil,f)?\ -((f)=(l)=(n),SetNil(nil,(n)->next)):\ -((l)->next=(n),(l)=(n),SetNil(nil,(n)->next))) -#define SLLQueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f)?\ -((f)=(l)=(n),SetNil(nil,(n)->next)):\ -((n)->next=(f),(f)=(n))) -#define SLLQueuePop_NZ(nil,f,l,next) ((f)==(l)?\ -(SetNil(nil,f),SetNil(nil,l)):\ -((f)=(f)->next)) + +// queue-push next with nil +#define sll_queue_push_nz(nil, f, l, n, next) \ +( \ + check_nil(nil, f) ? ( \ + (f) = (l) = (n), \ + set_nil(nil, (n)->next) \ + ) \ + : ( \ + (l)->next=(n), \ + (l) = (n), \ + set_nil(nil,(n)->next) \ + ) \ +) +// queue-push-front next with nil +#define sll_queue_push_front_nz(nil, f, l, n, next) \ +( \ + check_nil(nil, f) ? ( \ + (f) = (l) = (n), \ + set_nil(nil,(n)->next) \ + ) \ + : ( \ + (n)->next = (f), \ + (f) = (n) \ + ) \ +) +// queue-pop next with nil +#define sll_queue_pop_nz(nil, f, l, next) \ +( \ + (f) == (l) ? ( \ + set_nil(nil,f), \ + set_nil(nil,l) \ + ) \ + : ( \ + (f)=(f)->next \ + ) \ +) //- rjf: singly-linked, singly-headed lists (stacks) + #define sll_stack_push_n(f,n,next) ( (n)->next = (f), (f) = (n) ) #define sll_stack_pop_n(f,next) ( (f) = (f)->next ) //- rjf: doubly-linked-list helpers -#define dll_insert_np(f, l, p, n, next, prev) DLLInsert_NPZ (0, f, l, p, n, next, prev) -#define dll_push_back_np(f, l, n, next, prev) DLLPushBack_NPZ (0, f, l, n, next, prev) -#define dll_push_front_np(f, l, n, next, prev) DLLPushFront_NPZ(0, f, l, n, next, prev) -#define dll_remove_np(f, l, n, next, prev) DLLRemove_NPZ (0, f, l, n, next, prev) -#define dll_insert(f, l, p, n) DLLInsert_NPZ (0, f, l, p, n, next, prev) -#define dll_push_back(f, l, n) DLLPushBack_NPZ (0, f, l, n, next, prev) -#define dll_push_front(f, l, n) DLLPushFront_NPZ(0, f, l, n, next, prev) -#define dll_remove(f, l, n) DLLRemove_NPZ (0, f, l, n, next, prev) + +#define dll_insert_np(f, l, p, n, next, prev) dll_insert_npz (0, f, l, p, n, next, prev) +#define dll_push_back_np(f, l, n, next, prev) dll_push_back_npz (0, f, l, n, next, prev) +#define dll_push_front_np(f, l, n, next, prev) dll_push_front_npz(0, f, l, n, next, prev) +#define dll_remove_np(f, l, n, next, prev) dll_remove_npz (0, f, l, n, next, prev) +#define dll_insert(f, l, p, n) dll_insert_npz (0, f, l, p, n, next, prev) +#define dll_push_back(f, l, n) dll_push_back_npz (0, f, l, n, next, prev) +#define dll_push_front(f, l, n) dll_push_front_npz(0, f, l, n, next, prev) +#define dll_remove(f, l, n) dll_remove_npz (0, f, l, n, next, prev) //- rjf: singly-linked, doubly-headed list helpers -#define SLLQueuePush_N(f,l,n,next) SLLQueuePush_NZ(0,f,l,n,next) -#define SLLQueuePushFront_N(f,l,n,next) SLLQueuePushFront_NZ(0,f,l,n,next) -#define SLLQueuePop_N(f,l,next) SLLQueuePop_NZ(0,f,l,next) -#define SLLQueuePush(f,l,n) SLLQueuePush_NZ(0,f,l,n,next) -#define SLLQueuePushFront(f,l,n) SLLQueuePushFront_NZ(0,f,l,n,next) -#define SLLQueuePop(f,l) SLLQueuePop_NZ(0,f,l,next) + +#define sll_queue_push_n(f, l, n, next) sll_queue_push_nz (0, f, l, n, next) +#define sll_queue_push_fornt_n(f, l, n, next) sll_queue_push_front_nz(0, f, l, n, next) +#define sll_queue_pop_n(f, l, next) sll_queue_pop_nzs (0, f, l, next) +#define sll_queue_push(f, l, n) sll_queue_push_nz (0, f, l, n, next) +#define sll_queue_push_front(f, l ,n) sll_queue_push_front_nz(0, f, l, n, next) +#define sll_queue_pop(f, l) sll_queue_pop_nz (0, f, l, next) //- rjf: singly-linked, singly-headed list helpers -#define SLLStackPush(f,n) SLLStackPush_N(f,n,next) -#define SLLStackPop(f) SLLStackPop_N(f,next) + +#define sll_stack_push(f, n) sll_stack_push_n(f, n, next) +#define sll_stack_pop(f) sll_stack_pop_n (f, next) //////////////////////////////// //~ rjf: Address Sanitizer Markup -#if COMPILER_MSVC +#if MD_COMPILER_MSVC # if defined(__SANITIZE_ADDRESS__) # define ASAN_ENABLED 1 # define NO_ASAN __declspec(no_sanitize_address) # else # define NO_ASAN # endif -#elif COMPILER_CLANG +#elif MD_COMPILER_CLANG # if defined(__has_feature) # if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) # define ASAN_ENABLED 1 @@ -272,18 +302,18 @@ MD_C_API void __asan_poison_memory_region(void const volatile *addr, size_t size); MD_C_API void __asan_unpoison_memory_region(void const volatile *addr, size_t size); -# define AsanPoisonMemoryRegion(addr, size) __asan_poison_memory_region((addr), (size)) -# define AsanUnpoisonMemoryRegion(addr, size) __asan_unpoison_memory_region((addr), (size)) +# define asan_poison_memory_region(addr, size) __asan_poison_memory_region((addr), (size)) +# define asan_unpoison_memory_region(addr, size) __asan_unpoison_memory_region((addr), (size)) #else -# define AsanPoisonMemoryRegion(addr, size) ((void)(addr), (void)(size)) -# define AsanUnpoisonMemoryRegion(addr, size) ((void)(addr), (void)(size)) +# define asan_poison_memory_region(addr, size) ((void)(addr), (void)(size)) +# define asan_unpoison_memory_region(addr, size) ((void)(addr), (void)(size)) #endif //////////////////////////////// //~ rjf: Misc. Helper Macros #define stringify_(S) #S -#define stringify(S) Stringify_(S) +#define stringify(S) stringify_(S) #define glue_(A,B) A ## B #define glue(A,B) glue_(A,B) @@ -304,22 +334,22 @@ #define ptr_from_int(i) (void*)((U8*)0 + (i)) -#define Compose64Bit(a,b) ((((U64)a) << 32) | ((U64)b)); -#define AlignPow2(x,b) (((x) + (b) - 1)&(~((b) - 1))) -#define AlignDownPow2(x,b) ((x)&(~((b) - 1))) -#define AlignPadPow2(x,b) ((0-(x)) & ((b) - 1)) -#define IsPow2(x) ((x)!=0 && ((x)&((x)-1))==0) -#define IsPow2OrZero(x) ((((x) - 1)&(x)) == 0) +#define compose_64bit(a,b) ((((U64)a) << 32) | ((U64)b)); +#define align_pow_2(x,b) (((x) + (b) - 1)&( ~((b) - 1))) +#define align_down_pow_2(x,b) ((x) & (~((b) - 1))) +#define align_pad_pow_2(x,b) ((0-(x)) & ((b) - 1)) +#define is_pow_2(x) ((x) != 0 && ((x )& ((x) - 1)) == 0) +#define is_pow_2_or_zero(x) ((((x) - 1) & (x)) == 0) -#define ExtractBit(word, idx) (((word) >> (idx)) & 1) +#define extract_bit(word, idx) (((word) >> (idx)) & 1) -#if LANG_CPP +#if MD_LANG_CPP # define zero_struct {} #else # define zero_struct {0} #endif -#if COMPILER_MSVC && COMPILER_MSVC_YEAR < 2015 +#if MD_COMPILER_MSVC && MD_COMPILER_MSVC_YEAR < 2015 # define this_function_name "unknown" #else # define this_function_name __func__ diff --git a/code/base/memory_substrate.h b/code/base/memory_substrate.h index 4ba676c..ef1f673 100644 --- a/code/base/memory_substrate.h +++ b/code/base/memory_substrate.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" # include "linkage.h" @@ -22,19 +22,20 @@ #define MD__HAS_ZERO( x ) ( ( ( x ) - MD__ONES ) & ~( x ) & MD__HIGHS ) #if MD_COMPILER_MSVC || (MD_COMPILER_CLANG && MD_OS_WINDOWS) -# pragma section(".rdata$", read) -# define read_only __declspec(allocate(".rdata$")) +# pragma section(".rdata$", read) +# define read_only __declspec(allocate(".rdata$")) #elif (MD_COMPILER_CLANG && MD_OS_LINUX) -# define read_only __attribute__((section(".rodata"))) +# define read_only __attribute__((section(".rodata"))) #else // NOTE(rjf): I don't know of a useful way to do this in GCC land. // __attribute__((section(".rodata"))) looked promising, but it introduces a // strange warning about malformed section attributes, and it doesn't look // like writing to that section reliably produces access violations, strangely // enough. (It does on Clang) -# define read_only +# define read_only #endif +typedef U32 AllocType; enum AllocType enum_underlying(U32) { EAllocType_ALLOC, @@ -42,10 +43,10 @@ enum AllocType enum_underlying(U32) EAllocType_FREE_ALL, EAllocType_RESIZE, }; -typedef U32 AllocType; typedef void*(AllocatorProc)( void* allocator_data, AllocType type, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags ); +typedef struct AllocatorInfo; struct AllocatorInfo { AllocatorProc* proc; diff --git a/code/base/namespace.h b/code/base/namespace.h index fe9b675..ca87a67 100644 --- a/code/base/namespace.h +++ b/code/base/namespace.h @@ -1,11 +1,11 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" #endif // C++ namespace support -#if MD_DONT_USE_NAMESPACE || MD_LANG_C -# if MD_COMPILER_C +#if defined(MD_DONT_USE_NAMESPACE) || MD_LANG_C +# if MD_LANG_C # define MD_NS # define MD_NS_BEGIN # define MD_NS_END diff --git a/code/base/platform.c b/code/base/platform.c index 9354d52..679637d 100644 --- a/code/base/platform.c +++ b/code/base/platform.c @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "platform.h" #endif diff --git a/code/base/platform.h b/code/base/platform.h index 426de3d..332ea61 100644 --- a/code/base/platform.h +++ b/code/base/platform.h @@ -1,4 +1,4 @@ -#if MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" # include "linkage.h" @@ -10,6 +10,22 @@ #if defined( MD_OS_WINDOWS ) # include +# include +# include +# ifndef WIN32_LEAN_AND_MEAN +# ifndef NOMINMAX +# define NOMINMAX +# endif +# +# define WIN32_LEAN_AND_MEAN +# define WIN32_MEAN_AND_LEAN +# define VC_EXTRALEAN +# include +# endif +# undef NOMINMAX +# undef WIN32_LEAN_AND_MEAN +# undef WIN32_MEAN_AND_LEAN +# undef VC_EXTRALEAN #endif #if MD_LANG_C diff --git a/code/base/profiling.h b/code/base/profiling.h index cab2a01..664fac0 100644 --- a/code/base/profiling.h +++ b/code/base/profiling.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once #endif diff --git a/code/base/space.h b/code/base/space.h index e178a10..bd4c5de 100644 --- a/code/base/space.h +++ b/code/base/space.h @@ -1,6 +1,5 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once -# include "math.h" #endif //////////////////////////////// @@ -58,5 +57,4 @@ typedef enum Dir2 Dir2; #define axis2_from_dir2(d) (((d) & 1) ? Axis2_Y : Axis2_X) -#define side_from_dir2(d) (((d) < Dir2_Right) ? Side_Min : Side_Max) - +#define side_from_dir2(d) (((d) < Dir2_Right) ? Side_Min : Side_Max) diff --git a/code/base/strings.c b/code/base/strings.c index ff5b621..37dac52 100644 --- a/code/base/strings.c +++ b/code/base/strings.c @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES #pragma once #include "base/strings.h" #endif diff --git a/code/base/strings.h b/code/base/strings.h index 6eb785e..3706b37 100644 --- a/code/base/strings.h +++ b/code/base/strings.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "context_cracking.h" # include "linkage.h" @@ -7,6 +7,7 @@ # include "base_types.h" # include "constants.h" # include "math.h" +# include "space.h" # include "thread_context.h" # include "memory.h" # include "arena.h" @@ -27,22 +28,22 @@ typedef struct String8 String8; struct String8 { - U8 *str; - U64 size; + U8 *str; + U64 size; }; typedef struct String16 String16; struct String16 { - U16 *str; - U64 size; + U16 *str; + U64 size; }; typedef struct String32 String32; struct String32 { - U32 *str; - U64 size; + U32 *str; + U64 size; }; //////////////////////////////// @@ -51,31 +52,31 @@ struct String32 typedef struct String8Node String8Node; struct String8Node { - String8Node *next; - String8 string; + String8Node *next; + String8 string; }; typedef struct String8MetaNode String8MetaNode; struct String8MetaNode { - String8MetaNode *next; - String8Node *node; + String8MetaNode *next; + String8Node *node; }; typedef struct String8List String8List; struct String8List { - String8Node *first; - String8Node *last; - U64 node_count; - U64 total_size; + String8Node *first; + String8Node *last; + U64 node_count; + U64 total_size; }; typedef struct String8Array String8Array; struct String8Array { - String8 *v; - U64 count; + String8 *v; + U64 count; }; //////////////////////////////// @@ -114,9 +115,9 @@ PathStyle; typedef struct StringJoin StringJoin; struct StringJoin { - String8 pre; - String8 sep; - String8 post; + String8 pre; + String8 sep; + String8 post; }; //////////////////////////////// @@ -125,8 +126,8 @@ struct StringJoin typedef struct UnicodeDecode UnicodeDecode; struct UnicodeDecode { - U32 inc; - U32 codepoint; + U32 inc; + U32 codepoint; }; //////////////////////////////// @@ -135,18 +136,18 @@ struct UnicodeDecode typedef struct FuzzyMatchRangeNode FuzzyMatchRangeNode; struct FuzzyMatchRangeNode { - FuzzyMatchRangeNode *next; - Rng1U64 range; + FuzzyMatchRangeNode *next; + Rng1U64 range; }; typedef struct FuzzyMatchRangeList FuzzyMatchRangeList; struct FuzzyMatchRangeList { - FuzzyMatchRangeNode *first; - FuzzyMatchRangeNode *last; - U64 count; - U64 needle_part_count; - U64 total_dim; + FuzzyMatchRangeNode *first; + FuzzyMatchRangeNode *last; + U64 count; + U64 needle_part_count; + U64 total_dim; }; //////////////////////////////// @@ -331,8 +332,6 @@ internal String8 string_from_elapsed_time (Arena* arena, DateTime dt); internal String8 indented_from_string(Arena *arena, String8 string); - - //////////////////////////////// //~ rjf: String <-> Color diff --git a/code/base/text.c b/code/base/text.c index f262fc3..e245acb 100644 --- a/code/base/text.c +++ b/code/base/text.c @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES #include "text.h" #endif diff --git a/code/base/text.h b/code/base/text.h index 5b20d48..ca647b5 100644 --- a/code/base/text.h +++ b/code/base/text.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "linkage.h" # include "strings.h" diff --git a/code/base/thread_context.h b/code/base/thread_context.h index f26c172..e894119 100644 --- a/code/base/thread_context.h +++ b/code/base/thread_context.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "linkage.h" # include "base_types.h" diff --git a/code/base/toolchain.c b/code/base/toolchain.c index 81d16af..9feb887 100644 --- a/code/base/toolchain.c +++ b/code/base/toolchain.c @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES #include "toolchain.h" #endif diff --git a/code/base/toolchain.h b/code/base/toolchain.h index 9364671..6cf0fb8 100644 --- a/code/base/toolchain.h +++ b/code/base/toolchain.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once #endif @@ -35,4 +35,3 @@ typedef enum Compiler Compiler_COUNT, } Compiler; - diff --git a/code/mdesk/context.h b/code/mdesk/context.h index cb7dbec..3d63349 100644 --- a/code/mdesk/context.h +++ b/code/mdesk/context.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES #pragma once #include "base/memory.h" #endif diff --git a/code/mdesk/mdesk.c b/code/mdesk/mdesk.c index 5333d35..db0ae58 100644 --- a/code/mdesk/mdesk.c +++ b/code/mdesk/mdesk.c @@ -1,7 +1,7 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES #include "mdesk.h" #endif diff --git a/code/mdesk/mdesk.h b/code/mdesk/mdesk.h index 0e045f0..fe24e8c 100644 --- a/code/mdesk/mdesk.h +++ b/code/mdesk/mdesk.h @@ -1,4 +1,4 @@ -#if MD_INTELLISENSE_DIRECTIVES +#if INTELLISENSE_DIRECTIVES #pragma once #include "base/base_types.h" #include "base/math.h" diff --git a/code/metadesk.h b/code/metadesk.h index ea6ec98..e4f3c55 100644 --- a/code/metadesk.h +++ b/code/metadesk.h @@ -15,9 +15,13 @@ MD_NS_BEGIN #include "base/base_types.h" -#include "base/memory_substrate.h" #include "base/memory.h" +#include "base/memory_substrate.h" +#include "base/arena.h" +#include "base/space.h" +#include "base/toolchain.h" #include "base/strings.h" +#include "base/text.h" MD_NS_END diff --git a/code/os/core/linux/os_core_linux.h b/code/os/core/linux/os_core_linux.h index a0fc81e..857ab3c 100644 --- a/code/os/core/linux/os_core_linux.h +++ b/code/os/core/linux/os_core_linux.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES #pragma once #include "base/macros.h" #include "base/base_types.h" diff --git a/code/os/core/os_core.h b/code/os/core/os_core.h index d39d534..40de579 100644 --- a/code/os/core/os_core.h +++ b/code/os/core/os_core.h @@ -1,4 +1,4 @@ -#ifdef MD_INTELLISENSE_DIRECTIVES +#ifdef INTELLISENSE_DIRECTIVES # pragma once # include "base/cracking_arch.h" # include "base/cracking_compiler.h" diff --git a/metadesk.10x b/metadesk.10x new file mode 100644 index 0000000..59c2780 --- /dev/null +++ b/metadesk.10x @@ -0,0 +1,67 @@ + + + + *.c,*.cc,*.cpp,*.c++,*.cp,*.cxx,*.h,*.hh,*.hpp,*.h++,*.hp,*.hxx,*.inl,*.cs,*.rs,*.java,*.jav,*.js,*.jsc,*.jsx,*.json,*.cls,*.py,*.rpy,*.php,*.php3,*.phl,*.phtml,*.rhtml,*.tpl,*.phps,*.lua,*.html,*.html5,*.htm,*.xml,*.xaml,*.css,*.ssi,*.haml,*.yaml,*.bat,*.wbf,*.wbt,*.txt,*.cmake,*.make,*.makefile,*.mak,*.mk,*.sh,*.bash,*.csv,*.asp,*.pl,*.mac,*.ws,*.vbs,*.perl,*.src,*.rss,*.inc,*.f,*.go,*.prl,*.plx,*.rb,*.lsp,*.lpx,*.ps1,*.command,*.cbl,*.cob,*.qs,*.wxs,*.ph,*.msc,*.glsl,*.hlsl,*.fx,*.vert,*.tesc,*.tese,*.geom,*.frag,*.comp,*.pssl,*.scons,*.cu,*.jai, + + true + true + true + false + false + + + + + + + + + + + + false + false + + Debug + Release + + + x64 + Win32 + + + C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.42.34433\include + C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.42.34433\ATLMFC\include + C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\VS\include + C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt + C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\um + C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\shared + C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\winrt + C:\Program Files (x86)\Windows Kits\10\\include\10.0.22621.0\\cppwinrt + C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um + + + + + Debug:x64 + + + + + Debug + + + + x64 + + __STDC__ + _MSC_VER + _M_AMD64 + _WIN64 + INTELLISENSE_DIRECTIVES + + + + + + diff --git a/thirdparty/gencpp_c11/AST_Design.md b/thirdparty/gencpp_c11/AST_Design.md deleted file mode 100644 index 487d6dd..0000000 --- a/thirdparty/gencpp_c11/AST_Design.md +++ /dev/null @@ -1,59 +0,0 @@ -## Navigation - -[Top](../Readme.md) - -<- [docs - General](Readme.md) - -## Current Design - -`AST` is the actual managed node object for the library. -Its raw and really not meant to be used directly. - -All user interaction must be with its pointer so the type they deal with is `AST*`. -In order to abstract away constant use of `AST*` its wrapped in a Code type which can be either: - -When its the [C generated variant of the library](../gen_c_library/) -```c -typedef AST* Code; -typedef AST_* Code; -... -``` - -**or** - -For C++: -```cpp -struct Code { - AST* ast; -}; -struct Code { - ... - - AST_* ast; -}; -``` - -The full definitions of all asts are within: - -* [`ast.hpp`](../base/components/ast.hpp) -* [`ast_types.hpp`](../base/components/ast_types.hpp) -* [`code_types.hpp`](../base/components/code_types.hpp) - -The C/C++ interface procedures are located with `ast.hpp` (for the Code type), and `code_types.hpp` for all others. - -## Serialization - -All code types can either serialize using a function of the pattern: - -```c -StrBuilder _to_strbuilder(Code code); -// or -_to_strbuilder(Code code, StrBuilder& result); -``` - -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.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). - -Gencpp's serialization does not provide coherent formatting of the code. The user should use a formatter after serializing. diff --git a/thirdparty/gencpp_c11/AST_Types.md b/thirdparty/gencpp_c11/AST_Types.md deleted file mode 100644 index dbba845..0000000 --- a/thirdparty/gencpp_c11/AST_Types.md +++ /dev/null @@ -1,788 +0,0 @@ -## Navigation - -[Top](../Readme.md) - -<- [docs - General](Readme.md) - -# AST Types Documentation - -While the Readme for docs covers the data layout per AST, this will focus on the AST types available, and their nuances. - -## Body - -These are containers representing a scope body of a definition that can be of the following `CodeType` type: - -* Class_Body -* Enum_Body -* Export_Body -* Extern_Linkage_Body -* Function_Body -* Global_Body -* Namespace_Body -* Struct_Body -* Union_Body - -Fields: - -```cpp -StrCached Name; -Code Front; -Code Back; -Token* Tok; -Code Parent; -CodeType 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 CodeType type for the type of definition used. - -Serialization: - -Will output only the entries, the braces are handled by the parent. - -```cpp - -... - -``` - -## Attributes - -Represent standard or vendor specific C/C++ attributes. - -Fields: - -```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp - -``` - -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 -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp - -``` - -The parser will preserve 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; -StrCached Name; -CodeType Prev; -CodeType Next; -Token* Tok; -Code Parent; -CodeType Type; -ModuleFlag ModuleFlags; -AccessSpec ParentAccess; -``` - -Serialization: - -```cpp -// Class_Fwd - ; - -// Class - : , public Next>, ... -{ - -}; -``` - -You'll notice that only one parent type is supported only with parent access. This library only supports single inheritance, the rest are assumed to be interfaces and are given public acess specifiers. - -## Constructor - -Fields: - -```cpp -CodeComment InlineCmt; // Only supported by forward declarations -Code InitializerList; -CodeParams Params; -Code Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp -// Constructor_Fwd - Name>( ); - -// Constructor - Name>( ) - : -{ - -} - -// Constructor Source Implementation - ::~Name>( ) -{ - -} -``` - -## Define - -Represents a preprocessor define - -Fields: - -```cpp -CodeDefineParams Params; -Code Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp -#define -``` - -## DefineParams - -Preprocessor define's parameters. - -Fields: - -```cpp -StrCached Name; -Code Last; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -s32 NumEntries; -``` - -Serialization: - -```cpp -, ... -``` - -## Destructor - -Fields: - -```cpp -CodeComment InlineCmt; -CodeSpecifiers Specs; -Code Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp -// Destructor_Fwd - ~Name>( ) ; - -// Destructor - ~Name>( ) -{ - -} - -// Destructor Source Implementation - ::~Name>( ) -{ - -} -``` - -## Enum - -Fields: - -```cpp -CodeComment InlineCmt; -CodeAttributes Attributes; -CodeType UnderlyingType; -Code UnderlyingTypeMacro; -CodeBody Body; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -StrCached Name; -CodeType Type; -ModuleFlag ModuleFlags; -``` - -UnderlyingTypeMacro is a macro the library natively supports: `enum_underlying(type)` that is meant to behave as a wrapper for underlying type assignment. -The `enum_underlying_sig` is a `Str` global var that can be set which will be defined within `PreprocessorDefines` and used in `parser_parse_enum` to identify a valid macro. - -Serialization: - -```cpp -// Enum_Fwd - enum class : or ; - -// Enum - : or -{ - -}; -``` - -## Execution - -Just represents an execution body. Equivalent to an untyped body. -Will be obsolete when function body parsing is implemented. - -Fields: - -```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp - -``` - -## External Linkage (Extern) - -Fields: - -```cpp -CodeBody Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp -extern "" -{ - -} -``` - -## Include - -Fields: - -```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Code Parent; -Token* Tok; -CodeType Type; -``` - -Serialization: - -```cpp -#include -``` - -## 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; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp -friend ; -``` - -## Function - -Fields: - -```cpp -CodeComment InlineCmt; -CodeAttributes Attributes; -CodeSpecifiers Specs; -CodeType ReturnType; -CodeParams Params; -CodeBody Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -ModuleFlag ModuleFlags; -``` - -Serialization: - -```cpp -// Function_Fwd - ( ) ; - -// Function - ( ) -{ - -} -``` - -## Module - -Fields: - -```cpp -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -ModuleFlag ModuleFlags; -``` - -Serialization: - -```cpp - module ; -``` - -## Namespace - -Fields: - -```cpp -CodeBody Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -ModuleFlag ModuleFlags; -``` - -Serialization: - -```cpp - namespace -{ - -} -``` - -## Operator Overload (Operator) - -Fields: - -```cpp -CodeComment InlineCmt; -CodeAttributes Attributes; -CodeSpecifiers Specs; -CodeType ReturnType; -CodeParams Params; -CodeBody Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -ModuleFlag ModuleFlags; -OperatorT Op; -``` - -Serialization: - -```cpp -// Operator_Fwd - operator ( ) ; - -// Operator - operator ( ) -{ - -} -``` - -## Operator Cast Overload ( User-Defined Type Conversion, OpCast ) - -Fields: - -```cpp -CodeComment InlineCmt; -CodeSpecifiers Specs; -CodeType ValueType; -CodeBody Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp -// Operator_Cast_Fwd - operator () ; - -// Operator_Cast - operator () -{ - -} -``` - -## Parameters (AST_Params) - -Fields: - -```cpp -CodeType ValueType; -Code Macro; -Code Value; -Code PostNameMacro; -StrCached Name; -CodeParams Last; -CodeParams Next; -Token* Tok; -Code Parent; -CodeType Type; -s32 NumEntries; -``` - -Serialization: - -```cpp -, ... - - = , ... -``` - -## Pragma - -Fields: - -```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp -#pragma -``` - -## Preprocessor Conditional - -Fields: - -```cpp -StrCached Content; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -``` - -Serialization: - -```cpp -# -``` - -## Specifiers - -Fields: - -```cpp -SpecifierT ArrSpecs[ AST_ArrSpecs_Cap ]; -CodeSpecifiers NextSpecs; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -s32 NumEntries; -``` - -Serialization: - -```cpp -, ... -``` - -## Template - -Fields: - -```cpp -CodeParams Params; -Code Declaration; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -ModuleFlag ModuleFlags; -``` - -Serialization: - -```cpp - -template< > - -``` - -## Typename - -Typenames represent the type "symbol". - -Fields: - -```cpp -CodeAttributes Attributes; -CodeSpecifiers Specs; -CodeReturnType ReturnType; -CodeParams Params; -Code ArrExpr; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -StrCached Name; -CodeType Type; -b32 IsParamPack; -ETypenameTag TypeTag; -``` - -Serialization: - -```cpp - -// Function - -``` - -`` currently has the full serialization of anything with - -*Note: ArrExpr is not used in serialization by `typename_to_strbuilder_ref` its instead handled by a parent AST's serailization (variable, typedef, using).* - -## Typedef - -Behave as usual except function or macro typedefs. -Those (macros) don't use the underlying type field as everything was serialized under the Name field. - -Fields: - -```cpp -CodeComment InlineCmt; -Code UnderlyingType; -StrCached Name; -Code Prev; -Code Next; -Token* Tok -Code Parent; -CodeType Type; -ModuleFlag ModuleFlags; -b32 IsFunction; -``` - -Serialization: - -```cpp -// Regular - typedef ; - -// Functions - -// Currently: - typedef ; - -// Desired: Not handled yet - typedef ReturnType> UnderlyingType->Name> ( Parameters> ); - typedef ReturnType> ( Namespace> forhas(Spec_Ptr) ?: *> Name> ) ( Parameters> ); -``` - -## Union - -Fields: - -```cpp -CodeAttributes Attributes; -CodeBody Body; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -ModuleFlag ModuleFlags; -``` - -Serialization: - -```cpp - union -{ - -} -``` - -## Using - -Fields: - -```cpp -CodeComment InlineCmt; -CodeAttributes Attributes; -CodeType UnderlyingType; -StrCached Name; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -ModuleFlag ModuleFlags; -``` - -Serialization: - -```cpp -// Regular - using = ; - -// Namespace - using namespace ; -``` - -## Variable - -[Algo](./Parser_Algo.md:) - -Fields: - -```cpp -CodeComment InlineCmt; -CodeAttributes Attributes; -CodeSpecifiers Specs; -CodeType ValueType; -Code BitfieldSize; -Code Value; -StrCached Name; -CodeVar NextVar; -Code Prev; -Code Next; -Token* Tok; -Code Parent; -CodeType Type; -ModuleFlag ModuleFlags; -s32 VarParenthesizedInit; -``` - -Serialization: - -```cpp -// Regular - = , NextVar ...; - -// Bitfield - : = , NextVar ...; - -// VarParenthesizedInit - ( , NextVar ... ); -``` diff --git a/thirdparty/gencpp_c11/Parser_Algo.md b/thirdparty/gencpp_c11/Parser_Algo.md deleted file mode 100644 index 82594c2..0000000 --- a/thirdparty/gencpp_c11/Parser_Algo.md +++ /dev/null @@ -1,1221 +0,0 @@ -## Navigation - -[Top](../Readme.md) - -<- [docs - General](Readme.md) - -# Parser's Algorithm - -gencpp uses a hand-written recursive descent parser. Both the lexer and parser currently handle a full C/C++ file in a single pass. - -## Notable implementation background - -### Lexer - -File: [lexer.cpp](../base/components/lexer.cpp) - -The `lex` procedure does the lexical pass of content provided as a `Str` type. -The tokens are stored (for now) in `Lexer_Tokens`. - -Fields: - -```cpp -Array Arr; -s32 Idx; -``` - -What token types are supported can be found in [ETokType.csv](../base/enums/ETokType.csv) you can also find the token types in [ETokType.h](../base/components/gen/etoktype.cpp) , which is the generated enum from the csv file. - -```cpp -struct Token -{ - Str Text; - TokType Type; - s32 Line; - s32 Column; - u32 Flags; -} -``` - -Flags is a bitfield made up of TokFlags (Token Flags): - -* `TF_Operator` : Any operator token used in expressions -* `TF_Assign` - * Using statment assignment - * Parameter argument default value assignment - * Variable declaration initialization assignment -* `TF_Preprocess` : Related to a preprocessing directive -* `TF_Preprocess_Cond` : A preprocess conditional -* `TF_Attribute` : An attribute token -* `TF_AccessSpecifier` : An accesor operation token -* `TF_Specifier` : One of the specifier tokens -* `TF_EndDefinition` : Can be interpreted as an end definition for a scope. -* `TF_Formatting` : Considered a part of the formatting -* `TF_Literal` : Anything considered a literal by C++. -* `TF_Macro_Functional` : Used to indicate macro token is flagged as `MF_Functional`. -* `TF_Macro_Expects_Body` : Used to indicate macro token is flagged as `MF_Expects_Body`. - -### Parser - -Files: - -* [interface.parsering.cpp](../base/components/interface.parsing.cpp) -* [parser.cpp](../base/components/parser.cpp) - -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. 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 - parse_( Str 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 have the following format: - -```cpp -internal - parse_( ) -{ - push_scope(); - - ... - - result = () make_code(); - ... - - Context.pop(); - return result; -} -``` - -The parsing implementation contains throughut the codeapths to indicate how far their contextual AST node has been resolved. - -Example: - -```c -internal -CodeFn parser_parse_function() -{ - push_scope(); - - Specifier specs_found[16] = { Spec_NumSpecifiers }; - s32 NumSpecifiers = 0; - - CodeAttributes attributes = { nullptr }; - CodeSpecifiers specifiers = { nullptr }; - ModuleFlag mflags = ModuleFlag_None; - - if ( check(Tok_Module_Export) ) { - mflags = ModuleFlag_Export; - eat( Tok_Module_Export ); - } - // - - attributes = parse_attributes(); - // - - while ( left && tok_is_specifier(currtok) ) - { - Specifier spec = str_to_specifier( tok_to_str(currtok) ); - - switch ( spec ) - { - GEN_PARSER_FUNCTION_ALLOWED_SPECIFIER_CASES: - break; - - default: - log_failure( "Invalid specifier %S for functon\n%SB", spec_to_str(spec), parser_to_strbuilder(_ctx->parser) ); - parser_pop(& _ctx->parser); - return InvalidCode; - } - - if ( spec == Spec_Const ) - continue; - - specs_found[NumSpecifiers] = spec; - NumSpecifiers++; - eat( currtok.Type ); - } - - if ( NumSpecifiers ) { - specifiers = def_specifiers_arr( NumSpecifiers, specs_found ); - } - // - - CodeTypename ret_type = parser_parse_type(parser_not_from_template, nullptr); - if ( cast(Code, ret_type) == Code_Invalid ) { - parser_pop(& _ctx->parser); - return InvalidCode; - } - // - - Token name = parse_identifier(nullptr); - _ctx->parser.Scope->Name = name.Text; - if ( ! tok_is_valid(name) ) { - parser_pop(& _ctx->parser); - return InvalidCode; - } - // - - CodeFn result = parse_function_after_name( mflags, attributes, specifiers, ret_type, name ); - // ... - - parser_pop(& _ctx->parser); - return result; -} -``` - -In the above `parse_function` implementation: - -`// ...` - -Will be conventionlly used where by that point in time for the codepath: `` should be resolved for the AST. - -## Outline of parsing codepaths - -Below is an outline of the general alogirithim used for these internal procedures. The intention is to provide a basic briefing to aid the user in traversing the actual code definitions. These appear in the same order as they are in the `parser.cpp` file - -***NOTE: This is still heavily in an alpha state. A large swaph of this can change, make sure these docs are up to date before considering them 1:1 with the repo commit your considering.*** - -## `parse_array_decl` - -1. Push parser scope -2. Check for empty array `[]` - 1. Return untyped string with single space if found -3. Check for opening bracket `[` - 1. Validate parser not at EOF - 2. Reject empty array expression - 3. Capture expression tokens until closing bracket - 4. Calculate expression span length - 5. Convert to untyped string -4. Validate and consume closing bracket `]` -5. Handle multi-dimensional case - 1. If adjacent `[` detected, recursively parse - 2. Link array expressions via Next pointer -6. Pop parser scope -7. Return array expression or NullCode on failure - -## `parse_attributes` - -1. Push parser scope and initialize tracking - 1. Store initial token position - 2. Initialize length counter -2. Process attributes while available - 1. Handle C++ style attributes `[[...]]` - 1. Consume opening `[[` - 2. Capture content until closing `]]` - 3. Calculate attribute span length - 2. Handle GNU style `__attribute__((...))` - 1. Consume `__attribute__` keyword and opening `((` - 2. Capture content until closing `))` - 3. Calculate attribute span length - 3. Handle MSVC style `__declspec(...)` - 1. Consume `__declspec` and opening `(` - 2. Capture content until closing `)` - 3. Calculate attribute span length - 4. Handle macro-style attributes - 1. Consume attribute token - 2. If followed by parentheses - 1. Handle nested parentheses tracking - 2. Capture content maintaining paren balance - 3. Calculate attribute span length -3. Generate attribute code if content captured - 1. Create attribute text span from start position and length - 2. Strip formatting from attribute text - 3. Construct Code node - 1. Set type to `CT_PlatformAttributes` - 2. Cache and set Name and Content fields - 4. Return as CodeAttributes -4. Pop parser scope -5. Return NullCode if no attributes found - -## `parse_class_struct` - -1. Validate token type is class or struct - 1. Return InvalidCode if validation fails -2. Initialize class/struct metadata - 1. Access specifier (default) - 2. Parent class/struct reference - 3. Class/struct body - 4. Attributes - 5. Module flags -3. Parse module export flag if present - 1. Set ModuleFlag_Export - 2. Consume export token -4. Consume class/struct token -5. Parse attributes via `parse_attributes()` -6. Parse class/struct identifier - 1. Update parser scope name -7. Initialize interface array (4KB arena) -8. Parse inheritance/implementation - 1. If classifier token (`:`) present - 1. Parse access specifier if exists - 2. Parse parent class/struct name - 3. Parse additional interfaces - 1. Separated by commas - 2. Optional access specifiers - 3. Store in interface array -9. Parse class body if present - 1. Triggered by opening brace - 2. Parse via `parse_class_struct_body` -10. Handle statement termination - 1. Skip for inplace definitions - 2. Consume semicolon - 3. Parse inline comment if present -11. Construct result node - 1. Create class definition if Tok_Decl_Class - 2. Create struct definition if Tok_Decl_Struct - 3. Attach inline comment if exists -12. Cleanup interface array and return result - -## `parse_class_struct_body` - -1. Initialize scope and body structure - 1. Push parser scope - 2. Consume opening brace - 3. Create code node with `CT_Class_Body` or `CT_Struct_Body` type -2. Parse body members while not at closing brace - 1. Initialize member parsing state - 1. Code member (InvalidCode) - 2. Attributes (null) - 3. Specifiers (null) - 4. Function expectation flag - 2. Handle preprocessor hash if present - 3. Process member by token type in switch statement - 1. Statement termination - warn and skip - 2. Newline - format member - 3. Comments - parse comment - 4. Access specifiers - `public/protected/private` - 5. Declarations - `class/enum/struct/union/typedef/using` - 6. Operators - `destructors/casts` - 7. Preprocessor directives - `define/include/conditionals/pragmas` - 8. Preprocessor statement macros - 9. Report naked preprocossor expression macros detected as an error. - 10. Static assertions - 11. Attributes and specifiers - 1. Parse attributes - 2. Parse valid member specifiers - 3. Handle `attribute-specifier-attribute` case - 12. Identifiers and types - 1. Check for constructors - 2. Parse `operator/function/variable` - 13. Default - capture unknown content until closing brace - 4. Validate member parsing - 1. Return InvalidCode if member invalid - 2. Append valid member to body -3. Finalize body - 1. Consume closing brace - 2. Pop parser scope - 3. Return completed CodeBody - -## `parse_comment` - -1. Just wrap the token into a cached string ( the lexer did the processing ) - -## `parse_complicated_definition` - -1. Initialize parsing context - 1. Push scope - 2. Set inplace flag false - 3. Get token array reference -2. Scan ahead for statement termination - 1. Track brace nesting level - 2. Find first semicolon at level 0 -3. Handle declaration variants - 1. Forward declaration case - 1. Check if only 2 tokens before semicolon - 2. Parse via `parse_forward_or_definition` - 2. Function with trailing specifiers - 1. Identify trailing specifiers - 2. Check for function pattern - 3. Parse as `operator/function/variable` - 4. Return `InvalidCode` if pattern invalid - 3. Identifier-based declarations - 1. Check identifier patterns - 1. Inplace definition `{...} id;` - 2. Namespace type variable `which id id;` - 3. Enum with class qualifier - 4. `Pointer/reference` types - 2. Parse as `operator/function/variable` if valid - 3. Return `InvalidCode` if pattern invalid - 4. Basic type declarations - 1. Validate enum class pattern - 2. Parse via `parser_parse_enum` - 3. Return `InvalidCode` if invalid - 5. Direct definitions - 1. Handle closing brace - `parse_forward_or_definition` - 2. Handle array definitions - `parse_operator_function_or_variable` - 3. Return InvalidCode for unknown patterns - -## `parse_assignment_expression` - -1. Initialize expression parsing - 1. Null expression pointer - 2. Consume assignment operator token - 3. Capture initial expression token -2. Validate expression presence - 1. Check for immediate termination - 2. Return `InvalidCode` if missing expression -3. Parse balanced expression - 1. Track nesting level for - 1. Curly braces - 2. Parentheses - 2. Continue until - 1. End of input, or - 2. Statement terminator, or - 3. Unnested comma - 3. Consume tokens sequentially -4. Generate expression code - 1. Calculate expression span length - 2. Convert to untyped string - 3. Return expression node - -## `parse_forward_or_definition` - -1. Declaration type routing - 1. Class (`Tok_Decl_Class`) -> `parser_parse_class` - 2. Enum (`Tok_Decl_Enum`) -> `parser_parse_enum` - 3. Struct (`Tok_Decl_Struct`) -> `parser_parse_struct` - 4. Union (`Tok_Decl_Union`) -> `parser_parse_union` -2. Error handling - 1. Return `InvalidCode` for unsupported token types - 2. Log failure with parser context - -`is_inplace` flag propagates to specialized codepaths to maintain parsing context. - -## `parse_function_after_name` - -This is needed as a function definition is not easily resolvable early on, as such this function handles resolving a function -after its been made ceratin that the type of declaration or definition is indeed for a function signature. - -By the point this function is called the following are known : export module flag, attributes, specifiers, return type, & name - -1. Parameter parsing - 1. Push scope - 2. Parse parameter list with parentheses -2. Post-parameter specifier processing - 1. Collect trailing specifiers - 2. Initialize or append to existing specifiers -3. Parse function termination - 1. Function body case - 1. Parse body if open brace found - 2. Validate body type (`CT_Function_Body` or `CT_Untyped`) - 2. Pure virtual case - 1. Handle "`= 0`" syntax - 2. Append pure specifier - 3. Forward declaration case - 1. Consume statement terminator - 4. Handle inline comments for all cases -4. Construct function node - 1. Strip whitespace from name - 2. Initialize `CodeFn` with base properties - 1. Name (cached, stripped) - 2. Module flags - 3. Set node type - 1. `CT_Function` if body present - 2. `CT_Function_Fwd` if declaration only - 4. Attach components - 1. Attributes if present - 2. Specifiers if present - 3. Return type - 4. Parameters if present - 5. Inline comment if present -5. Cleanup and return - 1. Pop scope - 2. Return completed function node - -## `parse_function_body` - -Currently there is no actual parsing of the function body. Any content with the braces is shoved into an execution AST node. -In the future statements and expressions will be parsed. - -1. Initialize body parsing - 1. Push scope - 2. Consume opening brace - 3. Create CodeBody with CT_Function_Body type -2. Capture function content - 1. Record start token position - 2. Track brace nesting level - 3. Consume tokens while - 1. Input remains AND - 2. Not at unmatched closing brace - 4. Update level counters - 1. Increment on open brace - 2. Decrement on closing brace when level > 0 -3. Process captured content - 1. Calculate content length via pointer arithmetic - 2. Create execution block if content exists - 1. Construct string span from start position and length - 2. Wrap in execution node - 3. Append to body -4. Finalize - 1. Consume closing brace - 2. Pop scope - 3. Return cast body node - -## `parse_global_nspace` - -1. State initialization - 1. Push parser scope - 2. Validate namespace type (Global, Namespace, Export, Extern Linkage) - 3. Consume opening brace for non-global scopes - 4. Initialize `CodeBody` with specified body type: `which` -2. Member parsing loop (while not at closing brace) - 1. Reset parse state - * Member code - * Attributes - * Specifiers - * Function expectation flag - 2. Member type handling - 1. Declarations - * `Class/Struct/Union/Enum` via `parse_complicated_definition` - * `Template/Typedef/Using` via dedicated parsers - * `Namespace/Export/Extern` declarations - 2. Preprocessor directivess - * Include/Define - * Conditionals `(if / ifdef / ifndef / elif / else / endif)` - * Pragmas - * Preprocessor statement macros - * Report naked preprocossor expression macros detected as an error. - 3. Comments/Formatting - * Newlines - * Comments - 4. Static assertions - 3. Attributes and specifiers - 1. Parse attributes if present - 2. Collect valid specifiers (max 16) - 3. Handle `consteval` for function expectation - 4. Identifier resolution - 1. Check `constructor/destructor` implementation - 2. Look ahead for user defined operator implementation outside of class - 3. Default to `operator/function/variable` parse -3. Member validation/storage - 1. Validate parsed member - 2. Append to body if valid - 3. Return `InvalidCode` on parse failure -4. Scope finalization - 1. Consume closing brace for non-global scopes - 2. Pop parser scope - 3. Return completed body - -## `parse_global_nspace_constructor_destructor` - -1. Forward Token Analysis - 1. Scan for parameter list opening parenthesis - 2. Template Expression Handling - * Track template nesting depth - * Account for nested parentheses within templates - * Skip until template closure or parameter start - -```cpp - // Valid patterns: - ClassName :: ClassName(...) - ClassName :: ~ClassName(...) - ClassName< T ... > :: ClassName(...) -``` - -2. Constructor/Destructor Identification - 1. Token Validation Sequence - * Verify identifier preceding parameters - * Check for destructor indicator (`~`) - * Validate scope resolution operator (`::`) - 2. Left-side Token Analysis - * Process nested template expressions - * Maintain template/capture level tracking - * Locate matching identifier token -3. Parser Resolution - 1. Name Pattern Validation - * Compare identifier tokens for exact match - 2. Specialized Parsing - * Route to `parser_parse_destructor` for '~' prefix - * Route to `parser_parse_constructor` for direct match - 3. Apply specifiers to resulting node -4. Return result (`NullCode` on pattern mismatch) - -### Implementation Constraints - -* Cannot distinguish nested namespaces with identical names -* Return type detection requires parser enhancement -* Template parameter validation is syntax-based only -* Future enhancement: Implement type parsing with rollback capability - -## `parse_identifier` - -This is going to get heavily changed down the line to have a more broken down "identifier expression" so that the qualifier, template args, etc, can be distinguished between the targeted identifier. -The function can parse all of them, however the AST node compresses them all into a string. - -1. Initialize identifier context - 1. Push parser scope - 2. Capture initial token as name - 3. Set scope name from token text -2. Process initial identifier component - 1. Consume identifier token - 2. Parse template arguments if present -3. Handle qualified identifiers (loop while `::` found) - 1. Consume static access operator - 2. Validate token sequence: - 1. Handle destructor operator (`~`) - * Validate destructor parsing context - * Update name span if valid - * Return invalid on context mismatch - 2. Process member function pointer (`*`) - * Set possible_member_function flag if context allows - * Return invalid if pointer unexpected - 3. Verify identifier token follows - 3. Update identifier span - 1. Extend name length to include new qualifier - 2. Consume identifier token - 3. Parse additional template arguments -4. Return completed identifier token - -Notes: - -* Current implementation treats identifier as single token span -* TODO: Refactor to AST-based identifier representation for: - * Better support for nested symbol resolution - -## `parse_include` - -1. Consume include directive -2. Consume the path - -## `parse_operator_after_ret_type` - -This is needed as a operator definition is not easily resolvable early on, as such this function handles resolving a operator after its been made ceratin that the type of declaration or definition is indeed for a operator signature. - -By the point this function is called the following are known : export module flag, attributes, specifiers, and return type - -1. Initialize operator context - 1. Push scope - 2. Parse qualified namespace identifier - 3. Consume `operator` keyword -2. Operator identification - 1. Validate operator token presence - 2. Set scope name from operator token - 3. Map operator token to internal operator enum: - * Arithmetic: `+, -, *, /, %` - * Assignment: `+=, -=, *=, /=, %=, =` - * Bitwise: `&, |, ^, ~, >>` - * Logical: `&&, ||, !, ==` - * Comparison: `<, >, <=, >=` - * Member access: `->, ->*` - * Special: `(), [], new, delete` - 4. Handle array variants for new/delete -3. Parameter and specifier processing - 1. Parse parameter list - 2. Handle multiply/member-pointer ambiguity - 3. Collect trailing specifiers - 4. Merge with existing specifiers -4. Function body handling - 1. Parse implementation if present - 2. Otherwise consume statement terminator - 3. Capture inline comments -5. Result construction - 1. Create operator node with: - * Operator type - * Namespace qualification - * Parameters - * Return type - * Implementation body - * Specifiers - * Attributes - * Module flags - 2. Attach inline comments -6. Pop scope - -## `parse_operator_function_or_variable` - -When this function is called, attribute and specifiers may have been resolved, however what comes next can still be either an operator, function, or variable. - -1. Initial Type Resolution - 1. Push parsing scope - 2. Handle macro definitions via `parse_macro_as_definition` - 3. Parse base type, validate result - 4. Exit on invalid type -2. Declaration Classification - 1. Scan token stream for `operator` keyword - 2. Track static symbol access - 3. Branch handling: - * Operator overload: Forward to `parse_operator_after_ret_type` - * Function/variable: Parse identifier and analyze context -3. Function/Variable Disambiguation - 1. Parse identifier - 2. Analyze token patterns: - * Detect parameter capture via parenthesis - * Check for constructor initialization pattern - * Handle variadic argument cases - 3. Macro Expression Analysis: - * Validate functional macros - * Track parenthesis balance - * Detect comma patterns -4. Declaration Parsing - 1. Function path - * Verify function expectation (`consteval`) - * Delegate to `parse_function_after_name` - 2. Variable path - * Validate against function expectation - * Forward to `parse_variable_after_name` - -## `parse_macro_as_definition` - -1. Validation - 1. Check token type (Tok_Preprocess_Macro_Stmt) - 2. Retrieve macro from lookup - 3. Verify `MF_Allow_As_Definition` flag -2. Macro Processing - 1. Parse via `parse_simple_preprocess` - 2. Maintain original token categorization -3. Definition Construction - 1. Format components: - * Attributes (if present) - * Specifiers (if present) - * Macro content - 2. Build unified string representation - 3. Convert to untyped code node - -Notes: - -* Early exits return NullCode for non-qualifying macros -* TODO: Pending AST_Macro implementation for proper attribute/specifier support - -## `parse_pragma` - -1. Consume pragma directive -2. Process the token content into cached string - -## `parse_params` - -1. Parameter List Initialization - 1. Delimiter handling based on context - * Parentheses: `(...)` for standard parameters - * Angle brackets: `<...>` for template parameters - 2. Early return for empty parameter lists - 3. Initial parameter component initialization - * Macro reference - * Type information - * Parameter value - * Identifier token -2. Primary Parameter Processing - 1. Handle varadic arguments - 2. Process preprocessor macros (`UPARAM` style) - 3. Parse parameter sequence - * Type information - * Optional identifier - * Post-name macro expressions - * Default value expressions - 4. Value expression capture with nested structure tracking - * Template depth counting - * Parentheses balance - * Text span calculation -3. Multi-Parameter Handling - 1. Parse comma-separated entries - 2. Maintain parameter structure - * Macro context - * Type information - * Identifier caching - * Post-name macro persistence - * Value assignments - 3. Parameter list construction via `params_append` -4. Consume params capture termination token & return result. - -## `parse_preprocess_cond` - -1. Parse conditional directive -2. Process directive's content expression - -## `parse_simple_preprocess` - -1. Basic Setup - 1. Push scope - 2. Capture initial macro token - 3. Validate macro registration - * Lookup in macro registry - * Skip validation for unsupported macros -2. Functional Macro Processing - 1. Handle macro invocation - * Parse opening parenthesis - * Track nested parenthesis level - * Capture parameter content - * Update macro span length -3. Macro Body Handling - 1. Process associated block if macro expects body - * Parse curly brace delimited content - * Track nesting level - * Capture body content - 2. Handle statement termination - * Context-specific semicolon handling - * Process inline comments - * Update macro span -4. Context-Specific Termination - 1. Special case handling - * Enum context bypass - * Typedef context validation - * Global/class scope handling - 2. Statement termination rules - * Process semicolons based on context - * Update token span accordingly - -Notes: - -* Pending AST_Macro implementation for improved structure -* Current implementation uses simple token span capture - -## `parse_static_assert` - -1. Consume static assert and opening curly brace -2. Consume all tokens until the the closing brace is reached. -3. Consume curly brace and end statement -4. Place all tokens within braces into a content for the assert. - -## `parse_template_args` - -This will get changed heavily once we have better support for typename expressions - -1. Consume opening angle bracket -2. Consume all tokens until closing angle bracket -3. Consme closing angle bracket -4. Return the currtok with the ammended length. - -## `parse_variable_after_name` - -This is needed as a variable definition is not easily resolvable early on, it takes a long evaluation period before its known that the declaration or definition is a variable. As such this function handles resolving a variable. -By the point this function is called the following are known : export module flag, attributes, specifiers, value type, name - -1. Initialization Processing - 1. Array dimension parsing - 2. Expression capture - * Assignment expressions - * Constructor initializations - * Bitfield specifications -2. Expression Pattern Handling - 1. Direct assignment (`=`) - * Parse assignment expression - 2. Brace initialization (`{}`) - * Track nested braces - * Capture initialization list - 3. Constructor initialization (`()`) - * Track parenthesis nesting - * Update initialization flag - 4. Bitfield specification (`:`) - * Validate non-empty expression - * Capture bitfield size -3. Multi-Variable Processing - 1. Handle comma-separated declarations - 2. Statement termination - * Process semicolon - * Capture inline comments - 3. Link variable chain via NextVar -4. AST Node Construction - 1. Core properties - * Type (`CT_Variable`) - * Name caching - * Module flags - * Value type - 2. Optional components - * Array expression - * Bitfield size - * Attributes/Specifiers - * Initialization value - * Constructor flag - * Parent/Next linkage - -## `parse_variable_declaration_list` - -1. Chain Initialization - 1. Initialize null variable chain head and tail - 2. Process while comma token present -2. Per-Variable Processing - 1. Specifier Collection - * Validate specifier ordering (const after pointer) - * Handle core specifiers: `ptr, ref, rvalue` - * Maintain specifier chain integrity - * Log invalid specifier usage but continue parsing - 2. Variable Declaration - * Extract identifier name - * Parse remainder via `parse_variable_after_name` - * Note: Function pointers unsupported -3. Chain Management - 1. First Variable - * Set as chain head and tail - 2. Subsequent Variables - * Link to previous via NextVar - * Establish parent reference - * Update tail pointer - -Limitations: - -* No function pointer support - -## `parser_parse_class` - -1. `parse_class_struct` - -## `parser_parse_constructor` - -1. Core Parse Sequence - 1. Identifier extraction and parameter list capture - 2. Handle construction variants: - * Colon-prefixed member initializer lists - * Direct body implementation - * Default/delete assignment forms - * Forward declarations -2. Initializer List Processing - 1. Track nested parentheses balance - 2. Capture full initializer span - 3. Convert to untyped string representation -3. Implementation Variants - 1. Body implementation - * Parse full function body - * Set `CT_Constructor` type - 2. Forward declaration - * Process terminator and comments - * Set `CT_Constructor_Fwd` type - 3. Special forms - * Handle assignment operator cases - * Capture inline comments for declarations -4. AST Construction - 1. Core node attributes - * Cached identifier name - * Parameter list linkage - * Specifier chain - 2. Optional components - * Initializer list - * Implementation body - * Inline comments - -## `parser_parse_define` - -1. Token Stream Preparation - 1. Handle optional preprocessor hash - 2. Consume define directive - 3. Validate identifier presence -2. Define Node Initialization - 1. Construct CodeDefine with `CT_Preprocess_Define` type - 2. Cache identifier name - 3. Update scope context -3. Parameter Processing (Functional Macros) - 1. Initial parameter detection - * Verify macro functionality - * Initialize parameter list node (`CT_Parameters_Define`) - 2. Parameter chain construction -4. Content Handling - 1. Content validation - * Verify presence - * Handle empty content case with newline - 2. Content processing - * Strip formatting - * Preserve line termination - * Create untyped node - -## `parser_parse_destructor` - -1. Context Validation - 1. Verify parser scope hierarchy - 2. Check global namespace context - 3. Process `virtual` specifier if present -2. Identifier Resolution - 1. Parse prefix identifier in global scope - 2. Validate destructor operator (`~`) - 3. Capture destructor name - 4. Enforce empty parameter list -3. Specifier Processing - 1. Handle pure virtual case (`= 0`) - * Append `Spec_Pure` to specifiers - * Set `pure_virtual` flag - 2. Process default specifier (= default) - * Parse as assignment expression - 3. Validate specifier syntax -4. Implementation Processing - 1. Function body (non-pure case) - * Parse complete body - * Set `CT_Destructor` type - 2. Forward declaration - * Handle statement termination - * Process inline comments - * Set `CT_Destructor_Fwd` type -5. AST Construction - 1. Build destructor node - 2. Handle qualified names - * Concatenate prefix and identifier - 3. Attach components - * Specifiers - * Implementation body - * Inline comments - -## `parser_parse_enum` - -1. Declaration Components - 1. Basic structure processing - * Enum type detection (`enum/enum class`) - * Attributes parsing - * Identifier capture - 2. Underlying type resolution - * Standard type parsing - * Macro-based underlying type handling - * Classifier token validation -2. Body Processing - 1. Entry parsing loop - * Preprocessor directives (`#define, #if, #pragma`) - * Enum member declarations - * Comment preservation - * Formatting tokens - 2. Entry value handling - * Assignment expressions - * `UMETA` macro support - * Entry termination (commas) - 3. Token span calculation for entries -3. AST Construction - 1. Node type determination - * `CT_Enum/CT_Enum_Class` for definitions - * `CT_Enum_Fwd/CT_Enum_Class_Fwd` for declarations - 2. Component attachment - * Name caching - * Body linkage - * Underlying type/macro - * Attributes - * Inline comments - -## `parser_parse_export_body` - -1. `parse_global_nspace` - -## `parser_parse_extern_link_body` - -1. `parse_global_nspace` - -## `parser_parse_extern_link` - -1. Consume `Tok_Decl_Extern_Linkage` -2. Consume the linkage identifier -3. `parse_extern_link_body` - -## `parser_parse_friend` - -1. Consume `friend` -2. Parse specifiers -3. `parse_type` -4. If the currok is an identifier its a function declaration or definition - 1. `parse_function_after_name` -5. Otherwise its a operator: `parse_operator_after_ret_type` -6. Consume end statement so long as its not a function definion -7. Check for inline comment, `parse_comment` if exists - -## `parser_parse_function` - -1. Check and parse for `export` -2. `parse_attributes` -3. Parse specifiers -4. `parse_type` for return type -5. `parse_identifier` -6. `parse_function_after_name` - -## `parser_parse_namespace` - -1. Consume namespace declaration -2. Parse identifier -3. `parse_global_namespace` - -## `parser_parse_operator` - -1. Check for and parse export declaration -2. `parse_attributes` -3. Parse specifiers -4. `parse_type` -5. `parse_operator_after_ret_type` - -## `parser_parse_operator_cast` - -1. Look for and parse a qualifier namespace for the cast (in-case this is defined outside the class's scope) -2. Consume operator declaration -3. `parse_type` -4. Consume opening and closing parethesis -5. Check for a const qualifiying specifier -6. Check to see if this is a definition (`{`) - 1. Consume `{` - 2. Parse body to untyped string (parsing statement and expressions not supported yet) - 3. Consume `}` -7. Otherwise: - 1. Consume end statement - 2. Check for and consume comment : `parse_comment` - -## `parser_parse_struct` - -1. `parse_class_struct` - -## `parser_parse_template` - -1. Initial State Configuration - 1. Module flag handling (`export` keyword) - 2. Template parameter parsing via `parse_params` - * Uses specialized template capture mode - * Validates parameter list integrity -2. Declaration Type Resolution - 1. Primary type dispatch - * `Class/Struct/Union` declarations - * Using declarations - 2. Function/Variable handling - * Attribute collection - * Specifier validation (16 max) - * Function expectation detection -3. Special Case Processing - 1. Global namespace constructors/destructors - * Context validation - * Delegation to `parse_global_nspace_constructor_destructor` - 2. Operator cast implementations - * Token lookahead for operator detection - * Static symbol access validation - * Cast parsing delegation -4. AST Construction - 1. Template node composition - * `CT_Template` type assignment - * Parameter linkage - * Declaration binding - * Module flag preservation - -## `parser_parse_type` - -This implementatin will be updated in the future to properly handle functional typename signatures. - -### Current Algorithm - -Anything that is in the qualifier capture of the function typename is treated as an expression abstracted as an untyped string - -1. `parse_attributes` -2. Parse specifiers -3. If the `parse_type` was called from a template parse, check to see if class was used instead of typname and consume as name. -4. This is where things get ugly for each of these depend on what the next token is. - 1. If its an in-place definition of a class, enum, struct, or union: - 2. If its a decltype (Not supported yet but draft impl there) - 3. If its a compound native type expression (unsigned, char, short, long, int, float, dobule, etc ) - 4. If its a typename amcro - 5. A regular type alias of an identifier -5. Parse specifiers (postfix) -6. We need to now look ahead to see If we're dealing with a function typename -7. If wer're dealing with a function typename: - 1. Shove the specifiers, and identifier code we have so far into a return type typename's Name (untyped string) - 1. Reset the specifiers code for the top-level typeanme - 2. Check to see if the next token is an identifier: - 1. `parse_identifier` - 3. Check to see if the next token is capture start and is not the last capture ("qualifier capture"): - 1. Consume `(` - 2. Consume expresssion between capture - 3. Consume `)` - 4. `parse_params` - 5. Parse postfix specifiers -8. Check for varaidic argument (param pack) token: - 1. Consume varadic argument token - -### WIP - Alternative Algorithm - -Currently wrapped up via macro: `GEN_USE_NEW_TYPENAME_PARSING` -Anything that is in the qualifier capture of the function typename is treated as an expression abstracted as an untyped string - -1. `parse_attributes` -2. Parse specifiers (prefix) -3. This is where things get ugly for each of these depend on what the next token is. - 1. If its an in-place definition of a class, enum, struct, or union: - 2. If its a decltype (Not supported yet but draft impl there) - 3. If its a compound native type expression (unsigned, char, short, long, int, float, dobule, etc ) - 4. If its a typename amcro - 5. A regular type alias of an identifier -4. Parse specifiers (postfix) - 1. If any specifiers are found populate specifiers code with them. -5. We need to now look ahead to see If we're dealing with a function typename -6. If wer're dealing with a function typename: - 1. Shove the specifiers, and identifier code we have so far into a return type typename's Name (untyped string) - 1. Reset the specifiers code for the top-level typename - 2. Check to see if the next token is an identifier: - 1. `parse_identifier` - 3. Check to see if the next token is capture start and is not the last capture ("qualifier capture"): - 1. Consume `(` - 2. Parse binding specifiers - 3. `parse_identifier` - 4. `parse_parameters` -> params_nested - 5. Consume `)` - 6. Construct a nested function typename definition for the qualifier `Name` - 4. `parse_params` - > params - 5. Parse postfix specifiers -7. Check for varaidic argument (param pack) token: - 1. Consume varadic argument token - -### **Later: Algorithm based on typename expressions** - -## `parse_typedef` - -1. Check for export module specifier -2. typedef keyword -3. If its a preprocess macro: Get the macro name -4. Else: - 1. Check to see if its a complicated definition (in-place enum, class, struct, union) - 2. If its a complicated definition: - 1. Perform the look ahead similar to `parse_complicated_definition`'s implementation - 2. Check to see if its a forward declaration : `parse_forward_declaration` - 3. If end[-1] is an identifier: - 1. Its either an in-place, varaible type qualified identifier, or indirection type: - 1. `parse_foward_or_definition` - 4. else if end[-1] is a closing curly brace - 1. Its a definition: `parse_forward_or_definition` - 5. else if end[-1] is a closing square brace - 2. Its an array definition: `parse_type` - 3. Else : `parse-type` - 4. Check for identifier : Consume the token - 5. `parse_array_decl` -5. Consume end statement -6. Check for inline comment : `parse_comment` - -## `parse_union` - -1. Check for export module specifier -2. union keyword -3. `parse_attributes` -4. Check for identifier -5. Parse the body (Possible options): - 1. Newline - 2. Comment - 3. Decl_Class - 4. Decl_Enum - 5. Decl_Struct - 6. Decl_Union - 7. Preprocess_Define - 8. Preprocess_Conditional (if, ifdef, ifndef, elif, else, endif) - 9. Preprocess_Macro (`MT_Statement` or `MT_Typename`) - 10. Preprocess_Pragma - 11. Unsupported preprocess directive - 12. Variable -6. If its not an inplace definiton: End Statement - -## `parse_using` - -1. Check for export module specifier -2. using keyword -3. Check to see if its a using namespace -4. Get the identifier -5. If its a regular using declaration: - 1. `parse_attributes` - 2. `parse_type` - 3. `parse_array_decl` -6. End statement -7. Check for inline comment - -## `parse_variable` - -1. Check for export module specifier -2. `parse_attributes` -3. `parse specifiers` -4. `parse_type` -5. `parse_identifier` -6. `parse_variable_after_name` diff --git a/thirdparty/gencpp_c11/Parsing.md b/thirdparty/gencpp_c11/Parsing.md deleted file mode 100644 index b05bdd7..0000000 --- a/thirdparty/gencpp_c11/Parsing.md +++ /dev/null @@ -1,159 +0,0 @@ -## Navigation - -[Top](../Readme.md) - -<- [docs - General](Readme.md) - -# Parsing - -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 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 ***perceive*** 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 ( Str class_def ); -CodeConstructor parse_constructor ( Str constructor_def ); -CodeDefine parse_define ( Str define_def ); -CodeDestructor parse_destructor ( Str destructor_def ); -CodeEnum parse_enum ( Str enum_def ); -CodeBody parse_export_body ( Str export_def ); -CodeExtern parse_extern_link ( Str exten_link_def ); -CodeFriend parse_friend ( Str friend_def ); -CodeFn parse_function ( Str fn_def ); -CodeBody parse_global_body ( Str body_def ); -CodeNS parse_namespace ( Str namespace_def ); -CodeOperator parse_operator ( Str operator_def ); -CodeOpCast parse_operator_cast( Str operator_def ); -CodeStruct parse_struct ( Str struct_def ); -CodeTemplate parse_template ( Str template_def ); -CodeType parse_type ( Str type_def ); -CodeTypedef parse_typedef ( Str typedef_def ); -CodeUnion parse_union ( Str union_def ); -CodeUsing parse_using ( Str using_def ); -CodeVar parse_variable ( Str 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***, ***includes***, and ***pragmas***. - -The keywords supported for the preprocessor are: - -* include -* define -* if -* ifdef -* elif -* endif -* pragma - -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. - -The preprocessor lines are stored as members of their associated scope they are parsed within ( Global, Namespace, Class/Struct ). -***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). -Exceptions: - -* variable 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` -* typedefs allow for a preprocessed macro: `typedef MACRO();` - * Disable with: `#define GEN_PARSER_DISABLE_MACRO_TYPEDEF` -* Macros can behave as typenames -* 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)* -*(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 contains some egregious preprocessor abuse.* - -Macros used within a file should be registered by the user before parsing. This can be done two ways: - -1. The register macro interface within [interface.hpp](../base/components/interface.hpp). -2. Using `def_define` to create a CodeDefine and making sure to not set `opts.dont_register_to_preprocess_macros` to `true`. - -## 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 ` ` -* `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. -* 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.* -* Attributes ( `[[]]` (standard), `__declspec` (Microsoft), or `__attribute__` (GNU) ) - * Assumed to *come before specifiers* (`const`, `constexpr`, `extern`, `static`, etc) for a function or right afterthe return type. - * Or in the usual spot for class, structs, (*right after the declaration keyword*) - * typedefs have attributes with the type (`parse_type`) -* 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. - -**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).** diff --git a/thirdparty/gencpp_c11/Readme.md b/thirdparty/gencpp_c11/Readme.md deleted file mode 100644 index 06691c9..0000000 --- a/thirdparty/gencpp_c11/Readme.md +++ /dev/null @@ -1,147 +0,0 @@ -## Navigation - -[Top](../Readme.md) - -* [docs](../docs/Readme.md) - -# C Library Generation - -`c_library.cpp` generates both *segemnted* and *singleheader* variants of the library compliant with C11. - -The output will be in the `gen_segmented/gen` directory (if the directory does not exist, it will create it). - -If using the library's provided build scripts: - -```ps1 -.\build.ps1 c_lib -``` - -To generate a static or dynamic library: - -```ps1 -.\build.ps1 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). - -**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 due 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. Segmented 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` `HashTable` within [containers.hpp](../base/dependencies/containers.hpp) - -Both files follow the same pattern of providing three procedures: - -* `gen__base` : Intended to be called once, defines universal "base" definitions. -* `gen_` : Called per instatiation of the container for a given set of dependent args. -* `gen__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 `_DefinitionCounter` is used to know how many instantiations of the template have occured. This is used to determine how to define `GENERIC_SLOT__` 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`... - -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. - -Many C11 libraries don't use it.. and, of those that do. they usually end up obfuscate it with excessive preprocessor abuse; Effort was put into minimizing how much of these macros are handled by the preprocessor vs gencpp itself. - -*(I will be explaining this thing for the rest of this seciton along with gencpp c library's usage of it)* - - -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( (selecting_exp), \ - 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. diff --git a/thirdparty/gencpp_c11/Readme_Docs.md b/thirdparty/gencpp_c11/Readme_Docs.md deleted file mode 100644 index da9fc57..0000000 --- a/thirdparty/gencpp_c11/Readme_Docs.md +++ /dev/null @@ -1,453 +0,0 @@ -# General Docs - -[Top](../Readme.md) - -Contains: - -* [AST_Design](./AST_Design.md): Overview of ASTs -* [AST Types](./AST_Types.md): Listing of all AST types along with their Code type interface. -* [Parsing](./Parsing.md): Overview of the parsing interface. -* [Parser Algo](./Parser_Algo.md): In-depth breakdown of the parser's implementation. - -### *CURRENTLY UNSUPPORTED* - -**There is no support for validating expressions.** -Its a [todo](https://github.com/Ed94/gencpp/issues/49) - -**Only trivial template support is provided.** -The intention is for only simple, non-recursive substitution. -The parameters of the template are treated like regular parameter AST entries. -This means that the typename entry for the parameter AST would be either: - -* `class` -* `typename` -* A fundamental type, function, or pointer type. - -***Concepts and Constraints are not supported*** -Its a [todo](https://github.com/Ed94/gencpp/issues/21) - -### Feature Macros - -* `GEN_DEFINE_ATTRIBUTE_TOKENS` : Allows user to define their own attribute macros for use in parsing. - * This can be generated using base.cpp. -* `GEN_DEFINE_LIBRARY_CORE_CONSTANTS` : Optional typename codes as they are non-standard to C/C++ and not necessary to library usage -* `GEN_DONT_ENFORCE_GEN_TIME_GUARD` : By default, the library ( gen.hpp/ gen.cpp ) expects the macro `GEN_TIME` to be defined, this disables that. -* `GEN_ENFORCE_STRONG_CODE_TYPES` : Enforces casts to filtered code types. -* `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_DONT_ALLOW_INVALID_CODE` (Not implemented yet) : Will fail when an invalid code is constructed, parsed, or serialized. -* `GEN_C_LIKE_CPP` : Setting to `` 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 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. - -The AST is managed by the library and provided to the user via its interface. -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) - -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* -*`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`* -*`StrBuilder` is the dynamically allocating string builder type for the library* - -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: - -```cpp -constexpr static -int AST_ArrSpecs_Cap = -( - AST_POD_Size - - sizeof(Code) - - sizeof(StrCached) - - sizeof(Code) * 2 - - sizeof(Token*) - - sizeof(Code) - - sizeof(CodeType) - - sizeof(ModuleFlag) - - sizeof(u32) -) -/ sizeof(Specifier) - 1; -``` -Data Notes: - -* 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. -* 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. -* Strings used for serialization and file buffers are not contained by those used for cached strings. - * `_ctx->Allocator_Temp` is used. -* 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. - * Any modifcations to an existing AST should be to just construct another with the modifications done on-demand while traversing the AST (non-destructive). - -The following CodeTypes are used which the user may optionally use strong typing with if they enable: `GEN_ENFORCE_STRONG_CODE_TYPES` - -* CodeBody : Has support for `for : range` iterating across Code objects. -* CodeAttributes -* CodeComment -* CodeClass -* CodeConstructor -* CodeDefine -* CodeDefineParams -* CodeDestructor -* CodeEnum -* CodeExec -* CodeExtern -* CodeInclude -* CodeFriend -* CodeFn -* CodeModule -* CodeNS -* CodeOperator -* CodeOpCast : User defined member operator conversion -* CodeParams : Has support for `for : range` iterating across parameters. -* CodePreprocessCond -* CodePragma -* CodeSpecifiers : Has support for `for : range` iterating across specifiers. -* CodeStruct -* CodeTemplate -* CodeTypename -* CodeTypedef -* CodeUnion -* CodeUsing -* CodeVar - -Each `struct Code` has an associated "filtered AST" with the naming convention: `AST_` -Unrelated fields of the AST for that node type are omitted and only necessary padding members are defined otherwise. - -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 -* Parsing -* Untyped - -### Upfront Construction - -All component ASTs must be previously constructed, and provided on creation of the code AST. -The construction will fail and return CodeInvalid otherwise. - -Interface :`` - -* def_attributes - * *This is pre-appended right before the function symbol, or placed after the class or struct keyword for any flavor of attributes used.* - * *Its up to the user to use the desired attribute formatting: `[[]]` (standard), `__declspec` (Microsoft), or `__attribute__` (GNU).* -* def_comment -* def_class -* def_constructor -* def_define -* def_define_params -* def_destructor -* def_enum -* def_execution - * *This is equivalent to untyped_str, except that its intended for use only in execution scopes.* -* def_extern_link -* def_friend -* def_function -* def_include -* def_module -* def_namespace -* def_operator -* def_operator_cast -* def_param -* def_params -* def_pragma -* def_preprocess_cond -* def_specifier -* def_specifiers -* def_struct -* def_template -* def_type -* def_typedef -* def_union -* def_using -* def_using_namespace -* def_variable - -Bodies: - -* def_body -* def_class_body -* def_enum_body -* def_export_body -* def_extern_link_body -* def_function_body - * *Use this for operator bodies as well* -* def_global_body -* def_namespace_body -* def_struct_body -* def_union_body - -Usage: - -```cpp - = def_( ... ); - -Code -{ - ... - = def_( ... ); -} - -``` - -All optional parmeters are defined within `struct Opts_def_`. 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_` 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: - -```cpp -def_global_body( args( ht_entry, array_ht_entry, hashtable )); - -// instead of: -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 bodyss -When the members have been populated use: `code_validate_body` to verify that the members are valid entires for that type. - -### Parse construction - -A string provided to the API is parsed for the intended language construct. - -Interface : - -* parse_class -* parse_constructor -* parse_define -* parse_destructor -* parse_enum -* parse_export_body -* parse_extern_link -* parse_friend -* parse_function -* parse_global_body -* parse_namespace -* parse_operator -* parse_operator_cast -* parse_struct -* parse_template -* parse_type -* parse_typedef -* parse_union -* parse_using -* parse_variable - -Usage: - -```cpp -Code = parse_( string with code ); - -Code = def_( ..., parse_( - -)); -``` - -### Untyped constructions - -Code ASTs are constructed using unvalidated strings. - -Interface : - -* token_fmt_va -* token_fmt -* untyped_str -* untyped_fmt -* untyped_token_fmt - -During serialization any untyped Code AST has its string value directly injected inline of whatever context the content existed as an entry within. -Even though these are not validated from somewhat correct c/c++ syntax or components, it doesn't mean that Untyped code can be added as any component of a Code AST: - -* Untyped code cannot have children, thus there cannot be recursive injection this way. -* Untyped code can only be a child of a parent of body AST, or for values of an assignment (ex: variable assignment). - -These restrictions help prevent abuse of untyped code to some extent. - -Usage Conventions: - -```cpp -Code = def_variable( , , untyped_( - -)); - -Code = untyped_str( code( - -)); -``` - -Optionally, `code_str`, and `code_fmt` macros can be used so that the code macro doesn't have to be used: - -```cpp -Code = code_str( ) -``` - -Template metaprogramming in the traditional sense becomes possible with the use of `token_fmt` and parse constructors: - -```cpp -Str value = txt("Something"); - -char const* template_str = txt( - Code with to replace with token_values - ... -); -char const* gen_code_str = token_fmt( "key", value, template_str ); -Code = parse_( gen_code_str ); -``` - -## Predefined Codes - -The following are provided predefined by the library as they are commonly used: - -* `enum_underlying_macro` -* `access_public` -* `access_protected` -* `access_private` -* `attrib_api_export` -* `attrib_api_import` -* `module_global_fragment` -* `module_private_fragment` -* `fmt_newline` -* `pragma_once` -* `param_varaidc` (Used for varadic definitions) -* `preprocess_else` -* `preprocess_endif` -* `spec_const` -* `spec_consteval` -* `spec_constexpr` -* `spec_constinit` -* `spec_extern_linkage` (extern) -* `spec_final` -* `spec_forceinline` -* `spec_global` (global macro) -* `spec_inline` -* `spec_internal_linkage` (internal macro) -* `spec_local_persist` (local_persist macro) -* `spec_mutable` -* `spec_neverinline` -* `spec_noexcept` -* `spec_override` -* `spec_ptr` -* `spec_pure` -* `spec_ref` -* `spec_register` -* `spec_rvalue` -* `spec_static_member` (static) -* `spec_thread_local` -* `spec_virtual` -* `spec_volatile` -* `t_empty` (Used for varaidc macros) -* `t_auto` -* `t_void` -* `t_int` -* `t_bool` -* `t_char` -* `t_wchar_t` -* `t_class` -* `t_typename` - -Optionally the following may be defined if `GEN_DEFINE_LIBRARY_CODE_CONSTANTS` is defined - -* `t_b32` -* `t_s8` -* `t_s16` -* `t_s32` -* `t_s64` -* `t_u8` -* `t_u16` -* `t_u32` -* `t_u64` -* `t_ssize` (ssize_t) -* `t_usize` (size_t) -* `t_f32` -* `t_f64` - -## Extent of operator overload validation - -The AST and constructors will be able to validate that the arguments provided for the operator type match the expected form: - -* If return type must match a parameter -* If number of parameters is correct -* If added as a member symbol to a class or struct, that operator matches the requirements for the class (types match up) -* There is no support for validating new & delete operations (yet) - -The user is responsible for making sure the code types provided are correct -and have the desired specifiers assigned to them beforehand. - -## Code generation and modification - -There are two provided auxiliary interfaces: - -* Builder -* Scanner - -### Builder is a similar object to the jai language's strbuilder_builder - -* The purpose of it is to generate a file. -* A file is specified and opened for writing using the open( file_path) function. -* The code is provided via print( code ) function will be serialized to its buffer. -* When all serialization is finished, use the write() command to write the buffer to the file. - -### Scanner - -* The purpose is to scan or parse files -* Some with two basic functions to convert a fil to code: `scan_file` and `parse_file` - * `scan_file`: Merely grabs the file and stores it in an untyped Code. - * `parse_file`: Will parse the file using `parse_global_body` and return a `CodeBody`. -* Two basic functions for grabbing columns from a CSV: `parse_csv_one_column` and `parse_csv_two_columns` diff --git a/thirdparty/gencpp_c11/gen.h b/thirdparty/gencpp_c11/gencpp_c11.h similarity index 97% rename from thirdparty/gencpp_c11/gen.h rename to thirdparty/gencpp_c11/gencpp_c11.h index 755045f..cde0782 100644 --- a/thirdparty/gencpp_c11/gen.h +++ b/thirdparty/gencpp_c11/gencpp_c11.h @@ -38,7 +38,7 @@ | \_____|\___}_l |_|\___} .__/| .__/ {_____/ \__\__/_l\__. |\___/\__,_l \____}{_____}{_____} | | | | | | __} | | | l_l l_l {___/ | - ! ----------------------------------------------------------------------- VERSION: v0.24-Alpha | + ! ----------------------------------------------------------------------- VERSION: v0.25-Alpha | ! ============================================================================================= | ! 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 | @@ -232,7 +232,7 @@ GEN_NS_BEGIN #endif // GEN_API #ifndef gen_global // Global variables -# ifdef GEN_DYN_EXPORT +# if defined(GEN_STATIC_LINK) || defined(GEN_DYN_LINK) # define gen_global # else # define gen_global static @@ -3052,6 +3052,10 @@ gen_forceinline gen_usize gen_strbuilder_grow_formula(gen_usize value); GEN_API gen_StrBuilder gen_strbuilder_make_reserve(gen_AllocatorInfo allocator, gen_ssize capacity); GEN_API gen_StrBuilder gen_strbuilder_make_length(gen_AllocatorInfo allocator, char const* str, gen_ssize length); +GEN_API bool gen_strbuilder_make_space_for(gen_StrBuilder* str, char const* to_append, gen_ssize add_len); +GEN_API bool gen_strbuilder_append_c_str_len(gen_StrBuilder* str, char const* gen_c_str_to_append, gen_ssize length); +GEN_API void gen_strbuilder_trim(gen_StrBuilder str, char const* cut_set); +GEN_API gen_StrBuilder gen_strbuilder_visualize_whitespace(gen_StrBuilder const str); gen_StrBuilder gen_strbuilder_make_c_str(gen_AllocatorInfo allocator, char const* str); gen_StrBuilder gen_strbuilder_make_str(gen_AllocatorInfo allocator, gen_Str str); @@ -3060,10 +3064,8 @@ gen_StrBuilder gen_strbuilder_fmt_buf(gen_AllocatorInfo allocator, char c gen_StrBuilder gen_strbuilder_join(gen_AllocatorInfo allocator, char const** parts, gen_ssize num_parts, char const* glue); bool gen_strbuilder_are_equal(gen_StrBuilder const lhs, gen_StrBuilder const rhs); bool gen_strbuilder_are_equal_str(gen_StrBuilder const lhs, gen_Str rhs); -bool gen_strbuilder_make_space_for(gen_StrBuilder* str, char const* to_append, gen_ssize add_len); bool gen_strbuilder_append_char(gen_StrBuilder* str, char c); bool gen_strbuilder_append_c_str(gen_StrBuilder* str, char const* gen_c_str_to_append); -bool gen_strbuilder_append_c_str_len(gen_StrBuilder* str, char const* gen_c_str_to_append, gen_ssize length); bool gen_strbuilder_append_str(gen_StrBuilder* str, gen_Str gen_c_str_to_append); bool gen_strbuilder_append_string(gen_StrBuilder* str, gen_StrBuilder const other); bool gen_strbuilder_append_fmt(gen_StrBuilder* str, char const* fmt, ...); @@ -3082,9 +3084,7 @@ gen_b32 gen_strbuilder_starts_with_string(gen_StrBuilder const str void gen_strbuilder_skip_line(gen_StrBuilder str); void gen_strbuilder_strip_space(gen_StrBuilder str); gen_Str gen_strbuilder_to_str(gen_StrBuilder str); -void gen_strbuilder_trim(gen_StrBuilder str, char const* cut_set); void gen_strbuilder_trim_space(gen_StrBuilder str); -gen_StrBuilder gen_strbuilder_visualize_whitespace(gen_StrBuilder const str); struct gen_StrBuilderHeader { @@ -3174,28 +3174,6 @@ gen_forceinline bool gen_strbuilder_append_c_str(gen_StrBuilder* str, char const return gen_strbuilder_append_c_str_len(str, gen_c_str_to_append, gen_c_str_len(gen_c_str_to_append)); } -inline bool gen_strbuilder_append_c_str_len(gen_StrBuilder* str, char const* gen_c_str_to_append, gen_ssize append_length) -{ - GEN_ASSERT(str != gen_nullptr); - if (gen_rcast(gen_sptr, gen_c_str_to_append) > 0) - { - gen_ssize curr_len = gen_strbuilder_length(*str); - - if (! gen_strbuilder_make_space_for(str, gen_c_str_to_append, append_length)) - return false; - - gen_StrBuilderHeader* header = gen_strbuilder_get_header(*str); - - char* Data = *str; - gen_mem_copy(Data + curr_len, gen_c_str_to_append, append_length); - - Data[curr_len + append_length] = '\0'; - - header->Length = curr_len + append_length; - } - return gen_c_str_to_append != gen_nullptr; -} - gen_forceinline bool gen_strbuilder_append_str(gen_StrBuilder* str, gen_Str gen_c_str_to_append) { GEN_ASSERT(str != gen_nullptr); @@ -3332,44 +3310,6 @@ gen_forceinline gen_ssize gen_strbuilder_length(gen_StrBuilder const str) return header->Length; } -inline bool gen_strbuilder_make_space_for(gen_StrBuilder* str, char const* to_append, gen_ssize add_len) -{ - gen_ssize available = gen_strbuilder_avail_space(*str); - - if (available >= add_len) - { - return true; - } - else - { - gen_ssize new_len, old_size, new_size; - void* ptr; - void* new_ptr; - - gen_AllocatorInfo allocator = gen_strbuilder_get_header(*str)->Allocator; - gen_StrBuilderHeader* header = gen_nullptr; - - new_len = gen_strbuilder_grow_formula(gen_strbuilder_length(*str) + add_len); - ptr = gen_strbuilder_get_header(*str); - old_size = gen_size_of(gen_StrBuilderHeader) + gen_strbuilder_length(*str) + 1; - new_size = gen_size_of(gen_StrBuilderHeader) + new_len + 1; - - new_ptr = gen_resize(allocator, ptr, old_size, new_size); - - if (new_ptr == gen_nullptr) - return false; - - header = gen_rcast(gen_StrBuilderHeader*, new_ptr); - header->Allocator = allocator; - header->Capacity = new_len; - - char** Data = gen_rcast(char**, str); - *Data = gen_rcast(char*, header + 1); - - return true; - } -} - gen_forceinline gen_b32 gen_strbuilder_starts_with_str(gen_StrBuilder const str, gen_Str substring) { if (substring.Len > gen_strbuilder_length(str)) @@ -3437,68 +3377,11 @@ gen_forceinline gen_Str gen_strbuilder_to_str(gen_StrBuilder str) return result; } -inline void gen_strbuilder_trim(gen_StrBuilder str, char const* cut_set) -{ - gen_ssize len = 0; - - char* start_pos = str; - char* gen_end_pos = gen_scast(char*, str) + gen_strbuilder_length(str) - 1; - - while (start_pos <= gen_end_pos && gen_char_first_occurence(cut_set, *start_pos)) - start_pos++; - - while (gen_end_pos > start_pos && gen_char_first_occurence(cut_set, *gen_end_pos)) - gen_end_pos--; - - len = gen_scast(gen_ssize, (start_pos > gen_end_pos) ? 0 : ((gen_end_pos - start_pos) + 1)); - - if (str != start_pos) - gen_mem_move(str, start_pos, len); - - str[len] = '\0'; - - gen_strbuilder_get_header(str)->Length = len; -} - gen_forceinline void gen_strbuilder_trim_space(gen_StrBuilder str) { gen_strbuilder_trim(str, " \t\r\n\v\f"); } -inline gen_StrBuilder gen_strbuilder_visualize_whitespace(gen_StrBuilder const str) -{ - gen_StrBuilderHeader* header = (gen_StrBuilderHeader*)(gen_scast(char const*, str) - sizeof(gen_StrBuilderHeader)); - gen_StrBuilder result = gen_strbuilder_make_reserve(header->Allocator, gen_strbuilder_length(str) * 2); // Assume worst case for space requirements. - - for (char const* c = gen_strbuilder_begin(str); c != gen_strbuilder_end(str); c = gen_strbuilder_next(str, c)) - switch (*c) - { - case ' ': - gen_strbuilder_append_str(&result, txt("·")); - break; - case '\t': - gen_strbuilder_append_str(&result, txt("→")); - break; - case '\n': - gen_strbuilder_append_str(&result, txt("↵")); - break; - case '\r': - gen_strbuilder_append_str(&result, txt("⏎")); - break; - case '\v': - gen_strbuilder_append_str(&result, txt("⇕")); - break; - case '\f': - gen_strbuilder_append_str(&result, txt("⌂")); - break; - default: - gen_strbuilder_append_char(&result, *c); - break; - } - - return result; -} - #pragma endregion gen_StrBuilder gen_forceinline gen_Str gen_str_duplicate(gen_Str str, gen_AllocatorInfo allocator) @@ -6015,17 +5898,18 @@ enum TokFlags gen_enum_underlying(gen_u32) { TF_Operator = gen_bit(0), TF_Assign = gen_bit(1), - TF_Preprocess = gen_bit(2), - TF_Preprocess_Cond = gen_bit(3), - TF_Attribute = gen_bit(6), - TF_AccessOperator = gen_bit(7), - TF_AccessSpecifier = gen_bit(8), - TF_Specifier = gen_bit(9), - TF_EndDefinition = gen_bit(10), // Either ; or } - TF_Formatting = gen_bit(11), - TF_Literal = gen_bit(12), - TF_Macro_Functional = gen_bit(13), - TF_Macro_Expects_Body = gen_bit(14), + TF_Identifier = gen_bit(2), + TF_Preprocess = gen_bit(3), + TF_Preprocess_Cond = gen_bit(4), + TF_Attribute = gen_bit(5), + TF_AccessOperator = gen_bit(6), + TF_AccessSpecifier = gen_bit(7), + TF_Specifier = gen_bit(8), + TF_EndDefinition = gen_bit(9), // Either ; or } + TF_Formatting = gen_bit(10), + TF_Literal = gen_bit(11), + TF_Macro_Functional = gen_bit(12), + TF_Macro_Expects_Body = gen_bit(13), TF_Null = 0, TF_UnderlyingType = GEN_U32_MAX, }; @@ -6632,18 +6516,18 @@ typedef gen_AST_Var* gen_CodeVar; #pragma region gen_Code C-Interface -GEN_API void gen_code__append(gen_Code code, gen_Code other); +void gen_code__append(gen_Code code, gen_Code other); GEN_API gen_Str gen_code__debug_str(gen_Code code); GEN_API gen_Code gen_code__duplicate(gen_Code code); -GEN_API gen_Code* gen_code__entry(gen_Code code, gen_u32 idx); -GEN_API bool gen_code__has_entries(gen_Code code); -GEN_API bool gen_code__is_body(gen_Code code); +gen_Code* gen_code__entry(gen_Code code, gen_u32 idx); +bool gen_code__has_entries(gen_Code code); +bool gen_code__is_body(gen_Code code); GEN_API bool gen_code__is_equal(gen_Code code, gen_Code other); -GEN_API bool gen_code__is_valid(gen_Code code); -GEN_API void gen_code__set_global(gen_Code code); +bool gen_code__is_valid(gen_Code code); +void gen_code__set_global(gen_Code code); GEN_API gen_StrBuilder gen_code__to_strbuilder(gen_Code self); -GEN_API void gen_code__to_strbuilder_ptr(gen_Code self, gen_StrBuilder* result); -GEN_API gen_Str gen_code__type_str(gen_Code self); +GEN_API void gen_code__to_strbuilder_ref(gen_Code self, gen_StrBuilder* result); +gen_Str gen_code__type_str(gen_Code self); GEN_API bool gen_code__validate_body(gen_Code self); #pragma endregion gen_Code C - Interface @@ -6713,8 +6597,7 @@ struct gen_AST union { - gen_Code - NextVar; // Variable; Possible way to handle comma separated variables declarations. ( , NextVar->Specs NextVar->Name NextVar->ArrExpr = NextVar->Value ) + gen_Code NextVar; // Variable gen_Code SuffixSpecs; // Typename, Function (Thanks Unreal) gen_Code PostNameMacro; // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal) }; @@ -7152,39 +7035,39 @@ gen_static_assert(sizeof(gen_AST) == gen_AST_POD_Size, "ERROR: gen_AST is not si default: gen_generic_selection_fail \ ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code) -#define gen_code_to_strbuilder_ptr(code, result) \ +#define gen_code_to_strbuilder_ref(code, result) \ _Generic( \ (code), \ - gen_Code: gen_code__to_strbuilder_ptr, \ - gen_CodeBody: gen_code__to_strbuilder_ptr, \ - gen_CodeAttributes: gen_code__to_strbuilder_ptr, \ - gen_CodeComment: gen_code__to_strbuilder_ptr, \ - gen_CodeClass: gen_code__to_strbuilder_ptr, \ - gen_CodeConstructor: gen_code__to_strbuilder_ptr, \ - gen_CodeDefine: gen_code__to_strbuilder_ptr, \ - gen_CodeDefineParams: gen_code__to_strbuilder_ptr, \ - gen_CodeDestructor: gen_code__to_strbuilder_ptr, \ - gen_CodeEnum: gen_code__to_strbuilder_ptr, \ - gen_CodeExec: gen_code__to_strbuilder_ptr, \ - gen_CodeExtern: gen_code__to_strbuilder_ptr, \ - gen_CodeInclude: gen_code__to_strbuilder_ptr, \ - gen_CodeFriend: gen_code__to_strbuilder_ptr, \ - gen_CodeFn: gen_code__to_strbuilder_ptr, \ - gen_CodeModule: gen_code__to_strbuilder_ptr, \ - gen_CodeNS: gen_code__to_strbuilder_ptr, \ - gen_CodeOperator: gen_code__to_strbuilder_ptr, \ - gen_CodeOpCast: gen_code__to_strbuilder_ptr, \ - gen_CodePragma: gen_code__to_strbuilder_ptr, \ - gen_CodeParams: gen_code__to_strbuilder_ptr, \ - gen_CodePreprocessCond: gen_code__to_strbuilder_ptr, \ - gen_CodeSpecifiers: gen_code__to_strbuilder_ptr, \ - gen_CodeStruct: gen_code__to_strbuilder_ptr, \ - gen_CodeTemplate: gen_code__to_strbuilder_ptr, \ - gen_CodeTypename: gen_code__to_strbuilder_ptr, \ - gen_CodeTypedef: gen_code__to_strbuilder_ptr, \ - gen_CodeUnion: gen_code__to_strbuilder_ptr, \ - gen_CodeUsing: gen_code__to_strbuilder_ptr, \ - gen_CodeVar: gen_code__to_strbuilder_ptr, \ + gen_Code: gen_code__to_strbuilder_ref, \ + gen_CodeBody: gen_code__to_strbuilder_ref, \ + gen_CodeAttributes: gen_code__to_strbuilder_ref, \ + gen_CodeComment: gen_code__to_strbuilder_ref, \ + gen_CodeClass: gen_code__to_strbuilder_ref, \ + gen_CodeConstructor: gen_code__to_strbuilder_ref, \ + gen_CodeDefine: gen_code__to_strbuilder_ref, \ + gen_CodeDefineParams: gen_code__to_strbuilder_ref, \ + gen_CodeDestructor: gen_code__to_strbuilder_ref, \ + gen_CodeEnum: gen_code__to_strbuilder_ref, \ + gen_CodeExec: gen_code__to_strbuilder_ref, \ + gen_CodeExtern: gen_code__to_strbuilder_ref, \ + gen_CodeInclude: gen_code__to_strbuilder_ref, \ + gen_CodeFriend: gen_code__to_strbuilder_ref, \ + gen_CodeFn: gen_code__to_strbuilder_ref, \ + gen_CodeModule: gen_code__to_strbuilder_ref, \ + gen_CodeNS: gen_code__to_strbuilder_ref, \ + gen_CodeOperator: gen_code__to_strbuilder_ref, \ + gen_CodeOpCast: gen_code__to_strbuilder_ref, \ + gen_CodePragma: gen_code__to_strbuilder_ref, \ + gen_CodeParams: gen_code__to_strbuilder_ref, \ + gen_CodePreprocessCond: gen_code__to_strbuilder_ref, \ + gen_CodeSpecifiers: gen_code__to_strbuilder_ref, \ + gen_CodeStruct: gen_code__to_strbuilder_ref, \ + gen_CodeTemplate: gen_code__to_strbuilder_ref, \ + gen_CodeTypename: gen_code__to_strbuilder_ref, \ + gen_CodeTypedef: gen_code__to_strbuilder_ref, \ + gen_CodeUnion: gen_code__to_strbuilder_ref, \ + gen_CodeUsing: gen_code__to_strbuilder_ref, \ + gen_CodeVar: gen_code__to_strbuilder_ref, \ default: gen_generic_selection_fail \ ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code, result) @@ -7265,58 +7148,59 @@ gen_static_assert(sizeof(gen_AST) == gen_AST_POD_Size, "ERROR: gen_AST is not si GEN_API void gen_body_append(gen_CodeBody body, gen_Code other); GEN_API void gen_body_append_body(gen_CodeBody body, gen_CodeBody other); GEN_API gen_StrBuilder gen_body_to_strbuilder(gen_CodeBody body); -GEN_API void gen_body_to_strbuilder_ref(gen_CodeBody body, gen_StrBuilder* result); +void gen_body_to_strbuilder_ref(gen_CodeBody body, gen_StrBuilder* result); GEN_API void gen_body_to_strbuilder_export(gen_CodeBody body, gen_StrBuilder* result); -GEN_API gen_Code gen_begin_CodeBody(gen_CodeBody body); -GEN_API gen_Code gen_end_CodeBody(gen_CodeBody body); -GEN_API gen_Code gen_next_CodeBody(gen_CodeBody body, gen_Code entry_iter); +gen_Code gen_begin_CodeBody(gen_CodeBody body); +gen_Code gen_end_CodeBody(gen_CodeBody body); +gen_Code gen_next_CodeBody(gen_CodeBody body, gen_Code entry_iter); -GEN_API void gen_class_add_interface(gen_CodeClass self, gen_CodeTypename interface); +void gen_class_add_interface(gen_CodeClass self, gen_CodeTypename interface); GEN_API gen_StrBuilder gen_class_to_strbuilder(gen_CodeClass self); GEN_API void gen_class_to_strbuilder_def(gen_CodeClass self, gen_StrBuilder* result); GEN_API void gen_class_to_strbuilder_fwd(gen_CodeClass self, gen_StrBuilder* result); -GEN_API void gen_define_params_append(gen_CodeDefineParams appendee, gen_CodeDefineParams other); -GEN_API gen_CodeDefineParams gen_define_params_get(gen_CodeDefineParams params, gen_s32 idx); -GEN_API bool gen_define_params_has_entries(gen_CodeDefineParams params); -GEN_API gen_StrBuilder gen_define_params_to_strbuilder(gen_CodeDefineParams params); -GEN_API void gen_define_params_to_strbuilder_ref(gen_CodeDefineParams params, gen_StrBuilder* result); +void gen_define_params_append(gen_CodeDefineParams appendee, gen_CodeDefineParams other); +gen_CodeDefineParams gen_define_params_get(gen_CodeDefineParams params, gen_s32 idx); +bool gen_define_params_has_entries(gen_CodeDefineParams params); +gen_StrBuilder gen_define_params_to_strbuilder(gen_CodeDefineParams params); +GEN_API void gen_define_params_to_strbuilder_ref(gen_CodeDefineParams params, gen_StrBuilder* result); -GEN_API gen_CodeDefineParams gen_begin_CodeDefineParams(gen_CodeDefineParams params); -GEN_API gen_CodeDefineParams gen_end_CodeDefineParams(gen_CodeDefineParams params); -GEN_API gen_CodeDefineParams gen_next_CodeDefineParams(gen_CodeDefineParams params, gen_CodeDefineParams entry_iter); +gen_CodeDefineParams gen_begin_CodeDefineParams(gen_CodeDefineParams params); +gen_CodeDefineParams gen_end_CodeDefineParams(gen_CodeDefineParams params); +gen_CodeDefineParams gen_next_CodeDefineParams(gen_CodeDefineParams params, gen_CodeDefineParams entry_iter); -GEN_API void gen_params_append(gen_CodeParams appendee, gen_CodeParams other); -GEN_API gen_CodeParams gen_params_get(gen_CodeParams params, gen_s32 idx); -GEN_API bool gen_params_has_entries(gen_CodeParams params); -GEN_API gen_StrBuilder gen_params_to_strbuilder(gen_CodeParams params); -GEN_API void gen_params_to_strbuilder_ref(gen_CodeParams params, gen_StrBuilder* result); +void gen_params_append(gen_CodeParams appendee, gen_CodeParams other); +gen_CodeParams gen_params_get(gen_CodeParams params, gen_s32 idx); +bool gen_params_has_entries(gen_CodeParams params); +gen_StrBuilder gen_params_to_strbuilder(gen_CodeParams params); +GEN_API void gen_params_to_strbuilder_ref(gen_CodeParams params, gen_StrBuilder* result); -GEN_API gen_CodeParams gen_begin_CodeParams(gen_CodeParams params); -GEN_API gen_CodeParams gen_end_CodeParams(gen_CodeParams params); -GEN_API gen_CodeParams gen_next_CodeParams(gen_CodeParams params, gen_CodeParams entry_iter); +gen_CodeParams gen_begin_CodeParams(gen_CodeParams params); +gen_CodeParams gen_end_CodeParams(gen_CodeParams params); +gen_CodeParams gen_next_CodeParams(gen_CodeParams params, gen_CodeParams entry_iter); -GEN_API bool gen_specifiers_append(gen_CodeSpecifiers specifiers, gen_Specifier spec); -GEN_API gen_s32 gen_specifiers_has(gen_CodeSpecifiers specifiers, gen_Specifier spec); -GEN_API gen_s32 gen_specifiers_remove(gen_CodeSpecifiers specifiers, gen_Specifier to_remove); -GEN_API gen_StrBuilder gen_specifiers_to_strbuilder(gen_CodeSpecifiers specifiers); -GEN_API void gen_specifiers_to_strbuilder_ref(gen_CodeSpecifiers specifiers, gen_StrBuilder* result); +bool gen_specifiers_append(gen_CodeSpecifiers specifiers, gen_Specifier spec); +bool gen_specifiers_has(gen_CodeSpecifiers specifiers, gen_Specifier spec); +gen_s32 gen_specifiers_index_of(gen_CodeSpecifiers specifiers, gen_Specifier spec); +gen_s32 gen_specifiers_remove(gen_CodeSpecifiers specifiers, gen_Specifier to_remove); +gen_StrBuilder gen_specifiers_to_strbuilder(gen_CodeSpecifiers specifiers); +GEN_API void gen_specifiers_to_strbuilder_ref(gen_CodeSpecifiers specifiers, gen_StrBuilder* result); -GEN_API gen_Specifier* gen_begin_CodeSpecifiers(gen_CodeSpecifiers specifiers); -GEN_API gen_Specifier* gen_end_CodeSpecifiers(gen_CodeSpecifiers specifiers); -GEN_API gen_Specifier* gen_next_CodeSpecifiers(gen_CodeSpecifiers specifiers, gen_Specifier* gen_spec_iter); +gen_Specifier* gen_begin_CodeSpecifiers(gen_CodeSpecifiers specifiers); +gen_Specifier* gen_end_CodeSpecifiers(gen_CodeSpecifiers specifiers); +gen_Specifier* gen_next_CodeSpecifiers(gen_CodeSpecifiers specifiers, gen_Specifier* gen_spec_iter); -GEN_API void gen_struct_add_interface(gen_CodeStruct self, gen_CodeTypename interface); +void gen_struct_add_interface(gen_CodeStruct self, gen_CodeTypename interface); GEN_API gen_StrBuilder gen_struct_to_strbuilder(gen_CodeStruct self); GEN_API void gen_struct_to_strbuilder_fwd(gen_CodeStruct self, gen_StrBuilder* result); GEN_API void gen_struct_to_strbuilder_def(gen_CodeStruct self, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_attributes_to_strbuilder(gen_CodeAttributes attributes); -GEN_API void gen_attributes_to_strbuilder_ref(gen_CodeAttributes attributes, gen_StrBuilder* result); +gen_StrBuilder gen_attributes_to_strbuilder(gen_CodeAttributes attributes); +void gen_attributes_to_strbuilder_ref(gen_CodeAttributes attributes, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_comment_to_strbuilder(gen_CodeComment comment); -GEN_API void gen_comment_to_strbuilder_ref(gen_CodeComment comment, gen_StrBuilder* result); +gen_StrBuilder gen_comment_to_strbuilder(gen_CodeComment comment); +void gen_comment_to_strbuilder_ref(gen_CodeComment comment, gen_StrBuilder* result); GEN_API gen_StrBuilder gen_constructor__to_strbuilder(gen_CodeConstructor gen_constructor_); GEN_API void gen_constructor__to_strbuilder_def(gen_CodeConstructor gen_constructor_, gen_StrBuilder* result); @@ -7335,26 +7219,26 @@ GEN_API void gen_enum_to_strbuilder_fwd(gen_CodeEnum self, gen_StrBuil GEN_API void gen_enum_to_strbuilder_class_def(gen_CodeEnum self, gen_StrBuilder* result); GEN_API void gen_enum_to_strbuilder_class_fwd(gen_CodeEnum self, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_exec_to_strbuilder(gen_CodeExec exec); -GEN_API void gen_exec_to_strbuilder_ref(gen_CodeExec exec, gen_StrBuilder* result); +gen_StrBuilder gen_exec_to_strbuilder(gen_CodeExec exec); +void gen_exec_to_strbuilder_ref(gen_CodeExec exec, gen_StrBuilder* result); -GEN_API void gen_extern_to_strbuilder(gen_CodeExtern self, gen_StrBuilder* result); +void gen_extern_to_strbuilder(gen_CodeExtern self, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_include_to_strbuilder(gen_CodeInclude self); -GEN_API void gen_include_to_strbuilder_ref(gen_CodeInclude self, gen_StrBuilder* result); +gen_StrBuilder gen_include_to_strbuilder(gen_CodeInclude self); +void gen_include_to_strbuilder_ref(gen_CodeInclude self, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_friend_to_strbuilder(gen_CodeFriend self); -GEN_API void gen_friend_to_strbuilder_ref(gen_CodeFriend self, gen_StrBuilder* result); +gen_StrBuilder gen_friend_to_strbuilder(gen_CodeFriend self); +void gen_friend_to_strbuilder_ref(gen_CodeFriend self, gen_StrBuilder* result); GEN_API gen_StrBuilder gen_fn_to_strbuilder(gen_CodeFn self); GEN_API void gen_fn_to_strbuilder_def(gen_CodeFn self, gen_StrBuilder* result); GEN_API void gen_fn_to_strbuilder_fwd(gen_CodeFn self, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_module_to_strbuilder(gen_CodeModule self); -GEN_API void gen_module_to_strbuilder_ref(gen_CodeModule self, gen_StrBuilder* result); +gen_StrBuilder gen_module_to_strbuilder(gen_CodeModule self); +GEN_API void gen_module_to_strbuilder_ref(gen_CodeModule self, gen_StrBuilder* result); -GEN_API gen_StrBuilder namespace_to_strbuilder(gen_CodeNS self); -GEN_API void namespace_to_strbuilder_ref(gen_CodeNS self, gen_StrBuilder* result); +gen_StrBuilder namespace_to_strbuilder(gen_CodeNS self); +void namespace_to_strbuilder_ref(gen_CodeNS self, gen_StrBuilder* result); GEN_API gen_StrBuilder gen_code_op_to_strbuilder(gen_CodeOperator self); GEN_API void gen_code_op_to_strbuilder_fwd(gen_CodeOperator self, gen_StrBuilder* result); @@ -7364,36 +7248,38 @@ GEN_API gen_StrBuilder gen_opcast_to_strbuilder(gen_CodeOpCast op_cast); GEN_API void gen_opcast_to_strbuilder_def(gen_CodeOpCast op_cast, gen_StrBuilder* result); GEN_API void gen_opcast_to_strbuilder_fwd(gen_CodeOpCast op_cast, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_pragma_to_strbuilder(gen_CodePragma self); -GEN_API void gen_pragma_to_strbuilder_ref(gen_CodePragma self, gen_StrBuilder* result); +gen_StrBuilder gen_pragma_to_strbuilder(gen_CodePragma self); +void gen_pragma_to_strbuilder_ref(gen_CodePragma self, gen_StrBuilder* result); GEN_API gen_StrBuilder gen_preprocess_to_strbuilder(gen_CodePreprocessCond cond); -GEN_API void gen_preprocess_to_strbuilder_if(gen_CodePreprocessCond cond, gen_StrBuilder* result); -GEN_API void gen_preprocess_to_strbuilder_ifdef(gen_CodePreprocessCond cond, gen_StrBuilder* result); -GEN_API void gen_preprocess_to_strbuilder_ifndef(gen_CodePreprocessCond cond, gen_StrBuilder* result); -GEN_API void gen_preprocess_to_strbuilder_elif(gen_CodePreprocessCond cond, gen_StrBuilder* result); -GEN_API void gen_preprocess_to_strbuilder_else(gen_CodePreprocessCond cond, gen_StrBuilder* result); -GEN_API void gen_preprocess_to_strbuilder_endif(gen_CodePreprocessCond cond, gen_StrBuilder* result); +void gen_preprocess_to_strbuilder_if(gen_CodePreprocessCond cond, gen_StrBuilder* result); +void gen_preprocess_to_strbuilder_ifdef(gen_CodePreprocessCond cond, gen_StrBuilder* result); +void gen_preprocess_to_strbuilder_ifndef(gen_CodePreprocessCond cond, gen_StrBuilder* result); +void gen_preprocess_to_strbuilder_elif(gen_CodePreprocessCond cond, gen_StrBuilder* result); +void gen_preprocess_to_strbuilder_else(gen_CodePreprocessCond cond, gen_StrBuilder* result); +void gen_preprocess_to_strbuilder_endif(gen_CodePreprocessCond cond, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_template_to_strbuilder(gen_CodeTemplate self); -GEN_API void gen_template_to_strbuilder_ref(gen_CodeTemplate self, gen_StrBuilder* result); +gen_StrBuilder gen_template_to_strbuilder(gen_CodeTemplate self); +GEN_API void gen_template_to_strbuilder_ref(gen_CodeTemplate self, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_typename_to_strbuilder(gen_CodeTypename self); -GEN_API void gen_typename_to_strbuilder_ref(gen_CodeTypename self, gen_StrBuilder* result); +gen_StrBuilder gen_typedef_to_strbuilder(gen_CodeTypedef self); +GEN_API void gen_typedef_to_strbuilder_ref(gen_CodeTypedef self, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_typedef_to_strbuilder(gen_CodeTypedef self); -GEN_API void gen_typedef_to_strbuilder_ref(gen_CodeTypedef self, gen_StrBuilder* result); +gen_StrBuilder gen_typename_to_strbuilder(gen_CodeTypename self); +GEN_API void gen_typename_to_strbuilder_ref(gen_CodeTypename self, gen_StrBuilder* result); GEN_API gen_StrBuilder union_to_strbuilder(gen_CodeUnion self); GEN_API void union_to_strbuilder_def(gen_CodeUnion self, gen_StrBuilder* result); GEN_API void union_to_strbuilder_fwd(gen_CodeUnion self, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_using_to_strbuilder(gen_CodeUsing op_cast); -GEN_API void gen_using_to_strbuilder_ref(gen_CodeUsing op_cast, gen_StrBuilder* result); -GEN_API void gen_using_to_strbuilder_ns(gen_CodeUsing op_cast, gen_StrBuilder* result); +gen_StrBuilder gen_using_to_strbuilder(gen_CodeUsing op_cast); +GEN_API void gen_using_to_strbuilder_ref(gen_CodeUsing op_cast, gen_StrBuilder* result); +void gen_using_to_strbuilder_ns(gen_CodeUsing op_cast, gen_StrBuilder* result); -GEN_API gen_StrBuilder gen_var_to_strbuilder(gen_CodeVar self); -GEN_API void gen_var_to_strbuilder_ref(gen_CodeVar self, gen_StrBuilder* result); +gen_StrBuilder gen_var_to_strbuilder(gen_CodeVar self); +GEN_API void gen_var_to_strbuilder_ref(gen_CodeVar self, gen_StrBuilder* result); + +// TODO(Ed): Move C-Interface inlines here... #pragma endregion gen_Code Type C - Interface @@ -7656,7 +7542,7 @@ struct gen_AST_Enum gen_Code Parent; gen_CodeType Type; gen_ModuleFlag ModuleFlags; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; + char _PAD_UNUSED_[sizeof(gen_u32)]; }; typedef struct gen_AST_Enum gen_AST_Enum; gen_static_assert(sizeof(gen_AST_Enum) == sizeof(gen_AST), "ERROR: gen_AST_Enum is not the same size as gen_AST"); @@ -7955,8 +7841,8 @@ gen_static_assert(sizeof(gen_AST_PreprocessCond) == sizeof(gen_AST), "ERROR: gen struct gen_AST_Specifiers { gen_Specifier ArrSpecs[gen_AST_ArrSpecs_Cap]; - gen_StrCached Name; gen_CodeSpecifiers NextSpecs; + gen_StrCached Name; gen_Code Prev; gen_Code Next; gen_Token* Tok; @@ -9659,6 +9545,11 @@ struct gen_Context typedef struct gen_Context gen_Context; +// TODO(Ed): Eventually this library should opt out of an implicit context for baseline implementation +// This would automatically make it viable for multi-threaded purposes among other things +// An implicit context interface will be provided instead as wrapper procedures as convience. +GEN_API extern gen_Context* gen__ctx; + // Initialize the library. There first ctx initialized must exist for lifetime of other contextes that come after as its the one that GEN_API void gen_init(gen_Context* ctx); @@ -9772,7 +9663,7 @@ GEN_API gen_CodeEnum gen_def__enum(gen_Str name, gen_Opts_def_enum opts GEN_PARA GEN_API gen_CodeExec gen_def_execution(gen_Str content); GEN_API gen_CodeExtern gen_def_extern_link(gen_Str name, gen_CodeBody body); -GEN_API gen_CodeFriend gen_def_friend(gen_Code symbol); +GEN_API gen_CodeFriend gen_def_friend(gen_Code code); struct gen_Opts_def_function { @@ -9869,7 +9760,7 @@ GEN_API gen_CodeTemplate gen_def__template(gen_CodeParams params, gen_Code defin struct gen_Opts_def_type { gen_ETypenameTag type_tag; - gen_Code arrayexpr; + gen_Code gen_array_expr; gen_CodeSpecifiers specifiers; gen_CodeAttributes attributes; }; @@ -9923,7 +9814,7 @@ GEN_API gen_CodeVar gen_def__variable(gen_CodeTypename type, gen_Str name, gen_O #define gen_def_variable(type, name, ...) gen_def__variable(type, name, (gen_Opts_def_variable) { __VA_ARGS__ }) // Constructs an empty body. Use gen_AST::validate_body() to check if the body is was has valid entries. -GEN_API gen_CodeBody gen_def_body(gen_CodeType type); +gen_CodeBody gen_def_body(gen_CodeType type); // There are two options for defining a struct body, either varadically provided with the args macro to auto-deduce the arg num, /// or provide as an array of gen_Code objects. @@ -9990,7 +9881,7 @@ GEN_API gen_CodeVar gen_parse_variable(gen_Str gen_var_def); GEN_API gen_ssize gen_token_fmt_va(char* buf, gen_usize buf_size, gen_s32 num_tokens, va_list va); //! Do not use directly. Use the gen_token_fmt macro instead. -GEN_API gen_Str gen_token_fmt_impl(gen_ssize, ...); +gen_Str gen_token_fmt_impl(gen_ssize, ...); GEN_API gen_Code gen_untyped_str(gen_Str content); GEN_API gen_Code gen_untyped_fmt(char const* fmt, ...); @@ -10091,8 +9982,376 @@ So the full call for this example would be: #pragma endregion Gen Interface +#pragma region Constants + +// Predefined typename codes. Are set to readonly and are setup during gen::gen_init() + +GEN_API extern gen_Macro gen_enum_underlying_macro; + +GEN_API extern gen_Code gen_access_public; +GEN_API extern gen_Code gen_access_protected; +GEN_API extern gen_Code gen_access_private; + +GEN_API extern gen_CodeAttributes gen_attrib_api_export; +GEN_API extern gen_CodeAttributes gen_attrib_api_import; + +GEN_API extern gen_Code gen_module_global_fragment; +GEN_API extern gen_Code gen_module_private_fragment; + +GEN_API extern gen_Code gen_fmt_newline; + +GEN_API extern gen_CodePragma gen_pragma_once; + +GEN_API extern gen_CodeParams gen_param_varadic; + +GEN_API extern gen_CodePreprocessCond gen_preprocess_else; +GEN_API extern gen_CodePreprocessCond gen_preprocess_endif; + +GEN_API extern gen_CodeSpecifiers gen_spec_const; +GEN_API extern gen_CodeSpecifiers gen_spec_consteval; +GEN_API extern gen_CodeSpecifiers gen_spec_constexpr; +GEN_API extern gen_CodeSpecifiers gen_spec_constinit; +GEN_API extern gen_CodeSpecifiers gen_spec_extern_linkage; +GEN_API extern gen_CodeSpecifiers gen_spec_final; +GEN_API extern gen_CodeSpecifiers gen_spec_forceinline; +GEN_API extern gen_CodeSpecifiers gen_spec_global; +GEN_API extern gen_CodeSpecifiers gen_spec_inline; +GEN_API extern gen_CodeSpecifiers gen_spec_internal_linkage; +GEN_API extern gen_CodeSpecifiers gen_spec_local_persist; +GEN_API extern gen_CodeSpecifiers gen_spec_mutable; +GEN_API extern gen_CodeSpecifiers gen_spec_neverinline; +GEN_API extern gen_CodeSpecifiers gen_spec_noexcept; +GEN_API extern gen_CodeSpecifiers gen_spec_override; +GEN_API extern gen_CodeSpecifiers gen_spec_ptr; +GEN_API extern gen_CodeSpecifiers gen_spec_pure; +GEN_API extern gen_CodeSpecifiers gen_spec_ref; +GEN_API extern gen_CodeSpecifiers gen_spec_register; +GEN_API extern gen_CodeSpecifiers gen_spec_rvalue; +GEN_API extern gen_CodeSpecifiers gen_spec_static_member; +GEN_API extern gen_CodeSpecifiers gen_spec_thread_local; +GEN_API extern gen_CodeSpecifiers gen_spec_virtual; +GEN_API extern gen_CodeSpecifiers gen_spec_volatile; + +GEN_API extern gen_CodeTypename gen_t_empty; // Used with varaidc parameters. (Exposing just in case its useful for another circumstance) +GEN_API extern gen_CodeTypename gen_t_auto; +GEN_API extern gen_CodeTypename gen_t_void; +GEN_API extern gen_CodeTypename gen_t_int; +GEN_API extern gen_CodeTypename gen_t_bool; +GEN_API extern gen_CodeTypename gen_t_char; +GEN_API extern gen_CodeTypename gen_t_wchar_t; +GEN_API extern gen_CodeTypename gen_t_class; +GEN_API extern gen_CodeTypename gen_t_typename; + +#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS + +GEN_API extern gen_CodeTypename gen_t_b32; + +GEN_API extern gen_CodeTypename gen_t_s8; +GEN_API extern gen_CodeTypename gen_t_s16; +GEN_API extern gen_CodeTypename gen_t_s32; +GEN_API extern gen_CodeTypename gen_t_s64; + +GEN_API extern gen_CodeTypename gen_t_u8; +GEN_API extern gen_CodeTypename gen_t_u16; +GEN_API extern gen_CodeTypename gen_t_u32; +GEN_API extern gen_CodeTypename gen_t_u64; + +GEN_API extern gen_CodeTypename gen_t_ssize; +GEN_API extern gen_CodeTypename gen_t_usize; + +GEN_API extern gen_CodeTypename gen_t_f32; +GEN_API extern gen_CodeTypename gen_t_f64; +#endif + +#pragma endregion Constants + #pragma region Inlines +#pragma region Serialization + +inline gen_StrBuilder gen_attributes_to_strbuilder(gen_CodeAttributes attributes) +{ + GEN_ASSERT(attributes); + char* raw = gen_ccast(char*, gen_str_duplicate(attributes->Content, get_context()->Allocator_Temp).Ptr); + gen_StrBuilder result = { raw }; + return result; +} + +inline void gen_attributes_to_strbuilder_ref(gen_CodeAttributes attributes, gen_StrBuilder* result) +{ + GEN_ASSERT(attributes); + GEN_ASSERT(result); + gen_strbuilder_append_str(result, attributes->Content); +} + +inline gen_StrBuilder gen_comment_to_strbuilder(gen_CodeComment comment) +{ + GEN_ASSERT(comment); + char* raw = gen_ccast(char*, gen_str_duplicate(comment->Content, get_context()->Allocator_Temp).Ptr); + gen_StrBuilder result = { raw }; + return result; +} + +inline void gen_body_to_strbuilder_ref(gen_CodeBody body, gen_StrBuilder* result) +{ + GEN_ASSERT(body != gen_nullptr); + GEN_ASSERT(result != gen_nullptr); + gen_Code curr = body->Front; + gen_s32 left = body->NumEntries; + while (left--) + { + gen_code_to_strbuilder_ref(curr, result); + // gen_strbuilder_append_fmt( result, "%SB", gen_code_to_strbuilder(curr) ); + ++curr; + } +} + +inline void gen_comment_to_strbuilder_ref(gen_CodeComment comment, gen_StrBuilder* result) +{ + GEN_ASSERT(comment); + GEN_ASSERT(result); + gen_strbuilder_append_str(result, comment->Content); +} + +inline gen_StrBuilder gen_define_to_strbuilder(gen_CodeDefine define) +{ + GEN_ASSERT(define); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 512); + gen_define_to_strbuilder_ref(define, &result); + return result; +} + +inline gen_StrBuilder gen_define_params_to_strbuilder(gen_CodeDefineParams params) +{ + GEN_ASSERT(params); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 128); + gen_define_params_to_strbuilder_ref(params, &result); + return result; +} + +inline gen_StrBuilder gen_exec_to_strbuilder(gen_CodeExec exec) +{ + GEN_ASSERT(exec); + char* raw = gen_ccast(char*, gen_str_duplicate(exec->Content, gen__ctx->Allocator_Temp).Ptr); + gen_StrBuilder result = { raw }; + return result; +} + +inline void gen_exec_to_strbuilder_ref(gen_CodeExec exec, gen_StrBuilder* result) +{ + GEN_ASSERT(exec); + GEN_ASSERT(result); + gen_strbuilder_append_str(result, exec->Content); +} + +inline void gen_extern_to_strbuilder(gen_CodeExtern self, gen_StrBuilder* result) +{ + GEN_ASSERT(self); + GEN_ASSERT(result); + if (self->Body) + gen_strbuilder_append_fmt(result, "extern \"%S\"\n{\n%SB\n}\n", self->Name, gen_body_to_strbuilder(self->Body)); + else + gen_strbuilder_append_fmt(result, "extern \"%S\"\n{}\n", self->Name); +} + +inline gen_StrBuilder gen_friend_to_strbuilder(gen_CodeFriend self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 256); + gen_friend_to_strbuilder_ref(self, &result); + return result; +} + +inline void gen_friend_to_strbuilder_ref(gen_CodeFriend self, gen_StrBuilder* result) +{ + GEN_ASSERT(self); + GEN_ASSERT(result); + gen_strbuilder_append_fmt(result, "friend %SB", gen_code_to_strbuilder(self->Declaration)); + + if (self->Declaration->Type != CT_Function && self->Declaration->Type != CT_Operator && (*result)[gen_strbuilder_length(*result) - 1] != ';') + { + gen_strbuilder_append_str(result, txt(";")); + } + + if (self->InlineCmt) + gen_strbuilder_append_fmt(result, " %S", self->InlineCmt->Content); + else + gen_strbuilder_append_str(result, txt("\n")); +} + +inline gen_StrBuilder gen_include_to_strbuilder(gen_CodeInclude include) +{ + GEN_ASSERT(include); + return gen_strbuilder_fmt_buf(gen__ctx->Allocator_Temp, "#include %S\n", include->Content); +} + +inline void gen_include_to_strbuilder_ref(gen_CodeInclude include, gen_StrBuilder* result) +{ + GEN_ASSERT(include); + GEN_ASSERT(result); + gen_strbuilder_append_fmt(result, "#include %S\n", include->Content); +} + +inline gen_StrBuilder gen_module_to_strbuilder(gen_CodeModule self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 64); + gen_module_to_strbuilder_ref(self, &result); + return result; +} + +inline gen_StrBuilder namespace_to_strbuilder(gen_CodeNS self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 512); + namespace_to_strbuilder_ref(self, &result); + return result; +} + +inline void namespace_to_strbuilder_ref(gen_CodeNS self, gen_StrBuilder* result) +{ + GEN_ASSERT(self); + GEN_ASSERT(result); + if (gen_bitfield_is_set(gen_u32, self->ModuleFlags, ModuleFlag_Export)) + gen_strbuilder_append_str(result, txt("export ")); + + gen_strbuilder_append_fmt(result, "namespace %S\n{\n%SB\n}\n", self->Name, gen_body_to_strbuilder(self->Body)); +} + +inline gen_StrBuilder gen_params_to_strbuilder(gen_CodeParams self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 128); + gen_params_to_strbuilder_ref(self, &result); + return result; +} + +inline gen_StrBuilder gen_pragma_to_strbuilder(gen_CodePragma self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 256); + gen_pragma_to_strbuilder_ref(self, &result); + return result; +} + +inline void gen_pragma_to_strbuilder_ref(gen_CodePragma self, gen_StrBuilder* result) +{ + GEN_ASSERT(self); + GEN_ASSERT(result); + gen_strbuilder_append_fmt(result, "#pragma %S\n", self->Content); +} + +inline void gen_preprocess_to_strbuilder_if(gen_CodePreprocessCond cond, gen_StrBuilder* result) +{ + GEN_ASSERT(cond); + GEN_ASSERT(result); + gen_strbuilder_append_fmt(result, "#if %S", cond->Content); +} + +inline void gen_preprocess_to_strbuilder_ifdef(gen_CodePreprocessCond cond, gen_StrBuilder* result) +{ + GEN_ASSERT(cond); + GEN_ASSERT(result); + gen_strbuilder_append_fmt(result, "#ifdef %S\n", cond->Content); +} + +inline void gen_preprocess_to_strbuilder_ifndef(gen_CodePreprocessCond cond, gen_StrBuilder* result) +{ + GEN_ASSERT(cond); + GEN_ASSERT(result); + gen_strbuilder_append_fmt(result, "#ifndef %S", cond->Content); +} + +inline void gen_preprocess_to_strbuilder_elif(gen_CodePreprocessCond cond, gen_StrBuilder* result) +{ + GEN_ASSERT(cond); + GEN_ASSERT(result); + gen_strbuilder_append_fmt(result, "#elif %S\n", cond->Content); +} + +inline void gen_preprocess_to_strbuilder_else(gen_CodePreprocessCond cond, gen_StrBuilder* result) +{ + GEN_ASSERT(cond); + GEN_ASSERT(result); + gen_strbuilder_append_str(result, txt("#else\n")); +} + +inline void gen_preprocess_to_strbuilder_endif(gen_CodePreprocessCond cond, gen_StrBuilder* result) +{ + GEN_ASSERT(cond); + GEN_ASSERT(result); + gen_strbuilder_append_str(result, txt("#endif\n")); +} + +inline gen_StrBuilder gen_specifiers_to_strbuilder(gen_CodeSpecifiers self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 64); + gen_specifiers_to_strbuilder_ref(self, &result); + return result; +} + +inline gen_StrBuilder gen_template_to_strbuilder(gen_CodeTemplate self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 1024); + gen_template_to_strbuilder_ref(self, &result); + return result; +} + +inline gen_StrBuilder gen_typedef_to_strbuilder(gen_CodeTypedef self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 128); + gen_typedef_to_strbuilder_ref(self, &result); + return result; +} + +inline gen_StrBuilder gen_typename_to_strbuilder(gen_CodeTypename self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_str(gen__ctx->Allocator_Temp, txt("")); + gen_typename_to_strbuilder_ref(self, &result); + return result; +} + +inline gen_StrBuilder gen_using_to_strbuilder(gen_CodeUsing self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, 128); + switch (self->Type) + { + case CT_Using: + gen_using_to_strbuilder_ref(self, &result); + break; + case CT_Using_Namespace: + gen_using_to_strbuilder_ns(self, &result); + break; + } + return result; +} + +inline void gen_using_to_strbuilder_ns(gen_CodeUsing self, gen_StrBuilder* result) +{ + GEN_ASSERT(self); + GEN_ASSERT(result); + if (self->InlineCmt) + gen_strbuilder_append_fmt(result, "using namespace $S; %S", self->Name, self->InlineCmt->Content); + else + gen_strbuilder_append_fmt(result, "using namespace %S;\n", self->Name); +} + +inline gen_StrBuilder gen_var_to_strbuilder(gen_CodeVar self) +{ + GEN_ASSERT(self); + gen_StrBuilder result = gen_strbuilder_make_reserve(get_context()->Allocator_Temp, 256); + gen_var_to_strbuilder_ref(self, &result); + return result; +} + +#pragma endregion Serialization + + #pragma region gen_Code inline void gen_code__append(gen_Code self, gen_Code other) @@ -10163,7 +10422,7 @@ gen_forceinline bool gen_code__is_valid(gen_Code self) return self != gen_nullptr && self->Type != CT_Invalid; } -gen_forceinline bool gen_code__has_entries(gen_AST* self) +gen_forceinline bool gen_code__has_entries(gen_Code self) { GEN_ASSERT(self); return self->NumEntries > 0; @@ -10257,12 +10516,12 @@ inline void gen_class_add_interface(gen_CodeClass self, gen_CodeTypename type) // then you'll need to move this over to ParentType->next and update ParentAccess accordingly. } - while (possible_slot != gen_nullptr) + while (possible_slot->Next != gen_nullptr) { possible_slot = gen_cast(gen_CodeTypename, possible_slot->Next); } - possible_slot = type; + possible_slot->Next = gen_cast(gen_Code, type); } #pragma endregion gen_CodeClass @@ -10395,7 +10654,18 @@ inline bool gen_specifiers_append(gen_CodeSpecifiers self, gen_Specifier spec) return true; } -inline gen_s32 gen_specifiers_has(gen_CodeSpecifiers self, gen_Specifier spec) +inline bool gen_specifiers_has(gen_CodeSpecifiers self, gen_Specifier spec) +{ + GEN_ASSERT(self != gen_nullptr); + for (gen_s32 idx = 0; idx < self->NumEntries; idx++) + { + if (self->ArrSpecs[idx] == spec) + return true; + } + return false; +} + +inline gen_s32 gen_specifiers_index_of(gen_CodeSpecifiers self, gen_Specifier spec) { GEN_ASSERT(self != gen_nullptr); for (gen_s32 idx = 0; idx < self->NumEntries; idx++) @@ -10481,12 +10751,12 @@ inline void gen_struct_add_interface(gen_CodeStruct self, gen_CodeTypename type) // then you'll need to move this over to ParentType->next and update ParentAccess accordingly. } - while (possible_slot != gen_nullptr) + while (possible_slot->Next != gen_nullptr) { possible_slot = gen_cast(gen_CodeTypename, possible_slot->Next); } - possible_slot = type; + possible_slot->Next = gen_cast(gen_Code, type); } #pragma endregion gen_Code @@ -10537,91 +10807,6 @@ inline gen_Str gen_token_fmt_impl(gen_ssize num, ...) #pragma endregion Inlines -#pragma region Constants - - -GEN_API extern gen_Macro gen_enum_underlying_macro; - -GEN_API extern gen_Code gen_access_public; -GEN_API extern gen_Code gen_access_protected; -GEN_API extern gen_Code gen_access_private; - -GEN_API extern gen_CodeAttributes gen_attrib_api_export; -GEN_API extern gen_CodeAttributes gen_attrib_api_import; - -GEN_API extern gen_Code gen_module_global_fragment; -GEN_API extern gen_Code gen_module_private_fragment; - -GEN_API extern gen_Code gen_fmt_newline; - -GEN_API extern gen_CodePragma gen_pragma_once; - -GEN_API extern gen_CodeParams gen_param_varadic; - -GEN_API extern gen_CodePreprocessCond gen_preprocess_else; -GEN_API extern gen_CodePreprocessCond gen_preprocess_endif; - -GEN_API extern gen_CodeSpecifiers gen_spec_const; -GEN_API extern gen_CodeSpecifiers gen_spec_consteval; -GEN_API extern gen_CodeSpecifiers gen_spec_constexpr; -GEN_API extern gen_CodeSpecifiers gen_spec_constinit; -GEN_API extern gen_CodeSpecifiers gen_spec_extern_linkage; -GEN_API extern gen_CodeSpecifiers gen_spec_final; -GEN_API extern gen_CodeSpecifiers gen_spec_forceinline; -GEN_API extern gen_CodeSpecifiers gen_spec_global; -GEN_API extern gen_CodeSpecifiers gen_spec_inline; -GEN_API extern gen_CodeSpecifiers gen_spec_internal_linkage; -GEN_API extern gen_CodeSpecifiers gen_spec_local_persist; -GEN_API extern gen_CodeSpecifiers gen_spec_mutable; -GEN_API extern gen_CodeSpecifiers gen_spec_neverinline; -GEN_API extern gen_CodeSpecifiers gen_spec_noexcept; -GEN_API extern gen_CodeSpecifiers gen_spec_override; -GEN_API extern gen_CodeSpecifiers gen_spec_ptr; -GEN_API extern gen_CodeSpecifiers gen_spec_pure; -GEN_API extern gen_CodeSpecifiers gen_spec_ref; -GEN_API extern gen_CodeSpecifiers gen_spec_register; -GEN_API extern gen_CodeSpecifiers gen_spec_rvalue; -GEN_API extern gen_CodeSpecifiers gen_spec_static_member; -GEN_API extern gen_CodeSpecifiers gen_spec_thread_local; -GEN_API extern gen_CodeSpecifiers gen_spec_virtual; -GEN_API extern gen_CodeSpecifiers gen_spec_volatile; - -GEN_API extern gen_CodeTypename gen_t_empty; // Used with varaidc parameters. (Exposing just in case its useful for another circumstance) -GEN_API extern gen_CodeTypename gen_t_auto; -GEN_API extern gen_CodeTypename gen_t_void; -GEN_API extern gen_CodeTypename gen_t_int; -GEN_API extern gen_CodeTypename gen_t_bool; -GEN_API extern gen_CodeTypename gen_t_char; -GEN_API extern gen_CodeTypename gen_t_wchar_t; -GEN_API extern gen_CodeTypename gen_t_class; -GEN_API extern gen_CodeTypename gen_t_typename; - -#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS - -// Predefined typename codes. Are set to readonly and are setup during gen::gen_init() -GEN_API extern gen_Context* gen__ctx; - -GEN_API extern gen_CodeTypename gen_t_b32; - -GEN_API extern gen_CodeTypename gen_t_s8; -GEN_API extern gen_CodeTypename gen_t_s16; -GEN_API extern gen_CodeTypename gen_t_s32; -GEN_API extern gen_CodeTypename gen_t_s64; - -GEN_API extern gen_CodeTypename gen_t_u8; -GEN_API extern gen_CodeTypename gen_t_u16; -GEN_API extern gen_CodeTypename gen_t_u32; -GEN_API extern gen_CodeTypename gen_t_u64; - -GEN_API extern gen_CodeTypename gen_t_ssize; -GEN_API extern gen_CodeTypename gen_t_usize; - -GEN_API extern gen_CodeTypename gen_t_f32; -GEN_API extern gen_CodeTypename gen_t_f64; -#endif - -#pragma endregion Constants - #pragma region gen_Builder @@ -11745,7 +11930,7 @@ void gen_heap_stats_check( void ) typedef struct gen__heap_alloc_info gen__heap_alloc_info; struct gen__heap_alloc_info { - gen_ssize size; + gen_ssize size; void* physical_start; }; @@ -12323,6 +12508,122 @@ gen_StrBuilder gen_strbuilder_make_reserve( gen_AllocatorInfo allocator, gen_ssi return result; } +bool gen_strbuilder_make_space_for(gen_StrBuilder* str, char const* to_append, gen_ssize add_len) +{ + gen_ssize available = gen_strbuilder_avail_space(* str); + + if (available >= add_len) { + return true; + } + else + { + gen_ssize new_len, old_size, new_size; + void* ptr; + void* new_ptr; + + gen_AllocatorInfo allocator = gen_strbuilder_get_header(* str)->Allocator; + gen_StrBuilderHeader* header = gen_nullptr; + + new_len = gen_strbuilder_grow_formula(gen_strbuilder_length(* str) + add_len); + ptr = gen_strbuilder_get_header(* str); + old_size = gen_size_of(gen_StrBuilderHeader) + gen_strbuilder_length(* str) + 1; + new_size = gen_size_of(gen_StrBuilderHeader) + new_len + 1; + + new_ptr = gen_resize(allocator, ptr, old_size, new_size); + + if (new_ptr == gen_nullptr) + return false; + + header = gen_rcast(gen_StrBuilderHeader*, new_ptr); + header->Allocator = allocator; + header->Capacity = new_len; + + char** Data = gen_rcast(char**, str); + * Data = gen_rcast(char*, header + 1); + + return true; + } +} + +bool gen_strbuilder_append_c_str_len(gen_StrBuilder* str, char const* gen_c_str_to_append, gen_ssize append_length) +{ + GEN_ASSERT(str != gen_nullptr); + if ( gen_rcast(gen_sptr, gen_c_str_to_append) > 0) + { + gen_ssize curr_len = gen_strbuilder_length(* str); + + if ( ! gen_strbuilder_make_space_for(str, gen_c_str_to_append, append_length)) + return false; + + gen_StrBuilderHeader* header = gen_strbuilder_get_header(* str); + + char* Data = * str; + gen_mem_copy( Data + curr_len, gen_c_str_to_append, append_length); + + Data[curr_len + append_length] = '\0'; + + header->Length = curr_len + append_length; + } + return gen_c_str_to_append != gen_nullptr; +} + +void gen_strbuilder_trim(gen_StrBuilder str, char const* cut_set) +{ + gen_ssize len = 0; + + char* start_pos = str; + char* gen_end_pos = gen_scast(char*, str) + gen_strbuilder_length(str) - 1; + + while (start_pos <= gen_end_pos && gen_char_first_occurence(cut_set, *start_pos)) + start_pos++; + + while (gen_end_pos > start_pos && gen_char_first_occurence(cut_set, *gen_end_pos)) + gen_end_pos--; + + len = gen_scast(gen_ssize, (start_pos > gen_end_pos) ? 0 : ((gen_end_pos - start_pos) + 1)); + + if (str != start_pos) + gen_mem_move(str, start_pos, len); + + str[len] = '\0'; + + gen_strbuilder_get_header(str)->Length = len; +} + +gen_StrBuilder gen_strbuilder_visualize_whitespace(gen_StrBuilder const str) +{ + gen_StrBuilderHeader* header = (gen_StrBuilderHeader*)(gen_scast(char const*, str) - sizeof(gen_StrBuilderHeader)); + gen_StrBuilder result = gen_strbuilder_make_reserve(header->Allocator, gen_strbuilder_length(str) * 2); // Assume worst case for space requirements. + + for (char const* c = gen_strbuilder_begin(str); c != gen_strbuilder_end(str); c = gen_strbuilder_next(str, c)) + switch ( * c ) + { + case ' ': + gen_strbuilder_append_str(& result, txt("·")); + break; + case '\t': + gen_strbuilder_append_str(& result, txt("→")); + break; + case '\n': + gen_strbuilder_append_str(& result, txt("↵")); + break; + case '\r': + gen_strbuilder_append_str(& result, txt("⏎")); + break; + case '\v': + gen_strbuilder_append_str(& result, txt("⇕")); + break; + case '\f': + gen_strbuilder_append_str(& result, txt("⌂")); + break; + default: + gen_strbuilder_append_char(& result, * c); + break; + } + + return result; +} + #pragma endregion gen_StrBuilder #pragma region File Handling @@ -14807,11 +15108,11 @@ gen_Code result = gen_make_code(); gen_StrBuilder gen_code__to_strbuilder( gen_Code self) { gen_StrBuilder result = gen_strbuilder_make_str( gen__ctx->Allocator_Temp, txt("") ); - gen_code_to_strbuilder_ptr( self, & result ); + gen_code_to_strbuilder_ref( self, & result ); return result; } -void gen_code__to_strbuilder_ptr( gen_Code self, gen_StrBuilder * result) +void gen_code__to_strbuilder_ref( gen_Code self, gen_StrBuilder * result) { GEN_ASSERT(self != gen_nullptr); gen_local_persist gen_thread_local @@ -15730,21 +16031,6 @@ switch ( self->Type ) return false; } -inline -gen_StrBuilder gen_attributes_to_strbuilder(gen_CodeAttributes attributes) { - GEN_ASSERT(attributes); - char* raw = gen_ccast(char*, gen_str_duplicate( attributes->Content, gen__ctx->Allocator_Temp ).Ptr); - gen_StrBuilder result = { raw }; - return result; -} - -inline -void gen_attributes_to_strbuilder_ref(gen_CodeAttributes attributes, gen_StrBuilder* result) { - GEN_ASSERT(attributes); - GEN_ASSERT(result); - gen_strbuilder_append_str(result, attributes->Content); -} - gen_StrBuilder gen_body_to_strbuilder(gen_CodeBody body) { GEN_ASSERT(body); @@ -15774,20 +16060,6 @@ gen_StrBuilder gen_body_to_strbuilder(gen_CodeBody body) return result; } -void gen_body_to_strbuilder_ref( gen_CodeBody body, gen_StrBuilder* result ) -{ - GEN_ASSERT(body != gen_nullptr); - GEN_ASSERT(result != gen_nullptr); - gen_Code curr = body->Front; - gen_s32 left = body->NumEntries; - while ( left -- ) - { - gen_code_to_strbuilder_ptr(curr, result); - // gen_strbuilder_append_fmt( result, "%SB", gen_code_to_strbuilder(curr) ); - ++curr; - } -} - void gen_body_to_strbuilder_export( gen_CodeBody body, gen_StrBuilder* result ) { GEN_ASSERT(body != gen_nullptr); @@ -15798,7 +16070,7 @@ void gen_body_to_strbuilder_export( gen_CodeBody body, gen_StrBuilder* result ) gen_s32 left = body->NumEntries; while ( left-- ) { - gen_code_to_strbuilder_ptr(curr, result); + gen_code_to_strbuilder_ref(curr, result); // gen_strbuilder_append_fmt( result, "%SB", gen_code_to_strbuilder(curr) ); ++curr; } @@ -15806,23 +16078,9 @@ void gen_body_to_strbuilder_export( gen_CodeBody body, gen_StrBuilder* result ) gen_strbuilder_append_fmt( result, "};\n" ); } -inline -gen_StrBuilder gen_comment_to_strbuilder(gen_CodeComment comment) { - GEN_ASSERT(comment); - char* raw = gen_ccast(char*, gen_str_duplicate( comment->Content, gen__ctx->Allocator_Temp ).Ptr); - gen_StrBuilder result = { raw }; - return result; -} - -inline -void gen_comment_to_strbuilder_ref(gen_CodeComment comment, gen_StrBuilder* result) { - GEN_ASSERT(comment); - GEN_ASSERT(result); - gen_strbuilder_append_str(result, comment->Content); -} - gen_StrBuilder gen_constructor__to_strbuilder(gen_CodeConstructor self) { + GEN_ASSERT(self); gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 128 ); switch (self->Type) { @@ -15838,6 +16096,8 @@ gen_StrBuilder gen_constructor__to_strbuilder(gen_CodeConstructor self) void gen_constructor__to_strbuilder_def(gen_CodeConstructor self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); gen_Code ClassStructParent = self->Parent->Parent; if (ClassStructParent) { gen_strbuilder_append_str( result, ClassStructParent->Name ); @@ -15862,6 +16122,8 @@ void gen_constructor__to_strbuilder_def(gen_CodeConstructor self, gen_StrBuilder void gen_constructor__to_strbuilder_fwd(gen_CodeConstructor self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); gen_Code ClassStructParent = self->Parent->Parent; if (ClassStructParent) { gen_strbuilder_append_str( result, ClassStructParent->Name ); @@ -15886,6 +16148,7 @@ void gen_constructor__to_strbuilder_fwd(gen_CodeConstructor self, gen_StrBuilder gen_StrBuilder gen_class_to_strbuilder( gen_CodeClass self ) { + GEN_ASSERT(self); gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 512 ); switch ( self->Type ) { @@ -15902,6 +16165,7 @@ gen_StrBuilder gen_class_to_strbuilder( gen_CodeClass self ) void gen_class_to_strbuilder_def( gen_CodeClass self, gen_StrBuilder* result ) { GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -15916,7 +16180,7 @@ void gen_class_to_strbuilder_def( gen_CodeClass self, gen_StrBuilder* result ) if ( self->Name.Len ) gen_strbuilder_append_str( result, self->Name ); - if (self->Specs && gen_specifiers_has(self->Specs, Spec_Final) > -1) + if (self->Specs && gen_specifiers_has(self->Specs, Spec_Final)) gen_strbuilder_append_str(result, txt(" final")); if ( self->ParentType ) @@ -15949,6 +16213,7 @@ void gen_class_to_strbuilder_def( gen_CodeClass self, gen_StrBuilder* result ) void gen_class_to_strbuilder_fwd( gen_CodeClass self, gen_StrBuilder* result ) { GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -15968,13 +16233,6 @@ void gen_class_to_strbuilder_fwd( gen_CodeClass self, gen_StrBuilder* result ) } } -gen_StrBuilder gen_define_to_strbuilder(gen_CodeDefine define) -{ - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 512 ); - gen_define_to_strbuilder_ref(define, & result); - return result; -} - void gen_define_to_strbuilder_ref(gen_CodeDefine define, gen_StrBuilder* result ) { GEN_ASSERT(define); @@ -15989,14 +16247,6 @@ void gen_define_to_strbuilder_ref(gen_CodeDefine define, gen_StrBuilder* result } } -gen_StrBuilder gen_define_params_to_strbuilder(gen_CodeDefineParams params) -{ - GEN_ASSERT(params); - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 128 ); - gen_define_params_to_strbuilder_ref( params, & result ); - return result; -} - void gen_define_params_to_strbuilder_ref(gen_CodeDefineParams self, gen_StrBuilder* result) { GEN_ASSERT(self); @@ -16016,6 +16266,7 @@ void gen_define_params_to_strbuilder_ref(gen_CodeDefineParams self, gen_StrBuild gen_StrBuilder gen_destructor__to_strbuilder(gen_CodeDestructor self) { + GEN_ASSERT(self); gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 128 ); switch ( self->Type ) { @@ -16031,6 +16282,8 @@ gen_StrBuilder gen_destructor__to_strbuilder(gen_CodeDestructor self) void gen_destructor__to_strbuilder_def(gen_CodeDestructor self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( self->Name.Len ) { gen_strbuilder_append_fmt( result, "%S()", self->Name ); @@ -16050,6 +16303,8 @@ void gen_destructor__to_strbuilder_def(gen_CodeDestructor self, gen_StrBuilder* void gen_destructor__to_strbuilder_fwd(gen_CodeDestructor self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( self->Specs ) { if ( gen_specifiers_has(self->Specs, Spec_Virtual ) ) @@ -16073,6 +16328,7 @@ void gen_destructor__to_strbuilder_fwd(gen_CodeDestructor self, gen_StrBuilder* gen_StrBuilder gen_enum_to_strbuilder(gen_CodeEnum self) { + GEN_ASSERT(self); gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 512 ); switch ( self->Type ) { @@ -16094,6 +16350,8 @@ gen_StrBuilder gen_enum_to_strbuilder(gen_CodeEnum self) void gen_enum_to_strbuilder_def(gen_CodeEnum self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -16127,6 +16385,8 @@ void gen_enum_to_strbuilder_def(gen_CodeEnum self, gen_StrBuilder* result ) void gen_enum_to_strbuilder_fwd(gen_CodeEnum self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -16154,6 +16414,8 @@ void gen_enum_to_strbuilder_fwd(gen_CodeEnum self, gen_StrBuilder* result ) void gen_enum_to_strbuilder_class_def(gen_CodeEnum self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -16186,6 +16448,8 @@ void gen_enum_to_strbuilder_class_def(gen_CodeEnum self, gen_StrBuilder* result void gen_enum_to_strbuilder_class_fwd(gen_CodeEnum self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -16205,56 +16469,9 @@ void gen_enum_to_strbuilder_class_fwd(gen_CodeEnum self, gen_StrBuilder* result } } -gen_StrBuilder gen_exec_to_strbuilder(gen_CodeExec exec) -{ - GEN_ASSERT(exec); - char* raw = gen_ccast(char*, gen_str_duplicate( exec->Content, gen__ctx->Allocator_Temp ).Ptr); - gen_StrBuilder result = { raw }; - return result; -} - -void gen_extern_to_strbuilder(gen_CodeExtern self, gen_StrBuilder* result ) -{ - if ( self->Body ) - gen_strbuilder_append_fmt( result, "extern \"%S\"\n{\n%SB\n}\n", self->Name, gen_body_to_strbuilder(self->Body) ); - else - gen_strbuilder_append_fmt( result, "extern \"%S\"\n{}\n", self->Name ); -} - -gen_StrBuilder gen_include_to_strbuilder(gen_CodeInclude include) -{ - return gen_strbuilder_fmt_buf( gen__ctx->Allocator_Temp, "#include %S\n", include->Content ); -} - -void gen_include_to_strbuilder_ref( gen_CodeInclude include, gen_StrBuilder* result ) -{ - gen_strbuilder_append_fmt( result, "#include %S\n", include->Content ); -} - -gen_StrBuilder gen_friend_to_strbuilder(gen_CodeFriend self) -{ - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 256 ); - gen_friend_to_strbuilder_ref( self, & result ); - return result; -} - -void gen_friend_to_strbuilder_ref(gen_CodeFriend self, gen_StrBuilder* result ) -{ - gen_strbuilder_append_fmt( result, "friend %SB", gen_code_to_strbuilder(self->Declaration) ); - - if ( self->Declaration->Type != CT_Function && self->Declaration->Type != CT_Operator && (* result)[ gen_strbuilder_length(* result) - 1 ] != ';' ) - { - gen_strbuilder_append_str( result, txt(";") ); - } - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, " %S", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, txt("\n")); -} - gen_StrBuilder gen_fn_to_strbuilder(gen_CodeFn self) { + GEN_ASSERT(self); gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 512 ); switch ( self->Type ) { @@ -16270,6 +16487,8 @@ gen_StrBuilder gen_fn_to_strbuilder(gen_CodeFn self) void gen_fn_to_strbuilder_def(gen_CodeFn self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export") ); @@ -16327,6 +16546,8 @@ void gen_fn_to_strbuilder_def(gen_CodeFn self, gen_StrBuilder* result ) void gen_fn_to_strbuilder_fwd(gen_CodeFn self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -16376,9 +16597,9 @@ void gen_fn_to_strbuilder_fwd(gen_CodeFn self, gen_StrBuilder* result ) } } - if ( gen_specifiers_has(self->Specs, Spec_Pure ) >= 0 ) + if ( gen_specifiers_has(self->Specs, Spec_Pure ) ) gen_strbuilder_append_str( result, txt(" = 0") ); - else if ( gen_specifiers_has(self->Specs, Spec_Delete ) >= 0 ) + else if ( gen_specifiers_has(self->Specs, Spec_Delete ) ) gen_strbuilder_append_str( result, txt(" = delete") ); } @@ -16395,15 +16616,10 @@ void gen_fn_to_strbuilder_fwd(gen_CodeFn self, gen_StrBuilder* result ) gen_strbuilder_append_str( result, txt(";\n") ); } -gen_StrBuilder gen_module_to_strbuilder(gen_CodeModule self) -{ - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 64 ); - gen_module_to_strbuilder_ref( self, & result ); - return result; -} - void gen_module_to_strbuilder_ref(gen_CodeModule self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if (((gen_scast(gen_u32, ModuleFlag_Export) & gen_scast(gen_u32, self->ModuleFlags)) == gen_scast(gen_u32, ModuleFlag_Export))) gen_strbuilder_append_str( result, txt("export ")); @@ -16413,23 +16629,9 @@ void gen_module_to_strbuilder_ref(gen_CodeModule self, gen_StrBuilder* result ) gen_strbuilder_append_fmt( result, "%S;\n", self->Name ); } -gen_StrBuilder namespace_to_strbuilder(gen_CodeNS self) -{ - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 512 ); - namespace_to_strbuilder_ref( self, & result ); - return result; -} - -void namespace_to_strbuilder_ref(gen_CodeNS self, gen_StrBuilder* result ) -{ - if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) - gen_strbuilder_append_str( result, txt("export ") ); - - gen_strbuilder_append_fmt( result, "namespace %S\n{\n%SB\n}\n", self->Name, gen_body_to_strbuilder(self->Body) ); -} - gen_StrBuilder gen_code_op_to_strbuilder(gen_CodeOperator self) { + GEN_ASSERT(self); gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 512 ); switch ( self->Type ) { @@ -16447,6 +16649,8 @@ gen_StrBuilder gen_code_op_to_strbuilder(gen_CodeOperator self) void gen_code_op_to_strbuilder_def(gen_CodeOperator self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -16501,6 +16705,8 @@ void gen_code_op_to_strbuilder_def(gen_CodeOperator self, gen_StrBuilder* result void gen_code_op_to_strbuilder_fwd(gen_CodeOperator self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -16552,6 +16758,7 @@ void gen_code_op_to_strbuilder_fwd(gen_CodeOperator self, gen_StrBuilder* result gen_StrBuilder gen_opcast_to_strbuilder(gen_CodeOpCast self) { + GEN_ASSERT(self); gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 128 ); switch ( self->Type ) { @@ -16567,6 +16774,8 @@ gen_StrBuilder gen_opcast_to_strbuilder(gen_CodeOpCast self) void gen_opcast_to_strbuilder_def(gen_CodeOpCast self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( self->Specs ) { for ( gen_Specifier* spec = gen_begin_CodeSpecifiers(self->Specs); spec != gen_end_CodeSpecifiers(self->Specs); spec = gen_next_CodeSpecifiers(self->Specs, spec) ) @@ -16604,6 +16813,8 @@ void gen_opcast_to_strbuilder_def(gen_CodeOpCast self, gen_StrBuilder* result ) void gen_opcast_to_strbuilder_fwd(gen_CodeOpCast self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( self->Specs ) { for ( gen_Specifier* spec = gen_begin_CodeSpecifiers(self->Specs); spec != gen_end_CodeSpecifiers(self->Specs); spec = gen_next_CodeSpecifiers(self->Specs, spec) ) @@ -16639,14 +16850,6 @@ void gen_opcast_to_strbuilder_fwd(gen_CodeOpCast self, gen_StrBuilder* result ) gen_strbuilder_append_fmt( result, "operator %SB();\n", gen_typename_to_strbuilder(self->ValueType) ); } -gen_StrBuilder gen_params_to_strbuilder(gen_CodeParams self) -{ - GEN_ASSERT(self); - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 128 ); - gen_params_to_strbuilder_ref( self, & result ); - return result; -} - void gen_params_to_strbuilder_ref( gen_CodeParams self, gen_StrBuilder* result ) { GEN_ASSERT(self); @@ -16714,62 +16917,6 @@ gen_StrBuilder gen_preprocess_to_strbuilder(gen_CodePreprocessCond self) return result; } -void gen_preprocess_to_strbuilder_if(gen_CodePreprocessCond cond, gen_StrBuilder* result ) -{ - GEN_ASSERT(cond); - gen_strbuilder_append_fmt( result, "#if %S", cond->Content ); -} - -void gen_preprocess_to_strbuilder_ifdef(gen_CodePreprocessCond cond, gen_StrBuilder* result ) -{ - GEN_ASSERT(cond); - gen_strbuilder_append_fmt( result, "#ifdef %S\n", cond->Content ); -} - -void gen_preprocess_to_strbuilder_ifndef(gen_CodePreprocessCond cond, gen_StrBuilder* result ) -{ - GEN_ASSERT(cond); - gen_strbuilder_append_fmt( result, "#ifndef %S", cond->Content ); -} - -void gen_preprocess_to_strbuilder_elif(gen_CodePreprocessCond cond, gen_StrBuilder* result ) -{ - GEN_ASSERT(cond); - gen_strbuilder_append_fmt( result, "#elif %S\n", cond->Content ); -} - -void gen_preprocess_to_strbuilder_else(gen_CodePreprocessCond cond, gen_StrBuilder* result ) -{ - GEN_ASSERT(cond); - gen_strbuilder_append_str( result, txt("#else\n") ); -} - -void gen_preprocess_to_strbuilder_endif(gen_CodePreprocessCond cond, gen_StrBuilder* result ) -{ - GEN_ASSERT(cond); - gen_strbuilder_append_str( result, txt("#endif\n") ); -} - -gen_StrBuilder gen_pragma_to_strbuilder(gen_CodePragma self) -{ - GEN_ASSERT(self); - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 256 ); - gen_pragma_to_strbuilder_ref( self, & result ); - return result; -} - -void gen_pragma_to_strbuilder_ref(gen_CodePragma self, gen_StrBuilder* result ) -{ - gen_strbuilder_append_fmt( result, "#pragma %S\n", self->Content ); -} - -gen_StrBuilder gen_specifiers_to_strbuilder(gen_CodeSpecifiers self) -{ - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 64 ); - gen_specifiers_to_strbuilder_ref( self, & result ); - return result; -} - void gen_specifiers_to_strbuilder_ref( gen_CodeSpecifiers self, gen_StrBuilder* result ) { GEN_ASSERT(self); @@ -16882,14 +17029,6 @@ void gen_struct_to_strbuilder_fwd( gen_CodeStruct self, gen_StrBuilder* result ) } } -gen_StrBuilder gen_template_to_strbuilder(gen_CodeTemplate self) -{ - GEN_ASSERT(self); - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 1024 ); - gen_template_to_strbuilder_ref( self, & result ); - return result; -} - void gen_template_to_strbuilder_ref(gen_CodeTemplate self, gen_StrBuilder* result ) { GEN_ASSERT(self); @@ -16903,15 +17042,10 @@ void gen_template_to_strbuilder_ref(gen_CodeTemplate self, gen_StrBuilder* resul gen_strbuilder_append_fmt( result, "template<>\n%SB", gen_code_to_strbuilder(self->Declaration) ); } -gen_StrBuilder gen_typedef_to_strbuilder(gen_CodeTypedef self) -{ - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 128 ); - gen_typedef_to_strbuilder_ref( self, & result ); - return result; -} - void gen_typedef_to_strbuilder_ref(gen_CodeTypedef self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -16945,15 +17079,10 @@ void gen_typedef_to_strbuilder_ref(gen_CodeTypedef self, gen_StrBuilder* result gen_strbuilder_append_str( result, txt("\n")); } -gen_StrBuilder gen_typename_to_strbuilder(gen_CodeTypename self) -{ - gen_StrBuilder result = gen_strbuilder_make_str( gen__ctx->Allocator_Temp, txt("") ); - gen_typename_to_strbuilder_ref( self, & result ); - return result; -} - void gen_typename_to_strbuilder_ref(gen_CodeTypename self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); #if defined(GEN_USE_NEW_TYPENAME_PARSING) if ( self->ReturnType && self->Params ) { @@ -17010,6 +17139,7 @@ void gen_typename_to_strbuilder_ref(gen_CodeTypename self, gen_StrBuilder* resul gen_StrBuilder union_to_strbuilder(gen_CodeUnion self) { + GEN_ASSERT(self); gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 512 ); switch ( self->Type ) { @@ -17025,6 +17155,8 @@ gen_StrBuilder union_to_strbuilder(gen_CodeUnion self) void union_to_strbuilder_def(gen_CodeUnion self, gen_StrBuilder* result ) { + GEN_ASSERT(self); + GEN_ASSERT(result); if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) gen_strbuilder_append_str( result, txt("export ") ); @@ -17073,22 +17205,6 @@ void union_to_strbuilder_fwd(gen_CodeUnion self, gen_StrBuilder* result ) gen_strbuilder_append_str( result, txt(";\n")); } -gen_StrBuilder gen_using_to_strbuilder(gen_CodeUsing self) -{ - GEN_ASSERT(self); - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 128 ); - switch ( self->Type ) - { - case CT_Using: - gen_using_to_strbuilder_ref( self, & result ); - break; - case CT_Using_Namespace: - gen_using_to_strbuilder_ns( self, & result ); - break; - } - return result; -} - void gen_using_to_strbuilder_ref(gen_CodeUsing self, gen_StrBuilder* result ) { GEN_ASSERT(self); @@ -17126,26 +17242,6 @@ void gen_using_to_strbuilder_ref(gen_CodeUsing self, gen_StrBuilder* result ) gen_strbuilder_append_str( result, txt("\n")); } -inline -void gen_using_to_strbuilder_ns(gen_CodeUsing self, gen_StrBuilder* result ) -{ - GEN_ASSERT(self); - GEN_ASSERT(result); - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "using namespace $SC; %S", self->Name, self->InlineCmt->Content ); - else - gen_strbuilder_append_fmt( result, "using namespace %S;\n", self->Name ); -} - -inline -gen_StrBuilder gen_var_to_strbuilder(gen_CodeVar self) -{ - GEN_ASSERT(self); - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 256 ); - gen_var_to_strbuilder_ref( self, & result ); - return result; -} - gen_neverinline void gen_var_to_strbuilder_ref(gen_CodeVar self, gen_StrBuilder* result ) { @@ -19059,9 +19155,9 @@ gen_CodeTypename gen_def__type(gen_Str name, gen_Opts_def_type p) GEN_DEBUG_TRAP(); return gen_InvalidCode; } - gen_Code arrayexpr = p.arrayexpr; - gen_CodeSpecifiers specifiers = p.specifiers; - gen_CodeAttributes attributes = p.attributes; + gen_Code gen_array_expr = p.gen_array_expr; + gen_CodeSpecifiers specifiers = p.specifiers; + gen_CodeAttributes attributes = p.attributes; if (p.attributes && p.attributes->Type != CT_PlatformAttributes) { gen_log_failure("gen::gen_def_type: attributes is not of attributes type - %s", gen_code_debug_str((gen_Code)p.attributes)); @@ -19074,9 +19170,9 @@ gen_CodeTypename gen_def__type(gen_Str name, gen_Opts_def_type p) GEN_DEBUG_TRAP(); return gen_InvalidCode; } - if (p.arrayexpr && p.arrayexpr->Type != CT_Untyped) + if (p.gen_array_expr && p.gen_array_expr->Type != CT_Untyped) { - gen_log_failure("gen::gen_def_type: arrayexpr is not of untyped type - %s", gen_code_debug_str((gen_Code)p.arrayexpr)); + gen_log_failure("gen::gen_def_type: arrayexpr is not of untyped type - %s", gen_code_debug_str((gen_Code)p.gen_array_expr)); GEN_DEBUG_TRAP(); return gen_InvalidCode; } @@ -19085,7 +19181,7 @@ gen_CodeTypename gen_def__type(gen_Str name, gen_Opts_def_type p) result->Type = CT_Typename; result->Attributes = p.attributes; result->Specs = p.specifiers; - result->ArrExpr = p.arrayexpr; + result->ArrExpr = p.gen_array_expr; result->TypeTag = p.type_tag; return result; } @@ -20753,6 +20849,11 @@ void gen_lex_found_token(gen_LexContext* ctx) gen_TokType type = gen_str_to_toktype(ctx->token.Text); + if (type == Tok_Preprocess_Define || type == Tok_Preprocess_Include) + { + ctx->token.Flags |= TF_Identifier; + } + if (type <= Tok_Access_Public && type >= Tok_Access_Private) { ctx->token.Flags |= TF_AccessSpecifier; @@ -23419,8 +23520,11 @@ gen_internal inline gen_Code gen_parse_assignment_expression() eat(currtok.Type); } - expr_tok.Text.Len = ((gen_sptr)currtok.Text.Ptr + currtok.Text.Len) - (gen_sptr)expr_tok.Text.Ptr - 1; - expr = gen_untyped_str(expr_tok.Text); + if (left) + { + expr_tok.Text.Len = ((gen_sptr)currtok.Text.Ptr + currtok.Text.Len) - (gen_sptr)expr_tok.Text.Ptr - 1; + } + expr = gen_untyped_str(expr_tok.Text); // = return expr; } @@ -24859,10 +24963,10 @@ gen_internal inline gen_CodeParams gen_parse_params(bool use_template_capture) } // ( - if (check(Tok_Identifier)) + if (check(Tok_Identifier) || gen_bitfield_is_set(gen_u32, currtok.Flags, TF_Identifier)) { name = currtok; - eat(Tok_Identifier); + eat(currtok.Type); // ( } @@ -24971,10 +25075,10 @@ gen_internal inline gen_CodeParams gen_parse_params(bool use_template_capture) name = gen_NullToken; - if (check(Tok_Identifier)) + if (check(Tok_Identifier) || gen_bitfield_is_set(gen_u32, currtok.Flags, TF_Identifier)) { name = currtok; - eat(Tok_Identifier); + eat(currtok.Type); // ( = , } @@ -28355,7 +28459,7 @@ gen_Code gen_scan_file(char const* path) gen_file_read(&file, str, fsize); gen_strbuilder_get_header(str)->Length = fsize; - // Skip GEN_INTELLISENSE_DIRECTIVES preprocessor blocks + // Skip 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. { @@ -28369,7 +28473,7 @@ gen_Code gen_scan_file(char const* path) } while (0) const gen_Str directive_start = txt("ifdef"); const gen_Str directive_end = txt("endif"); - const gen_Str gen_def_intellisense = txt("GEN_INTELLISENSE_DIRECTIVES"); + const gen_Str gen_def_intellisense = txt("INTELLISENSE_DIRECTIVES"); bool found_directive = false; char const* scanner = (char const*)str;