From 7949d2ba5f11f28814c1b743163487758d8a67e2 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 10 Oct 2025 19:28:36 -0400 Subject: [PATCH] Remove gencpp_c11 for now (not using yet, maybe I'll do a truncated version) Prepparing to explore Lottes's C-- more, also how crufty it looks in odin. --- C/gencpp_c11.h | 29125 ---------------- C/watl.v0.llvm.lottes.c | 61 + ....lottes.c => watl.v0.llvm.lottes_hybrid.c} | 39 +- C/watl.v0.msvc.c | 2 +- Odin/watl.v0.win32.ideomatic.odin | 0 Odin/watl.win32.lottes.odin | 0 Readme.md | 2 + scripts/build.c_lottes.ps1 | 2 +- 8 files changed, 77 insertions(+), 29154 deletions(-) delete mode 100644 C/gencpp_c11.h create mode 100644 C/watl.v0.llvm.lottes.c rename C/{watl.v0.lottes.c => watl.v0.llvm.lottes_hybrid.c} (98%) create mode 100644 Odin/watl.v0.win32.ideomatic.odin create mode 100644 Odin/watl.win32.lottes.odin diff --git a/C/gencpp_c11.h b/C/gencpp_c11.h deleted file mode 100644 index dddd7c4..0000000 --- a/C/gencpp_c11.h +++ /dev/null @@ -1,29125 +0,0 @@ -// This file was generated automatially by gencpp's c_library.cpp (See: https://github.com/Ed94/gencpp) - -#pragma once - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wunused-const-variable" -# pragma clang diagnostic ignored "-Wunused-but-set-variable" -# pragma clang diagnostic ignored "-Wswitch" -# pragma clang diagnostic ignored "-Wunused-variable" -# pragma clang diagnostic ignored "-Wunknown-pragmas" -# pragma clang diagnostic ignored "-Wvarargs" -# pragma clang diagnostic ignored "-Wunused-function" -# pragma clang diagnostic ignored "-Wbraced-scalar-init" -# pragma clang diagnostic ignored "-W#pragma-messages" -# pragma clang diagnostic ignored "-Wstatic-in-inline" -#endif - -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -# pragma GCC diagnostic ignored "-Wcomment" -# pragma GCC diagnostic ignored "-Wswitch" -# pragma GCC diagnostic ignored "-Wunused-variable" -#endif -/* - gencpp: An attempt at "simple" staged metaprogramming for c/c++. - - See Readme.md for more information from the project repository. - - Public Address: - https://github.com/Ed94/gencpp ---------------------------------------------------------------. - | _____ _____ _ _ ___ __ __ | - | / ____) / ____} | | | / ,__} / | / | | - | | / ___ ___ _ __ ___ _ __ _ __ | {___ | l_ __ _ __ _, ___ __| | | | '-l | '-l | | - | | |{_ \/ __\ '_ \ / __} '_ l| '_ l \___ \| __/ _` |/ _` |/ __\/ _` | | | | | | | | - | | l__j | ___/ | | | {__; ;_l } ;_l } ____} | l| (_} | {_| | ___j {_; | | l___ _J l_ _J l_ | - | \_____|\___}_l |_|\___} .__/| .__/ {_____/ \__\__/_l\__. |\___/\__,_l \____}{_____}{_____} | - | | | | | __} | | - | l_l l_l {___/ | - ! ----------------------------------------------------------------------- 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 | - ! ============================================================================================= / -*/ -#if ! defined(GEN_DONT_ENFORCE_GEN_TIME_GUARD) && ! defined(GEN_TIME) -# error Gen.hpp : GEN_TIME not defined -#endif - -//! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file. -// Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl -#ifndef GEN_ROLL_OWN_DEPENDENCIES - -#pragma region Platform Detection - -/* Platform architecture */ - -#if defined( _WIN64 ) || defined( __x86_64__ ) || defined( _M_X64 ) || defined( __64BIT__ ) || defined( __powerpc64__ ) || defined( __ppc64__ ) || defined( __aarch64__ ) -# ifndef GEN_ARCH_64_BIT -# define GEN_ARCH_64_BIT 1 -# endif -#else -# ifndef GEN_ARCH_32_BItxt_StrCaT -# define GEN_ARCH_32_BIT 1 -# endif -#endif - -/* Platform OS */ - -#if defined( _WIN32 ) || defined( _WIN64 ) -# ifndef GEN_SYSTEM_WINDOWS -# define GEN_SYSTEM_WINDOWS 1 -# endif -#elif defined( __APPLE__ ) && defined( __MACH__ ) -# ifndef GEN_SYSTEM_OSX -# define GEN_SYSTEM_OSX 1 -# endif -# ifndef GEN_SYSTEM_MACOS -# define GEN_SYSTEM_MACOS 1 -# endif -#elif defined( __unix__ ) -# ifndef GEN_SYSTEM_UNIX -# define GEN_SYSTEM_UNIX 1 -# endif -# if defined( ANDROID ) || defined( __ANDROID__ ) -# ifndef GEN_SYSTEM_ANDROID -# define GEN_SYSTEM_ANDROID 1 -# endif -# ifndef GEN_SYSTEM_LINUX -# define GEN_SYSTEM_LINUX 1 -# endif -# elif defined( __linux__ ) -# ifndef GEN_SYSTEM_LINUX -# define GEN_SYSTEM_LINUX 1 -# endif -# elif defined( __FreeBSD__ ) || defined( __FreeBSD_kernel__ ) -# ifndef GEN_SYSTEM_FREEBSD -# define GEN_SYSTEM_FREEBSD 1 -# endif -# elif defined( __OpenBSD__ ) -# ifndef GEN_SYSTEM_OPENBSD -# define GEN_SYSTEM_OPENBSD 1 -# endif -# elif defined( __EMSCRIPTEN__ ) -# ifndef GEN_SYSTEM_EMSCRIPTEN -# define GEN_SYSTEM_EMSCRIPTEN 1 -# endif -# elif defined( __CYGWIN__ ) -# ifndef GEN_SYSTEM_CYGWIN -# define GEN_SYSTEM_CYGWIN 1 -# endif -# else -# error This UNIX operating system is not supported -# endif -#else -# error This operating system is not supported -#endif - -/* Platform compiler */ - -#if defined( _MSC_VER ) -# pragma message("Detected MSVC") -// # define GEN_COMPILER_CLANG 0 -# define GEN_COMPILER_MSVC 1 -// # define GEN_COMPILER_GCC 0 -#elif defined( __GNUC__ ) -# pragma message("Detected GCC") -// # define GEN_COMPILER_CLANG 0 -// # define GEN_COMPILER_MSVC 0 -# define GEN_COMPILER_GCC 1 -#elif defined( __clang__ ) -# pragma message("Detected CLANG") -# define GEN_COMPILER_CLANG 1 -// # define GEN_COMPILER_MSVC 0 -// # define GEN_COMPILER_GCC 0 -#else -# error Unknown compiler -#endif - -#if defined( __has_attribute ) -# define GEN_HAS_ATTRIBUTE( attribute ) __has_attribute( attribute ) -#else -# define GEN_HAS_ATTRIBUTE( attribute ) ( 0 ) -#endif - -#if defined(GEN_GCC_VERSION_CHECK) -# undef GEN_GCC_VERSION_CHECK -#endif -#if defined(GEN_GCC_VERSION) -# define GEN_GCC_VERSION_CHECK(major,minor,patch) (GEN_GCC_VERSION >= GEN_VERSION_ENCODE(major, minor, patch)) -#else -# define GEN_GCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if !defined(GEN_COMPILER_C) -# ifdef __cplusplus -# define GEN_COMPILER_C 0 -# define GEN_COMPILER_CPP 1 -# else -# if defined(__STDC__) -# define GEN_COMPILER_C 1 -# define GEN_COMPILER_CPP 0 -# else - // Fallback for very old C compilers -# define GEN_COMPILER_C 1 -# define GEN_COMPILER_CPP 0 -# endif -# endif -#endif - -#if GEN_COMPILER_C -#pragma message("GENCPP: Detected C") -#endif - -#pragma endregion Platform Detection - -#pragma region Mandatory Includes - -# include -# include - -# if defined( GEN_SYSTEM_WINDOWS ) -# include -# endif - -#if GEN_COMPILER_C -#include -#include -#endif - -#pragma endregion Mandatory Includes - -#if GEN_DONT_USE_NAMESPACE || GEN_COMPILER_C -# if GEN_COMPILER_C -# define GEN_NS -# define GEN_NS_BEGIN -# define GEN_NS_END -# else -# define GEN_NS :: -# define GEN_NS_BEGIN -# define GEN_NS_END -# endif -#else -# define GEN_NS gen:: -# define GEN_NS_BEGIN namespace gen { -# define GEN_NS_END } -#endif - -GEN_NS_BEGIN - -#pragma region Macros - -#ifndef GEN_API -#if GEN_COMPILER_MSVC - #ifdef GEN_DYN_LINK - #ifdef GEN_DYN_EXPORT - #define GEN_API __declspec(dllexport) - #else - #define GEN_API __declspec(dllimport) - #endif - #else - #define GEN_API // Empty for static builds - #endif -#else - #ifdef GEN_DYN_LINK - #define GEN_API __attribute__((visibility("default"))) - #else - #define GEN_API // Empty for static builds - #endif -#endif -#endif // GEN_API - -#ifndef gen_global // Global variables -# if defined(GEN_STATIC_LINK) || defined(GEN_DYN_LINK) -# define gen_global -# else -# define gen_global static -# endif -#endif -#ifndef gen_internal -#define gen_internal static // Internal linkage -#endif -#ifndef gen_local_persist -#define gen_local_persist static // Local Persisting variables -#endif - -#ifndef gen_bit -#define gen_bit( Value ) ( 1 << Value ) -#endif - -#ifndef gen_bitfield_is_set -#define gen_bitfield_is_set( Type, Field, Mask ) ( (gen_scast(Type, Mask) & gen_scast(Type, Field)) == gen_scast(Type, Mask) ) -#endif - -// Mainly intended for forcing the base library to utilize only C-valid constructs or type coercion -#ifndef GEN_C_LIKE_CPP -#define GEN_C_LIKE_CPP 0 -#endif - -#if GEN_COMPILER_CPP -# ifndef gen_cast -# define gen_cast( type, value ) (tmpl_cast( value )) -# endif -#else -# ifndef gen_cast -# define gen_cast( type, value ) ( (type)(value) ) -# endif -#endif - -#if GEN_COMPILER_CPP -# ifndef gen_ccast -# define gen_ccast( type, value ) ( const_cast< type >( (value) ) ) -# endif -# ifndef gen_pcast -# define gen_pcast( type, value ) ( * reinterpret_cast< type* >( & ( value ) ) ) -# endif -# ifndef gen_rcast -# define gen_rcast( type, value ) reinterpret_cast< type >( value ) -# endif -# ifndef gen_scast -# define gen_scast( type, value ) static_cast< type >( value ) -# endif -#else -# ifndef gen_ccast -# define gen_ccast( type, value ) ( (type)(value) ) -# endif -# ifndef gen_pcast -# define gen_pcast( type, value ) ( * (type*)(& value) ) -# endif -# ifndef gen_rcast -# define gen_rcast( type, value ) ( (type)(value) ) -# endif -# ifndef gen_scast -# define gen_scast( type, value ) ( (type)(value) ) -# endif -#endif - -#ifndef gen_stringize -#define gen_stringize_va( ... ) #__VA_ARGS__ -#define gen_stringize( ... ) gen_stringize_va( __VA_ARGS__ ) -#endif - -#define src_line_str gen_stringize(__LINE__) - -#ifndef gen_do_once -#define gen_do_once() \ - gen_local_persist int __do_once_counter_##src_line_str = 0; \ - for(; __do_once_counter_##src_line_str != 1; __do_once_counter_##src_line_str = 1 ) \ - -#define do_once_defer( expression ) \ - gen_local_persist int __do_once_counter_##src_line_str = 0; \ - for(;__do_once_counter_##src_line_str != 1; __do_once_counter_##src_line_str = 1, (expression)) \ - -#define gen_do_once_start \ - do \ - { \ - gen_local_persist \ - bool done = false; \ - if ( done ) \ - break; \ - done = true; - -#define gen_do_once_end \ - } \ - while(0); -#endif - -#ifndef gen_labeled_scope_start -#define gen_labeled_scope_start if ( false ) { -#define gen_labeled_scope_end } -#endif - -#ifndef gen_compiler_decorated_func_name -# ifdef COMPILER_CLANG -# define gen_compiler_decorated_func_name __PRETTY_NAME__ -# elif defined(COMPILER_MSVC) -# define gen_compiler_decorated_func_name __FUNCDNAME__ -# endif -#endif - -#ifndef gen_num_args_impl - -// This is essentially an arg couneter version of GEN_SELECT_ARG macros -// See section : _Generic function overloading for that usage (explains this heavier case) - -#define gen_num_args_impl( _0, \ - _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ - _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ - _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ - _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ - _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ - _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ - _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, \ - _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, \ - _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, \ - _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, \ - N, ... \ - ) N - -// ## deletes preceding comma if _VA_ARGS__ is empty (GCC, Clang) -#define gen_num_args(...) \ - gen_num_args_impl(_, ## __VA_ARGS__, \ - 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, \ - 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, \ - 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, \ - 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, \ - 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ - 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, \ - 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, \ - 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, \ - 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \ - 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, \ - 0 \ - ) -#endif - -#ifndef gen_clamp -#define gen_clamp( x, lower, upper ) gen_min( gen_max( ( x ), ( lower ) ), ( upper ) ) -#endif -#ifndef gen_count_of -#define gen_count_of( x ) ( ( gen_size_of( x ) / gen_size_of( 0 [ x ] ) ) / ( ( gen_ssize )( ! ( gen_size_of( x ) % gen_size_of( 0 [ x ] ) ) ) ) ) -#endif -#ifndef gen_is_between -#define gen_is_between( x, lower, upper ) ( ( ( lower ) <= ( x ) ) && ( ( x ) <= ( upper ) ) ) -#endif -#ifndef gen_size_of -#define gen_size_of( x ) ( gen_ssize )( sizeof( x ) ) -#endif - -#ifndef gen_max -#define gen_max( a, b ) ( (a > b) ? (a) : (b) ) -#endif -#ifndef gen_min -#define gen_min( a, b ) ( (a < b) ? (a) : (b) ) -#endif - -#if GEN_COMPILER_MSVC || GEN_COMPILER_TINYC -# define gen_offset_of( Type, element ) ( ( GEN_NS( gen_ssize ) ) & ( ( ( Type* )0 )->element ) ) -#else -# define gen_offset_of( Type, element ) __builtin_offsetof( Type, element ) -#endif - -#ifndef gen_forceinline -# if GEN_COMPILER_MSVC -# define gen_forceinline __forceinline -# elif GEN_COMPILER_GCC -# define gen_forceinline inline __attribute__((__always_inline__)) -# elif GEN_COMPILER_CLANG -# if __has_attribute(__always_inline__) -# define gen_forceinline inline __attribute__((__always_inline__)) -# else -# define gen_forceinline -# endif -# else -# define gen_forceinline -# endif -#endif - -#ifndef gen_neverinline -# if GEN_COMPILER_MSVC -# define gen_neverinline __declspec( noinline ) -# elif GEN_COMPILER_GCC -# define gen_neverinline __attribute__( ( __noinline__ ) ) -# elif GEN_COMPILER_CLANG -# if __has_attribute(__always_inline__) -# define gen_neverinline __attribute__( ( __noinline__ ) ) -# else -# define gen_neverinline -# endif -# else -# define gen_neverinline -# endif -#endif - -#if GEN_COMPILER_C -#ifndef gen_static_assert -#undef gen_static_assert - #if GEN_COMPILER_C && __STDC_VERSION__ >= 201112L - #define gen_static_assert(condition, message) _Static_assert(condition, message) - #else - #define gen_static_assert(condition, message) typedef char static_assertion_##__LINE__[(condition)?1:-1] - #endif -#endif -#endif - -#if GEN_COMPILER_CPP -// Already Defined -#elif GEN_COMPILER_C && __STDC_VERSION__ >= 201112L -# define gen_thread_local _Thread_local -#elif GEN_COMPILER_MSVC -# define gen_thread_local __declspec(thread) -#elif GEN_COMPILER_CLANG -# define gen_thread_local __thread -#else -# error "No thread local support" -#endif - -#if ! defined(gen_typeof) && (!GEN_COMPILER_C || __STDC_VERSION__ < 202311L) -# if ! GEN_COMPILER_C -# define gen_typeof decltype -# elif defined(_MSC_VER) -# define gen_typeof __typeof__ -# elif defined(__GNUC__) || defined(__clang__) -# define gen_typeof __typeof__ -# else -# error "Compiler not supported" -# endif -#endif - -#ifndef GEN_API_C_BEGIN -# if GEN_COMPILER_C -# define GEN_API_C_BEGIN -# define GEN_API_C_END -# else -# define GEN_API_C_BEGIN extern "C" { -# define GEN_API_C_END } -# endif -#endif - -#if GEN_COMPILER_C -# if __STDC_VERSION__ >= 202311L -# define gen_enum_underlying(type) : type -# else -# define gen_enum_underlying(type) -# endif -#else -# define gen_enum_underlying(type) : type -#endif - -#if GEN_COMPILER_C -# ifndef gen_nullptr -# define gen_nullptr NULL -# endif - -# ifndef GEN_REMOVE_PTR -# define GEN_REMOVE_PTR(type) gen_typeof(* ( (type) NULL) ) -# endif -#endif - -#if ! defined(GEN_PARAM_DEFAULT) && GEN_COMPILER_CPP -# define GEN_PARAM_DEFAULT = {} -#else -# define GEN_PARAM_DEFAULT -#endif - -#ifndef gen_struct_init -# if GEN_COMPILER_CPP -# define gen_struct_init(type) -# else -# define gen_struct_init(type) (type) -# endif -#endif - -#ifndef gen_struct_zero -# if GEN_COMPILER_CPP -# define gen_struct_zero(type) {} -# else -# define gen_struct_zero(type) (type) {0} -# endif -#endif - -#ifndef gen_struct_zero_init -# if GEN_COMPILER_CPP -# define gen_struct_zero_init() {} -# else -# define gen_struct_zero_init() {0} -# endif -#endif - -#if 0 -#ifndef GEN_OPTIMIZE_MAPPINGS_BEGIN -# define GEN_OPTIMIZE_MAPPINGS_BEGIN _pragma(optimize("gt", on)) -# define GEN_OPITMIZE_MAPPINGS_END _pragma(optimize("", on)) -#endif -#else -# define GEN_OPTIMIZE_MAPPINGS_BEGIN -# define GEN_OPITMIZE_MAPPINGS_END -#endif - -#ifndef get_optional -# if GEN_COMPILER_C -# define get_optional(opt) opt ? *opt : (gen_typeof(*opt)){0} -# else -# define get_optional(opt) opt -# endif -#endif - -#pragma endregion Macros - -#pragma region _Generic Macros -// ____ _ ______ _ _ ____ _ __ _ -// / ___} (_) | ____} | | (_) / __ \ | | | |(_) -// | | ___ ___ _ __ ___ _ __ _ ___ | |__ _ _ _ __ ___| |_ _ ___ _ __ | | | |_ _____ _ __ | | ___ __ _ __| | _ _ __ __ _ -// | |{__ |/ _ \ '_ \ / _ \ '__} |/ __| | __} | | | '_ \ / __} __} |/ _ \| '_ \ | | | \ \ / / _ \ '_ }| |/ _ \ / _` |/ _` || | '_ \ / _` | -// | |__j | __/ | | | __/ | | | (__ | | | |_| | | | | (__| l_| | (_) | | | | | l__| |\ V / __/ | | | (_) | (_| | (_| || | | | | (_| | -// \____/ \___}_l l_l\___}_l l_l\___| l_l \__,_l_l l_l\___}\__}_l\___/l_l l_l \____/ \_/ \___}_l l_l\___/ \__,_l\__,_l|_|_| |_|\__, | -// This implemnents macros for utilizing "The Naive Extendible _Generic Macro" explained in: __| | -// https://github.com/JacksonAllan/CC/blob/main/articles/Better_C_Generics_Part_1_The_Extendible_Generic.md {___/ -// Since gencpp is used to generate the c-library, it was choosen over the more novel implementations to keep the macros as easy to understand and unobfuscated as possible. - -#define GEN_COMMA_OPERATOR , // The comma operator is used by preprocessor macros to delimit arguments, so we have to represent it via a macro to prevent parsing incorrectly. - -// Helper macros for argument selection -#define GEN_SELECT_ARG_1( _1, ... ) _1 // <-- Of all th args passed pick _1. -#define GEN_SELECT_ARG_2( _1, _2, ... ) _2 // <-- Of all the args passed pick _2. -#define GEN_SELECT_ARG_3( _1, _2, _3, ... ) _3 // etc.. - -#define GEN_GENERIC_SEL_ENTRY_TYPE GEN_SELECT_ARG_1 // Use the arg expansion macro to select arg 1 which should have the type. -#define GEN_GENERIC_SEL_ENTRY_FUNCTION GEN_SELECT_ARG_2 // Use the arg expansion macro to select arg 2 which should have the function. -#define GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER GEN_SELECT_ARG_3 // Use the arg expansion macro to select arg 3 which should have the comma delimiter ','. - -#define GEN_RESOLVED_FUNCTION_CALL // Just used to indicate where the call "occurs" - -// ---------------------------------------------------------------------------------------------------------------------------------- -// GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( macro ) includes a _Generic slot only if the specified macro is defined (as type, function_name). -// It takes advantage of the fact that if the macro is defined, then the expanded text will contain a comma. -// Expands to ',' if it can find (type): (function) -// Where GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER is specifically looking for that , -#define GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( slot_exp ) GEN_GENERIC_SEL_ENTRY_COMMA_DELIMITER( slot_exp, GEN_GENERIC_SEL_ENTRY_TYPE( slot_exp, ): GEN_GENERIC_SEL_ENTRY_FUNCTION( slot_exp, ) GEN_COMMA_OPERATOR, , ) -// ^ Selects the comma ^ is the type ^ is the function ^ Insert a comma -// The slot won't exist if that comma is not found. - -// For the occastion where an expression didn't resolve to a selection option the "default: " will be set to: -typedef struct GENCPP_NO_RESOLVED_GENERIC_SELECTION GENCPP_NO_RESOLVED_GENERIC_SELECTION; -struct GENCPP_NO_RESOLVED_GENERIC_SELECTION { - void* _THE_VOID_SLOT_; -}; -GENCPP_NO_RESOLVED_GENERIC_SELECTION const gen_generic_selection_fail = {0}; -// Which will provide the message: error: called object type 'struct NO_RESOLVED_GENERIC_SELECTION' is not a function or function pointer -// ---------------------------------------------------------------------------------------------------------------------------------- - -// Below are generated on demand for an overlaod depdendent on a type: -// ---------------------------------------------------------------------------------------------------------------------------------- -#define GEN_FUNCTION_GENERIC_EXAMPLE( selector_arg ) _Generic( \ -(selector_arg), /* Select Via Expression*/ \ - /* Extendibility slots: */ \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__function_sig ) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_2__function_sig ) \ - default: gen_generic_selection_fail \ -) GEN_RESOLVED_FUNCTION_CALL( selector_arg ) -// ---------------------------------------------------------------------------------------------------------------------------------- - -// Then each definiton of a function has an associated define: -#// #define GENERIC_SLOT_<#>_ , - -// Then somehwere later on -// ( ) { } - -// Concrete example: - -// To add support for long: -#define GENERIC_SLOT_1_gen_example_hash long, gen_example_hash__P_long -size_t gen_example_hash__P_long( long val ) { return val * 2654435761ull; } - -// To add support for long long: -#define GENERIC_SLOT_2_gen_example_hash long long, gen_example_hash__P_long_long -size_t gen_example_hash__P_long_long( long long val ) { return val * 2654435761ull; } - -// If using an Editor with support for syntax hightlighting macros: -// GENERIC_SLOT_1_gen_example_hash and GENERIC_SLOT_2_gen_example_hash should show color highlighting indicating the slot is enabled, -// or, "defined" for usage during the compilation pass that handles the _Generic instrinsic. -#define gen_hash_example( function_arguments ) _Generic( \ -(function_arguments), /* Select Via Expression*/ \ - /* Extendibility slots: */ \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1_gen_example_hash ) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_2_gen_example_hash ) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_3_gen_example_hash ) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_4_gen_example_hash ) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_5_gen_example_hash ) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_6_gen_example_hash ) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_7_gen_example_hash ) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_8_gen_example_hash ) \ - default: gen_generic_selection_fail \ -) GEN_RESOLVED_FUNCTION_CALL( function_arguments ) - -// Additional Variations: - -// If the function takes more than one argument the following is used: -#define GEN_FUNCTION_GENERIC_EXAMPLE_VARADIC( selector_arg, ... ) _Generic( \ -(selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__function_sig ) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_2__function_sig ) \ - /* ... */ \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GENERIC_SLOT_N__function_sig ) \ - default: gen_generic_selection_fail \ -) GEN_RESOLVED_FUNCTION_CALL( selector_arg, __VA_ARG__ ) - -// If the function does not take the arugment as a parameter: -#define GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( selector_arg ) _Generic( \ -( GEN_TYPE_TO_EXP(selector_arg) ), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_1__function_sig ) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( GENERIC_SLOT_2__function_sig ) \ - /* ... */ \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GENERIC_SLOT_N__function_sig ) \ - default: gen_generic_selection_fail \ -) GEN_RESOLVED_FUNCTION_CALL() - -// Used to keep the _Generic keyword happy as bare types are not considered "expressions" -#define GEN_TYPE_TO_EXP(type) (* (type*)NULL) -// Instead of using this macro, you'll see it directly expanded by the code generation. - -// typedef void* GEN_GenericExampleType; -// GEN_FUNCTION_GENERIC_EXAMPLE_DIRECT_TYPE( GEN_GenericExampleType ); -#pragma endregion _Generic Macros - -GEN_API_C_BEGIN - -#pragma region Basic Types - -#define GEN_U8_MIN 0u -#define GEN_U8_MAX 0xffu -#define GEN_I8_MIN ( -0x7f - 1 ) -#define GEN_I8_MAX 0x7f - -#define GEN_U16_MIN 0u -#define GEN_U16_MAX 0xffffu -#define GEN_I16_MIN ( -0x7fff - 1 ) -#define GEN_I16_MAX 0x7fff - -#define GEN_U32_MIN 0u -#define GEN_U32_MAX 0xffffffffu -#define GEN_I32_MIN ( -0x7fffffff - 1 ) -#define GEN_I32_MAX 0x7fffffff - -#define GEN_U64_MIN 0ull -#define GEN_U64_MAX 0xffffffffffffffffull -#define GEN_I64_MIN ( -0x7fffffffffffffffll - 1 ) -#define GEN_I64_MAX 0x7fffffffffffffffll - -#if defined( GEN_ARCH_32_BIT ) -# define GEN_USIZE_MIN GEN_U32_MIN -# define GEN_USIZE_MAX GEN_U32_MAX -# define GEN_ISIZE_MIN GEN_S32_MIN -# define GEN_ISIZE_MAX GEN_S32_MAX -#elif defined( GEN_ARCH_64_BIT ) -# define GEN_USIZE_MIN GEN_U64_MIN -# define GEN_USIZE_MAX GEN_U64_MAX -# define GEN_ISIZE_MIN GEN_I64_MIN -# define GEN_ISIZE_MAX GEN_I64_MAX -#else -# error Unknown architecture size. This library only supports 32 gen_bit and 64 gen_bit architectures. -#endif - -#define GEN_F32_MIN 1.17549435e-38f -#define GEN_F32_MAX 3.40282347e+38f -#define GEN_F64_MIN 2.2250738585072014e-308 -#define GEN_F64_MAX 1.7976931348623157e+308 - -#if defined( GEN_COMPILER_MSVC ) -# if _MSC_VER < 1300 -typedef unsigned char gen_u8; -typedef signed char gen_s8; -typedef unsigned short gen_u16; -typedef signed short gen_s16; -typedef unsigned int gen_u32; -typedef signed int gen_s32; -# else -typedef unsigned __int8 gen_u8; -typedef signed __int8 gen_s8; -typedef unsigned __int16 gen_u16; -typedef signed __int16 gen_s16; -typedef unsigned __int32 gen_u32; -typedef signed __int32 gen_s32; -# endif -typedef unsigned __int64 gen_u64; -typedef signed __int64 gen_s64; -#else -# include - -typedef uint8_t gen_u8; -typedef int8_t gen_s8; -typedef uint16_t gen_u16; -typedef int16_t gen_s16; -typedef uint32_t gen_u32; -typedef int32_t gen_s32; -typedef uint64_t gen_u64; -typedef int64_t gen_s64; -#endif - -gen_static_assert( sizeof( gen_u8 ) == sizeof( gen_s8 ), "sizeof(gen_u8) != sizeof(gen_s8)" ); -gen_static_assert( sizeof( gen_u16 ) == sizeof( gen_s16 ), "sizeof(gen_u16) != sizeof(gen_s16)" ); -gen_static_assert( sizeof( gen_u32 ) == sizeof( gen_s32 ), "sizeof(gen_u32) != sizeof(gen_s32)" ); -gen_static_assert( sizeof( gen_u64 ) == sizeof( gen_s64 ), "sizeof(gen_u64) != sizeof(gen_s64)" ); - -gen_static_assert( sizeof( gen_u8 ) == 1, "sizeof(gen_u8) != 1" ); -gen_static_assert( sizeof( gen_u16 ) == 2, "sizeof(gen_u16) != 2" ); -gen_static_assert( sizeof( gen_u32 ) == 4, "sizeof(gen_u32) != 4" ); -gen_static_assert( sizeof( gen_u64 ) == 8, "sizeof(gen_u64) != 8" ); - -typedef size_t gen_usize; -typedef ptrdiff_t gen_ssize; - -gen_static_assert( sizeof( gen_usize ) == sizeof( gen_ssize ), "sizeof(gen_usize) != sizeof(gen_ssize)" ); - -// NOTE: (u)zpl_intptr is only here for semantic reasons really as this library will only support 32/64 gen_bit OSes. -#if defined( _WIN64 ) -typedef signed __int64 gen_sptr; -typedef unsigned __int64 gen_uptr; -#elif defined( _WIN32 ) -// NOTE; To mark types changing their size, e.g. zpl_intptr -# ifndef _W64 -# if ! defined( __midl ) && ( defined( _X86_ ) || defined( _M_IX86 ) ) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -# endif -typedef _W64 signed int gen_sptr; -typedef _W64 unsigned int gen_uptr; -#else -typedef uintptr_t gen_uptr; -typedef intptr_t gen_sptr; -#endif - -gen_static_assert( sizeof( gen_uptr ) == sizeof( gen_sptr ), "sizeof(gen_uptr) != sizeof(gen_sptr)" ); - -typedef float gen_f32; -typedef double gen_f64; - -gen_static_assert( sizeof( gen_f32 ) == 4, "sizeof(gen_f32) != 4" ); -gen_static_assert( sizeof( gen_f64 ) == 8, "sizeof(gen_f64) != 8" ); - -typedef gen_s8 gen_b8; -typedef gen_s16 gen_b16; -typedef gen_s32 gen_b32; - -typedef void* gen_mem_ptr; -typedef void const* gen_mem_ptr_const ; - -#if GEN_COMPILER_CPP -template gen_uptr gen_to_uptr( Type* ptr ) { return (gen_uptr)ptr; } -template gen_sptr gen_to_sptr( Type* ptr ) { return (gen_sptr)ptr; } - -template gen_mem_ptr gen_to_mem_ptr ( Type ptr ) { return (gen_mem_ptr) ptr; } -template gen_mem_ptr_const gen_to_mem_ptr_const( Type ptr ) { return (gen_mem_ptr_const)ptr; } -#else -#define gen_to_uptr( ptr ) ((gen_uptr)(ptr)) -#define gen_to_sptr( ptr ) ((gen_sptr)(ptr)) - -#define gen_to_mem_ptr( ptr) ((gen_mem_ptr)ptr) -#define gen_to_mem_ptr_const( ptr) ((gen_mem_ptr)ptr) -#endif - -#pragma endregion Basic Types - -#pragma region Debug - -#if GEN_BUILD_DEBUG -# if defined( GEN_COMPILER_MSVC ) -# if _MSC_VER < 1300 -// #pragma message("GEN_BUILD_DEBUG: __asm int 3") -# define GEN_DEBUG_TRAP() __asm int 3 /* Trap to debugger! */ -# else -// #pragma message("GEN_BUILD_DEBUG: __debugbreak()") -# define GEN_DEBUG_TRAP() __debugbreak() -# endif -# elif defined( GEN_COMPILER_TINYC ) -# define GEN_DEBUG_TRAP() gen_process_exit( 1 ) -# else -# define GEN_DEBUG_TRAP() __builtin_trap() -# endif -#else -// #pragma message("GEN_BUILD_DEBUG: omitted") -# define GEN_DEBUG_TRAP() -#endif - -#define GEN_ASSERT( cond ) GEN_ASSERT_MSG( cond, NULL ) - -#define GEN_ASSERT_MSG( cond, msg, ... ) \ - do \ - { \ - if ( ! ( cond ) ) \ - { \ - gen_assert_handler( #cond, __FILE__, __func__, gen_scast( gen_s64, __LINE__ ), msg, ##__VA_ARGS__ ); \ - GEN_DEBUG_TRAP(); \ - } \ - } while ( 0 ) - -#define GEN_ASSERT_NOT_NULL( ptr ) GEN_ASSERT_MSG( ( ptr ) != NULL, #ptr " must not be NULL" ) - -// NOTE: Things that shouldn't happen with a message! -#define GEN_PANIC( msg, ... ) GEN_ASSERT_MSG( 0, msg, ##__VA_ARGS__ ) - -#if GEN_BUILD_DEBUG - #define GEN_FATAL( ... ) \ - do \ - { \ - gen_local_persist gen_thread_local \ - char buf[GEN_PRINTF_MAXLEN] = { 0 }; \ - \ - gen_c_str_fmt(buf, GEN_PRINTF_MAXLEN, __VA_ARGS__); \ - GEN_PANIC(buf); \ - } \ - while (0) -#else - -# define GEN_FATAL( ... ) \ - do \ - { \ - gen_c_str_fmt_out_err( __VA_ARGS__ ); \ - GEN_DEBUG_TRAP(); \ - gen_process_exit(1); \ - } \ - while (0) -#endif - -GEN_API void gen_assert_handler( char const* condition, char const* file, char const* function, gen_s32 line, char const* msg, ... ); -GEN_API gen_s32 gen_assert_crash( char const* condition ); -GEN_API void gen_process_exit( gen_u32 code ); - -#pragma endregion Debug - -#pragma region Memory - - -#define gen_kilobytes(x) ((x) * (gen_s64)(1024)) -#define gen_megabytes(x) (gen_kilobytes(x) * (gen_s64)(1024)) -#define gen_gigabytes(x) (gen_megabytes(x) * (gen_s64)(1024)) -#define gen_terabytes(x) (gen_gigabytes(x) * (gen_s64)(1024)) - -#define GEN__ONES (gen_scast(GEN_NS gen_usize, -1) / GEN_U8_MAX) -#define GEN__HIGHS (GEN__ONES * (GEN_U8_MAX / 2 + 1)) -#define GEN__HAS_ZERO(x) (((x) - GEN__ONES) & ~(x) & GEN__HIGHS) - -#define gen_swap(a, b) \ - do \ - { \ - gen_typeof(a) temp = (a); \ - (a) = (b); \ - (b) = temp; \ - } while (0) -//! Checks if value is power of 2. -gen_b32 gen_is_power_of_two(gen_ssize x); - -//! Aligns address to specified alignment. -void* gen_align_forward(void* ptr, gen_ssize alignment); - -//! Aligns value to a specified alignment. -gen_s64 gen_align_forward_by_value(gen_s64 value, gen_ssize alignment); - -//! Moves pointer forward by bytes. -void* gen_pointer_add(void* ptr, gen_ssize bytes); - -//! Moves pointer forward by bytes. -void const* gen_pointer_add_const(void const* ptr, gen_ssize bytes); - -//! Calculates difference between two addresses. -gen_ssize gen_pointer_diff(void const* begin, void const* end); - -//! Copy non-overlapping memory from source to destination. -GEN_API void* gen_mem_copy(void* dest, void const* source, gen_ssize size); - -//! Search for a constant value within the size limit at memory location. -GEN_API void const* gen_mem_find(void const* data, gen_u8 byte_value, gen_ssize size); - -//! Copy memory from source to destination. -void* gen_mem_move(void* dest, void const* source, gen_ssize size); - -//! Set constant value at memory location with specified size. -void* gen_mem_set(void* data, gen_u8 byte_value, gen_ssize size); - -//! @param ptr Memory location to clear up. -//! @param size The size to clear up with. -void gen_zero_size(void* ptr, gen_ssize size); - -//! Clears up an item. -#define gen_zero_item(t) gen_zero_size((t), gen_size_of(*(t))) // NOTE: Pass pointer of struct - -//! Clears up an array. -#define gen_zero_array(a, count) gen_zero_size((a), gen_size_of(*(a)) * count) - -enum gen_AllocType gen_enum_underlying(gen_u8) -{ - EAllocation_ALLOC, - EAllocation_FREE, - EAllocation_FREE_ALL, - EAllocation_RESIZE, -}; - -typedef gen_u8 gen_AllocType; - -typedef void*(gen_AllocatorProc)(void* allocator_data, - gen_AllocType type, - gen_ssize size, - gen_ssize alignment, - void* old_memory, - gen_ssize old_size, - gen_u64 flags); - -struct gen_AllocatorInfo -{ - gen_AllocatorProc* Proc; - void* Data; -}; -typedef struct gen_AllocatorInfo gen_AllocatorInfo; - -enum gen_AllocFlag -{ - ALLOCATOR_FLAG_CLEAR_TO_ZERO = gen_bit(0), -}; -typedef enum gen_AllocFlag gen_AllocFlag; - -#ifndef GEN_DEFAULT_MEMORY_ALIGNMENT -#define GEN_DEFAULT_MEMORY_ALIGNMENT (2 * gen_size_of(void*)) -#endif - -#ifndef GEN_DEFAULT_ALLOCATOR_FLAGS -#define GEN_DEFAULT_ALLOCATOR_FLAGS (ALLOCATOR_FLAG_CLEAR_TO_ZERO) -#endif - -//! Allocate memory with default alignment. -void* gen_alloc(gen_AllocatorInfo a, gen_ssize size); - -//! Allocate memory with specified alignment. -void* gen_alloc_align(gen_AllocatorInfo a, gen_ssize size, gen_ssize alignment); - -//! Free allocated memory. -void gen_allocator_free(gen_AllocatorInfo a, void* ptr); - -//! Free all memory allocated by an allocator. -void gen_free_all(gen_AllocatorInfo a); - -//! Resize an allocated memory. -void* gen_resize(gen_AllocatorInfo a, void* ptr, gen_ssize old_size, gen_ssize new_size); - -//! Resize an allocated memory with specified alignment. -void* gen_resize_align(gen_AllocatorInfo a, void* ptr, gen_ssize old_size, gen_ssize new_size, gen_ssize alignment); - -//! Allocate memory for an item. -#define gen_alloc_item(allocator_, Type) (Type*)gen_alloc(allocator_, gen_size_of(Type)) - -//! Allocate memory for an array of items. -#define gen_alloc_array(allocator_, Type, count) (Type*)gen_alloc(allocator_, gen_size_of(Type) * (count)) - -/* gen_heap memory analysis tools */ -/* define GEN_HEAP_ANALYSIS to enable this feature */ -/* call zpl_heap_stats_init at the beginning of the entry point */ -/* you can call zpl_heap_stats_check near the end of the execution to validate any possible leaks */ -GEN_API void gen_heap_stats_init(void); -GEN_API gen_ssize gen_heap_stats_used_memory(void); -GEN_API gen_ssize gen_heap_stats_alloc_count(void); -GEN_API void gen_heap_stats_check(void); - -//! Allocate/Resize memory using default options. - -//! Use this if you don't need a "fancy" gen_resize allocation -void* gen_default_resize_align(gen_AllocatorInfo a, void* ptr, gen_ssize old_size, gen_ssize new_size, gen_ssize alignment); - -GEN_API void* - gen_heap_allocator_proc(void* allocator_data, gen_AllocType type, gen_ssize size, gen_ssize alignment, void* old_memory, gen_ssize old_size, gen_u64 flags); - -//! The gen_heap allocator backed by operating system's memory manager. -#define gen_heap() \ - (gen_AllocatorInfo) \ - { \ - gen_heap_allocator_proc, gen_nullptr \ - } - -struct gen_VirtualMemory -{ - void* data; - gen_ssize size; -}; -typedef struct gen_VirtualMemory gen_VirtualMemory; - -//! Initialize virtual memory from existing data. -GEN_API gen_VirtualMemory gen_vm_from_memory(void* data, gen_ssize size); - -//! Allocate virtual memory at address with size. - -//! @param addr The starting address of the region to reserve. If NULL, it lets operating system to decide where to allocate it. -//! @param size The size to serve. -GEN_API gen_VirtualMemory gen_vm_alloc(void* addr, gen_ssize size); - -//! Release the virtual memory. -GEN_API gen_b32 gen_vm_free(gen_VirtualMemory vm); - -//! Trim virtual memory. -GEN_API gen_VirtualMemory gen_vm_trim(gen_VirtualMemory vm, gen_ssize lead_size, gen_ssize size); - -//! Purge virtual memory. -GEN_API gen_b32 gen_vm_purge(gen_VirtualMemory vm); - -//! Retrieve VM's page size and alignment. -GEN_API gen_ssize gen_virtual_memory_page_size(gen_ssize* alignment_out); - -#pragma region gen_Arena - -struct gen_Arena; -typedef struct gen_Arena gen_Arena; - -gen_AllocatorInfo gen_arena_allocator_info(gen_Arena* arena); - -// Remove static keyword and rename allocator_proc -GEN_API void* gen_arena_allocator_proc( - void* allocator_data, - gen_AllocType type, - gen_ssize size, - gen_ssize alignment, - void* old_memory, - gen_ssize old_size, - gen_u64 flags -); - -// Add these declarations after the gen_Arena struct -gen_Arena gen_arena_init_from_allocator(gen_AllocatorInfo backing, gen_ssize size); -gen_Arena gen_arena_init_from_memory(void* start, gen_ssize size); - -gen_Arena gen_arena_init_sub(gen_Arena* parent, gen_ssize size); -gen_ssize gen_arena_alignment_of(gen_Arena* arena, gen_ssize alignment); -void gen_arena_check(gen_Arena* arena); -void gen_arena_free(gen_Arena* arena); -gen_ssize gen_arena_size_remaining(gen_Arena* arena, gen_ssize alignment); - -// TODO(Ed): Add gen_arena_pos, gen_arena_pop, and gen_arena_pop_to - -struct gen_Arena -{ - gen_AllocatorInfo Backing; - void* PhysicalStart; - gen_ssize TotalSize; - gen_ssize TotalUsed; - gen_ssize TempCount; -}; -typedef struct gen_Arena gen_Arena; - -inline gen_AllocatorInfo gen_arena_allocator_info(gen_Arena* arena) -{ - GEN_ASSERT(arena != gen_nullptr); - gen_AllocatorInfo info = { gen_arena_allocator_proc, arena }; - return info; -} - -inline gen_Arena gen_arena_init_from_memory(void* start, gen_ssize size) -{ - gen_Arena arena = { - { gen_nullptr, gen_nullptr }, - start, - size, - 0, - 0 - }; - return arena; -} - -inline gen_Arena gen_arena_init_from_allocator(gen_AllocatorInfo backing, gen_ssize size) -{ - gen_Arena result = { backing, gen_alloc(backing, size), size, 0, 0 }; - return result; -} - -inline gen_Arena gen_arena_init_sub(gen_Arena* parent, gen_ssize size) -{ - GEN_ASSERT(parent != gen_nullptr); - return gen_arena_init_from_allocator(parent->Backing, size); -} - -inline gen_ssize gen_arena_alignment_of(gen_Arena* arena, gen_ssize alignment) -{ - GEN_ASSERT(arena != gen_nullptr); - gen_ssize alignment_offset, result_pointer, mask; - GEN_ASSERT(gen_is_power_of_two(alignment)); - - alignment_offset = 0; - result_pointer = (gen_ssize)arena->PhysicalStart + arena->TotalUsed; - mask = alignment - 1; - - if (result_pointer & mask) - alignment_offset = alignment - (result_pointer & mask); - - return alignment_offset; -} - -inline void gen_arena_check(gen_Arena* arena) -{ - GEN_ASSERT(arena != gen_nullptr); - GEN_ASSERT(arena->TempCount == 0); -} - -inline void gen_arena_free(gen_Arena* arena) -{ - GEN_ASSERT(arena != gen_nullptr); - if (arena->Backing.Proc) - { - gen_allocator_free(arena->Backing, arena->PhysicalStart); - arena->PhysicalStart = gen_nullptr; - } -} - -inline gen_ssize gen_arena_size_remaining(gen_Arena* arena, gen_ssize alignment) -{ - GEN_ASSERT(arena != gen_nullptr); - gen_ssize result = arena->TotalSize - (arena->TotalUsed + gen_arena_alignment_of(arena, alignment)); - return result; -} - -#pragma endregion gen_Arena - - -#pragma region FixedArena - -struct gen_FixedArena_1KB -{ - char memory[gen_kilobytes(1)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_1KB gen_FixedArena_1KB; - -struct gen_FixedArena_4KB -{ - char memory[gen_kilobytes(4)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_4KB gen_FixedArena_4KB; - -struct gen_FixedArena_8KB -{ - char memory[gen_kilobytes(8)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_8KB gen_FixedArena_8KB; - -struct gen_FixedArena_16KB -{ - char memory[gen_kilobytes(16)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_16KB gen_FixedArena_16KB; - -struct gen_FixedArena_32KB -{ - char memory[gen_kilobytes(32)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_32KB gen_FixedArena_32KB; - -struct gen_FixedArena_64KB -{ - char memory[gen_kilobytes(64)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_64KB gen_FixedArena_64KB; - -struct gen_FixedArena_128KB -{ - char memory[gen_kilobytes(128)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_128KB gen_FixedArena_128KB; - -struct gen_FixedArena_256KB -{ - char memory[gen_kilobytes(256)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_256KB gen_FixedArena_256KB; - -struct gen_FixedArena_512KB -{ - char memory[gen_kilobytes(512)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_512KB gen_FixedArena_512KB; - -struct gen_FixedArena_1MB -{ - char memory[gen_megabytes(1)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_1MB gen_FixedArena_1MB; - -struct gen_FixedArena_2MB -{ - char memory[gen_megabytes(2)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_2MB gen_FixedArena_2MB; - -struct gen_FixedArena_4MB -{ - char memory[gen_megabytes(4)]; - gen_Arena arena; -}; -typedef struct gen_FixedArena_4MB gen_FixedArena_4MB; - -inline void gen_fixed_arena_init_1KB(gen_FixedArena_1KB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_kilobytes(1)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_1KB(gen_FixedArena_1KB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_1KB(gen_FixedArena_1KB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_4KB(gen_FixedArena_4KB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_kilobytes(4)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_4KB(gen_FixedArena_4KB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_4KB(gen_FixedArena_4KB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_8KB(gen_FixedArena_8KB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_kilobytes(8)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_8KB(gen_FixedArena_8KB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_8KB(gen_FixedArena_8KB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_16KB(gen_FixedArena_16KB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_kilobytes(16)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_16KB(gen_FixedArena_16KB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_16KB(gen_FixedArena_16KB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_32KB(gen_FixedArena_32KB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_kilobytes(32)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_32KB(gen_FixedArena_32KB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_32KB(gen_FixedArena_32KB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_64KB(gen_FixedArena_64KB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_kilobytes(64)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_64KB(gen_FixedArena_64KB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_64KB(gen_FixedArena_64KB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_128KB(gen_FixedArena_128KB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_kilobytes(128)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_128KB(gen_FixedArena_128KB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_128KB(gen_FixedArena_128KB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_256KB(gen_FixedArena_256KB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_kilobytes(256)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_256KB(gen_FixedArena_256KB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_256KB(gen_FixedArena_256KB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_512KB(gen_FixedArena_512KB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_kilobytes(512)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_512KB(gen_FixedArena_512KB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_512KB(gen_FixedArena_512KB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_1MB(gen_FixedArena_1MB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_megabytes(1)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_1MB(gen_FixedArena_1MB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_1MB(gen_FixedArena_1MB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_2MB(gen_FixedArena_2MB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_megabytes(2)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_2MB(gen_FixedArena_2MB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_2MB(gen_FixedArena_2MB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -inline void gen_fixed_arena_init_4MB(gen_FixedArena_4MB* result) -{ - result->arena = gen_arena_init_from_memory(&result->memory[0], gen_megabytes(4)); -} - -inline gen_ssize gen_fixed_arena_size_remaining_4MB(gen_FixedArena_4MB* fixed_arena, gen_ssize alignment) -{ - return gen_arena_size_remaining(&fixed_arena->arena, alignment); -} - -inline void gen_fixed_arena_free_4MB(gen_FixedArena_4MB* fixed_arena) -{ - gen_arena_free(&fixed_arena->arena); -} - -#define gen_fixed_arena_allocator_info(fixed_arena) ((gen_AllocatorInfo) { gen_arena_allocator_proc, &(fixed_arena)->arena }) -#define gen_fixed_arena_init(expr) \ - _Generic( \ - (expr), \ - gen_FixedArena_1KB *: gen_fixed_arena_init_1KB, \ - gen_FixedArena_4KB *: gen_fixed_arena_init_4KB, \ - gen_FixedArena_8KB *: gen_fixed_arena_init_8KB, \ - gen_FixedArena_16KB *: gen_fixed_arena_init_16KB, \ - gen_FixedArena_32KB *: gen_fixed_arena_init_32KB, \ - gen_FixedArena_64KB *: gen_fixed_arena_init_64KB, \ - gen_FixedArena_128KB *: gen_fixed_arena_init_128KB, \ - gen_FixedArena_256KB *: gen_fixed_arena_init_256KB, \ - gen_FixedArena_512KB *: gen_fixed_arena_init_512KB, \ - gen_FixedArena_1MB *: gen_fixed_arena_init_1MB, \ - gen_FixedArena_2MB *: gen_fixed_arena_init_2MB, \ - gen_FixedArena_4MB *: gen_fixed_arena_init_4MB, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(expr) - -#define gen_fixed_arena_free(expr) \ - _Generic( \ - (expr), \ - gen_FixedArena_1KB *: gen_fixed_arena_free_1KB, \ - gen_FixedArena_4KB *: gen_fixed_arena_free_4KB, \ - gen_FixedArena_8KB *: gen_fixed_arena_free_8KB, \ - gen_FixedArena_16KB *: gen_fixed_arena_free_16KB, \ - gen_FixedArena_32KB *: gen_fixed_arena_free_32KB, \ - gen_FixedArena_64KB *: gen_fixed_arena_free_64KB, \ - gen_FixedArena_128KB *: gen_fixed_arena_free_128KB, \ - gen_FixedArena_256KB *: gen_fixed_arena_free_256KB, \ - gen_FixedArena_512KB *: gen_fixed_arena_free_512KB, \ - gen_FixedArena_1MB *: gen_fixed_arena_free_1MB, \ - gen_FixedArena_2MB *: gen_fixed_arena_free_2MB, \ - gen_FixedArena_4MB *: gen_fixed_arena_free_4MB, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(expr) - -#define gen_fixed_arena_size_remaining(expr, alignment) \ - _Generic( \ - (expr), \ - gen_FixedArena_1KB *: gen_fixed_arena_size_remaining_1KB, \ - gen_FixedArena_4KB *: gen_fixed_arena_size_remaining_4KB, \ - gen_FixedArena_8KB *: gen_fixed_arena_size_remaining_8KB, \ - gen_FixedArena_16KB *: gen_fixed_arena_size_remaining_16KB, \ - gen_FixedArena_32KB *: gen_fixed_arena_size_remaining_32KB, \ - gen_FixedArena_64KB *: gen_fixed_arena_size_remaining_64KB, \ - gen_FixedArena_128KB *: gen_fixed_arena_size_remaining_128KB, \ - gen_FixedArena_256KB *: gen_fixed_arena_size_remaining_256KB, \ - gen_FixedArena_512KB *: gen_fixed_arena_size_remaining_512KB, \ - gen_FixedArena_1MB *: gen_fixed_arena_size_remaining_1MB, \ - gen_FixedArena_2MB *: gen_fixed_arena_size_remaining_2MB, \ - gen_FixedArena_4MB *: gen_fixed_arena_size_remaining_4MB, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(expr, alignment) - -#pragma endregion FixedArena - - -#pragma region gen_Pool - -struct gen_Pool; -typedef struct gen_Pool gen_Pool; - -GEN_API void* - gen_pool_allocator_proc(void* allocator_data, gen_AllocType type, gen_ssize size, gen_ssize alignment, void* old_memory, gen_ssize old_size, gen_u64 flags); - -gen_Pool gen_pool_init(gen_AllocatorInfo backing, gen_ssize num_blocks, gen_ssize block_size); -gen_Pool gen_pool_init_align(gen_AllocatorInfo backing, gen_ssize num_blocks, gen_ssize block_size, gen_ssize block_align); -gen_AllocatorInfo gen_pool_allocator_info(gen_Pool* pool); -GEN_API void gen_pool_clear(gen_Pool* pool); -void gen_pool_free(gen_Pool* pool); - -struct gen_Pool -{ - gen_AllocatorInfo Backing; - void* PhysicalStart; - void* FreeList; - gen_ssize BlockSize; - gen_ssize BlockAlign; - gen_ssize TotalSize; - gen_ssize NumBlocks; -}; -typedef struct gen_Pool gen_Pool; - -inline gen_AllocatorInfo gen_pool_allocator_info(gen_Pool* pool) -{ - gen_AllocatorInfo info = { gen_pool_allocator_proc, pool }; - return info; -} - -inline gen_Pool gen_pool_init(gen_AllocatorInfo backing, gen_ssize num_blocks, gen_ssize block_size) -{ - return gen_pool_init_align(backing, num_blocks, block_size, GEN_DEFAULT_MEMORY_ALIGNMENT); -} - -inline void gen_pool_free(gen_Pool* pool) -{ - if (pool->Backing.Proc) - { - gen_allocator_free(pool->Backing, pool->PhysicalStart); - } -} - -#pragma endregion gen_Pool - -inline gen_b32 gen_is_power_of_two(gen_ssize x) -{ - if (x <= 0) - return false; - return ! (x & (x - 1)); -} - -inline gen_mem_ptr gen_align_forward(void* ptr, gen_ssize alignment) -{ - GEN_ASSERT(gen_is_power_of_two(alignment)); - gen_uptr p = gen_to_uptr(ptr); - gen_uptr forward = (p + (alignment - 1)) & ~(alignment - 1); - - return gen_to_mem_ptr(forward); -} - -inline gen_s64 align_forward_s64(gen_s64 value, gen_ssize alignment) -{ - return value + (alignment - value % alignment) % alignment; -} - -inline void* gen_pointer_add(void* ptr, gen_ssize bytes) -{ - return gen_rcast(void*, gen_rcast(gen_u8*, ptr) + bytes); -} - -inline void const* gen_pointer_add_const(void const* ptr, gen_ssize bytes) -{ - return gen_rcast(void const*, gen_rcast(gen_u8 const*, ptr) + bytes); -} - -inline gen_sptr gen_pointer_diff(gen_mem_ptr_const begin, gen_mem_ptr_const end) -{ - return gen_scast(gen_ssize, gen_rcast(gen_u8 const*, end) - gen_rcast(gen_u8 const*, begin)); -} - -inline void* gen_mem_move(void* destination, void const* source, gen_ssize byte_count) -{ - if (destination == NULL) - { - return NULL; - } - - gen_u8* dest_ptr = gen_rcast(gen_u8*, destination); - gen_u8 const* src_ptr = gen_rcast(gen_u8 const*, source); - - if (dest_ptr == src_ptr) - return dest_ptr; - - if (src_ptr + byte_count <= dest_ptr || dest_ptr + byte_count <= src_ptr) // NOTE: Non-overlapping - return gen_mem_copy(dest_ptr, src_ptr, byte_count); - - if (dest_ptr < src_ptr) - { - if (gen_to_uptr(src_ptr) % gen_size_of(gen_ssize) == gen_to_uptr(dest_ptr) % gen_size_of(gen_ssize)) - { - while (gen_pcast(gen_uptr, dest_ptr) % gen_size_of(gen_ssize)) - { - if (! byte_count--) - return destination; - - *dest_ptr++ = *src_ptr++; - } - while (byte_count >= gen_size_of(gen_ssize)) - { - *gen_rcast(gen_ssize*, dest_ptr) = *gen_rcast(gen_ssize const*, src_ptr); - byte_count -= gen_size_of(gen_ssize); - dest_ptr += gen_size_of(gen_ssize); - src_ptr += gen_size_of(gen_ssize); - } - } - for (; byte_count; byte_count--) - *dest_ptr++ = *src_ptr++; - } - else - { - if ((gen_to_uptr(src_ptr) % gen_size_of(gen_ssize)) == (gen_to_uptr(dest_ptr) % gen_size_of(gen_ssize))) - { - while (gen_to_uptr(dest_ptr + byte_count) % gen_size_of(gen_ssize)) - { - if (! byte_count--) - return destination; - - dest_ptr[byte_count] = src_ptr[byte_count]; - } - while (byte_count >= gen_size_of(gen_ssize)) - { - byte_count -= gen_size_of(gen_ssize); - *gen_rcast(gen_ssize*, dest_ptr + byte_count) = *gen_rcast(gen_ssize const*, src_ptr + byte_count); - } - } - while (byte_count) - byte_count--, dest_ptr[byte_count] = src_ptr[byte_count]; - } - - return destination; -} - -inline void* gen_mem_set(void* destination, gen_u8 fill_byte, gen_ssize byte_count) -{ - if (destination == NULL) - { - return NULL; - } - - gen_ssize align_offset; - gen_u8* dest_ptr = gen_rcast(gen_u8*, destination); - gen_u32 fill_word = ((gen_u32)-1) / 255 * fill_byte; - - if (byte_count == 0) - return destination; - - dest_ptr[0] = dest_ptr[byte_count - 1] = fill_byte; - if (byte_count < 3) - return destination; - - dest_ptr[1] = dest_ptr[byte_count - 2] = fill_byte; - dest_ptr[2] = dest_ptr[byte_count - 3] = fill_byte; - if (byte_count < 7) - return destination; - - dest_ptr[3] = dest_ptr[byte_count - 4] = fill_byte; - if (byte_count < 9) - return destination; - - align_offset = -gen_to_sptr(dest_ptr) & 3; - dest_ptr += align_offset; - byte_count -= align_offset; - byte_count &= -4; - - *gen_rcast(gen_u32*, (dest_ptr + 0)) = fill_word; - *gen_rcast(gen_u32*, (dest_ptr + byte_count - 4)) = fill_word; - if (byte_count < 9) - return destination; - - *gen_rcast(gen_u32*, dest_ptr + 4) = fill_word; - *gen_rcast(gen_u32*, dest_ptr + 8) = fill_word; - *gen_rcast(gen_u32*, dest_ptr + byte_count - 12) = fill_word; - *gen_rcast(gen_u32*, dest_ptr + byte_count - 8) = fill_word; - if (byte_count < 25) - return destination; - - *gen_rcast(gen_u32*, dest_ptr + 12) = fill_word; - *gen_rcast(gen_u32*, dest_ptr + 16) = fill_word; - *gen_rcast(gen_u32*, dest_ptr + 20) = fill_word; - *gen_rcast(gen_u32*, dest_ptr + 24) = fill_word; - *gen_rcast(gen_u32*, dest_ptr + byte_count - 28) = fill_word; - *gen_rcast(gen_u32*, dest_ptr + byte_count - 24) = fill_word; - *gen_rcast(gen_u32*, dest_ptr + byte_count - 20) = fill_word; - *gen_rcast(gen_u32*, dest_ptr + byte_count - 16) = fill_word; - - align_offset = 24 + gen_to_uptr(dest_ptr) & 4; - dest_ptr += align_offset; - byte_count -= align_offset; - - { - gen_u64 fill_doubleword = (gen_scast(gen_u64, fill_word) << 32) | fill_word; - while (byte_count > 31) - { - *gen_rcast(gen_u64*, dest_ptr + 0) = fill_doubleword; - *gen_rcast(gen_u64*, dest_ptr + 8) = fill_doubleword; - *gen_rcast(gen_u64*, dest_ptr + 16) = fill_doubleword; - *gen_rcast(gen_u64*, dest_ptr + 24) = fill_doubleword; - - byte_count -= 32; - dest_ptr += 32; - } - } - - return destination; -} - -inline void* gen_alloc_align(gen_AllocatorInfo a, gen_ssize size, gen_ssize alignment) -{ - return a.Proc(a.Data, EAllocation_ALLOC, size, alignment, gen_nullptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS); -} - -inline void* gen_alloc(gen_AllocatorInfo a, gen_ssize size) -{ - return gen_alloc_align(a, size, GEN_DEFAULT_MEMORY_ALIGNMENT); -} - -inline void gen_allocator_free(gen_AllocatorInfo a, void* ptr) -{ - if (ptr != gen_nullptr) - a.Proc(a.Data, EAllocation_FREE, 0, 0, ptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS); -} - -inline void gen_free_all(gen_AllocatorInfo a) -{ - a.Proc(a.Data, EAllocation_FREE_ALL, 0, 0, gen_nullptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS); -} - -inline void* gen_resize(gen_AllocatorInfo a, void* ptr, gen_ssize old_size, gen_ssize new_size) -{ - return gen_resize_align(a, ptr, old_size, new_size, GEN_DEFAULT_MEMORY_ALIGNMENT); -} - -inline void* gen_resize_align(gen_AllocatorInfo a, void* ptr, gen_ssize old_size, gen_ssize new_size, gen_ssize alignment) -{ - return a.Proc(a.Data, EAllocation_RESIZE, new_size, alignment, ptr, old_size, GEN_DEFAULT_ALLOCATOR_FLAGS); -} - -inline void* gen_default_resize_align(gen_AllocatorInfo a, void* old_memory, gen_ssize old_size, gen_ssize new_size, gen_ssize alignment) -{ - if (! old_memory) - return gen_alloc_align(a, new_size, alignment); - - if (new_size == 0) - { - gen_allocator_free(a, old_memory); - return gen_nullptr; - } - - if (new_size < old_size) - new_size = old_size; - - if (old_size == new_size) - { - return old_memory; - } - else - { - void* new_memory = gen_alloc_align(a, new_size, alignment); - if (! new_memory) - return gen_nullptr; - - gen_mem_move(new_memory, old_memory, gen_min(new_size, old_size)); - gen_allocator_free(a, old_memory); - return new_memory; - } -} - -inline void gen_zero_size(void* ptr, gen_ssize size) -{ - gen_mem_set(ptr, 0, size); -} - -#pragma endregion Memory - -#pragma region Printing - - -typedef struct gen_FileInfo gen_FileInfo; - -#ifndef GEN_PRINTF_MAXLEN -#define GEN_PRINTF_MAXLEN gen_kilobytes(128) -#endif -typedef char gen_PrintF_Buffer[GEN_PRINTF_MAXLEN]; - -// NOTE: A locally persisting buffer is used internally -GEN_API char* gen_c_str_fmt_buf(char const* fmt, ...); -GEN_API char* gen_c_str_fmt_buf_va(char const* fmt, va_list va); -GEN_API gen_ssize gen_c_str_fmt(char* str, gen_ssize n, char const* fmt, ...); -GEN_API gen_ssize gen_c_str_fmt_va(char* str, gen_ssize n, char const* fmt, va_list va); -GEN_API gen_ssize gen_c_str_fmt_out_va(char const* fmt, va_list va); -GEN_API gen_ssize gen_c_str_fmt_out_err(char const* fmt, ...); -GEN_API gen_ssize gen_c_str_fmt_out_err_va(char const* fmt, va_list va); -GEN_API gen_ssize gen_c_str_fmt_file(gen_FileInfo* f, char const* fmt, ...); -GEN_API gen_ssize gen_c_str_fmt_file_va(gen_FileInfo* f, char const* fmt, va_list va); - -#define gen_Msg_Invalid_Value "INVALID VALUE PROVIDED" - -#pragma endregion Printing - -#pragma region String Ops - -const char* gen_char_first_occurence( const char* str, char c ); - -gen_b32 gen_char_is_alpha( char c ); -gen_b32 gen_char_is_alphanumeric( char c ); -gen_b32 gen_char_is_digit( char c ); -gen_b32 gen_char_is_hex_digit( char c ); -gen_b32 gen_char_is_space( char c ); -char gen_char_to_lower( char c ); -char gen_char_to_upper( char c ); - -gen_s32 gen_digit_to_int( char c ); -gen_s32 hex_digit_to_int( char c ); - -gen_s32 gen_c_str_compare( const char* s1, const char* s2 ); -gen_s32 gen_c_str_compare_len( const char* s1, const char* s2, gen_ssize len ); -char* gen_c_str_copy( char* dest, const char* source, gen_ssize len ); -gen_ssize gen_c_str_copy_nulpad( char* dest, const char* source, gen_ssize len ); -gen_ssize gen_c_str_len( const char* str ); -gen_ssize gen_c_str_len_capped( const char* str, gen_ssize max_len ); -char* gen_c_str_reverse( char* str ); // NOTE: ASCII only -char const* gen_c_str_skip( char const* str, char c ); -char const* gen_c_str_skip_any( char const* str, char const* gen_char_list ); -char const* gen_c_str_trim( char const* str, gen_b32 catch_newline ); - -// NOTE: ASCII only -void gen_c_str_to_lower( char* str ); -void gen_c_str_to_upper( char* str ); - -GEN_API gen_s64 gen_c_str_to_i64( const char* str, char** gen_end_ptr, gen_s32 base ); -GEN_API void gen_i64_to_str( gen_s64 value, char* string, gen_s32 base ); -GEN_API void gen_u64_to_str( gen_u64 value, char* string, gen_s32 base ); -GEN_API gen_f64 gen_c_str_to_f64( const char* str, char** gen_end_ptr ); - -inline -const char* gen_char_first_occurence( const char* s, char c ) -{ - char ch = c; - for ( ; *s != ch; s++ ) - { - if ( *s == '\0' ) - return NULL; - } - return s; -} - -inline -gen_b32 gen_char_is_alpha( char c ) -{ - if ( ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' ) ) - return true; - return false; -} - -inline -gen_b32 gen_char_is_alphanumeric( char c ) -{ - return gen_char_is_alpha( c ) || gen_char_is_digit( c ); -} - -inline -gen_b32 gen_char_is_digit( char c ) -{ - if ( c >= '0' && c <= '9' ) - return true; - return false; -} - -inline -gen_b32 gen_char_is_hex_digit( char c ) -{ - if ( gen_char_is_digit( c ) || ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) ) - return true; - return false; -} - -inline -gen_b32 gen_char_is_space( char c ) -{ - if ( c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v' ) - return true; - return false; -} - -inline -char gen_char_to_lower( char c ) -{ - if ( c >= 'A' && c <= 'Z' ) - return 'a' + ( c - 'A' ); - return c; -} - -inline char gen_char_to_upper( char c ) -{ - if ( c >= 'a' && c <= 'z' ) - return 'A' + ( c - 'a' ); - return c; -} - -inline -gen_s32 gen_digit_to_int( char c ) -{ - return gen_char_is_digit( c ) ? c - '0' : c - 'W'; -} - -inline -gen_s32 hex_digit_to_int( char c ) -{ - if ( gen_char_is_digit( c ) ) - return gen_digit_to_int( c ); - else if ( gen_is_between( c, 'a', 'f' ) ) - return c - 'a' + 10; - else if ( gen_is_between( c, 'A', 'F' ) ) - return c - 'A' + 10; - return -1; -} - -inline -gen_s32 gen_c_str_compare( const char* s1, const char* s2 ) -{ - while ( *s1 && ( *s1 == *s2 ) ) - { - s1++, s2++; - } - return *( gen_u8* )s1 - *( gen_u8* )s2; -} - -inline -gen_s32 gen_c_str_compare_len( const char* s1, const char* s2, gen_ssize len ) -{ - for ( ; len > 0; s1++, s2++, len-- ) - { - if ( *s1 != *s2 ) - return ( ( s1 < s2 ) ? -1 : +1 ); - else if ( *s1 == '\0' ) - return 0; - } - return 0; -} - -inline -char* gen_c_str_copy( char* dest, const char* source, gen_ssize len ) -{ - GEN_ASSERT_NOT_NULL( dest ); - if ( source ) - { - char* str = dest; - while ( len > 0 && *source ) - { - *str++ = *source++; - len--; - } - while ( len > 0 ) - { - *str++ = '\0'; - len--; - } - } - return dest; -} - -inline -gen_ssize gen_c_str_copy_nulpad( char* dest, const char* source, gen_ssize len ) -{ - gen_ssize result = 0; - GEN_ASSERT_NOT_NULL( dest ); - if ( source ) - { - const char* source_start = source; - char* str = dest; - while ( len > 0 && *source ) - { - *str++ = *source++; - len--; - } - while ( len > 0 ) - { - *str++ = '\0'; - len--; - } - - result = source - source_start; - } - return result; -} - -inline -gen_ssize gen_c_str_len( const char* str ) -{ - if ( str == NULL ) - { - return 0; - } - const char* p = str; - while ( *str ) - str++; - return str - p; -} - -inline -gen_ssize gen_c_str_len_capped( const char* str, gen_ssize max_len ) -{ - const char* end = gen_rcast(const char*, gen_mem_find( str, 0, max_len )); - if ( end ) - return end - str; - return max_len; -} - -inline -char* gen_c_str_reverse( char* str ) -{ - gen_ssize len = gen_c_str_len( str ); - char* a = str + 0; - char* b = str + len - 1; - len /= 2; - while ( len-- ) - { - gen_swap( *a, *b ); - a++, b--; - } - return str; -} - -inline -char const* gen_c_str_skip( char const* str, char c ) -{ - while ( *str && *str != c ) - { - ++str; - } - return str; -} - -inline -char const* gen_c_str_skip_any( char const* str, char const* gen_char_list ) -{ - char const* closest_ptr = gen_rcast( char const*, gen_pointer_add_const( gen_rcast(gen_mem_ptr_const, str), gen_c_str_len( str ) )); - gen_ssize gen_char_list_count = gen_c_str_len( gen_char_list ); - for ( gen_ssize i = 0; i < gen_char_list_count; i++ ) - { - char const* p = gen_c_str_skip( str, gen_char_list[ i ] ); - closest_ptr = gen_min( closest_ptr, p ); - } - return closest_ptr; -} - -inline -char const* gen_c_str_trim( char const* str, gen_b32 catch_newline ) -{ - while ( *str && gen_char_is_space( *str ) && ( ! catch_newline || ( catch_newline && *str != '\n' ) ) ) - { - ++str; - } - return str; -} - -inline -void gen_c_str_to_lower( char* str ) -{ - if ( ! str ) - return; - while ( *str ) - { - *str = gen_char_to_lower( *str ); - str++; - } -} - -inline -void gen_c_str_to_upper( char* str ) -{ - if ( ! str ) - return; - while ( *str ) - { - *str = gen_char_to_upper( *str ); - str++; - } -} - -#pragma endregion String Ops - -#pragma region Containers - -typedef struct gen_ArrayHeader gen_ArrayHeader; - -struct gen_ArrayHeader -{ - gen_AllocatorInfo Allocator; - gen_usize Capacity; - gen_usize Num; -}; - -#define gen_Array(Type) gen_Array_##Type -#define gen_array_grow_formula(value) (2 * value + 8) -#define gen_array_get_header(self) ((gen_ArrayHeader*)(self) - 1) -#define gen_array_begin(array) (array) -#define gen_array_end(array) (array + gen_array_get_header(array)->Num) -#define gen_array_next(array, entry) (entry + 1) - -#define gen_array_init(selector_arg, ...) \ - _Generic( \ - (*(selector_arg*)NULL), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_init) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_init) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_init) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_init) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_init) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_init) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_init) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_init) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_init) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_init) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(__VA_ARGS__) - -#define gen_array_init_reserve(selector_arg, ...) \ - _Generic( \ - (*(selector_arg*)NULL), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_init_reserve) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( \ - GEN_GENERIC_SLOT_2__array_init_reserve \ - ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_init_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_init_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_init_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_init_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_init_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_init_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_init_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_init_reserve) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(__VA_ARGS__) - -#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__) - -#define gen_array_append_at(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_append_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_append_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_append_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_append_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_append_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_append_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_append_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_append_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_append_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_append_at) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(&selector_arg, __VA_ARGS__) - -#define gen_array_append_items(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_append_items) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( \ - GEN_GENERIC_SLOT_2__array_append_items \ - ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_append_items) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_append_items) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_append_items) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_append_items) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_append_items) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_append_items) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_append_items) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_append_items) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(&selector_arg, __VA_ARGS__) - -#define gen_array_append_items_at(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_append_items_at) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( \ - GEN_GENERIC_SLOT_2__array_append_items_at \ - ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_append_items_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_append_items_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_append_items_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_append_items_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_append_items_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_append_items_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_append_items_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_append_items_at) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(&selector_arg, __VA_ARGS__) - -#define gen_array_back(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_back) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_back) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_back) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_back) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_back) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_back) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_back) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_back) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_back) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_back) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg) - -#define gen_array_clear(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_clear) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_clear) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_clear) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_clear) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_clear) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_clear) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_clear) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_clear) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_clear) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_clear) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg) - -#define gen_array_fill(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_fill) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_fill) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_fill) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_fill) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_fill) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_fill) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_fill) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_fill) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_fill) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_fill) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg, __VA_ARGS__) - -#define gen_array_free(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_free) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_free) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_free) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_free) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_free) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_free) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_free) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_free) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_free) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_free) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(&selector_arg) - -#define gen_array_grow(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_grow) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_grow) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_grow) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_grow) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_grow) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_grow) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_grow) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_grow) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_grow) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_grow) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg, __VA_ARGS__) - -#define gen_array_num(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_num) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_num) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_num) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_num) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_num) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_num) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_num) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_num) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_num) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_num) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg) - -#define gen_array_pop(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_pop) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_pop) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_pop) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_pop) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_pop) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_pop) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_pop) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_pop) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_pop) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_pop) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg) - -#define gen_array_remove_at(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_remove_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_remove_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_remove_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_remove_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_remove_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_remove_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_remove_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_remove_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_remove_at) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_remove_at) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg, __VA_ARGS__) - -#define gen_array_reserve(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_reserve) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_reserve) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(&selector_arg, __VA_ARGS__) - -#define gen_array_resize(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_resize) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__array_resize) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_resize) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_resize) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_resize) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_resize) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_resize) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_resize) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_resize) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_resize) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(&selector_arg, __VA_ARGS__) - -#define gen_array_set_capacity(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__array_set_capacity) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT( \ - GEN_GENERIC_SLOT_2__array_set_capacity \ - ) GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_3__array_set_capacity) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_4__array_set_capacity) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_5__array_set_capacity) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_6__array_set_capacity) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_7__array_set_capacity) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_8__array_set_capacity) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_9__array_set_capacity) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_10__array_set_capacity) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg, __VA_ARGS__) - -typedef struct gen_HT_FindResult_Def gen_HT_FindResult; - -struct gen_HT_FindResult_Def -{ - gen_ssize HashIndex; - gen_ssize PrevIndex; - gen_ssize EntryIndex; -}; - -#define gen_HashTable(_type) struct gen_HashTable_##_type -#define gen_HashTable_CriticalLoadScale 0.7f - -#define gen_hashtable_init(selector_arg, ...) \ - _Generic( \ - (*(selector_arg*)NULL), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_init) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_init) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(__VA_ARGS__) - -#define gen_hashtable_init_reserve(selector_arg, ...) \ - _Generic( \ - (*(selector_arg*)NULL), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_init_reserve) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_init_reserve) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(__VA_ARGS__) - -#define gen_hashtable_clear(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_clear) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_clear) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg) - -#define gen_hashtable_destroy(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_destroy) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_destroy) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(&selector_arg) - -#define gen_hashtable_get(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_get) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_get) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg, __VA_ARGS__) - -#define gen_hashtable_grow(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_grow) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_grow) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg) - -#define gen_hashtable_rehash(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_rehash) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_rehash) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg, __VA_ARGS__) - -#define gen_hashtable_rehash_fast(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_rehash_fast) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_rehash_fast) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg) - -#define gen_hashtable_remove(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_remove) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_remove) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg, __VA_ARGS__) - -#define gen_hashtable_remove_entry(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_remove_entry) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_remove_entry) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg, __VA_ARGS__) - -#define gen_hashtable_set(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_set) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_set) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(&selector_arg, __VA_ARGS__) - -#define gen_hashtable_slot(selector_arg, ...) \ - _Generic( \ - (selector_arg), \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_1__hashtable_slot) \ - GEN_IF_MACRO_DEFINED_INCLUDE_THIS_SLOT(GEN_GENERIC_SLOT_2__hashtable_slot) default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(selector_arg, __VA_ARGS__) - -#pragma region gen_Array_gen_ssize - -#define GEN_GENERIC_SLOT_1__array_init gen_ssize, gen_Array_gen_ssize_init -#define GEN_GENERIC_SLOT_1__array_init_reserve gen_ssize, gen_Array_gen_ssize_init_reserve -#define GEN_GENERIC_SLOT_1__array_append gen_Array_gen_ssize, gen_Array_gen_ssize_append -#define GEN_GENERIC_SLOT_1__array_append_items gen_Array_gen_ssize, gen_Array_gen_ssize_append_items -#define GEN_GENERIC_SLOT_1__array_append_at gen_Array_gen_ssize, gen_Array_gen_ssize_append_at -#define GEN_GENERIC_SLOT_1__array_append_items_at gen_Array_gen_ssize, gen_Array_gen_ssize_append_items_at -#define GEN_GENERIC_SLOT_1__array_back gen_Array_gen_ssize, gen_Array_gen_ssize_back -#define GEN_GENERIC_SLOT_1__array_clear gen_Array_gen_ssize, gen_Array_gen_ssize_clear -#define GEN_GENERIC_SLOT_1__array_fill gen_Array_gen_ssize, gen_Array_gen_ssize_fill -#define GEN_GENERIC_SLOT_1__array_free gen_Array_gen_ssize, gen_Array_gen_ssize_free -#define GEN_GENERIC_SLOT_1__array_grow gen_Array_gen_ssize*, gen_Array_gen_ssize_grow -#define GEN_GENERIC_SLOT_1__array_num gen_Array_gen_ssize, gen_Array_gen_ssize_num -#define GEN_GENERIC_SLOT_1__array_pop gen_Array_gen_ssize, gen_Array_gen_ssize_pop -#define GEN_GENERIC_SLOT_1__array_remove_at gen_Array_gen_ssize, gen_Array_gen_ssize_remove_at -#define GEN_GENERIC_SLOT_1__array_reserve gen_Array_gen_ssize, gen_Array_gen_ssize_reserve -#define GEN_GENERIC_SLOT_1__array_resize gen_Array_gen_ssize, gen_Array_gen_ssize_resize -#define GEN_GENERIC_SLOT_1__array_set_capacity gen_Array_gen_ssize*, gen_Array_gen_ssize_set_capacity - -typedef gen_ssize* gen_Array_gen_ssize; -gen_Array_gen_ssize gen_Array_gen_ssize_init(gen_AllocatorInfo allocator); -gen_Array_gen_ssize gen_Array_gen_ssize_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity); -bool gen_Array_gen_ssize_append_array(gen_Array_gen_ssize* self, gen_Array_gen_ssize other); -bool gen_Array_gen_ssize_append(gen_Array_gen_ssize* self, gen_ssize value); -bool gen_Array_gen_ssize_append_items(gen_Array_gen_ssize* self, gen_ssize* items, gen_usize item_num); -bool gen_Array_gen_ssize_append_at(gen_Array_gen_ssize* self, gen_ssize item, gen_usize idx); -bool gen_Array_gen_ssize_append_items_at(gen_Array_gen_ssize* self, gen_ssize* items, gen_usize item_num, gen_usize idx); -gen_ssize* gen_Array_gen_ssize_back(gen_Array_gen_ssize self); -void gen_Array_gen_ssize_clear(gen_Array_gen_ssize self); -bool gen_Array_gen_ssize_fill(gen_Array_gen_ssize self, gen_usize begin, gen_usize end, gen_ssize value); -void gen_Array_gen_ssize_free(gen_Array_gen_ssize* self); -bool gen_Array_gen_ssize_grow(gen_Array_gen_ssize* self, gen_usize min_capacity); -gen_usize gen_Array_gen_ssize_num(gen_Array_gen_ssize self); -gen_ssize gen_Array_gen_ssize_pop(gen_Array_gen_ssize self); -void gen_Array_gen_ssize_remove_at(gen_Array_gen_ssize self, gen_usize idx); -bool gen_Array_gen_ssize_reserve(gen_Array_gen_ssize* self, gen_usize new_capacity); -bool gen_Array_gen_ssize_resize(gen_Array_gen_ssize* self, gen_usize num); -bool gen_Array_gen_ssize_set_capacity(gen_Array_gen_ssize* self, gen_usize new_capacity); - -gen_forceinline gen_Array_gen_ssize gen_Array_gen_ssize_init(gen_AllocatorInfo allocator) -{ - size_t initial_size = gen_array_grow_formula(0); - return gen_array_init_reserve(gen_ssize, allocator, initial_size); -} - -inline gen_Array_gen_ssize gen_Array_gen_ssize_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity) -{ - GEN_ASSERT(capacity > 0); - gen_ArrayHeader* header = gen_rcast(gen_ArrayHeader*, gen_alloc(allocator, sizeof(gen_ArrayHeader) + sizeof(gen_ssize) * capacity)); - if (header == gen_nullptr) - return gen_nullptr; - header->Allocator = allocator; - header->Capacity = capacity; - header->Num = 0; - return gen_rcast(gen_ssize*, header + 1); -} - -gen_forceinline bool gen_Array_gen_ssize_append_array(gen_Array_gen_ssize* self, gen_Array_gen_ssize other) -{ - return gen_array_append_items(*self, (gen_Array_gen_ssize)other, gen_Array_gen_ssize_num(other)); -} - -inline bool gen_Array_gen_ssize_append(gen_Array_gen_ssize* self, gen_ssize value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num == header->Capacity) - { - if (! gen_array_grow(self, header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - (*self)[header->Num] = value; - header->Num++; - return true; -} - -inline bool gen_Array_gen_ssize_append_items(gen_Array_gen_ssize* self, gen_ssize* items, gen_usize item_num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(items != gen_nullptr); - GEN_ASSERT(item_num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num + item_num > header->Capacity) - { - if (! gen_array_grow(self, header->Capacity + item_num)) - return false; - header = gen_array_get_header(*self); - } - gen_mem_copy((*self) + header->Num, items, sizeof(gen_ssize) * item_num); - header->Num += item_num; - return true; -} - -inline bool gen_Array_gen_ssize_append_at(gen_Array_gen_ssize* self, gen_ssize item, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - idx = header->Num - 1; - if (idx < 0) - idx = 0; - if (header->Capacity < header->Num + 1) - { - if (! gen_array_grow(self, header->Capacity + 1)) - return false; - header = gen_array_get_header(*self); - } - gen_Array_gen_ssize target = (*self) + idx; - gen_mem_move(target + 1, target, (header->Num - idx) * sizeof(gen_ssize)); - header->Num++; - return true; -} - -inline bool gen_Array_gen_ssize_append_items_at(gen_Array_gen_ssize* self, gen_ssize* items, gen_usize item_num, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - { - return gen_array_append_items(*self, items, item_num); - } - if (item_num > header->Capacity) - { - if (! gen_array_grow(self, item_num + header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - gen_ssize* target = (*self) + idx + item_num; - gen_ssize* src = (*self) + idx; - gen_mem_move(target, src, (header->Num - idx) * sizeof(gen_ssize)); - gen_mem_copy(src, items, item_num * sizeof(gen_ssize)); - header->Num += item_num; - return true; -} - -inline gen_ssize* gen_Array_gen_ssize_back(gen_Array_gen_ssize self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - if (header->Num == 0) - return 0; - return self + header->Num - 1; -} - -inline void gen_Array_gen_ssize_clear(gen_Array_gen_ssize self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - header->Num = 0; -} - -inline bool gen_Array_gen_ssize_fill(gen_Array_gen_ssize self, gen_usize begin, gen_usize end, gen_ssize value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(begin <= end); - gen_ArrayHeader* header = gen_array_get_header(self); - if (begin < 0 || end > header->Num) - return false; - for (gen_ssize idx = (gen_ssize)begin; idx < (gen_ssize)end; idx++) - self[idx] = value; - return true; -} - -inline void gen_Array_gen_ssize_free(gen_Array_gen_ssize* self) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_allocator_free(header->Allocator, header); - self = 0; -} - -inline bool gen_Array_gen_ssize_grow(gen_Array_gen_ssize* self, gen_usize min_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(min_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_usize new_capacity = gen_array_grow_formula(header->Capacity); - if (new_capacity < min_capacity) - new_capacity = min_capacity; - return gen_array_set_capacity(self, new_capacity); -} - -gen_forceinline gen_usize gen_Array_gen_ssize_num(gen_Array_gen_ssize self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_array_get_header(self)->Num; -} - -inline gen_ssize gen_Array_gen_ssize_pop(gen_Array_gen_ssize self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(header->Num > 0); - gen_ssize result = self[header->Num - 1]; - header->Num--; - return result; -} - -gen_forceinline void gen_Array_gen_ssize_remove_at(gen_Array_gen_ssize self, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(idx < header->Num); - gen_mem_move(self + idx, self + idx + 1, sizeof(gen_ssize) * (header->Num - idx - 1)); - header->Num--; -} - -inline bool gen_Array_gen_ssize_reserve(gen_Array_gen_ssize* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < new_capacity) - return gen_array_set_capacity(self, new_capacity); - return true; -} - -inline bool gen_Array_gen_ssize_resize(gen_Array_gen_ssize* self, gen_usize num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < num) - { - if (! gen_array_grow(self, num)) - return false; - header = gen_array_get_header(*self); - } - header->Num = num; - return true; -} - -inline bool gen_Array_gen_ssize_set_capacity(gen_Array_gen_ssize* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (new_capacity == header->Capacity) - return true; - if (new_capacity < header->Num) - { - header->Num = new_capacity; - return true; - } - gen_usize size = sizeof(gen_ArrayHeader) + sizeof(gen_ssize) * new_capacity; - gen_ArrayHeader* new_header = gen_cast(gen_ArrayHeader*, gen_alloc(header->Allocator, size)); - if (new_header == 0) - return false; - gen_mem_move(new_header, header, sizeof(gen_ArrayHeader) + sizeof(gen_ssize) * header->Num); - new_header->Capacity = new_capacity; - gen_allocator_free(header->Allocator, &header); - *self = gen_cast(gen_ssize*, new_header + 1); - return true; -} - -#pragma endregion gen_Array_gen_ssize - -#pragma region gen_Array_gen_u8 - -#define GEN_GENERIC_SLOT_4__array_init gen_u8, gen_Array_gen_u8_init -#define GEN_GENERIC_SLOT_4__array_init_reserve gen_u8, gen_Array_gen_u8_init_reserve -#define GEN_GENERIC_SLOT_4__array_append gen_Array_gen_u8, gen_Array_gen_u8_append -#define GEN_GENERIC_SLOT_4__array_append_items gen_Array_gen_u8, gen_Array_gen_u8_append_items -#define GEN_GENERIC_SLOT_4__array_append_at gen_Array_gen_u8, gen_Array_gen_u8_append_at -#define GEN_GENERIC_SLOT_4__array_append_items_at gen_Array_gen_u8, gen_Array_gen_u8_append_items_at -#define GEN_GENERIC_SLOT_4__array_back gen_Array_gen_u8, gen_Array_gen_u8_back -#define GEN_GENERIC_SLOT_4__array_clear gen_Array_gen_u8, gen_Array_gen_u8_clear -#define GEN_GENERIC_SLOT_4__array_fill gen_Array_gen_u8, gen_Array_gen_u8_fill -#define GEN_GENERIC_SLOT_4__array_free gen_Array_gen_u8, gen_Array_gen_u8_free -#define GEN_GENERIC_SLOT_4__array_grow gen_Array_gen_u8*, gen_Array_gen_u8_grow -#define GEN_GENERIC_SLOT_4__array_num gen_Array_gen_u8, gen_Array_gen_u8_num -#define GEN_GENERIC_SLOT_4__array_pop gen_Array_gen_u8, gen_Array_gen_u8_pop -#define GEN_GENERIC_SLOT_4__array_remove_at gen_Array_gen_u8, gen_Array_gen_u8_remove_at -#define GEN_GENERIC_SLOT_4__array_reserve gen_Array_gen_u8, gen_Array_gen_u8_reserve -#define GEN_GENERIC_SLOT_4__array_resize gen_Array_gen_u8, gen_Array_gen_u8_resize -#define GEN_GENERIC_SLOT_4__array_set_capacity gen_Array_gen_u8*, gen_Array_gen_u8_set_capacity - -typedef gen_u8* gen_Array_gen_u8; -gen_Array_gen_u8 gen_Array_gen_u8_init(gen_AllocatorInfo allocator); -gen_Array_gen_u8 gen_Array_gen_u8_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity); -bool gen_Array_gen_u8_append_array(gen_Array_gen_u8* self, gen_Array_gen_u8 other); -bool gen_Array_gen_u8_append(gen_Array_gen_u8* self, gen_u8 value); -bool gen_Array_gen_u8_append_items(gen_Array_gen_u8* self, gen_u8* items, gen_usize item_num); -bool gen_Array_gen_u8_append_at(gen_Array_gen_u8* self, gen_u8 item, gen_usize idx); -bool gen_Array_gen_u8_append_items_at(gen_Array_gen_u8* self, gen_u8* items, gen_usize item_num, gen_usize idx); -gen_u8* gen_Array_gen_u8_back(gen_Array_gen_u8 self); -void gen_Array_gen_u8_clear(gen_Array_gen_u8 self); -bool gen_Array_gen_u8_fill(gen_Array_gen_u8 self, gen_usize begin, gen_usize end, gen_u8 value); -void gen_Array_gen_u8_free(gen_Array_gen_u8* self); -bool gen_Array_gen_u8_grow(gen_Array_gen_u8* self, gen_usize min_capacity); -gen_usize gen_Array_gen_u8_num(gen_Array_gen_u8 self); -gen_u8 gen_Array_gen_u8_pop(gen_Array_gen_u8 self); -void gen_Array_gen_u8_remove_at(gen_Array_gen_u8 self, gen_usize idx); -bool gen_Array_gen_u8_reserve(gen_Array_gen_u8* self, gen_usize new_capacity); -bool gen_Array_gen_u8_resize(gen_Array_gen_u8* self, gen_usize num); -bool gen_Array_gen_u8_set_capacity(gen_Array_gen_u8* self, gen_usize new_capacity); - -gen_forceinline gen_Array_gen_u8 gen_Array_gen_u8_init(gen_AllocatorInfo allocator) -{ - size_t initial_size = gen_array_grow_formula(0); - return gen_array_init_reserve(gen_u8, allocator, initial_size); -} - -inline gen_Array_gen_u8 gen_Array_gen_u8_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity) -{ - GEN_ASSERT(capacity > 0); - gen_ArrayHeader* header = gen_rcast(gen_ArrayHeader*, gen_alloc(allocator, sizeof(gen_ArrayHeader) + sizeof(gen_u8) * capacity)); - if (header == gen_nullptr) - return gen_nullptr; - header->Allocator = allocator; - header->Capacity = capacity; - header->Num = 0; - return gen_rcast(gen_u8*, header + 1); -} - -gen_forceinline bool gen_Array_gen_u8_append_array(gen_Array_gen_u8* self, gen_Array_gen_u8 other) -{ - return gen_array_append_items(*self, (gen_Array_gen_u8)other, gen_Array_gen_u8_num(other)); -} - -inline bool gen_Array_gen_u8_append(gen_Array_gen_u8* self, gen_u8 value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num == header->Capacity) - { - if (! gen_array_grow(self, header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - (*self)[header->Num] = value; - header->Num++; - return true; -} - -inline bool gen_Array_gen_u8_append_items(gen_Array_gen_u8* self, gen_u8* items, gen_usize item_num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(items != gen_nullptr); - GEN_ASSERT(item_num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num + item_num > header->Capacity) - { - if (! gen_array_grow(self, header->Capacity + item_num)) - return false; - header = gen_array_get_header(*self); - } - gen_mem_copy((*self) + header->Num, items, sizeof(gen_u8) * item_num); - header->Num += item_num; - return true; -} - -inline bool gen_Array_gen_u8_append_at(gen_Array_gen_u8* self, gen_u8 item, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - idx = header->Num - 1; - if (idx < 0) - idx = 0; - if (header->Capacity < header->Num + 1) - { - if (! gen_array_grow(self, header->Capacity + 1)) - return false; - header = gen_array_get_header(*self); - } - gen_Array_gen_u8 target = (*self) + idx; - gen_mem_move(target + 1, target, (header->Num - idx) * sizeof(gen_u8)); - header->Num++; - return true; -} - -inline bool gen_Array_gen_u8_append_items_at(gen_Array_gen_u8* self, gen_u8* items, gen_usize item_num, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - { - return gen_array_append_items(*self, items, item_num); - } - if (item_num > header->Capacity) - { - if (! gen_array_grow(self, item_num + header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - gen_u8* target = (*self) + idx + item_num; - gen_u8* src = (*self) + idx; - gen_mem_move(target, src, (header->Num - idx) * sizeof(gen_u8)); - gen_mem_copy(src, items, item_num * sizeof(gen_u8)); - header->Num += item_num; - return true; -} - -inline gen_u8* gen_Array_gen_u8_back(gen_Array_gen_u8 self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - if (header->Num == 0) - return 0; - return self + header->Num - 1; -} - -inline void gen_Array_gen_u8_clear(gen_Array_gen_u8 self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - header->Num = 0; -} - -inline bool gen_Array_gen_u8_fill(gen_Array_gen_u8 self, gen_usize begin, gen_usize end, gen_u8 value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(begin <= end); - gen_ArrayHeader* header = gen_array_get_header(self); - if (begin < 0 || end > header->Num) - return false; - for (gen_ssize idx = (gen_ssize)begin; idx < (gen_ssize)end; idx++) - self[idx] = value; - return true; -} - -inline void gen_Array_gen_u8_free(gen_Array_gen_u8* self) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_allocator_free(header->Allocator, header); - self = 0; -} - -inline bool gen_Array_gen_u8_grow(gen_Array_gen_u8* self, gen_usize min_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(min_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_usize new_capacity = gen_array_grow_formula(header->Capacity); - if (new_capacity < min_capacity) - new_capacity = min_capacity; - return gen_array_set_capacity(self, new_capacity); -} - -gen_forceinline gen_usize gen_Array_gen_u8_num(gen_Array_gen_u8 self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_array_get_header(self)->Num; -} - -inline gen_u8 gen_Array_gen_u8_pop(gen_Array_gen_u8 self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(header->Num > 0); - gen_u8 result = self[header->Num - 1]; - header->Num--; - return result; -} - -gen_forceinline void gen_Array_gen_u8_remove_at(gen_Array_gen_u8 self, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(idx < header->Num); - gen_mem_move(self + idx, self + idx + 1, sizeof(gen_u8) * (header->Num - idx - 1)); - header->Num--; -} - -inline bool gen_Array_gen_u8_reserve(gen_Array_gen_u8* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < new_capacity) - return gen_array_set_capacity(self, new_capacity); - return true; -} - -inline bool gen_Array_gen_u8_resize(gen_Array_gen_u8* self, gen_usize num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < num) - { - if (! gen_array_grow(self, num)) - return false; - header = gen_array_get_header(*self); - } - header->Num = num; - return true; -} - -inline bool gen_Array_gen_u8_set_capacity(gen_Array_gen_u8* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (new_capacity == header->Capacity) - return true; - if (new_capacity < header->Num) - { - header->Num = new_capacity; - return true; - } - gen_usize size = sizeof(gen_ArrayHeader) + sizeof(gen_u8) * new_capacity; - gen_ArrayHeader* new_header = gen_cast(gen_ArrayHeader*, gen_alloc(header->Allocator, size)); - if (new_header == 0) - return false; - gen_mem_move(new_header, header, sizeof(gen_ArrayHeader) + sizeof(gen_u8) * header->Num); - new_header->Capacity = new_capacity; - gen_allocator_free(header->Allocator, &header); - *self = gen_cast(gen_u8*, new_header + 1); - return true; -} - -#pragma endregion gen_Array_gen_u8 - -#pragma endregion Containers - -#pragma region Hashing - -GEN_API gen_u32 gen_crc32( void const* data, gen_ssize len ); -GEN_API gen_u64 gen_crc64( void const* data, gen_ssize len ); - -#pragma endregion Hashing - -#pragma region Strings - - -typedef struct gen_Str gen_Str; -struct gen_Str; - -gen_Str gen_to_str_from_c_str(char const* bad_string); -bool gen_str_are_equal(gen_Str lhs, gen_Str rhs); -char const* gen_str_back(gen_Str str); -bool gen_str_contains(gen_Str str, gen_Str substring); -gen_Str gen_str_duplicate(gen_Str str, gen_AllocatorInfo allocator); -gen_b32 gen_str_starts_with(gen_Str str, gen_Str substring); -gen_Str gen_str_visualize_whitespace(gen_Str str, gen_AllocatorInfo allocator); - -// Constant string with length. -struct gen_Str -{ - char const* Ptr; - gen_ssize Len; -}; - -#define gen_cast_to_str(str) *gen_rcast(gen_Str*, (str) - sizeof(gen_ssize)) - -#ifndef gen_txt -#define gen_txt(text) (GEN_NS gen_Str) { (text), sizeof(text) - 1 } -#endif - -GEN_API_C_BEGIN - -gen_forceinline char const* gen_str_begin(gen_Str str) -{ - return str.Ptr; -} - -gen_forceinline char const* gen_str_end(gen_Str str) -{ - return str.Ptr + str.Len; -} - -gen_forceinline char const* gen_str_next(gen_Str str, char const* iter) -{ - return iter + 1; -} - -GEN_API_C_END - -inline bool gen_str_are_equal(gen_Str lhs, gen_Str rhs) -{ - if (lhs.Len != rhs.Len) - return false; - - for (gen_ssize idx = 0; idx < lhs.Len; ++idx) - if (lhs.Ptr[idx] != rhs.Ptr[idx]) - return false; - - return true; -} - -inline char const* gen_str_back(gen_Str str) -{ - return &str.Ptr[str.Len - 1]; -} - -inline bool gen_str_contains(gen_Str str, gen_Str substring) -{ - if (substring.Len > str.Len) - return false; - - gen_ssize main_len = str.Len; - gen_ssize sub_len = substring.Len; - for (gen_ssize idx = 0; idx <= main_len - sub_len; ++idx) - { - if (gen_c_str_compare_len(str.Ptr + idx, substring.Ptr, sub_len) == 0) - return true; - } - return false; -} - -inline gen_b32 gen_str_starts_with(gen_Str str, gen_Str substring) -{ - if (substring.Len > str.Len) - return false; - - gen_b32 result = gen_c_str_compare_len(str.Ptr, substring.Ptr, substring.Len) == 0; - return result; -} - -inline gen_Str gen_to_str_from_c_str(char const* bad_str) -{ - gen_Str result = { bad_str, gen_c_str_len(bad_str) }; - return result; -} - -// Dynamic gen_StrBuilder -// This is directly based off the ZPL string api. -// They used a header pattern -// I kept it for simplicty of porting but its not necessary to keep it that way. -#pragma region gen_StrBuilder - -typedef struct gen_StrBuilderHeader gen_StrBuilderHeader; -struct gen_StrBuilderHeader; - - -typedef char* gen_StrBuilder; - -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); -gen_StrBuilder gen_strbuilder_fmt(gen_AllocatorInfo allocator, char* buf, gen_ssize buf_size, char const* fmt, ...); -gen_StrBuilder gen_strbuilder_fmt_buf(gen_AllocatorInfo allocator, char const* fmt, ...); -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_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_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, ...); -gen_ssize gen_strbuilder_avail_space(gen_StrBuilder const str); -char* gen_strbuilder_back(gen_StrBuilder str); -bool gen_strbuilder_contains_str(gen_StrBuilder const str, gen_Str substring); -bool gen_strbuilder_contains_string(gen_StrBuilder const str, gen_StrBuilder const substring); -gen_ssize gen_strbuilder_capacity(gen_StrBuilder const str); -void gen_strbuilder_clear(gen_StrBuilder str); -gen_StrBuilder gen_strbuilder_duplicate(gen_StrBuilder const str, gen_AllocatorInfo allocator); -void gen_strbuilder_free(gen_StrBuilder* str); -gen_StrBuilderHeader* gen_strbuilder_get_header(gen_StrBuilder str); -gen_ssize gen_strbuilder_length(gen_StrBuilder const str); -gen_b32 gen_strbuilder_starts_with_str(gen_StrBuilder const str, gen_Str substring); -gen_b32 gen_strbuilder_starts_with_string(gen_StrBuilder const str, gen_StrBuilder substring); -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_space(gen_StrBuilder str); - -struct gen_StrBuilderHeader -{ - gen_AllocatorInfo Allocator; - gen_ssize Capacity; - gen_ssize Length; -}; - -gen_forceinline char* gen_strbuilder_begin(gen_StrBuilder str) -{ - return ((char*)str); -} - -gen_forceinline char* gen_strbuilder_end(gen_StrBuilder str) -{ - return ((char*)str + gen_strbuilder_length(str)); -} - -gen_forceinline char* gen_strbuilder_next(gen_StrBuilder str, char const* iter) -{ - return ((char*)iter + 1); -} - -gen_forceinline gen_usize gen_strbuilder_grow_formula(gen_usize value) -{ - // Using a very aggressive growth formula to reduce time mem_copying with recursive calls to append in this library. - return 4 * value + 8; -} - -gen_forceinline gen_StrBuilder gen_strbuilder_make_c_str(gen_AllocatorInfo allocator, char const* str) -{ - gen_ssize length = str ? gen_c_str_len(str) : 0; - return gen_strbuilder_make_length(allocator, str, length); -} - -gen_forceinline gen_StrBuilder gen_strbuilder_make_str(gen_AllocatorInfo allocator, gen_Str str) -{ - return gen_strbuilder_make_length(allocator, str.Ptr, str.Len); -} - -inline gen_StrBuilder gen_strbuilder_fmt(gen_AllocatorInfo allocator, char* buf, gen_ssize buf_size, char const* fmt, ...) -{ - va_list va; - va_start(va, fmt); - gen_ssize res = gen_c_str_fmt_va(buf, buf_size, fmt, va) - 1; - va_end(va); - - return gen_strbuilder_make_length(allocator, buf, res); -} - -inline gen_StrBuilder gen_strbuilder_fmt_buf(gen_AllocatorInfo allocator, char const* fmt, ...) -{ - gen_local_persist gen_thread_local gen_PrintF_Buffer buf = gen_struct_zero_init(); - - va_list va; - va_start(va, fmt); - gen_ssize res = gen_c_str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va) - 1; - va_end(va); - - return gen_strbuilder_make_length(allocator, buf, res); -} - -inline gen_StrBuilder gen_strbuilder_join(gen_AllocatorInfo allocator, char const** parts, gen_ssize num_parts, char const* glue) -{ - gen_StrBuilder result = gen_strbuilder_make_c_str(allocator, ""); - - for (gen_ssize idx = 0; idx < num_parts; ++idx) - { - gen_strbuilder_append_c_str(&result, parts[idx]); - - if (idx < num_parts - 1) - gen_strbuilder_append_c_str(&result, glue); - } - - return result; -} - -gen_forceinline bool gen_strbuilder_append_char(gen_StrBuilder* str, char c) -{ - GEN_ASSERT(str != gen_nullptr); - return gen_strbuilder_append_c_str_len(str, (char const*)&c, (gen_ssize)1); -} - -gen_forceinline bool gen_strbuilder_append_c_str(gen_StrBuilder* str, char const* gen_c_str_to_append) -{ - GEN_ASSERT(str != gen_nullptr); - return gen_strbuilder_append_c_str_len(str, gen_c_str_to_append, gen_c_str_len(gen_c_str_to_append)); -} - -gen_forceinline bool gen_strbuilder_append_str(gen_StrBuilder* str, gen_Str gen_c_str_to_append) -{ - GEN_ASSERT(str != gen_nullptr); - return gen_strbuilder_append_c_str_len(str, gen_c_str_to_append.Ptr, gen_c_str_to_append.Len); -} - -gen_forceinline bool gen_strbuilder_append_string(gen_StrBuilder* str, gen_StrBuilder const other) -{ - GEN_ASSERT(str != gen_nullptr); - return gen_strbuilder_append_c_str_len(str, (char const*)other, gen_strbuilder_length(other)); -} - -inline bool gen_strbuilder_append_fmt(gen_StrBuilder* str, char const* fmt, ...) -{ - GEN_ASSERT(str != gen_nullptr); - gen_ssize res; - char buf[GEN_PRINTF_MAXLEN] = { 0 }; - - va_list va; - va_start(va, fmt); - res = gen_c_str_fmt_va(buf, gen_count_of(buf) - 1, fmt, va) - 1; - va_end(va); - - return gen_strbuilder_append_c_str_len(str, (char const*)buf, res); -} - -inline bool gen_strbuilder_are_equal_string(gen_StrBuilder const lhs, gen_StrBuilder const rhs) -{ - if (gen_strbuilder_length(lhs) != gen_strbuilder_length(rhs)) - return false; - - for (gen_ssize idx = 0; idx < gen_strbuilder_length(lhs); ++idx) - if (lhs[idx] != rhs[idx]) - return false; - - return true; -} - -inline bool gen_strbuilder_are_equal_str(gen_StrBuilder const lhs, gen_Str rhs) -{ - if (gen_strbuilder_length(lhs) != (rhs.Len)) - return false; - - for (gen_ssize idx = 0; idx < gen_strbuilder_length(lhs); ++idx) - if (lhs[idx] != rhs.Ptr[idx]) - return false; - - return true; -} - -gen_forceinline gen_ssize gen_strbuilder_avail_space(gen_StrBuilder const str) -{ - gen_StrBuilderHeader const* header = gen_rcast(gen_StrBuilderHeader const*, gen_scast(char const*, str) - sizeof(gen_StrBuilderHeader)); - return header->Capacity - header->Length; -} - -gen_forceinline char* gen_strbuilder_back(gen_StrBuilder str) -{ - return &(str)[gen_strbuilder_length(str) - 1]; -} - -inline bool gen_strbuilder_contains_StrC(gen_StrBuilder const str, gen_Str substring) -{ - gen_StrBuilderHeader const* header = gen_rcast(gen_StrBuilderHeader const*, gen_scast(char const*, str) - sizeof(gen_StrBuilderHeader)); - - if (substring.Len > header->Length) - return false; - - gen_ssize main_len = header->Length; - gen_ssize sub_len = substring.Len; - - for (gen_ssize idx = 0; idx <= main_len - sub_len; ++idx) - { - if (gen_c_str_compare_len(str + idx, substring.Ptr, sub_len) == 0) - return true; - } - - return false; -} - -inline bool gen_strbuilder_contains_string(gen_StrBuilder const str, gen_StrBuilder const substring) -{ - gen_StrBuilderHeader const* header = gen_rcast(gen_StrBuilderHeader const*, gen_scast(char const*, str) - sizeof(gen_StrBuilderHeader)); - - if (gen_strbuilder_length(substring) > header->Length) - return false; - - gen_ssize main_len = header->Length; - gen_ssize sub_len = gen_strbuilder_length(substring); - - for (gen_ssize idx = 0; idx <= main_len - sub_len; ++idx) - { - if (gen_c_str_compare_len(str + idx, substring, sub_len) == 0) - return true; - } - - return false; -} - -gen_forceinline gen_ssize gen_strbuilder_capacity(gen_StrBuilder const str) -{ - gen_StrBuilderHeader const* header = gen_rcast(gen_StrBuilderHeader const*, gen_scast(char const*, str) - sizeof(gen_StrBuilderHeader)); - return header->Capacity; -} - -gen_forceinline void gen_strbuilder_clear(gen_StrBuilder str) -{ - gen_strbuilder_get_header(str)->Length = 0; -} - -gen_forceinline gen_StrBuilder gen_strbuilder_duplicate(gen_StrBuilder const str, gen_AllocatorInfo allocator) -{ - return gen_strbuilder_make_length(allocator, str, gen_strbuilder_length(str)); -} - -gen_forceinline void gen_strbuilder_free(gen_StrBuilder* str) -{ - GEN_ASSERT(str != gen_nullptr); - if (! (*str)) - return; - - gen_StrBuilderHeader* header = gen_strbuilder_get_header(*str); - gen_allocator_free(header->Allocator, header); -} - -gen_forceinline gen_StrBuilderHeader* gen_strbuilder_get_header(gen_StrBuilder str) -{ - return (gen_StrBuilderHeader*)(gen_scast(char*, str) - sizeof(gen_StrBuilderHeader)); -} - -gen_forceinline gen_ssize gen_strbuilder_length(gen_StrBuilder const str) -{ - gen_StrBuilderHeader const* header = gen_rcast(gen_StrBuilderHeader const*, gen_scast(char const*, str) - sizeof(gen_StrBuilderHeader)); - return header->Length; -} - -gen_forceinline gen_b32 gen_strbuilder_starts_with_str(gen_StrBuilder const str, gen_Str substring) -{ - if (substring.Len > gen_strbuilder_length(str)) - return false; - - gen_b32 result = gen_c_str_compare_len(str, substring.Ptr, substring.Len) == 0; - return result; -} - -gen_forceinline gen_b32 gen_strbuilder_starts_with_string(gen_StrBuilder const str, gen_StrBuilder substring) -{ - if (gen_strbuilder_length(substring) > gen_strbuilder_length(str)) - return false; - - gen_b32 result = gen_c_str_compare_len(str, substring, gen_strbuilder_length(substring) - 1) == 0; - return result; -} - -inline void gen_strbuilder_skip_line(gen_StrBuilder str) -{ -#define current (*scanner) - char* scanner = str; - while (current != '\r' && current != '\n') - { - ++scanner; - } - - gen_s32 new_length = scanner - str; - - if (current == '\r') - { - new_length += 1; - } - - gen_mem_move((char*)str, scanner, new_length); - - gen_StrBuilderHeader* header = gen_strbuilder_get_header(str); - header->Length = new_length; -#undef current -} - -inline void gen_strbuilder_strip_space(gen_StrBuilder str) -{ - char* write_pos = str; - char* read_pos = str; - - while (*read_pos) - { - if (! gen_char_is_space(*read_pos)) - { - *write_pos = *read_pos; - write_pos++; - } - read_pos++; - } - write_pos[0] = '\0'; // Null-terminate the modified string - - // Update the length if needed - gen_strbuilder_get_header(str)->Length = write_pos - str; -} - -gen_forceinline gen_Str gen_strbuilder_to_str(gen_StrBuilder str) -{ - gen_Str result = { (char const*)str, gen_strbuilder_length(str) }; - return result; -} - -gen_forceinline void gen_strbuilder_trim_space(gen_StrBuilder str) -{ - gen_strbuilder_trim(str, " \t\r\n\v\f"); -} - -#pragma endregion gen_StrBuilder - -gen_forceinline gen_Str gen_str_duplicate(gen_Str str, gen_AllocatorInfo allocator) -{ - gen_Str result = gen_strbuilder_to_str(gen_strbuilder_make_length(allocator, str.Ptr, str.Len)); - return result; -} - -inline gen_Str gen_str_visualize_whitespace(gen_Str str, gen_AllocatorInfo allocator) -{ - gen_StrBuilder result = gen_strbuilder_make_reserve(allocator, str.Len * 2); // Assume worst case for space requirements. - for (char const* c = gen_str_begin(str); c != gen_str_end(str); c = gen_str_next(str, c)) - switch (*c) - { - case ' ': - gen_strbuilder_append_str(&result, gen_txt("·")); - break; - case '\t': - gen_strbuilder_append_str(&result, gen_txt("→")); - break; - case '\n': - gen_strbuilder_append_str(&result, gen_txt("↵")); - break; - case '\r': - gen_strbuilder_append_str(&result, gen_txt("⏎")); - break; - case '\v': - gen_strbuilder_append_str(&result, gen_txt("⇕")); - break; - case '\f': - gen_strbuilder_append_str(&result, gen_txt("⌂")); - break; - default: - gen_strbuilder_append_char(&result, *c); - break; - } - return gen_strbuilder_to_str(result); -} - -// Represents strings cached with the string table. -// Should never be modified, if changed string is desired, cache_string( str ) another. -typedef gen_Str gen_StrCached; - -// Implements basic string interning. Data structure is based off the ZPL Hashtable. -#pragma region gen_StringTable - -#define GEN_GENERIC_SLOT_1__hashtable_init gen_Str, gen_StringTable_init -#define GEN_GENERIC_SLOT_1__hashtable_init_reserve gen_Str, gen_StringTable_init_reserve -#define GEN_GENERIC_SLOT_1__hashtable_clear gen_StringTable, gen_StringTable_clear -#define GEN_GENERIC_SLOT_1__hashtable_destroy gen_StringTable, gen_StringTable_destroy -#define GEN_GENERIC_SLOT_1__hashtable_get gen_StringTable, gen_StringTable_get -#define GEN_GENERIC_SLOT_1__hashtable_map gen_StringTable, gen_StringTable_map -#define GEN_GENERIC_SLOT_1__hashtable_map_mut gen_StringTable, gen_StringTable_map_mut -#define GEN_GENERIC_SLOT_1__hashtable_grow gen_StringTable*, gen_StringTable_grow -#define GEN_GENERIC_SLOT_1__hashtable_rehash gen_StringTable*, gen_StringTable_rehash -#define GEN_GENERIC_SLOT_1__hashtable_rehash_fast gen_StringTable, gen_StringTable_rehash_fast -#define GEN_GENERIC_SLOT_1__hashtable_remove_entry gen_StringTable, gen_StringTable_remove_entry -#define GEN_GENERIC_SLOT_1__hashtable_set gen_StringTable, gen_StringTable_set -#define GEN_GENERIC_SLOT_1__hashtable_slot gen_StringTable, gen_StringTable_slot - -#define GEN_GENERIC_SLOT_1__hashtable__add_entry gen_StringTable*, gen_StringTable__add_entry -#define GEN_GENERIC_SLOT_1__hashtable__find gen_StringTable, gen_StringTable__find -#define GEN_GENERIC_SLOT_1__hashtable__full gen_StringTable, gen_StringTable__full - -typedef struct gen_HashTable_gen_Str gen_StringTable; -typedef struct gen_HTE_StringTable gen_HTE_StringTable; - -struct gen_HTE_StringTable -{ - gen_u64 Key; - gen_ssize Next; - gen_Str Value; -}; - -typedef void (*gen_StringTable_MapProc)(gen_StringTable self, gen_u64 key, gen_Str value); -typedef void (*gen_StringTable_MapMutProc)(gen_StringTable self, gen_u64 key, gen_Str* value); - -#pragma region gen_Arr_HTE_StringTable - -#define GEN_GENERIC_SLOT_3__array_init gen_HTE_StringTable, gen_Arr_HTE_StringTable_init -#define GEN_GENERIC_SLOT_3__array_init_reserve gen_HTE_StringTable, gen_Arr_HTE_StringTable_init_reserve -#define GEN_GENERIC_SLOT_3__array_append gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_append -#define GEN_GENERIC_SLOT_3__array_append_items gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_append_items -#define GEN_GENERIC_SLOT_3__array_append_at gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_append_at -#define GEN_GENERIC_SLOT_3__array_append_items_at gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_append_items_at -#define GEN_GENERIC_SLOT_3__array_back gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_back -#define GEN_GENERIC_SLOT_3__array_clear gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_clear -#define GEN_GENERIC_SLOT_3__array_fill gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_fill -#define GEN_GENERIC_SLOT_3__array_free gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_free -#define GEN_GENERIC_SLOT_3__array_grow gen_Arr_HTE_StringTable*, gen_Arr_HTE_StringTable_grow -#define GEN_GENERIC_SLOT_3__array_num gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_num -#define GEN_GENERIC_SLOT_3__array_pop gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_pop -#define GEN_GENERIC_SLOT_3__array_remove_at gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_remove_at -#define GEN_GENERIC_SLOT_3__array_reserve gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_reserve -#define GEN_GENERIC_SLOT_3__array_resize gen_Arr_HTE_StringTable, gen_Arr_HTE_StringTable_resize -#define GEN_GENERIC_SLOT_3__array_set_capacity gen_Arr_HTE_StringTable*, gen_Arr_HTE_StringTable_set_capacity - -typedef gen_HTE_StringTable* gen_Arr_HTE_StringTable; -gen_Arr_HTE_StringTable gen_Arr_HTE_StringTable_init(gen_AllocatorInfo allocator); -gen_Arr_HTE_StringTable gen_Arr_HTE_StringTable_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity); -bool gen_Arr_HTE_StringTable_append_array(gen_Arr_HTE_StringTable* self, gen_Arr_HTE_StringTable other); -bool gen_Arr_HTE_StringTable_append(gen_Arr_HTE_StringTable* self, gen_HTE_StringTable value); -bool gen_Arr_HTE_StringTable_append_items(gen_Arr_HTE_StringTable* self, gen_HTE_StringTable* items, gen_usize item_num); -bool gen_Arr_HTE_StringTable_append_at(gen_Arr_HTE_StringTable* self, gen_HTE_StringTable item, gen_usize idx); -bool gen_Arr_HTE_StringTable_append_items_at(gen_Arr_HTE_StringTable* self, gen_HTE_StringTable* items, gen_usize item_num, gen_usize idx); -gen_HTE_StringTable* gen_Arr_HTE_StringTable_back(gen_Arr_HTE_StringTable self); -void gen_Arr_HTE_StringTable_clear(gen_Arr_HTE_StringTable self); -bool gen_Arr_HTE_StringTable_fill(gen_Arr_HTE_StringTable self, gen_usize begin, gen_usize end, gen_HTE_StringTable value); -void gen_Arr_HTE_StringTable_free(gen_Arr_HTE_StringTable* self); -bool gen_Arr_HTE_StringTable_grow(gen_Arr_HTE_StringTable* self, gen_usize min_capacity); -gen_usize gen_Arr_HTE_StringTable_num(gen_Arr_HTE_StringTable self); -gen_HTE_StringTable gen_Arr_HTE_StringTable_pop(gen_Arr_HTE_StringTable self); -void gen_Arr_HTE_StringTable_remove_at(gen_Arr_HTE_StringTable self, gen_usize idx); -bool gen_Arr_HTE_StringTable_reserve(gen_Arr_HTE_StringTable* self, gen_usize new_capacity); -bool gen_Arr_HTE_StringTable_resize(gen_Arr_HTE_StringTable* self, gen_usize num); -bool gen_Arr_HTE_StringTable_set_capacity(gen_Arr_HTE_StringTable* self, gen_usize new_capacity); - -gen_forceinline gen_Arr_HTE_StringTable gen_Arr_HTE_StringTable_init(gen_AllocatorInfo allocator) -{ - size_t initial_size = gen_array_grow_formula(0); - return gen_array_init_reserve(gen_HTE_StringTable, allocator, initial_size); -} - -inline gen_Arr_HTE_StringTable gen_Arr_HTE_StringTable_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity) -{ - GEN_ASSERT(capacity > 0); - gen_ArrayHeader* header = gen_rcast(gen_ArrayHeader*, gen_alloc(allocator, sizeof(gen_ArrayHeader) + sizeof(gen_HTE_StringTable) * capacity)); - if (header == gen_nullptr) - return gen_nullptr; - header->Allocator = allocator; - header->Capacity = capacity; - header->Num = 0; - return gen_rcast(gen_HTE_StringTable*, header + 1); -} - -gen_forceinline bool gen_Arr_HTE_StringTable_append_array(gen_Arr_HTE_StringTable* self, gen_Arr_HTE_StringTable other) -{ - return gen_array_append_items(*self, (gen_Arr_HTE_StringTable)other, gen_Arr_HTE_StringTable_num(other)); -} - -inline bool gen_Arr_HTE_StringTable_append(gen_Arr_HTE_StringTable* self, gen_HTE_StringTable value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num == header->Capacity) - { - if (! gen_array_grow(self, header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - (*self)[header->Num] = value; - header->Num++; - return true; -} - -inline bool gen_Arr_HTE_StringTable_append_items(gen_Arr_HTE_StringTable* self, gen_HTE_StringTable* items, gen_usize item_num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(items != gen_nullptr); - GEN_ASSERT(item_num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num + item_num > header->Capacity) - { - if (! gen_array_grow(self, header->Capacity + item_num)) - return false; - header = gen_array_get_header(*self); - } - gen_mem_copy((*self) + header->Num, items, sizeof(gen_HTE_StringTable) * item_num); - header->Num += item_num; - return true; -} - -inline bool gen_Arr_HTE_StringTable_append_at(gen_Arr_HTE_StringTable* self, gen_HTE_StringTable item, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - idx = header->Num - 1; - if (idx < 0) - idx = 0; - if (header->Capacity < header->Num + 1) - { - if (! gen_array_grow(self, header->Capacity + 1)) - return false; - header = gen_array_get_header(*self); - } - gen_Arr_HTE_StringTable target = (*self) + idx; - gen_mem_move(target + 1, target, (header->Num - idx) * sizeof(gen_HTE_StringTable)); - header->Num++; - return true; -} - -inline bool gen_Arr_HTE_StringTable_append_items_at(gen_Arr_HTE_StringTable* self, gen_HTE_StringTable* items, gen_usize item_num, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - { - return gen_array_append_items(*self, items, item_num); - } - if (item_num > header->Capacity) - { - if (! gen_array_grow(self, item_num + header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - gen_HTE_StringTable* target = (*self) + idx + item_num; - gen_HTE_StringTable* src = (*self) + idx; - gen_mem_move(target, src, (header->Num - idx) * sizeof(gen_HTE_StringTable)); - gen_mem_copy(src, items, item_num * sizeof(gen_HTE_StringTable)); - header->Num += item_num; - return true; -} - -inline gen_HTE_StringTable* gen_Arr_HTE_StringTable_back(gen_Arr_HTE_StringTable self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - if (header->Num == 0) - return 0; - return self + header->Num - 1; -} - -inline void gen_Arr_HTE_StringTable_clear(gen_Arr_HTE_StringTable self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - header->Num = 0; -} - -inline bool gen_Arr_HTE_StringTable_fill(gen_Arr_HTE_StringTable self, gen_usize begin, gen_usize end, gen_HTE_StringTable value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(begin <= end); - gen_ArrayHeader* header = gen_array_get_header(self); - if (begin < 0 || end > header->Num) - return false; - for (gen_ssize idx = (gen_ssize)begin; idx < (gen_ssize)end; idx++) - self[idx] = value; - return true; -} - -inline void gen_Arr_HTE_StringTable_free(gen_Arr_HTE_StringTable* self) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_allocator_free(header->Allocator, header); - self = 0; -} - -inline bool gen_Arr_HTE_StringTable_grow(gen_Arr_HTE_StringTable* self, gen_usize min_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(min_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_usize new_capacity = gen_array_grow_formula(header->Capacity); - if (new_capacity < min_capacity) - new_capacity = min_capacity; - return gen_array_set_capacity(self, new_capacity); -} - -gen_forceinline gen_usize gen_Arr_HTE_StringTable_num(gen_Arr_HTE_StringTable self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_array_get_header(self)->Num; -} - -inline gen_HTE_StringTable gen_Arr_HTE_StringTable_pop(gen_Arr_HTE_StringTable self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(header->Num > 0); - gen_HTE_StringTable result = self[header->Num - 1]; - header->Num--; - return result; -} - -gen_forceinline void gen_Arr_HTE_StringTable_remove_at(gen_Arr_HTE_StringTable self, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(idx < header->Num); - gen_mem_move(self + idx, self + idx + 1, sizeof(gen_HTE_StringTable) * (header->Num - idx - 1)); - header->Num--; -} - -inline bool gen_Arr_HTE_StringTable_reserve(gen_Arr_HTE_StringTable* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < new_capacity) - return gen_array_set_capacity(self, new_capacity); - return true; -} - -inline bool gen_Arr_HTE_StringTable_resize(gen_Arr_HTE_StringTable* self, gen_usize num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < num) - { - if (! gen_array_grow(self, num)) - return false; - header = gen_array_get_header(*self); - } - header->Num = num; - return true; -} - -inline bool gen_Arr_HTE_StringTable_set_capacity(gen_Arr_HTE_StringTable* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (new_capacity == header->Capacity) - return true; - if (new_capacity < header->Num) - { - header->Num = new_capacity; - return true; - } - gen_usize size = sizeof(gen_ArrayHeader) + sizeof(gen_HTE_StringTable) * new_capacity; - gen_ArrayHeader* new_header = gen_cast(gen_ArrayHeader*, gen_alloc(header->Allocator, size)); - if (new_header == 0) - return false; - gen_mem_move(new_header, header, sizeof(gen_ArrayHeader) + sizeof(gen_HTE_StringTable) * header->Num); - new_header->Capacity = new_capacity; - gen_allocator_free(header->Allocator, &header); - *self = gen_cast(gen_HTE_StringTable*, new_header + 1); - return true; -} - -#pragma endregion gen_Arr_HTE_StringTable - -struct gen_HashTable_gen_Str -{ - gen_Array_gen_ssize Hashes; - gen_Arr_HTE_StringTable Entries; -}; - -gen_StringTable gen_StringTable_init(gen_AllocatorInfo allocator); -gen_StringTable gen_StringTable_init_reserve(gen_AllocatorInfo allocator, gen_ssize num); -void gen_StringTable_clear(gen_StringTable self); -void gen_StringTable_destroy(gen_StringTable* self); -gen_Str* gen_StringTable_get(gen_StringTable self, gen_u64 key); -void gen_StringTable_map(gen_StringTable self, gen_StringTable_MapProc map_proc); -void gen_StringTable_map_mut(gen_StringTable self, gen_StringTable_MapMutProc map_proc); -void gen_StringTable_grow(gen_StringTable* self); -void gen_StringTable_rehash(gen_StringTable* self, gen_ssize new_num); -void gen_StringTable_rehash_fast(gen_StringTable self); -void gen_StringTable_remove(gen_StringTable self, gen_u64 key); -void gen_StringTable_remove_entry(gen_StringTable self, gen_ssize idx); -void gen_StringTable_set(gen_StringTable* self, gen_u64 key, gen_Str value); -gen_ssize gen_StringTable_slot(gen_StringTable self, gen_u64 key); -gen_ssize gen_StringTable__add_entry(gen_StringTable* self, gen_u64 key); -gen_HT_FindResult gen_StringTable__find(gen_StringTable self, gen_u64 key); -gen_b32 gen_StringTable__full(gen_StringTable self); - -gen_StringTable gen_StringTable_init(gen_AllocatorInfo allocator) -{ - gen_StringTable result = gen_hashtable_init_reserve(gen_Str, allocator, 8); - return result; -} - -gen_StringTable gen_StringTable_init_reserve(gen_AllocatorInfo allocator, gen_ssize num) -{ - gen_StringTable result = { 0, 0 }; - result.Hashes = gen_array_init_reserve(gen_ssize, allocator, num); - gen_array_get_header(result.Hashes)->Num = num; - gen_array_resize(result.Hashes, num); - gen_array_fill(result.Hashes, 0, num, -1); - result.Entries = gen_array_init_reserve(gen_HTE_StringTable, allocator, num); - return result; -} - -void gen_StringTable_clear(gen_StringTable self) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_array_clear(self.Entries); - gen_s32 what = gen_array_num(self.Hashes); - gen_array_fill(self.Hashes, 0, what, (gen_ssize)-1); -} - -void gen_StringTable_destroy(gen_StringTable* self) -{ - GEN_ASSERT_NOT_NULL(self); - GEN_ASSERT_NOT_NULL(self->Hashes); - GEN_ASSERT_NOT_NULL(self->Entries); - if (self->Hashes && gen_array_get_header(self->Hashes)->Capacity) - { - gen_array_free(self->Hashes); - gen_array_free(self->Entries); - } -} - -gen_Str* gen_StringTable_get(gen_StringTable self, gen_u64 key) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_ssize idx = gen_StringTable__find(self, key).EntryIndex; - if (idx > 0) - return &self.Entries[idx].Value; - return gen_nullptr; -} - -void gen_StringTable_map(gen_StringTable self, gen_StringTable_MapProc map_proc) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - GEN_ASSERT_NOT_NULL(map_proc); - for (gen_ssize idx = 0; idx < gen_array_get_header(self.Entries)->Num; idx++) - { - map_proc(self, self.Entries[idx].Key, self.Entries[idx].Value); - } -} - -void gen_StringTable_map_mut(gen_StringTable self, gen_StringTable_MapMutProc map_proc) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - GEN_ASSERT_NOT_NULL(map_proc); - for (gen_ssize idx = 0; idx < gen_array_get_header(self.Entries)->Num; idx++) - { - map_proc(self, self.Entries[idx].Key, &self.Entries[idx].Value); - } -} - -void gen_StringTable_grow(gen_StringTable* self) -{ - GEN_ASSERT_NOT_NULL(self); - GEN_ASSERT_NOT_NULL(self->Hashes); - GEN_ASSERT_NOT_NULL(self->Entries); - gen_ssize new_num = gen_array_grow_formula(gen_array_get_header(self->Entries)->Num); - gen_hashtable_rehash(self, new_num); -} - -void gen_StringTable_rehash(gen_StringTable* self, gen_ssize new_num) -{ - GEN_ASSERT_NOT_NULL(self); - GEN_ASSERT_NOT_NULL(self->Hashes); - GEN_ASSERT_NOT_NULL(self->Entries); - GEN_ASSERT(new_num > 0); - gen_ssize idx; - gen_ssize last_added_index; - gen_ArrayHeader* old_hash_header = gen_array_get_header(self->Hashes); - gen_ArrayHeader* old_entries_header = gen_array_get_header(self->Entries); - gen_StringTable new_tbl = gen_hashtable_init_reserve(gen_Str, old_hash_header->Allocator, old_hash_header->Num); - gen_ArrayHeader* new_hash_header = gen_array_get_header(new_tbl.Hashes); - for (gen_ssize idx = 0; idx < gen_cast(gen_ssize, old_hash_header->Num); ++idx) - { - gen_HTE_StringTable* entry = &self->Entries[idx]; - gen_HT_FindResult find_result; - find_result = gen_StringTable__find(new_tbl, entry->Key); - last_added_index = gen_StringTable__add_entry(&new_tbl, entry->Key); - if (find_result.PrevIndex < 0) - new_tbl.Hashes[find_result.HashIndex] = last_added_index; - else - new_tbl.Entries[find_result.PrevIndex].Next = last_added_index; - new_tbl.Entries[last_added_index].Next = find_result.EntryIndex; - new_tbl.Entries[last_added_index].Value = entry->Value; - } - gen_StringTable_destroy(self); - *self = new_tbl; -} - -void gen_StringTable_rehash_fast(gen_StringTable self) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_ssize idx; - for (idx = 0; idx < gen_array_get_header(self.Entries)->Num; idx++) - self.Entries[idx].Next = -1; - for (idx = 0; idx < gen_array_get_header(self.Hashes)->Num; idx++) - self.Hashes[idx] = -1; - for (idx = 0; idx < gen_array_get_header(self.Entries)->Num; idx++) - { - gen_HTE_StringTable* entry; - gen_HT_FindResult find_result; - entry = &self.Entries[idx]; - find_result = gen_StringTable__find(self, entry->Key); - if (find_result.PrevIndex < 0) - self.Hashes[find_result.HashIndex] = idx; - else - self.Entries[find_result.PrevIndex].Next = idx; - } -} - -void gen_StringTable_remove(gen_StringTable self, gen_u64 key) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_HT_FindResult find_result = gen_StringTable__find(self, key); - if (find_result.EntryIndex >= 0) - { - gen_array_remove_at(self.Entries, find_result.EntryIndex); - gen_hashtable_rehash_fast(self); - } -} - -void gen_StringTable_remove_entry(gen_StringTable self, gen_ssize idx) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_array_remove_at(self.Entries, idx); -} - -void gen_StringTable_set(gen_StringTable* self, gen_u64 key, gen_Str value) -{ - GEN_ASSERT_NOT_NULL(self); - GEN_ASSERT_NOT_NULL(self->Hashes); - GEN_ASSERT_NOT_NULL(self->Entries); - gen_ssize idx; - gen_HT_FindResult find_result; - if (gen_array_get_header(self->Hashes)->Num == 0) - gen_hashtable_grow(self); - find_result = gen_StringTable__find(*self, key); - if (find_result.EntryIndex >= 0) - { - idx = find_result.EntryIndex; - } - else - { - idx = gen_StringTable__add_entry(self, key); - if (find_result.PrevIndex >= 0) - { - self->Entries[find_result.PrevIndex].Next = idx; - } - else - { - self->Hashes[find_result.HashIndex] = idx; - } - } - self->Entries[idx].Value = value; - if (gen_StringTable__full(*self)) - gen_hashtable_grow(self); -} - -gen_ssize gen_StringTable_slot(gen_StringTable self, gen_u64 key) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - for (gen_ssize idx = 0; idx < gen_array_get_header(self.Hashes)->Num; ++idx) - if (self.Hashes[idx] == key) - return idx; - return -1; -} - -gen_ssize gen_StringTable__add_entry(gen_StringTable* self, gen_u64 key) -{ - GEN_ASSERT_NOT_NULL(self); - GEN_ASSERT_NOT_NULL(self->Hashes); - GEN_ASSERT_NOT_NULL(self->Entries); - gen_ssize idx; - gen_HTE_StringTable entry = { key, -1 }; - idx = gen_array_get_header(self->Entries)->Num; - gen_array_append(self->Entries, entry); - return idx; -} - -gen_HT_FindResult gen_StringTable__find(gen_StringTable self, gen_u64 key) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_HT_FindResult result = { -1, -1, -1 }; - gen_ArrayHeader* hash_header = gen_array_get_header(self.Hashes); - if (hash_header->Num > 0) - { - result.HashIndex = key % hash_header->Num; - result.EntryIndex = self.Hashes[result.HashIndex]; - while (result.EntryIndex >= 0) - { - if (self.Entries[result.EntryIndex].Key == key) - break; - result.PrevIndex = result.EntryIndex; - result.EntryIndex = self.Entries[result.EntryIndex].Next; - } - } - return result; -} - -gen_b32 gen_StringTable__full(gen_StringTable self) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_ArrayHeader* hash_header = gen_array_get_header(self.Hashes); - gen_ArrayHeader* entries_header = gen_array_get_header(self.Entries); - gen_usize critical_load = gen_cast(gen_usize, gen_HashTable_CriticalLoadScale * gen_cast(gen_f32, hash_header->Num)); - gen_b32 result = entries_header->Num > critical_load; - return result; -} - -#pragma endregion gen_StringTable - -#pragma endregion Strings - -#pragma region File Handling - -enum gen_FileModeFlag -{ - EFileMode_READ = gen_bit(0), - EFileMode_WRITE = gen_bit(1), - EFileMode_APPEND = gen_bit(2), - EFileMode_RW = gen_bit(3), - GEN_FILE_MODES = EFileMode_READ | EFileMode_WRITE | EFileMode_APPEND | EFileMode_RW, -}; -typedef enum gen_FileModeFlag gen_FileModeFlag; - -// NOTE: Only used internally and for the file operations -enum gen_SeekWhenceType -{ - ESeekWhence_BEGIN = 0, - ESeekWhence_CURRENT = 1, - ESeekWhence_END = 2, -}; -typedef enum gen_SeekWhenceType gen_SeekWhenceType; - -enum gen_FileError -{ - EFileError_NONE, - EFileError_INVALID, - EFileError_INVALID_FILENAME, - EFileError_EXISTS, - EFileError_NOT_EXISTS, - EFileError_PERMISSION, - EFileError_TRUNCATION_FAILURE, - EFileError_NOT_EMPTY, - EFileError_NAME_TOO_LONG, - EFileError_UNKNOWN, -}; -typedef enum gen_FileError gen_FileError; - -union gen_FileDescriptor -{ - void* p; - gen_sptr i; - gen_uptr u; -}; -typedef union gen_FileDescriptor gen_FileDescriptor; - -typedef gen_u32 gen_FileMode; -typedef struct gen_FileOperations gen_FileOperations; - -#define GEN_FILE_OPEN_PROC(name) gen_FileError name(gen_FileDescriptor* fd, gen_FileOperations* ops, gen_FileMode mode, char const* filename) -#define GEN_FILE_READ_AT_PROC(name) \ - gen_b32 name(gen_FileDescriptor fd, void* buffer, gen_ssize size, gen_s64 offset, gen_ssize* bytes_read, gen_b32 stop_at_newline) -#define GEN_FILE_WRITE_AT_PROC(name) gen_b32 name(gen_FileDescriptor fd, gen_mem_ptr_const buffer, gen_ssize size, gen_s64 offset, gen_ssize* bytes_written) -#define GEN_FILE_SEEK_PROC(name) gen_b32 name(gen_FileDescriptor fd, gen_s64 offset, gen_SeekWhenceType whence, gen_s64* new_offset) -#define GEN_FILE_CLOSE_PROC(name) void name(gen_FileDescriptor fd) - -typedef GEN_FILE_OPEN_PROC(gen_file_open_proc); -typedef GEN_FILE_READ_AT_PROC(FileReadProc); -typedef GEN_FILE_WRITE_AT_PROC(FileWriteProc); -typedef GEN_FILE_SEEK_PROC(FileSeekProc); -typedef GEN_FILE_CLOSE_PROC(FileCloseProc); - -struct gen_FileOperations -{ - FileReadProc* read_at; - FileWriteProc* write_at; - FileSeekProc* seek; - FileCloseProc* close; -}; -typedef struct gen_FileOperations gen_FileOperations; - -extern gen_FileOperations const default_file_operations; - -typedef gen_u64 word; - -enum gen_DirType -{ - GEN_DIR_TYPE_FILE, - GEN_DIR_TYPE_FOLDER, - GEN_DIR_TYPE_UNKNOWN, -}; -typedef enum gen_DirType gen_DirType; - -struct gen_DirInfo; -typedef struct gen_DirInfo gen_DirInfo; - -struct gen_DirEntry -{ - char const* filename; - gen_DirInfo* dir_info; - gen_u8 type; -}; -typedef struct gen_DirEntry gen_DirEntry; - -struct gen_DirInfo -{ - char const* fullpath; - gen_DirEntry* entries; // zpl_array - - // Internals - char** filenames; // zpl_array - gen_StrBuilder buf; -}; -typedef struct gen_DirInfo gen_DirInfo; - -struct gen_FileInfo -{ - gen_FileOperations ops; - gen_FileDescriptor fd; - gen_b32 is_temp; - - char const* filename; - word last_write_time; - gen_DirEntry* dir; -}; -typedef struct gen_FileInfo gen_FileInfo; - -enum gen_FileStandardType -{ - EFileStandard_INPUT, - EFileStandard_OUTPUT, - EFileStandard_ERROR, - EFileStandard_COUNT, -}; -typedef enum gen_FileStandardType gen_FileStandardType; - -/** - * Get standard file I/O. - * @param std Check zpl_file_standard_type - * @return File handle to standard I/O - */ -GEN_API gen_FileInfo* gen_file_get_standard(gen_FileStandardType std); - -/** - * Closes the file - * @param file - */ -GEN_API gen_FileError gen_file_close(gen_FileInfo* file); - -/** - * Returns the currently opened file's name - * @param file - */ -inline char const* gen_file_name(gen_FileInfo* file) -{ - return file->filename ? file->filename : ""; -} - -/** - * Opens a file - * @param file - * @param filename - */ -GEN_API gen_FileError gen_file_open(gen_FileInfo* file, char const* filename); - -/** - * Opens a file using a specified mode - * @param file - * @param mode Access mode to use - * @param filename - */ -GEN_API gen_FileError gen_file_open_mode(gen_FileInfo* file, gen_FileMode mode, char const* filename); - -/** - * Reads from a file - * @param file - * @param buffer Buffer to read to - * @param size Size to read - */ -gen_b32 gen_file_read(gen_FileInfo* file, void* buffer, gen_ssize size); - -/** - * Reads file at a specific offset - * @param file - * @param buffer Buffer to read to - * @param size Size to read - * @param offset Offset to read from - * @param bytes_read How much data we've actually read - */ -gen_b32 gen_file_read_at(gen_FileInfo* file, void* buffer, gen_ssize size, gen_s64 offset); - -/** - * Reads file safely - * @param file - * @param buffer Buffer to read to - * @param size Size to read - * @param offset Offset to read from - * @param bytes_read How much data we've actually read - */ -gen_b32 gen_file_read_at_check(gen_FileInfo* file, void* buffer, gen_ssize size, gen_s64 offset, gen_ssize* bytes_read); - -typedef struct FileContents FileContents; - -struct FileContents -{ - gen_AllocatorInfo allocator; - void* data; - gen_ssize size; -}; -typedef struct FileContents FileContents; - -#define gen_file_zero_terminate true -#define gen_file_no_zero_terminate false - -/** - * Reads the whole file contents - * @param a Allocator to use - * @param zero_terminate End the read data with null terminator - * @param filepath Path to the file - * @return File contents data - */ -GEN_API FileContents gen_file_read_contents(gen_AllocatorInfo a, gen_b32 zero_terminate, char const* filepath); - -/** - * Returns a size of the file - * @param file - * @return File size - */ -GEN_API gen_s64 gen_file_size(gen_FileInfo* file); - -/** - * Seeks the file cursor from the beginning of file to a specific position - * @param file - * @param offset Offset to seek to - */ -gen_s64 gen_file_seek(gen_FileInfo* file, gen_s64 offset); - -/** - * Seeks the file cursor to the end of the file - * @param file - */ -gen_s64 gen_file_seek_to_end(gen_FileInfo* file); - -/** - * Returns the length from the beginning of the file we've read so far - * @param file - * @return Our current position in file - */ -gen_s64 gen_file_tell(gen_FileInfo* file); - -/** - * Writes to a file - * @param file - * @param buffer Buffer to read from - * @param size Size to read - */ -gen_b32 gen_file_write(gen_FileInfo* file, void const* buffer, gen_ssize size); - -/** - * Writes to file at a specific offset - * @param file - * @param buffer Buffer to read from - * @param size Size to write - * @param offset Offset to write to - * @param bytes_written How much data we've actually written - */ -gen_b32 gen_file_write_at(gen_FileInfo* file, void const* buffer, gen_ssize size, gen_s64 offset); - -/** - * Writes to file safely - * @param file - * @param buffer Buffer to read from - * @param size Size to write - * @param offset Offset to write to - * @param bytes_written How much data we've actually written - */ -gen_b32 gen_file_write_at_check(gen_FileInfo* file, void const* buffer, gen_ssize size, gen_s64 offset, gen_ssize* bytes_written); - -enum FileStreamFlags gen_enum_underlying(gen_u32) -{ - /* Allows us to write to the buffer directly. Beware: you can not append a new data! */ - EFileStream_WRITABLE = gen_bit(0), /* Clones the input buffer so you can write (zpl_file_write*) data into it. */ - /* Since we work with a clone, the buffer size can dynamically grow as well. */ - EFileStream_CLONE_WRITABLE = gen_bit(1), - EFileStream_UNDERLYING = GEN_U32_MAX, -}; - -typedef gen_u32 FileStreamFlags; - -/** - * Opens a new memory stream - * @param file - * @param allocator - */ -GEN_API gen_b8 gen_file_stream_new(gen_FileInfo* file, gen_AllocatorInfo allocator); - -/** - * Opens a memory stream over an existing buffer - * @param file - * @param allocator - * @param buffer Memory to create stream from - * @param size Buffer's size - * @param flags - */ -GEN_API gen_b8 gen_file_stream_open(gen_FileInfo* file, gen_AllocatorInfo allocator, gen_u8* buffer, gen_ssize size, FileStreamFlags flags); - -/** - * Retrieves the stream's underlying buffer and buffer size. - * @param file memory stream - * @param size (Optional) buffer size - */ -GEN_API gen_u8* gen_file_stream_buf(gen_FileInfo* file, gen_ssize* size); - -extern gen_FileOperations const memory_file_operations; - -inline gen_s64 gen_file_seek(gen_FileInfo* f, gen_s64 offset) -{ - gen_s64 new_offset = 0; - - if (! f->ops.read_at) - f->ops = default_file_operations; - - f->ops.seek(f->fd, offset, ESeekWhence_BEGIN, &new_offset); - - return new_offset; -} - -inline gen_s64 gen_file_seek_to_end(gen_FileInfo* f) -{ - gen_s64 new_offset = 0; - - if (! f->ops.read_at) - f->ops = default_file_operations; - - f->ops.seek(f->fd, 0, ESeekWhence_END, &new_offset); - - return new_offset; -} - -inline gen_s64 gen_file_tell(gen_FileInfo* f) -{ - gen_s64 new_offset = 0; - - if (! f->ops.read_at) - f->ops = default_file_operations; - - f->ops.seek(f->fd, 0, ESeekWhence_CURRENT, &new_offset); - - return new_offset; -} - -inline gen_b32 gen_file_read(gen_FileInfo* f, void* buffer, gen_ssize size) -{ - gen_s64 cur_offset = gen_file_tell(f); - gen_b32 result = gen_file_read_at(f, buffer, size, gen_file_tell(f)); - gen_file_seek(f, cur_offset + size); - return result; -} - -inline gen_b32 gen_file_read_at(gen_FileInfo* f, void* buffer, gen_ssize size, gen_s64 offset) -{ - return gen_file_read_at_check(f, buffer, size, offset, NULL); -} - -inline gen_b32 gen_file_read_at_check(gen_FileInfo* f, void* buffer, gen_ssize size, gen_s64 offset, gen_ssize* bytes_read) -{ - if (! f->ops.read_at) - f->ops = default_file_operations; - return f->ops.read_at(f->fd, buffer, size, offset, bytes_read, false); -} - -inline gen_b32 gen_file_write(gen_FileInfo* f, void const* buffer, gen_ssize size) -{ - gen_s64 cur_offset = gen_file_tell(f); - gen_b32 result = gen_file_write_at(f, buffer, size, gen_file_tell(f)); - - gen_file_seek(f, cur_offset + size); - - return result; -} - -inline gen_b32 gen_file_write_at(gen_FileInfo* f, void const* buffer, gen_ssize size, gen_s64 offset) -{ - return gen_file_write_at_check(f, buffer, size, offset, NULL); -} - -inline gen_b32 gen_file_write_at_check(gen_FileInfo* f, void const* buffer, gen_ssize size, gen_s64 offset, gen_ssize* bytes_written) -{ - if (! f->ops.read_at) - f->ops = default_file_operations; - - return f->ops.write_at(f->fd, buffer, size, offset, bytes_written); -} - -#pragma endregion File Handling - -#pragma region Timing - -#ifdef GEN_BENCHMARK -//! Return CPU timestamp. -GEN_API gen_u64 gen_read_cpu_time_stamp_counter( void ); - -//! Return relative time (in seconds) since the application start. -GEN_API gen_f64 gen_time_rel( void ); - -//! Return relative time since the application start. -GEN_API gen_u64 gen_time_rel_ms( void ); -#endif - -#pragma endregion Timing - -#pragma region ADT - -struct gen_ADT_Node; -typedef struct gen_ADT_Node gen_ADT_Node; -typedef gen_ADT_Node* gen_Array_gen_ADT_Node; - -enum gen_ADT_Type gen_enum_underlying(gen_u32) -{ - EADT_TYPE_UNINITIALISED, /* node was not initialised, this is a programming error! */ - EADT_TYPE_ARRAY, - EADT_TYPE_OBJECT, - EADT_TYPE_STRING, - EADT_TYPE_MULTISTRING, - EADT_TYPE_INTEGER, - EADT_TYPE_REAL, -}; - -typedef gen_u32 gen_ADT_Type; - -enum gen_ADT_Props gen_enum_underlying(gen_u32) -{ - EADT_PROPS_NONE, - EADT_PROPS_NAN, - EADT_PROPS_NAN_NEG, - EADT_PROPS_INFINITY, - EADT_PROPS_INFINITY_NEG, - EADT_PROPS_FALSE, - EADT_PROPS_TRUE, - EADT_PROPS_NULL, - EADT_PROPS_IS_EXP, - EADT_PROPS_IS_HEX, // Used internally so that people can fill in real numbers they plan to write. - EADT_PROPS_IS_PARSED_REAL, -}; - -typedef gen_u32 gen_ADT_Props; - -enum gen_ADT_NamingStyle gen_enum_underlying(gen_u32) -{ - EADT_NAME_STYLE_DOUBLE_QUOTE, - EADT_NAME_STYLE_SINGLE_QUOTE, - EADT_NAME_STYLE_NO_QUOTES, -}; - -typedef gen_u32 gen_ADT_NamingStyle; - -enum gen_ADT_AssignStyle gen_enum_underlying(gen_u32) -{ - EADT_ASSIGN_STYLE_COLON, - EADT_ASSIGN_STYLE_EQUALS, - EADT_ASSIGN_STYLE_LINE, -}; - -typedef gen_u32 gen_ADT_AssignStyle; - -enum gen_ADT_DelimStyle gen_enum_underlying(gen_u32) -{ - EADT_DELIM_STYLE_COMMA, - EADT_DELIM_STYLE_LINE, - EADT_DELIM_STYLE_NEWLINE, -}; - -typedef gen_u32 gen_ADT_DelimStyle; - -enum gen_ADT_Error gen_enum_underlying(gen_u32) -{ - EADT_ERROR_NONE, - EADT_ERROR_INTERNAL, - EADT_ERROR_ALREADY_CONVERTED, - EADT_ERROR_INVALID_TYPE, - EADT_ERROR_OUT_OF_MEMORY, -}; - -typedef gen_u32 gen_ADT_Error; - -struct gen_ADT_Node -{ - char const* name; - struct gen_ADT_Node* parent; - - /* properties */ - gen_ADT_Type type : 4; - gen_u8 props : 4; -#ifndef GEN_PARSER_DISABLE_ANALYSIS - gen_u8 cfg_mode : 1; - gen_u8 name_style : 2; - gen_u8 assign_style : 2; - gen_u8 delim_style : 2; - gen_u8 delim_line_width : 4; - gen_u8 assign_line_width : 4; -#endif - - /* adt data */ - union - { - char const* string; - gen_Array(gen_ADT_Node) nodes; ///< zpl_array - - struct - { - union - { - gen_f64 real; - gen_s64 integer; - }; - -#ifndef GEN_PARSER_DISABLE_ANALYSIS - /* number analysis */ - gen_s32 base; - gen_s32 base2; - gen_u8 base2_offset : 4; - gen_s8 exp : 4; - gen_u8 neg_zero : 1; - gen_u8 lead_digit : 1; -#endif - }; - }; -}; - -#pragma region gen_Array_gen_ADT_Node - -#define GEN_GENERIC_SLOT_5__array_init gen_ADT_Node, gen_Array_gen_ADT_Node_init -#define GEN_GENERIC_SLOT_5__array_init_reserve gen_ADT_Node, gen_Array_gen_ADT_Node_init_reserve -#define GEN_GENERIC_SLOT_5__array_append gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_append -#define GEN_GENERIC_SLOT_5__array_append_items gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_append_items -#define GEN_GENERIC_SLOT_5__array_append_at gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_append_at -#define GEN_GENERIC_SLOT_5__array_append_items_at gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_append_items_at -#define GEN_GENERIC_SLOT_5__array_back gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_back -#define GEN_GENERIC_SLOT_5__array_clear gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_clear -#define GEN_GENERIC_SLOT_5__array_fill gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_fill -#define GEN_GENERIC_SLOT_5__array_free gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_free -#define GEN_GENERIC_SLOT_5__array_grow gen_Array_gen_ADT_Node*, gen_Array_gen_ADT_Node_grow -#define GEN_GENERIC_SLOT_5__array_num gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_num -#define GEN_GENERIC_SLOT_5__array_pop gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_pop -#define GEN_GENERIC_SLOT_5__array_remove_at gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_remove_at -#define GEN_GENERIC_SLOT_5__array_reserve gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_reserve -#define GEN_GENERIC_SLOT_5__array_resize gen_Array_gen_ADT_Node, gen_Array_gen_ADT_Node_resize -#define GEN_GENERIC_SLOT_5__array_set_capacity gen_Array_gen_ADT_Node*, gen_Array_gen_ADT_Node_set_capacity - -gen_Array_gen_ADT_Node gen_Array_gen_ADT_Node_init(gen_AllocatorInfo allocator); -gen_Array_gen_ADT_Node gen_Array_gen_ADT_Node_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity); -bool gen_Array_gen_ADT_Node_append_array(gen_Array_gen_ADT_Node* self, gen_Array_gen_ADT_Node other); -bool gen_Array_gen_ADT_Node_append(gen_Array_gen_ADT_Node* self, gen_ADT_Node value); -bool gen_Array_gen_ADT_Node_append_items(gen_Array_gen_ADT_Node* self, gen_ADT_Node* items, gen_usize item_num); -bool gen_Array_gen_ADT_Node_append_at(gen_Array_gen_ADT_Node* self, gen_ADT_Node item, gen_usize idx); -bool gen_Array_gen_ADT_Node_append_items_at(gen_Array_gen_ADT_Node* self, gen_ADT_Node* items, gen_usize item_num, gen_usize idx); -gen_ADT_Node* gen_Array_gen_ADT_Node_back(gen_Array_gen_ADT_Node self); -void gen_Array_gen_ADT_Node_clear(gen_Array_gen_ADT_Node self); -bool gen_Array_gen_ADT_Node_fill(gen_Array_gen_ADT_Node self, gen_usize begin, gen_usize end, gen_ADT_Node value); -void gen_Array_gen_ADT_Node_free(gen_Array_gen_ADT_Node* self); -bool gen_Array_gen_ADT_Node_grow(gen_Array_gen_ADT_Node* self, gen_usize min_capacity); -gen_usize gen_Array_gen_ADT_Node_num(gen_Array_gen_ADT_Node self); -gen_ADT_Node gen_Array_gen_ADT_Node_pop(gen_Array_gen_ADT_Node self); -void gen_Array_gen_ADT_Node_remove_at(gen_Array_gen_ADT_Node self, gen_usize idx); -bool gen_Array_gen_ADT_Node_reserve(gen_Array_gen_ADT_Node* self, gen_usize new_capacity); -bool gen_Array_gen_ADT_Node_resize(gen_Array_gen_ADT_Node* self, gen_usize num); -bool gen_Array_gen_ADT_Node_set_capacity(gen_Array_gen_ADT_Node* self, gen_usize new_capacity); - -gen_forceinline gen_Array_gen_ADT_Node gen_Array_gen_ADT_Node_init(gen_AllocatorInfo allocator) -{ - size_t initial_size = gen_array_grow_formula(0); - return gen_array_init_reserve(gen_ADT_Node, allocator, initial_size); -} - -inline gen_Array_gen_ADT_Node gen_Array_gen_ADT_Node_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity) -{ - GEN_ASSERT(capacity > 0); - gen_ArrayHeader* header = gen_rcast(gen_ArrayHeader*, gen_alloc(allocator, sizeof(gen_ArrayHeader) + sizeof(gen_ADT_Node) * capacity)); - if (header == gen_nullptr) - return gen_nullptr; - header->Allocator = allocator; - header->Capacity = capacity; - header->Num = 0; - return gen_rcast(gen_ADT_Node*, header + 1); -} - -gen_forceinline bool gen_Array_gen_ADT_Node_append_array(gen_Array_gen_ADT_Node* self, gen_Array_gen_ADT_Node other) -{ - return gen_array_append_items(*self, (gen_Array_gen_ADT_Node)other, gen_Array_gen_ADT_Node_num(other)); -} - -inline bool gen_Array_gen_ADT_Node_append(gen_Array_gen_ADT_Node* self, gen_ADT_Node value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num == header->Capacity) - { - if (! gen_array_grow(self, header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - (*self)[header->Num] = value; - header->Num++; - return true; -} - -inline bool gen_Array_gen_ADT_Node_append_items(gen_Array_gen_ADT_Node* self, gen_ADT_Node* items, gen_usize item_num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(items != gen_nullptr); - GEN_ASSERT(item_num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num + item_num > header->Capacity) - { - if (! gen_array_grow(self, header->Capacity + item_num)) - return false; - header = gen_array_get_header(*self); - } - gen_mem_copy((*self) + header->Num, items, sizeof(gen_ADT_Node) * item_num); - header->Num += item_num; - return true; -} - -inline bool gen_Array_gen_ADT_Node_append_at(gen_Array_gen_ADT_Node* self, gen_ADT_Node item, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - idx = header->Num - 1; - if (idx < 0) - idx = 0; - if (header->Capacity < header->Num + 1) - { - if (! gen_array_grow(self, header->Capacity + 1)) - return false; - header = gen_array_get_header(*self); - } - gen_Array_gen_ADT_Node target = (*self) + idx; - gen_mem_move(target + 1, target, (header->Num - idx) * sizeof(gen_ADT_Node)); - header->Num++; - return true; -} - -inline bool gen_Array_gen_ADT_Node_append_items_at(gen_Array_gen_ADT_Node* self, gen_ADT_Node* items, gen_usize item_num, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - { - return gen_array_append_items(*self, items, item_num); - } - if (item_num > header->Capacity) - { - if (! gen_array_grow(self, item_num + header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - gen_ADT_Node* target = (*self) + idx + item_num; - gen_ADT_Node* src = (*self) + idx; - gen_mem_move(target, src, (header->Num - idx) * sizeof(gen_ADT_Node)); - gen_mem_copy(src, items, item_num * sizeof(gen_ADT_Node)); - header->Num += item_num; - return true; -} - -inline gen_ADT_Node* gen_Array_gen_ADT_Node_back(gen_Array_gen_ADT_Node self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - if (header->Num == 0) - return 0; - return self + header->Num - 1; -} - -inline void gen_Array_gen_ADT_Node_clear(gen_Array_gen_ADT_Node self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - header->Num = 0; -} - -inline bool gen_Array_gen_ADT_Node_fill(gen_Array_gen_ADT_Node self, gen_usize begin, gen_usize end, gen_ADT_Node value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(begin <= end); - gen_ArrayHeader* header = gen_array_get_header(self); - if (begin < 0 || end > header->Num) - return false; - for (gen_ssize idx = (gen_ssize)begin; idx < (gen_ssize)end; idx++) - self[idx] = value; - return true; -} - -inline void gen_Array_gen_ADT_Node_free(gen_Array_gen_ADT_Node* self) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_allocator_free(header->Allocator, header); - self = 0; -} - -inline bool gen_Array_gen_ADT_Node_grow(gen_Array_gen_ADT_Node* self, gen_usize min_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(min_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_usize new_capacity = gen_array_grow_formula(header->Capacity); - if (new_capacity < min_capacity) - new_capacity = min_capacity; - return gen_array_set_capacity(self, new_capacity); -} - -gen_forceinline gen_usize gen_Array_gen_ADT_Node_num(gen_Array_gen_ADT_Node self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_array_get_header(self)->Num; -} - -inline gen_ADT_Node gen_Array_gen_ADT_Node_pop(gen_Array_gen_ADT_Node self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(header->Num > 0); - gen_ADT_Node result = self[header->Num - 1]; - header->Num--; - return result; -} - -gen_forceinline void gen_Array_gen_ADT_Node_remove_at(gen_Array_gen_ADT_Node self, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(idx < header->Num); - gen_mem_move(self + idx, self + idx + 1, sizeof(gen_ADT_Node) * (header->Num - idx - 1)); - header->Num--; -} - -inline bool gen_Array_gen_ADT_Node_reserve(gen_Array_gen_ADT_Node* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < new_capacity) - return gen_array_set_capacity(self, new_capacity); - return true; -} - -inline bool gen_Array_gen_ADT_Node_resize(gen_Array_gen_ADT_Node* self, gen_usize num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < num) - { - if (! gen_array_grow(self, num)) - return false; - header = gen_array_get_header(*self); - } - header->Num = num; - return true; -} - -inline bool gen_Array_gen_ADT_Node_set_capacity(gen_Array_gen_ADT_Node* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (new_capacity == header->Capacity) - return true; - if (new_capacity < header->Num) - { - header->Num = new_capacity; - return true; - } - gen_usize size = sizeof(gen_ArrayHeader) + sizeof(gen_ADT_Node) * new_capacity; - gen_ArrayHeader* new_header = gen_cast(gen_ArrayHeader*, gen_alloc(header->Allocator, size)); - if (new_header == 0) - return false; - gen_mem_move(new_header, header, sizeof(gen_ArrayHeader) + sizeof(gen_ADT_Node) * header->Num); - new_header->Capacity = new_capacity; - gen_allocator_free(header->Allocator, &header); - *self = gen_cast(gen_ADT_Node*, new_header + 1); - return true; -} - -#pragma endregion gen_Array_gen_ADT_Node - - - -/* ADT NODE LIMITS - * delimiter and assignment segment width is limited to 128 whitespace symbols each. - * real number limits decimal position to 128 places. - * real number exponent is limited to 64 digits. - */ - -/** - * @brief Initialise an ADT object or array - * - * @param node - * @param backing Memory allocator used for descendants - * @param name Node's name - * @param is_array - * @return error code - */ -GEN_API gen_u8 gen_adt_make_branch(gen_ADT_Node* node, gen_AllocatorInfo backing, char const* name, gen_b32 is_array); - -/** - * @brief Destroy an ADT branch and its descendants - * - * @param node - * @return error code - */ -GEN_API gen_u8 gen_adt_destroy_branch(gen_ADT_Node* node); - -/** - * @brief Initialise an ADT leaf - * - * @param node - * @param name Node's name - * @param type Node's type (use zpl_adt_make_branch for container nodes) - * @return error code - */ -GEN_API gen_u8 gen_adt_make_leaf(gen_ADT_Node* node, char const* name, gen_ADT_Type type); - - -/** - * @brief Fetch a node using provided URI string. - * - * This method uses a basic syntax to fetch a node from the ADT. The following features are available - * to retrieve the data: - * - * - "a/b/c" navigates through objects "a" and "b" to get to "c" - * - "arr/[foo=123]/bar" iterates over "arr" to find any object with param "foo" that matches the value "123", then gets its field called "bar" - * - "arr/3" retrieves the 4th element in "arr" - * - "arr/[apple]" retrieves the first element of value "apple" in "arr" - * - * @param node ADT node - * @param uri Locator string as described above - * @return zpl_adt_node* - * - * @see code/apps/examples/json_get.c - */ -GEN_API gen_ADT_Node* gen_adt_query(gen_ADT_Node* node, char const* uri); - -/** - * @brief Find a field node within an object by the given name. - * - * @param node - * @param name - * @param deep_search Perform search recursively - * @return zpl_adt_node * node - */ -GEN_API gen_ADT_Node* gen_adt_find(gen_ADT_Node* node, char const* name, gen_b32 deep_search); - -/** - * @brief Allocate an unitialised node within a container at a specified index. - * - * @param parent - * @param index - * @return zpl_adt_node * node - */ -GEN_API gen_ADT_Node* gen_adt_alloc_at(gen_ADT_Node* parent, gen_ssize index); - -/** - * @brief Allocate an unitialised node within a container. - * - * @param parent - * @return zpl_adt_node * node - */ -GEN_API gen_ADT_Node* gen_adt_alloc(gen_ADT_Node* parent); - -/** - * @brief Move an existing node to a new container at a specified index. - * - * @param node - * @param new_parent - * @param index - * @return zpl_adt_node * node - */ -GEN_API gen_ADT_Node* gen_adt_move_node_at(gen_ADT_Node* node, gen_ADT_Node* new_parent, gen_ssize index); - -/** - * @brief Move an existing node to a new container. - * - * @param node - * @param new_parent - * @return zpl_adt_node * node - */ -GEN_API gen_ADT_Node* gen_adt_move_node(gen_ADT_Node* node, gen_ADT_Node* new_parent); - -/** - * @brief Swap two nodes. - * - * @param node - * @param other_node - * @return - */ -GEN_API void gen_adt_swap_nodes(gen_ADT_Node* node, gen_ADT_Node* other_node); - -/** - * @brief Remove node from container. - * - * @param node - * @return - */ -GEN_API void gen_adt_remove_node(gen_ADT_Node* node); - -/** - * @brief Initialise a node as an object - * - * @param obj - * @param name - * @param backing - * @return - */ -GEN_API gen_b8 gen_adt_set_obj(gen_ADT_Node* obj, char const* name, gen_AllocatorInfo backing); - -/** - * @brief Initialise a node as an array - * - * @param obj - * @param name - * @param backing - * @return - */ -GEN_API gen_b8 gen_adt_set_arr(gen_ADT_Node* obj, char const* name, gen_AllocatorInfo backing); - -/** - * @brief Initialise a node as a string - * - * @param obj - * @param name - * @param value - * @return - */ -GEN_API gen_b8 gen_adt_set_str(gen_ADT_Node* obj, char const* name, char const* value); - -/** - * @brief Initialise a node as a float - * - * @param obj - * @param name - * @param value - * @return - */ -GEN_API gen_b8 gen_adt_set_flt(gen_ADT_Node* obj, char const* name, gen_f64 value); - -/** - * @brief Initialise a node as a signed integer - * - * @param obj - * @param name - * @param value - * @return - */ -GEN_API gen_b8 gen_adt_set_int(gen_ADT_Node* obj, char const* name, gen_s64 value); - -/** - * @brief Append a new node to a container as an object - * - * @param parent - * @param name - * @return* - */ -GEN_API gen_ADT_Node* gen_adt_append_obj(gen_ADT_Node* parent, char const* name); - -/** - * @brief Append a new node to a container as an array - * - * @param parent - * @param name - * @return* - */ -GEN_API gen_ADT_Node* gen_adt_append_arr(gen_ADT_Node* parent, char const* name); - -/** - * @brief Append a new node to a container as a string - * - * @param parent - * @param name - * @param value - * @return* - */ -GEN_API gen_ADT_Node* gen_adt_append_str(gen_ADT_Node* parent, char const* name, char const* value); - -/** - * @brief Append a new node to a container as a float - * - * @param parent - * @param name - * @param value - * @return* - */ -GEN_API gen_ADT_Node* gen_adt_append_flt(gen_ADT_Node* parent, char const* name, gen_f64 value); - -/** - * @brief Append a new node to a container as a signed integer - * - * @param parent - * @param name - * @param value - * @return* - */ -GEN_API gen_ADT_Node* gen_adt_append_int(gen_ADT_Node* parent, char const* name, gen_s64 value); - -/* parser helpers */ - -/** - * @brief Parses a text and stores the result into an unitialised node. - * - * @param node - * @param base - * @return* - */ -GEN_API char* gen_adt_parse_number(gen_ADT_Node* node, char* base); - -/** - * @brief Parses a text and stores the result into an unitialised node. - * This function expects the entire input to be a number. - * - * @param node - * @param base - * @return* - */ -GEN_API char* gen_adt_parse_number_strict(gen_ADT_Node* node, char* base_str); - -/** - * @brief Parses and converts an existing string node into a number. - * - * @param node - * @return - */ -GEN_API gen_ADT_Error gen_adt_c_str_to_number(gen_ADT_Node* node); - -/** - * @brief Parses and converts an existing string node into a number. - * This function expects the entire input to be a number. - * - * @param node - * @return - */ -GEN_API gen_ADT_Error gen_adt_c_str_to_number_strict(gen_ADT_Node* node); - -/** - * @brief Prints a number into a file stream. - * - * The provided file handle can also be a memory mapped stream. - * - * @see zpl_file_stream_new - * @param file - * @param node - * @return - */ -GEN_API gen_ADT_Error gen_adt_print_number(gen_FileInfo* file, gen_ADT_Node* node); - -/** - * @brief Prints a string into a file stream. - * - * The provided file handle can also be a memory mapped stream. - * - * @see zpl_file_stream_new - * @param file - * @param node - * @param escaped_chars - * @param escape_symbol - * @return - */ -GEN_API gen_ADT_Error gen_adt_print_string(gen_FileInfo* file, gen_ADT_Node* node, char const* escaped_chars, char const* escape_symbol); - -#pragma endregion ADT - -struct gen_ADT_Node; -typedef struct gen_ADT_Node gen_ADT_Node; - -enum gen_CSV_Error gen_enum_underlying(gen_u32) -{ - ECSV_Error__NONE, - ECSV_Error__INTERNAL, - ECSV_Error__UNEXPECTED_END_OF_INPUT, - ECSV_Error__MISMATCHED_ROWS, -}; - -typedef gen_u32 gen_CSV_Error; - -typedef gen_ADT_Node gen_CSV_Object; - -gen_u8 gen_csv_parse(gen_CSV_Object* root, char* text, gen_AllocatorInfo allocator, gen_b32 has_header); -GEN_API gen_u8 gen_csv_parse_delimiter(gen_CSV_Object* root, char* text, gen_AllocatorInfo allocator, gen_b32 has_header, char delim); -void gen_csv_free(gen_CSV_Object* obj); - -void gen_csv_write(gen_FileInfo* file, gen_CSV_Object* obj); -gen_StrBuilder gen_csv_write_string(gen_AllocatorInfo a, gen_CSV_Object* obj); -GEN_API void gen_csv_write_delimiter(gen_FileInfo* file, gen_CSV_Object* obj, char delim); -GEN_API gen_StrBuilder gen_csv_write_strbuilder_delimiter(gen_AllocatorInfo a, gen_CSV_Object* obj, char delim); - -/* inline */ - -inline gen_u8 gen_csv_parse(gen_CSV_Object* root, char* text, gen_AllocatorInfo allocator, gen_b32 has_header) -{ - return gen_csv_parse_delimiter(root, text, allocator, has_header, ','); -} - -inline void gen_csv_write(gen_FileInfo* file, gen_CSV_Object* obj) -{ - gen_csv_write_delimiter(file, obj, ','); -} - -inline gen_StrBuilder gen_csv_write_string(gen_AllocatorInfo a, gen_CSV_Object* obj) -{ - return gen_csv_write_strbuilder_delimiter(a, obj, ','); -} - -GEN_API_C_END -GEN_NS_END - -// GEN_ROLL_OWN_DEPENDENCIES -#endif - -GEN_NS_BEGIN -GEN_API_C_BEGIN - -#pragma region Types - -/* - ________ __ __ ________ -| \ | \ | \ | \ -| ▓▓▓▓▓▓▓▓_______ __ __ ______ ____ _______ | ▓▓\ | ▓▓ \▓▓▓▓▓▓▓▓__ __ ______ ______ _______ -| ▓▓__ | \| \ | \ \ \ / \ | ▓▓▓\| ▓▓ | ▓▓ | \ | \/ \ / \ / \ -| ▓▓ \ | ▓▓▓▓▓▓▓\ ▓▓ | ▓▓ ▓▓▓▓▓▓\▓▓▓▓\ ▓▓▓▓▓▓▓ | ▓▓▓▓\ ▓▓ | ▓▓ | ▓▓ | ▓▓ ▓▓▓▓▓▓\ ▓▓▓▓▓▓\ ▓▓▓▓▓▓▓ -| ▓▓▓▓▓ | ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓ | ▓▓ | ▓▓\▓▓ \ | ▓▓\▓▓ ▓▓ | ▓▓ | ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓ ▓▓\▓▓ \ -| ▓▓_____| ▓▓ | ▓▓ ▓▓__/ ▓▓ ▓▓ | ▓▓ | ▓▓_\▓▓▓▓▓▓\ | ▓▓ \▓▓▓▓ | ▓▓ | ▓▓__/ ▓▓ ▓▓__/ ▓▓ ▓▓▓▓▓▓▓▓_\▓▓▓▓▓▓\ -| ▓▓ \ ▓▓ | ▓▓\▓▓ ▓▓ ▓▓ | ▓▓ | ▓▓ ▓▓ | ▓▓ \▓▓▓ | ▓▓ \▓▓ ▓▓ ▓▓ ▓▓\▓▓ \ ▓▓ - \▓▓▓▓▓▓▓▓\▓▓ \▓▓ \▓▓▓▓▓▓ \▓▓ \▓▓ \▓▓\▓▓▓▓▓▓▓ \▓▓ \▓▓ \▓▓ _\▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓\▓▓▓▓▓▓▓ - | \__| ▓▓ ▓▓ - \▓▓ ▓▓ ▓▓ - \▓▓▓▓▓▓ \▓▓ - -*/ - -enum LogLevel -{ - LL_Null, - LL_Note, - LL_Warning, - LL_Error, - LL_Fatal, - LL_UnderlyingType = GEN_U32_MAX, -}; -typedef enum LogLevel LogLevel; -typedef enum LogLevel LogLevel; - -gen_Str loglevel_to_str(LogLevel level) -{ - gen_local_persist gen_Str lookup[] = { - { "Null", sizeof("Null") - 1 }, - { "Note", sizeof("Note") - 1 }, - { "Warning", sizeof("Info") - 1 }, - { "Error", sizeof("Error") - 1 }, - { "Fatal", sizeof("Fatal") - 1 }, - }; - return lookup[level]; -} - -typedef struct LogEntry LogEntry; - -struct LogEntry -{ - gen_Str msg; - LogLevel level; -}; - -typedef void LoggerProc(LogEntry entry); - -// By default this library will either crash or exit if an error is detected while generating codes. -// Even if set to not use GEN_FATAL, GEN_FATAL will still be used for memory failures as the library is unusable when they occur. -#ifdef GEN_DONT_USE_FATAL - -#define gen_log_failure gen_log_fmt -#else -#define gen_log_failure GEN_FATAL -#endif - -enum gen_AccessSpec gen_enum_underlying(gen_u32) -{ - AccessSpec_Default, - AccessSpec_Private, - AccessSpec_Protected, - AccessSpec_Public, - AccessSpec_Num_AccessSpec, - AccessSpec_Invalid, - AccessSpec_SizeDef = GEN_U32_MAX, -}; - -typedef gen_u32 gen_AccessSpec; -gen_static_assert(gen_size_of(gen_AccessSpec) == gen_size_of(gen_u32), "gen_AccessSpec not gen_u32 size"); - -inline gen_Str gen_access_spec_to_str(gen_AccessSpec type) -{ - gen_local_persist gen_Str lookup[(gen_u32)AccessSpec_Num_AccessSpec] = { - { "", sizeof("") - 1 }, - { "private", sizeof("prviate") - 1 }, - { "private", sizeof("protected") - 1 }, - { "public", sizeof("public") - 1 }, - }; - - gen_Str invalid = { "Invalid", sizeof("Invalid") - 1 }; - if (type > AccessSpec_Public) - return invalid; - - return lookup[(gen_u32)type]; -} - -enum gen_CodeFlag gen_enum_underlying(gen_u32) -{ - CodeFlag_None = 0, - CodeFlag_FunctionType = gen_bit(0), - CodeFlag_ParamPack = gen_bit(1), - CodeFlag_Module_Export = gen_bit(2), - CodeFlag_Module_Import = gen_bit(3), - CodeFlag_SizeDef = GEN_U32_MAX, -}; - -typedef gen_u32 gen_CodeFlag; -gen_static_assert(gen_size_of(gen_CodeFlag) == gen_size_of(gen_u32), "gen_CodeFlag not gen_u32 size"); - -// Used to indicate if enum definitoin is an enum class or regular enum. -enum gen_EnumDecl gen_enum_underlying(gen_u8) -{ - EnumDecl_Regular, - EnumDecl_Class, - EnumT_SizeDef = GEN_U8_MAX, -}; - -typedef gen_u8 gen_EnumDecl; -typedef gen_u8 EnumT; - -enum gen_ModuleFlag gen_enum_underlying(gen_u32) -{ - ModuleFlag_None = 0, - ModuleFlag_Export = gen_bit(0), - ModuleFlag_Import = gen_bit(1), - Num_ModuleFlags, - ModuleFlag_Invalid, - ModuleFlag_SizeDef = GEN_U32_MAX, -}; - -typedef gen_u32 gen_ModuleFlag; -gen_static_assert(gen_size_of(gen_ModuleFlag) == gen_size_of(gen_u32), "gen_ModuleFlag not gen_u32 size"); - -inline gen_Str gen_module_flag_to_str(gen_ModuleFlag flag) -{ - gen_local_persist gen_Str lookup[(gen_u32)Num_ModuleFlags] = { - { "__none__", sizeof("__none__") - 1 }, - { "export", sizeof("export") - 1 }, - { "import", sizeof("import") - 1 }, - }; - - gen_local_persist gen_Str invalid_flag = { "invalid", sizeof("invalid") }; - if (flag > ModuleFlag_Import) - return invalid_flag; - - return lookup[(gen_u32)flag]; -} - -enum gen_EPreprocessCOnd gen_enum_underlying(gen_u32) -{ - PreprocessCond_If, - PreprocessCond_IfDef, - PreprocessCond_IfNotDef, - PreprocessCond_ElIf, - EPreprocessCond_SizeDef = GEN_U32_MAX, -}; - -typedef gen_u32 gen_EPreprocessCOnd; -gen_static_assert(gen_size_of(gen_EPreprocessCOnd) == gen_size_of(gen_u32), "gen_EPreprocessCOnd not gen_u32 size"); - -enum gen_ETypenameTag gen_enum_underlying(gen_u16) -{ - Tag_None, - Tag_Class, - Tag_Enum, - Tag_Struct, - Tag_Union, - Tag_UnderlyingType = GEN_U16_MAX, -}; - -typedef gen_u16 gen_ETypenameTag; -gen_static_assert(gen_size_of(gen_ETypenameTag) == gen_size_of(gen_u16), "gen_ETypenameTag is not gen_u16 size"); - -enum gen_CodeType gen_enum_underlying(gen_u32) -{ - CT_Invalid, - CT_Untyped, - CT_NewLine, - CT_Comment, - CT_Access_Private, - CT_Access_Protected, - CT_Access_Public, - CT_PlatformAttributes, - CT_Class, - CT_Class_Fwd, - CT_Class_Body, - CT_Constructor, - CT_Constructor_Fwd, - CT_Destructor, - CT_Destructor_Fwd, - CT_Enum, - CT_Enum_Fwd, - CT_Enum_Body, - CT_Enum_Class, - CT_Enum_Class_Fwd, - CT_Execution, - CT_Export_Body, - CT_Extern_Linkage, - CT_Extern_Linkage_Body, - CT_Friend, - CT_Function, - CT_Function_Fwd, - CT_Function_Body, - CT_Global_Body, - CT_Module, - CT_Namespace, - CT_Namespace_Body, - CT_Operator, - CT_Operator_Fwd, - CT_Operator_Member, - CT_Operator_Member_Fwd, - CT_Operator_Cast, - CT_Operator_Cast_Fwd, - CT_Parameters, - CT_Parameters_Define, - CT_Preprocess_Define, - CT_Preprocess_Include, - CT_Preprocess_If, - CT_Preprocess_IfDef, - CT_Preprocess_IfNotDef, - CT_Preprocess_ElIf, - CT_Preprocess_Else, - CT_Preprocess_EndIf, - CT_Preprocess_Pragma, - CT_Specifiers, - CT_Struct, - CT_Struct_Fwd, - CT_Struct_Body, - CT_Template, - CT_Typedef, - CT_Typename, - CT_Union, - CT_Union_Fwd, - CT_Union_Body, - CT_Using, - CT_Using_Namespace, - CT_Variable, - CT_NumTypes, - CT_UnderlyingType = GEN_U32_MAX -}; -typedef enum gen_CodeType gen_CodeType; - -inline gen_Str gen_codetype_to_str(gen_CodeType type) -{ - gen_local_persist gen_Str lookup[] = { - { "Invalid", sizeof("Invalid") - 1 }, - { "Untyped", sizeof("Untyped") - 1 }, - { "NewLine", sizeof("NewLine") - 1 }, - { "Comment", sizeof("Comment") - 1 }, - { "Access_Private", sizeof("Access_Private") - 1 }, - { "Access_Protected", sizeof("Access_Protected") - 1 }, - { "Access_Public", sizeof("Access_Public") - 1 }, - { "PlatformAttributes", sizeof("PlatformAttributes") - 1 }, - { "Class", sizeof("Class") - 1 }, - { "Class_Fwd", sizeof("Class_Fwd") - 1 }, - { "Class_Body", sizeof("Class_Body") - 1 }, - { "Constructor", sizeof("Constructor") - 1 }, - { "Constructor_Fwd", sizeof("Constructor_Fwd") - 1 }, - { "Destructor", sizeof("Destructor") - 1 }, - { "Destructor_Fwd", sizeof("Destructor_Fwd") - 1 }, - { "Enum", sizeof("Enum") - 1 }, - { "Enum_Fwd", sizeof("Enum_Fwd") - 1 }, - { "Enum_Body", sizeof("Enum_Body") - 1 }, - { "Enum_Class", sizeof("Enum_Class") - 1 }, - { "Enum_Class_Fwd", sizeof("Enum_Class_Fwd") - 1 }, - { "Execution", sizeof("Execution") - 1 }, - { "Export_Body", sizeof("Export_Body") - 1 }, - { "Extern_Linkage", sizeof("Extern_Linkage") - 1 }, - { "Extern_Linkage_Body", sizeof("Extern_Linkage_Body") - 1 }, - { "Friend", sizeof("Friend") - 1 }, - { "Function", sizeof("Function") - 1 }, - { "Function_Fwd", sizeof("Function_Fwd") - 1 }, - { "Function_Body", sizeof("Function_Body") - 1 }, - { "Global_Body", sizeof("Global_Body") - 1 }, - { "Module", sizeof("Module") - 1 }, - { "Namespace", sizeof("Namespace") - 1 }, - { "Namespace_Body", sizeof("Namespace_Body") - 1 }, - { "gen_Operator", sizeof("gen_Operator") - 1 }, - { "Operator_Fwd", sizeof("Operator_Fwd") - 1 }, - { "Operator_Member", sizeof("Operator_Member") - 1 }, - { "Operator_Member_Fwd", sizeof("Operator_Member_Fwd") - 1 }, - { "Operator_Cast", sizeof("Operator_Cast") - 1 }, - { "Operator_Cast_Fwd", sizeof("Operator_Cast_Fwd") - 1 }, - { "Parameters", sizeof("Parameters") - 1 }, - { "Parameters_Define", sizeof("Parameters_Define") - 1 }, - { "Preprocess_Define", sizeof("Preprocess_Define") - 1 }, - { "Preprocess_Include", sizeof("Preprocess_Include") - 1 }, - { "Preprocess_If", sizeof("Preprocess_If") - 1 }, - { "Preprocess_IfDef", sizeof("Preprocess_IfDef") - 1 }, - { "Preprocess_IfNotDef", sizeof("Preprocess_IfNotDef") - 1 }, - { "Preprocess_ElIf", sizeof("Preprocess_ElIf") - 1 }, - { "Preprocess_Else", sizeof("Preprocess_Else") - 1 }, - { "Preprocess_EndIf", sizeof("Preprocess_EndIf") - 1 }, - { "Preprocess_Pragma", sizeof("Preprocess_Pragma") - 1 }, - { "Specifiers", sizeof("Specifiers") - 1 }, - { "Struct", sizeof("Struct") - 1 }, - { "Struct_Fwd", sizeof("Struct_Fwd") - 1 }, - { "Struct_Body", sizeof("Struct_Body") - 1 }, - { "Template", sizeof("Template") - 1 }, - { "Typedef", sizeof("Typedef") - 1 }, - { "Typename", sizeof("Typename") - 1 }, - { "Union", sizeof("Union") - 1 }, - { "Union_Fwd", sizeof("Union_Fwd") - 1 }, - { "Union_Body", sizeof("Union_Body") - 1 }, - { "Using", sizeof("Using") - 1 }, - { "Using_Namespace", sizeof("Using_Namespace") - 1 }, - { "Variable", sizeof("Variable") - 1 }, - }; - return lookup[type]; -} - -inline gen_Str gen_codetype_to_keyword_str(gen_CodeType type) -{ - gen_local_persist gen_Str lookup[] = { - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "//", sizeof("//") - 1 }, - { "private", sizeof("private") - 1 }, - { "protected", sizeof("protected") - 1 }, - { "public", sizeof("public") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "class", sizeof("class") - 1 }, - { "clsss", sizeof("clsss") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "enum", sizeof("enum") - 1 }, - { "enum", sizeof("enum") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "enum class", sizeof("enum class") - 1 }, - { "enum class", sizeof("enum class") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "extern", sizeof("extern") - 1 }, - { "extern", sizeof("extern") - 1 }, - { "friend", sizeof("friend") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "module", sizeof("module") - 1 }, - { "namespace", sizeof("namespace") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "operator", sizeof("operator") - 1 }, - { "operator", sizeof("operator") - 1 }, - { "operator", sizeof("operator") - 1 }, - { "operator", sizeof("operator") - 1 }, - { "operator", sizeof("operator") - 1 }, - { "operator", sizeof("operator") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "define", sizeof("define") - 1 }, - { "include", sizeof("include") - 1 }, - { "if", sizeof("if") - 1 }, - { "ifdef", sizeof("ifdef") - 1 }, - { "ifndef", sizeof("ifndef") - 1 }, - { "elif", sizeof("elif") - 1 }, - { "else", sizeof("else") - 1 }, - { "endif", sizeof("endif") - 1 }, - { "pragma", sizeof("pragma") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "struct", sizeof("struct") - 1 }, - { "struct", sizeof("struct") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "template", sizeof("template") - 1 }, - { "typedef", sizeof("typedef") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "union", sizeof("union") - 1 }, - { "union", sizeof("union") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - { "using", sizeof("using") - 1 }, - { "using namespace", sizeof("using namespace") - 1 }, - { "__NA__", sizeof("__NA__") - 1 }, - }; - return lookup[type]; -} - -enum gen_Operator gen_enum_underlying(gen_u32) -{ - Op_Invalid, - Op_Assign, - Op_Assign_Add, - Op_Assign_Subtract, - Op_Assign_Multiply, - Op_Assign_Divide, - Op_Assign_Modulo, - Op_Assign_BAnd, - Op_Assign_BOr, - Op_Assign_BXOr, - Op_Assign_LShift, - Op_Assign_RShift, - Op_Increment, - Op_Decrement, - Op_Unary_Plus, - Op_Unary_Minus, - Op_UnaryNot, - Op_Add, - Op_Subtract, - Op_Multiply, - Op_Divide, - Op_Modulo, - Op_BNot, - Op_BAnd, - Op_BOr, - Op_BXOr, - Op_LShift, - Op_RShift, - Op_LAnd, - Op_LOr, - Op_LEqual, - Op_LNot, - Op_Lesser, - Op_Greater, - Op_LesserEqual, - Op_GreaterEqual, - Op_Subscript, - Op_Indirection, - Op_AddressOf, - Op_MemberOfPointer, - Op_PtrToMemOfPtr, - Op_FunctionCall, - Op_Comma, - Op_New, - Op_NewArray, - Op_Delete, - Op_DeleteArray, - Op_NumOps, - Op_UnderlyingType = 0xffffffffu -}; -typedef enum gen_Operator gen_Operator; - -inline gen_Str gen_operator_to_str(gen_Operator op) -{ - gen_local_persist gen_Str lookup[] = { - { "INVALID", sizeof("INVALID") - 1 }, - { "=", sizeof("=") - 1 }, - { "+=", sizeof("+=") - 1 }, - { "-=", sizeof("-=") - 1 }, - { "*=", sizeof("*=") - 1 }, - { "/=", sizeof("/=") - 1 }, - { "%=", sizeof("%=") - 1 }, - { "&=", sizeof("&=") - 1 }, - { "|=", sizeof("|=") - 1 }, - { "^=", sizeof("^=") - 1 }, - { "<<=", sizeof("<<=") - 1 }, - { ">>=", sizeof(">>=") - 1 }, - { "++", sizeof("++") - 1 }, - { "--", sizeof("--") - 1 }, - { "+", sizeof("+") - 1 }, - { "-", sizeof("-") - 1 }, - { "!", sizeof("!") - 1 }, - { "+", sizeof("+") - 1 }, - { "-", sizeof("-") - 1 }, - { "*", sizeof("*") - 1 }, - { "/", sizeof("/") - 1 }, - { "%", sizeof("%") - 1 }, - { "~", sizeof("~") - 1 }, - { "&", sizeof("&") - 1 }, - { "|", sizeof("|") - 1 }, - { "^", sizeof("^") - 1 }, - { "<<", sizeof("<<") - 1 }, - { ">>", sizeof(">>") - 1 }, - { "&&", sizeof("&&") - 1 }, - { "||", sizeof("||") - 1 }, - { "==", sizeof("==") - 1 }, - { "!=", sizeof("!=") - 1 }, - { "<", sizeof("<") - 1 }, - { ">", sizeof(">") - 1 }, - { "<=", sizeof("<=") - 1 }, - { ">=", sizeof(">=") - 1 }, - { "[]", sizeof("[]") - 1 }, - { "*", sizeof("*") - 1 }, - { "&", sizeof("&") - 1 }, - { "->", sizeof("->") - 1 }, - { "->*", sizeof("->*") - 1 }, - { "()", sizeof("()") - 1 }, - { ",", sizeof(",") - 1 }, - { "new", sizeof("new") - 1 }, - { "new[]", sizeof("new[]") - 1 }, - { "delete", sizeof("delete") - 1 }, - { "delete[]", sizeof("delete[]") - 1 }, - }; - return lookup[op]; -} - -enum gen_Specifier gen_enum_underlying(gen_u32) -{ - Spec_Invalid, - Spec_Consteval, - Spec_Constexpr, - Spec_Constinit, - Spec_Explicit, - Spec_External_Linkage, - Spec_ForceInline, - Spec_Global, - Spec_Inline, - Spec_Internal_Linkage, - Spec_Local_Persist, - Spec_Mutable, - Spec_NeverInline, - Spec_Ptr, - Spec_Ref, - Spec_Register, - Spec_Restrict, - Spec_RValue, - Spec_Static, - Spec_Thread_Local, - Spec_Virtual, - Spec_Const, - Spec_Final, - Spec_NoExceptions, - Spec_Override, - Spec_Pure, - Spec_Delete, - Spec_Volatile, - Spec_NumSpecifiers, - Spec_UnderlyingType = 0xffffffffu -}; -typedef enum gen_Specifier gen_Specifier; - -inline gen_Str gen_spec_to_str(gen_Specifier type) -{ - gen_local_persist gen_Str lookup[] = { - { "INVALID", sizeof("INVALID") - 1 }, - { "consteval", sizeof("consteval") - 1 }, - { "constexpr", sizeof("constexpr") - 1 }, - { "constinit", sizeof("constinit") - 1 }, - { "explicit", sizeof("explicit") - 1 }, - { "extern", sizeof("extern") - 1 }, - { "gen_forceinline", sizeof("gen_forceinline") - 1 }, - { "gen_global", sizeof("gen_global") - 1 }, - { "inline", sizeof("inline") - 1 }, - { "gen_internal", sizeof("gen_internal") - 1 }, - { "gen_local_persist", sizeof("gen_local_persist") - 1 }, - { "mutable", sizeof("mutable") - 1 }, - { "gen_neverinline", sizeof("gen_neverinline") - 1 }, - { "*", sizeof("*") - 1 }, - { "&", sizeof("&") - 1 }, - { "register", sizeof("register") - 1 }, - { "restrict", sizeof("restrict") - 1 }, - { "&&", sizeof("&&") - 1 }, - { "static", sizeof("static") - 1 }, - { "gen_thread_local", sizeof("gen_thread_local") - 1 }, - { "virtual", sizeof("virtual") - 1 }, - { "const", sizeof("const") - 1 }, - { "final", sizeof("final") - 1 }, - { "noexcept", sizeof("noexcept") - 1 }, - { "override", sizeof("override") - 1 }, - { "= 0", sizeof("= 0") - 1 }, - { "= delete", sizeof("= delete") - 1 }, - { "volatile", sizeof("volatile") - 1 }, - }; - return lookup[type]; -} - -inline bool gen_spec_is_trailing(gen_Specifier specifier) -{ - switch (specifier) - { - case Spec_Const: - case Spec_Final: - case Spec_NoExceptions: - case Spec_Override: - case Spec_Pure: - case Spec_Delete: - case Spec_Volatile: - return true; - default: - return false; - } -} - -inline gen_Specifier gen_str_to_specifier(gen_Str str) -{ - gen_local_persist gen_u32 keymap[Spec_NumSpecifiers]; - gen_do_once_start for (gen_u32 index = 0; index < Spec_NumSpecifiers; index++) - { - gen_Str gen_enum_str = gen_spec_to_str((gen_Specifier)index); - keymap[index] = gen_crc32(gen_enum_str.Ptr, gen_enum_str.Len); - } - gen_do_once_end gen_u32 gen_hash = gen_crc32(str.Ptr, str.Len); - for (gen_u32 index = 0; index < Spec_NumSpecifiers; index++) - { - if (keymap[index] == gen_hash) - return (gen_Specifier)index; - } - return Spec_Invalid; -} -#define GEN_DEFINE_ATTRIBUTE_TOKENS Entry(Tok_Attribute_GEN_API, "GEN_API") - -enum gen_TokType -{ - Tok_Invalid, - Tok_Access_Private, - Tok_Access_Protected, - Tok_Access_Public, - Tok_Access_MemberSymbol, - Tok_Access_StaticSymbol, - Tok_Ampersand, - Tok_Ampersand_DBL, - Tok_Assign_Classifer, - Tok_Attribute_Open, - Tok_Attribute_Close, - Tok_BraceCurly_Open, - Tok_BraceCurly_Close, - Tok_BraceSquare_Open, - Tok_BraceSquare_Close, - Tok_Paren_Open, - Tok_Paren_Close, - Tok_Comment, - Tok_Comment_End, - Tok_Comment_Start, - Tok_Char, - Tok_Comma, - Tok_Decl_Class, - Tok_Decl_GNU_Attribute, - Tok_Decl_MSVC_Attribute, - Tok_Decl_Enum, - Tok_Decl_Extern_Linkage, - Tok_Decl_Friend, - Tok_Decl_Module, - Tok_Decl_Namespace, - Tok_Decl_Operator, - Tok_Decl_Struct, - Tok_Decl_Template, - Tok_Decl_Typedef, - Tok_Decl_Using, - Tok_Decl_Union, - Tok_Identifier, - Tok_Module_Import, - Tok_Module_Export, - Tok_NewLine, - Tok_Number, - Tok_Operator, - Tok_Preprocess_Hash, - Tok_Preprocess_Define, - Tok_Preprocess_Define_Param, - Tok_Preprocess_If, - Tok_Preprocess_IfDef, - Tok_Preprocess_IfNotDef, - Tok_Preprocess_ElIf, - Tok_Preprocess_Else, - Tok_Preprocess_EndIf, - Tok_Preprocess_Include, - Tok_Preprocess_Pragma, - Tok_Preprocess_Content, - Tok_Preprocess_Macro_Expr, - Tok_Preprocess_Macro_Stmt, - Tok_Preprocess_Macro_Typename, - Tok_Preprocess_Unsupported, - Tok_Spec_Alignas, - Tok_Spec_Const, - Tok_Spec_Consteval, - Tok_Spec_Constexpr, - Tok_Spec_Constinit, - Tok_Spec_Explicit, - Tok_Spec_Extern, - Tok_Spec_Final, - Tok_Spec_ForceInline, - Tok_Spec_Global, - Tok_Spec_Inline, - Tok_Spec_Internal_Linkage, - Tok_Spec_LocalPersist, - Tok_Spec_Mutable, - Tok_Spec_NeverInline, - Tok_Spec_Override, - Tok_Spec_Restrict, - Tok_Spec_Static, - Tok_Spec_ThreadLocal, - Tok_Spec_Volatile, - Tok_Spec_Virtual, - Tok_Star, - Tok_Statement_End, - Tok_StaticAssert, - Tok_String, - Tok_Type_Typename, - Tok_Type_Unsigned, - Tok_Type_Signed, - Tok_Type_Short, - Tok_Type_Long, - Tok_Type_bool, - Tok_Type_char, - Tok_Type_int, - Tok_Type_double, - Tok_Type_MS_int8, - Tok_Type_MS_int16, - Tok_Type_MS_int32, - Tok_Type_MS_int64, - Tok_Type_MS_W64, - Tok_Varadic_Argument, - Tok___Attributes_Start, - Tok_Attribute_GEN_API, - Tok_NumTokens, - Tok_UnderlyingType = 0xffffffffu -}; -typedef enum gen_TokType gen_TokType; - -inline gen_Str gen_toktype_to_str(gen_TokType type) -{ - gen_local_persist gen_Str lookup[] = { - { "__invalid__", sizeof("__invalid__") - 1 }, - { "private", sizeof("private") - 1 }, - { "protected", sizeof("protected") - 1 }, - { "public", sizeof("public") - 1 }, - { ".", sizeof(".") - 1 }, - { "::", sizeof("::") - 1 }, - { "&", sizeof("&") - 1 }, - { "&&", sizeof("&&") - 1 }, - { ":", sizeof(":") - 1 }, - { "[[", sizeof("[[") - 1 }, - { "]]", sizeof("]]") - 1 }, - { "{", sizeof("{") - 1 }, - { "}", sizeof("}") - 1 }, - { "[", sizeof("[") - 1 }, - { "]", sizeof("]") - 1 }, - { "(", sizeof("(") - 1 }, - { ")", sizeof(")") - 1 }, - { "__comment__", sizeof("__comment__") - 1 }, - { "__comment_end__", sizeof("__comment_end__") - 1 }, - { "__comment_start__", sizeof("__comment_start__") - 1 }, - { "__character__", sizeof("__character__") - 1 }, - { ",", sizeof(",") - 1 }, - { "class", sizeof("class") - 1 }, - { "__attribute__", sizeof("__attribute__") - 1 }, - { "__declspec", sizeof("__declspec") - 1 }, - { "enum", sizeof("enum") - 1 }, - { "extern", sizeof("extern") - 1 }, - { "friend", sizeof("friend") - 1 }, - { "module", sizeof("module") - 1 }, - { "namespace", sizeof("namespace") - 1 }, - { "operator", sizeof("operator") - 1 }, - { "struct", sizeof("struct") - 1 }, - { "template", sizeof("template") - 1 }, - { "typedef", sizeof("typedef") - 1 }, - { "using", sizeof("using") - 1 }, - { "union", sizeof("union") - 1 }, - { "__identifier__", sizeof("__identifier__") - 1 }, - { "import", sizeof("import") - 1 }, - { "export", sizeof("export") - 1 }, - { "__new_line__", sizeof("__new_line__") - 1 }, - { "__number__", sizeof("__number__") - 1 }, - { "__operator__", sizeof("__operator__") - 1 }, - { "#", sizeof("#") - 1 }, - { "define", sizeof("define") - 1 }, - { "__define_param__", sizeof("__define_param__") - 1 }, - { "if", sizeof("if") - 1 }, - { "ifdef", sizeof("ifdef") - 1 }, - { "ifndef", sizeof("ifndef") - 1 }, - { "elif", sizeof("elif") - 1 }, - { "else", sizeof("else") - 1 }, - { "endif", sizeof("endif") - 1 }, - { "include", sizeof("include") - 1 }, - { "pragma", sizeof("pragma") - 1 }, - { "__macro_content__", sizeof("__macro_content__") - 1 }, - { "__macro_expression__", sizeof("__macro_expression__") - 1 }, - { "__macro_statment__", sizeof("__macro_statment__") - 1 }, - { "__macro_typename__", sizeof("__macro_typename__") - 1 }, - { "__unsupported__", sizeof("__unsupported__") - 1 }, - { "alignas", sizeof("alignas") - 1 }, - { "const", sizeof("const") - 1 }, - { "consteval", sizeof("consteval") - 1 }, - { "constexpr", sizeof("constexpr") - 1 }, - { "constinit", sizeof("constinit") - 1 }, - { "explicit", sizeof("explicit") - 1 }, - { "extern", sizeof("extern") - 1 }, - { "final", sizeof("final") - 1 }, - { "gen_forceinline", sizeof("gen_forceinline") - 1 }, - { "gen_global", sizeof("gen_global") - 1 }, - { "inline", sizeof("inline") - 1 }, - { "gen_internal", sizeof("gen_internal") - 1 }, - { "gen_local_persist", sizeof("gen_local_persist") - 1 }, - { "mutable", sizeof("mutable") - 1 }, - { "gen_neverinline", sizeof("gen_neverinline") - 1 }, - { "override", sizeof("override") - 1 }, - { "restrict", sizeof("restrict") - 1 }, - { "static", sizeof("static") - 1 }, - { "gen_thread_local", sizeof("gen_thread_local") - 1 }, - { "volatile", sizeof("volatile") - 1 }, - { "virtual", sizeof("virtual") - 1 }, - { "*", sizeof("*") - 1 }, - { ";", sizeof(";") - 1 }, - { "gen_static_assert", sizeof("gen_static_assert") - 1 }, - { "__string__", sizeof("__string__") - 1 }, - { "typename", sizeof("typename") - 1 }, - { "unsigned", sizeof("unsigned") - 1 }, - { "signed", sizeof("signed") - 1 }, - { "short", sizeof("short") - 1 }, - { "long", sizeof("long") - 1 }, - { "bool", sizeof("bool") - 1 }, - { "char", sizeof("char") - 1 }, - { "int", sizeof("int") - 1 }, - { "double", sizeof("double") - 1 }, - { "__int8", sizeof("__int8") - 1 }, - { "__int16", sizeof("__int16") - 1 }, - { "__int32", sizeof("__int32") - 1 }, - { "__int64", sizeof("__int64") - 1 }, - { "_W64", sizeof("_W64") - 1 }, - { "...", sizeof("...") - 1 }, - { "__attrib_start__", sizeof("__attrib_start__") - 1 }, - { "GEN_API", sizeof("GEN_API") - 1 }, - }; - return lookup[type]; -} - -inline gen_TokType gen_str_to_toktype(gen_Str str) -{ - gen_local_persist gen_u32 keymap[Tok_NumTokens]; - gen_do_once_start for (gen_u32 index = 0; index < Tok_NumTokens; index++) - { - gen_Str gen_enum_str = gen_toktype_to_str((gen_TokType)index); - keymap[index] = gen_crc32(gen_enum_str.Ptr, gen_enum_str.Len); - } - gen_do_once_end gen_u32 gen_hash = gen_crc32(str.Ptr, str.Len); - for (gen_u32 index = 0; index < Tok_NumTokens; index++) - { - if (keymap[index] == gen_hash) - return (gen_TokType)index; - } - return Tok_Invalid; -} - -enum TokFlags gen_enum_underlying(gen_u32) -{ - TF_Operator = gen_bit(0), - TF_Assign = gen_bit(1), - 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, -}; - -typedef gen_u32 TokFlags; - -struct gen_Token; -typedef struct gen_Token gen_Token; -typedef gen_Token* gen_Array_gen_Token; - -struct gen_Token -{ - gen_Str Text; - gen_TokType Type; - gen_s32 Line; - gen_s32 Column; - gen_u32 Flags; -}; - -#pragma region gen_Array_gen_Token - -#define GEN_GENERIC_SLOT_6__array_init gen_Token, gen_Array_gen_Token_init -#define GEN_GENERIC_SLOT_6__array_init_reserve gen_Token, gen_Array_gen_Token_init_reserve -#define GEN_GENERIC_SLOT_6__array_append gen_Array_gen_Token, gen_Array_gen_Token_append -#define GEN_GENERIC_SLOT_6__array_append_items gen_Array_gen_Token, gen_Array_gen_Token_append_items -#define GEN_GENERIC_SLOT_6__array_append_at gen_Array_gen_Token, gen_Array_gen_Token_append_at -#define GEN_GENERIC_SLOT_6__array_append_items_at gen_Array_gen_Token, gen_Array_gen_Token_append_items_at -#define GEN_GENERIC_SLOT_6__array_back gen_Array_gen_Token, gen_Array_gen_Token_back -#define GEN_GENERIC_SLOT_6__array_clear gen_Array_gen_Token, gen_Array_gen_Token_clear -#define GEN_GENERIC_SLOT_6__array_fill gen_Array_gen_Token, gen_Array_gen_Token_fill -#define GEN_GENERIC_SLOT_6__array_free gen_Array_gen_Token, gen_Array_gen_Token_free -#define GEN_GENERIC_SLOT_6__array_grow gen_Array_gen_Token*, gen_Array_gen_Token_grow -#define GEN_GENERIC_SLOT_6__array_num gen_Array_gen_Token, gen_Array_gen_Token_num -#define GEN_GENERIC_SLOT_6__array_pop gen_Array_gen_Token, gen_Array_gen_Token_pop -#define GEN_GENERIC_SLOT_6__array_remove_at gen_Array_gen_Token, gen_Array_gen_Token_remove_at -#define GEN_GENERIC_SLOT_6__array_reserve gen_Array_gen_Token, gen_Array_gen_Token_reserve -#define GEN_GENERIC_SLOT_6__array_resize gen_Array_gen_Token, gen_Array_gen_Token_resize -#define GEN_GENERIC_SLOT_6__array_set_capacity gen_Array_gen_Token*, gen_Array_gen_Token_set_capacity - -gen_Array_gen_Token gen_Array_gen_Token_init(gen_AllocatorInfo allocator); -gen_Array_gen_Token gen_Array_gen_Token_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity); -bool gen_Array_gen_Token_append_array(gen_Array_gen_Token* self, gen_Array_gen_Token other); -bool gen_Array_gen_Token_append(gen_Array_gen_Token* self, gen_Token value); -bool gen_Array_gen_Token_append_items(gen_Array_gen_Token* self, gen_Token* items, gen_usize item_num); -bool gen_Array_gen_Token_append_at(gen_Array_gen_Token* self, gen_Token item, gen_usize idx); -bool gen_Array_gen_Token_append_items_at(gen_Array_gen_Token* self, gen_Token* items, gen_usize item_num, gen_usize idx); -gen_Token* gen_Array_gen_Token_back(gen_Array_gen_Token self); -void gen_Array_gen_Token_clear(gen_Array_gen_Token self); -bool gen_Array_gen_Token_fill(gen_Array_gen_Token self, gen_usize begin, gen_usize end, gen_Token value); -void gen_Array_gen_Token_free(gen_Array_gen_Token* self); -bool gen_Array_gen_Token_grow(gen_Array_gen_Token* self, gen_usize min_capacity); -gen_usize gen_Array_gen_Token_num(gen_Array_gen_Token self); -gen_Token gen_Array_gen_Token_pop(gen_Array_gen_Token self); -void gen_Array_gen_Token_remove_at(gen_Array_gen_Token self, gen_usize idx); -bool gen_Array_gen_Token_reserve(gen_Array_gen_Token* self, gen_usize new_capacity); -bool gen_Array_gen_Token_resize(gen_Array_gen_Token* self, gen_usize num); -bool gen_Array_gen_Token_set_capacity(gen_Array_gen_Token* self, gen_usize new_capacity); - -gen_forceinline gen_Array_gen_Token gen_Array_gen_Token_init(gen_AllocatorInfo allocator) -{ - size_t initial_size = gen_array_grow_formula(0); - return gen_array_init_reserve(gen_Token, allocator, initial_size); -} - -inline gen_Array_gen_Token gen_Array_gen_Token_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity) -{ - GEN_ASSERT(capacity > 0); - gen_ArrayHeader* header = gen_rcast(gen_ArrayHeader*, gen_alloc(allocator, sizeof(gen_ArrayHeader) + sizeof(gen_Token) * capacity)); - if (header == gen_nullptr) - return gen_nullptr; - header->Allocator = allocator; - header->Capacity = capacity; - header->Num = 0; - return gen_rcast(gen_Token*, header + 1); -} - -gen_forceinline bool gen_Array_gen_Token_append_array(gen_Array_gen_Token* self, gen_Array_gen_Token other) -{ - return gen_array_append_items(*self, (gen_Array_gen_Token)other, gen_Array_gen_Token_num(other)); -} - -inline bool gen_Array_gen_Token_append(gen_Array_gen_Token* self, gen_Token value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num == header->Capacity) - { - if (! gen_array_grow(self, header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - (*self)[header->Num] = value; - header->Num++; - return true; -} - -inline bool gen_Array_gen_Token_append_items(gen_Array_gen_Token* self, gen_Token* items, gen_usize item_num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(items != gen_nullptr); - GEN_ASSERT(item_num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num + item_num > header->Capacity) - { - if (! gen_array_grow(self, header->Capacity + item_num)) - return false; - header = gen_array_get_header(*self); - } - gen_mem_copy((*self) + header->Num, items, sizeof(gen_Token) * item_num); - header->Num += item_num; - return true; -} - -inline bool gen_Array_gen_Token_append_at(gen_Array_gen_Token* self, gen_Token item, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - idx = header->Num - 1; - if (idx < 0) - idx = 0; - if (header->Capacity < header->Num + 1) - { - if (! gen_array_grow(self, header->Capacity + 1)) - return false; - header = gen_array_get_header(*self); - } - gen_Array_gen_Token target = (*self) + idx; - gen_mem_move(target + 1, target, (header->Num - idx) * sizeof(gen_Token)); - header->Num++; - return true; -} - -inline bool gen_Array_gen_Token_append_items_at(gen_Array_gen_Token* self, gen_Token* items, gen_usize item_num, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - { - return gen_array_append_items(*self, items, item_num); - } - if (item_num > header->Capacity) - { - if (! gen_array_grow(self, item_num + header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - gen_Token* target = (*self) + idx + item_num; - gen_Token* src = (*self) + idx; - gen_mem_move(target, src, (header->Num - idx) * sizeof(gen_Token)); - gen_mem_copy(src, items, item_num * sizeof(gen_Token)); - header->Num += item_num; - return true; -} - -inline gen_Token* gen_Array_gen_Token_back(gen_Array_gen_Token self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - if (header->Num == 0) - return 0; - return self + header->Num - 1; -} - -inline void gen_Array_gen_Token_clear(gen_Array_gen_Token self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - header->Num = 0; -} - -inline bool gen_Array_gen_Token_fill(gen_Array_gen_Token self, gen_usize begin, gen_usize end, gen_Token value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(begin <= end); - gen_ArrayHeader* header = gen_array_get_header(self); - if (begin < 0 || end > header->Num) - return false; - for (gen_ssize idx = (gen_ssize)begin; idx < (gen_ssize)end; idx++) - self[idx] = value; - return true; -} - -inline void gen_Array_gen_Token_free(gen_Array_gen_Token* self) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_allocator_free(header->Allocator, header); - self = 0; -} - -inline bool gen_Array_gen_Token_grow(gen_Array_gen_Token* self, gen_usize min_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(min_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_usize new_capacity = gen_array_grow_formula(header->Capacity); - if (new_capacity < min_capacity) - new_capacity = min_capacity; - return gen_array_set_capacity(self, new_capacity); -} - -gen_forceinline gen_usize gen_Array_gen_Token_num(gen_Array_gen_Token self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_array_get_header(self)->Num; -} - -inline gen_Token gen_Array_gen_Token_pop(gen_Array_gen_Token self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(header->Num > 0); - gen_Token result = self[header->Num - 1]; - header->Num--; - return result; -} - -gen_forceinline void gen_Array_gen_Token_remove_at(gen_Array_gen_Token self, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(idx < header->Num); - gen_mem_move(self + idx, self + idx + 1, sizeof(gen_Token) * (header->Num - idx - 1)); - header->Num--; -} - -inline bool gen_Array_gen_Token_reserve(gen_Array_gen_Token* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < new_capacity) - return gen_array_set_capacity(self, new_capacity); - return true; -} - -inline bool gen_Array_gen_Token_resize(gen_Array_gen_Token* self, gen_usize num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < num) - { - if (! gen_array_grow(self, num)) - return false; - header = gen_array_get_header(*self); - } - header->Num = num; - return true; -} - -inline bool gen_Array_gen_Token_set_capacity(gen_Array_gen_Token* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (new_capacity == header->Capacity) - return true; - if (new_capacity < header->Num) - { - header->Num = new_capacity; - return true; - } - gen_usize size = sizeof(gen_ArrayHeader) + sizeof(gen_Token) * new_capacity; - gen_ArrayHeader* new_header = gen_cast(gen_ArrayHeader*, gen_alloc(header->Allocator, size)); - if (new_header == 0) - return false; - gen_mem_move(new_header, header, sizeof(gen_ArrayHeader) + sizeof(gen_Token) * header->Num); - new_header->Capacity = new_capacity; - gen_allocator_free(header->Allocator, &header); - *self = gen_cast(gen_Token*, new_header + 1); - return true; -} - -#pragma endregion gen_Array_gen_Token - - -#define gen_NullToken \ - (gen_Token) \ - { \ - {}, Tok_Invalid, 0, 0, TF_Null \ - } - -gen_forceinline gen_AccessSpec gen_tok_to_access_specifier(gen_Token tok) -{ - return gen_scast(gen_AccessSpec, tok.Type); -} - -gen_forceinline bool gen_tok_is_valid(gen_Token tok) -{ - return tok.Text.Ptr && tok.Text.Len && tok.Type != Tok_Invalid; -} - -gen_forceinline bool gen_tok_is_access_operator(gen_Token tok) -{ - return gen_bitfield_is_set(gen_u32, tok.Flags, TF_AccessOperator); -} - -gen_forceinline bool gen_tok_is_access_specifier(gen_Token tok) -{ - return gen_bitfield_is_set(gen_u32, tok.Flags, TF_AccessSpecifier); -} - -gen_forceinline bool gen_tok_is_attribute(gen_Token tok) -{ - return gen_bitfield_is_set(gen_u32, tok.Flags, TF_Attribute); -} - -gen_forceinline bool gen_tok_is_operator(gen_Token tok) -{ - return gen_bitfield_is_set(gen_u32, tok.Flags, TF_Operator); -} - -gen_forceinline bool gen_tok_is_preprocessor(gen_Token tok) -{ - return gen_bitfield_is_set(gen_u32, tok.Flags, TF_Preprocess); -} - -gen_forceinline bool gen_tok_is_preprocess_cond(gen_Token tok) -{ - return gen_bitfield_is_set(gen_u32, tok.Flags, TF_Preprocess_Cond); -} - -gen_forceinline bool gen_tok_is_specifier(gen_Token tok) -{ - return gen_bitfield_is_set(gen_u32, tok.Flags, TF_Specifier); -} - -gen_forceinline bool gen_tok_is_end_definition(gen_Token tok) -{ - return gen_bitfield_is_set(gen_u32, tok.Flags, TF_EndDefinition); -} - -gen_StrBuilder gen_tok_to_strbuilder(gen_AllocatorInfo ainfo, gen_Token tok); - -typedef struct TokenSlice TokenSlice; - -struct TokenSlice -{ - gen_Token* ptr; - gen_s32 num; - -#if GEN_COMPILER_CPP - gen_forceinline operator gen_Token*() const - { - return ptr; - } - - gen_forceinline gen_Token& operator[](gen_ssize index) const - { - return ptr[index]; - } -#endif -}; - -gen_forceinline gen_Str gen_token_range_to_str(gen_Token start, gen_Token end) -{ - gen_Str result = { start.Text.Ptr, - (gen_scast(gen_sptr, gen_rcast(gen_uptr, end.Text.Ptr)) + end.Text.Len) - gen_scast(gen_sptr, gen_rcast(gen_uptr, start.Text.Ptr)) }; - return result; -} - -typedef struct gen_TokArray gen_TokArray; - -struct gen_TokArray -{ - gen_Array(gen_Token) Arr; - gen_s32 Idx; -}; - -typedef struct LexerMessage LexerMessage; -typedef struct LexerMessage LexerMessage; - -struct LexerMessage -{ - LexerMessage* next; - gen_Str content; - LogLevel level; -}; - -typedef struct gen_LexContext gen_LexContext; - -struct gen_LexContext -{ - gen_AllocatorInfo allocator_temp; - LexerMessage* messages; - gen_Str content; - gen_s32 left; - char const* scanner; - gen_s32 line; - gen_s32 column; - gen_Token token; - gen_Array(gen_Token) tokens; -}; - -typedef struct LexedInfo LexedInfo; - -struct LexedInfo -{ - LexerMessage* messages; - gen_Str text; - TokenSlice tokens; -}; - -typedef struct gen_ParseStackNode gen_ParseStackNode; - -typedef struct ParseMessage ParseMessage; -typedef struct ParseMessage ParseMessage; - -struct ParseMessage -{ - ParseMessage* Next; - gen_ParseStackNode* Scope; - gen_Str Content; - LogLevel Level; -}; - -typedef struct gen_ParseContext gen_ParseContext; - -struct gen_ParseContext -{ - ParseMessage* messages; - gen_ParseStackNode* scope; - // gen_TokArray Tokens; - TokenSlice tokens; - gen_s32 gen_token_id; -}; - -enum gen_MacroType gen_enum_underlying(gen_u16) -{ - MT_Expression, // A macro is assumed to be a expression if not resolved. - MT_Statement, - MT_Typename, - MT_Block_Start, // Not Supported yet - MT_Block_End, // Not Supported yet - MT_Case_Statement, // Not Supported yet - - MT_UnderlyingType = GEN_U16_MAX, -}; - -typedef gen_u16 gen_MacroType; - -gen_forceinline gen_TokType gen_macrotype__to_toktype(gen_MacroType type) -{ - switch (type) - { - case MT_Statement: - return Tok_Preprocess_Macro_Stmt; - case MT_Expression: - return Tok_Preprocess_Macro_Expr; - case MT_Typename: - return Tok_Preprocess_Macro_Typename; - } - // All others unsupported for now. - return Tok_Invalid; -} - -inline gen_Str gen_macrotype__to_str(gen_MacroType type) -{ - gen_local_persist gen_Str lookup[] = { - { "Statement", sizeof("Statement") - 1 }, - { "Expression", sizeof("Expression") - 1 }, - { "Typename", sizeof("Typename") - 1 }, - { "Block_Start", sizeof("Block_Start") - 1 }, - { "Block_End", sizeof("Block_End") - 1 }, - { "Case_Statement", sizeof("Case_Statement") - 1 }, - }; - gen_local_persist gen_Str invalid = { "Invalid", sizeof("Invalid") }; - if (type > MT_Case_Statement) - return invalid; - - return lookup[type]; -} - -enum gen_EMacroFlags gen_enum_underlying(gen_u16) -{ - // gen_Macro has parameters (args expected to be passed) - MF_Functional = gen_bit(0), // Expects to assign a braced scope to its body. - MF_Expects_Body = gen_bit(1), // gen_lex__eat wil treat this macro as an identifier if the parser attempts to consume it as one. - // This is a kludge because we don't support push/pop macro pragmas rn. - MF_Allow_As_Identifier = gen_bit( - 2 - ), // When parsing identifiers, it will allow the consumption of the macro parameters (as its expected to be a part of constructing the identifier) - // Example of a decarator macro from stb_sprintf.h: - // STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char* buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3); - // ^^ STB_SPRINTF_DECORATE is decorating sprintf - MF_Identifier_Decorator = gen_bit(3), // gen_lex__eat wil treat this macro as an attribute if the parser attempts to consume it as one. - // This a kludge because unreal has a macro that behaves as both a 'statement' and an attribute (UE_DEPRECATED, PRAGMA_ENABLE_DEPRECATION_WARNINGS, etc) - // TODO(Ed): We can keep the MF_Allow_As_Attribute flag for macros, however, we need to add the ability of gen_AST_Attributes to chain themselves. - // Its thats already a thing in the standard language anyway - // & it would allow UE_DEPRECATED, (UE_PROPERTY / UE_FUNCTION) to chain themselves as attributes of a resolved member function/variable definition - MF_Allow_As_Attribute = gen_bit(4), // When a macro is encountered after attributes and specifiers while parsing a function, or variable: - // It will consume the macro and treat it as resolving the definition. - // (MUST BE OF MT_Statement TYPE) - MF_Allow_As_Definition = gen_bit(5), // Created for Unreal's PURE_VIRTUAL - MF_Allow_As_Specifier = gen_bit(6), - MF_Null = 0, - MF_UnderlyingType = GEN_U16_MAX, -}; - -typedef gen_u16 gen_EMacroFlags; -typedef gen_u16 gen_MacroFlags; - -typedef struct gen_Macro gen_Macro; - -struct gen_Macro -{ - gen_StrCached Name; - gen_MacroType Type; - gen_MacroFlags Flags; -}; - -gen_forceinline gen_b32 gen_macro_is_functional(gen_Macro macro) -{ - return gen_bitfield_is_set(gen_b16, macro.Flags, MF_Functional); -} - -gen_forceinline gen_b32 gen_macro_expects_body(gen_Macro macro) -{ - return gen_bitfield_is_set(gen_b16, macro.Flags, MF_Expects_Body); -} - -#if GEN_COMPILER_CPP && ! GEN_C_LIKE_CPP -gen_forceinline gen_b32 is_functional(gen_Macro macro) -{ - return gen_bitfield_is_set(gen_b16, macro.Flags, MF_Functional); -} - -gen_forceinline gen_b32 expects_body(gen_Macro macro) -{ - return gen_bitfield_is_set(gen_b16, macro.Flags, MF_Expects_Body); -} -#endif - -typedef gen_HashTable(gen_Macro) MacroTable; -#pragma endregion Types - -#pragma region AST - -/* - ______ ______ ________ __ __ ______ __ - / \ / \| \ | \ | \ / \ | \ -| ▓▓▓▓▓▓\ ▓▓▓▓▓▓\\▓▓▓▓▓▓▓▓ | ▓▓\ | ▓▓ | ▓▓▓▓▓▓\ ______ ____| ▓▓ ______ -| ▓▓__| ▓▓ ▓▓___\▓▓ | ▓▓ | ▓▓▓\| ▓▓ | ▓▓ \▓▓/ \ / ▓▓/ \ -| ▓▓ ▓▓\▓▓ \ | ▓▓ | ▓▓▓▓\ ▓▓ | ▓▓ | ▓▓▓▓▓▓\ ▓▓▓▓▓▓▓ ▓▓▓▓▓▓\ -| ▓▓▓▓▓▓▓▓_\▓▓▓▓▓▓\ | ▓▓ | ▓▓\▓▓ ▓▓ | ▓▓ __| ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓ ▓▓ -| ▓▓ | ▓▓ \__| ▓▓ | ▓▓ | ▓▓ \▓▓▓▓ | ▓▓__/ \ ▓▓__/ ▓▓ ▓▓__| ▓▓ ▓▓▓▓▓▓▓▓ -| ▓▓ | ▓▓\▓▓ ▓▓ | ▓▓ | ▓▓ \▓▓▓ \▓▓ ▓▓\▓▓ ▓▓\▓▓ ▓▓\▓▓ \ - \▓▓ \▓▓ \▓▓▓▓▓▓ \▓▓ \▓▓ \▓▓ \▓▓▓▓▓▓ \▓▓▓▓▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ -*/ - -struct gen_AST; -typedef struct gen_AST gen_AST; -struct gen_AST_Body; -typedef struct gen_AST_Body gen_AST_Body; -struct gen_AST_Attributes; -typedef struct gen_AST_Attributes gen_AST_Attributes; -struct gen_AST_Comment; -typedef struct gen_AST_Comment gen_AST_Comment; -struct gen_AST_Constructor; -typedef struct gen_AST_Constructor gen_AST_Constructor; -// struct gen_AST_BaseClass; -struct gen_AST_Class; -typedef struct gen_AST_Class gen_AST_Class; -struct gen_AST_Define; -typedef struct gen_AST_Define gen_AST_Define; -struct gen_AST_DefineParams; -typedef struct gen_AST_DefineParams gen_AST_DefineParams; -struct gen_AST_Destructor; -typedef struct gen_AST_Destructor gen_AST_Destructor; -struct gen_AST_Enum; -typedef struct gen_AST_Enum gen_AST_Enum; -struct gen_AST_Exec; -typedef struct gen_AST_Exec gen_AST_Exec; -struct gen_AST_Extern; -typedef struct gen_AST_Extern gen_AST_Extern; -struct gen_AST_Include; -typedef struct gen_AST_Include gen_AST_Include; -struct gen_AST_Friend; -typedef struct gen_AST_Friend gen_AST_Friend; -struct gen_AST_Fn; -typedef struct gen_AST_Fn gen_AST_Fn; -struct gen_AST_Module; -typedef struct gen_AST_Module gen_AST_Module; -struct gen_AST_NS; -typedef struct gen_AST_NS gen_AST_NS; -struct gen_AST_Operator; -typedef struct gen_AST_Operator gen_AST_Operator; -struct gen_AST_OpCast; -typedef struct gen_AST_OpCast gen_AST_OpCast; -struct gen_AST_Params; -typedef struct gen_AST_Params gen_AST_Params; -struct gen_AST_Pragma; -typedef struct gen_AST_Pragma gen_AST_Pragma; -struct gen_AST_PreprocessCond; -typedef struct gen_AST_PreprocessCond gen_AST_PreprocessCond; -struct gen_AST_Specifiers; -typedef struct gen_AST_Specifiers gen_AST_Specifiers; - - -struct gen_AST_Struct; -typedef struct gen_AST_Struct gen_AST_Struct; -struct gen_AST_Template; -typedef struct gen_AST_Template gen_AST_Template; -struct gen_AST_Typename; -typedef struct gen_AST_Typename gen_AST_Typename; -struct gen_AST_Typedef; -typedef struct gen_AST_Typedef gen_AST_Typedef; -struct gen_AST_Union; -typedef struct gen_AST_Union gen_AST_Union; -struct gen_AST_Using; -typedef struct gen_AST_Using gen_AST_Using; -struct gen_AST_Var; -typedef struct gen_AST_Var gen_AST_Var; - - -typedef gen_AST* gen_Code; - -typedef gen_AST_Body* gen_CodeBody; -typedef gen_AST_Attributes* gen_CodeAttributes; -typedef gen_AST_Comment* gen_CodeComment; -typedef gen_AST_Class* gen_CodeClass; -typedef gen_AST_Constructor* gen_CodeConstructor; -typedef gen_AST_Define* gen_CodeDefine; -typedef gen_AST_DefineParams* gen_CodeDefineParams; -typedef gen_AST_Destructor* gen_CodeDestructor; -typedef gen_AST_Enum* gen_CodeEnum; -typedef gen_AST_Exec* gen_CodeExec; -typedef gen_AST_Extern* gen_CodeExtern; -typedef gen_AST_Include* gen_CodeInclude; -typedef gen_AST_Friend* gen_CodeFriend; -typedef gen_AST_Fn* gen_CodeFn; -typedef gen_AST_Module* gen_CodeModule; -typedef gen_AST_NS* gen_CodeNS; -typedef gen_AST_Operator* gen_CodeOperator; -typedef gen_AST_OpCast* gen_CodeOpCast; -typedef gen_AST_Params* gen_CodeParams; -typedef gen_AST_PreprocessCond* gen_CodePreprocessCond; -typedef gen_AST_Pragma* gen_CodePragma; -typedef gen_AST_Specifiers* gen_CodeSpecifiers; - - -typedef gen_AST_Struct* gen_CodeStruct; -typedef gen_AST_Template* gen_CodeTemplate; -typedef gen_AST_Typename* gen_CodeTypename; -typedef gen_AST_Typedef* gen_CodeTypedef; -typedef gen_AST_Union* gen_CodeUnion; -typedef gen_AST_Using* gen_CodeUsing; -typedef gen_AST_Var* gen_CodeVar; - -#pragma region gen_Code C-Interface - - -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_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); -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_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 - - - -// Used to identify ASTs that should always be duplicated. (Global constant ASTs) -GEN_API extern gen_Code gen_Code_Global; - -// Used to identify invalid generated code. -GEN_API extern gen_Code gen_Code_Invalid; - -struct gen_Code_POD -{ - gen_AST* ast; -}; -typedef struct gen_Code_POD gen_Code_POD; -gen_static_assert(sizeof(gen_Code) == sizeof(gen_Code_POD), "ERROR: gen_Code is not POD"); - -// Desired width of the gen_AST data structure. -#define gen_AST_POD_Size 128 - -#define gen_AST_ArrSpecs_Cap \ - (gen_AST_POD_Size - sizeof(gen_Code) - sizeof(gen_StrCached) - sizeof(gen_Code) * 2 - sizeof(gen_Token*) - sizeof(gen_Code) - sizeof(gen_CodeType) \ - - sizeof(gen_ModuleFlag) - sizeof(gen_u32)) \ - / sizeof(gen_Specifier) \ - - 1 - -/* - Simple gen_AST POD with functionality to seralize into C++ syntax. - TODO(Ed): Eventually haven't a transparent gen_AST like this will longer be viable once statements & expressions are in (most likely....) -*/ -struct gen_AST -{ - union - { - struct - { - gen_Code InlineCmt; // Class, Constructor, Destructor, Enum, Friend, Functon, gen_Operator, OpCast, Struct, Typedef, Using, Variable - gen_Code Attributes; // Class, Enum, Function, Struct, Typedef, Union, Using, Variable // TODO(Ed): Parameters can have attributes - gen_Code Specs; // Class, Destructor, Function, gen_Operator, Struct, Typename, Variable - - union - { - gen_Code InitializerList; // Constructor - gen_Code ParentType; // Class, Struct, ParentType->Next has a possible list of interfaces. - gen_Code ReturnType; // Function, gen_Operator, Typename - gen_Code UnderlyingType; // Enum, Typedef - gen_Code ValueType; // Parameter, Variable - }; - - union - { - gen_Code gen_Macro; // Parameter - gen_Code BitfieldSize; // Variable (Class/Struct Data Member) - gen_Code Params; // Constructor, Define, Function, gen_Operator, Template, Typename - gen_Code UnderlyingTypeMacro; // Enum - }; - - union - { - gen_Code ArrExpr; // Typename - gen_Code Body; // Class, Constructor, Define, Destructor, Enum, Friend, Function, Namespace, Struct, Union - gen_Code Declaration; // Friend, Template - gen_Code Value; // Parameter, Variable - }; - - union - { - gen_Code NextVar; // Variable - gen_Code SuffixSpecs; // Typename, Function (Thanks Unreal) - gen_Code PostNameMacro; // Only used with parameters for specifically UE_REQUIRES (Thanks Unreal) - }; - }; - - gen_StrCached Content; // Attributes, Comment, Execution, Include - TokenSlice ContentToks; // TODO(Ed): Use a token slice for content - - struct - { - gen_Specifier ArrSpecs[gen_AST_ArrSpecs_Cap]; // Specifiers - gen_Code NextSpecs; // Specifiers; If ArrSpecs is full, then NextSpecs is used. - }; - }; - - gen_StrCached Name; - - union - { - gen_Code Prev; - gen_Code Front; - gen_Code Last; - }; - - union - { - gen_Code Next; - gen_Code Back; - }; - - gen_Token* gen_Token; // Reference to starting token, only available if it was derived from parsing. // TODO(Ed): Change this to a token slice. - gen_Code Parent; - gen_CodeType Type; - // gen_CodeFlag CodeFlags; - gen_ModuleFlag ModuleFlags; - - union - { - gen_b32 IsFunction; // Used by typedef to not serialize the name field. - - struct - { - gen_b16 IsParamPack; // Used by typename to know if type should be considered a parameter pack. - gen_ETypenameTag TypeTag; // Used by typename to keep track of explicitly declared tags for the identifier (enum, struct, union) - }; - - gen_Operator Op; - gen_AccessSpec ParentAccess; - gen_s32 NumEntries; - gen_s32 - VarParenthesizedInit; // Used by variables to know that initialization is using a gen_constructor_ expression instead of an assignment expression. - }; -}; - -gen_static_assert(sizeof(gen_AST) == gen_AST_POD_Size, "ERROR: gen_AST is not size of gen_AST_POD_Size"); - -#define gen_InvalidCode \ - (void*) \ - { \ - (void*)gen_Code_Invalid \ - } - -#define gen_NullCode gen_nullptr - -/* - ______ __ ______ __ ______ - / \ | \ | \ | \ / \ -| ▓▓▓▓▓▓\ ______ ____| ▓▓ ______ \▓▓▓▓▓▓_______ _| ▓▓_ ______ ______ | ▓▓▓▓▓▓\ ______ _______ ______ -| ▓▓ \▓▓/ \ / ▓▓/ \ | ▓▓ | \| ▓▓ \ / \ / \| ▓▓_ \▓▓| \ / \/ \ -| ▓▓ | ▓▓▓▓▓▓\ ▓▓▓▓▓▓▓ ▓▓▓▓▓▓\ | ▓▓ | ▓▓▓▓▓▓▓\\▓▓▓▓▓▓ | ▓▓▓▓▓▓\ ▓▓▓▓▓▓\ ▓▓ \ \▓▓▓▓▓▓\ ▓▓▓▓▓▓▓ ▓▓▓▓▓▓\ -| ▓▓ __| ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓ ▓▓ | ▓▓ | ▓▓ | ▓▓ | ▓▓ __| ▓▓ ▓▓ ▓▓ \▓▓ ▓▓▓▓ / ▓▓ ▓▓ | ▓▓ ▓▓ -| ▓▓__/ \ ▓▓__/ ▓▓ ▓▓__| ▓▓ ▓▓▓▓▓▓▓▓ _| ▓▓_| ▓▓ | ▓▓ | ▓▓| \ ▓▓▓▓▓▓▓▓ ▓▓ | ▓▓ | ▓▓▓▓▓▓▓ ▓▓_____| ▓▓▓▓▓▓▓▓ - \▓▓ ▓▓\▓▓ ▓▓\▓▓ ▓▓\▓▓ \ | ▓▓ \ ▓▓ | ▓▓ \▓▓ ▓▓\▓▓ \ ▓▓ | ▓▓ \▓▓ ▓▓\▓▓ \\▓▓ \ - \▓▓▓▓▓▓ \▓▓▓▓▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓\▓▓ \▓▓ \▓▓▓▓ \▓▓▓▓▓▓▓\▓▓ \▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ -*/ - -#pragma region gen_Code Type C-Interface - -#define gen_code_append(code, other) \ - _Generic( \ - (code), \ - gen_Code: gen_code__append, \ - gen_CodeBody: gen_code__append, \ - gen_CodeAttributes: gen_code__append, \ - gen_CodeComment: gen_code__append, \ - gen_CodeClass: gen_code__append, \ - gen_CodeConstructor: gen_code__append, \ - gen_CodeDefine: gen_code__append, \ - gen_CodeDefineParams: gen_code__append, \ - gen_CodeDestructor: gen_code__append, \ - gen_CodeEnum: gen_code__append, \ - gen_CodeExec: gen_code__append, \ - gen_CodeExtern: gen_code__append, \ - gen_CodeInclude: gen_code__append, \ - gen_CodeFriend: gen_code__append, \ - gen_CodeFn: gen_code__append, \ - gen_CodeModule: gen_code__append, \ - gen_CodeNS: gen_code__append, \ - gen_CodeOperator: gen_code__append, \ - gen_CodeOpCast: gen_code__append, \ - gen_CodePragma: gen_code__append, \ - gen_CodeParams: gen_code__append, \ - gen_CodePreprocessCond: gen_code__append, \ - gen_CodeSpecifiers: gen_code__append, \ - gen_CodeStruct: gen_code__append, \ - gen_CodeTemplate: gen_code__append, \ - gen_CodeTypename: gen_code__append, \ - gen_CodeTypedef: gen_code__append, \ - gen_CodeUnion: gen_code__append, \ - gen_CodeUsing: gen_code__append, \ - gen_CodeVar: gen_code__append, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code, other) - -#define gen_code_debug_str(code) \ - _Generic( \ - (code), \ - gen_Code: gen_code__debug_str, \ - gen_CodeBody: gen_code__debug_str, \ - gen_CodeAttributes: gen_code__debug_str, \ - gen_CodeComment: gen_code__debug_str, \ - gen_CodeClass: gen_code__debug_str, \ - gen_CodeConstructor: gen_code__debug_str, \ - gen_CodeDefine: gen_code__debug_str, \ - gen_CodeDefineParams: gen_code__debug_str, \ - gen_CodeDestructor: gen_code__debug_str, \ - gen_CodeEnum: gen_code__debug_str, \ - gen_CodeExec: gen_code__debug_str, \ - gen_CodeExtern: gen_code__debug_str, \ - gen_CodeInclude: gen_code__debug_str, \ - gen_CodeFriend: gen_code__debug_str, \ - gen_CodeFn: gen_code__debug_str, \ - gen_CodeModule: gen_code__debug_str, \ - gen_CodeNS: gen_code__debug_str, \ - gen_CodeOperator: gen_code__debug_str, \ - gen_CodeOpCast: gen_code__debug_str, \ - gen_CodePragma: gen_code__debug_str, \ - gen_CodeParams: gen_code__debug_str, \ - gen_CodePreprocessCond: gen_code__debug_str, \ - gen_CodeSpecifiers: gen_code__debug_str, \ - gen_CodeStruct: gen_code__debug_str, \ - gen_CodeTemplate: gen_code__debug_str, \ - gen_CodeTypename: gen_code__debug_str, \ - gen_CodeTypedef: gen_code__debug_str, \ - gen_CodeUnion: gen_code__debug_str, \ - gen_CodeUsing: gen_code__debug_str, \ - gen_CodeVar: gen_code__debug_str, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code) - -#define gen_code_duplicate(code) \ - _Generic( \ - (code), \ - gen_Code: gen_code__duplicate, \ - gen_CodeBody: gen_code__duplicate, \ - gen_CodeAttributes: gen_code__duplicate, \ - gen_CodeComment: gen_code__duplicate, \ - gen_CodeClass: gen_code__duplicate, \ - gen_CodeConstructor: gen_code__duplicate, \ - gen_CodeDefine: gen_code__duplicate, \ - gen_CodeDefineParams: gen_code__duplicate, \ - gen_CodeDestructor: gen_code__duplicate, \ - gen_CodeEnum: gen_code__duplicate, \ - gen_CodeExec: gen_code__duplicate, \ - gen_CodeExtern: gen_code__duplicate, \ - gen_CodeInclude: gen_code__duplicate, \ - gen_CodeFriend: gen_code__duplicate, \ - gen_CodeFn: gen_code__duplicate, \ - gen_CodeModule: gen_code__duplicate, \ - gen_CodeNS: gen_code__duplicate, \ - gen_CodeOperator: gen_code__duplicate, \ - gen_CodeOpCast: gen_code__duplicate, \ - gen_CodePragma: gen_code__duplicate, \ - gen_CodeParams: gen_code__duplicate, \ - gen_CodePreprocessCond: gen_code__duplicate, \ - gen_CodeSpecifiers: gen_code__duplicate, \ - gen_CodeStruct: gen_code__duplicate, \ - gen_CodeTemplate: gen_code__duplicate, \ - gen_CodeTypename: gen_code__duplicate, \ - gen_CodeTypedef: gen_code__duplicate, \ - gen_CodeUnion: gen_code__duplicate, \ - gen_CodeUsing: gen_code__duplicate, \ - gen_CodeVar: gen_code__duplicate, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code) - -#define gen_code_entry(code, idx) \ - _Generic( \ - (code), \ - gen_Code: gen_code__entry, \ - gen_CodeBody: gen_code__entry, \ - gen_CodeAttributes: gen_code__entry, \ - gen_CodeComment: gen_code__entry, \ - gen_CodeClass: gen_code__entry, \ - gen_CodeConstructor: gen_code__entry, \ - gen_CodeDefine: gen_code__entry, \ - gen_CodeDefineParams: gen_code__entry, \ - gen_CodeDestructor: gen_code__entry, \ - gen_CodeEnum: gen_code__entry, \ - gen_CodeExec: gen_code__entry, \ - gen_CodeExtern: gen_code__entry, \ - gen_CodeInclude: gen_code__entry, \ - gen_CodeFriend: gen_code__entry, \ - gen_CodeFn: gen_code__entry, \ - gen_CodeModule: gen_code__entry, \ - gen_CodeNS: gen_code__entry, \ - gen_CodeOperator: gen_code__entry, \ - gen_CodeOpCast: gen_code__entry, \ - gen_CodePragma: gen_code__entry, \ - gen_CodeParams: gen_code__entry, \ - gen_CodePreprocessCond: gen_code__entry, \ - gen_CodeSpecifiers: gen_code__entry, \ - gen_CodeStruct: gen_code__entry, \ - gen_CodeTemplate: gen_code__entry, \ - gen_CodeTypename: gen_code__entry, \ - gen_CodeTypedef: gen_code__entry, \ - gen_CodeUnion: gen_code__entry, \ - gen_CodeUsing: gen_code__entry, \ - gen_CodeVar: gen_code__entry, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code, idx) - -#define gen_code_has_entries(code) \ - _Generic( \ - (code), \ - gen_Code: gen_code__has_entries, \ - gen_CodeBody: gen_code__has_entries, \ - gen_CodeAttributes: gen_code__has_entries, \ - gen_CodeComment: gen_code__has_entries, \ - gen_CodeClass: gen_code__has_entries, \ - gen_CodeConstructor: gen_code__has_entries, \ - gen_CodeDefine: gen_code__has_entries, \ - gen_CodeDefineParams: gen_code__has_entries, \ - gen_CodeDestructor: gen_code__has_entries, \ - gen_CodeEnum: gen_code__has_entries, \ - gen_CodeExec: gen_code__has_entries, \ - gen_CodeExtern: gen_code__has_entries, \ - gen_CodeInclude: gen_code__has_entries, \ - gen_CodeFriend: gen_code__has_entries, \ - gen_CodeFn: gen_code__has_entries, \ - gen_CodeModule: gen_code__has_entries, \ - gen_CodeNS: gen_code__has_entries, \ - gen_CodeOperator: gen_code__has_entries, \ - gen_CodeOpCast: gen_code__has_entries, \ - gen_CodePragma: gen_code__has_entries, \ - gen_CodeParams: gen_code__has_entries, \ - gen_CodePreprocessCond: gen_code__has_entries, \ - gen_CodeSpecifiers: gen_code__has_entries, \ - gen_CodeStruct: gen_code__has_entries, \ - gen_CodeTemplate: gen_code__has_entries, \ - gen_CodeTypename: gen_code__has_entries, \ - gen_CodeTypedef: gen_code__has_entries, \ - gen_CodeUnion: gen_code__has_entries, \ - gen_CodeUsing: gen_code__has_entries, \ - gen_CodeVar: gen_code__has_entries, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code) - -#define gen_code_is_body(code) \ - _Generic( \ - (code), \ - gen_Code: gen_code__is_body, \ - gen_CodeBody: gen_code__is_body, \ - gen_CodeAttributes: gen_code__is_body, \ - gen_CodeComment: gen_code__is_body, \ - gen_CodeClass: gen_code__is_body, \ - gen_CodeConstructor: gen_code__is_body, \ - gen_CodeDefine: gen_code__is_body, \ - gen_CodeDefineParams: gen_code__is_body, \ - gen_CodeDestructor: gen_code__is_body, \ - gen_CodeEnum: gen_code__is_body, \ - gen_CodeExec: gen_code__is_body, \ - gen_CodeExtern: gen_code__is_body, \ - gen_CodeInclude: gen_code__is_body, \ - gen_CodeFriend: gen_code__is_body, \ - gen_CodeFn: gen_code__is_body, \ - gen_CodeModule: gen_code__is_body, \ - gen_CodeNS: gen_code__is_body, \ - gen_CodeOperator: gen_code__is_body, \ - gen_CodeOpCast: gen_code__is_body, \ - gen_CodePragma: gen_code__is_body, \ - gen_CodeParams: gen_code__is_body, \ - gen_CodePreprocessCond: gen_code__is_body, \ - gen_CodeSpecifiers: gen_code__is_body, \ - gen_CodeStruct: gen_code__is_body, \ - gen_CodeTemplate: gen_code__is_body, \ - gen_CodeTypename: gen_code__is_body, \ - gen_CodeTypedef: gen_code__is_body, \ - gen_CodeUnion: gen_code__is_body, \ - gen_CodeUsing: gen_code__is_body, \ - gen_CodeVar: gen_code__is_body, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code) - -#define gen_code_is_equal(code, other) \ - _Generic( \ - (code), \ - gen_Code: gen_code__is_equal, \ - gen_CodeBody: gen_code__is_equal, \ - gen_CodeAttributes: gen_code__is_equal, \ - gen_CodeComment: gen_code__is_equal, \ - gen_CodeClass: gen_code__is_equal, \ - gen_CodeConstructor: gen_code__is_equal, \ - gen_CodeDefine: gen_code__is_equal, \ - gen_CodeDefineParams: gen_code__is_equal, \ - gen_CodeDestructor: gen_code__is_equal, \ - gen_CodeEnum: gen_code__is_equal, \ - gen_CodeExec: gen_code__is_equal, \ - gen_CodeExtern: gen_code__is_equal, \ - gen_CodeInclude: gen_code__is_equal, \ - gen_CodeFriend: gen_code__is_equal, \ - gen_CodeFn: gen_code__is_equal, \ - gen_CodeModule: gen_code__is_equal, \ - gen_CodeNS: gen_code__is_equal, \ - gen_CodeOperator: gen_code__is_equal, \ - gen_CodeOpCast: gen_code__is_equal, \ - gen_CodePragma: gen_code__is_equal, \ - gen_CodeParams: gen_code__is_equal, \ - gen_CodePreprocessCond: gen_code__is_equal, \ - gen_CodeSpecifiers: gen_code__is_equal, \ - gen_CodeStruct: gen_code__is_equal, \ - gen_CodeTemplate: gen_code__is_equal, \ - gen_CodeTypename: gen_code__is_equal, \ - gen_CodeTypedef: gen_code__is_equal, \ - gen_CodeUnion: gen_code__is_equal, \ - gen_CodeUsing: gen_code__is_equal, \ - gen_CodeVar: gen_code__is_equal, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code, other) - -#define gen_code_is_valid(code) \ - _Generic( \ - (code), \ - gen_Code: gen_code__is_valid, \ - gen_CodeBody: gen_code__is_valid, \ - gen_CodeAttributes: gen_code__is_valid, \ - gen_CodeComment: gen_code__is_valid, \ - gen_CodeClass: gen_code__is_valid, \ - gen_CodeConstructor: gen_code__is_valid, \ - gen_CodeDefine: gen_code__is_valid, \ - gen_CodeDefineParams: gen_code__is_valid, \ - gen_CodeDestructor: gen_code__is_valid, \ - gen_CodeEnum: gen_code__is_valid, \ - gen_CodeExec: gen_code__is_valid, \ - gen_CodeExtern: gen_code__is_valid, \ - gen_CodeInclude: gen_code__is_valid, \ - gen_CodeFriend: gen_code__is_valid, \ - gen_CodeFn: gen_code__is_valid, \ - gen_CodeModule: gen_code__is_valid, \ - gen_CodeNS: gen_code__is_valid, \ - gen_CodeOperator: gen_code__is_valid, \ - gen_CodeOpCast: gen_code__is_valid, \ - gen_CodePragma: gen_code__is_valid, \ - gen_CodeParams: gen_code__is_valid, \ - gen_CodePreprocessCond: gen_code__is_valid, \ - gen_CodeSpecifiers: gen_code__is_valid, \ - gen_CodeStruct: gen_code__is_valid, \ - gen_CodeTemplate: gen_code__is_valid, \ - gen_CodeTypename: gen_code__is_valid, \ - gen_CodeTypedef: gen_code__is_valid, \ - gen_CodeUnion: gen_code__is_valid, \ - gen_CodeUsing: gen_code__is_valid, \ - gen_CodeVar: gen_code__is_valid, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code) - -#define gen_code_set_global(code) \ - _Generic( \ - (code), \ - gen_Code: gen_code__set_global, \ - gen_CodeBody: gen_code__set_global, \ - gen_CodeAttributes: gen_code__set_global, \ - gen_CodeComment: gen_code__set_global, \ - gen_CodeClass: gen_code__set_global, \ - gen_CodeConstructor: gen_code__set_global, \ - gen_CodeDefine: gen_code__set_global, \ - gen_CodeDefineParams: gen_code__set_global, \ - gen_CodeDestructor: gen_code__set_global, \ - gen_CodeEnum: gen_code__set_global, \ - gen_CodeExec: gen_code__set_global, \ - gen_CodeExtern: gen_code__set_global, \ - gen_CodeInclude: gen_code__set_global, \ - gen_CodeFriend: gen_code__set_global, \ - gen_CodeFn: gen_code__set_global, \ - gen_CodeModule: gen_code__set_global, \ - gen_CodeNS: gen_code__set_global, \ - gen_CodeOperator: gen_code__set_global, \ - gen_CodeOpCast: gen_code__set_global, \ - gen_CodePragma: gen_code__set_global, \ - gen_CodeParams: gen_code__set_global, \ - gen_CodePreprocessCond: gen_code__set_global, \ - gen_CodeSpecifiers: gen_code__set_global, \ - gen_CodeStruct: gen_code__set_global, \ - gen_CodeTemplate: gen_code__set_global, \ - gen_CodeTypename: gen_code__set_global, \ - gen_CodeTypedef: gen_code__set_global, \ - gen_CodeUnion: gen_code__set_global, \ - gen_CodeUsing: gen_code__set_global, \ - gen_CodeVar: gen_code__set_global, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code) - -#define gen_code_to_strbuilder(code) \ - _Generic( \ - (code), \ - gen_Code: gen_code__to_strbuilder, \ - gen_CodeBody: gen_code__to_strbuilder, \ - gen_CodeAttributes: gen_code__to_strbuilder, \ - gen_CodeComment: gen_code__to_strbuilder, \ - gen_CodeClass: gen_code__to_strbuilder, \ - gen_CodeConstructor: gen_code__to_strbuilder, \ - gen_CodeDefine: gen_code__to_strbuilder, \ - gen_CodeDefineParams: gen_code__to_strbuilder, \ - gen_CodeDestructor: gen_code__to_strbuilder, \ - gen_CodeEnum: gen_code__to_strbuilder, \ - gen_CodeExec: gen_code__to_strbuilder, \ - gen_CodeExtern: gen_code__to_strbuilder, \ - gen_CodeInclude: gen_code__to_strbuilder, \ - gen_CodeFriend: gen_code__to_strbuilder, \ - gen_CodeFn: gen_code__to_strbuilder, \ - gen_CodeModule: gen_code__to_strbuilder, \ - gen_CodeNS: gen_code__to_strbuilder, \ - gen_CodeOperator: gen_code__to_strbuilder, \ - gen_CodeOpCast: gen_code__to_strbuilder, \ - gen_CodePragma: gen_code__to_strbuilder, \ - gen_CodeParams: gen_code__to_strbuilder, \ - gen_CodePreprocessCond: gen_code__to_strbuilder, \ - gen_CodeSpecifiers: gen_code__to_strbuilder, \ - gen_CodeStruct: gen_code__to_strbuilder, \ - gen_CodeTemplate: gen_code__to_strbuilder, \ - gen_CodeTypename: gen_code__to_strbuilder, \ - gen_CodeTypedef: gen_code__to_strbuilder, \ - gen_CodeUnion: gen_code__to_strbuilder, \ - gen_CodeUsing: gen_code__to_strbuilder, \ - gen_CodeVar: gen_code__to_strbuilder, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code) - -#define gen_code_to_strbuilder_ref(code, result) \ - _Generic( \ - (code), \ - 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) - -#define gen_code_type_str(code) \ - _Generic( \ - (code), \ - gen_Code: gen_code__type_str, \ - gen_CodeBody: gen_code__type_str, \ - gen_CodeAttributes: gen_code__type_str, \ - gen_CodeComment: gen_code__type_str, \ - gen_CodeClass: gen_code__type_str, \ - gen_CodeConstructor: gen_code__type_str, \ - gen_CodeDefine: gen_code__type_str, \ - gen_CodeDefineParams: gen_code__type_str, \ - gen_CodeDestructor: gen_code__type_str, \ - gen_CodeEnum: gen_code__type_str, \ - gen_CodeExec: gen_code__type_str, \ - gen_CodeExtern: gen_code__type_str, \ - gen_CodeInclude: gen_code__type_str, \ - gen_CodeFriend: gen_code__type_str, \ - gen_CodeFn: gen_code__type_str, \ - gen_CodeModule: gen_code__type_str, \ - gen_CodeNS: gen_code__type_str, \ - gen_CodeOperator: gen_code__type_str, \ - gen_CodeOpCast: gen_code__type_str, \ - gen_CodePragma: gen_code__type_str, \ - gen_CodeParams: gen_code__type_str, \ - gen_CodePreprocessCond: gen_code__type_str, \ - gen_CodeSpecifiers: gen_code__type_str, \ - gen_CodeStruct: gen_code__type_str, \ - gen_CodeTemplate: gen_code__type_str, \ - gen_CodeTypename: gen_code__type_str, \ - gen_CodeTypedef: gen_code__type_str, \ - gen_CodeUnion: gen_code__type_str, \ - gen_CodeUsing: gen_code__type_str, \ - gen_CodeVar: gen_code__type_str, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code) - -#define gen_code_validate_body(code) \ - _Generic( \ - (code), \ - gen_Code: gen_code__validate_body, \ - gen_CodeBody: gen_code__validate_body, \ - gen_CodeAttributes: gen_code__validate_body, \ - gen_CodeComment: gen_code__validate_body, \ - gen_CodeClass: gen_code__validate_body, \ - gen_CodeConstructor: gen_code__validate_body, \ - gen_CodeDefine: gen_code__validate_body, \ - gen_CodeDefineParams: gen_code__validate_body, \ - gen_CodeDestructor: gen_code__validate_body, \ - gen_CodeEnum: gen_code__validate_body, \ - gen_CodeExec: gen_code__validate_body, \ - gen_CodeExtern: gen_code__validate_body, \ - gen_CodeInclude: gen_code__validate_body, \ - gen_CodeFriend: gen_code__validate_body, \ - gen_CodeFn: gen_code__validate_body, \ - gen_CodeModule: gen_code__validate_body, \ - gen_CodeNS: gen_code__validate_body, \ - gen_CodeOperator: gen_code__validate_body, \ - gen_CodeOpCast: gen_code__validate_body, \ - gen_CodePragma: gen_code__validate_body, \ - gen_CodeParams: gen_code__validate_body, \ - gen_CodePreprocessCond: gen_code__validate_body, \ - gen_CodeSpecifiers: gen_code__validate_body, \ - gen_CodeStruct: gen_code__validate_body, \ - gen_CodeTemplate: gen_code__validate_body, \ - gen_CodeTypename: gen_code__validate_body, \ - gen_CodeTypedef: gen_code__validate_body, \ - gen_CodeUnion: gen_code__validate_body, \ - gen_CodeUsing: gen_code__validate_body, \ - gen_CodeVar: gen_code__validate_body, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL((gen_Code)code) - - - -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); -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_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); - -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); - -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_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); - -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_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); - -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_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); - -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_StrBuilder gen_attributes_to_strbuilder(gen_CodeAttributes attributes); -void gen_attributes_to_strbuilder_ref(gen_CodeAttributes attributes, 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); -GEN_API void gen_constructor__to_strbuilder_fwd(gen_CodeConstructor gen_constructor_, gen_StrBuilder* result); - -GEN_API gen_StrBuilder gen_define_to_strbuilder(gen_CodeDefine self); -GEN_API void gen_define_to_strbuilder_ref(gen_CodeDefine self, gen_StrBuilder* result); - -GEN_API gen_StrBuilder gen_destructor__to_strbuilder(gen_CodeDestructor gen_destructor_); -GEN_API void gen_destructor__to_strbuilder_fwd(gen_CodeDestructor gen_destructor_, gen_StrBuilder* result); -GEN_API void gen_destructor__to_strbuilder_def(gen_CodeDestructor gen_destructor_, gen_StrBuilder* result); - -GEN_API gen_StrBuilder gen_enum_to_strbuilder(gen_CodeEnum self); -GEN_API void gen_enum_to_strbuilder_def(gen_CodeEnum self, gen_StrBuilder* result); -GEN_API void gen_enum_to_strbuilder_fwd(gen_CodeEnum self, gen_StrBuilder* result); -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_StrBuilder gen_exec_to_strbuilder(gen_CodeExec exec); -void gen_exec_to_strbuilder_ref(gen_CodeExec exec, gen_StrBuilder* result); - -void gen_extern_to_strbuilder(gen_CodeExtern 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_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_StrBuilder gen_module_to_strbuilder(gen_CodeModule self); -GEN_API void gen_module_to_strbuilder_ref(gen_CodeModule 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); -GEN_API void gen_code_op_to_strbuilder_def(gen_CodeOperator self, gen_StrBuilder* result); - -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_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); -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_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_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_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_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 - -#pragma region gen_AST Types - -/* - ______ ______ ________ ________ - / \ / \| \ | \ -| ▓▓▓▓▓▓\ ▓▓▓▓▓▓\\▓▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓▓__ __ ______ ______ _______ -| ▓▓__| ▓▓ ▓▓___\▓▓ | ▓▓ | ▓▓ | \ | \/ \ / \ / \ -| ▓▓ ▓▓\▓▓ \ | ▓▓ | ▓▓ | ▓▓ | ▓▓ ▓▓▓▓▓▓\ ▓▓▓▓▓▓\ ▓▓▓▓▓▓▓ -| ▓▓▓▓▓▓▓▓_\▓▓▓▓▓▓\ | ▓▓ | ▓▓ | ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓ ▓▓\▓▓ \ -| ▓▓ | ▓▓ \__| ▓▓ | ▓▓ | ▓▓ | ▓▓__/ ▓▓ ▓▓__/ ▓▓ ▓▓▓▓▓▓▓▓_\▓▓▓▓▓▓\ -| ▓▓ | ▓▓\▓▓ ▓▓ | ▓▓ | ▓▓ \▓▓ ▓▓ ▓▓ ▓▓\▓▓ \ ▓▓ - \▓▓ \▓▓ \▓▓▓▓▓▓ \▓▓ \▓▓ _\▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓\▓▓▓▓▓▓▓ - | \__| ▓▓ ▓▓ - \▓▓ ▓▓ ▓▓ - \▓▓▓▓▓▓ \▓▓ -*/ - -/* - Show only relevant members of the gen_AST for its type. - gen_AST* fields are replaced with gen_Code types. - - Guards assignemnts to gen_AST* fields to ensure the gen_AST is duplicated if assigned to another parent. -*/ - -struct gen_AST_Body -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - }; - - gen_StrCached Name; - gen_Code Front; - gen_Code Back; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag)]; - gen_s32 NumEntries; -}; -typedef struct gen_AST_Body gen_AST_Body; -gen_static_assert(sizeof(gen_AST_Body) == sizeof(gen_AST), "ERROR: gen_AST_Body is not the same size as gen_AST"); - -// TODO(Ed): Support chaining attributes (Use parameter linkage pattern) -struct gen_AST_Attributes -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - gen_StrCached Content; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_Attributes gen_AST_Attributes; -gen_static_assert(sizeof(gen_AST_Attributes) == sizeof(gen_AST), "ERROR: gen_AST_Attributes is not the same size as gen_AST"); - -#if 0 -struct gen_AST_BaseClass -{ -union -{ -char _PAD_[ 64 ]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - -}; -gen_StrCached Name; -gen_Code Prev; -gen_Code Next; -gen_Token * Tok; -gen_Code Parent; -gen_CodeType Type; -char _PAD_UNUSED_[ sizeof(gen_ModuleFlag) + sizeof(gen_u32) ]; - -}; -typedef struct gen_AST_BaseClass gen_AST_BaseClass; -gen_static_assert( sizeof(gen_AST_BaseClass) == sizeof(gen_AST), "ERROR: gen_AST_BaseClass is not the same size as gen_AST"); -#endif - -struct gen_AST_Comment -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - gen_StrCached Content; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_Comment gen_AST_Comment; -gen_static_assert(sizeof(gen_AST_Comment) == sizeof(gen_AST), "ERROR: gen_AST_Comment is not the same size as gen_AST"); - -struct gen_AST_Class -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; // Only supported by forward declarations - gen_CodeAttributes Attributes; - gen_CodeSpecifiers Specs; // Support for final - gen_CodeTypename ParentType; - char _PAD_PARAMS_[sizeof(gen_AST*)]; - gen_CodeBody Body; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_CodeTypename Prev; - gen_CodeTypename Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - gen_AccessSpec ParentAccess; -}; -typedef struct gen_AST_Class gen_AST_Class; -gen_static_assert(sizeof(gen_AST_Class) == sizeof(gen_AST), "ERROR: gen_AST_Class is not the same size as gen_AST"); - -struct gen_AST_Constructor -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; // Only supported by forward declarations - char _PAD_PROPERTIES_[sizeof(gen_AST*) * 1]; - gen_CodeSpecifiers Specs; - gen_Code InitializerList; - gen_CodeParams Params; - gen_Code Body; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*) * 2]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_Constructor gen_AST_Constructor; -gen_static_assert(sizeof(gen_AST_Constructor) == sizeof(gen_AST), "ERROR: gen_AST_Constructor is not the same size as gen_AST"); - -struct gen_AST_Define -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - char _PAD_PROPERTIES_[sizeof(gen_AST*) * 4]; - gen_CodeDefineParams Params; - gen_Code Body; // Should be completely serialized for now to a: gen_StrCached Content. - char _PAD_PROPERTIES_2_[sizeof(gen_AST*) * 1]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_Define gen_AST_Define; -gen_static_assert(sizeof(gen_AST_Define) == sizeof(gen_AST), "ERROR: gen_AST_Define is not the same size as gen_AST"); - -struct gen_AST_DefineParams -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - }; - - gen_StrCached Name; - gen_CodeDefineParams Last; - gen_CodeDefineParams Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag)]; - gen_s32 NumEntries; -}; -typedef struct gen_AST_DefineParams gen_AST_DefineParams; -gen_static_assert(sizeof(gen_AST_DefineParams) == sizeof(gen_AST), "ERROR: gen_AST_DefineParams is not the same size as gen_AST"); - -struct gen_AST_Destructor -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; - char _PAD_PROPERTIES_[sizeof(gen_AST*) * 1]; - gen_CodeSpecifiers Specs; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*) * 2]; - gen_Code Body; - char _PAD_PROPERTIES_3_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_Destructor gen_AST_Destructor; -gen_static_assert(sizeof(gen_AST_Destructor) == sizeof(gen_AST), "ERROR: gen_AST_Destructor is not the same size as gen_AST"); - -struct gen_AST_Enum -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; - gen_CodeAttributes Attributes; - char _PAD_SPEC_[sizeof(gen_AST*)]; - gen_CodeTypename UnderlyingType; - gen_Code UnderlyingTypeMacro; - gen_CodeBody Body; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - 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"); - -struct gen_AST_Exec -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - gen_StrCached Content; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_Exec gen_AST_Exec; -gen_static_assert(sizeof(gen_AST_Exec) == sizeof(gen_AST), "ERROR: gen_AST_Exec is not the same size as gen_AST"); - -struct gen_AST_Extern -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - char _PAD_PROPERTIES_[sizeof(gen_AST*) * 5]; - gen_CodeBody Body; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_Extern gen_AST_Extern; -gen_static_assert(sizeof(gen_AST_Extern) == sizeof(gen_AST), "ERROR: gen_AST_Extern is not the same size as gen_AST"); - -struct gen_AST_Include -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - gen_StrCached Content; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_Include gen_AST_Include; -gen_static_assert(sizeof(gen_AST_Include) == sizeof(gen_AST), "ERROR: gen_AST_Include is not the same size as gen_AST"); - -struct gen_AST_Friend -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; - char _PAD_PROPERTIES_[sizeof(gen_AST*) * 4]; - gen_Code Declaration; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_Friend gen_AST_Friend; -gen_static_assert(sizeof(gen_AST_Friend) == sizeof(gen_AST), "ERROR: gen_AST_Friend is not the same size as gen_AST"); - -struct gen_AST_Fn -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; - gen_CodeAttributes Attributes; - gen_CodeSpecifiers Specs; - gen_CodeTypename ReturnType; - gen_CodeParams Params; - gen_CodeBody Body; - gen_Code SuffixSpecs; // Thanks Unreal - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - char _PAD_UNUSED_[sizeof(gen_u32)]; -}; -typedef struct gen_AST_Fn gen_AST_Fn; -gen_static_assert(sizeof(gen_AST_Fn) == sizeof(gen_AST), "ERROR: gen_AST_Fn is not the same size as gen_AST"); - -struct gen_AST_Module -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - char _PAD_UNUSED_[sizeof(gen_u32)]; -}; -typedef struct gen_AST_Module gen_AST_Module; -gen_static_assert(sizeof(gen_AST_Module) == sizeof(gen_AST), "ERROR: gen_AST_Module is not the same size as gen_AST"); - -struct gen_AST_NS -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - char _PAD_PROPERTIES_[sizeof(gen_AST*) * 5]; - gen_CodeBody Body; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - char _PAD_UNUSED_[sizeof(gen_u32)]; -}; -typedef struct gen_AST_NS gen_AST_NS; -gen_static_assert(sizeof(gen_AST_NS) == sizeof(gen_AST), "ERROR: gen_AST_NS is not the same size as gen_AST"); - -struct gen_AST_Operator -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; - gen_CodeAttributes Attributes; - gen_CodeSpecifiers Specs; - gen_CodeTypename ReturnType; - gen_CodeParams Params; - gen_CodeBody Body; - char _PAD_PROPERTIES_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - gen_Operator Op; -}; -typedef struct gen_AST_Operator gen_AST_Operator; -gen_static_assert(sizeof(gen_AST_Operator) == sizeof(gen_AST), "ERROR: gen_AST_Operator is not the same size as gen_AST"); - -struct gen_AST_OpCast -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; - char _PAD_PROPERTIES_[sizeof(gen_AST*)]; - gen_CodeSpecifiers Specs; - gen_CodeTypename ValueType; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*)]; - gen_CodeBody Body; - char _PAD_PROPERTIES_3_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_OpCast gen_AST_OpCast; -gen_static_assert(sizeof(gen_AST_OpCast) == sizeof(gen_AST), "ERROR: gen_AST_OpCast is not the same size as gen_AST"); - -struct gen_AST_Params -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - // TODO(Ed): Support attributes for parameters (Some prefix macros can be converted to that...) - char _PAD_PROPERTIES_2_[sizeof(gen_AST*) * 3]; - gen_CodeTypename ValueType; - gen_Code gen_Macro; - gen_Code Value; - gen_Code PostNameMacro; // Thanks Unreal - // char _PAD_PROPERTIES_3_[sizeof( gen_AST* )]; - }; - }; - - gen_StrCached Name; - gen_CodeParams Last; - gen_CodeParams Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag)]; - gen_s32 NumEntries; -}; -typedef struct gen_AST_Params gen_AST_Params; -gen_static_assert(sizeof(gen_AST_Params) == sizeof(gen_AST), "ERROR: gen_AST_Params is not the same size as gen_AST"); - -struct gen_AST_Pragma -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - gen_StrCached Content; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_Pragma gen_AST_Pragma; -gen_static_assert(sizeof(gen_AST_Pragma) == sizeof(gen_AST), "ERROR: gen_AST_Pragma is not the same size as gen_AST"); - -struct gen_AST_PreprocessCond -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - gen_StrCached Content; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag) + sizeof(gen_u32)]; -}; -typedef struct gen_AST_PreprocessCond gen_AST_PreprocessCond; -gen_static_assert(sizeof(gen_AST_PreprocessCond) == sizeof(gen_AST), "ERROR: gen_AST_PreprocessCond is not the same size as gen_AST"); - -struct gen_AST_Specifiers -{ - gen_Specifier ArrSpecs[gen_AST_ArrSpecs_Cap]; - gen_CodeSpecifiers NextSpecs; - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag)]; - gen_s32 NumEntries; -}; -typedef struct gen_AST_Specifiers gen_AST_Specifiers; -gen_static_assert(sizeof(gen_AST_Specifiers) == sizeof(gen_AST), "ERROR: gen_AST_Specifier is not the same size as gen_AST"); - -struct gen_AST_Struct -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; - gen_CodeAttributes Attributes; - gen_CodeSpecifiers Specs; // Support for final - gen_CodeTypename ParentType; - char _PAD_PARAMS_[sizeof(gen_AST*)]; - gen_CodeBody Body; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_CodeTypename Prev; - gen_CodeTypename Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - gen_AccessSpec ParentAccess; -}; -typedef struct gen_AST_Struct gen_AST_Struct; -gen_static_assert(sizeof(gen_AST_Struct) == sizeof(gen_AST), "ERROR: gen_AST_Struct is not the same size as gen_AST"); - -struct gen_AST_Template -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - char _PAD_PROPERTIES_[sizeof(gen_AST*) * 4]; - gen_CodeParams Params; - gen_Code Declaration; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - char _PAD_UNUSED_[sizeof(gen_u32)]; -}; -typedef struct gen_AST_Template gen_AST_Template; -gen_static_assert(sizeof(gen_AST_Template) == sizeof(gen_AST), "ERROR: gen_AST_Template is not the same size as gen_AST"); - -#if 0 -// WIP... The type ast is going to become more advanced and lead to a major change to gen_AST design. -struct gen_AST_Type -{ -union -{ -char _PAD_[ 64 ]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C -struct -{ -char _PAD_INLINE_CMT_[ sizeof(gen_AST*) ]; -gen_CodeAttributes Attributes; -gen_CodeSpecifiers Specs; -gen_Code QualifierID; -// gen_CodeTypename ReturnType; // Only used for function signatures -// gen_CodeParams Params; // Only used for function signatures -gen_Code ArrExpr; -// gen_CodeSpecifiers SpecsFuncSuffix; // Only used for function signatures - -}; - -}; -gen_StrCached Name; -gen_Code Prev; -gen_Code Next; -gen_Token * Tok; -gen_Code Parent; -gen_CodeType Type; -char _PAD_UNUSED_[ sizeof(gen_ModuleFlag) ]; -gen_b32 IsParamPack; - -}; -typedef struct gen_AST_Type gen_AST_Type; -gen_static_assert( sizeof(gen_AST_Type) == sizeof(gen_AST), "ERROR: gen_AST_Type is not the same size as gen_AST"); -#endif - -struct gen_AST_Typename -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - char _PAD_INLINE_CMT_[sizeof(gen_AST*)]; - gen_CodeAttributes Attributes; - gen_CodeSpecifiers Specs; - gen_CodeTypename ReturnType; // Only used for function signatures - gen_CodeParams Params; // Only used for function signatures - gen_Code ArrExpr; - gen_CodeSpecifiers SpecsFuncSuffix; // Only used for function signatures - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - char _PAD_UNUSED_[sizeof(gen_ModuleFlag)]; - - struct - { - gen_b16 IsParamPack; // Used by typename to know if type should be considered a parameter pack. - gen_ETypenameTag TypeTag; // Used by typename to keep track of explicitly declared tags for the identifier (enum, struct, union) - }; -}; -typedef struct gen_AST_Typename gen_AST_Typename; -gen_static_assert(sizeof(gen_AST_Typename) == sizeof(gen_AST), "ERROR: gen_AST_Type is not the same size as gen_AST"); - -struct gen_AST_Typedef -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; - char _PAD_PROPERTIES_[sizeof(gen_AST*) * 2]; - gen_Code UnderlyingType; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*) * 3]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - gen_b32 IsFunction; -}; -typedef struct gen_AST_Typedef gen_AST_Typedef; -gen_static_assert(sizeof(gen_AST_Typedef) == sizeof(gen_AST), "ERROR: gen_AST_Typedef is not the same size as gen_AST"); - -struct gen_AST_Union -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - char _PAD_INLINE_CMT_[sizeof(gen_AST*)]; - gen_CodeAttributes Attributes; - char _PAD_PROPERTIES_[sizeof(gen_AST*) * 3]; - gen_CodeBody Body; - char _PAD_PROPERTIES_2_[sizeof(gen_AST*)]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - char _PAD_UNUSED_[sizeof(gen_u32)]; -}; -typedef struct gen_AST_Union gen_AST_Union; -gen_static_assert(sizeof(gen_AST_Union) == sizeof(gen_AST), "ERROR: gen_AST_Union is not the same size as gen_AST"); - -struct gen_AST_Using -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; - gen_CodeAttributes Attributes; - char _PAD_SPECS_[sizeof(gen_AST*)]; - gen_CodeTypename UnderlyingType; - char _PAD_PROPERTIES_[sizeof(gen_AST*) * 3]; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - char _PAD_UNUSED_[sizeof(gen_u32)]; -}; -typedef struct gen_AST_Using gen_AST_Using; -gen_static_assert(sizeof(gen_AST_Using) == sizeof(gen_AST), "ERROR: gen_AST_Using is not the same size as gen_AST"); - -struct gen_AST_Var -{ - union - { - char _PAD_[64]; // Had to hardcode _PAD_ because (sizeof(gen_Specifier) * gen_AST_ArrSpecs_Cap + sizeof(gen_AST*)) was 67 bytes in C - - struct - { - gen_CodeComment InlineCmt; - gen_CodeAttributes Attributes; - gen_CodeSpecifiers Specs; - gen_CodeTypename ValueType; - gen_Code BitfieldSize; - gen_Code Value; - gen_CodeVar NextVar; - }; - }; - - gen_StrCached Name; - gen_Code Prev; - gen_Code Next; - gen_Token* Tok; - gen_Code Parent; - gen_CodeType Type; - gen_ModuleFlag ModuleFlags; - gen_s32 VarParenthesizedInit; -}; -typedef struct gen_AST_Var gen_AST_Var; -gen_static_assert(sizeof(gen_AST_Var) == sizeof(gen_AST), "ERROR: gen_AST_Var is not the same size as gen_AST"); - -#pragma endregion gen_AST Types - -#pragma endregion AST - -#pragma region gen_Array_gen_Arena - -#define GEN_GENERIC_SLOT_7__array_init gen_Arena, gen_Array_gen_Arena_init -#define GEN_GENERIC_SLOT_7__array_init_reserve gen_Arena, gen_Array_gen_Arena_init_reserve -#define GEN_GENERIC_SLOT_7__array_append gen_Array_gen_Arena, gen_Array_gen_Arena_append -#define GEN_GENERIC_SLOT_7__array_append_items gen_Array_gen_Arena, gen_Array_gen_Arena_append_items -#define GEN_GENERIC_SLOT_7__array_append_at gen_Array_gen_Arena, gen_Array_gen_Arena_append_at -#define GEN_GENERIC_SLOT_7__array_append_items_at gen_Array_gen_Arena, gen_Array_gen_Arena_append_items_at -#define GEN_GENERIC_SLOT_7__array_back gen_Array_gen_Arena, gen_Array_gen_Arena_back -#define GEN_GENERIC_SLOT_7__array_clear gen_Array_gen_Arena, gen_Array_gen_Arena_clear -#define GEN_GENERIC_SLOT_7__array_fill gen_Array_gen_Arena, gen_Array_gen_Arena_fill -#define GEN_GENERIC_SLOT_7__array_free gen_Array_gen_Arena, gen_Array_gen_Arena_free -#define GEN_GENERIC_SLOT_7__array_grow gen_Array_gen_Arena*, gen_Array_gen_Arena_grow -#define GEN_GENERIC_SLOT_7__array_num gen_Array_gen_Arena, gen_Array_gen_Arena_num -#define GEN_GENERIC_SLOT_7__array_pop gen_Array_gen_Arena, gen_Array_gen_Arena_pop -#define GEN_GENERIC_SLOT_7__array_remove_at gen_Array_gen_Arena, gen_Array_gen_Arena_remove_at -#define GEN_GENERIC_SLOT_7__array_reserve gen_Array_gen_Arena, gen_Array_gen_Arena_reserve -#define GEN_GENERIC_SLOT_7__array_resize gen_Array_gen_Arena, gen_Array_gen_Arena_resize -#define GEN_GENERIC_SLOT_7__array_set_capacity gen_Array_gen_Arena*, gen_Array_gen_Arena_set_capacity - -typedef gen_Arena* gen_Array_gen_Arena; -gen_Array_gen_Arena gen_Array_gen_Arena_init(gen_AllocatorInfo allocator); -gen_Array_gen_Arena gen_Array_gen_Arena_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity); -bool gen_Array_gen_Arena_append_array(gen_Array_gen_Arena* self, gen_Array_gen_Arena other); -bool gen_Array_gen_Arena_append(gen_Array_gen_Arena* self, gen_Arena value); -bool gen_Array_gen_Arena_append_items(gen_Array_gen_Arena* self, gen_Arena* items, gen_usize item_num); -bool gen_Array_gen_Arena_append_at(gen_Array_gen_Arena* self, gen_Arena item, gen_usize idx); -bool gen_Array_gen_Arena_append_items_at(gen_Array_gen_Arena* self, gen_Arena* items, gen_usize item_num, gen_usize idx); -gen_Arena* gen_Array_gen_Arena_back(gen_Array_gen_Arena self); -void gen_Array_gen_Arena_clear(gen_Array_gen_Arena self); -bool gen_Array_gen_Arena_fill(gen_Array_gen_Arena self, gen_usize begin, gen_usize end, gen_Arena value); -void gen_Array_gen_Arena_free(gen_Array_gen_Arena* self); -bool gen_Array_gen_Arena_grow(gen_Array_gen_Arena* self, gen_usize min_capacity); -gen_usize gen_Array_gen_Arena_num(gen_Array_gen_Arena self); -gen_Arena gen_Array_gen_Arena_pop(gen_Array_gen_Arena self); -void gen_Array_gen_Arena_remove_at(gen_Array_gen_Arena self, gen_usize idx); -bool gen_Array_gen_Arena_reserve(gen_Array_gen_Arena* self, gen_usize new_capacity); -bool gen_Array_gen_Arena_resize(gen_Array_gen_Arena* self, gen_usize num); -bool gen_Array_gen_Arena_set_capacity(gen_Array_gen_Arena* self, gen_usize new_capacity); - -gen_forceinline gen_Array_gen_Arena gen_Array_gen_Arena_init(gen_AllocatorInfo allocator) -{ - size_t initial_size = gen_array_grow_formula(0); - return gen_array_init_reserve(gen_Arena, allocator, initial_size); -} - -inline gen_Array_gen_Arena gen_Array_gen_Arena_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity) -{ - GEN_ASSERT(capacity > 0); - gen_ArrayHeader* header = gen_rcast(gen_ArrayHeader*, gen_alloc(allocator, sizeof(gen_ArrayHeader) + sizeof(gen_Arena) * capacity)); - if (header == gen_nullptr) - return gen_nullptr; - header->Allocator = allocator; - header->Capacity = capacity; - header->Num = 0; - return gen_rcast(gen_Arena*, header + 1); -} - -gen_forceinline bool gen_Array_gen_Arena_append_array(gen_Array_gen_Arena* self, gen_Array_gen_Arena other) -{ - return gen_array_append_items(*self, (gen_Array_gen_Arena)other, gen_Array_gen_Arena_num(other)); -} - -inline bool gen_Array_gen_Arena_append(gen_Array_gen_Arena* self, gen_Arena value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num == header->Capacity) - { - if (! gen_array_grow(self, header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - (*self)[header->Num] = value; - header->Num++; - return true; -} - -inline bool gen_Array_gen_Arena_append_items(gen_Array_gen_Arena* self, gen_Arena* items, gen_usize item_num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(items != gen_nullptr); - GEN_ASSERT(item_num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num + item_num > header->Capacity) - { - if (! gen_array_grow(self, header->Capacity + item_num)) - return false; - header = gen_array_get_header(*self); - } - gen_mem_copy((*self) + header->Num, items, sizeof(gen_Arena) * item_num); - header->Num += item_num; - return true; -} - -inline bool gen_Array_gen_Arena_append_at(gen_Array_gen_Arena* self, gen_Arena item, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - idx = header->Num - 1; - if (idx < 0) - idx = 0; - if (header->Capacity < header->Num + 1) - { - if (! gen_array_grow(self, header->Capacity + 1)) - return false; - header = gen_array_get_header(*self); - } - gen_Array_gen_Arena target = (*self) + idx; - gen_mem_move(target + 1, target, (header->Num - idx) * sizeof(gen_Arena)); - header->Num++; - return true; -} - -inline bool gen_Array_gen_Arena_append_items_at(gen_Array_gen_Arena* self, gen_Arena* items, gen_usize item_num, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - { - return gen_array_append_items(*self, items, item_num); - } - if (item_num > header->Capacity) - { - if (! gen_array_grow(self, item_num + header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - gen_Arena* target = (*self) + idx + item_num; - gen_Arena* src = (*self) + idx; - gen_mem_move(target, src, (header->Num - idx) * sizeof(gen_Arena)); - gen_mem_copy(src, items, item_num * sizeof(gen_Arena)); - header->Num += item_num; - return true; -} - -inline gen_Arena* gen_Array_gen_Arena_back(gen_Array_gen_Arena self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - if (header->Num == 0) - return 0; - return self + header->Num - 1; -} - -inline void gen_Array_gen_Arena_clear(gen_Array_gen_Arena self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - header->Num = 0; -} - -inline bool gen_Array_gen_Arena_fill(gen_Array_gen_Arena self, gen_usize begin, gen_usize end, gen_Arena value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(begin <= end); - gen_ArrayHeader* header = gen_array_get_header(self); - if (begin < 0 || end > header->Num) - return false; - for (gen_ssize idx = (gen_ssize)begin; idx < (gen_ssize)end; idx++) - self[idx] = value; - return true; -} - -inline void gen_Array_gen_Arena_free(gen_Array_gen_Arena* self) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_allocator_free(header->Allocator, header); - self = 0; -} - -inline bool gen_Array_gen_Arena_grow(gen_Array_gen_Arena* self, gen_usize min_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(min_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_usize new_capacity = gen_array_grow_formula(header->Capacity); - if (new_capacity < min_capacity) - new_capacity = min_capacity; - return gen_array_set_capacity(self, new_capacity); -} - -gen_forceinline gen_usize gen_Array_gen_Arena_num(gen_Array_gen_Arena self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_array_get_header(self)->Num; -} - -inline gen_Arena gen_Array_gen_Arena_pop(gen_Array_gen_Arena self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(header->Num > 0); - gen_Arena result = self[header->Num - 1]; - header->Num--; - return result; -} - -gen_forceinline void gen_Array_gen_Arena_remove_at(gen_Array_gen_Arena self, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(idx < header->Num); - gen_mem_move(self + idx, self + idx + 1, sizeof(gen_Arena) * (header->Num - idx - 1)); - header->Num--; -} - -inline bool gen_Array_gen_Arena_reserve(gen_Array_gen_Arena* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < new_capacity) - return gen_array_set_capacity(self, new_capacity); - return true; -} - -inline bool gen_Array_gen_Arena_resize(gen_Array_gen_Arena* self, gen_usize num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < num) - { - if (! gen_array_grow(self, num)) - return false; - header = gen_array_get_header(*self); - } - header->Num = num; - return true; -} - -inline bool gen_Array_gen_Arena_set_capacity(gen_Array_gen_Arena* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (new_capacity == header->Capacity) - return true; - if (new_capacity < header->Num) - { - header->Num = new_capacity; - return true; - } - gen_usize size = sizeof(gen_ArrayHeader) + sizeof(gen_Arena) * new_capacity; - gen_ArrayHeader* new_header = gen_cast(gen_ArrayHeader*, gen_alloc(header->Allocator, size)); - if (new_header == 0) - return false; - gen_mem_move(new_header, header, sizeof(gen_ArrayHeader) + sizeof(gen_Arena) * header->Num); - new_header->Capacity = new_capacity; - gen_allocator_free(header->Allocator, &header); - *self = gen_cast(gen_Arena*, new_header + 1); - return true; -} - -#pragma endregion gen_Array_gen_Arena - -#pragma region gen_Array_gen_Pool - -#define GEN_GENERIC_SLOT_8__array_init gen_Pool, gen_Array_gen_Pool_init -#define GEN_GENERIC_SLOT_8__array_init_reserve gen_Pool, gen_Array_gen_Pool_init_reserve -#define GEN_GENERIC_SLOT_8__array_append gen_Array_gen_Pool, gen_Array_gen_Pool_append -#define GEN_GENERIC_SLOT_8__array_append_items gen_Array_gen_Pool, gen_Array_gen_Pool_append_items -#define GEN_GENERIC_SLOT_8__array_append_at gen_Array_gen_Pool, gen_Array_gen_Pool_append_at -#define GEN_GENERIC_SLOT_8__array_append_items_at gen_Array_gen_Pool, gen_Array_gen_Pool_append_items_at -#define GEN_GENERIC_SLOT_8__array_back gen_Array_gen_Pool, gen_Array_gen_Pool_back -#define GEN_GENERIC_SLOT_8__array_clear gen_Array_gen_Pool, gen_Array_gen_Pool_clear -#define GEN_GENERIC_SLOT_8__array_fill gen_Array_gen_Pool, gen_Array_gen_Pool_fill -#define GEN_GENERIC_SLOT_8__array_free gen_Array_gen_Pool, gen_Array_gen_Pool_free -#define GEN_GENERIC_SLOT_8__array_grow gen_Array_gen_Pool*, gen_Array_gen_Pool_grow -#define GEN_GENERIC_SLOT_8__array_num gen_Array_gen_Pool, gen_Array_gen_Pool_num -#define GEN_GENERIC_SLOT_8__array_pop gen_Array_gen_Pool, gen_Array_gen_Pool_pop -#define GEN_GENERIC_SLOT_8__array_remove_at gen_Array_gen_Pool, gen_Array_gen_Pool_remove_at -#define GEN_GENERIC_SLOT_8__array_reserve gen_Array_gen_Pool, gen_Array_gen_Pool_reserve -#define GEN_GENERIC_SLOT_8__array_resize gen_Array_gen_Pool, gen_Array_gen_Pool_resize -#define GEN_GENERIC_SLOT_8__array_set_capacity gen_Array_gen_Pool*, gen_Array_gen_Pool_set_capacity - -typedef gen_Pool* gen_Array_gen_Pool; -gen_Array_gen_Pool gen_Array_gen_Pool_init(gen_AllocatorInfo allocator); -gen_Array_gen_Pool gen_Array_gen_Pool_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity); -bool gen_Array_gen_Pool_append_array(gen_Array_gen_Pool* self, gen_Array_gen_Pool other); -bool gen_Array_gen_Pool_append(gen_Array_gen_Pool* self, gen_Pool value); -bool gen_Array_gen_Pool_append_items(gen_Array_gen_Pool* self, gen_Pool* items, gen_usize item_num); -bool gen_Array_gen_Pool_append_at(gen_Array_gen_Pool* self, gen_Pool item, gen_usize idx); -bool gen_Array_gen_Pool_append_items_at(gen_Array_gen_Pool* self, gen_Pool* items, gen_usize item_num, gen_usize idx); -gen_Pool* gen_Array_gen_Pool_back(gen_Array_gen_Pool self); -void gen_Array_gen_Pool_clear(gen_Array_gen_Pool self); -bool gen_Array_gen_Pool_fill(gen_Array_gen_Pool self, gen_usize begin, gen_usize end, gen_Pool value); -void gen_Array_gen_Pool_free(gen_Array_gen_Pool* self); -bool gen_Array_gen_Pool_grow(gen_Array_gen_Pool* self, gen_usize min_capacity); -gen_usize gen_Array_gen_Pool_num(gen_Array_gen_Pool self); -gen_Pool gen_Array_gen_Pool_pop(gen_Array_gen_Pool self); -void gen_Array_gen_Pool_remove_at(gen_Array_gen_Pool self, gen_usize idx); -bool gen_Array_gen_Pool_reserve(gen_Array_gen_Pool* self, gen_usize new_capacity); -bool gen_Array_gen_Pool_resize(gen_Array_gen_Pool* self, gen_usize num); -bool gen_Array_gen_Pool_set_capacity(gen_Array_gen_Pool* self, gen_usize new_capacity); - -gen_forceinline gen_Array_gen_Pool gen_Array_gen_Pool_init(gen_AllocatorInfo allocator) -{ - size_t initial_size = gen_array_grow_formula(0); - return gen_array_init_reserve(gen_Pool, allocator, initial_size); -} - -inline gen_Array_gen_Pool gen_Array_gen_Pool_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity) -{ - GEN_ASSERT(capacity > 0); - gen_ArrayHeader* header = gen_rcast(gen_ArrayHeader*, gen_alloc(allocator, sizeof(gen_ArrayHeader) + sizeof(gen_Pool) * capacity)); - if (header == gen_nullptr) - return gen_nullptr; - header->Allocator = allocator; - header->Capacity = capacity; - header->Num = 0; - return gen_rcast(gen_Pool*, header + 1); -} - -gen_forceinline bool gen_Array_gen_Pool_append_array(gen_Array_gen_Pool* self, gen_Array_gen_Pool other) -{ - return gen_array_append_items(*self, (gen_Array_gen_Pool)other, gen_Array_gen_Pool_num(other)); -} - -inline bool gen_Array_gen_Pool_append(gen_Array_gen_Pool* self, gen_Pool value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num == header->Capacity) - { - if (! gen_array_grow(self, header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - (*self)[header->Num] = value; - header->Num++; - return true; -} - -inline bool gen_Array_gen_Pool_append_items(gen_Array_gen_Pool* self, gen_Pool* items, gen_usize item_num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(items != gen_nullptr); - GEN_ASSERT(item_num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num + item_num > header->Capacity) - { - if (! gen_array_grow(self, header->Capacity + item_num)) - return false; - header = gen_array_get_header(*self); - } - gen_mem_copy((*self) + header->Num, items, sizeof(gen_Pool) * item_num); - header->Num += item_num; - return true; -} - -inline bool gen_Array_gen_Pool_append_at(gen_Array_gen_Pool* self, gen_Pool item, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - idx = header->Num - 1; - if (idx < 0) - idx = 0; - if (header->Capacity < header->Num + 1) - { - if (! gen_array_grow(self, header->Capacity + 1)) - return false; - header = gen_array_get_header(*self); - } - gen_Array_gen_Pool target = (*self) + idx; - gen_mem_move(target + 1, target, (header->Num - idx) * sizeof(gen_Pool)); - header->Num++; - return true; -} - -inline bool gen_Array_gen_Pool_append_items_at(gen_Array_gen_Pool* self, gen_Pool* items, gen_usize item_num, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - { - return gen_array_append_items(*self, items, item_num); - } - if (item_num > header->Capacity) - { - if (! gen_array_grow(self, item_num + header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - gen_Pool* target = (*self) + idx + item_num; - gen_Pool* src = (*self) + idx; - gen_mem_move(target, src, (header->Num - idx) * sizeof(gen_Pool)); - gen_mem_copy(src, items, item_num * sizeof(gen_Pool)); - header->Num += item_num; - return true; -} - -inline gen_Pool* gen_Array_gen_Pool_back(gen_Array_gen_Pool self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - if (header->Num == 0) - return 0; - return self + header->Num - 1; -} - -inline void gen_Array_gen_Pool_clear(gen_Array_gen_Pool self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - header->Num = 0; -} - -inline bool gen_Array_gen_Pool_fill(gen_Array_gen_Pool self, gen_usize begin, gen_usize end, gen_Pool value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(begin <= end); - gen_ArrayHeader* header = gen_array_get_header(self); - if (begin < 0 || end > header->Num) - return false; - for (gen_ssize idx = (gen_ssize)begin; idx < (gen_ssize)end; idx++) - self[idx] = value; - return true; -} - -inline void gen_Array_gen_Pool_free(gen_Array_gen_Pool* self) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_allocator_free(header->Allocator, header); - self = 0; -} - -inline bool gen_Array_gen_Pool_grow(gen_Array_gen_Pool* self, gen_usize min_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(min_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_usize new_capacity = gen_array_grow_formula(header->Capacity); - if (new_capacity < min_capacity) - new_capacity = min_capacity; - return gen_array_set_capacity(self, new_capacity); -} - -gen_forceinline gen_usize gen_Array_gen_Pool_num(gen_Array_gen_Pool self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_array_get_header(self)->Num; -} - -inline gen_Pool gen_Array_gen_Pool_pop(gen_Array_gen_Pool self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(header->Num > 0); - gen_Pool result = self[header->Num - 1]; - header->Num--; - return result; -} - -gen_forceinline void gen_Array_gen_Pool_remove_at(gen_Array_gen_Pool self, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(idx < header->Num); - gen_mem_move(self + idx, self + idx + 1, sizeof(gen_Pool) * (header->Num - idx - 1)); - header->Num--; -} - -inline bool gen_Array_gen_Pool_reserve(gen_Array_gen_Pool* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < new_capacity) - return gen_array_set_capacity(self, new_capacity); - return true; -} - -inline bool gen_Array_gen_Pool_resize(gen_Array_gen_Pool* self, gen_usize num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < num) - { - if (! gen_array_grow(self, num)) - return false; - header = gen_array_get_header(*self); - } - header->Num = num; - return true; -} - -inline bool gen_Array_gen_Pool_set_capacity(gen_Array_gen_Pool* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (new_capacity == header->Capacity) - return true; - if (new_capacity < header->Num) - { - header->Num = new_capacity; - return true; - } - gen_usize size = sizeof(gen_ArrayHeader) + sizeof(gen_Pool) * new_capacity; - gen_ArrayHeader* new_header = gen_cast(gen_ArrayHeader*, gen_alloc(header->Allocator, size)); - if (new_header == 0) - return false; - gen_mem_move(new_header, header, sizeof(gen_ArrayHeader) + sizeof(gen_Pool) * header->Num); - new_header->Capacity = new_capacity; - gen_allocator_free(header->Allocator, &header); - *self = gen_cast(gen_Pool*, new_header + 1); - return true; -} - -#pragma endregion gen_Array_gen_Pool - -#pragma region gen_Array_gen_StrCached - -#define GEN_GENERIC_SLOT_2__array_init gen_StrCached, gen_Array_gen_StrCached_init -#define GEN_GENERIC_SLOT_2__array_init_reserve gen_StrCached, gen_Array_gen_StrCached_init_reserve -#define GEN_GENERIC_SLOT_2__array_append gen_Array_gen_StrCached, gen_Array_gen_StrCached_append -#define GEN_GENERIC_SLOT_2__array_append_items gen_Array_gen_StrCached, gen_Array_gen_StrCached_append_items -#define GEN_GENERIC_SLOT_2__array_append_at gen_Array_gen_StrCached, gen_Array_gen_StrCached_append_at -#define GEN_GENERIC_SLOT_2__array_append_items_at gen_Array_gen_StrCached, gen_Array_gen_StrCached_append_items_at -#define GEN_GENERIC_SLOT_2__array_back gen_Array_gen_StrCached, gen_Array_gen_StrCached_back -#define GEN_GENERIC_SLOT_2__array_clear gen_Array_gen_StrCached, gen_Array_gen_StrCached_clear -#define GEN_GENERIC_SLOT_2__array_fill gen_Array_gen_StrCached, gen_Array_gen_StrCached_fill -#define GEN_GENERIC_SLOT_2__array_free gen_Array_gen_StrCached, gen_Array_gen_StrCached_free -#define GEN_GENERIC_SLOT_2__array_grow gen_Array_gen_StrCached*, gen_Array_gen_StrCached_grow -#define GEN_GENERIC_SLOT_2__array_num gen_Array_gen_StrCached, gen_Array_gen_StrCached_num -#define GEN_GENERIC_SLOT_2__array_pop gen_Array_gen_StrCached, gen_Array_gen_StrCached_pop -#define GEN_GENERIC_SLOT_2__array_remove_at gen_Array_gen_StrCached, gen_Array_gen_StrCached_remove_at -#define GEN_GENERIC_SLOT_2__array_reserve gen_Array_gen_StrCached, gen_Array_gen_StrCached_reserve -#define GEN_GENERIC_SLOT_2__array_resize gen_Array_gen_StrCached, gen_Array_gen_StrCached_resize -#define GEN_GENERIC_SLOT_2__array_set_capacity gen_Array_gen_StrCached*, gen_Array_gen_StrCached_set_capacity - -typedef gen_StrCached* gen_Array_gen_StrCached; -gen_Array_gen_StrCached gen_Array_gen_StrCached_init(gen_AllocatorInfo allocator); -gen_Array_gen_StrCached gen_Array_gen_StrCached_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity); -bool gen_Array_gen_StrCached_append_array(gen_Array_gen_StrCached* self, gen_Array_gen_StrCached other); -bool gen_Array_gen_StrCached_append(gen_Array_gen_StrCached* self, gen_StrCached value); -bool gen_Array_gen_StrCached_append_items(gen_Array_gen_StrCached* self, gen_StrCached* items, gen_usize item_num); -bool gen_Array_gen_StrCached_append_at(gen_Array_gen_StrCached* self, gen_StrCached item, gen_usize idx); -bool gen_Array_gen_StrCached_append_items_at(gen_Array_gen_StrCached* self, gen_StrCached* items, gen_usize item_num, gen_usize idx); -gen_StrCached* gen_Array_gen_StrCached_back(gen_Array_gen_StrCached self); -void gen_Array_gen_StrCached_clear(gen_Array_gen_StrCached self); -bool gen_Array_gen_StrCached_fill(gen_Array_gen_StrCached self, gen_usize begin, gen_usize end, gen_StrCached value); -void gen_Array_gen_StrCached_free(gen_Array_gen_StrCached* self); -bool gen_Array_gen_StrCached_grow(gen_Array_gen_StrCached* self, gen_usize min_capacity); -gen_usize gen_Array_gen_StrCached_num(gen_Array_gen_StrCached self); -gen_StrCached gen_Array_gen_StrCached_pop(gen_Array_gen_StrCached self); -void gen_Array_gen_StrCached_remove_at(gen_Array_gen_StrCached self, gen_usize idx); -bool gen_Array_gen_StrCached_reserve(gen_Array_gen_StrCached* self, gen_usize new_capacity); -bool gen_Array_gen_StrCached_resize(gen_Array_gen_StrCached* self, gen_usize num); -bool gen_Array_gen_StrCached_set_capacity(gen_Array_gen_StrCached* self, gen_usize new_capacity); - -gen_forceinline gen_Array_gen_StrCached gen_Array_gen_StrCached_init(gen_AllocatorInfo allocator) -{ - size_t initial_size = gen_array_grow_formula(0); - return gen_array_init_reserve(gen_StrCached, allocator, initial_size); -} - -inline gen_Array_gen_StrCached gen_Array_gen_StrCached_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity) -{ - GEN_ASSERT(capacity > 0); - gen_ArrayHeader* header = gen_rcast(gen_ArrayHeader*, gen_alloc(allocator, sizeof(gen_ArrayHeader) + sizeof(gen_StrCached) * capacity)); - if (header == gen_nullptr) - return gen_nullptr; - header->Allocator = allocator; - header->Capacity = capacity; - header->Num = 0; - return gen_rcast(gen_StrCached*, header + 1); -} - -gen_forceinline bool gen_Array_gen_StrCached_append_array(gen_Array_gen_StrCached* self, gen_Array_gen_StrCached other) -{ - return gen_array_append_items(*self, (gen_Array_gen_StrCached)other, gen_Array_gen_StrCached_num(other)); -} - -inline bool gen_Array_gen_StrCached_append(gen_Array_gen_StrCached* self, gen_StrCached value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num == header->Capacity) - { - if (! gen_array_grow(self, header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - (*self)[header->Num] = value; - header->Num++; - return true; -} - -inline bool gen_Array_gen_StrCached_append_items(gen_Array_gen_StrCached* self, gen_StrCached* items, gen_usize item_num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(items != gen_nullptr); - GEN_ASSERT(item_num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num + item_num > header->Capacity) - { - if (! gen_array_grow(self, header->Capacity + item_num)) - return false; - header = gen_array_get_header(*self); - } - gen_mem_copy((*self) + header->Num, items, sizeof(gen_StrCached) * item_num); - header->Num += item_num; - return true; -} - -inline bool gen_Array_gen_StrCached_append_at(gen_Array_gen_StrCached* self, gen_StrCached item, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - idx = header->Num - 1; - if (idx < 0) - idx = 0; - if (header->Capacity < header->Num + 1) - { - if (! gen_array_grow(self, header->Capacity + 1)) - return false; - header = gen_array_get_header(*self); - } - gen_Array_gen_StrCached target = (*self) + idx; - gen_mem_move(target + 1, target, (header->Num - idx) * sizeof(gen_StrCached)); - header->Num++; - return true; -} - -inline bool gen_Array_gen_StrCached_append_items_at(gen_Array_gen_StrCached* self, gen_StrCached* items, gen_usize item_num, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - { - return gen_array_append_items(*self, items, item_num); - } - if (item_num > header->Capacity) - { - if (! gen_array_grow(self, item_num + header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - gen_StrCached* target = (*self) + idx + item_num; - gen_StrCached* src = (*self) + idx; - gen_mem_move(target, src, (header->Num - idx) * sizeof(gen_StrCached)); - gen_mem_copy(src, items, item_num * sizeof(gen_StrCached)); - header->Num += item_num; - return true; -} - -inline gen_StrCached* gen_Array_gen_StrCached_back(gen_Array_gen_StrCached self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - if (header->Num == 0) - return 0; - return self + header->Num - 1; -} - -inline void gen_Array_gen_StrCached_clear(gen_Array_gen_StrCached self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - header->Num = 0; -} - -inline bool gen_Array_gen_StrCached_fill(gen_Array_gen_StrCached self, gen_usize begin, gen_usize end, gen_StrCached value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(begin <= end); - gen_ArrayHeader* header = gen_array_get_header(self); - if (begin < 0 || end > header->Num) - return false; - for (gen_ssize idx = (gen_ssize)begin; idx < (gen_ssize)end; idx++) - self[idx] = value; - return true; -} - -inline void gen_Array_gen_StrCached_free(gen_Array_gen_StrCached* self) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_allocator_free(header->Allocator, header); - self = 0; -} - -inline bool gen_Array_gen_StrCached_grow(gen_Array_gen_StrCached* self, gen_usize min_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(min_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_usize new_capacity = gen_array_grow_formula(header->Capacity); - if (new_capacity < min_capacity) - new_capacity = min_capacity; - return gen_array_set_capacity(self, new_capacity); -} - -gen_forceinline gen_usize gen_Array_gen_StrCached_num(gen_Array_gen_StrCached self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_array_get_header(self)->Num; -} - -inline gen_StrCached gen_Array_gen_StrCached_pop(gen_Array_gen_StrCached self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(header->Num > 0); - gen_StrCached result = self[header->Num - 1]; - header->Num--; - return result; -} - -gen_forceinline void gen_Array_gen_StrCached_remove_at(gen_Array_gen_StrCached self, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(idx < header->Num); - gen_mem_move(self + idx, self + idx + 1, sizeof(gen_StrCached) * (header->Num - idx - 1)); - header->Num--; -} - -inline bool gen_Array_gen_StrCached_reserve(gen_Array_gen_StrCached* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < new_capacity) - return gen_array_set_capacity(self, new_capacity); - return true; -} - -inline bool gen_Array_gen_StrCached_resize(gen_Array_gen_StrCached* self, gen_usize num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < num) - { - if (! gen_array_grow(self, num)) - return false; - header = gen_array_get_header(*self); - } - header->Num = num; - return true; -} - -inline bool gen_Array_gen_StrCached_set_capacity(gen_Array_gen_StrCached* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (new_capacity == header->Capacity) - return true; - if (new_capacity < header->Num) - { - header->Num = new_capacity; - return true; - } - gen_usize size = sizeof(gen_ArrayHeader) + sizeof(gen_StrCached) * new_capacity; - gen_ArrayHeader* new_header = gen_cast(gen_ArrayHeader*, gen_alloc(header->Allocator, size)); - if (new_header == 0) - return false; - gen_mem_move(new_header, header, sizeof(gen_ArrayHeader) + sizeof(gen_StrCached) * header->Num); - new_header->Capacity = new_capacity; - gen_allocator_free(header->Allocator, &header); - *self = gen_cast(gen_StrCached*, new_header + 1); - return true; -} - -#pragma endregion gen_Array_gen_StrCached - -#pragma region MacroTable - -#define GEN_GENERIC_SLOT_2__hashtable_init gen_Macro, MacroTable_init -#define GEN_GENERIC_SLOT_2__hashtable_init_reserve gen_Macro, MacroTable_init_reserve -#define GEN_GENERIC_SLOT_2__hashtable_clear MacroTable, MacroTable_clear -#define GEN_GENERIC_SLOT_2__hashtable_destroy MacroTable, MacroTable_destroy -#define GEN_GENERIC_SLOT_2__hashtable_get MacroTable, MacroTable_get -#define GEN_GENERIC_SLOT_2__hashtable_map MacroTable, MacroTable_map -#define GEN_GENERIC_SLOT_2__hashtable_map_mut MacroTable, MacroTable_map_mut -#define GEN_GENERIC_SLOT_2__hashtable_grow MacroTable*, MacroTable_grow -#define GEN_GENERIC_SLOT_2__hashtable_rehash MacroTable*, MacroTable_rehash -#define GEN_GENERIC_SLOT_2__hashtable_rehash_fast MacroTable, MacroTable_rehash_fast -#define GEN_GENERIC_SLOT_2__hashtable_remove_entry MacroTable, MacroTable_remove_entry -#define GEN_GENERIC_SLOT_2__hashtable_set MacroTable, MacroTable_set -#define GEN_GENERIC_SLOT_2__hashtable_slot MacroTable, MacroTable_slot - -#define GEN_GENERIC_SLOT_2__hashtable__add_entry MacroTable*, MacroTable__add_entry -#define GEN_GENERIC_SLOT_2__hashtable__find MacroTable, MacroTable__find -#define GEN_GENERIC_SLOT_2__hashtable__full MacroTable, MacroTable__full - -typedef struct gen_HashTable_gen_Macro MacroTable; -typedef struct gen_HTE_MacroTable gen_HTE_MacroTable; - -struct gen_HTE_MacroTable -{ - gen_u64 Key; - gen_ssize Next; - gen_Macro Value; -}; - -typedef void (*MacroTable_MapProc)(MacroTable self, gen_u64 key, gen_Macro value); -typedef void (*MacroTable_MapMutProc)(MacroTable self, gen_u64 key, gen_Macro* value); - -#pragma region gen_Arr_HTE_MacroTable - -#define GEN_GENERIC_SLOT_9__array_init gen_HTE_MacroTable, gen_Arr_HTE_MacroTable_init -#define GEN_GENERIC_SLOT_9__array_init_reserve gen_HTE_MacroTable, gen_Arr_HTE_MacroTable_init_reserve -#define GEN_GENERIC_SLOT_9__array_append gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_append -#define GEN_GENERIC_SLOT_9__array_append_items gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_append_items -#define GEN_GENERIC_SLOT_9__array_append_at gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_append_at -#define GEN_GENERIC_SLOT_9__array_append_items_at gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_append_items_at -#define GEN_GENERIC_SLOT_9__array_back gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_back -#define GEN_GENERIC_SLOT_9__array_clear gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_clear -#define GEN_GENERIC_SLOT_9__array_fill gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_fill -#define GEN_GENERIC_SLOT_9__array_free gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_free -#define GEN_GENERIC_SLOT_9__array_grow gen_Arr_HTE_MacroTable*, gen_Arr_HTE_MacroTable_grow -#define GEN_GENERIC_SLOT_9__array_num gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_num -#define GEN_GENERIC_SLOT_9__array_pop gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_pop -#define GEN_GENERIC_SLOT_9__array_remove_at gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_remove_at -#define GEN_GENERIC_SLOT_9__array_reserve gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_reserve -#define GEN_GENERIC_SLOT_9__array_resize gen_Arr_HTE_MacroTable, gen_Arr_HTE_MacroTable_resize -#define GEN_GENERIC_SLOT_9__array_set_capacity gen_Arr_HTE_MacroTable*, gen_Arr_HTE_MacroTable_set_capacity - -typedef gen_HTE_MacroTable* gen_Arr_HTE_MacroTable; -gen_Arr_HTE_MacroTable gen_Arr_HTE_MacroTable_init(gen_AllocatorInfo allocator); -gen_Arr_HTE_MacroTable gen_Arr_HTE_MacroTable_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity); -bool gen_Arr_HTE_MacroTable_append_array(gen_Arr_HTE_MacroTable* self, gen_Arr_HTE_MacroTable other); -bool gen_Arr_HTE_MacroTable_append(gen_Arr_HTE_MacroTable* self, gen_HTE_MacroTable value); -bool gen_Arr_HTE_MacroTable_append_items(gen_Arr_HTE_MacroTable* self, gen_HTE_MacroTable* items, gen_usize item_num); -bool gen_Arr_HTE_MacroTable_append_at(gen_Arr_HTE_MacroTable* self, gen_HTE_MacroTable item, gen_usize idx); -bool gen_Arr_HTE_MacroTable_append_items_at(gen_Arr_HTE_MacroTable* self, gen_HTE_MacroTable* items, gen_usize item_num, gen_usize idx); -gen_HTE_MacroTable* gen_Arr_HTE_MacroTable_back(gen_Arr_HTE_MacroTable self); -void gen_Arr_HTE_MacroTable_clear(gen_Arr_HTE_MacroTable self); -bool gen_Arr_HTE_MacroTable_fill(gen_Arr_HTE_MacroTable self, gen_usize begin, gen_usize end, gen_HTE_MacroTable value); -void gen_Arr_HTE_MacroTable_free(gen_Arr_HTE_MacroTable* self); -bool gen_Arr_HTE_MacroTable_grow(gen_Arr_HTE_MacroTable* self, gen_usize min_capacity); -gen_usize gen_Arr_HTE_MacroTable_num(gen_Arr_HTE_MacroTable self); -gen_HTE_MacroTable gen_Arr_HTE_MacroTable_pop(gen_Arr_HTE_MacroTable self); -void gen_Arr_HTE_MacroTable_remove_at(gen_Arr_HTE_MacroTable self, gen_usize idx); -bool gen_Arr_HTE_MacroTable_reserve(gen_Arr_HTE_MacroTable* self, gen_usize new_capacity); -bool gen_Arr_HTE_MacroTable_resize(gen_Arr_HTE_MacroTable* self, gen_usize num); -bool gen_Arr_HTE_MacroTable_set_capacity(gen_Arr_HTE_MacroTable* self, gen_usize new_capacity); - -gen_forceinline gen_Arr_HTE_MacroTable gen_Arr_HTE_MacroTable_init(gen_AllocatorInfo allocator) -{ - size_t initial_size = gen_array_grow_formula(0); - return gen_array_init_reserve(gen_HTE_MacroTable, allocator, initial_size); -} - -inline gen_Arr_HTE_MacroTable gen_Arr_HTE_MacroTable_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity) -{ - GEN_ASSERT(capacity > 0); - gen_ArrayHeader* header = gen_rcast(gen_ArrayHeader*, gen_alloc(allocator, sizeof(gen_ArrayHeader) + sizeof(gen_HTE_MacroTable) * capacity)); - if (header == gen_nullptr) - return gen_nullptr; - header->Allocator = allocator; - header->Capacity = capacity; - header->Num = 0; - return gen_rcast(gen_HTE_MacroTable*, header + 1); -} - -gen_forceinline bool gen_Arr_HTE_MacroTable_append_array(gen_Arr_HTE_MacroTable* self, gen_Arr_HTE_MacroTable other) -{ - return gen_array_append_items(*self, (gen_Arr_HTE_MacroTable)other, gen_Arr_HTE_MacroTable_num(other)); -} - -inline bool gen_Arr_HTE_MacroTable_append(gen_Arr_HTE_MacroTable* self, gen_HTE_MacroTable value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num == header->Capacity) - { - if (! gen_array_grow(self, header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - (*self)[header->Num] = value; - header->Num++; - return true; -} - -inline bool gen_Arr_HTE_MacroTable_append_items(gen_Arr_HTE_MacroTable* self, gen_HTE_MacroTable* items, gen_usize item_num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(items != gen_nullptr); - GEN_ASSERT(item_num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num + item_num > header->Capacity) - { - if (! gen_array_grow(self, header->Capacity + item_num)) - return false; - header = gen_array_get_header(*self); - } - gen_mem_copy((*self) + header->Num, items, sizeof(gen_HTE_MacroTable) * item_num); - header->Num += item_num; - return true; -} - -inline bool gen_Arr_HTE_MacroTable_append_at(gen_Arr_HTE_MacroTable* self, gen_HTE_MacroTable item, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - idx = header->Num - 1; - if (idx < 0) - idx = 0; - if (header->Capacity < header->Num + 1) - { - if (! gen_array_grow(self, header->Capacity + 1)) - return false; - header = gen_array_get_header(*self); - } - gen_Arr_HTE_MacroTable target = (*self) + idx; - gen_mem_move(target + 1, target, (header->Num - idx) * sizeof(gen_HTE_MacroTable)); - header->Num++; - return true; -} - -inline bool gen_Arr_HTE_MacroTable_append_items_at(gen_Arr_HTE_MacroTable* self, gen_HTE_MacroTable* items, gen_usize item_num, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - { - return gen_array_append_items(*self, items, item_num); - } - if (item_num > header->Capacity) - { - if (! gen_array_grow(self, item_num + header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - gen_HTE_MacroTable* target = (*self) + idx + item_num; - gen_HTE_MacroTable* src = (*self) + idx; - gen_mem_move(target, src, (header->Num - idx) * sizeof(gen_HTE_MacroTable)); - gen_mem_copy(src, items, item_num * sizeof(gen_HTE_MacroTable)); - header->Num += item_num; - return true; -} - -inline gen_HTE_MacroTable* gen_Arr_HTE_MacroTable_back(gen_Arr_HTE_MacroTable self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - if (header->Num == 0) - return 0; - return self + header->Num - 1; -} - -inline void gen_Arr_HTE_MacroTable_clear(gen_Arr_HTE_MacroTable self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - header->Num = 0; -} - -inline bool gen_Arr_HTE_MacroTable_fill(gen_Arr_HTE_MacroTable self, gen_usize begin, gen_usize end, gen_HTE_MacroTable value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(begin <= end); - gen_ArrayHeader* header = gen_array_get_header(self); - if (begin < 0 || end > header->Num) - return false; - for (gen_ssize idx = (gen_ssize)begin; idx < (gen_ssize)end; idx++) - self[idx] = value; - return true; -} - -inline void gen_Arr_HTE_MacroTable_free(gen_Arr_HTE_MacroTable* self) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_allocator_free(header->Allocator, header); - self = 0; -} - -inline bool gen_Arr_HTE_MacroTable_grow(gen_Arr_HTE_MacroTable* self, gen_usize min_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(min_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_usize new_capacity = gen_array_grow_formula(header->Capacity); - if (new_capacity < min_capacity) - new_capacity = min_capacity; - return gen_array_set_capacity(self, new_capacity); -} - -gen_forceinline gen_usize gen_Arr_HTE_MacroTable_num(gen_Arr_HTE_MacroTable self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_array_get_header(self)->Num; -} - -inline gen_HTE_MacroTable gen_Arr_HTE_MacroTable_pop(gen_Arr_HTE_MacroTable self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(header->Num > 0); - gen_HTE_MacroTable result = self[header->Num - 1]; - header->Num--; - return result; -} - -gen_forceinline void gen_Arr_HTE_MacroTable_remove_at(gen_Arr_HTE_MacroTable self, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(idx < header->Num); - gen_mem_move(self + idx, self + idx + 1, sizeof(gen_HTE_MacroTable) * (header->Num - idx - 1)); - header->Num--; -} - -inline bool gen_Arr_HTE_MacroTable_reserve(gen_Arr_HTE_MacroTable* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < new_capacity) - return gen_array_set_capacity(self, new_capacity); - return true; -} - -inline bool gen_Arr_HTE_MacroTable_resize(gen_Arr_HTE_MacroTable* self, gen_usize num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < num) - { - if (! gen_array_grow(self, num)) - return false; - header = gen_array_get_header(*self); - } - header->Num = num; - return true; -} - -inline bool gen_Arr_HTE_MacroTable_set_capacity(gen_Arr_HTE_MacroTable* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (new_capacity == header->Capacity) - return true; - if (new_capacity < header->Num) - { - header->Num = new_capacity; - return true; - } - gen_usize size = sizeof(gen_ArrayHeader) + sizeof(gen_HTE_MacroTable) * new_capacity; - gen_ArrayHeader* new_header = gen_cast(gen_ArrayHeader*, gen_alloc(header->Allocator, size)); - if (new_header == 0) - return false; - gen_mem_move(new_header, header, sizeof(gen_ArrayHeader) + sizeof(gen_HTE_MacroTable) * header->Num); - new_header->Capacity = new_capacity; - gen_allocator_free(header->Allocator, &header); - *self = gen_cast(gen_HTE_MacroTable*, new_header + 1); - return true; -} - -#pragma endregion gen_Arr_HTE_MacroTable - -struct gen_HashTable_gen_Macro -{ - gen_Array_gen_ssize Hashes; - gen_Arr_HTE_MacroTable Entries; -}; - -MacroTable MacroTable_init(gen_AllocatorInfo allocator); -MacroTable MacroTable_init_reserve(gen_AllocatorInfo allocator, gen_ssize num); -void MacroTable_clear(MacroTable self); -void MacroTable_destroy(MacroTable* self); -gen_Macro* MacroTable_get(MacroTable self, gen_u64 key); -void MacroTable_map(MacroTable self, MacroTable_MapProc map_proc); -void MacroTable_map_mut(MacroTable self, MacroTable_MapMutProc map_proc); -void MacroTable_grow(MacroTable* self); -void MacroTable_rehash(MacroTable* self, gen_ssize new_num); -void MacroTable_rehash_fast(MacroTable self); -void MacroTable_remove(MacroTable self, gen_u64 key); -void MacroTable_remove_entry(MacroTable self, gen_ssize idx); -void MacroTable_set(MacroTable* self, gen_u64 key, gen_Macro value); -gen_ssize MacroTable_slot(MacroTable self, gen_u64 key); -gen_ssize MacroTable__add_entry(MacroTable* self, gen_u64 key); -gen_HT_FindResult MacroTable__find(MacroTable self, gen_u64 key); -gen_b32 MacroTable__full(MacroTable self); - -MacroTable MacroTable_init(gen_AllocatorInfo allocator) -{ - MacroTable result = gen_hashtable_init_reserve(gen_Macro, allocator, 8); - return result; -} - -MacroTable MacroTable_init_reserve(gen_AllocatorInfo allocator, gen_ssize num) -{ - MacroTable result = { 0, 0 }; - result.Hashes = gen_array_init_reserve(gen_ssize, allocator, num); - gen_array_get_header(result.Hashes)->Num = num; - gen_array_resize(result.Hashes, num); - gen_array_fill(result.Hashes, 0, num, -1); - result.Entries = gen_array_init_reserve(gen_HTE_MacroTable, allocator, num); - return result; -} - -void MacroTable_clear(MacroTable self) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_array_clear(self.Entries); - gen_s32 what = gen_array_num(self.Hashes); - gen_array_fill(self.Hashes, 0, what, (gen_ssize)-1); -} - -void MacroTable_destroy(MacroTable* self) -{ - GEN_ASSERT_NOT_NULL(self); - GEN_ASSERT_NOT_NULL(self->Hashes); - GEN_ASSERT_NOT_NULL(self->Entries); - if (self->Hashes && gen_array_get_header(self->Hashes)->Capacity) - { - gen_array_free(self->Hashes); - gen_array_free(self->Entries); - } -} - -gen_Macro* MacroTable_get(MacroTable self, gen_u64 key) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_ssize idx = MacroTable__find(self, key).EntryIndex; - if (idx > 0) - return &self.Entries[idx].Value; - return gen_nullptr; -} - -void MacroTable_map(MacroTable self, MacroTable_MapProc map_proc) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - GEN_ASSERT_NOT_NULL(map_proc); - for (gen_ssize idx = 0; idx < gen_array_get_header(self.Entries)->Num; idx++) - { - map_proc(self, self.Entries[idx].Key, self.Entries[idx].Value); - } -} - -void MacroTable_map_mut(MacroTable self, MacroTable_MapMutProc map_proc) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - GEN_ASSERT_NOT_NULL(map_proc); - for (gen_ssize idx = 0; idx < gen_array_get_header(self.Entries)->Num; idx++) - { - map_proc(self, self.Entries[idx].Key, &self.Entries[idx].Value); - } -} - -void MacroTable_grow(MacroTable* self) -{ - GEN_ASSERT_NOT_NULL(self); - GEN_ASSERT_NOT_NULL(self->Hashes); - GEN_ASSERT_NOT_NULL(self->Entries); - gen_ssize new_num = gen_array_grow_formula(gen_array_get_header(self->Entries)->Num); - gen_hashtable_rehash(self, new_num); -} - -void MacroTable_rehash(MacroTable* self, gen_ssize new_num) -{ - GEN_ASSERT_NOT_NULL(self); - GEN_ASSERT_NOT_NULL(self->Hashes); - GEN_ASSERT_NOT_NULL(self->Entries); - GEN_ASSERT(new_num > 0); - gen_ssize idx; - gen_ssize last_added_index; - gen_ArrayHeader* old_hash_header = gen_array_get_header(self->Hashes); - gen_ArrayHeader* old_entries_header = gen_array_get_header(self->Entries); - MacroTable new_tbl = gen_hashtable_init_reserve(gen_Macro, old_hash_header->Allocator, old_hash_header->Num); - gen_ArrayHeader* new_hash_header = gen_array_get_header(new_tbl.Hashes); - for (gen_ssize idx = 0; idx < gen_cast(gen_ssize, old_hash_header->Num); ++idx) - { - gen_HTE_MacroTable* entry = &self->Entries[idx]; - gen_HT_FindResult find_result; - find_result = MacroTable__find(new_tbl, entry->Key); - last_added_index = MacroTable__add_entry(&new_tbl, entry->Key); - if (find_result.PrevIndex < 0) - new_tbl.Hashes[find_result.HashIndex] = last_added_index; - else - new_tbl.Entries[find_result.PrevIndex].Next = last_added_index; - new_tbl.Entries[last_added_index].Next = find_result.EntryIndex; - new_tbl.Entries[last_added_index].Value = entry->Value; - } - MacroTable_destroy(self); - *self = new_tbl; -} - -void MacroTable_rehash_fast(MacroTable self) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_ssize idx; - for (idx = 0; idx < gen_array_get_header(self.Entries)->Num; idx++) - self.Entries[idx].Next = -1; - for (idx = 0; idx < gen_array_get_header(self.Hashes)->Num; idx++) - self.Hashes[idx] = -1; - for (idx = 0; idx < gen_array_get_header(self.Entries)->Num; idx++) - { - gen_HTE_MacroTable* entry; - gen_HT_FindResult find_result; - entry = &self.Entries[idx]; - find_result = MacroTable__find(self, entry->Key); - if (find_result.PrevIndex < 0) - self.Hashes[find_result.HashIndex] = idx; - else - self.Entries[find_result.PrevIndex].Next = idx; - } -} - -void MacroTable_remove(MacroTable self, gen_u64 key) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_HT_FindResult find_result = MacroTable__find(self, key); - if (find_result.EntryIndex >= 0) - { - gen_array_remove_at(self.Entries, find_result.EntryIndex); - gen_hashtable_rehash_fast(self); - } -} - -void MacroTable_remove_entry(MacroTable self, gen_ssize idx) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_array_remove_at(self.Entries, idx); -} - -void MacroTable_set(MacroTable* self, gen_u64 key, gen_Macro value) -{ - GEN_ASSERT_NOT_NULL(self); - GEN_ASSERT_NOT_NULL(self->Hashes); - GEN_ASSERT_NOT_NULL(self->Entries); - gen_ssize idx; - gen_HT_FindResult find_result; - if (gen_array_get_header(self->Hashes)->Num == 0) - gen_hashtable_grow(self); - find_result = MacroTable__find(*self, key); - if (find_result.EntryIndex >= 0) - { - idx = find_result.EntryIndex; - } - else - { - idx = MacroTable__add_entry(self, key); - if (find_result.PrevIndex >= 0) - { - self->Entries[find_result.PrevIndex].Next = idx; - } - else - { - self->Hashes[find_result.HashIndex] = idx; - } - } - self->Entries[idx].Value = value; - if (MacroTable__full(*self)) - gen_hashtable_grow(self); -} - -gen_ssize MacroTable_slot(MacroTable self, gen_u64 key) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - for (gen_ssize idx = 0; idx < gen_array_get_header(self.Hashes)->Num; ++idx) - if (self.Hashes[idx] == key) - return idx; - return -1; -} - -gen_ssize MacroTable__add_entry(MacroTable* self, gen_u64 key) -{ - GEN_ASSERT_NOT_NULL(self); - GEN_ASSERT_NOT_NULL(self->Hashes); - GEN_ASSERT_NOT_NULL(self->Entries); - gen_ssize idx; - gen_HTE_MacroTable entry = { key, -1 }; - idx = gen_array_get_header(self->Entries)->Num; - gen_array_append(self->Entries, entry); - return idx; -} - -gen_HT_FindResult MacroTable__find(MacroTable self, gen_u64 key) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_HT_FindResult result = { -1, -1, -1 }; - gen_ArrayHeader* hash_header = gen_array_get_header(self.Hashes); - if (hash_header->Num > 0) - { - result.HashIndex = key % hash_header->Num; - result.EntryIndex = self.Hashes[result.HashIndex]; - while (result.EntryIndex >= 0) - { - if (self.Entries[result.EntryIndex].Key == key) - break; - result.PrevIndex = result.EntryIndex; - result.EntryIndex = self.Entries[result.EntryIndex].Next; - } - } - return result; -} - -gen_b32 MacroTable__full(MacroTable self) -{ - GEN_ASSERT_NOT_NULL(self.Hashes); - GEN_ASSERT_NOT_NULL(self.Entries); - gen_ArrayHeader* hash_header = gen_array_get_header(self.Hashes); - gen_ArrayHeader* entries_header = gen_array_get_header(self.Entries); - gen_usize critical_load = gen_cast(gen_usize, gen_HashTable_CriticalLoadScale * gen_cast(gen_f32, hash_header->Num)); - gen_b32 result = entries_header->Num > critical_load; - return result; -} - -#pragma endregion MacroTable - -#pragma region Gen Interface - -/* - / \ | \ | \ / \ -| ▓▓▓▓▓▓\ ______ _______ \▓▓▓▓▓▓_______ _| ▓▓_ ______ ______ | ▓▓▓▓▓▓\ ______ _______ ______ -| ▓▓ __\▓▓/ \| \ | ▓▓ | \| ▓▓ \ / \ / \| ▓▓_ \▓▓| \ / \/ \ -| ▓▓| \ ▓▓▓▓▓▓\ ▓▓▓▓▓▓▓\ | ▓▓ | ▓▓▓▓▓▓▓\\▓▓▓▓▓▓ | ▓▓▓▓▓▓\ ▓▓▓▓▓▓\ ▓▓ \ \▓▓▓▓▓▓\ ▓▓▓▓▓▓▓ ▓▓▓▓▓▓\ -| ▓▓ \▓▓▓▓ ▓▓ ▓▓ ▓▓ | ▓▓ | ▓▓ | ▓▓ | ▓▓ | ▓▓ __| ▓▓ ▓▓ ▓▓ \▓▓ ▓▓▓▓ / ▓▓ ▓▓ | ▓▓ ▓▓ -| ▓▓__| ▓▓ ▓▓▓▓▓▓▓▓ ▓▓ | ▓▓ _| ▓▓_| ▓▓ | ▓▓ | ▓▓| \ ▓▓▓▓▓▓▓▓ ▓▓ | ▓▓ | ▓▓▓▓▓▓▓ ▓▓_____| ▓▓▓▓▓▓▓▓ - \▓▓ ▓▓\▓▓ \ ▓▓ | ▓▓ | ▓▓ \ ▓▓ | ▓▓ \▓▓ ▓▓\▓▓ \ ▓▓ | ▓▓ \▓▓ ▓▓\▓▓ \\▓▓ \ - \▓▓▓▓▓▓ \▓▓▓▓▓▓▓\▓▓ \▓▓ \▓▓▓▓▓▓\▓▓ \▓▓ \▓▓▓▓ \▓▓▓▓▓▓▓\▓▓ \▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ -*/ - -// Note(Ed): This is subject to heavily change -// with upcoming changes to the library's fallback (default) allocations strategy; -// and major changes to lexer/parser context usage. -struct gen_Context -{ - // User Configuration - - // Persistent Data Allocation - gen_AllocatorInfo Allocator_DyanmicContainers; // By default will use a genral slab allocator (TODO(Ed): Currently does not) - gen_AllocatorInfo Allocator_Pool; // By default will use the growing vmem reserve (TODO(Ed): Currently does not) - gen_AllocatorInfo Allocator_StrCache; // By default will use a dedicated slab allocator (TODO(Ed): Currently does not) - - // Temporary Allocation - gen_AllocatorInfo Allocator_Temp; - - // LoggerCallaback* log_callback; // TODO(Ed): Impl user logger callback as an option. - - // Initalization config - gen_u32 Max_CommentLineLength; // Used by gen_def_comment - gen_u32 Max_StrCacheLength; // Any cached string longer than this is always allocated again. - - gen_u32 InitSize_BuilderBuffer; - gen_u32 InitSize_CodePoolsArray; - gen_u32 InitSize_StringArenasArray; - - gen_u32 CodePool_NumBlocks; - - // TODO(Ed): Review these... (No longer needed if using the proper allocation strategy) - gen_u32 InitSize_LexerTokens; - gen_u32 SizePer_StringArena; - - gen_u32 InitSize_StrCacheTable; - gen_u32 InitSize_MacrosTable; - - // TODO(Ed): Symbol Table - // Keep track of all resolved symbols (naemspaced identifiers) - - // Logging - - LoggerProc* Logger; - - // Parser - - // Used by the lexer to persistently treat all these identifiers as preprocessor defines. - // Populate with strings via gen::gen_cache_str. - // Functional defines must have format: id( ;at minimum to indicate that the define is only valid with arguments. - MacroTable Macros; - - // Backend - - // The fallback allocator is utilized if any fo the three above allocators is not specified by the user. - gen_u32 InitSize_Fallback_Allocator_Bucket_Size; - gen_Array(gen_Arena) Fallback_AllocatorBuckets; - - gen_StringTable gen_token_fmt_map; - - // gen_Array(gen_Token) LexerTokens; - - gen_Array(gen_Pool) CodePools; - gen_Array(gen_Arena) StringArenas; - - gen_StringTable StrCache; - - // TODO(Ed): Active parse context vs a parse result need to be separated conceptually - gen_ParseContext parser; - - // TODO(Ed): Formatting - This will eventually be in a separate struct when in the process of serialization of the builder. - gen_s32 temp_serialize_indent; -}; -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; - -// TODO(Ed): Swap all usage of this with logger_fmt (then rename logger_fmt to gen_log_fmt) -inline gen_ssize gen_log_fmt(char const* fmt, ...) -{ - gen_ssize res; - va_list va; - - va_start(va, fmt); - res = gen_c_str_fmt_out_va(fmt, va); - va_end(va); - - return res; -} - -inline void logger_fmt(gen_Context* ctx, LogLevel level, char const* fmt, ...) -{ - gen_local_persist gen_thread_local gen_PrintF_Buffer buf = gen_struct_zero_init(); - - va_list va; - va_start(va, fmt); - gen_ssize res = gen_c_str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va) - 1; - va_end(va); - - gen_StrBuilder msg = gen_strbuilder_make_length(ctx->Allocator_Temp, buf, res); - - LogEntry entry = { gen_strbuilder_to_str(msg), level }; - ctx->Logger(entry); -} - -// 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); - -// Currently manually free's the arenas, code for checking for leaks. -// However on Windows at least, it doesn't need to occur as the OS will clean up after the process. -GEN_API void gen_deinit(gen_Context* ctx); - -// Retrieves the active context (not usually needed, but here in case...) -GEN_API gen_Context* gen_get_context(); - -// Clears the allocations, but doesn't free the memory, then calls gen_init() again. -// Ease of use. -GEN_API void gen_reset(gen_Context* ctx); - -GEN_API void set_context(gen_Context* ctx); - -// Mostly intended for the parser -GEN_API gen_Macro* lookup_macro(gen_Str Name); - -// Alternative way to add a preprocess define entry for the lexer & parser to utilize -// if the user doesn't want to use gen_def_define -// Macros are tracked by name so if the name already exists the entry will be overwritten. -GEN_API void gen_register_macro(gen_Macro macro); - -// Ease of use batch registration -GEN_API void gen_register_macros(gen_s32 num, ...); -GEN_API void gen_register_macros_arr(gen_s32 num, gen_Macro* macros); - - -// Used internally to retrive or make string allocations. -// Strings are stored in a series of string arenas of fixed size (SizePer_StringArena) -GEN_API gen_StrCached gen_cache_str(gen_Str str); - -/* - This provides a fresh gen_Code gen_AST. - The gen interface use this as their method from getting a new gen_AST object from the CodePool. - Use this if you want to make your own API for formatting the supported gen_Code Types. -*/ -GEN_API gen_Code gen_make_code(); - -// Set these before calling gen's gen_init() procedure. - -#pragma region Upfront - - -GEN_API gen_CodeAttributes gen_def_attributes(gen_Str content); -GEN_API gen_CodeComment gen_def_comment(gen_Str content); - -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_CodeSpecifiers specifiers; // Only used for final specifier for now. - gen_ModuleFlag mflags; -}; -typedef struct gen_Opts_def_struct gen_Opts_def_struct; - -GEN_API gen_CodeClass gen_def__class(gen_Str name, gen_Opts_def_struct* opts GEN_PARAM_DEFAULT); -#define gen_def_class(name, ...) gen_def__class(name, &(gen_Opts_def_struct) { __VA_ARGS__ }) - -struct gen_Opts_def_constructor -{ - gen_CodeParams params; - gen_Code initializer_list; - gen_Code body; -}; -typedef struct gen_Opts_def_constructor gen_Opts_def_constructor; - -GEN_API gen_CodeConstructor gen_def__constructor(gen_Opts_def_constructor* opts); -#define gen_def_constructor(...) gen_def__constructor(&(gen_Opts_def_constructor) { __VA_ARGS__ }) - -struct gen_Opts_def_define -{ - gen_CodeDefineParams params; - gen_Str content; - gen_MacroFlags flags; - gen_b32 dont_register_to_preprocess_macros; -}; -typedef struct gen_Opts_def_define gen_Opts_def_define; - -GEN_API gen_CodeDefine gen_def__define(gen_Str name, gen_MacroType type, gen_Opts_def_define* opts GEN_PARAM_DEFAULT); -#define gen_def_define(name, type, ...) gen_def__define(name, type, &(gen_Opts_def_define) { __VA_ARGS__ }) - -struct gen_Opts_def_destructor -{ - gen_Code body; - gen_CodeSpecifiers specifiers; -}; -typedef struct gen_Opts_def_destructor gen_Opts_def_destructor; - -GEN_API gen_CodeDestructor gen_def__destructor(gen_Opts_def_destructor* opts); -#define gen_def_destructor(...) gen_def__destructor(&(gen_Opts_def_destructor) { __VA_ARGS__ }) - -struct gen_Opts_def_enum -{ - gen_CodeBody body; - gen_CodeTypename type; - EnumT specifier; - gen_CodeAttributes attributes; - gen_ModuleFlag mflags; - gen_Code type_macro; -}; -typedef struct gen_Opts_def_enum gen_Opts_def_enum; - -GEN_API gen_CodeEnum gen_def__enum(gen_Str name, gen_Opts_def_enum* opts GEN_PARAM_DEFAULT); -#define gen_def_enum(name, ...) gen_def__enum(name, &(gen_Opts_def_enum) { __VA_ARGS__ }) - -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 code); - -struct gen_Opts_def_function -{ - gen_CodeParams params; - gen_CodeTypename ret_type; - gen_CodeBody body; - gen_CodeSpecifiers specs; - gen_CodeAttributes attrs; - gen_ModuleFlag mflags; -}; -typedef struct gen_Opts_def_function gen_Opts_def_function; - -GEN_API gen_CodeFn gen_def__function(gen_Str name, gen_Opts_def_function* opts GEN_PARAM_DEFAULT); -#define gen_def_function(name, ...) gen_def__function(name, &(gen_Opts_def_function) { __VA_ARGS__ }) - -struct gen_Opts_def_include -{ - gen_b32 foreign; -}; -typedef struct gen_Opts_def_include gen_Opts_def_include; - -struct gen_Opts_def_module -{ - gen_ModuleFlag mflags; -}; -typedef struct gen_Opts_def_module gen_Opts_def_module; - -struct gen_Opts_def_namespace -{ - gen_ModuleFlag mflags; -}; -typedef struct gen_Opts_def_namespace gen_Opts_def_namespace; - -GEN_API gen_CodeInclude gen_def__include(gen_Str content, gen_Opts_def_include* opts GEN_PARAM_DEFAULT); -#define gen_def_include(content, ...) gen_def__include(content, &(gen_Opts_def_include) { __VA_ARGS__ }) - -GEN_API gen_CodeModule gen_def__module(gen_Str name, gen_Opts_def_module* opts GEN_PARAM_DEFAULT); -#define gen_def_module(name, ...) gen_def__module(name, &(gen_Opts_def_module) { __VA_ARGS__ }) - -GEN_API gen_CodeNS gen_def__namespace(gen_Str name, gen_CodeBody body, gen_Opts_def_namespace* opts GEN_PARAM_DEFAULT); -#define gen_def_namespace(name, body, ...) gen_def__namespace(name, body, &(gen_Opts_def_namespace) { __VA_ARGS__ }) - -struct gen_Opts_def_operator -{ - gen_CodeParams params; - gen_CodeTypename ret_type; - gen_CodeBody body; - gen_CodeSpecifiers specifiers; - gen_CodeAttributes attributes; - gen_ModuleFlag mflags; -}; -typedef struct gen_Opts_def_operator gen_Opts_def_operator; - -GEN_API gen_CodeOperator gen_def__operator(gen_Operator op, gen_Str nspace, gen_Opts_def_operator* opts GEN_PARAM_DEFAULT); -#define gen_def_operator(op, nspace, ...) gen_def__operator(op, nspace, &(gen_Opts_def_operator) { __VA_ARGS__ }) - -struct gen_Opts_def_operator_cast -{ - gen_CodeBody body; - gen_CodeSpecifiers specs; -}; -typedef struct gen_Opts_def_operator_cast gen_Opts_def_operator_cast; - -GEN_API gen_CodeOpCast gen_def__operator_cast(gen_CodeTypename type, gen_Opts_def_operator_cast* opts GEN_PARAM_DEFAULT); -#define gen_def_operator_cast(type, ...) gen_def__operator_cast(type, &(gen_Opts_def_operator_cast) { __VA_ARGS__ }) - -struct gen_Opts_def_param -{ - gen_Code value; -}; -typedef struct gen_Opts_def_param gen_Opts_def_param; - -GEN_API gen_CodeParams gen_def__param(gen_CodeTypename type, gen_Str name, gen_Opts_def_param* opts GEN_PARAM_DEFAULT); -#define gen_def_param(type, name, ...) gen_def__param(type, name, &(gen_Opts_def_param) { __VA_ARGS__ }) - -GEN_API gen_CodePragma gen_def_pragma(gen_Str directive); - -GEN_API gen_CodePreprocessCond gen_def_preprocess_cond(gen_EPreprocessCOnd type, gen_Str content); - -GEN_API gen_CodeSpecifiers gen_def_specifier(gen_Specifier specifier); - -GEN_API gen_CodeStruct 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__ }) - -struct gen_Opts_def_template -{ - gen_ModuleFlag mflags; -}; -typedef struct gen_Opts_def_template gen_Opts_def_template; - -GEN_API gen_CodeTemplate gen_def__template(gen_CodeParams params, gen_Code definition, gen_Opts_def_template* opts GEN_PARAM_DEFAULT); -#define gen_def_template(params, definition, ...) gen_def__template(params, definition, &(gen_Opts_def_template) { __VA_ARGS__ }) - -struct gen_Opts_def_type -{ - gen_ETypenameTag type_tag; - gen_Code gen_array_expr; - gen_CodeSpecifiers specifiers; - gen_CodeAttributes attributes; -}; -typedef struct gen_Opts_def_type gen_Opts_def_type; - -GEN_API gen_CodeTypename gen_def__type(gen_Str name, gen_Opts_def_type* opts GEN_PARAM_DEFAULT); -#define gen_def_type(name, ...) gen_def__type(name, &(gen_Opts_def_type) { __VA_ARGS__ }) - -struct gen_Opts_def_typedef -{ - gen_CodeAttributes attributes; - gen_ModuleFlag mflags; -}; -typedef struct gen_Opts_def_typedef gen_Opts_def_typedef; - -GEN_API gen_CodeTypedef gen_def__typedef(gen_Str name, gen_Code type, gen_Opts_def_typedef* opts GEN_PARAM_DEFAULT); -#define gen_def_typedef(name, type, ...) gen_def__typedef(name, type, &(gen_Opts_def_typedef) { __VA_ARGS__ }) - -struct gen_Opts_def_union -{ - gen_CodeAttributes attributes; - gen_ModuleFlag mflags; -}; -typedef struct gen_Opts_def_union gen_Opts_def_union; - -GEN_API gen_CodeUnion gen_def__union(gen_Str name, gen_CodeBody body, gen_Opts_def_union* opts GEN_PARAM_DEFAULT); -#define gen_def_union(name, body, ...) gen_def__union(name, body, &(gen_Opts_def_union) { __VA_ARGS__ }) - -struct gen_Opts_def_using -{ - gen_CodeAttributes attributes; - gen_ModuleFlag mflags; -}; -typedef struct gen_Opts_def_using gen_Opts_def_using; - -GEN_API gen_CodeUsing gen_def__using(gen_Str name, gen_CodeTypename type, gen_Opts_def_using* opts GEN_PARAM_DEFAULT); -#define gen_def_using(name, type, ...) gen_def__using(name, type, &(gen_Opts_def_using) { __VA_ARGS__ }) - -GEN_API gen_CodeUsing gen_def_using_namespace(gen_Str name); - -struct gen_Opts_def_variable -{ - gen_Code value; - gen_CodeSpecifiers specifiers; - gen_CodeAttributes attributes; - gen_ModuleFlag mflags; -}; -typedef struct gen_Opts_def_variable gen_Opts_def_variable; - -GEN_API gen_CodeVar gen_def__variable(gen_CodeTypename type, gen_Str name, gen_Opts_def_variable* opts GEN_PARAM_DEFAULT); -#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_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. - -GEN_API gen_CodeBody gen_def_class_body(gen_s32 num, ...); -GEN_API gen_CodeBody gen_def_class_body_arr(gen_s32 num, gen_Code* codes); -GEN_API gen_CodeDefineParams gen_def_define_params(gen_s32 num, ...); -GEN_API gen_CodeDefineParams gen_def_define_params_arr(gen_s32 num, gen_CodeDefineParams* codes); -GEN_API gen_CodeBody gen_def_enum_body(gen_s32 num, ...); -GEN_API gen_CodeBody gen_def_enum_body_arr(gen_s32 num, gen_Code* codes); -GEN_API gen_CodeBody gen_def_export_body(gen_s32 num, ...); -GEN_API gen_CodeBody gen_def_export_body_arr(gen_s32 num, gen_Code* codes); -GEN_API gen_CodeBody gen_def_extern_link_body(gen_s32 num, ...); -GEN_API gen_CodeBody gen_def_extern_link_body_arr(gen_s32 num, gen_Code* codes); -GEN_API gen_CodeBody gen_def_function_body(gen_s32 num, ...); -GEN_API gen_CodeBody gen_def_function_body_arr(gen_s32 num, gen_Code* codes); -GEN_API gen_CodeBody gen_def_global_body(gen_s32 num, ...); -GEN_API gen_CodeBody gen_def_global_body_arr(gen_s32 num, gen_Code* codes); -GEN_API gen_CodeBody gen_def_namespace_body(gen_s32 num, ...); -GEN_API gen_CodeBody gen_def_namespace_body_arr(gen_s32 num, gen_Code* codes); -GEN_API gen_CodeParams gen_def_params(gen_s32 num, ...); -GEN_API gen_CodeParams gen_def_params_arr(gen_s32 num, gen_CodeParams* params); -GEN_API gen_CodeSpecifiers gen_def_specifiers(gen_s32 num, ...); -GEN_API gen_CodeSpecifiers gen_def_specifiers_arr(gen_s32 num, gen_Specifier* specs); -GEN_API gen_CodeBody gen_def_struct_body(gen_s32 num, ...); -GEN_API gen_CodeBody gen_def_struct_body_arr(gen_s32 num, gen_Code* codes); -GEN_API gen_CodeBody gen_def_union_body(gen_s32 num, ...); -GEN_API gen_CodeBody gen_def_union_body_arr(gen_s32 num, gen_Code* codes); - - -#pragma endregion Upfront - - -#pragma region Parsing - -struct gen_ParseStackNode -{ - gen_ParseStackNode* prev; - - TokenSlice tokens; - gen_Token* start; - gen_Str name; // The name of the gen_AST node (if parsed) - gen_Str proc_name; // The name of the procedure - gen_Code gen_code_rel; // Relevant gen_AST node - // TODO(Ed): When an error occurs, the parse stack is not released and instead the scope is left dangling. -}; -typedef struct gen_ParseStackNode gen_ParseStackNode; - -struct ParseInfo -{ - ParseMessage* messages; - LexedInfo lexed; - gen_Code result; -}; -typedef struct ParseInfo ParseInfo; - -struct ParseOpts -{ - gen_AllocatorInfo backing_msgs; - gen_AllocatorInfo backing_tokens; - gen_AllocatorInfo backing_ast; -}; -typedef struct ParseOpts ParseOpts; - - -ParseInfo wip_parse_str(LexedInfo lexed, ParseOpts* opts GEN_PARAM_DEFAULT); - -GEN_API gen_CodeClass gen_parse_class(gen_Str gen_class_def); -GEN_API gen_CodeConstructor gen_parse_constructor(gen_Str gen_constructor__def); -GEN_API gen_CodeDefine gen_parse_define(gen_Str gen_define_def); -GEN_API gen_CodeDestructor gen_parse_destructor(gen_Str gen_destructor__def); -GEN_API gen_CodeEnum gen_parse_enum(gen_Str gen_enum_def); -GEN_API gen_CodeBody gen_parse_export_body(gen_Str export_def); -GEN_API gen_CodeExtern gen_parse_extern_link(gen_Str exten_link_def); -GEN_API gen_CodeFriend gen_parse_friend(gen_Str gen_friend_def); -GEN_API gen_CodeFn gen_parse_function(gen_Str gen_fn_def); -GEN_API gen_CodeBody gen_parse_global_body(gen_Str gen_body_def); -GEN_API gen_CodeNS gen_parse_namespace(gen_Str namespace_def); -GEN_API gen_CodeOperator gen_parse_operator(gen_Str operator_def); -GEN_API gen_CodeOpCast gen_parse_operator_cast(gen_Str operator_def); -GEN_API gen_CodeStruct gen_parse_struct(gen_Str gen_struct_def); -GEN_API gen_CodeTemplate gen_parse_template(gen_Str gen_template_def); -GEN_API gen_CodeTypename gen_parse_type(gen_Str type_def); -GEN_API gen_CodeTypedef gen_parse_typedef(gen_Str gen_typedef_def); -GEN_API gen_CodeUnion gen_parse_union(gen_Str union_def); -GEN_API gen_CodeUsing gen_parse_using(gen_Str gen_using_def); -GEN_API gen_CodeVar gen_parse_variable(gen_Str gen_var_def); - -#pragma endregion Parsing - - -#pragma region Untyped text - - -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_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, ...); -GEN_API gen_Code gen_untyped_token_fmt(gen_s32 num_tokens, char const* fmt, ...); -GEN_API gen_Code gen_untyped_toks(TokenSlice tokens); - -#pragma endregion Untyped text - - -#pragma region Macros - - -#ifndef gen_main -#define gen_main main -#endif - -#ifndef name -// Convienence for defining any name used with the gen api. -// Lets you provide the length and string literal to the functions without the need for the DSL. -#if GEN_COMPILER_C -#define name(Id_) (gen_Str) { gen_stringize(Id_), sizeof(gen_stringize(Id_)) - 1 } -#else -#define name(Id_) gen_Str { gen_stringize(Id_), sizeof(gen_stringize(Id_)) - 1 } -#endif -#endif - -#ifndef code -// Same as name just used to indicate intention of literal for code instead of names. -#if GEN_COMPILER_C -#define code(...) (gen_Str) { gen_stringize(__VA_ARGS__), sizeof(gen_stringize(__VA_ARGS__)) - 1 } -#else -#define code(...) gen_Str { gen_stringize(__VA_ARGS__), sizeof(gen_stringize(__VA_ARGS__)) - 1 } -#endif -#endif - -#ifndef args -// Provides the number of arguments while passing args inplace. -#define args(...) gen_num_args(__VA_ARGS__), __VA_ARGS__ -#endif - -#ifndef gen_code_str -// Just wrappers over common untyped code definition constructions. -#define gen_code_str(...) GEN_NS gen_untyped_str(code(__VA_ARGS__)) -#endif - -#ifndef gen_code_fmt -#define gen_code_fmt(...) GEN_NS gen_untyped_str(gen_token_fmt(__VA_ARGS__)) -#endif - -#ifndef gen_parse_fmt -#define gen_parse_fmt(type, ...) GEN_NS gen_parse_##type(gen_token_fmt(__VA_ARGS__)) -#endif - -#ifndef gen_token_fmt -/* -Takes a format string (char const*) and a list of tokens (gen_Str) and returns a gen_Str of the formatted string. -Tokens are provided in '<'identifier'>' format where '<' '>' are just angle brackets (you can change it in gen_token_fmt_va) ---------------------------------------------------------- - Example - A string with: - typedef ; - Will have a gen_token_fmt arguments populated with: - "type", gen_str_for_type, - "name", gen_str_for_name, - and: - gen_stringize( typedef ; ) ------------------------------------------------------------ -So the full call for this example would be: - gen_token_fmt( - "type", gen_str_for_type - , "name", gen_str_for_name - , gen_stringize( - typedef - )); -!---------------------------------------------------------- -! Note: gen_token_fmt_va is whitespace sensitive for the tokens. -! This can be alleviated by skipping whitespace between brackets but it was choosen to not have that implementation by default. -*/ -#define gen_token_fmt(...) GEN_NS gen_token_fmt_impl((gen_num_args(__VA_ARGS__) + 1) / 2, __VA_ARGS__) -#endif - -#pragma endregion Macros - - -#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, gen_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, gen_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 = curr->Next; - } -} - -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, gen_txt(";")); - } - - if (self->InlineCmt) - gen_strbuilder_append_fmt(result, " %S", self->InlineCmt->Content); - else - gen_strbuilder_append_str(result, gen_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, gen_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, gen_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, gen_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, gen_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(gen_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) -{ - GEN_ASSERT(self); - GEN_ASSERT(other); - GEN_ASSERT_MSG(self != other, "Attempted to recursively append gen_Code gen_AST to itself."); - - if (other->Parent != gen_nullptr) - other = gen_code_duplicate(other); - - other->Parent = self; - - if (self->Front == gen_nullptr) - { - self->Front = other; - self->Back = other; - - self->NumEntries++; - return; - } - - gen_Code Current = self->Back; - Current->Next = other; - other->Prev = Current; - self->Back = other; - self->NumEntries++; -} - -inline bool gen_code__is_body(gen_Code self) -{ - GEN_ASSERT(self); - switch (self->Type) - { - case CT_Enum_Body: - case CT_Class_Body: - case CT_Union_Body: - case CT_Export_Body: - case CT_Global_Body: - case CT_Struct_Body: - case CT_Function_Body: - case CT_Namespace_Body: - case CT_Extern_Linkage_Body: - return true; - } - return false; -} - -inline gen_Code* gen_code__entry(gen_Code self, gen_u32 idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_Code* current = &self->Front; - while (idx >= 0 && current != gen_nullptr) - { - if (idx == 0) - return gen_rcast(gen_Code*, current); - - current = &(*current)->Next; - idx--; - } - - return gen_rcast(gen_Code*, current); -} - -gen_forceinline bool gen_code__is_valid(gen_Code self) -{ - GEN_ASSERT(self); - return self != gen_nullptr && self->Type != CT_Invalid; -} - -gen_forceinline bool gen_code__has_entries(gen_Code self) -{ - GEN_ASSERT(self); - return self->NumEntries > 0; -} - -gen_forceinline void gen_code__set_global(gen_Code self) -{ - if (self == gen_nullptr) - { - gen_log_failure("gen_Code::set_global: Cannot set code as gen_global, gen_AST is null!"); - return; - } - - self->Parent = gen_Code_Global; -} - -gen_forceinline gen_Str gen_code__type_str(gen_Code self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_codetype_to_str(self->Type); -} - -#pragma endregion gen_Code - - -#pragma region gen_CodeBody - -inline void gen_body_append(gen_CodeBody self, gen_Code other) -{ - GEN_ASSERT(self); - GEN_ASSERT(other); - - if (gen_code_is_body(other)) - { - gen_body_append_body(self, gen_cast(gen_CodeBody, other)); - return; - } - - gen_code_append(gen_cast(gen_Code, self), other); -} - -inline void gen_body_append_body(gen_CodeBody self, gen_CodeBody body) -{ - GEN_ASSERT(self); - GEN_ASSERT(body); - GEN_ASSERT_MSG(self != body, "Attempted to append body to itself."); - - for (gen_Code entry = gen_begin_CodeBody(body); entry != gen_end_CodeBody(body); entry = gen_next_CodeBody(body, entry)) - { - gen_body_append(self, entry); - } -} - -inline gen_Code gen_begin_CodeBody(gen_CodeBody body) -{ - GEN_ASSERT(body); - if (body != gen_nullptr) - return body->Front; - - return gen_NullCode; -} - -gen_forceinline gen_Code gen_end_CodeBody(gen_CodeBody body) -{ - GEN_ASSERT(body); - return body->Back->Next; -} - -inline gen_Code gen_next_CodeBody(gen_CodeBody body, gen_Code entry) -{ - GEN_ASSERT(body); - GEN_ASSERT(entry); - return entry->Next; -} - -#pragma endregion gen_CodeBody - - -#pragma region gen_CodeClass - -inline void gen_class_add_interface(gen_CodeClass self, gen_CodeTypename type) -{ - GEN_ASSERT(self); - GEN_ASSERT(type); - gen_CodeTypename possible_slot = self->ParentType; - if (possible_slot != gen_nullptr) - { - // Were adding an interface to parent type, so we need to make sure the parent type is public. - self->ParentAccess = AccessSpec_Public; - // If your planning on adding a proper parent, - // then you'll need to move this over to ParentType->next and update ParentAccess accordingly. - } - - while (possible_slot->Next != gen_nullptr) - { - possible_slot = gen_cast(gen_CodeTypename, possible_slot->Next); - } - - possible_slot->Next = gen_cast(gen_Code, type); -} - -#pragma endregion gen_CodeClass - - -#pragma region gen_CodeParams - -inline void gen_params_append(gen_CodeParams appendee, gen_CodeParams other) -{ - GEN_ASSERT(appendee); - GEN_ASSERT(other); - GEN_ASSERT_MSG(appendee != other, "Attempted to append parameter to itself."); - gen_Code self = gen_cast(gen_Code, appendee); - gen_Code entry = gen_cast(gen_Code, other); - - if (entry->Parent != gen_nullptr) - entry = gen_code_duplicate(entry); - - entry->Parent = self; - - if (self->Last == gen_nullptr) - { - self->Last = entry; - self->Next = entry; - self->NumEntries++; - return; - } - - self->Last->Next = entry; - self->Last = entry; - self->NumEntries++; -} - -inline gen_CodeParams gen_params_get(gen_CodeParams self, gen_s32 idx) -{ - GEN_ASSERT(self); - gen_CodeParams param = self; - do - { - if (++param != gen_nullptr) - return gen_NullCode; - - param = gen_cast(gen_CodeParams, gen_cast(gen_Code, param)->Next); - } while (--idx); - - return param; -} - -gen_forceinline bool gen_params_has_entries(gen_CodeParams self) -{ - GEN_ASSERT(self); - return self->NumEntries > 0; -} - -gen_forceinline gen_CodeParams gen_begin_CodeParams(gen_CodeParams params) -{ - if (params != gen_nullptr) - return params; - - return gen_NullCode; -} - -gen_forceinline gen_CodeParams gen_end_CodeParams(gen_CodeParams params) -{ - // return { (gen_AST_Params*) gen_rcast( gen_AST*, ast)->Last }; - return gen_NullCode; -} - -gen_forceinline gen_CodeParams gen_next_CodeParams(gen_CodeParams params, gen_CodeParams param_iter) -{ - GEN_ASSERT(param_iter); - return param_iter->Next; -} - -#pragma endregion gen_CodeParams - - -#pragma region gen_CodeDefineParams - -gen_forceinline void gen_define_params_append(gen_CodeDefineParams appendee, gen_CodeDefineParams other) -{ - gen_params_append(gen_cast(gen_CodeParams, appendee), gen_cast(gen_CodeParams, other)); -} - -gen_forceinline gen_CodeDefineParams gen_define_params_get(gen_CodeDefineParams self, gen_s32 idx) -{ - return (gen_CodeDefineParams)(gen_Code)gen_params_get(gen_cast(gen_CodeParams, self), idx); -} - -gen_forceinline bool gen_define_params_has_entries(gen_CodeDefineParams self) -{ - return gen_params_has_entries(gen_cast(gen_CodeParams, self)); -} - -gen_forceinline gen_CodeDefineParams gen_begin_CodeDefineParams(gen_CodeDefineParams params) -{ - return (gen_CodeDefineParams)(gen_Code)gen_begin_CodeParams(gen_cast(gen_CodeParams, (gen_Code)params)); -} - -gen_forceinline gen_CodeDefineParams gen_end_CodeDefineParams(gen_CodeDefineParams params) -{ - return (gen_CodeDefineParams)(gen_Code)gen_end_CodeParams(gen_cast(gen_CodeParams, (gen_Code)params)); -} - -gen_forceinline gen_CodeDefineParams gen_next_CodeDefineParams(gen_CodeDefineParams params, gen_CodeDefineParams entry_iter) -{ - return (gen_CodeDefineParams)(gen_Code)gen_next_CodeParams(gen_cast(gen_CodeParams, (gen_Code)params), gen_cast(gen_CodeParams, (gen_Code)entry_iter)); -} - -#pragma endregion gen_CodeDefineParams - - -#pragma region gen_CodeSpecifiers - -inline bool gen_specifiers_append(gen_CodeSpecifiers self, gen_Specifier spec) -{ - if (self == gen_nullptr) - { - gen_log_failure("gen_CodeSpecifiers: Attempted to append to a null specifiers gen_AST!"); - return false; - } - if (self->NumEntries == gen_AST_ArrSpecs_Cap) - { - gen_log_failure("gen_CodeSpecifiers: Attempted to append over %d specifiers to a specifiers gen_AST!", gen_AST_ArrSpecs_Cap); - return false; - } - - self->ArrSpecs[self->NumEntries] = spec; - self->NumEntries++; - return true; -} - -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++) - { - if (self->ArrSpecs[idx] == spec) - return idx; - } - return -1; -} - -inline gen_s32 gen_specifiers_remove(gen_CodeSpecifiers self, gen_Specifier to_remove) -{ - if (self == gen_nullptr) - { - gen_log_failure("gen_CodeSpecifiers: Attempted to append to a null specifiers gen_AST!"); - return -1; - } - if (self->NumEntries == gen_AST_ArrSpecs_Cap) - { - gen_log_failure("gen_CodeSpecifiers: Attempted to append over %d specifiers to a specifiers gen_AST!", gen_AST_ArrSpecs_Cap); - return -1; - } - - gen_s32 result = -1; - - gen_s32 curr = 0; - gen_s32 next = 0; - for (; next < self->NumEntries; ++curr, ++next) - { - gen_Specifier spec = self->ArrSpecs[next]; - if (spec == to_remove) - { - result = next; - - next++; - if (next >= self->NumEntries) - break; - - spec = self->ArrSpecs[next]; - } - - self->ArrSpecs[curr] = spec; - } - - if (result > -1) - { - self->NumEntries--; - } - return result; -} - -gen_forceinline gen_Specifier* gen_begin_CodeSpecifiers(gen_CodeSpecifiers self) -{ - if (self != gen_nullptr) - return &self->ArrSpecs[0]; - - return gen_nullptr; -} - -gen_forceinline gen_Specifier* gen_end_CodeSpecifiers(gen_CodeSpecifiers self) -{ - return self->ArrSpecs + self->NumEntries; -} - -gen_forceinline gen_Specifier* gen_next_CodeSpecifiers(gen_CodeSpecifiers self, gen_Specifier* gen_spec_iter) -{ - return gen_spec_iter + 1; -} - -#pragma endregion gen_CodeSpecifiers - - -#pragma region gen_CodeStruct - -inline void gen_struct_add_interface(gen_CodeStruct self, gen_CodeTypename type) -{ - gen_CodeTypename possible_slot = self->ParentType; - if (possible_slot != gen_nullptr) - { - // Were adding an interface to parent type, so we need to make sure the parent type is public. - self->ParentAccess = AccessSpec_Public; - // If your planning on adding a proper parent, - // then you'll need to move this over to ParentType->next and update ParentAccess accordingly. - } - - while (possible_slot->Next != gen_nullptr) - { - possible_slot = gen_cast(gen_CodeTypename, possible_slot->Next); - } - - possible_slot->Next = gen_cast(gen_Code, type); -} - -#pragma endregion gen_Code - - -#pragma region Interface - -inline gen_CodeBody gen_def_body(gen_CodeType type) -{ - switch (type) - { - case CT_Class_Body: - case CT_Enum_Body: - case CT_Export_Body: - case CT_Extern_Linkage: - case CT_Function_Body: - case CT_Global_Body: - case CT_Namespace_Body: - case CT_Struct_Body: - case CT_Union_Body: - break; - - default: - gen_log_failure("gen_def_body: Invalid type %s", gen_codetype_to_str(type).Ptr); - return (gen_CodeBody)gen_Code_Invalid; - } - - gen_Code result = gen_make_code(); - result->Type = type; - return (gen_CodeBody)result; -} - -inline gen_Str gen_token_fmt_impl(gen_ssize num, ...) -{ - gen_local_persist gen_thread_local char buf[GEN_PRINTF_MAXLEN] = { 0 }; - gen_mem_set(buf, 0, GEN_PRINTF_MAXLEN); - - va_list va; - va_start(va, num); - gen_ssize result = gen_token_fmt_va(buf, GEN_PRINTF_MAXLEN, num, va); - va_end(va); - - gen_Str str = { buf, result }; - return str; -} - -#pragma endregion Interface -#pragma endregion Inlines - - -#pragma region gen_Builder - - -struct gen_Builder; -typedef struct gen_Builder gen_Builder; - -GEN_API gen_Builder gen_builder_open(char const* path); -GEN_API void gen_builder_pad_lines(gen_Builder* builder, gen_s32 num); -GEN_API void gen_builder__print(gen_Builder* builder, gen_Code code); -GEN_API void gen_builder_print_fmt_va(gen_Builder* builder, char const* fmt, va_list va); -GEN_API void gen_builder_write(gen_Builder* builder); - -gen_forceinline void gen_builder_print_fmt(gen_Builder* builder, char const* fmt, ...) -{ - va_list va; - va_start(va, fmt); - gen_builder_print_fmt_va(builder, fmt, va); - va_end(va); -} - -#define gen_builder_print(builder, code) \ - _Generic( \ - (code), \ - gen_Code: gen_builder__print, \ - gen_CodeBody: gen_builder__print, \ - gen_CodeAttributes: gen_builder__print, \ - gen_CodeComment: gen_builder__print, \ - gen_CodeClass: gen_builder__print, \ - gen_CodeConstructor: gen_builder__print, \ - gen_CodeDefine: gen_builder__print, \ - gen_CodeDefineParams: gen_builder__print, \ - gen_CodeDestructor: gen_builder__print, \ - gen_CodeEnum: gen_builder__print, \ - gen_CodeExec: gen_builder__print, \ - gen_CodeExtern: gen_builder__print, \ - gen_CodeInclude: gen_builder__print, \ - gen_CodeFriend: gen_builder__print, \ - gen_CodeFn: gen_builder__print, \ - gen_CodeModule: gen_builder__print, \ - gen_CodeNS: gen_builder__print, \ - gen_CodeOperator: gen_builder__print, \ - gen_CodeOpCast: gen_builder__print, \ - gen_CodePragma: gen_builder__print, \ - gen_CodeParams: gen_builder__print, \ - gen_CodePreprocessCond: gen_builder__print, \ - gen_CodeSpecifiers: gen_builder__print, \ - gen_CodeStruct: gen_builder__print, \ - gen_CodeTemplate: gen_builder__print, \ - gen_CodeTypename: gen_builder__print, \ - gen_CodeTypedef: gen_builder__print, \ - gen_CodeUnion: gen_builder__print, \ - gen_CodeUsing: gen_builder__print, \ - gen_CodeVar: gen_builder__print, \ - default: gen_generic_selection_fail \ - ) GEN_RESOLVED_FUNCTION_CALL(builder, (gen_Code)code) - -struct gen_Builder -{ - gen_FileInfo File; - gen_StrBuilder Buffer; -}; - -#pragma endregion gen_Builder - -#pragma region Scanner - -// This is a simple file reader that reads the entire file into memory. -// It has an extra option to skip the first few lines for undesired includes. -// This is done so that includes can be kept in dependency and component files so that intellisense works. -GEN_API gen_Code gen_scan_file(char const* path); - -GEN_API gen_CodeBody gen_parse_file(const char* path); - -// The follow is basic support for light csv parsing (use it as an example) -// Make something robust if its more serious. - -typedef struct gen_CSV_Column gen_CSV_Column; - -struct gen_CSV_Column -{ - gen_CSV_Object ADT; - gen_Array(gen_ADT_Node) Content; -}; - -typedef struct gen_CSV_Columns2 gen_CSV_Columns2; - -struct gen_CSV_Columns2 -{ - gen_CSV_Object ADT; - gen_Array(gen_ADT_Node) Col_1; - gen_Array(gen_ADT_Node) Col_2; -}; - -GEN_API gen_CSV_Column gen_parse_csv_one_column(gen_AllocatorInfo allocator, char const* path); -GEN_API gen_CSV_Columns2 gen_parse_csv_two_columns(gen_AllocatorInfo allocator, char const* path); - -#pragma endregion Scanner - -GEN_API_C_END -GEN_NS_END - - -#pragma region GENCPP IMPLEMENTATION GUARD -#if defined(GEN_IMPLEMENTATION) && ! defined(GEN_IMPLEMENTED) -# define GEN_IMPLEMENTED - -//! If its desired to roll your own dependencies, define GEN_ROLL_OWN_DEPENDENCIES before including this file. -// Dependencies are derived from the c-zpl library: https://github.com/zpl-c/zpl -#ifndef GEN_ROLL_OWN_DEPENDENCIES - -GEN_NS_BEGIN -GEN_API_C_BEGIN - -#pragma region Macros and Includes - -# include -// NOTE: Ensure we use standard methods for these calls if we use GEN_PICO -# if ! defined( GEN_PICO_CUSTOM_ROUTINES ) -# if ! defined( GEN_MODULE_CORE ) -# define _strlen strlen -# define _printf_err( fmt, ... ) fprintf( stderr, fmt, __VA_ARGS__ ) -# define _printf_err_va( fmt, va ) vfprintf( stderr, fmt, va ) -# else -# define _strlen gen_c_str_len -# define _printf_err( fmt, ... ) gen_c_str_fmt_out_err( fmt, __VA_ARGS__ ) -# define _printf_err_va( fmt, va ) gen_c_str_fmt_out_err_va( fmt, va ) -# endif -# endif -# -# include -# -# if defined( GEN_SYSTEM_UNIX ) || defined( GEN_SYSTEM_MACOS ) -# include -# elif defined( GEN_SYSTEM_WINDOWS ) -# if ! defined( GEN_NO_WINDOWS_H ) -# ifndef WIN32_LEAN_AND_MEAN -# ifndef NOMINMAX -# define NOMINMAX -# endif -# -# define WIN32_LEAN_AND_MEAN -# define WIN32_MEAN_AND_LEAN -# define VC_EXTRALEAN -# endif -# include -# undef NOMINMAX -# undef WIN32_LEAN_AND_MEAN -# undef WIN32_MEAN_AND_LEAN -# undef VC_EXTRALEAN -# endif -# endif - -#include - -#ifdef GEN_SYSTEM_MACOS -# include -#endif - -#ifdef GEN_SYSTEM_CYGWIN -# include -#endif - -#if defined( GEN_SYSTEM_WINDOWS ) && ! defined( GEN_COMPILER_GCC ) -# include -#endif - -#if defined( GEN_SYSTEM_LINUX ) -# include -#endif - -#ifdef GEN_BENCHMARK -// Timing includes -#if defined( GEN_SYSTEM_MACOS ) || GEN_SYSTEM_UNIX -# include -# include -#endif - -#if defined( GEN_SYSTEM_MACOS ) -# include -# include -# include -#endif - -#if defined( GEN_SYSTEM_EMSCRIPTEN ) -# include -#endif - -#if defined( GEN_SYSTEM_WINDOWS ) -# include -#endif -#endif - -#pragma endregion Macros and Includes - -#pragma region Debug - -void gen_assert_handler( char const* condition, char const* file, char const* function, gen_s32 line, char const* msg, ... ) -{ - _printf_err( "%s - %s:(%d): Assert Failure: ", file, function, line ); - - if ( condition ) - _printf_err( "`%s` \n", condition ); - - if ( msg ) - { - va_list va; - va_start( va, msg ); - _printf_err_va( msg, va ); - va_end( va ); - } - - _printf_err( "%s", "\n" ); -} - -gen_s32 gen_assert_crash( char const* condition ) -{ - GEN_PANIC( condition ); - return 0; -} - -#if defined( GEN_SYSTEM_WINDOWS ) - void gen_process_exit( gen_u32 code ) - { - ExitProcess( code ); - } -#else -# include - - void gen_process_exit( gen_u32 code ) - { - exit( code ); - } -#endif - -#pragma endregion Debug - -#pragma region String Ops - -gen_internal -gen_ssize _scan_zpl_i64( const char* text, gen_s32 base, gen_s64* value ) -{ - const char* text_begin = text; - gen_s64 result = 0; - gen_b32 negative = false; - - if ( *text == '-' ) - { - negative = true; - text++; - } - - if ( base == 16 && gen_c_str_compare_len( text, "0x", 2 ) == 0 ) - text += 2; - - for ( ;; ) - { - gen_s64 v; - if ( gen_char_is_digit( *text ) ) - v = *text - '0'; - else if ( base == 16 && gen_char_is_hex_digit( *text ) ) - v = hex_digit_to_int( *text ); - else - break; - - result *= base; - result += v; - text++; - } - - if ( value ) - { - if ( negative ) - result = -result; - *value = result; - } - - return ( text - text_begin ); -} - -// TODO : Are these good enough for characters? -gen_global const char _num_to_char_table[] = - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "@$"; - -gen_s64 gen_c_str_to_i64( const char* str, char** gen_end_ptr, gen_s32 base ) -{ - gen_ssize len; - gen_s64 value; - - if ( ! base ) - { - if ( ( gen_c_str_len( str ) > 2 ) && ( gen_c_str_compare_len( str, "0x", 2 ) == 0 ) ) - base = 16; - else - base = 10; - } - - len = _scan_zpl_i64( str, base, &value ); - if ( gen_end_ptr ) - *gen_end_ptr = ( char* )str + len; - return value; -} - -void gen_i64_to_str( gen_s64 value, char* string, gen_s32 base ) -{ - char* buf = string; - gen_b32 negative = false; - gen_u64 v; - - if ( value < 0 ) - { - negative = true; - value = -value; - } - - v = gen_scast( gen_u64, value); - if ( v != 0 ) - { - while ( v > 0 ) - { - *buf++ = _num_to_char_table[ v % base ]; - v /= base; - } - } - else - { - *buf++ = '0'; - } - if ( negative ) - *buf++ = '-'; - *buf = '\0'; - gen_c_str_reverse( string ); -} - -void gen_u64_to_str( gen_u64 value, char* string, gen_s32 base ) -{ - char* buf = string; - - if ( value ) - { - while ( value > 0 ) - { - *buf++ = _num_to_char_table[ value % base ]; - value /= base; - } - } - else - { - *buf++ = '0'; - } - *buf = '\0'; - - gen_c_str_reverse( string ); -} - -gen_f64 gen_c_str_to_f64( const char* str, char** gen_end_ptr ) -{ - gen_f64 result, value, sign, scale; - gen_s32 frac; - - while ( gen_char_is_space( *str ) ) - { - str++; - } - - sign = 1.0; - if ( *str == '-' ) - { - sign = -1.0; - str++; - } - else if ( *str == '+' ) - { - str++; - } - - for ( value = 0.0; gen_char_is_digit( *str ); str++ ) - { - value = value * 10.0 + ( *str - '0' ); - } - - if ( *str == '.' ) - { - gen_f64 pow10 = 10.0; - str++; - while ( gen_char_is_digit( *str ) ) - { - value += ( *str - '0' ) / pow10; - pow10 *= 10.0; - str++; - } - } - - frac = 0; - scale = 1.0; - if ( ( *str == 'e' ) || ( *str == 'E' ) ) - { - gen_u32 exp; - - str++; - if ( *str == '-' ) - { - frac = 1; - str++; - } - else if ( *str == '+' ) - { - str++; - } - - for ( exp = 0; gen_char_is_digit( *str ); str++ ) - { - exp = exp * 10 + ( *str - '0' ); - } - if ( exp > 308 ) - exp = 308; - - while ( exp >= 50 ) - { - scale *= 1e50; - exp -= 50; - } - while ( exp >= 8 ) - { - scale *= 1e8; - exp -= 8; - } - while ( exp > 0 ) - { - scale *= 10.0; - exp -= 1; - } - } - - result = sign * ( frac ? ( value / scale ) : ( value * scale ) ); - - if ( gen_end_ptr ) - * gen_end_ptr = gen_rcast( char*, gen_ccast(char*, str) ); - - return result; -} - -#pragma endregion String Ops - -#pragma region Printing - -enum -{ - GEN_FMT_MINUS = gen_bit( 0 ), - GEN_FMT_PLUS = gen_bit( 1 ), - GEN_FMT_ALT = gen_bit( 2 ), - GEN_FMT_SPACE = gen_bit( 3 ), - GEN_FMT_ZERO = gen_bit( 4 ), - - GEN_FMT_CHAR = gen_bit( 5 ), - GEN_FMT_SHORT = gen_bit( 6 ), - GEN_FMT_INT = gen_bit( 7 ), - GEN_FMT_LONG = gen_bit( 8 ), - GEN_FMT_LLONG = gen_bit( 9 ), - GEN_FMT_SIZE = gen_bit( 10 ), - GEN_FMT_INTPTR = gen_bit( 11 ), - - GEN_FMT_UNSIGNED = gen_bit( 12 ), - GEN_FMT_LOWER = gen_bit( 13 ), - GEN_FMT_UPPER = gen_bit( 14 ), - GEN_FMT_WIDTH = gen_bit( 15 ), - - GEN_FMT_DONE = gen_bit( 30 ), - - GEN_FMT_INTS = GEN_FMT_CHAR | GEN_FMT_SHORT | GEN_FMT_INT | GEN_FMT_LONG | GEN_FMT_LLONG | GEN_FMT_SIZE | GEN_FMT_INTPTR -}; - -typedef struct gen__format_info gen__format_info; -struct gen__format_info -{ - gen_s32 base; - gen_s32 flags; - gen_s32 width; - gen_s32 precision; -}; - -gen_internal gen_ssize gen__print_string( char* text, gen_ssize max_len, gen__format_info* info, char const* str ) -{ - gen_ssize res = 0, len = 0; - gen_ssize remaining = max_len; - char* begin = text; - - if ( str == NULL && max_len >= 6 ) - { - res += gen_c_str_copy_nulpad( text, "(null)", 6 ); - return res; - } - - if ( info && info->precision >= 0 ) - // Made the design decision for this library that precision is the length of the string. - len = info->precision; - else - len = gen_c_str_len( str ); - - if ( info && ( info->width == 0 && info->flags & GEN_FMT_WIDTH ) ) - { - return res; - } - - if ( info && ( info->width == 0 || info->flags & GEN_FMT_MINUS ) ) - { - if ( info->precision > 0 ) - len = info->precision < len ? info->precision : len; - if ( res + len > max_len ) - return res; - res += gen_c_str_copy_nulpad( text, str, len ); - text += res; - - if ( info->width > res ) - { - gen_ssize padding = info->width - len; - - char pad = ( info->flags & GEN_FMT_ZERO ) ? '0' : ' '; - while ( padding-- > 0 && remaining-- > 0 ) - *text++ = pad, res++; - } - } - else - { - if ( info && ( info->width > res ) ) - { - gen_ssize padding = info->width - len; - char pad = ( info->flags & GEN_FMT_ZERO ) ? '0' : ' '; - while ( padding-- > 0 && remaining-- > 0 ) - *text++ = pad, res++; - } - - if ( res + len > max_len ) - return res; - res += gen_c_str_copy_nulpad( text, str, len ); - } - - if ( info ) - { - if ( info->flags & GEN_FMT_UPPER ) - gen_c_str_to_upper( begin ); - else if ( info->flags & GEN_FMT_LOWER ) - gen_c_str_to_lower( begin ); - } - - return res; -} - -gen_internal gen_ssize gen__print_char( char* text, gen_ssize max_len, gen__format_info* info, char arg ) -{ - char str[ 2 ] = ""; - str[ 0 ] = arg; - return gen__print_string( text, max_len, info, str ); -} - -gen_internal gen_ssize gen__print_repeated_char( char* text, gen_ssize max_len, gen__format_info* info, char arg ) -{ - gen_ssize res = 0; - gen_s32 rem = ( info ) ? ( info->width > 0 ) ? info->width : 1 : 1; - res = rem; - while ( rem-- > 0 ) - *text++ = arg; - - return res; -} - -gen_internal gen_ssize gen__print_i64( char* text, gen_ssize max_len, gen__format_info* info, gen_s64 value ) -{ - char num[ 130 ]; - gen_i64_to_str( value, num, info ? info->base : 10 ); - return gen__print_string( text, max_len, info, num ); -} - -gen_internal gen_ssize gen__print_u64( char* text, gen_ssize max_len, gen__format_info* info, gen_u64 value ) -{ - char num[ 130 ]; - gen_u64_to_str( value, num, info ? info->base : 10 ); - return gen__print_string( text, max_len, info, num ); -} - -gen_internal gen_ssize gen__print_f64( char* text, gen_ssize max_len, gen__format_info* info, gen_b32 is_hexadecimal, gen_f64 arg ) -{ - // TODO: Handle exponent notation - gen_ssize width, len, remaining = max_len; - char* text_begin = text; - - if ( arg ) - { - gen_u64 value; - if ( arg < 0 ) - { - if ( remaining > 1 ) - *text = '-', remaining--; - text++; - arg = -arg; - } - else if ( info->flags & GEN_FMT_MINUS ) - { - if ( remaining > 1 ) - *text = '+', remaining--; - text++; - } - - value = gen_scast( gen_u64, arg); - len = gen__print_u64( text, remaining, NULL, value ); - text += len; - - if ( len >= remaining ) - remaining = gen_min( remaining, 1 ); - else - remaining -= len; - arg -= value; - - if ( info->precision < 0 ) - info->precision = 6; - - if ( ( info->flags & GEN_FMT_ALT ) || info->precision > 0 ) - { - gen_s64 mult = 10; - if ( remaining > 1 ) - *text = '.', remaining--; - text++; - while ( info->precision-- > 0 ) - { - value = gen_scast( gen_u64, arg * mult ); - len = gen__print_u64( text, remaining, NULL, value ); - text += len; - if ( len >= remaining ) - remaining = gen_min( remaining, 1 ); - else - remaining -= len; - arg -= gen_scast( gen_f64, value / mult); - mult *= 10; - } - } - } - else - { - if ( remaining > 1 ) - *text = '0', remaining--; - text++; - if ( info->flags & GEN_FMT_ALT ) - { - if ( remaining > 1 ) - *text = '.', remaining--; - text++; - } - } - - width = info->width - ( text - text_begin ); - if ( width > 0 ) - { - char fill = ( info->flags & GEN_FMT_ZERO ) ? '0' : ' '; - char* end = text + remaining - 1; - len = ( text - text_begin ); - - for ( len = ( text - text_begin ); len--; ) - { - if ( ( text_begin + len + width ) < end ) - *( text_begin + len + width ) = *( text_begin + len ); - } - - len = width; - text += len; - if ( len >= remaining ) - remaining = gen_min( remaining, 1 ); - else - remaining -= len; - - while ( len-- ) - { - if ( text_begin + len < end ) - text_begin[ len ] = fill; - } - } - - return ( text - text_begin ); -} - -gen_neverinline gen_ssize gen_c_str_fmt_va( char* text, gen_ssize max_len, char const* fmt, va_list va ) -{ - char const* text_begin = text; - gen_ssize remaining = max_len, res; - - while ( *fmt ) - { - gen__format_info info = { 0 }; - gen_ssize len = 0; - info.precision = -1; - - while ( *fmt && *fmt != '%' && remaining ) - *text++ = *fmt++; - - if ( *fmt == '%' ) - { - do - { - switch ( *++fmt ) - { - case '-' : - { - info.flags |= GEN_FMT_MINUS; - break; - } - case '+' : - { - info.flags |= GEN_FMT_PLUS; - break; - } - case '#' : - { - info.flags |= GEN_FMT_ALT; - break; - } - case ' ' : - { - info.flags |= GEN_FMT_SPACE; - break; - } - case '0' : - { - info.flags |= ( GEN_FMT_ZERO | GEN_FMT_WIDTH ); - break; - } - default : - { - info.flags |= GEN_FMT_DONE; - break; - } - } - } while ( ! ( info.flags & GEN_FMT_DONE ) ); - } - - // NOTE: Optional Width - if ( *fmt == '*' ) - { - int width = va_arg( va, int ); - if ( width < 0 ) - { - info.flags |= GEN_FMT_MINUS; - info.width = -width; - } - else - { - info.width = width; - } - info.flags |= GEN_FMT_WIDTH; - fmt++; - } - else - { - info.width = gen_scast( gen_s32, gen_c_str_to_i64( fmt, gen_ccast( char**, & fmt), 10 )); - if ( info.width != 0 ) - { - info.flags |= GEN_FMT_WIDTH; - } - } - - // NOTE: Optional Precision - if ( *fmt == '.' ) - { - fmt++; - if ( *fmt == '*' ) - { - info.precision = va_arg( va, int ); - fmt++; - } - else - { - info.precision = gen_scast( gen_s32, gen_c_str_to_i64( fmt, gen_ccast( char**, & fmt), 10 )); - } - info.flags &= ~GEN_FMT_ZERO; - } - - switch ( *fmt++ ) - { - case 'h' : - if ( *fmt == 'h' ) - { // hh => char - info.flags |= GEN_FMT_CHAR; - fmt++; - } - else - { // h => short - info.flags |= GEN_FMT_SHORT; - } - break; - - case 'l' : - if ( *fmt == 'l' ) - { // ll => long long - info.flags |= GEN_FMT_LLONG; - fmt++; - } - else - { // l => long - info.flags |= GEN_FMT_LONG; - } - break; - - break; - - case 'z' : // NOTE: zpl_usize - info.flags |= GEN_FMT_UNSIGNED; - // fallthrough - case 't' : // NOTE: zpl_isize - info.flags |= GEN_FMT_SIZE; - break; - - default : - fmt--; - break; - } - - switch ( *fmt ) - { - case 'u' : - info.flags |= GEN_FMT_UNSIGNED; - // fallthrough - case 'd' : - case 'i' : - info.base = 10; - break; - - case 'o' : - info.base = 8; - break; - - case 'x' : - info.base = 16; - info.flags |= ( GEN_FMT_UNSIGNED | GEN_FMT_LOWER ); - break; - - case 'X' : - info.base = 16; - info.flags |= ( GEN_FMT_UNSIGNED | GEN_FMT_UPPER ); - break; - - case 'f' : - case 'F' : - case 'g' : - case 'G' : - len = gen__print_f64( text, remaining, &info, 0, va_arg( va, gen_f64 ) ); - break; - - case 'a' : - case 'A' : - len = gen__print_f64( text, remaining, &info, 1, va_arg( va, gen_f64 ) ); - break; - - case 'c' : - len = gen__print_char( text, remaining, &info, gen_scast( char, va_arg( va, int ) )); - break; - - case 's' : - len = gen__print_string( text, remaining, &info, va_arg( va, char* ) ); - break; - - case 'S': - { - if ( *(fmt + 1) == 'B' ) - { - - ++ fmt; - gen_StrBuilder gen_str = { va_arg( va, char*) }; - - info.precision = gen_strbuilder_length(gen_str); - len = gen__print_string( text, remaining, &info, gen_str ); - break; - } - - gen_Str gen_str = va_arg( va, gen_Str); - info.precision = gen_str.Len; - len = gen__print_string( text, remaining, &info, gen_str.Ptr ); - } - break; - - case 'r' : - len = gen__print_repeated_char( text, remaining, &info, va_arg( va, int ) ); - break; - - case 'p' : - info.base = 16; - info.flags |= ( GEN_FMT_LOWER | GEN_FMT_UNSIGNED | GEN_FMT_ALT | GEN_FMT_INTPTR ); - break; - - case '%' : - len = gen__print_char( text, remaining, &info, '%' ); - break; - - default : - fmt--; - break; - } - - fmt++; - - if ( info.base != 0 ) - { - if ( info.flags & GEN_FMT_UNSIGNED ) - { - gen_u64 value = 0; - switch ( info.flags & GEN_FMT_INTS ) - { - case GEN_FMT_CHAR : - value = gen_scast( gen_u64, gen_scast( gen_u8, va_arg( va, int ))); - break; - case GEN_FMT_SHORT : - value = gen_scast( gen_u64, gen_scast( gen_u16, va_arg( va, int ))); - break; - case GEN_FMT_LONG: - value = gen_scast( gen_u64, va_arg( va, unsigned long )); - break; - case GEN_FMT_LLONG : - value = gen_scast( gen_u64, va_arg( va, unsigned long long )); - break; - case GEN_FMT_SIZE : - value = gen_scast( gen_u64, va_arg( va, gen_usize )); - break; - case GEN_FMT_INTPTR : - value = gen_scast( gen_u64, va_arg( va, gen_uptr )); - break; - default : - value = gen_scast( gen_u64, va_arg( va, unsigned int )); - break; - } - - len = gen__print_u64( text, remaining, &info, value ); - } - else - { - gen_s64 value = 0; - switch ( info.flags & GEN_FMT_INTS ) - { - case GEN_FMT_CHAR : - value = gen_scast( gen_s64, gen_scast( gen_s8, va_arg( va, int ))); - break; - case GEN_FMT_SHORT : - value = gen_scast( gen_s64, gen_scast( gen_s16, va_arg( va, int ))); - break; - case GEN_FMT_LONG : - value = gen_scast( gen_s64, va_arg( va, long )); - break; - case GEN_FMT_LLONG : - value = gen_scast( gen_s64, va_arg( va, long long )); - break; - case GEN_FMT_SIZE : - value = gen_scast( gen_s64, va_arg( va, gen_usize )); - break; - case GEN_FMT_INTPTR : - value = gen_scast( gen_s64, va_arg( va, gen_uptr )); - break; - default : - value = gen_scast( gen_s64, va_arg( va, int )); - break; - } - - len = gen__print_i64( text, remaining, &info, value ); - } - } - - text += len; - if ( len >= remaining ) - remaining = gen_min( remaining, 1 ); - else - remaining -= len; - } - - *text++ = '\0'; - res = ( text - text_begin ); - return ( res >= max_len || res < 0 ) ? -1 : res; -} - -char* gen_c_str_fmt_buf_va( char const* fmt, va_list va ) -{ - gen_local_persist gen_thread_local char buffer[ GEN_PRINTF_MAXLEN ]; - gen_c_str_fmt_va( buffer, gen_size_of( buffer ), fmt, va ); - return buffer; -} - -char* gen_c_str_fmt_buf( char const* fmt, ... ) -{ - va_list va; - char* str; - va_start( va, fmt ); - str = gen_c_str_fmt_buf_va( fmt, va ); - va_end( va ); - return str; -} - -gen_ssize gen_c_str_fmt_file_va( gen_FileInfo* f, char const* fmt, va_list va ) -{ - gen_local_persist gen_thread_local char buf[ GEN_PRINTF_MAXLEN ]; - gen_ssize len = gen_c_str_fmt_va( buf, gen_size_of( buf ), fmt, va ); - gen_b32 res = gen_file_write( f, buf, len - 1 ); // NOTE: prevent extra whitespace - return res ? len : -1; -} - -gen_ssize gen_c_str_fmt_file( gen_FileInfo* f, char const* fmt, ... ) -{ - gen_ssize res; - va_list va; - va_start( va, fmt ); - res = gen_c_str_fmt_file_va( f, fmt, va ); - va_end( va ); - return res; -} - -gen_ssize gen_c_str_fmt( char* str, gen_ssize n, char const* fmt, ... ) -{ - gen_ssize res; - va_list va; - va_start( va, fmt ); - res = gen_c_str_fmt_va( str, n, fmt, va ); - va_end( va ); - return res; -} - -gen_ssize gen_c_str_fmt_out_va( char const* fmt, va_list va ) -{ - return gen_c_str_fmt_file_va( gen_file_get_standard( EFileStandard_OUTPUT ), fmt, va ); -} - -gen_ssize gen_c_str_fmt_out_err_va( char const* fmt, va_list va ) -{ - return gen_c_str_fmt_file_va( gen_file_get_standard( EFileStandard_ERROR ), fmt, va ); -} - -gen_ssize gen_c_str_fmt_out_err( char const* fmt, ... ) -{ - gen_ssize res; - va_list va; - va_start( va, fmt ); - res = gen_c_str_fmt_out_err_va( fmt, va ); - va_end( va ); - return res; -} - -#pragma endregion Printing - -#pragma region Memory - -void* gen_mem_copy( void* dest, void const* source, gen_ssize n ) -{ - if ( dest == gen_nullptr ) - { - return gen_nullptr; - } - - return memcpy( dest, source, n ); -} - -void const* gen_mem_find( void const* data, gen_u8 c, gen_ssize n ) -{ - gen_u8 const* s = gen_rcast( gen_u8 const*, data); - while ( ( gen_rcast( gen_uptr, s) & ( sizeof( gen_usize ) - 1 ) ) && n && *s != c ) - { - s++; - n--; - } - if ( n && *s != c ) - { - gen_ssize const* w; - gen_ssize k = GEN__ONES * c; - w = gen_rcast( gen_ssize const*, s); - while ( n >= gen_size_of( gen_ssize ) && ! GEN__HAS_ZERO( *w ^ k ) ) - { - w++; - n -= gen_size_of( gen_ssize ); - } - s = gen_rcast( gen_u8 const*, w); - while ( n && *s != c ) - { - s++; - n--; - } - } - - return n ? gen_rcast( void const*, s ) : NULL; -} - -#define GEN_HEAP_STATS_MAGIC 0xDEADC0DE - -typedef struct gen__heap_stats gen__heap_stats; -struct gen__heap_stats -{ - gen_u32 magic; - gen_ssize used_memory; - gen_ssize alloc_count; -}; - -gen_global gen__heap_stats _heap_stats_info; - -void gen_heap_stats_init( void ) -{ - gen_zero_item( &_heap_stats_info ); - _heap_stats_info.magic = GEN_HEAP_STATS_MAGIC; -} - -gen_ssize gen_heap_stats_used_memory( void ) -{ - GEN_ASSERT_MSG( _heap_stats_info.magic == GEN_HEAP_STATS_MAGIC, "heap_stats is not initialised yet, call gen_heap_stats_init first!" ); - return _heap_stats_info.used_memory; -} - -gen_ssize gen_heap_stats_alloc_count( void ) -{ - GEN_ASSERT_MSG( _heap_stats_info.magic == GEN_HEAP_STATS_MAGIC, "heap_stats is not initialised yet, call gen_heap_stats_init first!" ); - return _heap_stats_info.alloc_count; -} - -void gen_heap_stats_check( void ) -{ - GEN_ASSERT_MSG( _heap_stats_info.magic == GEN_HEAP_STATS_MAGIC, "heap_stats is not initialised yet, call gen_heap_stats_init first!" ); - GEN_ASSERT( _heap_stats_info.used_memory == 0 ); - GEN_ASSERT( _heap_stats_info.alloc_count == 0 ); -} - -typedef struct gen__heap_alloc_info gen__heap_alloc_info; -struct gen__heap_alloc_info -{ - gen_ssize size; - void* physical_start; -}; - -void* gen_heap_allocator_proc( void* allocator_data, gen_AllocType type, gen_ssize size, gen_ssize alignment, void* old_memory, gen_ssize old_size, gen_u64 flags ) -{ - void* ptr = gen_nullptr; - // unused( allocator_data ); - // unused( old_size ); - if ( ! alignment ) - alignment = GEN_DEFAULT_MEMORY_ALIGNMENT; - -#ifdef GEN_HEAP_ANALYSIS - gen_ssize alloc_info_size = gen_size_of( gen__heap_alloc_info ); - gen_ssize alloc_info_remainder = ( alloc_info_size % alignment ); - gen_ssize track_size = gen_max( alloc_info_size, alignment ) + alloc_info_remainder; - switch ( type ) - { - case EAllocation_FREE : - { - if ( ! old_memory ) - break; - gen__heap_alloc_info* alloc_info = gen_rcast( gen__heap_alloc_info*, old_memory) - 1; - _heap_stats_info.used_memory -= alloc_info->size; - _heap_stats_info.alloc_count--; - old_memory = alloc_info->physical_start; - } - break; - case EAllocation_ALLOC : - { - size += track_size; - } - break; - default : - break; - } -#endif - - switch ( type ) - { -#if defined( GEN_COMPILER_MSVC ) || ( defined( GEN_COMPILER_GCC ) && defined( GEN_SYSTEM_WINDOWS ) ) || ( defined( GEN_COMPILER_TINYC ) && defined( GEN_SYSTEM_WINDOWS ) ) - case EAllocation_ALLOC : - ptr = _aligned_malloc( size, alignment ); - if ( flags & ALLOCATOR_FLAG_CLEAR_TO_ZERO ) - gen_zero_size( ptr, size ); - break; - case EAllocation_FREE : - _aligned_free( old_memory ); - break; - case EAllocation_RESIZE : - { - gen_AllocatorInfo a = gen_heap(); - ptr = gen_default_resize_align( a, old_memory, old_size, size, alignment ); - } - break; - -#elif defined( GEN_SYSTEM_LINUX ) && ! defined( GEN_CPU_ARM ) && ! defined( GEN_COMPILER_TINYC ) - case EAllocation_ALLOC : - { - ptr = aligned_alloc( alignment, ( size + alignment - 1 ) & ~( alignment - 1 ) ); - - if ( flags & GEN_ALLOCATOR_FLAG_CLEAR_TO_ZERO ) - { - gen_zero_size( ptr, size ); - } - } - break; - - case EAllocation_FREE : - { - free( old_memory ); - } - break; - - case EAllocation_RESIZE : - { - gen_AllocatorInfo a = gen_heap(); - ptr = gen_default_resize_align( a, old_memory, old_size, size, alignment ); - } - break; -#else - case EAllocation_ALLOC : - { - posix_memalign( &ptr, alignment, size ); - - if ( flags & GEN_ALLOCATOR_FLAG_CLEAR_TO_ZERO ) - { - gen_zero_size( ptr, size ); - } - } - break; - - case EAllocation_FREE : - { - free( old_memory ); - } - break; - - case EAllocation_RESIZE : - { - gen_AllocatorInfo a = gen_heap(); - ptr = gen_default_resize_align( a, old_memory, old_size, size, alignment ); - } - break; -#endif - - case EAllocation_FREE_ALL : - break; - } - -#ifdef GEN_HEAP_ANALYSIS - if ( type == EAllocation_ALLOC ) - { - gen__heap_alloc_info* alloc_info = gen_rcast( gen__heap_alloc_info*, gen_rcast( char*, ptr) + alloc_info_remainder ); - gen_zero_item( alloc_info ); - alloc_info->size = size - track_size; - alloc_info->physical_start = ptr; - ptr = gen_rcast( void*, alloc_info + 1 ); - _heap_stats_info.used_memory += alloc_info->size; - _heap_stats_info.alloc_count++; - } -#endif - - return ptr; -} - -#pragma region gen_VirtualMemory -gen_VirtualMemory gen_vm_from_memory( void* data, gen_ssize size ) -{ - gen_VirtualMemory vm; - vm.data = data; - vm.size = size; - return vm; -} - -#if defined( GEN_SYSTEM_WINDOWS ) -gen_VirtualMemory gen_vm_alloc( void* addr, gen_ssize size ) -{ - gen_VirtualMemory vm; - GEN_ASSERT( size > 0 ); - vm.data = VirtualAlloc( addr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); - vm.size = size; - return vm; -} - -gen_b32 gen_vm_free( gen_VirtualMemory vm ) -{ - MEMORY_BASIC_INFORMATION info; - while ( vm.size > 0 ) - { - if ( VirtualQuery( vm.data, &info, gen_size_of( info ) ) == 0 ) - return false; - if ( info.BaseAddress != vm.data || info.AllocationBase != vm.data || info.State != MEM_COMMIT || info.RegionSize > gen_scast( gen_usize, vm.size) ) - { - return false; - } - if ( VirtualFree( vm.data, 0, MEM_RELEASE ) == 0 ) - return false; - vm.data = gen_pointer_add( vm.data, info.RegionSize ); - vm.size -= info.RegionSize; - } - return true; -} - -gen_VirtualMemory gen_vm_trim( gen_VirtualMemory vm, gen_ssize lead_size, gen_ssize size ) -{ - gen_VirtualMemory new_vm = { 0 }; - void* ptr; - GEN_ASSERT( vm.size >= lead_size + size ); - - ptr = gen_pointer_add( vm.data, lead_size ); - - gen_vm_free( vm ); - new_vm = gen_vm_alloc( ptr, size ); - if ( new_vm.data == ptr ) - return new_vm; - if ( new_vm.data ) - gen_vm_free( new_vm ); - return new_vm; -} - -gen_b32 gen_vm_purge( gen_VirtualMemory vm ) -{ - VirtualAlloc( vm.data, vm.size, MEM_RESET, PAGE_READWRITE ); - // NOTE: Can this really fail? - return true; -} - -gen_ssize gen_virtual_memory_page_size( gen_ssize* alignment_out ) -{ - SYSTEM_INFO info; - GetSystemInfo( &info ); - if ( alignment_out ) - *alignment_out = info.dwAllocationGranularity; - return info.dwPageSize; -} - -#else -# include - -# ifndef MAP_ANONYMOUS -# define MAP_ANONYMOUS MAP_ANON -# endif -gen_VirtualMemory gen_vm_alloc( void* addr, gen_ssize size ) -{ - gen_VirtualMemory vm; - GEN_ASSERT( size > 0 ); - vm.data = mmap( addr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0 ); - vm.size = size; - return vm; -} - -gen_b32 gen_vm_free( gen_VirtualMemory vm ) -{ - munmap( vm.data, vm.size ); - return true; -} - -gen_VirtualMemory gen_vm_trim( gen_VirtualMemory vm, gen_ssize lead_size, gen_ssize size ) -{ - void* ptr; - gen_ssize trail_size; - GEN_ASSERT( vm.size >= lead_size + size ); - - ptr = gen_pointer_add( vm.data, lead_size ); - trail_size = vm.size - lead_size - size; - - if ( lead_size != 0 ) - gen_vm_free( gen_vm_from_memory(( vm.data, lead_size ) ); - if ( trail_size != 0 ) - gen_vm_free( gen_vm_from_memory( ptr, trail_size ) ); - return gen_vm_from_memory( ptr, size ); -} - -gen_b32 gen_vm_purge( gen_VirtualMemory vm ) -{ - int err = madvise( vm.data, vm.size, MADV_DONTNEED ); - return err != 0; -} - -gen_ssize gen_virtual_memory_page_size( gen_ssize* alignment_out ) -{ - // TODO: Is this always true? - gen_ssize result = gen_scast( gen_ssize, sysconf( _SC_PAGE_SIZE )); - if ( alignment_out ) - *alignment_out = result; - return result; -} -#endif - -#pragma endregion gen_VirtualMemory - -void* gen_arena_allocator_proc( void* allocator_data, gen_AllocType type, gen_ssize size, gen_ssize alignment, void* old_memory, gen_ssize old_size, gen_u64 flags ) -{ - gen_Arena* arena = gen_rcast(gen_Arena*, allocator_data); - void* ptr = NULL; - - // unused( old_size ); - - switch ( type ) - { - case EAllocation_ALLOC : - { - void* end = gen_pointer_add( arena->PhysicalStart, arena->TotalUsed ); - gen_ssize total_size = align_forward_s64( size, alignment ); - - // NOTE: Out of memory - if ( arena->TotalUsed + total_size > (gen_ssize) arena->TotalSize ) - { - // zpl__printf_err("%s", "gen_Arena out of memory\n"); - GEN_FATAL("gen_Arena out of memory! (Possibly could not fit for the largest size gen_Arena!!)"); - } - - - ptr = gen_align_forward( end, alignment ); - arena->TotalUsed += total_size; - - if ( flags & ALLOCATOR_FLAG_CLEAR_TO_ZERO ) - gen_zero_size( ptr, size ); - } - break; - - case EAllocation_FREE : - // NOTE: Free all at once - // Use Temp_Arena_Memory if you want to free a block - break; - - case EAllocation_FREE_ALL : - arena->TotalUsed = 0; - break; - - case EAllocation_RESIZE : - { - // TODO : Check if ptr is on top of stack and just extend - gen_AllocatorInfo a = arena->Backing; - ptr = gen_default_resize_align( a, old_memory, old_size, size, alignment ); - } - break; - } - return ptr; -} - -void* gen_pool_allocator_proc( void* allocator_data, gen_AllocType type, gen_ssize size, gen_ssize alignment, void* old_memory, gen_ssize old_size, gen_u64 flags ) -{ - gen_Pool* pool = gen_rcast( gen_Pool*, allocator_data); - void* ptr = NULL; - - // unused( old_size ); - - switch ( type ) - { - case EAllocation_ALLOC : - { - gen_uptr gen_next_free; - - GEN_ASSERT( size == pool->BlockSize ); - GEN_ASSERT( alignment == pool->BlockAlign ); - GEN_ASSERT( pool->FreeList != NULL ); - - gen_next_free = * gen_rcast( gen_uptr*, pool->FreeList); - ptr = pool->FreeList; - pool->FreeList = gen_rcast( void*, gen_next_free); - pool->TotalSize += pool->BlockSize; - - if ( flags & ALLOCATOR_FLAG_CLEAR_TO_ZERO ) - gen_zero_size( ptr, size ); - } - break; - - case EAllocation_FREE : - { - gen_uptr* next; - if ( old_memory == NULL ) - return NULL; - - next = gen_rcast( gen_uptr*, old_memory); - *next = gen_rcast( gen_uptr, pool->FreeList); - pool->FreeList = old_memory; - pool->TotalSize -= pool->BlockSize; - } - break; - - case EAllocation_FREE_ALL : - { - gen_ssize actual_block_size, block_index; - void* curr; - gen_uptr* end; - - actual_block_size = pool->BlockSize + pool->BlockAlign; - pool->TotalSize = 0; - - // NOTE: Init intrusive freelist - curr = pool->PhysicalStart; - for ( block_index = 0; block_index < pool->NumBlocks - 1; block_index++ ) - { - gen_uptr* next = gen_rcast( gen_uptr*, curr); - * next = gen_rcast( gen_uptr, curr) + actual_block_size; - curr = gen_pointer_add( curr, actual_block_size ); - } - - end = gen_rcast( gen_uptr*, curr); - * end = gen_scast( gen_uptr, NULL); - pool->FreeList = pool->PhysicalStart; - } - break; - - case EAllocation_RESIZE : - // NOTE: Cannot gen_resize - GEN_PANIC( "You cannot gen_resize something allocated by with a pool." ); - break; - } - - return ptr; -} - -gen_Pool gen_pool_init_align( gen_AllocatorInfo backing, gen_ssize num_blocks, gen_ssize block_size, gen_ssize block_align ) -{ - gen_Pool pool = {}; - - gen_ssize actual_block_size, gen_pool_size, block_index; - void *data, *curr; - gen_uptr* end; - - gen_zero_item( &pool ); - - pool.Backing = backing; - pool.BlockSize = block_size; - pool.BlockAlign = block_align; - pool.NumBlocks = num_blocks; - - actual_block_size = block_size + block_align; - gen_pool_size = num_blocks * actual_block_size; - - data = gen_alloc_align( backing, gen_pool_size, block_align ); - - // NOTE: Init intrusive freelist - curr = data; - for ( block_index = 0; block_index < num_blocks - 1; block_index++ ) - { - gen_uptr* next = ( gen_uptr* ) curr; - *next = ( gen_uptr ) curr + actual_block_size; - curr = gen_pointer_add( curr, actual_block_size ); - } - - end = ( gen_uptr* ) curr; - *end = ( gen_uptr ) NULL; - - pool.PhysicalStart = data; - pool.FreeList = data; - - return pool; -} - -void gen_pool_clear(gen_Pool* pool) -{ - gen_ssize actual_block_size, block_index; - void* curr; - gen_uptr* end; - - actual_block_size = pool->BlockSize + pool->BlockAlign; - - curr = pool->PhysicalStart; - for ( block_index = 0; block_index < pool->NumBlocks - 1; block_index++ ) - { - gen_uptr* next = ( gen_uptr* ) curr; - *next = ( gen_uptr ) curr + actual_block_size; - curr = gen_pointer_add( curr, actual_block_size ); - } - - end = ( gen_uptr* ) curr; - *end = ( gen_uptr ) NULL; - - pool->FreeList = pool->PhysicalStart; -} - -#pragma endregion Memory - -#pragma region Hashing - -gen_global gen_u32 const gen__crc32_table[ 256 ] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, - 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, - 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, - 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, - 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, - 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, - 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, - 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, -}; - -gen_u32 gen_crc32( void const* data, gen_ssize len ) -{ - gen_ssize remaining; - gen_u32 result = ~( gen_scast( gen_u32, 0) ); - gen_u8 const* c = gen_rcast( gen_u8 const*, data); - for ( remaining = len; remaining--; c++ ) - result = ( result >> 8 ) ^ ( gen__crc32_table[ ( result ^ *c ) & 0xff ] ); - return ~result; -} - -gen_global gen_u64 const gen__crc64_table[ 256 ] = { - 0x0000000000000000ull, 0x7ad870c830358979ull, 0xf5b0e190606b12f2ull, 0x8f689158505e9b8bull, 0xc038e5739841b68full, 0xbae095bba8743ff6ull, 0x358804e3f82aa47dull, - 0x4f50742bc81f2d04ull, 0xab28ecb46814fe75ull, 0xd1f09c7c5821770cull, 0x5e980d24087fec87ull, 0x24407dec384a65feull, 0x6b1009c7f05548faull, 0x11c8790fc060c183ull, - 0x9ea0e857903e5a08ull, 0xe478989fa00bd371ull, 0x7d08ff3b88be6f81ull, 0x07d08ff3b88be6f8ull, 0x88b81eabe8d57d73ull, 0xf2606e63d8e0f40aull, 0xbd301a4810ffd90eull, - 0xc7e86a8020ca5077ull, 0x4880fbd87094cbfcull, 0x32588b1040a14285ull, 0xd620138fe0aa91f4ull, 0xacf86347d09f188dull, 0x2390f21f80c18306ull, 0x594882d7b0f40a7full, - 0x1618f6fc78eb277bull, 0x6cc0863448deae02ull, 0xe3a8176c18803589ull, 0x997067a428b5bcf0ull, 0xfa11fe77117cdf02ull, 0x80c98ebf2149567bull, 0x0fa11fe77117cdf0ull, - 0x75796f2f41224489ull, 0x3a291b04893d698dull, 0x40f16bccb908e0f4ull, 0xcf99fa94e9567b7full, 0xb5418a5cd963f206ull, 0x513912c379682177ull, 0x2be1620b495da80eull, - 0xa489f35319033385ull, 0xde51839b2936bafcull, 0x9101f7b0e12997f8ull, 0xebd98778d11c1e81ull, 0x64b116208142850aull, 0x1e6966e8b1770c73ull, 0x8719014c99c2b083ull, - 0xfdc17184a9f739faull, 0x72a9e0dcf9a9a271ull, 0x08719014c99c2b08ull, 0x4721e43f0183060cull, 0x3df994f731b68f75ull, 0xb29105af61e814feull, 0xc849756751dd9d87ull, - 0x2c31edf8f1d64ef6ull, 0x56e99d30c1e3c78full, 0xd9810c6891bd5c04ull, 0xa3597ca0a188d57dull, 0xec09088b6997f879ull, 0x96d1784359a27100ull, 0x19b9e91b09fcea8bull, - 0x636199d339c963f2ull, 0xdf7adabd7a6e2d6full, 0xa5a2aa754a5ba416ull, 0x2aca3b2d1a053f9dull, 0x50124be52a30b6e4ull, 0x1f423fcee22f9be0ull, 0x659a4f06d21a1299ull, - 0xeaf2de5e82448912ull, 0x902aae96b271006bull, 0x74523609127ad31aull, 0x0e8a46c1224f5a63ull, 0x81e2d7997211c1e8ull, 0xfb3aa75142244891ull, 0xb46ad37a8a3b6595ull, - 0xceb2a3b2ba0eececull, 0x41da32eaea507767ull, 0x3b024222da65fe1eull, 0xa2722586f2d042eeull, 0xd8aa554ec2e5cb97ull, 0x57c2c41692bb501cull, 0x2d1ab4dea28ed965ull, - 0x624ac0f56a91f461ull, 0x1892b03d5aa47d18ull, 0x97fa21650afae693ull, 0xed2251ad3acf6feaull, 0x095ac9329ac4bc9bull, 0x7382b9faaaf135e2ull, 0xfcea28a2faafae69ull, - 0x8632586aca9a2710ull, 0xc9622c4102850a14ull, 0xb3ba5c8932b0836dull, 0x3cd2cdd162ee18e6ull, 0x460abd1952db919full, 0x256b24ca6b12f26dull, 0x5fb354025b277b14ull, - 0xd0dbc55a0b79e09full, 0xaa03b5923b4c69e6ull, 0xe553c1b9f35344e2ull, 0x9f8bb171c366cd9bull, 0x10e3202993385610ull, 0x6a3b50e1a30ddf69ull, 0x8e43c87e03060c18ull, - 0xf49bb8b633338561ull, 0x7bf329ee636d1eeaull, 0x012b592653589793ull, 0x4e7b2d0d9b47ba97ull, 0x34a35dc5ab7233eeull, 0xbbcbcc9dfb2ca865ull, 0xc113bc55cb19211cull, - 0x5863dbf1e3ac9decull, 0x22bbab39d3991495ull, 0xadd33a6183c78f1eull, 0xd70b4aa9b3f20667ull, 0x985b3e827bed2b63ull, 0xe2834e4a4bd8a21aull, 0x6debdf121b863991ull, - 0x1733afda2bb3b0e8ull, 0xf34b37458bb86399ull, 0x8993478dbb8deae0ull, 0x06fbd6d5ebd3716bull, 0x7c23a61ddbe6f812ull, 0x3373d23613f9d516ull, 0x49aba2fe23cc5c6full, - 0xc6c333a67392c7e4ull, 0xbc1b436e43a74e9dull, 0x95ac9329ac4bc9b5ull, 0xef74e3e19c7e40ccull, 0x601c72b9cc20db47ull, 0x1ac40271fc15523eull, 0x5594765a340a7f3aull, - 0x2f4c0692043ff643ull, 0xa02497ca54616dc8ull, 0xdafce7026454e4b1ull, 0x3e847f9dc45f37c0ull, 0x445c0f55f46abeb9ull, 0xcb349e0da4342532ull, 0xb1eceec59401ac4bull, - 0xfebc9aee5c1e814full, 0x8464ea266c2b0836ull, 0x0b0c7b7e3c7593bdull, 0x71d40bb60c401ac4ull, 0xe8a46c1224f5a634ull, 0x927c1cda14c02f4dull, 0x1d148d82449eb4c6ull, - 0x67ccfd4a74ab3dbfull, 0x289c8961bcb410bbull, 0x5244f9a98c8199c2ull, 0xdd2c68f1dcdf0249ull, 0xa7f41839ecea8b30ull, 0x438c80a64ce15841ull, 0x3954f06e7cd4d138ull, - 0xb63c61362c8a4ab3ull, 0xcce411fe1cbfc3caull, 0x83b465d5d4a0eeceull, 0xf96c151de49567b7ull, 0x76048445b4cbfc3cull, 0x0cdcf48d84fe7545ull, 0x6fbd6d5ebd3716b7ull, - 0x15651d968d029fceull, 0x9a0d8ccedd5c0445ull, 0xe0d5fc06ed698d3cull, 0xaf85882d2576a038ull, 0xd55df8e515432941ull, 0x5a3569bd451db2caull, 0x20ed197575283bb3ull, - 0xc49581ead523e8c2ull, 0xbe4df122e51661bbull, 0x3125607ab548fa30ull, 0x4bfd10b2857d7349ull, 0x04ad64994d625e4dull, 0x7e7514517d57d734ull, 0xf11d85092d094cbfull, - 0x8bc5f5c11d3cc5c6ull, 0x12b5926535897936ull, 0x686de2ad05bcf04full, 0xe70573f555e26bc4ull, 0x9ddd033d65d7e2bdull, 0xd28d7716adc8cfb9ull, 0xa85507de9dfd46c0ull, - 0x273d9686cda3dd4bull, 0x5de5e64efd965432ull, 0xb99d7ed15d9d8743ull, 0xc3450e196da80e3aull, 0x4c2d9f413df695b1ull, 0x36f5ef890dc31cc8ull, 0x79a59ba2c5dc31ccull, - 0x037deb6af5e9b8b5ull, 0x8c157a32a5b7233eull, 0xf6cd0afa9582aa47ull, 0x4ad64994d625e4daull, 0x300e395ce6106da3ull, 0xbf66a804b64ef628ull, 0xc5bed8cc867b7f51ull, - 0x8aeeace74e645255ull, 0xf036dc2f7e51db2cull, 0x7f5e4d772e0f40a7ull, 0x05863dbf1e3ac9deull, 0xe1fea520be311aafull, 0x9b26d5e88e0493d6ull, 0x144e44b0de5a085dull, - 0x6e963478ee6f8124ull, 0x21c640532670ac20ull, 0x5b1e309b16452559ull, 0xd476a1c3461bbed2ull, 0xaeaed10b762e37abull, 0x37deb6af5e9b8b5bull, 0x4d06c6676eae0222ull, - 0xc26e573f3ef099a9ull, 0xb8b627f70ec510d0ull, 0xf7e653dcc6da3dd4ull, 0x8d3e2314f6efb4adull, 0x0256b24ca6b12f26ull, 0x788ec2849684a65full, 0x9cf65a1b368f752eull, - 0xe62e2ad306bafc57ull, 0x6946bb8b56e467dcull, 0x139ecb4366d1eea5ull, 0x5ccebf68aecec3a1ull, 0x2616cfa09efb4ad8ull, 0xa97e5ef8cea5d153ull, 0xd3a62e30fe90582aull, - 0xb0c7b7e3c7593bd8ull, 0xca1fc72bf76cb2a1ull, 0x45775673a732292aull, 0x3faf26bb9707a053ull, 0x70ff52905f188d57ull, 0x0a2722586f2d042eull, 0x854fb3003f739fa5ull, - 0xff97c3c80f4616dcull, 0x1bef5b57af4dc5adull, 0x61372b9f9f784cd4ull, 0xee5fbac7cf26d75full, 0x9487ca0fff135e26ull, 0xdbd7be24370c7322ull, 0xa10fceec0739fa5bull, - 0x2e675fb4576761d0ull, 0x54bf2f7c6752e8a9ull, 0xcdcf48d84fe75459ull, 0xb71738107fd2dd20ull, 0x387fa9482f8c46abull, 0x42a7d9801fb9cfd2ull, 0x0df7adabd7a6e2d6ull, - 0x772fdd63e7936bafull, 0xf8474c3bb7cdf024ull, 0x829f3cf387f8795dull, 0x66e7a46c27f3aa2cull, 0x1c3fd4a417c62355ull, 0x935745fc4798b8deull, 0xe98f353477ad31a7ull, - 0xa6df411fbfb21ca3ull, 0xdc0731d78f8795daull, 0x536fa08fdfd90e51ull, 0x29b7d047efec8728ull, -}; - -gen_u64 gen_crc64( void const* data, gen_ssize len ) -{ - gen_ssize remaining; - gen_u64 result = ( gen_scast( gen_u64, 0) ); - gen_u8 const* c = gen_rcast( gen_u8 const*, data); - for ( remaining = len; remaining--; c++ ) - result = ( result >> 8 ) ^ ( gen__crc64_table[ ( result ^ *c ) & 0xff ] ); - return result; -} - -#pragma endregion Hashing - -#pragma region gen_StrBuilder - -gen_StrBuilder gen_strbuilder_make_length( gen_AllocatorInfo allocator, char const* str, gen_ssize length ) -{ - gen_ssize const header_size = sizeof( gen_StrBuilderHeader ); - - gen_s32 alloc_size = header_size + length + 1; - void* allocation = gen_alloc( allocator, alloc_size ); - - if ( allocation == gen_nullptr ) { - gen_StrBuilder null_string = {gen_nullptr}; - return null_string; - } - - gen_StrBuilderHeader* - header = gen_rcast(gen_StrBuilderHeader*, allocation); - header->Allocator = allocator; - header->Capacity = length; - header->Length = length; - - gen_StrBuilder result = { gen_rcast( char*, allocation) + header_size }; - - if ( length && str ) - gen_mem_copy( result, str, length ); - else - gen_mem_set( result, 0, alloc_size - header_size ); - - result[ length ] = '\0'; - - return result; -} - -gen_StrBuilder gen_strbuilder_make_reserve( gen_AllocatorInfo allocator, gen_ssize capacity ) -{ - gen_ssize const header_size = sizeof( gen_StrBuilderHeader ); - - gen_s32 alloc_size = header_size + capacity + 1; - void* allocation = gen_alloc( allocator, alloc_size ); - - if ( allocation == gen_nullptr ) { - gen_StrBuilder null_string = {gen_nullptr}; - return null_string; - } - gen_mem_set( allocation, 0, alloc_size ); - - gen_StrBuilderHeader* - header = gen_rcast(gen_StrBuilderHeader*, allocation); - header->Allocator = allocator; - header->Capacity = capacity; - header->Length = 0; - - gen_StrBuilder result = { gen_rcast(char*, allocation) + header_size }; - 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, gen_txt("·")); - break; - case '\t': - gen_strbuilder_append_str(& result, gen_txt("→")); - break; - case '\n': - gen_strbuilder_append_str(& result, gen_txt("↵")); - break; - case '\r': - gen_strbuilder_append_str(& result, gen_txt("⏎")); - break; - case '\v': - gen_strbuilder_append_str(& result, gen_txt("⇕")); - break; - case '\f': - gen_strbuilder_append_str(& result, gen_txt("⌂")); - break; - default: - gen_strbuilder_append_char(& result, * c); - break; - } - - return result; -} - -#pragma endregion gen_StrBuilder - -#pragma region File Handling - -#if defined( GEN_SYSTEM_WINDOWS ) || defined( GEN_SYSTEM_CYGWIN ) - -gen_internal -wchar_t* gen__alloc_utf8_to_ucs2( gen_AllocatorInfo a, char const* text, gen_ssize* w_len_ ) -{ - wchar_t* w_text = NULL; - gen_ssize len = 0, w_len = 0, w_len1 = 0; - if ( text == NULL ) - { - if ( w_len_ ) - *w_len_ = w_len; - return NULL; - } - len = gen_c_str_len( text ); - if ( len == 0 ) - { - if ( w_len_ ) - *w_len_ = w_len; - return NULL; - } - w_len = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, text, gen_scast( int, len), NULL, 0 ); - if ( w_len == 0 ) - { - if ( w_len_ ) - *w_len_ = w_len; - return NULL; - } - w_text = gen_alloc_array( a, wchar_t, w_len + 1 ); - w_len1 = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, text, gen_scast( int, len), w_text, gen_scast( int, w_len) ); - if ( w_len1 == 0 ) - { - gen_allocator_free( a, w_text ); - if ( w_len_ ) - *w_len_ = 0; - return NULL; - } - w_text[ w_len ] = 0; - if ( w_len_ ) - *w_len_ = w_len; - return w_text; -} - -gen_internal -GEN_FILE_SEEK_PROC( gen__win32_file_seek ) -{ - LARGE_INTEGER li_offset; - li_offset.QuadPart = offset; - if ( ! SetFilePointerEx( fd.p, li_offset, &li_offset, whence ) ) - { - return false; - } - - if ( new_offset ) - *new_offset = li_offset.QuadPart; - return true; -} - -gen_internal -GEN_FILE_READ_AT_PROC( gen__win32_file_read ) -{ - // unused( stop_at_newline ); - gen_b32 result = false; - gen__win32_file_seek( fd, offset, ESeekWhence_BEGIN, NULL ); - DWORD size_ = gen_scast( DWORD, ( size > GEN_I32_MAX ? GEN_I32_MAX : size )); - DWORD bytes_read_; - if ( ReadFile( fd.p, buffer, size_, &bytes_read_, NULL ) ) - { - if ( bytes_read ) - *bytes_read = bytes_read_; - result = true; - } - - return result; -} - -gen_internal -GEN_FILE_WRITE_AT_PROC( gen__win32_file_write ) -{ - DWORD size_ = gen_scast( DWORD, ( size > GEN_I32_MAX ? GEN_I32_MAX : size )); - DWORD bytes_written_; - gen__win32_file_seek( fd, offset, ESeekWhence_BEGIN, NULL ); - if ( WriteFile( fd.p, buffer, size_, &bytes_written_, NULL ) ) - { - if ( bytes_written ) - *bytes_written = bytes_written_; - return true; - } - return false; -} - -gen_internal -GEN_FILE_CLOSE_PROC( gen__win32_file_close ) -{ - CloseHandle( fd.p ); -} - -gen_FileOperations const default_file_operations = { gen__win32_file_read, gen__win32_file_write, gen__win32_file_seek, gen__win32_file_close }; - -gen_neverinline -GEN_FILE_OPEN_PROC( gen__win32_file_open ) -{ - DWORD desired_access; - DWORD creation_disposition; - void* handle; - wchar_t* w_text; - - switch ( mode & GEN_FILE_MODES ) - { - case EFileMode_READ : - desired_access = GENERIC_READ; - creation_disposition = OPEN_EXISTING; - break; - case EFileMode_WRITE : - desired_access = GENERIC_WRITE; - creation_disposition = CREATE_ALWAYS; - break; - case EFileMode_APPEND : - desired_access = GENERIC_WRITE; - creation_disposition = OPEN_ALWAYS; - break; - case EFileMode_READ | EFileMode_RW : - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = OPEN_EXISTING; - break; - case EFileMode_WRITE | EFileMode_RW : - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = CREATE_ALWAYS; - break; - case EFileMode_APPEND | EFileMode_RW : - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = OPEN_ALWAYS; - break; - default : - GEN_PANIC( "Invalid file mode" ); - return EFileError_INVALID; - } - - w_text = gen__alloc_utf8_to_ucs2( gen_heap(), filename, NULL ); - handle = CreateFileW( w_text, desired_access, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL ); - - gen_allocator_free( gen_heap(), w_text ); - - if ( handle == INVALID_HANDLE_VALUE ) - { - DWORD err = GetLastError(); - switch ( err ) - { - case ERROR_FILE_NOT_FOUND : - return EFileError_NOT_EXISTS; - case ERROR_FILE_EXISTS : - return EFileError_EXISTS; - case ERROR_ALREADY_EXISTS : - return EFileError_EXISTS; - case ERROR_ACCESS_DENIED : - return EFileError_PERMISSION; - } - return EFileError_INVALID; - } - - if ( mode & EFileMode_APPEND ) - { - LARGE_INTEGER offset = { { 0 } }; - if ( ! SetFilePointerEx( handle, offset, NULL, ESeekWhence_END ) ) - { - CloseHandle( handle ); - return EFileError_INVALID; - } - } - - fd->p = handle; - *ops = default_file_operations; - return EFileError_NONE; -} - -#else // POSIX -# include - -gen_internal -GEN_FILE_SEEK_PROC( gen__posix_file_seek ) -{ -# if defined( GEN_SYSTEM_OSX ) - gen_s64 res = lseek( fd.i, offset, whence ); -# else // TODO(ZaKlaus): @fixme lseek64 - gen_s64 res = lseek( fd.i, offset, whence ); -# endif - if ( res < 0 ) - return false; - if ( new_offset ) - *new_offset = res; - return true; -} - -gen_internal -GEN_FILE_READ_AT_PROC( gen__posix_file_read ) -{ - unused( stop_at_newline ); - gen_ssize res = pread( fd.i, buffer, size, offset ); - if ( res < 0 ) - return false; - if ( bytes_read ) - *bytes_read = res; - return true; -} - -gen_internal -GEN_FILE_WRITE_AT_PROC( gen__posix_file_write ) -{ - gen_ssize res; - gen_s64 curr_offset = 0; - gen__posix_file_seek( fd, 0, ESeekWhence_CURRENT, &curr_offset ); - if ( curr_offset == offset ) - { - // NOTE: Writing to stdout et al. doesn't like pwrite for numerous reasons - res = write( gen_scast( int, fd.i), buffer, size ); - } - else - { - res = pwrite( gen_scast( int, fd.i), buffer, size, offset ); - } - if ( res < 0 ) - return false; - if ( bytes_written ) - *bytes_written = res; - return true; -} - -gen_internal -GEN_FILE_CLOSE_PROC( gen__posix_file_close ) -{ - close( fd.i ); -} - -gen_FileOperations const default_file_operations = { gen__posix_file_read, gen__posix_file_write, gen__posix_file_seek, gen__posix_file_close }; - -gen_neverinline -GEN_FILE_OPEN_PROC( gen__posix_file_open ) -{ - gen_s32 os_mode; - switch ( mode & GEN_FILE_MODES ) - { - case EFileMode_READ : - os_mode = O_RDONLY; - break; - case EFileMode_WRITE : - os_mode = O_WRONLY | O_CREAT | O_TRUNC; - break; - case EFileMode_APPEND : - os_mode = O_WRONLY | O_APPEND | O_CREAT; - break; - case EFileMode_READ | EFileMode_RW : - os_mode = O_RDWR; - break; - case EFileMode_WRITE | EFileMode_RW : - os_mode = O_RDWR | O_CREAT | O_TRUNC; - break; - case EFileMode_APPEND | EFileMode_RW : - os_mode = O_RDWR | O_APPEND | O_CREAT; - break; - default : - GEN_PANIC( "Invalid file mode" ); - return EFileError_INVALID; - } - - fd->i = open( filename, os_mode, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ); - if ( fd->i < 0 ) - { - // TODO : More file errors - return EFileError_INVALID; - } - - *ops = default_file_operations; - return EFileError_NONE; -} - -// POSIX -#endif - -gen_internal void gen__dirinfo_free_entry( gen_DirEntry* entry ); - -// TODO(zpl) : Is this a bad idea? -gen_global gen_b32 gen__std_file_set = false; -gen_global gen_FileInfo _std_files[ EFileStandard_COUNT ] = { -{ - { gen_nullptr, gen_nullptr, gen_nullptr, gen_nullptr }, - { gen_nullptr }, - 0, - gen_nullptr, - 0, - gen_nullptr -} }; - -#if defined( GEN_SYSTEM_WINDOWS ) || defined( GEN_SYSTEM_CYGWIN ) - -gen_FileInfo* gen_file_get_standard( gen_FileStandardType std ) -{ - if ( ! gen__std_file_set ) - { -# define GEN__SET_STD_FILE( type, v ) \ - _std_files[ type ].fd.p = v; \ - _std_files[ type ].ops = default_file_operations - GEN__SET_STD_FILE( EFileStandard_INPUT, GetStdHandle( STD_INPUT_HANDLE ) ); - GEN__SET_STD_FILE( EFileStandard_OUTPUT, GetStdHandle( STD_OUTPUT_HANDLE ) ); - GEN__SET_STD_FILE( EFileStandard_ERROR, GetStdHandle( STD_ERROR_HANDLE ) ); -# undef GEN__SET_STD_FILE - gen__std_file_set = true; - } - return &_std_files[ std ]; -} - -#else // POSIX - -gen_FileInfo* gen_file_get_standard( gen_FileStandardType std ) -{ - if ( ! gen__std_file_set ) - { -# define GEN__SET_STD_FILE( type, v ) \ - _std_files[ type ].fd.i = v; \ - _std_files[ type ].ops = default_file_operations - GEN__SET_STD_FILE( EFileStandard_INPUT, 0 ); - GEN__SET_STD_FILE( EFileStandard_OUTPUT, 1 ); - GEN__SET_STD_FILE( EFileStandard_ERROR, 2 ); -# undef GEN__SET_STD_FILE - gen__std_file_set = true; - } - return &_std_files[ std ]; -} - -#endif - -gen_FileError gen_file_close( gen_FileInfo* f ) -{ - if ( ! f ) - return EFileError_INVALID; - - if ( f->filename ) - gen_allocator_free( gen_heap(), gen_ccast( char*, f->filename )); - -#if defined( GEN_SYSTEM_WINDOWS ) - if ( f->fd.p == INVALID_HANDLE_VALUE ) - return EFileError_INVALID; -#else - if ( f->fd.i < 0 ) - return EFileError_INVALID; -#endif - - if ( f->is_temp ) - { - f->ops.close( f->fd ); - return EFileError_NONE; - } - - if ( ! f->ops.read_at ) - f->ops = default_file_operations; - f->ops.close( f->fd ); - -#if 0 - if ( f->Dir ) - { - gen__dirinfo_free_entry( f->Dir ); - gen_mfree( f->Dir ); - f->Dir = NULL; - } -#endif - - return EFileError_NONE; -} - -gen_FileError gen_file_new( gen_FileInfo* f, gen_FileDescriptor fd, gen_FileOperations ops, char const* filename ) -{ - gen_FileError err = EFileError_NONE; - gen_ssize len = gen_c_str_len( filename ); - - f->ops = ops; - f->fd = fd; - f->dir = gen_nullptr; - f->last_write_time = 0; - f->filename = gen_alloc_array( gen_heap(), char, len + 1 ); - gen_mem_copy( gen_ccast( char*, f->filename), gen_ccast( char*, filename), len + 1 ); - - return err; -} - -gen_FileError gen_file_open( gen_FileInfo* f, char const* filename ) -{ - return gen_file_open_mode( f, EFileMode_READ, filename ); -} - -gen_FileError gen_file_open_mode( gen_FileInfo* f, gen_FileMode mode, char const* filename ) -{ - gen_FileInfo gen_file_ = - { - { gen_nullptr, gen_nullptr, gen_nullptr, gen_nullptr }, - { gen_nullptr }, - 0, - gen_nullptr, - 0, - gen_nullptr - }; - - *f = gen_file_; - gen_FileError err; - -#if defined( GEN_SYSTEM_WINDOWS ) || defined( GEN_SYSTEM_CYGWIN ) - err = gen__win32_file_open( &f->fd, &f->ops, mode, filename ); -#else - err = gen__posix_file_open( &f->fd, &f->ops, mode, filename ); -#endif - - if ( err == EFileError_NONE ) - return gen_file_new( f, f->fd, f->ops, filename ); - - return err; -} - -gen_s64 gen_file_size( gen_FileInfo* f ) -{ - gen_s64 size = 0; - gen_s64 prev_offset = gen_file_tell( f ); - - gen_file_seek_to_end( f ); - size = gen_file_tell( f ); - - gen_file_seek( f, prev_offset ); - - return size; -} - -FileContents gen_file_read_contents( gen_AllocatorInfo a, gen_b32 zero_terminate, char const* filepath ) -{ - FileContents result; - gen_FileInfo file ; - - result.allocator = a; - - if ( gen_file_open( &file, filepath ) == EFileError_NONE ) - { - gen_ssize fsize = gen_scast( gen_ssize , gen_file_size( &file )); - if ( fsize > 0 ) - { - result.data = gen_alloc( a, zero_terminate ? fsize + 1 : fsize ); - result.size = fsize; - gen_file_read_at( &file, result.data, result.size, 0 ); - if ( zero_terminate ) - { - gen_u8* str = gen_rcast( gen_u8*, result.data); - str[ fsize ] = '\0'; - } - } - gen_file_close( &file ); - } - - return result; -} - -typedef struct gen__memory_fd gen__memory_fd; -struct gen__memory_fd -{ - gen_u8 magic; - gen_u8* buf; //< zpl_array OR plain buffer if we can't write - gen_ssize cursor; - gen_AllocatorInfo allocator; - - FileStreamFlags flags; - gen_ssize cap; -}; - -#define GEN__FILE_STREAM_FD_MAGIC 37 - -gen_FileDescriptor gen__file_stream_fd_make( gen__memory_fd* d ); -gen__memory_fd* gen__file_stream_from_fd( gen_FileDescriptor fd ); - -inline -gen_FileDescriptor gen__file_stream_fd_make( gen__memory_fd* d ) -{ - gen_FileDescriptor fd = { 0 }; - fd.p = ( void* )d; - return fd; -} - -inline -gen__memory_fd* gen__file_stream_from_fd( gen_FileDescriptor fd ) -{ - gen__memory_fd* d = ( gen__memory_fd* )fd.p; - GEN_ASSERT( d->magic == GEN__FILE_STREAM_FD_MAGIC ); - return d; -} - -gen_b8 gen_file_stream_new( gen_FileInfo* file, gen_AllocatorInfo allocator ) -{ - GEN_ASSERT_NOT_NULL( file ); - - gen__memory_fd* d = ( gen__memory_fd* )gen_alloc( allocator, gen_size_of( gen__memory_fd ) ); - - if ( ! d ) - return false; - - gen_zero_item( file ); - d->magic = GEN__FILE_STREAM_FD_MAGIC; - d->allocator = allocator; - d->flags = EFileStream_CLONE_WRITABLE; - d->cap = 0; - d->buf = gen_array_init( gen_u8, allocator ); - - if ( ! d->buf ) - return false; - - file->ops = memory_file_operations; - file->fd = gen__file_stream_fd_make( d ); - file->dir = NULL; - file->last_write_time = 0; - file->filename = NULL; - file->is_temp = true; - return true; -} - -gen_b8 gen_file_stream_open( gen_FileInfo* file, gen_AllocatorInfo allocator, gen_u8* buffer, gen_ssize size, FileStreamFlags flags ) -{ - GEN_ASSERT_NOT_NULL( file ); - gen__memory_fd* d = ( gen__memory_fd* )gen_alloc( allocator, gen_size_of( gen__memory_fd ) ); - if ( ! d ) - return false; - gen_zero_item( file ); - d->magic = GEN__FILE_STREAM_FD_MAGIC; - d->allocator = allocator; - d->flags = flags; - if ( d->flags & EFileStream_CLONE_WRITABLE ) - { - gen_Array(gen_u8) arr = gen_array_init_reserve(gen_u8, allocator, size ); - d->buf = arr; - - if ( ! d->buf ) - return false; - - gen_mem_copy( d->buf, buffer, size ); - d->cap = size; - - gen_array_get_header(arr)->Num = size; - } - else - { - d->buf = buffer; - d->cap = size; - } - file->ops = memory_file_operations; - file->fd = gen__file_stream_fd_make( d ); - file->dir = NULL; - file->last_write_time = 0; - file->filename = NULL; - file->is_temp = true; - return true; -} - -gen_u8* gen_file_stream_buf( gen_FileInfo* file, gen_ssize* size ) -{ - GEN_ASSERT_NOT_NULL( file ); - gen__memory_fd* d = gen__file_stream_from_fd( file->fd ); - if ( size ) - *size = d->cap; - return d->buf; -} - -gen_internal -GEN_FILE_SEEK_PROC( gen__memory_file_seek ) -{ - gen__memory_fd* d = gen__file_stream_from_fd( fd ); - gen_ssize buflen = d->cap; - - if ( whence == ESeekWhence_BEGIN ) - d->cursor = 0; - else if ( whence == ESeekWhence_END ) - d->cursor = buflen; - - d->cursor = gen_max( 0, gen_clamp( d->cursor + offset, 0, buflen ) ); - if ( new_offset ) - *new_offset = d->cursor; - return true; -} - -gen_internal -GEN_FILE_READ_AT_PROC( gen__memory_file_read ) -{ - // unused( stop_at_newline ); - gen__memory_fd* d = gen__file_stream_from_fd( fd ); - gen_mem_copy( buffer, d->buf + offset, size ); - if ( bytes_read ) - *bytes_read = size; - return true; -} - -gen_internal -GEN_FILE_WRITE_AT_PROC( gen__memory_file_write ) -{ - gen__memory_fd* d = gen__file_stream_from_fd( fd ); - - if ( ! ( d->flags & ( EFileStream_CLONE_WRITABLE | EFileStream_WRITABLE ) ) ) - return false; - - gen_ssize buflen = d->cap; - gen_ssize extralen = gen_max( 0, size - ( buflen - offset ) ); - gen_ssize rwlen = size - extralen; - gen_ssize new_cap = buflen + extralen; - - if ( d->flags & EFileStream_CLONE_WRITABLE ) - { - gen_Array(gen_u8) arr = { d->buf }; - - if ( gen_array_get_header(arr)->Capacity < gen_scast(gen_usize, new_cap) ) - { - if ( ! gen_array_grow( & arr, ( gen_s64 )( new_cap ) ) ) - return false; - d->buf = arr; - } - } - - gen_mem_copy( d->buf + offset, buffer, rwlen ); - - if ( ( d->flags & EFileStream_CLONE_WRITABLE ) && extralen > 0 ) - { - gen_Array(gen_u8) arr = { d->buf }; - - gen_mem_copy( d->buf + offset + rwlen, gen_pointer_add_const( buffer, rwlen ), extralen ); - d->cap = new_cap; - gen_array_get_header(arr)->Capacity = new_cap; - } - else - { - extralen = 0; - } - - if ( bytes_written ) - *bytes_written = ( rwlen + extralen ); - return true; -} - -gen_internal -GEN_FILE_CLOSE_PROC( gen__memory_file_close ) -{ - gen__memory_fd* d = gen__file_stream_from_fd( fd ); - gen_AllocatorInfo allocator = d->allocator; - - if ( d->flags & EFileStream_CLONE_WRITABLE ) - { - gen_Array(gen_u8) arr = { d->buf }; - gen_array_free(arr); - } - - gen_allocator_free( allocator, d ); -} - -gen_FileOperations const memory_file_operations = { gen__memory_file_read, gen__memory_file_write, gen__memory_file_seek, gen__memory_file_close }; - -#pragma endregion File Handling - -#pragma region Timing - -#ifdef GEN_BENCHMARK - #if defined( GEN_COMPILER_MSVC ) && ! defined( __clang__ ) - gen_u64 gen_read_cpu_time_stamp_counter( void ) - { - return __rdtsc(); - } - #elif defined( __i386__ ) - gen_u64 gen_read_cpu_time_stamp_counter( void ) - { - gen_u64 x; - __asm__ volatile( ".byte 0x0f, 0x31" : "=A"( x ) ); - return x; - } - #elif defined( __x86_64__ ) - gen_u64 gen_read_cpu_time_stamp_counter( void ) - { - gen_u32 hi, lo; - __asm__ __volatile__( "rdtsc" : "=a"( lo ), "=d"( hi ) ); - return gen_scast( gen_u64, lo ) | ( gen_scast( gen_u64, hi ) << 32 ); - } - #elif defined( __powerpc__ ) - gen_u64 gen_read_cpu_time_stamp_counter( void ) - { - gen_u64 result = 0; - gen_u32 upper, lower, tmp; - __asm__ volatile( - "0: \n" - "\tmftbu %0 \n" - "\tmftb %1 \n" - "\tmftbu %2 \n" - "\tcmpw %2,%0 \n" - "\tbne 0b \n" - : "=r"( upper ), "=r"( lower ), "=r"( tmp ) - ); - result = upper; - result = result << 32; - result = result | lower; - - return result; - } - #elif defined( GEN_SYSTEM_EMSCRIPTEN ) - gen_u64 gen_read_cpu_time_stamp_counter( void ) - { - return ( gen_u64 )( emscripten_get_now() * 1e+6 ); - } - #elif defined( GEN_CPU_ARM ) && ! defined( GEN_COMPILER_TINYC ) - gen_u64 gen_read_cpu_time_stamp_counter( void ) - { - # if defined( __aarch64__ ) - int64_t r = 0; - asm volatile( "mrs %0, cntvct_el0" : "=r"( r ) ); - # elif ( __ARM_ARCH >= 6 ) - uint32_t r = 0; - uint32_t pmccntr; - uint32_t pmuseren; - uint32_t pmcntenset; - - // Read the user mode perf monitor counter access permissions. - asm volatile( "mrc p15, 0, %0, c9, c14, 0" : "=r"( pmuseren ) ); - if ( pmuseren & 1 ) - { // Allows reading perfmon counters for user mode code. - asm volatile( "mrc p15, 0, %0, c9, c12, 1" : "=r"( pmcntenset ) ); - if ( pmcntenset & 0x80000000ul ) - { // Is it counting? - asm volatile( "mrc p15, 0, %0, c9, c13, 0" : "=r"( pmccntr ) ); - // The counter is set up to count every 64th cycle - return ( ( int64_t )pmccntr ) * 64; // Should optimize to << 6 - } - } - # else - # error "No suitable method for gen_read_cpu_time_stamp_counter for this cpu type" - # endif - - return r; - } - #else - gen_u64 gen_read_cpu_time_stamp_counter( void ) - { - GEN_PANIC( "gen_read_cpu_time_stamp_counter is not supported on this particular setup" ); - return -0; - } - #endif - - #if defined( GEN_SYSTEM_WINDOWS ) || defined( GEN_SYSTEM_CYGWIN ) - - gen_u64 gen_time_rel_ms( void ) - { - gen_local_persist LARGE_INTEGER win32_perf_count_freq = {}; - gen_u64 result; - LARGE_INTEGER counter; - gen_local_persist LARGE_INTEGER win32_perf_counter = {}; - if ( ! win32_perf_count_freq.QuadPart ) - { - QueryPerformanceFrequency( &win32_perf_count_freq ); - GEN_ASSERT( win32_perf_count_freq.QuadPart != 0 ); - QueryPerformanceCounter( &win32_perf_counter ); - } - - QueryPerformanceCounter( &counter ); - - result = ( counter.QuadPart - win32_perf_counter.QuadPart ) * 1000 / ( win32_perf_count_freq.QuadPart ); - return result; - } - - #else - - # if defined( GEN_SYSTEM_LINUX ) || defined( GEN_SYSTEM_FREEBSD ) || defined( GEN_SYSTEM_OPENBSD ) || defined( GEN_SYSTEM_EMSCRIPTEN ) - gen_u64 gen__unix_gettime( void ) - { - struct timespec t; - gen_u64 result; - - clock_gettime( 1 /*CLOCK_MONOTONIC*/, &t ); - result = 1000 * t.tv_sec + 1.0e-6 * t.tv_nsec; - return result; - } - # endif - - gen_u64 gen_time_rel_ms( void ) - { - # if defined( GEN_SYSTEM_OSX ) - gen_u64 result; - - gen_local_persist gen_u64 timebase = 0; - gen_local_persist gen_u64 timestart = 0; - - if ( ! timestart ) - { - mach_timebase_info_data_t tb = { 0 }; - mach_timebase_info( &tb ); - timebase = tb.numer; - timebase /= tb.denom; - timestart = mach_absolute_time(); - } - - // NOTE: mach_absolute_time() returns things in nanoseconds - result = 1.0e-6 * ( mach_absolute_time() - timestart ) * timebase; - return result; - # else - gen_local_persist gen_u64 unix_timestart = 0.0; - - if ( ! unix_timestart ) - { - unix_timestart = gen__unix_gettime(); - } - - gen_u64 now = gen__unix_gettime(); - - return ( now - unix_timestart ); - # endif - } - #endif - - gen_f64 gen_time_rel( void ) - { - return ( gen_f64 )( gen_time_rel_ms() * 1e-3 ); - } -#endif - -#pragma endregion Timing - -#pragma region ADT - -#define gen__adt_fprintf(s_, fmt_, ...) \ - do \ - { \ - if (gen_c_str_fmt_file(s_, fmt_, ##__VA_ARGS__) < 0) \ - return EADT_ERROR_OUT_OF_MEMORY; \ - } while (0) - -gen_u8 gen_adt_make_branch(gen_ADT_Node* node, gen_AllocatorInfo backing, char const* name, gen_b32 is_array) -{ - gen_ADT_Type type = EADT_TYPE_OBJECT; - if (is_array) - type = EADT_TYPE_ARRAY; - - gen_ADT_Node* parent = node->parent; - gen_zero_item(node); - - node->type = type; - node->name = name; - node->parent = parent; - node->nodes = gen_array_init(gen_ADT_Node, backing); - - if (! node->nodes) - return EADT_ERROR_OUT_OF_MEMORY; - - return 0; -} - -gen_u8 gen_adt_destroy_branch(gen_ADT_Node* node) -{ - GEN_ASSERT_NOT_NULL(node); - if ((node->type == EADT_TYPE_OBJECT || node->type == EADT_TYPE_ARRAY) && node->nodes) - { - for (gen_ssize i = 0; i < gen_scast(gen_ssize, gen_array_num(node->nodes)); ++i) - { - gen_adt_destroy_branch(node->nodes + i); - } - - gen_array_free(node->nodes); - } - return 0; -} - -gen_u8 gen_adt_make_leaf(gen_ADT_Node* node, char const* name, gen_ADT_Type type) -{ - GEN_ASSERT(type != EADT_TYPE_OBJECT && type != EADT_TYPE_ARRAY); - - gen_ADT_Node* parent = node->parent; - gen_zero_item(node); - - node->type = type; - node->name = name; - node->parent = parent; - return 0; -} - -gen_ADT_Node* gen_adt_find(gen_ADT_Node* node, char const* name, gen_b32 deep_search) -{ - if (node->type != EADT_TYPE_OBJECT) - { - return NULL; - } - - for (gen_ssize i = 0; i < gen_scast(gen_ssize, gen_array_num(node->nodes)); i++) - { - if (! gen_c_str_compare(node->nodes[i].name, name)) - { - return (node->nodes + i); - } - } - - if (deep_search) - { - for (gen_ssize i = 0; i < gen_scast(gen_ssize, gen_array_num(node->nodes)); i++) - { - gen_ADT_Node* res = gen_adt_find(node->nodes + i, name, deep_search); - - if (res != NULL) - return res; - } - } - - return NULL; -} - -gen_internal gen_ADT_Node* gen__adt_get_value(gen_ADT_Node* node, char const* value) -{ - switch (node->type) - { - case EADT_TYPE_MULTISTRING: - case EADT_TYPE_STRING: - { - if (node->string && ! gen_c_str_compare(node->string, value)) - { - return node; - } - } - break; - case EADT_TYPE_INTEGER: - case EADT_TYPE_REAL: - { - char back[4096] = { 0 }; - gen_FileInfo tmp; - - /* allocate a file descriptor for a memory-mapped number to string conversion, input source buffer is not cloned, however. */ - gen_file_stream_open(&tmp, gen_heap(), (gen_u8*)back, gen_size_of(back), EFileStream_WRITABLE); - gen_adt_print_number(&tmp, node); - - gen_ssize fsize = 0; - gen_u8* buf = gen_file_stream_buf(&tmp, &fsize); - - if (! gen_c_str_compare((char const*)buf, value)) - { - gen_file_close(&tmp); - return node; - } - - gen_file_close(&tmp); - } - break; - default: - break; /* node doesn't support value based lookup */ - } - - return NULL; -} - -gen_internal gen_ADT_Node* gen__adt_get_field(gen_ADT_Node* node, char* name, char* value) -{ - for (gen_ssize i = 0; i < gen_scast(gen_ssize, gen_array_num(node->nodes)); i++) - { - if (! gen_c_str_compare(node->nodes[i].name, name)) - { - gen_ADT_Node* child = &node->nodes[i]; - if (gen__adt_get_value(child, value)) - { - return node; /* this object does contain a field of a specified value! */ - } - } - } - - return NULL; -} - -gen_ADT_Node* gen_adt_query(gen_ADT_Node* node, char const* uri) -{ - GEN_ASSERT_NOT_NULL(uri); - - if (*uri == '/') - { - uri++; - } - - if (*uri == 0) - { - return node; - } - - if (! node || (node->type != EADT_TYPE_OBJECT && node->type != EADT_TYPE_ARRAY)) - { - return NULL; - } - -#if defined EADT_URI_DEBUG || 0 - gen_c_str_fmt_out("uri: %s\n", uri); -#endif - - char * p = (char*)uri, *b = p, *e = p; - gen_ADT_Node* found_node = NULL; - - b = p; - p = e = (char*)gen_c_str_skip(p, '/'); - char* buf = gen_c_str_fmt_buf("%.*s", (int)(e - b), b); - - /* handle field value lookup */ - if (*b == '[') - { - char *l_p = buf + 1, *l_b = l_p, *l_e = l_p, *l_b2 = l_p, *l_e2 = l_p; - l_e = (char*)gen_c_str_skip(l_p, '='); - l_e2 = (char*)gen_c_str_skip(l_p, ']'); - - if ((! *l_e && node->type != EADT_TYPE_ARRAY) || ! *l_e2) - { - GEN_ASSERT_MSG(0, "Invalid field value lookup"); - return NULL; - } - - *l_e2 = 0; - - /* [field=value] */ - if (*l_e) - { - *l_e = 0; - l_b2 = l_e + 1; - - /* run a value comparison against our own fields */ - if (node->type == EADT_TYPE_OBJECT) - { - found_node = gen__adt_get_field(node, l_b, l_b2); - } - - /* run a value comparison against any child that is an object node */ - else if (node->type == EADT_TYPE_ARRAY) - { - for (gen_ssize i = 0; i < gen_scast(gen_ssize, gen_array_num(node->nodes)); i++) - { - gen_ADT_Node* child = &node->nodes[i]; - if (child->type != EADT_TYPE_OBJECT) - { - continue; - } - - found_node = gen__adt_get_field(child, l_b, l_b2); - - if (found_node) - break; - } - } - } - /* [value] */ - else - { - for (gen_ssize i = 0; i < gen_scast(gen_ssize, gen_array_num(node->nodes)); i++) - { - gen_ADT_Node* child = &node->nodes[i]; - if (gen__adt_get_value(child, l_b2)) - { - found_node = child; - break; /* we found a matching value in array, ignore the rest of it */ - } - } - } - - /* go deeper if uri continues */ - if (*e) - { - return gen_adt_query(found_node, e + 1); - } - } - /* handle field name lookup */ - else if (node->type == EADT_TYPE_OBJECT) - { - found_node = gen_adt_find(node, buf, false); - - /* go deeper if uri continues */ - if (*e) - { - return gen_adt_query(found_node, e + 1); - } - } - /* handle array index lookup */ - else - { - gen_ssize idx = (gen_ssize)gen_c_str_to_i64(buf, NULL, 10); - if (idx >= 0 && idx < gen_scast(gen_ssize, gen_array_num(node->nodes))) - { - found_node = &node->nodes[idx]; - - /* go deeper if uri continues */ - if (*e) - { - return gen_adt_query(found_node, e + 1); - } - } - } - - return found_node; -} - -gen_ADT_Node* gen_adt_alloc_at(gen_ADT_Node* parent, gen_ssize index) -{ - if (! parent || (parent->type != EADT_TYPE_OBJECT && parent->type != EADT_TYPE_ARRAY)) - { - return NULL; - } - - if (! parent->nodes) - return NULL; - - if (index < 0 || index > gen_scast(gen_ssize, gen_array_num(parent->nodes))) - return NULL; - - gen_ADT_Node o = { 0 }; - o.parent = parent; - if (! gen_array_append_at(parent->nodes, o, index)) - return NULL; - - gen_ADT_Node* node = &parent->nodes[index]; - return node; -} - -gen_ADT_Node* gen_adt_alloc(gen_ADT_Node* parent) -{ - if (! parent || (parent->type != EADT_TYPE_OBJECT && parent->type != EADT_TYPE_ARRAY)) - { - return NULL; - } - - if (! parent->nodes) - return NULL; - - return gen_adt_alloc_at(parent, gen_array_num(parent->nodes)); -} - -gen_b8 gen_adt_set_obj(gen_ADT_Node* obj, char const* name, gen_AllocatorInfo backing) -{ - return gen_adt_make_branch(obj, backing, name, 0); -} - -gen_b8 gen_adt_set_arr(gen_ADT_Node* obj, char const* name, gen_AllocatorInfo backing) -{ - return gen_adt_make_branch(obj, backing, name, 1); -} - -gen_b8 gen_adt_set_str(gen_ADT_Node* obj, char const* name, char const* value) -{ - gen_adt_make_leaf(obj, name, EADT_TYPE_STRING); - obj->string = value; - return true; -} - -gen_b8 gen_adt_set_flt(gen_ADT_Node* obj, char const* name, gen_f64 value) -{ - gen_adt_make_leaf(obj, name, EADT_TYPE_REAL); - obj->real = value; - return true; -} - -gen_b8 gen_adt_set_int(gen_ADT_Node* obj, char const* name, gen_s64 value) -{ - gen_adt_make_leaf(obj, name, EADT_TYPE_INTEGER); - obj->integer = value; - return true; -} - -gen_ADT_Node* gen_adt_move_node_at(gen_ADT_Node* node, gen_ADT_Node* new_parent, gen_ssize index) -{ - GEN_ASSERT_NOT_NULL(node); - GEN_ASSERT_NOT_NULL(new_parent); - gen_ADT_Node* old_parent = node->parent; - gen_ADT_Node* new_node = gen_adt_alloc_at(new_parent, index); - *new_node = *node; - new_node->parent = new_parent; - if (old_parent) - { - gen_adt_remove_node(node); - } - return new_node; -} - -gen_ADT_Node* gen_adt_move_node(gen_ADT_Node* node, gen_ADT_Node* new_parent) -{ - GEN_ASSERT_NOT_NULL(node); - GEN_ASSERT_NOT_NULL(new_parent); - GEN_ASSERT(new_parent->type == EADT_TYPE_ARRAY || new_parent->type == EADT_TYPE_OBJECT); - return gen_adt_move_node_at(node, new_parent, gen_array_num(new_parent->nodes)); -} - -void gen_adt_swap_nodes(gen_ADT_Node* node, gen_ADT_Node* other_node) -{ - GEN_ASSERT_NOT_NULL(node); - GEN_ASSERT_NOT_NULL(other_node); - gen_ADT_Node* parent = node->parent; - gen_ADT_Node* other_parent = other_node->parent; - gen_ssize index = (gen_pointer_diff(parent->nodes, node) / gen_size_of(gen_ADT_Node)); - gen_ssize index2 = (gen_pointer_diff(other_parent->nodes, other_node) / gen_size_of(gen_ADT_Node)); - gen_ADT_Node temp = parent->nodes[index]; - temp.parent = other_parent; - other_parent->nodes[index2].parent = parent; - parent->nodes[index] = other_parent->nodes[index2]; - other_parent->nodes[index2] = temp; -} - -void gen_adt_remove_node(gen_ADT_Node* node) -{ - GEN_ASSERT_NOT_NULL(node); - GEN_ASSERT_NOT_NULL(node->parent); - gen_ADT_Node* parent = node->parent; - gen_ssize index = (gen_pointer_diff(parent->nodes, node) / gen_size_of(gen_ADT_Node)); - gen_array_remove_at(parent->nodes, index); -} - -gen_ADT_Node* gen_adt_append_obj(gen_ADT_Node* parent, char const* name) -{ - gen_ADT_Node* o = gen_adt_alloc(parent); - if (! o) - return NULL; - if (gen_adt_set_obj(o, name, gen_array_get_header(parent->nodes)->Allocator)) - { - gen_adt_remove_node(o); - return NULL; - } - return o; -} - -gen_ADT_Node* gen_adt_append_arr(gen_ADT_Node* parent, char const* name) -{ - gen_ADT_Node* o = gen_adt_alloc(parent); - if (! o) - return NULL; - - gen_ArrayHeader* node_header = gen_array_get_header(parent->nodes); - if (gen_adt_set_arr(o, name, node_header->Allocator)) - { - gen_adt_remove_node(o); - return NULL; - } - return o; -} - -gen_ADT_Node* gen_adt_append_str(gen_ADT_Node* parent, char const* name, char const* value) -{ - gen_ADT_Node* o = gen_adt_alloc(parent); - if (! o) - return NULL; - gen_adt_set_str(o, name, value); - return o; -} - -gen_ADT_Node* gen_adt_append_flt(gen_ADT_Node* parent, char const* name, gen_f64 value) -{ - gen_ADT_Node* o = gen_adt_alloc(parent); - if (! o) - return NULL; - gen_adt_set_flt(o, name, value); - return o; -} - -gen_ADT_Node* gen_adt_append_int(gen_ADT_Node* parent, char const* name, gen_s64 value) -{ - gen_ADT_Node* o = gen_adt_alloc(parent); - if (! o) - return NULL; - gen_adt_set_int(o, name, value); - return o; -} - -/* parser helpers */ -char* gen_adt_parse_number_strict(gen_ADT_Node* node, char* base_str) -{ - GEN_ASSERT_NOT_NULL(node); - GEN_ASSERT_NOT_NULL(base_str); - char *p = base_str, *e = p; - - while (*e) - ++e; - - while (*p && (gen_char_first_occurence("eE.+-", *p) || gen_char_is_hex_digit(*p))) - { - ++p; - } - - if (p >= e) - { - return gen_adt_parse_number(node, base_str); - } - - return base_str; -} - -char* gen_adt_parse_number(gen_ADT_Node* node, char* base_str) -{ - GEN_ASSERT_NOT_NULL(node); - GEN_ASSERT_NOT_NULL(base_str); - char *p = base_str, *e = p; - - gen_s32 base = 0; - gen_s32 base2 = 0; - gen_u8 base2_offset = 0; - gen_s8 exp = 0, orig_exp = 0; - gen_u8 neg_zero = 0; - gen_u8 lead_digit = 0; - gen_ADT_Type node_type = EADT_TYPE_UNINITIALISED; - gen_u8 node_props = 0; - - /* skip false positives and special cases */ - if (! ! gen_char_first_occurence("eE", *p) || (! ! gen_char_first_occurence(".+-", *p) && ! gen_char_is_hex_digit(*(p + 1)) && *(p + 1) != '.')) - { - return ++base_str; - } - - node_type = EADT_TYPE_INTEGER; - neg_zero = false; - - gen_ssize ib = 0; - char buf[48] = { 0 }; - - if (*e == '+') - ++e; - else if (*e == '-') - { - buf[ib++] = *e++; - } - - if (*e == '.') - { - node_type = EADT_TYPE_REAL; - node_props = EADT_PROPS_IS_PARSED_REAL; - lead_digit = false; - buf[ib++] = '0'; - do - { - buf[ib++] = *e; - } while (gen_char_is_digit(*++e)); - } - else - { - if (! gen_c_str_compare_len(e, "0x", 2) || ! gen_c_str_compare_len(e, "0X", 2)) - { - node_props = EADT_PROPS_IS_HEX; - } - - /* bail if ZPL_ADT_PROPS_IS_HEX is unset but we get 'x' on input */ - if (gen_char_to_lower(*e) == 'x' && (node_props != EADT_PROPS_IS_HEX)) - { - return ++base_str; - } - - while (gen_char_is_hex_digit(*e) || gen_char_to_lower(*e) == 'x') - { - buf[ib++] = *e++; - } - - if (*e == '.') - { - node_type = EADT_TYPE_REAL; - lead_digit = true; - gen_u32 step = 0; - - do - { - buf[ib++] = *e; - ++step; - } while (gen_char_is_digit(*++e)); - - if (step < 2) - { - buf[ib++] = '0'; - } - } - } - - /* check if we have a dot here, this is a false positive (IP address, ...) */ - if (*e == '.') - { - return ++base_str; - } - - gen_f32 eb = 10; - char expbuf[6] = { 0 }; - gen_ssize expi = 0; - - if (*e && ! ! gen_char_first_occurence("eE", *e)) - { - ++e; - if (*e == '+' || *e == '-' || gen_char_is_digit(*e)) - { - if (*e == '-') - { - eb = 0.1f; - } - if (! gen_char_is_digit(*e)) - { - ++e; - } - while (gen_char_is_digit(*e)) - { - expbuf[expi++] = *e++; - } - } - - orig_exp = exp = (gen_u8)gen_c_str_to_i64(expbuf, NULL, 10); - } - - if (node_type == EADT_TYPE_INTEGER) - { - node->integer = gen_c_str_to_i64(buf, 0, 0); -#ifndef GEN_PARSER_DISABLE_ANALYSIS - /* special case: negative zero */ - if (node->integer == 0 && buf[0] == '-') - { - neg_zero = true; - } -#endif - while (orig_exp-- > 0) - { - node->integer *= (gen_s64)eb; - } - } - else - { - node->real = gen_c_str_to_f64(buf, 0); - -#ifndef GEN_PARSER_DISABLE_ANALYSIS - char *q = buf, *base_string = q, *base_string2 = q; - base_string = gen_ccast(char*, gen_c_str_skip(base_string, '.')); - *base_string = '\0'; - base_string2 = base_string + 1; - char* base_strbuilder_off = base_string2; - while (*base_strbuilder_off++ == '0') - base2_offset++; - - base = (gen_s32)gen_c_str_to_i64(q, 0, 0); - base2 = (gen_s32)gen_c_str_to_i64(base_string2, 0, 0); - if (exp) - { - exp = exp * (! (eb == 10.0f) ? -1 : 1); - node_props = EADT_PROPS_IS_EXP; - } - - /* special case: negative zero */ - if (base == 0 && buf[0] == '-') - { - neg_zero = true; - } -#endif - while (orig_exp-- > 0) - { - node->real *= eb; - } - } - - node->type = node_type; - node->props = node_props; - -#ifndef GEN_PARSER_DISABLE_ANALYSIS - node->base = base; - node->base2 = base2; - node->base2_offset = base2_offset; - node->exp = exp; - node->neg_zero = neg_zero; - node->lead_digit = lead_digit; -#else - unused(base); - unused(base2); - unused(base2_offset); - unused(exp); - unused(neg_zero); - unused(lead_digit); -#endif - return e; -} - -gen_ADT_Error gen_adt_print_number(gen_FileInfo* file, gen_ADT_Node* node) -{ - GEN_ASSERT_NOT_NULL(file); - GEN_ASSERT_NOT_NULL(node); - if (node->type != EADT_TYPE_INTEGER && node->type != EADT_TYPE_REAL) - { - return EADT_ERROR_INVALID_TYPE; - } - -#ifndef GEN_PARSER_DISABLE_ANALYSIS - if (node->neg_zero) - { - gen__adt_fprintf(file, "-"); - } -#endif - - switch (node->type) - { - case EADT_TYPE_INTEGER: - { - if (node->props == EADT_PROPS_IS_HEX) - { - gen__adt_fprintf(file, "0x%llx", (long long)node->integer); - } - else - { - gen__adt_fprintf(file, "%lld", (long long)node->integer); - } - } - break; - - case EADT_TYPE_REAL: - { - if (node->props == EADT_PROPS_NAN) - { - gen__adt_fprintf(file, "NaN"); - } - else if (node->props == EADT_PROPS_NAN_NEG) - { - gen__adt_fprintf(file, "-NaN"); - } - else if (node->props == EADT_PROPS_INFINITY) - { - gen__adt_fprintf(file, "Infinity"); - } - else if (node->props == EADT_PROPS_INFINITY_NEG) - { - gen__adt_fprintf(file, "-Infinity"); - } - else if (node->props == EADT_PROPS_TRUE) - { - gen__adt_fprintf(file, "true"); - } - else if (node->props == EADT_PROPS_FALSE) - { - gen__adt_fprintf(file, "false"); - } - else if (node->props == EADT_PROPS_NULL) - { - gen__adt_fprintf(file, "null"); -#ifndef GEN_PARSER_DISABLE_ANALYSIS - } - else if (node->props == EADT_PROPS_IS_EXP) - { - gen__adt_fprintf(file, "%lld.%0*d%llde%lld", (long long)node->base, node->base2_offset, 0, (long long)node->base2, (long long)node->exp); - } - else if (node->props == EADT_PROPS_IS_PARSED_REAL) - { - if (! node->lead_digit) - gen__adt_fprintf(file, ".%0*d%lld", node->base2_offset, 0, (long long)node->base2); - else - gen__adt_fprintf(file, "%lld.%0*d%lld", (long long int)node->base2_offset, 0, (int)node->base, (long long)node->base2); -#endif - } - else - { - gen__adt_fprintf(file, "%f", node->real); - } - } - break; - } - - return EADT_ERROR_NONE; -} - -gen_ADT_Error gen_adt_print_string(gen_FileInfo* file, gen_ADT_Node* node, char const* escaped_chars, char const* escape_symbol) -{ - GEN_ASSERT_NOT_NULL(file); - GEN_ASSERT_NOT_NULL(node); - GEN_ASSERT_NOT_NULL(escaped_chars); - if (node->type != EADT_TYPE_STRING && node->type != EADT_TYPE_MULTISTRING) - { - return EADT_ERROR_INVALID_TYPE; - } - - /* escape string */ - char const *p = node->string, *b = p; - - if (! p) - return EADT_ERROR_NONE; - - do - { - p = gen_c_str_skip_any(p, escaped_chars); - gen__adt_fprintf(file, "%.*s", gen_pointer_diff(b, p), b); - if (*p && ! ! gen_char_first_occurence(escaped_chars, *p)) - { - gen__adt_fprintf(file, "%s%c", escape_symbol, *p); - p++; - } - b = p; - } while (*p); - - return EADT_ERROR_NONE; -} - -gen_ADT_Error gen_adt_c_str_to_number(gen_ADT_Node* node) -{ - GEN_ASSERT(node); - - if (node->type == EADT_TYPE_REAL || node->type == EADT_TYPE_INTEGER) - return EADT_ERROR_ALREADY_CONVERTED; /* this is already converted/parsed */ - if (node->type != EADT_TYPE_STRING && node->type != EADT_TYPE_MULTISTRING) - { - return EADT_ERROR_INVALID_TYPE; - } - - gen_adt_parse_number(node, (char*)node->string); - - return EADT_ERROR_NONE; -} - -gen_ADT_Error gen_adt_c_str_to_number_strict(gen_ADT_Node* node) -{ - GEN_ASSERT(node); - - if (node->type == EADT_TYPE_REAL || node->type == EADT_TYPE_INTEGER) - return EADT_ERROR_ALREADY_CONVERTED; /* this is already converted/parsed */ - if (node->type != EADT_TYPE_STRING && node->type != EADT_TYPE_MULTISTRING) - { - return EADT_ERROR_INVALID_TYPE; - } - - gen_adt_parse_number_strict(node, (char*)node->string); - - return EADT_ERROR_NONE; -} - -#undef gen__adt_fprintf - -#pragma endregion ADT - -#pragma region CSV - -#ifdef GEN_CSV_DEBUG -#define GEN_CSV_ASSERT(msg) GEN_PANIC(msg) -#else -#define GEN_CSV_ASSERT(msg) -#endif - -gen_u8 gen_csv_parse_delimiter(gen_CSV_Object* root, char* text, gen_AllocatorInfo allocator, gen_b32 has_header, char delim) -{ - gen_CSV_Error error = ECSV_Error__NONE; - GEN_ASSERT_NOT_NULL(root); - GEN_ASSERT_NOT_NULL(text); - gen_zero_item(root); - - gen_adt_make_branch(root, allocator, NULL, has_header ? false : true); - - char* currentChar = text; - char* beginChar; - char* endChar; - - gen_ssize columnIndex = 0; - gen_ssize totalColumnIndex = 0; - - do - { - char delimiter = 0; - currentChar = gen_ccast(char*, gen_c_str_trim(currentChar, false)); - - if (*currentChar == 0) - break; - - gen_ADT_Node rowItem = { 0 }; - rowItem.type = EADT_TYPE_STRING; - -#ifndef GEN_PARSER_DISABLE_ANALYSIS - rowItem.name_style = EADT_NAME_STYLE_NO_QUOTES; -#endif - - /* handle string literals */ - if (*currentChar == '"') - { - currentChar += 1; - beginChar = currentChar; - endChar = currentChar; - rowItem.string = beginChar; -#ifndef GEN_PARSER_DISABLE_ANALYSIS - rowItem.name_style = EADT_NAME_STYLE_DOUBLE_QUOTE; -#endif - do - { - endChar = gen_ccast(char*, gen_c_str_skip(endChar, '"')); - - if (*endChar && *(endChar + 1) == '"') - { - endChar += 2; - } - else - break; - } while (*endChar); - - if (*endChar == 0) - { - GEN_CSV_ASSERT("unmatched quoted string"); - error = ECSV_Error__UNEXPECTED_END_OF_INPUT; - return error; - } - - *endChar = 0; - currentChar = gen_ccast(char*, gen_c_str_trim(endChar + 1, true)); - delimiter = *currentChar; - - /* unescape escaped quotes (so that unescaped text escapes :) */ - { - char* escapedChar = beginChar; - do - { - if (*escapedChar == '"' && *(escapedChar + 1) == '"') - { - gen_mem_move(escapedChar, escapedChar + 1, gen_c_str_len(escapedChar)); - } - escapedChar++; - } while (*escapedChar); - } - } - else if (*currentChar == delim) - { - delimiter = *currentChar; - rowItem.string = ""; - } - else if (*currentChar) - { - /* regular data */ - beginChar = currentChar; - endChar = currentChar; - rowItem.string = beginChar; - - do - { - endChar++; - } while (*endChar && *endChar != delim && *endChar != '\n'); - - if (*endChar) - { - currentChar = gen_ccast(char*, gen_c_str_trim(endChar, true)); - - while (gen_char_is_space(*(endChar - 1))) - { - endChar--; - } - - delimiter = *currentChar; - *endChar = 0; - } - else - { - delimiter = 0; - currentChar = endChar; - } - - /* check if number and process if so */ - gen_b32 skip_number = false; - char* num_p = beginChar; - - // We only consider hexadecimal values if they start with 0x - if (gen_c_str_len(num_p) > 2 && num_p[0] == '0' && (num_p[1] == 'x' || num_p[1] == 'X')) - { - num_p += 2; // skip '0x' prefix - do - { - if (! gen_char_is_hex_digit(*num_p)) - { - skip_number = true; - break; - } - } while (*num_p++); - } - else - { - skip_number = true; - } - - if (! skip_number) - { - gen_adt_c_str_to_number(&rowItem); - } - } - - if (columnIndex >= gen_scast(gen_ssize, gen_array_num(root->nodes))) - { - gen_adt_append_arr(root, NULL); - } - - gen_array_append(root->nodes[columnIndex].nodes, rowItem); - - if (delimiter == delim) - { - columnIndex++; - currentChar++; - } - else if (delimiter == '\n' || delimiter == 0) - { - /* check if number of rows is not mismatched */ - if (totalColumnIndex < columnIndex) - totalColumnIndex = columnIndex; - - else if (totalColumnIndex != columnIndex) - { - GEN_CSV_ASSERT("mismatched rows"); - error = ECSV_Error__MISMATCHED_ROWS; - return error; - } - - columnIndex = 0; - - if (delimiter != 0) - currentChar++; - } - } while (*currentChar); - - if (gen_array_num(root->nodes) == 0) - { - GEN_CSV_ASSERT("unexpected end of input. stream is empty."); - error = ECSV_Error__UNEXPECTED_END_OF_INPUT; - return error; - } - - /* consider first row as a header. */ - if (has_header) - { - for (gen_ssize i = 0; i < gen_scast(gen_ssize, gen_array_num(root->nodes)); i++) - { - gen_CSV_Object* col = root->nodes + i; - gen_CSV_Object* hdr = col->nodes; - col->name = hdr->string; - gen_array_remove_at(col->nodes, 0); - } - } - - return error; -} - -void gen_csv_free(gen_CSV_Object* obj) -{ - gen_adt_destroy_branch(obj); -} - -void gen__csv_write_record(gen_FileInfo* file, gen_CSV_Object* node) -{ - switch (node->type) - { - case EADT_TYPE_STRING: - { -#ifndef GEN_PARSER_DISABLE_ANALYSIS - switch (node->name_style) - { - case EADT_NAME_STYLE_DOUBLE_QUOTE: - { - gen_c_str_fmt_file(file, "\""); - gen_adt_print_string(file, node, "\"", "\""); - gen_c_str_fmt_file(file, "\""); - } - break; - - case EADT_NAME_STYLE_NO_QUOTES: - { -#endif - gen_c_str_fmt_file(file, "%s", node->string); -#ifndef GEN_PARSER_DISABLE_ANALYSIS - } - break; - } -#endif - } - break; - - case EADT_TYPE_REAL: - case EADT_TYPE_INTEGER: - { - gen_adt_print_number(file, node); - } - break; - } -} - -void gen__csv_write_header(gen_FileInfo* file, gen_CSV_Object* header) -{ - gen_CSV_Object temp = *header; - temp.string = temp.name; - temp.type = EADT_TYPE_STRING; - gen__csv_write_record(file, &temp); -} - -void gen_csv_write_delimiter(gen_FileInfo* file, gen_CSV_Object* obj, char delimiter) -{ - GEN_ASSERT_NOT_NULL(file); - GEN_ASSERT_NOT_NULL(obj); - GEN_ASSERT(obj->nodes); - gen_ssize cols = gen_array_num(obj->nodes); - if (cols == 0) - return; - - gen_ssize rows = gen_array_num(obj->nodes[0].nodes); - if (rows == 0) - return; - - gen_b32 has_headers = obj->nodes[0].name != NULL; - - if (has_headers) - { - for (gen_ssize i = 0; i < cols; i++) - { - gen__csv_write_header(file, &obj->nodes[i]); - if (i + 1 != cols) - { - gen_c_str_fmt_file(file, "%c", delimiter); - } - } - gen_c_str_fmt_file(file, "\n"); - } - - for (gen_ssize r = 0; r < rows; r++) - { - for (gen_ssize i = 0; i < cols; i++) - { - gen__csv_write_record(file, &obj->nodes[i].nodes[r]); - if (i + 1 != cols) - { - gen_c_str_fmt_file(file, "%c", delimiter); - } - } - gen_c_str_fmt_file(file, "\n"); - } -} - -gen_StrBuilder gen_csv_write_strbuilder_delimiter(gen_AllocatorInfo a, gen_CSV_Object* obj, char delimiter) -{ - gen_FileInfo tmp; - gen_file_stream_new(&tmp, a); - gen_csv_write_delimiter(&tmp, obj, delimiter); - - gen_ssize fsize; - gen_u8* buf = gen_file_stream_buf(&tmp, &fsize); - gen_StrBuilder output = gen_strbuilder_make_length(a, (char*)buf, fsize); - gen_file_close(&tmp); - return output; -} - -#undef gen__adt_fprintf - -#pragma endregion CSV - -GEN_API_C_END -GEN_NS_END - -// GEN_ROLL_OWN_DEPENDENCIES -#endif - -GEN_NS_BEGIN -GEN_API_C_BEGIN - -#pragma region StaticData -GEN_API gen_global gen_Context* gen__ctx; -GEN_API gen_global gen_u32 context_counter; - -#pragma region Constants -GEN_API gen_global gen_Macro gen_enum_underlying_macro; - -GEN_API gen_global gen_Code gen_Code_Global; -GEN_API gen_global gen_Code gen_Code_Invalid; - -GEN_API gen_global gen_Code gen_access_public; -GEN_API gen_global gen_Code gen_access_protected; -GEN_API gen_global gen_Code gen_access_private; - -GEN_API gen_global gen_CodeAttributes gen_attrib_api_export; -GEN_API gen_global gen_CodeAttributes gen_attrib_api_import; - -GEN_API gen_global gen_Code gen_module_global_fragment; -GEN_API gen_global gen_Code gen_module_private_fragment; - -GEN_API gen_global gen_Code gen_fmt_newline; - -GEN_API gen_global gen_CodeParams gen_param_varadic; - -GEN_API gen_global gen_CodePragma gen_pragma_once; - -GEN_API gen_global gen_CodePreprocessCond gen_preprocess_else; -GEN_API gen_global gen_CodePreprocessCond gen_preprocess_endif; - -GEN_API gen_global gen_CodeSpecifiers gen_spec_const; -GEN_API gen_global gen_CodeSpecifiers gen_spec_consteval; -GEN_API gen_global gen_CodeSpecifiers gen_spec_constexpr; -GEN_API gen_global gen_CodeSpecifiers gen_spec_constinit; -GEN_API gen_global gen_CodeSpecifiers gen_spec_extern_linkage; -GEN_API gen_global gen_CodeSpecifiers gen_spec_final; -GEN_API gen_global gen_CodeSpecifiers gen_spec_forceinline; -GEN_API gen_global gen_CodeSpecifiers gen_spec_global; -GEN_API gen_global gen_CodeSpecifiers gen_spec_inline; -GEN_API gen_global gen_CodeSpecifiers gen_spec_internal_linkage; -GEN_API gen_global gen_CodeSpecifiers gen_spec_local_persist; -GEN_API gen_global gen_CodeSpecifiers gen_spec_mutable; -GEN_API gen_global gen_CodeSpecifiers gen_spec_noexcept; -GEN_API gen_global gen_CodeSpecifiers gen_spec_neverinline; -GEN_API gen_global gen_CodeSpecifiers gen_spec_override; -GEN_API gen_global gen_CodeSpecifiers gen_spec_ptr; -GEN_API gen_global gen_CodeSpecifiers gen_spec_pure; -GEN_API gen_global gen_CodeSpecifiers gen_spec_ref; -GEN_API gen_global gen_CodeSpecifiers gen_spec_register; -GEN_API gen_global gen_CodeSpecifiers gen_spec_rvalue; -GEN_API gen_global gen_CodeSpecifiers gen_spec_static_member; -GEN_API gen_global gen_CodeSpecifiers gen_spec_thread_local; -GEN_API gen_global gen_CodeSpecifiers gen_spec_virtual; -GEN_API gen_global gen_CodeSpecifiers gen_spec_volatile; - -GEN_API gen_global gen_CodeTypename gen_t_empty; -GEN_API gen_global gen_CodeTypename gen_t_auto; -GEN_API gen_global gen_CodeTypename gen_t_void; -GEN_API gen_global gen_CodeTypename gen_t_int; -GEN_API gen_global gen_CodeTypename gen_t_bool; -GEN_API gen_global gen_CodeTypename gen_t_char; -GEN_API gen_global gen_CodeTypename gen_t_wchar_t; -GEN_API gen_global gen_CodeTypename gen_t_class; -GEN_API gen_global gen_CodeTypename gen_t_typename; - -#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS -GEN_API gen_global gen_CodeTypename gen_t_b32; - -GEN_API gen_global gen_CodeTypename gen_t_s8; -GEN_API gen_global gen_CodeTypename gen_t_s16; -GEN_API gen_global gen_CodeTypename gen_t_s32; -GEN_API gen_global gen_CodeTypename gen_t_s64; - -GEN_API gen_global gen_CodeTypename gen_t_u8; -GEN_API gen_global gen_CodeTypename gen_t_u16; -GEN_API gen_global gen_CodeTypename gen_t_u32; -GEN_API gen_global gen_CodeTypename gen_t_u64; - -GEN_API gen_global gen_CodeTypename gen_t_ssize; -GEN_API gen_global gen_CodeTypename gen_t_usize; - -GEN_API gen_global gen_CodeTypename gen_t_f32; -GEN_API gen_global gen_CodeTypename gen_t_f64; -#endif - -#pragma endregion Constants - -#pragma endregion StaticData - -#pragma region AST - -// These macros are used in the swtich cases within ast.cpp, inteface.upfront.cpp, parser.cpp - -# define GEN_AST_BODY_CLASS_UNALLOWED_TYPES_CASES \ - case CT_PlatformAttributes: \ - case CT_Class_Body: \ - case CT_Enum_Body: \ - case CT_Extern_Linkage: \ - case CT_Function_Body: \ - case CT_Function_Fwd: \ - case CT_Global_Body: \ - case CT_Namespace: \ - case CT_Namespace_Body: \ - case CT_Operator: \ - case CT_Operator_Fwd: \ - case CT_Parameters: \ - case CT_Specifiers: \ - case CT_Struct_Body: \ - case CT_Typename -# define GEN_AST_BODY_STRUCT_UNALLOWED_TYPES_CASES GEN_AST_BODY_CLASS_UNALLOWED_TYPES_CASES - -# define GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES_CASES \ - case CT_Access_Public: \ - case CT_Access_Protected: \ - case CT_Access_Private: \ - case CT_PlatformAttributes: \ - case CT_Class_Body: \ - case CT_Enum_Body: \ - case CT_Extern_Linkage: \ - case CT_Friend: \ - case CT_Function_Body: \ - case CT_Function_Fwd: \ - case CT_Global_Body: \ - case CT_Namespace: \ - case CT_Namespace_Body: \ - case CT_Operator: \ - case CT_Operator_Fwd: \ - case CT_Operator_Member: \ - case CT_Operator_Member_Fwd: \ - case CT_Parameters: \ - case CT_Specifiers: \ - case CT_Struct_Body: \ - case CT_Typename - -# define GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES \ - case CT_Access_Public: \ - case CT_Access_Protected: \ - case CT_Access_Private: \ - case CT_PlatformAttributes: \ - case CT_Class_Body: \ - case CT_Enum_Body: \ - case CT_Execution: \ - case CT_Friend: \ - case CT_Function_Body: \ - case CT_Namespace_Body: \ - case CT_Operator_Member: \ - case CT_Operator_Member_Fwd: \ - case CT_Parameters: \ - case CT_Specifiers: \ - case CT_Struct_Body: \ - case CT_Typename -# define GEN_AST_BODY_EXPORT_UNALLOWED_TYPES_CASES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES -# define GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES_CASES GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES - -# define GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES_CASES \ - case CT_Access_Public: \ - case CT_Access_Protected: \ - case CT_Access_Private: \ - case CT_PlatformAttributes: \ - case CT_Class_Body: \ - case CT_Enum_Body: \ - case CT_Execution: \ - case CT_Friend: \ - case CT_Function_Body: \ - case CT_Namespace_Body: \ - case CT_Operator_Member: \ - case CT_Operator_Member_Fwd: \ - case CT_Parameters: \ - case CT_Specifiers: \ - case CT_Struct_Body: \ - case CT_Typename - -// This serializes all the data-members in a "debug" format, where each member is printed with its associated value. -gen_Str gen_code__debug_str( gen_Code self) -{ -GEN_ASSERT(self != gen_nullptr); - gen_StrBuilder result_stack = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, gen_kilobytes(1) ); - gen_StrBuilder* result = & result_stack; - - if ( self->Parent ) - gen_strbuilder_append_fmt( result, "\n\tParent : %S %S", gen_code_type_str(self->Parent), self->Name.Len ? self->Name : gen_txt("Null") ); - else - gen_strbuilder_append_fmt( result, "\n\tParent : %S", gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tName : %S", self->Name.Len ? self->Name : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tType : %S", gen_code_type_str(self) ); - gen_strbuilder_append_fmt( result, "\n\tModule Flags : %S", gen_module_flag_to_str( self->ModuleFlags ) ); - - switch ( self->Type ) - { - case CT_Invalid: - case CT_NewLine: - case CT_Access_Private: - case CT_Access_Protected: - case CT_Access_Public: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - break; - - case CT_Untyped: - case CT_Execution: - case CT_Comment: - case CT_PlatformAttributes: - case CT_Preprocess_Include: - case CT_Preprocess_Pragma: - case CT_Preprocess_If: - case CT_Preprocess_ElIf: - case CT_Preprocess_Else: - case CT_Preprocess_IfDef: - case CT_Preprocess_IfNotDef: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tContent: %S", self->Content ); - break; - - case CT_Preprocess_Define: - // TODO(ED): Needs implementaton - gen_log_failure("gen_code_debug_str: NOT IMPLEMENTED for CT_Preprocess_Define"); - break; - - case CT_Class: - case CT_Struct: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tParentAccess: %S", self->ParentType ? gen_access_spec_to_str( self->ParentAccess ) : gen_txt("No Parent") ); - gen_strbuilder_append_fmt( result, "\n\tParentType : %S", self->ParentType ? gen_code_type_str(self->ParentType) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? gen_code_debug_str(self->Body) : gen_txt("Null") ); - break; - - case CT_Class_Fwd: - case CT_Struct_Fwd: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tParentAccess: %S", self->ParentType ? gen_access_spec_to_str( self->ParentAccess ) : gen_txt("No Parent") ); - gen_strbuilder_append_fmt( result, "\n\tParentType : %S", self->ParentType ? gen_code_type_str(self->ParentType) : gen_txt("Null") ); - break; - - case CT_Constructor: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tInitializerList: %S", self->InitializerList ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->InitializerList) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Params) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? gen_code_debug_str(self->Body) : gen_txt("Null") ); - break; - - case CT_Constructor_Fwd: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tInitializerList: %S", self->InitializerList ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->InitializerList) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Params) ) : gen_txt("Null") ); - break; - - case CT_Destructor: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? gen_code_debug_str(self->Body) : gen_txt("Null") ); - break; - - case CT_Destructor_Fwd: - break; - - case CT_Enum: - case CT_Enum_Class: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tUnderlying Type : %S", self->UnderlyingType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->UnderlyingType)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? gen_code_debug_str(self->Body) : gen_txt("Null") ); - break; - - case CT_Enum_Fwd: - case CT_Enum_Class_Fwd: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tUnderlying Type : %S", self->UnderlyingType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->UnderlyingType)) : gen_txt("Null") ); - break; - - case CT_Extern_Linkage: - case CT_Namespace: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tBody: %S", self->Body ? gen_code_debug_str(self->Body) : gen_txt("Null") ); - break; - - case CT_Friend: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tDeclaration: %S", self->Declaration ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Declaration)) : gen_txt("Null") ); - break; - - case CT_Function: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->ReturnType)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Params)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? gen_code_debug_str(self->Body) : gen_txt("Null") ); - break; - - case CT_Function_Fwd: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->ReturnType)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Params)) : gen_txt("Null") ); - break; - - case CT_Module: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - break; - - case CT_Operator: - case CT_Operator_Member: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->ReturnType)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Params)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? gen_code_debug_str(self->Body) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tOp : %S", gen_operator_to_str( self->Op ) ); - break; - - case CT_Operator_Fwd: - case CT_Operator_Member_Fwd: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->ReturnType) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Params) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tOp : %S", gen_operator_to_str( self->Op ) ); - break; - - case CT_Operator_Cast: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tValueType : %S", self->ValueType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->ValueType)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? gen_code_debug_str(self->Body) : gen_txt("Null") ); - break; - - case CT_Operator_Cast_Fwd: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tValueType : %S", self->ValueType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->ValueType)) : gen_txt("Null") ); - break; - - case CT_Parameters: - gen_strbuilder_append_fmt( result, "\n\tNumEntries: %d", self->NumEntries ); - gen_strbuilder_append_fmt( result, "\n\tLast : %S", self->Last->Name ); - gen_strbuilder_append_fmt( result, "\n\tNext : %S", self->Next->Name ); - gen_strbuilder_append_fmt( result, "\n\tValueType : %S", self->ValueType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->ValueType)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tValue : %S", self->Value ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Value)) : gen_txt("Null") ); - break; - - case CT_Parameters_Define: - // TODO(ED): Needs implementaton - gen_log_failure("gen_code_debug_str: NOT IMPLEMENTED for CT_Parameters_Define"); - break; - - case CT_Specifiers: - { - gen_strbuilder_append_fmt( result, "\n\tNumEntries: %d", self->NumEntries ); - gen_strbuilder_append_str( result, gen_txt("\n\tArrSpecs: ") ); - - gen_s32 idx = 0; - gen_s32 left = self->NumEntries; - while ( left-- ) - { - gen_Str spec = gen_spec_to_str( self->ArrSpecs[idx] ); - gen_strbuilder_append_fmt( result, "%.*s, ", spec.Len, spec.Ptr ); - idx++; - } - gen_strbuilder_append_fmt( result, "\n\tNextSpecs: %S", self->NextSpecs ? gen_code_debug_str(self->NextSpecs) : gen_txt("Null") ); - } - break; - - case CT_Template: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Params)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tDeclaration: %S", self->Declaration ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Declaration)) : gen_txt("Null") ); - break; - - case CT_Typedef: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tUnderlyingType: %S", self->UnderlyingType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->UnderlyingType)) : gen_txt("Null") ); - break; - - case CT_Typename: - gen_strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tReturnType : %S", self->ReturnType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->ReturnType)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Params)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tArrExpr : %S", self->ArrExpr ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->ArrExpr)) : gen_txt("Null") ); - break; - - case CT_Union: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? gen_code_debug_str(self->Body) : gen_txt("Null") ); - break; - - case CT_Using: - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tUnderlyingType: %S", self->UnderlyingType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->UnderlyingType)) : gen_txt("Null") ); - break; - - case CT_Variable: - - if ( self->Parent && self->Parent->Type == CT_Variable ) - { - // Its a NextVar - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tValue : %S", self->Value ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Value)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tBitfieldSize: %S", self->BitfieldSize ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->BitfieldSize)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tNextVar : %S", self->NextVar ? gen_code_debug_str(self->NextVar) : gen_txt("Null") ); - break; - } - - if ( self->Prev ) - gen_strbuilder_append_fmt( result, "\n\tPrev: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - if ( self->Next ) - gen_strbuilder_append_fmt( result, "\n\tNext: %S %S", gen_code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : gen_txt("Null") ); - - gen_strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Attributes) ) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Specs)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tValueType : %S", self->ValueType ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->ValueType)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tBitfieldSize: %S", self->BitfieldSize ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->BitfieldSize)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tValue : %S", self->Value ? gen_strbuilder_to_str( gen_code_to_strbuilder(self->Value)) : gen_txt("Null") ); - gen_strbuilder_append_fmt( result, "\n\tNextVar : %S", self->NextVar ? gen_code_debug_str(self->NextVar) : gen_txt("Null") ); - break; - } - - return gen_strbuilder_to_str( * result ); -} - -gen_Code gen_code__duplicate( gen_Code self) -{ -gen_Code result = gen_make_code(); - - void* mem_result = gen_rcast(void*, gen_cast(gen_AST*, result)); - void* mem_self = gen_rcast(void*, gen_cast(gen_AST*, self)); - gen_mem_copy( mem_result, mem_self, sizeof( gen_AST ) ); - - result->Parent = gen_NullCode; - return result; -} - -gen_StrBuilder gen_code__to_strbuilder( gen_Code self) -{ -gen_StrBuilder result = gen_strbuilder_make_str( gen__ctx->Allocator_Temp, gen_txt("") ); - gen_code_to_strbuilder_ref( self, & result ); - return result; -} - -void gen_code__to_strbuilder_ref( gen_Code self, gen_StrBuilder * result) -{ -GEN_ASSERT(self != gen_nullptr); - gen_local_persist gen_thread_local - char SerializationLevel = 0; - - switch ( self->Type ) - { - case CT_Invalid: - #ifdef GEN_DONT_ALLOW_INVALID_CODE - gen_log_failure("Attempted to serialize invalid code! - %S", Parent ? Parent->gen_code_debug_str() : Name ); - #else - gen_strbuilder_append_fmt( result, "Invalid gen_Code!" ); - #endif - break; - - case CT_NewLine: - gen_strbuilder_append_str( result, gen_txt("\n")); - break; - - case CT_Untyped: - case CT_Execution: - case CT_Comment: - case CT_PlatformAttributes: - gen_strbuilder_append_str( result, self->Content ); - break; - - case CT_Access_Private: - case CT_Access_Protected: - case CT_Access_Public: - gen_strbuilder_append_str( result, self->Name ); - break; - - case CT_Class: - gen_class_to_strbuilder_def(gen_cast(gen_CodeClass, self), result ); - break; - - case CT_Class_Fwd: - gen_class_to_strbuilder_fwd(gen_cast(gen_CodeClass, self), result ); - break; - - case CT_Constructor: - gen_constructor__to_strbuilder_def(gen_cast(gen_CodeConstructor, self), result ); - break; - - case CT_Constructor_Fwd: - gen_constructor__to_strbuilder_fwd(gen_cast(gen_CodeConstructor, self), result ); - break; - - case CT_Destructor: - gen_destructor__to_strbuilder_def(gen_cast(gen_CodeDestructor, self), result ); - break; - - case CT_Destructor_Fwd: - gen_destructor__to_strbuilder_fwd(gen_cast(gen_CodeDestructor, self), result ); - break; - - case CT_Enum: - gen_enum_to_strbuilder_def(gen_cast(gen_CodeEnum, self), result ); - break; - - case CT_Enum_Fwd: - gen_enum_to_strbuilder_fwd(gen_cast(gen_CodeEnum, self), result ); - break; - - case CT_Enum_Class: - gen_enum_to_strbuilder_class_def(gen_cast(gen_CodeEnum, self), result ); - break; - - case CT_Enum_Class_Fwd: - gen_enum_to_strbuilder_class_fwd(gen_cast(gen_CodeEnum, self), result ); - break; - - case CT_Export_Body: - gen_body_to_strbuilder_export(gen_cast(gen_CodeBody, self), result ); - break; - - case CT_Extern_Linkage: - gen_extern_to_strbuilder(gen_cast(gen_CodeExtern, self), result ); - break; - - case CT_Friend: - gen_friend_to_strbuilder_ref(gen_cast(gen_CodeFriend, self), result ); - break; - - case CT_Function: - gen_fn_to_strbuilder_def(gen_cast(gen_CodeFn, self), result ); - break; - - case CT_Function_Fwd: - gen_fn_to_strbuilder_fwd(gen_cast(gen_CodeFn, self), result ); - break; - - case CT_Module: - gen_module_to_strbuilder_ref(gen_cast(gen_CodeModule, self), result ); - break; - - case CT_Namespace: - namespace_to_strbuilder_ref(gen_cast(gen_CodeNS, self), result ); - break; - - case CT_Operator: - case CT_Operator_Member: - gen_code_op_to_strbuilder_def(gen_cast(gen_CodeOperator, self), result ); - break; - - case CT_Operator_Fwd: - case CT_Operator_Member_Fwd: - gen_code_op_to_strbuilder_fwd(gen_cast(gen_CodeOperator, self), result ); - break; - - case CT_Operator_Cast: - gen_opcast_to_strbuilder_def(gen_cast(gen_CodeOpCast, self), result ); - break; - - case CT_Operator_Cast_Fwd: - gen_opcast_to_strbuilder_fwd(gen_cast(gen_CodeOpCast, self), result ); - break; - - case CT_Parameters: - gen_params_to_strbuilder_ref(gen_cast(gen_CodeParams, self), result ); - break; - - case CT_Parameters_Define: - gen_define_params_to_strbuilder_ref(gen_cast(gen_CodeDefineParams, self), result); - break; - - case CT_Preprocess_Define: - gen_define_to_strbuilder_ref(gen_cast(gen_CodeDefine, self), result ); - break; - - case CT_Preprocess_If: - gen_preprocess_to_strbuilder_if(gen_cast(gen_CodePreprocessCond, self), result ); - break; - - case CT_Preprocess_IfDef: - gen_preprocess_to_strbuilder_ifdef(gen_cast(gen_CodePreprocessCond, self), result ); - break; - - case CT_Preprocess_IfNotDef: - gen_preprocess_to_strbuilder_ifndef(gen_cast(gen_CodePreprocessCond, self), result ); - break; - - case CT_Preprocess_Include: - gen_include_to_strbuilder_ref(gen_cast(gen_CodeInclude, self), result ); - break; - - case CT_Preprocess_ElIf: - gen_preprocess_to_strbuilder_elif(gen_cast(gen_CodePreprocessCond, self), result ); - break; - - case CT_Preprocess_Else: - gen_preprocess_to_strbuilder_else(gen_cast(gen_CodePreprocessCond, self), result ); - break; - - case CT_Preprocess_EndIf: - gen_preprocess_to_strbuilder_endif(gen_cast(gen_CodePreprocessCond, self), result ); - break; - - case CT_Preprocess_Pragma: - gen_pragma_to_strbuilder_ref(gen_cast(gen_CodePragma, self), result ); - break; - - case CT_Specifiers: - gen_specifiers_to_strbuilder_ref(gen_cast(gen_CodeSpecifiers, self), result ); - break; - - case CT_Struct: - gen_struct_to_strbuilder_def(gen_cast(gen_CodeStruct, self), result ); - break; - - case CT_Struct_Fwd: - gen_struct_to_strbuilder_fwd(gen_cast(gen_CodeStruct, self), result ); - break; - - case CT_Template: - gen_template_to_strbuilder_ref(gen_cast(gen_CodeTemplate, self), result ); - break; - - case CT_Typedef: - gen_typedef_to_strbuilder_ref(gen_cast(gen_CodeTypedef, self), result ); - break; - - case CT_Typename: - gen_typename_to_strbuilder_ref(gen_cast(gen_CodeTypename, self), result ); - break; - - case CT_Union: - union_to_strbuilder_def( gen_cast(gen_CodeUnion, self), result ); - break; - - case CT_Union_Fwd: - union_to_strbuilder_fwd( gen_cast(gen_CodeUnion, self), result ); - break; - - case CT_Using: - gen_using_to_strbuilder_ref(gen_cast(gen_CodeUsing, self), result ); - break; - - case CT_Using_Namespace: - gen_using_to_strbuilder_ns(gen_cast(gen_CodeUsing, self), result ); - break; - - case CT_Variable: - gen_var_to_strbuilder_ref(gen_cast(gen_CodeVar, self), result ); - break; - - case CT_Enum_Body: - case CT_Class_Body: - case CT_Extern_Linkage_Body: - case CT_Function_Body: - case CT_Global_Body: - case CT_Namespace_Body: - case CT_Struct_Body: - case CT_Union_Body: - gen_body_to_strbuilder_ref( gen_cast(gen_CodeBody, self), result ); - break; - } -} - -bool gen_code__is_equal( gen_Code self, gen_Code other) -{ -/* - gen_AST values are either some gen_u32 value, a cached string, or a pointer to another gen_AST. - - gen_u32 values are compared by value. - Cached strings are compared by pointer. - gen_AST nodes are compared with gen_AST::is_equal. -*/ - if ( other == gen_nullptr ) - { - gen_log_fmt( "gen_AST::is_equal: other is null\nAST: %S", gen_code_debug_str(self) ); - return false; - } - - if ( self->Type != other->Type ) - { - gen_log_fmt("gen_AST::is_equal: Type check failure with other\nAST: %S\nOther: %S" - , gen_code_debug_str(self) - , gen_code_debug_str(other) - ); - - return false; - } - - switch ( self->Type ) - { - #define check_member_val( val ) \ - if ( self->val != other->val ) \ - { \ - gen_log_fmt("\nAST::is_equal: Member - " #val " failed\n" \ - "gen_AST : %S\n" \ - "Other: %S\n" \ - , gen_code_debug_str(self) \ - ,gen_code_debug_str(other) \ - ); \ - \ - return false; \ - } - - #define check_member_str( str ) \ - if ( ! gen_str_are_equal( self->str, other->str ) ) \ - { \ - gen_log_fmt("\nAST::is_equal: Member string - "#str " failed\n" \ - "gen_AST : %S\n" \ - "Other: %S\n" \ - , gen_code_debug_str(self) \ - ,gen_code_debug_str(other) \ - ); \ - \ - return false; \ - } - - #define check_member_content( content ) \ - if ( ! gen_str_are_equal( self->content, other->content )) \ - { \ - gen_log_fmt("\nAST::is_equal: Member content - "#content " failed\n" \ - "gen_AST : %S\n" \ - "Other: %S\n" \ - , gen_code_debug_str(self) \ - , gen_code_debug_str(other) \ - ); \ - \ - gen_log_fmt("Content cannot be trusted to be unique with this check " \ - "so it must be verified by eye for now\n" \ - "gen_AST Content:\n%S\n" \ - "Other Content:\n%S\n" \ - , gen_str_visualize_whitespace(self->content, gen__ctx->Allocator_Temp) \ - , gen_str_visualize_whitespace(other->content, gen__ctx->Allocator_Temp) \ - ); \ - } - - #define check_member_ast( ast ) \ - if ( self->ast ) \ - { \ - if ( other->ast == gen_nullptr ) \ - { \ - gen_log_fmt("\nAST::is_equal: Failed for member " #ast " other equivalent param is null\n" \ - "gen_AST : %S\n" \ - "Other: %S\n" \ - "For ast member: %S\n" \ - , gen_code_debug_str(self) \ - , gen_code_debug_str(other) \ - , gen_code_debug_str(self->ast) \ - ); \ - \ - return false; \ - } \ - \ - if ( ! gen_code_is_equal(self->ast, other->ast ) ) \ - { \ - gen_log_fmt( "\nAST::is_equal: Failed for " #ast"\n" \ - "gen_AST : %S\n" \ - "Other: %S\n" \ - "For ast member: %S\n" \ - "other's ast member: %S\n" \ - , gen_code_debug_str(self) \ - , gen_code_debug_str(other) \ - , gen_code_debug_str(self->ast) \ - , gen_code_debug_str(other->ast) \ - ); \ - \ - return false; \ - } \ - } - - case CT_NewLine: - case CT_Access_Public: - case CT_Access_Protected: - case CT_Access_Private: - case CT_Preprocess_Else: - case CT_Preprocess_EndIf: - return true; - - - // Comments are not validated. - case CT_Comment: - return true; - - case CT_Execution: - case CT_PlatformAttributes: - case CT_Untyped: - { - check_member_content( Content ); - return true; - } - - case CT_Class_Fwd: - case CT_Struct_Fwd: - { - check_member_str( Name ); - check_member_ast( ParentType ); - check_member_val( ParentAccess ); - check_member_ast( Attributes ); - - return true; - } - - case CT_Class: - case CT_Struct: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( ParentType ); - check_member_val( ParentAccess ); - check_member_ast( Attributes ); - check_member_ast( Body ); - - return true; - } - - case CT_Constructor: - { - check_member_ast( InitializerList ); - check_member_ast( Params ); - check_member_ast( Body ); - - return true; - } - - case CT_Constructor_Fwd: - { - check_member_ast( InitializerList ); - check_member_ast( Params ); - - return true; - } - - case CT_Destructor: - { - check_member_ast( Specs ); - check_member_ast( Body ); - - return true; - } - - case CT_Destructor_Fwd: - { - check_member_ast( Specs ); - - return true; - } - - case CT_Enum: - case CT_Enum_Class: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( Attributes ); - check_member_ast( UnderlyingType ); - check_member_ast( Body ); - check_member_ast( UnderlyingTypeMacro ); - - return true; - } - - case CT_Enum_Fwd: - case CT_Enum_Class_Fwd: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( Attributes ); - check_member_ast( UnderlyingType ); - check_member_ast( UnderlyingTypeMacro ); - - return true; - } - - case CT_Extern_Linkage: - { - check_member_str( Name ); - check_member_ast( Body ); - - return true; - } - - case CT_Friend: - { - check_member_str( Name ); - check_member_ast( Declaration ); - - return true; - } - - case CT_Function: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( ReturnType ); - check_member_ast( Attributes ); - check_member_ast( Specs ); - check_member_ast( Params ); - check_member_ast( Body ); - - return true; - } - - case CT_Function_Fwd: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( ReturnType ); - check_member_ast( Attributes ); - check_member_ast( Specs ); - check_member_ast( Params ); - - return true; - } - - case CT_Module: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - - return true; - } - - case CT_Namespace: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( Body ); - - return true; - } - - case CT_Operator: - case CT_Operator_Member: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( ReturnType ); - check_member_ast( Attributes ); - check_member_ast( Specs ); - check_member_ast( Params ); - check_member_ast( Body ); - - return true; - } - - case CT_Operator_Fwd: - case CT_Operator_Member_Fwd: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( ReturnType ); - check_member_ast( Attributes ); - check_member_ast( Specs ); - check_member_ast( Params ); - - return true; - } - - case CT_Operator_Cast: - { - check_member_str( Name ); - check_member_ast( Specs ); - check_member_ast( ValueType ); - check_member_ast( Body ); - - return true; - } - - case CT_Operator_Cast_Fwd: - { - check_member_str( Name ); - check_member_ast( Specs ); - check_member_ast( ValueType ); - - return true; - } - - case CT_Parameters: - { - if ( self->NumEntries > 1 ) - { - gen_Code curr = self; - gen_Code curr_other = other; - while ( curr != gen_nullptr ) - { - if ( curr ) - { - if ( curr_other == gen_nullptr ) - { - gen_log_fmt("\nAST::is_equal: Failed for parameter, other equivalent param is null\n" - "gen_AST : %S\n" - "Other: %S\n" - "For ast member: %S\n" - , gen_code_debug_str(curr) - ); - - return false; - } - - if ( gen_str_are_equal(curr->Name, curr_other->Name) ) - { - gen_log_fmt( "\nAST::is_equal: Failed for parameter name check\n" - "gen_AST : %S\n" - "Other: %S\n" - "For ast member: %S\n" - "other's ast member: %S\n" - , gen_code_debug_str(self) - , gen_code_debug_str(other) - , gen_code_debug_str(curr) - , gen_code_debug_str(curr_other) - ); - return false; - } - - if ( curr->ValueType && ! gen_code_is_equal(curr->ValueType, curr_other->ValueType) ) - { - gen_log_fmt( "\nAST::is_equal: Failed for parameter value type check\n" - "gen_AST : %S\n" - "Other: %S\n" - "For ast member: %S\n" - "other's ast member: %S\n" - , gen_code_debug_str(self) - , gen_code_debug_str(other) - , gen_code_debug_str(curr) - , gen_code_debug_str(curr_other) - ); - return false; - } - - if ( curr->Value && ! gen_code_is_equal(curr->Value, curr_other->Value) ) - { - gen_log_fmt( "\nAST::is_equal: Failed for parameter value check\n" - "gen_AST : %S\n" - "Other: %S\n" - "For ast member: %S\n" - "other's ast member: %S\n" - , gen_code_debug_str(self) - , gen_code_debug_str(other) - , gen_code_debug_str(curr) - , gen_code_debug_str(curr_other) - ); - return false; - } - } - - curr = curr->Next; - curr_other = curr_other->Next; - } - - check_member_val( NumEntries ); - - return true; - } - - check_member_str( Name ); - check_member_ast( ValueType ); - check_member_ast( Value ); - check_member_ast( ArrExpr ); - - return true; - } - - case CT_Parameters_Define: - { - // TODO(ED): Needs implementaton - gen_log_failure("gen_code_is_equal: NOT IMPLEMENTED for CT_Parameters_Define"); - return false; - } - - case CT_Preprocess_Define: - { - check_member_str( Name ); - check_member_content( Body->Content ); - return true; - } - - case CT_Preprocess_If: - case CT_Preprocess_IfDef: - case CT_Preprocess_IfNotDef: - case CT_Preprocess_ElIf: - { - check_member_content( Content ); - - return true; - } - - case CT_Preprocess_Include: - case CT_Preprocess_Pragma: - { - check_member_content( Content ); - - return true; - } - - case CT_Specifiers: - { - check_member_val( NumEntries ); - check_member_str( Name ); - for ( gen_s32 idx = 0; idx < self->NumEntries; ++idx ) - { - check_member_val( ArrSpecs[ idx ] ); - } - return true; - } - - case CT_Template: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( Params ); - check_member_ast( Declaration ); - - return true; - } - - case CT_Typedef: - { - check_member_val( IsFunction ); - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( Specs ); - check_member_ast( UnderlyingType ); - - return true; - } - case CT_Typename: - { - check_member_val( IsParamPack ); - check_member_str( Name ); - check_member_ast( Specs ); - check_member_ast( ArrExpr ); - - return true; - } - - case CT_Union: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( Attributes ); - check_member_ast( Body ); - - return true; - } - - case CT_Union_Fwd: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( Attributes ); - } - - case CT_Using: - case CT_Using_Namespace: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( UnderlyingType ); - check_member_ast( Attributes ); - - return true; - } - - case CT_Variable: - { - check_member_val( ModuleFlags ); - check_member_str( Name ); - check_member_ast( ValueType ); - check_member_ast( BitfieldSize ); - check_member_ast( Value ); - check_member_ast( Attributes ); - check_member_ast( Specs ); - check_member_ast( NextVar ); - - return true; - } - - case CT_Class_Body: - case CT_Enum_Body: - case CT_Export_Body: - case CT_Global_Body: - case CT_Namespace_Body: - case CT_Struct_Body: - case CT_Union_Body: - { - check_member_ast( Front ); - check_member_ast( Back ); - - gen_Code curr = self->Front; - gen_Code curr_other = other->Front; - while ( curr != gen_nullptr ) - { - if ( curr_other == gen_nullptr ) - { - gen_log_fmt("\nAST::is_equal: Failed for body, other equivalent param is null\n" - "gen_AST : %S\n" - "Other: %S\n" - , gen_code_debug_str(curr) - , gen_code_debug_str(other) - ); - - return false; - } - - if ( ! gen_code_is_equal( curr, curr_other ) ) - { - gen_log_fmt( "\nAST::is_equal: Failed for body\n" - "gen_AST : %S\n" - "Other: %S\n" - "For ast member: %S\n" - "other's ast member: %S\n" - , gen_code_debug_str(self) - , gen_code_debug_str(other) - , gen_code_debug_str(curr) - , gen_code_debug_str(curr_other) - ); - - return false; - } - - curr = curr->Next; - curr_other = curr_other->Next; - } - - check_member_val( NumEntries ); - - return true; - } - - #undef check_member_val - #undef check_member_str - #undef check_member_ast - } - - return true; -} - -bool gen_code__validate_body( gen_Code self) -{ -switch ( self->Type ) - { - case CT_Class_Body: - { - gen_CodeBody body = gen_cast(gen_CodeBody, self); - for (gen_Code gen_code_entry = gen_begin_CodeBody(body); gen_code_entry != gen_end_CodeBody(body); gen_next_CodeBody(body, gen_code_entry)) switch (gen_code_entry->Type) - { - GEN_AST_BODY_CLASS_UNALLOWED_TYPES_CASES: - gen_log_failure("gen_AST::validate_body: Invalid entry in body %S", gen_code_debug_str(gen_code_entry)); - return false; - - default: - continue; - } - } - break; - case CT_Enum_Body: - { - gen_CodeBody body = gen_cast(gen_CodeBody, self); - for ( gen_Code entry = gen_begin_CodeBody(body); entry != gen_end_CodeBody(body); gen_next_CodeBody(body, entry) ) - { - if ( entry->Type != CT_Untyped ) - { - gen_log_failure( "gen_AST::validate_body: Invalid entry in enum body (needs to be untyped or comment) %S", gen_code_debug_str(entry) ); - return false; - } - } - } - break; - case CT_Export_Body: - { - gen_CodeBody body = gen_cast(gen_CodeBody, self); - for (gen_Code gen_code_entry = gen_begin_CodeBody(body); gen_code_entry != gen_end_CodeBody(body); gen_next_CodeBody(body, gen_code_entry)) switch (gen_code_entry->Type) - { - GEN_AST_BODY_EXPORT_UNALLOWED_TYPES_CASES: - gen_log_failure("gen_AST::validate_body: Invalid entry in body %S", gen_code_debug_str(gen_code_entry)); - return false; - - default: - continue; - } - } - break; - case CT_Extern_Linkage: - { - gen_CodeBody body = gen_cast(gen_CodeBody, self); - for (gen_Code gen_code_entry = gen_begin_CodeBody(body); gen_code_entry != gen_end_CodeBody(body); gen_next_CodeBody(body, gen_code_entry)) switch (gen_code_entry->Type) - { - GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES_CASES: - gen_log_failure("gen_AST::validate_body: Invalid entry in body %S", gen_code_debug_str(gen_code_entry)); - return false; - - default: - continue; - } - } - break; - case CT_Function_Body: - { - gen_CodeBody body = gen_cast(gen_CodeBody, self); - for (gen_Code gen_code_entry = gen_begin_CodeBody(body); gen_code_entry != gen_end_CodeBody(body); gen_next_CodeBody(body, gen_code_entry)) switch (gen_code_entry->Type) - { - GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES_CASES: - gen_log_failure("gen_AST::validate_body: Invalid entry in body %S", gen_code_debug_str(gen_code_entry)); - return false; - - default: - continue; - } - } - break; - case CT_Global_Body: - { - gen_CodeBody body = gen_cast(gen_CodeBody, self); - for ( gen_Code entry = gen_begin_CodeBody(body); entry != gen_end_CodeBody(body); gen_next_CodeBody(body, entry) )switch (entry->Type) - { - GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES: - gen_log_failure("gen_AST::validate_body: Invalid entry in body %S", gen_code_debug_str(entry)); - return false; - } - } - break; - case CT_Namespace_Body: - { - gen_CodeBody body = gen_cast(gen_CodeBody, self); - for ( gen_Code entry = gen_begin_CodeBody(body); entry != gen_end_CodeBody(body); gen_next_CodeBody(body, entry) ) switch (entry->Type) - { - GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES_CASES: - gen_log_failure("gen_AST::validate_body: Invalid entry in body %S", gen_code_debug_str(entry)); - return false; - } - } - break; - case CT_Struct_Body: - { - gen_CodeBody body = gen_cast(gen_CodeBody, self); - for ( gen_Code entry = gen_begin_CodeBody(body); entry != gen_end_CodeBody(body); gen_next_CodeBody(body, entry) ) switch (entry->Type) - { - GEN_AST_BODY_STRUCT_UNALLOWED_TYPES_CASES: - gen_log_failure("gen_AST::validate_body: Invalid entry in body %S", gen_code_debug_str(entry)); - return false; - } - } - break; - case CT_Union_Body: - { - gen_CodeBody body = gen_cast(gen_CodeBody, self); - for ( gen_Code entry = gen_begin_CodeBody(body); entry != gen_end_CodeBody(body); gen_next_CodeBody(body, entry) ) - { - if ( entry->Type != CT_Untyped ) - { - gen_log_failure( "gen_AST::validate_body: Invalid entry in union body (needs to be untyped or comment) %S", gen_code_debug_str(entry) ); - return false; - } - } - } - break; - - default: - gen_log_failure( "gen_AST::validate_body: Invalid this gen_AST does not have a body %S", gen_code_debug_str(self) ); - return false; - } - return false; -} - -gen_StrBuilder gen_body_to_strbuilder(gen_CodeBody body) -{ - GEN_ASSERT(body); - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 128 ); - switch ( body->Type ) - { - case CT_Untyped: - case CT_Execution: - gen_strbuilder_append_str( & result, gen_cast(gen_Code, body)->Content ); - break; - - case CT_Enum_Body: - case CT_Class_Body: - case CT_Extern_Linkage_Body: - case CT_Function_Body: - case CT_Global_Body: - case CT_Namespace_Body: - case CT_Struct_Body: - case CT_Union_Body: - gen_body_to_strbuilder_ref( body, & result ); - break; - - case CT_Export_Body: - gen_body_to_strbuilder_export( body, & result ); - break; - } - return result; -} - -void gen_body_to_strbuilder_export( gen_CodeBody body, gen_StrBuilder* result ) -{ - GEN_ASSERT(body != gen_nullptr); - GEN_ASSERT(result != gen_nullptr); - gen_strbuilder_append_fmt( result, "export\n{\n" ); - - 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 = curr->Next; - } - - gen_strbuilder_append_fmt( result, "};\n" ); -} - -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) - { - case CT_Constructor: - gen_constructor__to_strbuilder_def( self, & result ); - break; - case CT_Constructor_Fwd: - gen_constructor__to_strbuilder_fwd( self, & result ); - break; - } - return result; -} - -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 ); - } - else { - gen_strbuilder_append_str( result, self->Name ); - } - - if ( self->Params ) - gen_strbuilder_append_fmt( result, "( %SB )", gen_params_to_strbuilder(self->Params) ); - else - gen_strbuilder_append_str( result, gen_txt("()") ); - - if ( self->InitializerList ) - gen_strbuilder_append_fmt( result, " : %SB", gen_code_to_strbuilder(self->InitializerList) ); - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, " // %S", self->InlineCmt->Content ); - - gen_strbuilder_append_fmt( result, "\n{\n%SB\n}\n", gen_code_to_strbuilder(self->Body) ); -} - -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 ); - } - else { - gen_strbuilder_append_str( result, self->Name ); - } - - if ( self->Params ) - gen_strbuilder_append_fmt( result, "( %SB )", gen_params_to_strbuilder(self->Params) ); - else - gen_strbuilder_append_fmt( result, "()"); - - if (self->Body) - gen_strbuilder_append_fmt( result, " = %SB", gen_code_to_strbuilder(self->Body) ); - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "; // %S\n", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, gen_txt(";\n") ); -} - -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 ) - { - case CT_Class: - gen_class_to_strbuilder_def(self, & result ); - break; - case CT_Class_Fwd: - gen_class_to_strbuilder_fwd(self, & result ); - break; - } - return result; -} - -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, gen_txt("export ") ); - - gen_strbuilder_append_str( result, gen_txt("class ") ); - - if ( self->Attributes ) - { - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - } - - if ( self->Name.Len ) - gen_strbuilder_append_str( result, self->Name ); - - if (self->Specs && gen_specifiers_has(self->Specs, Spec_Final)) - gen_strbuilder_append_str(result, gen_txt(" final")); - - if ( self->ParentType ) - { - gen_Str access_level = gen_access_spec_to_str( self->ParentAccess ); - gen_strbuilder_append_fmt( result, " : %S %SB", self->Name, access_level, gen_typename_to_strbuilder(self->ParentType) ); - - gen_CodeTypename interface = gen_cast(gen_CodeTypename, self->ParentType->Next); - if ( interface ) - gen_strbuilder_append_str( result, gen_txt("\n") ); - - while ( interface ) - { - gen_strbuilder_append_fmt( result, ", public %SB", gen_typename_to_strbuilder(interface) ); - interface = interface->Next ? gen_cast(gen_CodeTypename, interface->Next) : gen_NullCode; - } - } - - if ( self->InlineCmt ) - { - gen_strbuilder_append_fmt( result, " // %S", self->InlineCmt->Content ); - } - - gen_strbuilder_append_fmt( result, "\n{\n%SB\n}", gen_body_to_strbuilder(self->Body) ); - - if ( self->Parent == gen_nullptr || ( self->Parent->Type != CT_Typedef && self->Parent->Type != CT_Variable ) ) - gen_strbuilder_append_str( result, gen_txt(";\n") ); -} - -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, gen_txt("export ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "class %SB %S", gen_attributes_to_strbuilder(self->Attributes), self->Name ); - - else gen_strbuilder_append_fmt( result, "class %S", self->Name ); - - // Check if it can have an end-statement - if ( self->Parent == gen_nullptr || ( self->Parent->Type != CT_Typedef && self->Parent->Type != CT_Variable ) ) - { - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "; // %S\n", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, gen_txt(";\n") ); - } -} - -void gen_define_to_strbuilder_ref(gen_CodeDefine define, gen_StrBuilder* result ) -{ - GEN_ASSERT(define); - GEN_ASSERT(define->Body); - GEN_ASSERT(define->Body->Content.Ptr && define->Body->Content.Len > 0); - if (define->Params) { - gen_StrBuilder gen_params_builder = gen_define_params_to_strbuilder(define->Params); - gen_strbuilder_append_fmt( result, "#define %S(%S) %S", define->Name, gen_strbuilder_to_str(gen_params_builder), define->Body->Content ); - } - else { - gen_strbuilder_append_fmt( result, "#define %S %S", define->Name, define->Body->Content ); - } -} - -void gen_define_params_to_strbuilder_ref(gen_CodeDefineParams self, gen_StrBuilder* result) -{ - GEN_ASSERT(self); - GEN_ASSERT(result); - if ( self->Name.Ptr && self->Name.Len ) - { - gen_strbuilder_append_fmt( result, " %S", self->Name ); - } - if ( self->NumEntries - 1 > 0 ) - { - for ( gen_CodeDefineParams param = gen_begin_CodeDefineParams(self->Next); param != gen_end_CodeDefineParams(self->Next); param = gen_next_CodeDefineParams(self->Next, param) ) - { - gen_strbuilder_append_fmt( result, ", %SB", gen_define_params_to_strbuilder(param) ); - } - } -} - -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 ) - { - case CT_Destructor: - gen_destructor__to_strbuilder_def( self, & result ); - break; - case CT_Destructor_Fwd: - gen_destructor__to_strbuilder_fwd( self, & result ); - break; - } - return result; -} - -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 ); - } - else if ( self->Specs ) - { - if ( gen_specifiers_has(self->Specs, Spec_Virtual ) ) - gen_strbuilder_append_fmt( result, "virtual ~%S()", self->Parent->Name ); - else - gen_strbuilder_append_fmt( result, "~%S()", self->Parent->Name ); - } - else - gen_strbuilder_append_fmt( result, "~%S()", self->Parent->Name ); - - gen_strbuilder_append_fmt( result, "\n{\n%SB\n}\n", gen_code_to_strbuilder(self->Body) ); -} - -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 ) ) - gen_strbuilder_append_fmt( result, "virtual ~%S();\n", self->Parent->Name ); - else - gen_strbuilder_append_fmt( result, "~%S()", self->Parent->Name ); - - if ( gen_specifiers_has(self->Specs, Spec_Pure ) ) - gen_strbuilder_append_str( result, gen_txt(" = 0;") ); - else if (self->Body) - gen_strbuilder_append_fmt( result, " = %SB;", gen_code_to_strbuilder(self->Body) ); - } - else - gen_strbuilder_append_fmt( result, "~%S();", self->Parent->Name ); - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, " %S", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, gen_txt("\n")); -} - -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 ) - { - case CT_Enum: - gen_enum_to_strbuilder_def(self, & result ); - break; - case CT_Enum_Fwd: - gen_enum_to_strbuilder_fwd(self, & result ); - break; - case CT_Enum_Class: - gen_enum_to_strbuilder_class_def(self, & result ); - break; - case CT_Enum_Class_Fwd: - gen_enum_to_strbuilder_class_fwd(self, & result ); - break; - } - return result; -} - -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, gen_txt("export ") ); - - if ( self->Attributes || self->UnderlyingType || self->UnderlyingTypeMacro ) - { - gen_strbuilder_append_str( result, gen_txt("enum ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - if ( self->UnderlyingType ) - gen_strbuilder_append_fmt( result, "%S : %SB\n{\n%SB\n}" - , self->Name - , gen_typename_to_strbuilder(self->UnderlyingType) - , gen_body_to_strbuilder(self->Body) - ); - else if ( self->UnderlyingTypeMacro ) - gen_strbuilder_append_fmt( result, "%S %SB\n{\n%SB\n}" - , self->Name - , gen_code_to_strbuilder(self->UnderlyingTypeMacro) - , gen_body_to_strbuilder(self->Body) - ); - - else gen_strbuilder_append_fmt( result, "%S\n{\n%SB\n}", self->Name, gen_body_to_strbuilder(self->Body) ); - } - else gen_strbuilder_append_fmt( result, "enum %S\n{\n%SB\n}", self->Name, gen_body_to_strbuilder(self->Body) ); - - if ( self->Parent == gen_nullptr || ( self->Parent->Type != CT_Typedef && self->Parent->Type != CT_Variable ) ) - gen_strbuilder_append_str( result, gen_txt(";\n")); -} - -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, gen_txt("export ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - if ( self->UnderlyingType ) - gen_strbuilder_append_fmt( result, "enum %S : %SB", self->Name, gen_typename_to_strbuilder(self->UnderlyingType) ); - else if (self->UnderlyingTypeMacro) - { - gen_log_fmt("IDENTIFIED A UNDERLYING ENUM MACRO"); - gen_strbuilder_append_fmt( result, "enum %S %SB", self->Name, gen_code_to_strbuilder(self->UnderlyingTypeMacro) ); - } - else - gen_strbuilder_append_fmt( result, "enum %S", self->Name ); - - if ( self->Parent == gen_nullptr || ( self->Parent->Type != CT_Typedef && self->Parent->Type != CT_Variable ) ) - { - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "; %S", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, gen_txt(";\n")); - } -} - -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, gen_txt("export ") ); - - if ( self->Attributes || self->UnderlyingType ) - { - gen_strbuilder_append_str( result, gen_txt("enum class ") ); - - if ( self->Attributes ) - { - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - } - - if ( self->UnderlyingType ) - { - gen_strbuilder_append_fmt( result, "%S : %SB\n{\n%SB\n}", self->Name, gen_typename_to_strbuilder(self->UnderlyingType), gen_body_to_strbuilder(self->Body) ); - } - else - { - gen_strbuilder_append_fmt( result, "%S\n{\n%SB\n}", self->Name, gen_body_to_strbuilder(self->Body) ); - } - } - else - { - gen_strbuilder_append_fmt( result, "enum %S\n{\n%SB\n}", self->Name, gen_body_to_strbuilder(self->Body) ); - } - - if ( self->Parent == gen_nullptr || ( self->Parent->Type != CT_Typedef && self->Parent->Type != CT_Variable ) ) - gen_strbuilder_append_str( result, gen_txt(";\n")); -} - -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, gen_txt("export ") ); - - gen_strbuilder_append_str( result, gen_txt("enum class ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - gen_strbuilder_append_fmt( result, "%S : %SB", self->Name, gen_typename_to_strbuilder(self->UnderlyingType) ); - - if ( self->Parent == gen_nullptr || ( self->Parent->Type != CT_Typedef && self->Parent->Type != CT_Variable ) ) - { - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "; %S", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, gen_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 ) - { - case CT_Function: - gen_fn_to_strbuilder_def(self, & result ); - break; - case CT_Function_Fwd: - gen_fn_to_strbuilder_fwd(self, & result ); - break; - } - return result; -} - -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, gen_txt("export") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, " %SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - bool prefix_specs = false; - 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) ) - { - if ( ! gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, " %.*s", gen_spec_str.Len, gen_spec_str.Ptr ); - - prefix_specs = true; - } - } - } - - if ( self->Attributes || prefix_specs ) - gen_strbuilder_append_str( result, gen_txt("\n") ); - - if ( self->ReturnType ) - gen_strbuilder_append_fmt( result, "%SB %S(", gen_typename_to_strbuilder(self->ReturnType), self->Name ); - - else - gen_strbuilder_append_fmt( result, "%S(", self->Name ); - - if ( self->Params ) - gen_strbuilder_append_fmt( result, "%SB)", gen_params_to_strbuilder(self->Params) ); - - else - gen_strbuilder_append_str( result, gen_txt(")") ); - - 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) ) - { - if ( gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, " %.*s", gen_spec_str.Len, gen_spec_str.Ptr ); - } - } - } - - // This is bodged in for now SOLEY for Unreal's PURE_VIRTUAL functional macro - if ( self->SuffixSpecs ) - gen_strbuilder_append_fmt( result, " %SB", gen_code_to_strbuilder(self->SuffixSpecs) ); - - gen_strbuilder_append_fmt( result, "\n{\n%SB\n}\n", gen_body_to_strbuilder(self->Body) ); -} - -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, gen_txt("export ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - gen_b32 prefix_specs = false; - 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) ) - { - if ( ! gen_spec_is_trailing( * spec ) || ! ( * spec != Spec_Pure) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, " %.*s", gen_spec_str.Len, gen_spec_str.Ptr ); - - prefix_specs = true; - } - } - } - - if ( self->Attributes || prefix_specs ) - { - gen_strbuilder_append_str( result, gen_txt("\n") ); - } - - if ( self->ReturnType ) - gen_strbuilder_append_fmt( result, "%SB %S(", gen_typename_to_strbuilder(self->ReturnType), self->Name ); - - else - gen_strbuilder_append_fmt( result, "%S(", self->Name ); - - if ( self->Params ) - gen_strbuilder_append_fmt( result, "%SB)", gen_params_to_strbuilder(self->Params) ); - - else - gen_strbuilder_append_str( result, gen_txt(")") ); - - 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) ) - { - if ( gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, " %.*s", gen_spec_str.Len, gen_spec_str.Ptr ); - } - } - - if ( gen_specifiers_has(self->Specs, Spec_Pure ) ) - gen_strbuilder_append_str( result, gen_txt(" = 0") ); - else if ( gen_specifiers_has(self->Specs, Spec_Delete ) ) - gen_strbuilder_append_str( result, gen_txt(" = delete") ); - } - - // This is bodged in for now SOLEY for Unreal's PURE_VIRTUAL functional macro (I kept it open ended for other jank) - if ( self->SuffixSpecs ) - gen_strbuilder_append_fmt( result, " %SB", gen_code_to_strbuilder(self->SuffixSpecs) ); - - if (self->Body) - gen_strbuilder_append_fmt( result, " = %SB;", gen_body_to_strbuilder(self->Body) ); - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "; %S", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, gen_txt(";\n") ); -} - -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, gen_txt("export ")); - - if (((gen_scast(gen_u32, ModuleFlag_Import) & gen_scast(gen_u32, self->ModuleFlags)) == gen_scast(gen_u32, ModuleFlag_Import))) - gen_strbuilder_append_str( result, gen_txt("import ")); - - gen_strbuilder_append_fmt( result, "%S;\n", self->Name ); -} - -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 ) - { - case CT_Operator: - case CT_Operator_Member: - gen_code_op_to_strbuilder_def( self, & result ); - break; - case CT_Operator_Fwd: - case CT_Operator_Member_Fwd: - gen_code_op_to_strbuilder_fwd( self, & result ); - break; - } - return result; -} - -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, gen_txt("export ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - 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) ) - { - if ( ! gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, " %.*s", gen_spec_str.Len, gen_spec_str.Ptr ); - } - } - } - - if ( self->Attributes || self->Specs ) - { - gen_strbuilder_append_str( result, gen_txt("\n") ); - } - - if ( self->ReturnType ) - gen_strbuilder_append_fmt( result, "%SB %S (", gen_typename_to_strbuilder(self->ReturnType), self->Name ); - - if ( self->Params ) - gen_strbuilder_append_fmt( result, "%SB)", gen_params_to_strbuilder(self->Params) ); - - else - gen_strbuilder_append_str( result, gen_txt(")") ); - - 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) ) - { - if ( gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, " %.*s", gen_spec_str.Len, gen_spec_str.Ptr ); - } - } - } - - gen_strbuilder_append_fmt( result, "\n{\n%SB\n}\n" - , gen_body_to_strbuilder(self->Body) - ); -} - -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, gen_txt("export ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB\n", gen_attributes_to_strbuilder(self->Attributes) ); - - 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) ) - { - if ( ! gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, " %.*s", gen_spec_str.Len, gen_spec_str.Ptr ); - } - } - } - - if ( self->Attributes || self->Specs ) - { - gen_strbuilder_append_str( result, gen_txt("\n") ); - } - - gen_strbuilder_append_fmt( result, "%SB %S (", gen_typename_to_strbuilder(self->ReturnType), self->Name ); - - if ( self->Params ) - gen_strbuilder_append_fmt( result, "%SB)", gen_params_to_strbuilder(self->Params) ); - - else - gen_strbuilder_append_fmt( 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) ) - { - if ( gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, " %.*s", gen_spec_str.Len, gen_spec_str.Ptr ); - } - } - } - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "; %S", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, gen_txt(";\n") ); -} - -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 ) - { - case CT_Operator_Cast: - gen_opcast_to_strbuilder_def(self, & result ); - break; - case CT_Operator_Cast_Fwd: - gen_opcast_to_strbuilder_fwd(self, & result ); - break; - } - return result; -} - -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) ) - { - if ( ! gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, "%*s ", gen_spec_str.Len, gen_spec_str.Ptr ); - } - } - - if ( self->Name.Ptr && self->Name.Len ) - gen_strbuilder_append_fmt( result, "%S operator %SB()", self->Name, gen_typename_to_strbuilder(self->ValueType) ); - else - gen_strbuilder_append_fmt( result, "operator %SB()", gen_typename_to_strbuilder(self->ValueType) ); - - for ( gen_Specifier* spec = gen_begin_CodeSpecifiers(self->Specs); spec != gen_end_CodeSpecifiers(self->Specs); spec = gen_next_CodeSpecifiers(self->Specs, spec) ) - { - if ( gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, " %.*s", gen_spec_str.Len, gen_spec_str.Ptr ); - } - } - - gen_strbuilder_append_fmt( result, "\n{\n%SB\n}\n", gen_body_to_strbuilder(self->Body) ); - return; - } - - if ( self->Name.Ptr && self->Name.Len ) - gen_strbuilder_append_fmt( result, "%S operator %SB()\n{\n%SB\n}\n", self->Name, gen_typename_to_strbuilder(self->ValueType), gen_body_to_strbuilder(self->Body) ); - else - gen_strbuilder_append_fmt( result, "operator %SB()\n{\n%SB\n}\n", gen_typename_to_strbuilder(self->ValueType), gen_body_to_strbuilder(self->Body) ); -} - -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) ) - { - if ( ! gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, "%*s ", gen_spec_str.Len, gen_spec_str.Ptr ); - } - } - - gen_strbuilder_append_fmt( result, "operator %SB()", gen_typename_to_strbuilder(self->ValueType) ); - - for ( gen_Specifier* spec = gen_begin_CodeSpecifiers(self->Specs); spec != gen_end_CodeSpecifiers(self->Specs); spec = gen_next_CodeSpecifiers(self->Specs, spec) ) - { - if ( gen_spec_is_trailing( * spec ) ) - { - gen_Str gen_spec_str = gen_spec_to_str( * spec ); - gen_strbuilder_append_fmt( result, " %*s", gen_spec_str.Len, gen_spec_str.Ptr ); - } - } - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "; %S", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, gen_txt(";\n") ); - return; - } - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "operator %SB(); %SB", gen_typename_to_strbuilder(self->ValueType) ); - else - gen_strbuilder_append_fmt( result, "operator %SB();\n", gen_typename_to_strbuilder(self->ValueType) ); -} - -void gen_params_to_strbuilder_ref( gen_CodeParams self, gen_StrBuilder* result ) -{ - GEN_ASSERT(self); - GEN_ASSERT(result); - if ( self->gen_Macro ) - { - // Related to parsing: ( , ... ) - gen_strbuilder_append_str( result, self->gen_Macro->Content ); - // Could also be: ( , ... ) - } - - if ( self->Name.Ptr && self->Name.Len ) - { - if ( self->ValueType == gen_nullptr ) - gen_strbuilder_append_fmt( result, " %S", self->Name ); - else - gen_strbuilder_append_fmt( result, " %SB %S", gen_typename_to_strbuilder(self->ValueType), self->Name ); - - } - else if ( self->ValueType ) - gen_strbuilder_append_fmt( result, " %SB", gen_typename_to_strbuilder(self->ValueType) ); - - if ( self->PostNameMacro ) - { - gen_strbuilder_append_fmt( result, " %SB", gen_code_to_strbuilder(self->PostNameMacro) ); - } - - if ( self->Value ) - gen_strbuilder_append_fmt( result, " = %SB", gen_code_to_strbuilder(self->Value) ); - - if ( self->NumEntries - 1 > 0 ) - { - for ( gen_CodeParams param = gen_begin_CodeParams(self->Next); param != gen_end_CodeParams(self->Next); param = gen_next_CodeParams(self->Next, param) ) - { - gen_strbuilder_append_fmt( result, ", %SB", gen_params_to_strbuilder(param) ); - } - } -} - -gen_StrBuilder gen_preprocess_to_strbuilder(gen_CodePreprocessCond self) -{ - GEN_ASSERT(self); - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 256 ); - switch ( self->Type ) - { - case CT_Preprocess_If: - gen_preprocess_to_strbuilder_if( self, & result ); - break; - case CT_Preprocess_IfDef: - gen_preprocess_to_strbuilder_ifdef( self, & result ); - break; - case CT_Preprocess_IfNotDef: - gen_preprocess_to_strbuilder_ifndef( self, & result ); - break; - case CT_Preprocess_ElIf: - gen_preprocess_to_strbuilder_elif( self, & result ); - break; - case CT_Preprocess_Else: - gen_preprocess_to_strbuilder_else( self, & result ); - break; - case CT_Preprocess_EndIf: - gen_preprocess_to_strbuilder_endif( self, & result ); - break; - } - return result; -} - -void gen_specifiers_to_strbuilder_ref( gen_CodeSpecifiers self, gen_StrBuilder* result ) -{ - GEN_ASSERT(self); - GEN_ASSERT(result); - gen_s32 idx = 0; - gen_s32 left = self->NumEntries; - while ( left -- ) - { - gen_Specifier spec = self->ArrSpecs[idx]; - gen_Str gen_spec_str = gen_spec_to_str( spec ); - if ( idx > 0 ) switch (spec) { - case Spec_Ptr: - case Spec_Ref: - case Spec_RValue: - break; - - default: - gen_strbuilder_append_str(result, gen_txt(" ")); - break; - } - gen_strbuilder_append_fmt( result, "%S", gen_spec_str ); - idx++; - } - gen_strbuilder_append_str(result, gen_txt(" ")); -} - -gen_StrBuilder gen_struct_to_strbuilder(gen_CodeStruct self) -{ - GEN_ASSERT(self); - GEN_ASSERT(self); - gen_StrBuilder result = gen_strbuilder_make_reserve( gen__ctx->Allocator_Temp, 512 ); - switch ( self->Type ) - { - case CT_Struct: - gen_struct_to_strbuilder_def( self, & result ); - break; - case CT_Struct_Fwd: - gen_struct_to_strbuilder_fwd( self, & result ); - break; - } - return result; -} - -void gen_struct_to_strbuilder_def( gen_CodeStruct 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, gen_txt("export ") ); - - gen_strbuilder_append_str( result, gen_txt("struct ") ); - - if ( self->Attributes ) - { - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - } - - if ( self->Name.Len ) - gen_strbuilder_append_str( result, self->Name ); - - if (self->Specs && gen_specifiers_has(self->Specs, Spec_Final)) - gen_strbuilder_append_str( result, gen_txt(" final")); - - if ( self->ParentType ) - { - gen_Str access_level = gen_access_spec_to_str( self->ParentAccess ); - - gen_strbuilder_append_fmt( result, " : %S %SB", access_level, gen_typename_to_strbuilder(self->ParentType) ); - - gen_CodeTypename interface = gen_cast(gen_CodeTypename, self->ParentType->Next); - if ( interface ) - gen_strbuilder_append_str( result, gen_txt("\n") ); - - while ( interface ) - { - gen_strbuilder_append_fmt( result, ", %SB", gen_typename_to_strbuilder(interface) ); - interface = interface->Next ? gen_cast( gen_CodeTypename, interface->Next) : gen_NullCode; - } - } - - if ( self->InlineCmt ) - { - gen_strbuilder_append_fmt( result, " // %S", self->InlineCmt->Content ); - } - - gen_strbuilder_append_fmt( result, "\n{\n%SB\n}", gen_body_to_strbuilder(self->Body) ); - - if ( self->Parent == gen_nullptr || ( self->Parent->Type != CT_Typedef && self->Parent->Type != CT_Variable ) ) - gen_strbuilder_append_str( result, gen_txt(";\n")); -} - -void gen_struct_to_strbuilder_fwd( gen_CodeStruct 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, gen_txt("export ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "struct %SB %S", gen_attributes_to_strbuilder(self->Attributes), self->Name ); - - else gen_strbuilder_append_fmt( result, "struct %S", self->Name ); - - if ( self->Parent == gen_nullptr || ( self->Parent->Type != CT_Typedef && self->Parent->Type != CT_Variable ) ) - { - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "; %S", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, gen_txt( ";\n") ); - } -} - -void gen_template_to_strbuilder_ref(gen_CodeTemplate 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, gen_txt("export ") ); - - if ( self->Params ) - gen_strbuilder_append_fmt( result, "template< %SB >\n%SB", gen_params_to_strbuilder(self->Params), gen_code_to_strbuilder(self->Declaration) ); - else - gen_strbuilder_append_fmt( result, "template<>\n%SB", gen_code_to_strbuilder(self->Declaration) ); -} - -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, gen_txt("export ") ); - - gen_strbuilder_append_str( result, gen_txt("typedef ")); - - // Determines if the typedef is a function typename - if ( self->UnderlyingType->ReturnType ) - gen_strbuilder_append_string( result, gen_code_to_strbuilder(self->UnderlyingType) ); - else - gen_strbuilder_append_fmt( result, "%SB %S", gen_code_to_strbuilder(self->UnderlyingType), self->Name ); - - if ( self->UnderlyingType->Type == CT_Typename && self->UnderlyingType->ArrExpr ) - { - gen_strbuilder_append_fmt( result, "[ %SB ];", gen_code_to_strbuilder(self->UnderlyingType->ArrExpr) ); - - gen_Code gen_next_arr_expr = self->UnderlyingType->ArrExpr->Next; - while ( gen_next_arr_expr ) - { - gen_strbuilder_append_fmt( result, "[ %SB ];", gen_code_to_strbuilder(gen_next_arr_expr) ); - gen_next_arr_expr = gen_next_arr_expr->Next; - } - } - else - { - gen_strbuilder_append_str( result, gen_txt(";") ); - } - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, " %S", self->InlineCmt->Content); - else - gen_strbuilder_append_str( result, gen_txt("\n")); -} - -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 ) - { - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - else - { - if ( self->Specs ) - gen_strbuilder_append_fmt( result, "%SB ( %S ) ( %SB ) %SB", gen_typename_to_strbuilder(self->ReturnType), self->Name, gen_params_to_strbuilder(self->Params), gen_specifiers_to_strbuilder(self->Specs) ); - else - gen_strbuilder_append_fmt( result, "%SB ( %S ) ( %SB )", gen_typename_to_strbuilder(self->ReturnType), self->Name, gen_params_to_strbuilder(self->Params) ); - } - - break; - } - #else - if ( self->ReturnType && self->Params ) - { - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - else - { - if ( self->Specs ) - gen_strbuilder_append_fmt( result, "%SB %S ( %SB ) %SB", gen_typename_to_strbuilder(self->ReturnType), self->Name, gen_params_to_strbuilder(self->Params), gen_specifiers_to_strbuilder(self->Specs) ); - else - gen_strbuilder_append_fmt( result, "%SB %S ( %SB )", gen_typename_to_strbuilder(self->ReturnType), self->Name, gen_params_to_strbuilder(self->Params) ); - } - - return; - } - #endif - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - switch ( self->TypeTag ) - { - case Tag_Class : gen_strbuilder_append_str( result, gen_txt("class ")); break; - case Tag_Enum : gen_strbuilder_append_str( result, gen_txt("enum ")); break; - case Tag_Struct : gen_strbuilder_append_str( result, gen_txt("struct ")); break; - case Tag_Union : gen_strbuilder_append_str( result, gen_txt("union ")); break; - default: - break; - } - - if ( self->Specs ) - gen_strbuilder_append_fmt( result, "%S %SB", self->Name, gen_specifiers_to_strbuilder(self->Specs) ); - else - gen_strbuilder_append_fmt( result, "%S", self->Name ); - - if ( self->IsParamPack ) - gen_strbuilder_append_str( result, gen_txt("...")); -} - -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 ) - { - case CT_Union: - union_to_strbuilder_def( self, & result ); - break; - case CT_Union_Fwd: - union_to_strbuilder_fwd( self, & result ); - break; - } - return result; -} - -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, gen_txt("export ") ); - - gen_strbuilder_append_str( result, gen_txt("union ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - if ( self->Name.Len ) - { - gen_strbuilder_append_fmt( result, "%S\n{\n%SB\n}" - , self->Name - , gen_body_to_strbuilder(self->Body) - ); - } - else - { - // Anonymous union - gen_strbuilder_append_fmt( result, "\n{\n%SB\n}" - , gen_body_to_strbuilder(self->Body) - ); - } - - if ( self->Parent == gen_nullptr || ( self->Parent->Type != CT_Typedef && self->Parent->Type != CT_Variable ) ) - gen_strbuilder_append_str( result, gen_txt(";\n")); -} - -void union_to_strbuilder_fwd(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, gen_txt("export ") ); - - gen_strbuilder_append_str( result, gen_txt("union ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - if ( self->Name.Len ) - { - gen_strbuilder_append_fmt( result, "%S", self->Name); - } - - if ( self->Parent == gen_nullptr || ( self->Parent->Type != CT_Typedef && self->Parent->Type != CT_Variable ) ) - gen_strbuilder_append_str( result, gen_txt(";\n")); -} - -void gen_using_to_strbuilder_ref(gen_CodeUsing 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, gen_txt("export ") ); - - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - if ( self->UnderlyingType ) - { - gen_strbuilder_append_fmt( result, "using %S = %SB", self->Name, gen_typename_to_strbuilder(self->UnderlyingType) ); - - if ( self->UnderlyingType->ArrExpr ) - { - gen_strbuilder_append_fmt( result, "[ %SB ]", gen_code_to_strbuilder(self->UnderlyingType->ArrExpr) ); - - gen_Code gen_next_arr_expr = self->UnderlyingType->ArrExpr->Next; - while ( gen_next_arr_expr ) - { - gen_strbuilder_append_fmt( result, "[ %SB ]", gen_code_to_strbuilder(gen_next_arr_expr) ); - gen_next_arr_expr = gen_next_arr_expr->Next; - } - } - - gen_strbuilder_append_str( result, gen_txt(";") ); - } - else - gen_strbuilder_append_fmt( result, "using %S;", self->Name ); - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, " %S\n", self->InlineCmt->Content ); - else - gen_strbuilder_append_str( result, gen_txt("\n")); -} - -gen_neverinline -void gen_var_to_strbuilder_ref(gen_CodeVar self, gen_StrBuilder* result ) -{ - GEN_ASSERT(self); - GEN_ASSERT(result); - if ( self->Parent && self->Parent->Type == CT_Variable ) - { - // Its a comma-separated variable ( a NextVar ) - - if ( self->Specs ) - gen_strbuilder_append_fmt( result, "%SB ", gen_specifiers_to_strbuilder(self->Specs) ); - - gen_strbuilder_append_str( result, self->Name ); - - if ( self->ValueType && self->ValueType->ArrExpr ) - { - gen_strbuilder_append_fmt( result, "[ %SB ]", gen_code_to_strbuilder(self->ValueType->ArrExpr) ); - - gen_Code gen_next_arr_expr = self->ValueType->ArrExpr->Next; - while ( gen_next_arr_expr ) - { - gen_strbuilder_append_fmt( result, "[ %SB ]", gen_code_to_strbuilder(gen_next_arr_expr) ); - gen_next_arr_expr = gen_next_arr_expr->Next; - } - } - - if ( self->Value ) - { - if ( self->VarParenthesizedInit ) - gen_strbuilder_append_fmt( result, "( %SB ", gen_code_to_strbuilder(self->Value) ); - else - gen_strbuilder_append_fmt( result, " = %SB", gen_code_to_strbuilder(self->Value) ); - } - - // Keep the chain going... - if ( self->NextVar ) - gen_strbuilder_append_fmt( result, ", %SB", gen_var_to_strbuilder(self->NextVar) ); - - if ( self->VarParenthesizedInit ) - gen_strbuilder_append_str( result, gen_txt(" )")); - - return; - } - - if ( gen_bitfield_is_set( gen_u32, self->ModuleFlags, ModuleFlag_Export )) - gen_strbuilder_append_str( result, gen_txt("export ") ); - - if ( self->Attributes || self->Specs ) - { - if ( self->Attributes ) - gen_strbuilder_append_fmt( result, "%SB ", gen_attributes_to_strbuilder(self->Attributes) ); - - if ( self->Specs ) - gen_strbuilder_append_fmt( result, "%SB", gen_specifiers_to_strbuilder(self->Specs) ); - - gen_strbuilder_append_fmt( result, "%SB %S", gen_typename_to_strbuilder(self->ValueType), self->Name ); - - if ( self->ValueType && self->ValueType->ArrExpr ) - { - gen_strbuilder_append_fmt( result, "[ %SB ]", gen_code_to_strbuilder(self->ValueType->ArrExpr) ); - - gen_Code gen_next_arr_expr = self->ValueType->ArrExpr->Next; - while ( gen_next_arr_expr ) - { - gen_strbuilder_append_fmt( result, "[ %SB ]", gen_code_to_strbuilder(gen_next_arr_expr) ); - gen_next_arr_expr = gen_next_arr_expr->Next; - } - } - - if ( self->BitfieldSize ) - gen_strbuilder_append_fmt( result, " : %SB", gen_code_to_strbuilder(self->BitfieldSize) ); - - if ( self->Value ) - { - if ( self->VarParenthesizedInit ) - gen_strbuilder_append_fmt( result, "( %SB ", gen_code_to_strbuilder(self->Value) ); - else - gen_strbuilder_append_fmt( result, " = %SB", gen_code_to_strbuilder(self->Value) ); - } - - if ( self->NextVar ) - gen_strbuilder_append_fmt( result, ", %SB", gen_var_to_strbuilder(self->NextVar) ); - - if ( self->VarParenthesizedInit ) - gen_strbuilder_append_str( result, gen_txt(" )")); - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, "; %S", self->InlineCmt->Content); - else - gen_strbuilder_append_str( result, gen_txt(";\n") ); - - return; - } - - if ( self->BitfieldSize ) - gen_strbuilder_append_fmt( result, "%SB %S : %SB", gen_typename_to_strbuilder(self->ValueType), self->Name, gen_code_to_strbuilder(self->BitfieldSize) ); - - else if ( self->ValueType && self->ValueType->ArrExpr ) - { - gen_strbuilder_append_fmt( result, "%SB %S[ %SB ]", gen_typename_to_strbuilder(self->ValueType), self->Name, gen_code_to_strbuilder(self->ValueType->ArrExpr) ); - - gen_Code gen_next_arr_expr = self->ValueType->ArrExpr->Next; - while ( gen_next_arr_expr ) - { - gen_strbuilder_append_fmt( result, "[ %SB ]", gen_code_to_strbuilder(gen_next_arr_expr) ); - gen_next_arr_expr = gen_next_arr_expr->Next; - } - } - - else - gen_strbuilder_append_fmt( result, "%SB %S", gen_typename_to_strbuilder(self->ValueType), self->Name ); - - if ( self->Value ) - { - if ( self->VarParenthesizedInit ) - gen_strbuilder_append_fmt( result, "( %SB ", gen_code_to_strbuilder(self->Value) ); - else - gen_strbuilder_append_fmt( result, " = %SB", gen_code_to_strbuilder(self->Value) ); - } - - if ( self->NextVar ) - gen_strbuilder_append_fmt( result, ", %SB", gen_var_to_strbuilder( self->NextVar) ); - - if ( self->VarParenthesizedInit ) - gen_strbuilder_append_str( result, gen_txt(" )")); - - gen_strbuilder_append_str( result, gen_txt(";") ); - - if ( self->InlineCmt ) - gen_strbuilder_append_fmt( result, " %S", self->InlineCmt->Content); - else - gen_strbuilder_append_str( result, gen_txt("\n")); -} -#pragma endregion AST - -#pragma region Interface - -gen_internal void gen_parser_init(gen_Context* ctx); -gen_internal void gen_parser_deinit(gen_Context* ctx); - -gen_internal void* gen_Global_Allocator_Proc( - void* allocator_data, - gen_AllocType type, - gen_ssize size, - gen_ssize alignment, - void* old_memory, - gen_ssize old_size, - gen_u64 flags -) -{ - GEN_ASSERT(gen__ctx); - GEN_ASSERT(gen__ctx->Fallback_AllocatorBuckets); - gen_Arena* last = gen_array_back(gen__ctx->Fallback_AllocatorBuckets); - - switch (type) - { - case EAllocation_ALLOC: - { - if ((last->TotalUsed + size) > last->TotalSize) - { - gen_Arena bucket = gen_arena_init_from_allocator(gen_heap(), gen__ctx->InitSize_Fallback_Allocator_Bucket_Size); - - if (bucket.PhysicalStart == gen_nullptr) - GEN_FATAL("Failed to create bucket for Fallback_AllocatorBuckets"); - - if (! gen_array_append(gen__ctx->Fallback_AllocatorBuckets, bucket)) - GEN_FATAL("Failed to append bucket to Fallback_AllocatorBuckets"); - - last = gen_array_back(gen__ctx->Fallback_AllocatorBuckets); - } - - return gen_alloc_align(gen_arena_allocator_info(last), size, alignment); - } - case EAllocation_FREE: - { - // Doesn't recycle. - } - break; - case EAllocation_FREE_ALL: - { - // Memory::cleanup instead. - } - break; - case EAllocation_RESIZE: - { - if (last->TotalUsed + size > last->TotalSize) - { - gen_Arena bucket = gen_arena_init_from_allocator(gen_heap(), gen__ctx->InitSize_Fallback_Allocator_Bucket_Size); - - if (bucket.PhysicalStart == gen_nullptr) - GEN_FATAL("Failed to create bucket for Fallback_AllocatorBuckets"); - - if (! gen_array_append(gen__ctx->Fallback_AllocatorBuckets, bucket)) - GEN_FATAL("Failed to append bucket to Fallback_AllocatorBuckets"); - - last = gen_array_back(gen__ctx->Fallback_AllocatorBuckets); - } - - void* result = gen_alloc_align(last->Backing, size, alignment); - - if (result != gen_nullptr && old_memory != gen_nullptr) - { - gen_mem_copy(result, old_memory, old_size); - } - - return result; - } - } - - return gen_nullptr; -} - -gen_internal void fallback_logger(LogEntry entry) -{ - GEN_ASSERT(entry.msg.Len > 0); - GEN_ASSERT(entry.msg.Ptr); - gen_log_fmt("%S: %S", loglevel_to_str(entry.level), entry.msg); -} - -gen_internal void gen_define_constants() -{ - // We only initalize these if there is no base context. - if (context_counter > 0) - return; - - gen_Code_Global = gen_make_code(); - gen_Code_Global->Name = gen_cache_str(gen_txt("Global gen_Code")); - gen_Code_Global->Content = gen_Code_Global->Name; - - gen_Code_Invalid = gen_make_code(); - gen_code_set_global(gen_Code_Invalid); - - gen_t_empty = (gen_CodeTypename)gen_make_code(); - gen_t_empty->Type = CT_Typename; - gen_t_empty->Name = gen_cache_str(gen_txt("")); - gen_code_set_global(gen_cast(gen_Code, gen_t_empty)); - - gen_access_private = gen_make_code(); - gen_access_private->Type = CT_Access_Private; - gen_access_private->Name = gen_cache_str(gen_txt("private:\n")); - gen_code_set_global(gen_cast(gen_Code, gen_access_private)); - - gen_access_protected = gen_make_code(); - gen_access_protected->Type = CT_Access_Protected; - gen_access_protected->Name = gen_cache_str(gen_txt("protected:\n")); - gen_code_set_global(gen_access_protected); - - gen_access_public = gen_make_code(); - gen_access_public->Type = CT_Access_Public; - gen_access_public->Name = gen_cache_str(gen_txt("public:\n")); - gen_code_set_global(gen_access_public); - - gen_Str api_export_str = code(GEN_API_Export_Code); - gen_attrib_api_export = gen_def_attributes(api_export_str); - gen_code_set_global(gen_cast(gen_Code, gen_attrib_api_export)); - - gen_Str api_import_str = code(GEN_API_Import_Code); - gen_attrib_api_import = gen_def_attributes(api_import_str); - gen_code_set_global(gen_cast(gen_Code, gen_attrib_api_import)); - - gen_module_global_fragment = gen_make_code(); - gen_module_global_fragment->Type = CT_Untyped; - gen_module_global_fragment->Name = gen_cache_str(gen_txt("module;")); - gen_module_global_fragment->Content = gen_module_global_fragment->Name; - gen_code_set_global(gen_cast(gen_Code, gen_module_global_fragment)); - - gen_module_private_fragment = gen_make_code(); - gen_module_private_fragment->Type = CT_Untyped; - gen_module_private_fragment->Name = gen_cache_str(gen_txt("module : private;")); - gen_module_private_fragment->Content = gen_module_private_fragment->Name; - gen_code_set_global(gen_cast(gen_Code, gen_module_private_fragment)); - - gen_fmt_newline = gen_make_code(); - gen_fmt_newline->Type = CT_NewLine; - gen_code_set_global((gen_Code)gen_fmt_newline); - - gen_pragma_once = (gen_CodePragma)gen_make_code(); - gen_pragma_once->Type = CT_Preprocess_Pragma; - gen_pragma_once->Name = gen_cache_str(gen_txt("once")); - gen_pragma_once->Content = gen_pragma_once->Name; - gen_code_set_global((gen_Code)gen_pragma_once); - - gen_param_varadic = (gen_CodeParams)gen_make_code(); - gen_param_varadic->Type = CT_Parameters; - gen_param_varadic->Name = gen_cache_str(gen_txt("...")); - gen_param_varadic->ValueType = gen_t_empty; - gen_code_set_global((gen_Code)gen_param_varadic); - - gen_preprocess_else = (gen_CodePreprocessCond)gen_make_code(); - gen_preprocess_else->Type = CT_Preprocess_Else; - gen_code_set_global((gen_Code)gen_preprocess_else); - - gen_preprocess_endif = (gen_CodePreprocessCond)gen_make_code(); - gen_preprocess_endif->Type = CT_Preprocess_EndIf; - gen_code_set_global((gen_Code)gen_preprocess_endif); - - gen_Str auto_str = gen_txt("auto"); - gen_t_auto = gen_def_type(auto_str); - gen_code_set_global(gen_t_auto); - gen_Str void_str = gen_txt("void"); - gen_t_void = gen_def_type(void_str); - gen_code_set_global(gen_t_void); - gen_Str int_str = gen_txt("int"); - gen_t_int = gen_def_type(int_str); - gen_code_set_global(gen_t_int); - gen_Str bool_str = gen_txt("bool"); - gen_t_bool = gen_def_type(bool_str); - gen_code_set_global(gen_t_bool); - gen_Str gen_char_str = gen_txt("char"); - gen_t_char = gen_def_type(gen_char_str); - gen_code_set_global(gen_t_char); - gen_Str wchar_str = gen_txt("wchar_t"); - gen_t_wchar_t = gen_def_type(wchar_str); - gen_code_set_global(gen_t_wchar_t); - gen_Str gen_class_str = gen_txt("class"); - gen_t_class = gen_def_type(gen_class_str); - gen_code_set_global(gen_t_class); - gen_Str gen_typename_str = gen_txt("typename"); - gen_t_typename = gen_def_type(gen_typename_str); - gen_code_set_global(gen_t_typename); - -#ifdef GEN_DEFINE_LIBRARY_CODE_CONSTANTS - gen_t_b32 = gen_def_type(name(gen_b32)); - gen_code_set_global(gen_t_b32); - - gen_Str s8_str = gen_txt("gen_s8"); - gen_t_s8 = gen_def_type(s8_str); - gen_code_set_global(gen_t_s8); - gen_Str s16_str = gen_txt("gen_s16"); - gen_t_s16 = gen_def_type(s16_str); - gen_code_set_global(gen_t_s16); - gen_Str s32_str = gen_txt("gen_s32"); - gen_t_s32 = gen_def_type(s32_str); - gen_code_set_global(gen_t_s32); - gen_Str s64_str = gen_txt("gen_s64"); - gen_t_s64 = gen_def_type(s64_str); - gen_code_set_global(gen_t_s64); - - gen_Str u8_str = gen_txt("gen_u8"); - gen_t_u8 = gen_def_type(u8_str); - gen_code_set_global(gen_t_u8); - gen_Str u16_str = gen_txt("gen_u16"); - gen_t_u16 = gen_def_type(u16_str); - gen_code_set_global(gen_t_u16); - gen_Str u32_str = gen_txt("gen_u32"); - gen_t_u32 = gen_def_type(u32_str); - gen_code_set_global(gen_t_u32); - gen_Str u64_str = gen_txt("gen_u64"); - gen_t_u64 = gen_def_type(u64_str); - gen_code_set_global(gen_t_u64); - - gen_Str ssize_str = gen_txt("gen_ssize"); - gen_t_ssize = gen_def_type(ssize_str); - gen_code_set_global(gen_t_ssize); - gen_Str usize_str = gen_txt("gen_usize"); - gen_t_usize = gen_def_type(usize_str); - gen_code_set_global(gen_t_usize); - - gen_Str f32_str = gen_txt("gen_f32"); - gen_t_f32 = gen_def_type(f32_str); - gen_code_set_global(gen_t_f32); - gen_Str f64_str = gen_txt("gen_f64"); - gen_t_f64 = gen_def_type(f64_str); - gen_code_set_global(gen_t_f64); -#endif - - gen_spec_const = gen_def_specifier(Spec_Const); - gen_code_set_global(gen_cast(gen_Code, gen_spec_const)); - gen_spec_consteval = gen_def_specifier(Spec_Consteval); - gen_code_set_global(gen_cast(gen_Code, gen_spec_consteval)); - gen_spec_constexpr = gen_def_specifier(Spec_Constexpr); - gen_code_set_global(gen_cast(gen_Code, gen_spec_constexpr)); - gen_spec_constinit = gen_def_specifier(Spec_Constinit); - gen_code_set_global(gen_cast(gen_Code, gen_spec_constinit)); - gen_spec_extern_linkage = gen_def_specifier(Spec_External_Linkage); - gen_code_set_global(gen_cast(gen_Code, gen_spec_extern_linkage)); - gen_spec_final = gen_def_specifier(Spec_Final); - gen_code_set_global(gen_cast(gen_Code, gen_spec_final)); - gen_spec_forceinline = gen_def_specifier(Spec_ForceInline); - gen_code_set_global(gen_cast(gen_Code, gen_spec_forceinline)); - gen_spec_global = gen_def_specifier(Spec_Global); - gen_code_set_global(gen_cast(gen_Code, gen_spec_global)); - gen_spec_inline = gen_def_specifier(Spec_Inline); - gen_code_set_global(gen_cast(gen_Code, gen_spec_inline)); - gen_spec_internal_linkage = gen_def_specifier(Spec_Internal_Linkage); - gen_code_set_global(gen_cast(gen_Code, gen_spec_internal_linkage)); - gen_spec_local_persist = gen_def_specifier(Spec_Local_Persist); - gen_code_set_global(gen_cast(gen_Code, gen_spec_local_persist)); - gen_spec_mutable = gen_def_specifier(Spec_Mutable); - gen_code_set_global(gen_cast(gen_Code, gen_spec_mutable)); - gen_spec_neverinline = gen_def_specifier(Spec_NeverInline); - gen_code_set_global(gen_cast(gen_Code, gen_spec_neverinline)); - gen_spec_noexcept = gen_def_specifier(Spec_NoExceptions); - gen_code_set_global(gen_cast(gen_Code, gen_spec_noexcept)); - gen_spec_override = gen_def_specifier(Spec_Override); - gen_code_set_global(gen_cast(gen_Code, gen_spec_override)); - gen_spec_ptr = gen_def_specifier(Spec_Ptr); - gen_code_set_global(gen_cast(gen_Code, gen_spec_ptr)); - gen_spec_pure = gen_def_specifier(Spec_Pure); - gen_code_set_global(gen_cast(gen_Code, gen_spec_pure)); - gen_spec_ref = gen_def_specifier(Spec_Ref); - gen_code_set_global(gen_cast(gen_Code, gen_spec_ref)); - gen_spec_register = gen_def_specifier(Spec_Register); - gen_code_set_global(gen_cast(gen_Code, gen_spec_register)); - gen_spec_rvalue = gen_def_specifier(Spec_RValue); - gen_code_set_global(gen_cast(gen_Code, gen_spec_rvalue)); - gen_spec_static_member = gen_def_specifier(Spec_Static); - gen_code_set_global(gen_cast(gen_Code, gen_spec_static_member)); - gen_spec_thread_local = gen_def_specifier(Spec_Thread_Local); - gen_code_set_global(gen_cast(gen_Code, gen_spec_thread_local)); - gen_spec_virtual = gen_def_specifier(Spec_Virtual); - gen_code_set_global(gen_cast(gen_Code, gen_spec_virtual)); - gen_spec_volatile = gen_def_specifier(Spec_Volatile); - gen_code_set_global(gen_cast(gen_Code, gen_spec_volatile)); - - gen_spec_local_persist = gen_def_specifiers(1, Spec_Local_Persist); - gen_code_set_global(gen_cast(gen_Code, gen_spec_local_persist)); - - if (gen_enum_underlying_macro.Name.Len == 0) - { - gen_enum_underlying_macro.Name = gen_txt("gen_enum_underlying"); - gen_enum_underlying_macro.Type = MT_Expression; - gen_enum_underlying_macro.Flags = MF_Functional; - } - gen_register_macro(gen_enum_underlying_macro); -} - -void gen_init(gen_Context* ctx) -{ - gen_do_once() - { - context_counter = 0; - } - gen_AllocatorInfo fallback_allocator = { &gen_Global_Allocator_Proc, gen_nullptr }; - - gen_b32 gen_using_fallback_allocator = false; - if (ctx->Allocator_DyanmicContainers.Proc == gen_nullptr) - { - ctx->Allocator_DyanmicContainers = fallback_allocator; - gen_using_fallback_allocator = true; - } - if (ctx->Allocator_Pool.Proc == gen_nullptr) - { - ctx->Allocator_Pool = fallback_allocator; - gen_using_fallback_allocator = true; - } - if (ctx->Allocator_StrCache.Proc == gen_nullptr) - { - ctx->Allocator_StrCache = fallback_allocator; - gen_using_fallback_allocator = true; - } - if (ctx->Allocator_Temp.Proc == gen_nullptr) - { - ctx->Allocator_Temp = fallback_allocator; - gen_using_fallback_allocator = true; - } - // Setup fallback allocator - if (gen_using_fallback_allocator) - { - ctx->Fallback_AllocatorBuckets = gen_array_init_reserve(gen_Arena, gen_heap(), 128); - if (ctx->Fallback_AllocatorBuckets == gen_nullptr) - GEN_FATAL("Failed to reserve memory for Fallback_AllocatorBuckets"); - - gen_Arena bucket = gen_arena_init_from_allocator(gen_heap(), ctx->InitSize_Fallback_Allocator_Bucket_Size); - if (bucket.PhysicalStart == gen_nullptr) - GEN_FATAL("Failed to create first bucket for Fallback_AllocatorBuckets"); - - gen_array_append(ctx->Fallback_AllocatorBuckets, bucket); - } - - if (ctx->Max_CommentLineLength == 0) - { - ctx->Max_CommentLineLength = 1024; - } - if (ctx->Max_StrCacheLength == 0) - { - ctx->Max_StrCacheLength = gen_kilobytes(512); - } - - if (ctx->InitSize_BuilderBuffer == 0) - { - ctx->InitSize_BuilderBuffer = gen_megabytes(2); - } - if (ctx->InitSize_CodePoolsArray == 0) - { - ctx->InitSize_CodePoolsArray = 16; - } - if (ctx->InitSize_StringArenasArray == 0) - { - ctx->InitSize_StringArenasArray = 16; - } - if (ctx->CodePool_NumBlocks == 0) - { - ctx->CodePool_NumBlocks = gen_kilobytes(16); - } - - if (ctx->InitSize_LexerTokens == 0) - { - ctx->InitSize_LexerTokens = gen_kilobytes(64); - } - if (ctx->SizePer_StringArena == 0) - { - ctx->SizePer_StringArena = gen_megabytes(1); - } - - if (ctx->InitSize_Fallback_Allocator_Bucket_Size == 0) - { - ctx->InitSize_Fallback_Allocator_Bucket_Size = gen_megabytes(8); - } - - if (ctx->InitSize_StrCacheTable == 0) - { - ctx->InitSize_StrCacheTable = gen_kilobytes(8); - } - if (ctx->InitSize_MacrosTable == 0) - { - ctx->InitSize_MacrosTable = gen_kilobytes(8); - } - - if (ctx->Logger == gen_nullptr) - { - ctx->Logger = &fallback_logger; - } - - // Override the current context (user has to put it back if unwanted). - gen__ctx = ctx; - - // Setup the arrays - { - ctx->CodePools = gen_array_init_reserve(gen_Pool, ctx->Allocator_DyanmicContainers, ctx->InitSize_CodePoolsArray); - if (ctx->CodePools == gen_nullptr) - GEN_FATAL("gen::gen_init: Failed to initialize the CodePools array"); - - ctx->StringArenas = gen_array_init_reserve(gen_Arena, ctx->Allocator_DyanmicContainers, ctx->InitSize_StringArenasArray); - if (ctx->StringArenas == gen_nullptr) - GEN_FATAL("gen::gen_init: Failed to initialize the StringArenas array"); - } - // Setup the code pool and code entries arena. - { - gen_Pool gen_code_pool = gen_pool_init(ctx->Allocator_Pool, ctx->CodePool_NumBlocks, gen_size_of(gen_AST)); - if (gen_code_pool.PhysicalStart == gen_nullptr) - GEN_FATAL("gen::gen_init: Failed to initialize the code pool"); - gen_array_append(ctx->CodePools, gen_code_pool); - - // TODO(Ed): Eventually the string arenas needs to be phased out for a dedicated string slab allocator - gen_Arena gen_strbuilder_arena = gen_arena_init_from_allocator(ctx->Allocator_StrCache, ctx->SizePer_StringArena); - if (gen_strbuilder_arena.PhysicalStart == gen_nullptr) - GEN_FATAL("gen::gen_init: Failed to initialize the string arena"); - gen_array_append(ctx->StringArenas, gen_strbuilder_arena); - } - // Setup the gen_hash tables - { - ctx->StrCache = gen_hashtable_init_reserve(gen_StrCached, ctx->Allocator_DyanmicContainers, ctx->InitSize_StrCacheTable); - if (ctx->StrCache.Entries == gen_nullptr) - GEN_FATAL("gen::gen_init: Failed to initialize the StringCache"); - - ctx->Macros = gen_hashtable_init_reserve(gen_Macro, ctx->Allocator_DyanmicContainers, ctx->InitSize_MacrosTable); - if (ctx->Macros.Hashes == gen_nullptr || ctx->Macros.Entries == gen_nullptr) - { - GEN_FATAL("gen::gen_init: Failed to initialize the PreprocessMacros table"); - } - } - - gen_define_constants(); - gen_parser_init(ctx); - - ++context_counter; -} - -void gen_deinit(gen_Context* ctx) -{ - GEN_ASSERT(context_counter); - GEN_ASSERT_MSG(context_counter > 0, "Attempted to gen_deinit a context that for some reason wan't accounted for!"); - gen_usize index = 0; - gen_usize left = gen_array_num(ctx->CodePools); - do - { - gen_Pool* gen_code_pool = &ctx->CodePools[index]; - gen_pool_free(gen_code_pool); - index++; - } while (left--, left); - - index = 0; - left = gen_array_num(ctx->StringArenas); - do - { - gen_Arena* gen_strbuilder_arena = &ctx->StringArenas[index]; - gen_arena_free(gen_strbuilder_arena); - index++; - } while (left--, left); - - gen_hashtable_destroy(ctx->StrCache); - - gen_array_free(ctx->CodePools); - gen_array_free(ctx->StringArenas); - - gen_hashtable_destroy(ctx->Macros); - - left = gen_array_num(ctx->Fallback_AllocatorBuckets); - if (left) - { - index = 0; - do - { - gen_Arena* bucket = &ctx->Fallback_AllocatorBuckets[index]; - gen_arena_free(bucket); - index++; - } while (left--, left); - gen_array_free(ctx->Fallback_AllocatorBuckets); - } - gen_parser_deinit(ctx); - - if (gen__ctx == ctx) - gen__ctx = gen_nullptr; - --context_counter; - - gen_Context wipe = {}; - *ctx = wipe; -} - -gen_Context* gen_get_context() -{ - return gen__ctx; -} - -void gen_reset(gen_Context* ctx) -{ - gen_s32 index = 0; - gen_s32 left = gen_array_num(ctx->CodePools); - do - { - gen_Pool* gen_code_pool = &ctx->CodePools[index]; - gen_pool_clear(gen_code_pool); - index++; - } while (left--, left); - - index = 0; - left = gen_array_num(ctx->StringArenas); - do - { - gen_Arena* gen_strbuilder_arena = &ctx->StringArenas[index]; - gen_strbuilder_arena->TotalUsed = 0; - ; - index++; - } while (left--, left); - - gen_hashtable_clear(ctx->StrCache); - gen_hashtable_clear(ctx->Macros); - gen_define_constants(); -} - -void set_context(gen_Context* new_ctx) -{ - GEN_ASSERT(new_ctx); - gen__ctx = new_ctx; -} - -gen_AllocatorInfo get_cached_str_allocator(gen_s32 gen_str_length) -{ - gen_Arena* last = gen_array_back(gen__ctx->StringArenas); - gen_usize size_req = gen_str_length + sizeof(gen_StrBuilderHeader) + sizeof(char*); - if (last->TotalUsed + gen_scast(gen_ssize, size_req) > last->TotalSize) - { - gen_Arena new_arena = gen_arena_init_from_allocator(gen__ctx->Allocator_StrCache, gen__ctx->SizePer_StringArena); - if (! gen_array_append(gen__ctx->StringArenas, new_arena)) - GEN_FATAL("gen::get_cached_str_allocator: Failed to allocate a new string arena"); - - last = gen_array_back(gen__ctx->StringArenas); - } - return gen_arena_allocator_info(last); -} - -// Will either make or retrive a code string. -gen_StrCached gen_cache_str(gen_Str str) -{ - if (str.Len > gen__ctx->Max_StrCacheLength) - { - // Do not cache the string, just shove into the arena and and return it. - gen_Str result = gen_strbuilder_to_str(gen_strbuilder_make_str(get_cached_str_allocator(str.Len), str)); - return result; - } - gen_u64 key = gen_crc32(str.Ptr, str.Len); - { - gen_StrCached* result = gen_hashtable_get(gen__ctx->StrCache, key); - if (result) - return *result; - } - gen_Str result = gen_strbuilder_to_str(gen_strbuilder_make_str(get_cached_str_allocator(str.Len), str)); - gen_hashtable_set(gen__ctx->StrCache, key, result); - return result; -} - -// Used internally to retireve a gen_Code object form the CodePool. -gen_Code gen_make_code() -{ - gen_Pool* allocator = gen_array_back(gen__ctx->CodePools); - if (allocator->FreeList == gen_nullptr) - { - gen_Pool gen_code_pool = gen_pool_init(gen__ctx->Allocator_Pool, gen__ctx->CodePool_NumBlocks, sizeof(gen_AST)); - - if (gen_code_pool.PhysicalStart == gen_nullptr) - GEN_FATAL("gen::gen_make_code: Failed to allocate a new code pool - CodePool allcoator returned gen_nullptr."); - - if (! gen_array_append(gen__ctx->CodePools, gen_code_pool)) - GEN_FATAL("gen::gen_make_code: Failed to allocate a new code pool - CodePools failed to append new pool."); - - allocator = gen_array_back(gen__ctx->CodePools); - } - gen_Code result = { gen_rcast(gen_AST*, gen_alloc(gen_pool_allocator_info(allocator), sizeof(gen_AST))) }; - gen_mem_set(gen_rcast(void*, gen_cast(gen_AST*, result)), 0, sizeof(gen_AST)); - return result; -} - -gen_Macro* lookup_macro(gen_Str name) -{ - gen_u32 key = gen_crc32(name.Ptr, name.Len); - return gen_hashtable_get(gen__ctx->Macros, key); -} - -void gen_register_macro(gen_Macro macro) -{ - GEN_ASSERT_NOT_NULL(macro.Name.Ptr); - GEN_ASSERT(macro.Name.Len > 0); - gen_u32 key = gen_crc32(macro.Name.Ptr, macro.Name.Len); - macro.Name = gen_cache_str(macro.Name); - gen_hashtable_set(gen__ctx->Macros, key, macro); -} - -void gen_register_macros(gen_s32 num, ...) -{ - GEN_ASSERT(num > 0); - va_list va; - va_start(va, num); - do - { - gen_Macro macro = va_arg(va, gen_Macro); - GEN_ASSERT_NOT_NULL(macro.Name.Ptr); - GEN_ASSERT(macro.Name.Len > 0); - macro.Name = gen_cache_str(macro.Name); - - gen_u32 key = gen_crc32(macro.Name.Ptr, macro.Name.Len); - gen_hashtable_set(gen__ctx->Macros, key, macro); - } while (num--, num > 0); - va_end(va); -} - -void gen_register_macros_arr(gen_s32 num, gen_Macro* macros) -{ - GEN_ASSERT(num > 0); - do - { - gen_Macro macro = *macros; - GEN_ASSERT_NOT_NULL(macro.Name.Ptr); - GEN_ASSERT(macro.Name.Len > 0); - macro.Name = gen_cache_str(macro.Name); - - gen_u32 key = gen_crc32(macro.Name.Ptr, macro.Name.Len); - gen_hashtable_set(gen__ctx->Macros, key, macro); - ++macros; - } while (num--, num > 0); -} - -#pragma region Upfront - -enum OpValidateResult gen_enum_underlying(gen_u32) -{ - OpValResult_Fail, - OpValResult_Global, - OpValResult_Member -}; - -typedef gen_u32 OpValidateResult; - -gen_internal gen_neverinline OpValidateResult - gen_operator__validate(gen_Operator op, gen_CodeParams gen_params_code, gen_CodeTypename ret_type, gen_CodeSpecifiers specifier) -{ - if (op == Op_Invalid) - { - gen_log_failure("gen::gen_def_operator: op cannot be invalid"); - return OpValResult_Fail; - } - -#pragma region Helper Macros -#define check_params() \ - if (! gen_params_code) \ - { \ - gen_log_failure("gen::gen_def_operator: params is null and operator %S requires it", gen_operator_to_str(op)); \ - return OpValResult_Fail; \ - } \ - if (gen_params_code->Type != CT_Parameters) \ - { \ - gen_log_failure("gen::gen_def_operator: params is not of Parameters type - %S", gen_code_debug_str(gen_cast(gen_Code, gen_params_code))); \ - return OpValResult_Fail; \ - } - -#define check_param_eq_ret() \ - if (! is_member_symbol && ! gen_code_is_equal(gen_cast(gen_Code, gen_params_code->ValueType), gen_cast(gen_Code, ret_type))) \ - { \ - gen_log_failure( \ - "gen::gen_def_operator: operator %S requires first parameter to equal return type\n" \ - "param types: %S\n" \ - "return type: %S", \ - gen_operator_to_str(op), \ - gen_code_debug_str(gen_cast(gen_Code, gen_params_code)), \ - gen_code_debug_str(gen_cast(gen_Code, ret_type)) \ - ); \ - return OpValResult_Fail; \ - } -#pragma endregion Helper Macros - - if (! ret_type) - { - gen_log_failure("gen::gen_def_operator: ret_type is null but is required by operator %S", gen_operator_to_str(op)); - } - - if (ret_type->Type != CT_Typename) - { - gen_log_failure( - "gen::gen_def_operator: operator %S - ret_type is not of typename type - %S", - gen_operator_to_str(op), - gen_code_debug_str(gen_cast(gen_Code, ret_type)) - ); - return OpValResult_Fail; - } - - bool is_member_symbol = false; - - switch (op) - { -#define specs(...) gen_num_args(__VA_ARGS__), __VA_ARGS__ - case Op_Assign: - check_params(); - - if (gen_params_code->NumEntries > 1) - { - gen_log_failure( - "gen::gen_def_operator: " - "operator %S does not support non-member definition (more than one parameter provided) - %S", - gen_operator_to_str(op), - gen_code_debug_str(gen_cast(gen_Code, gen_params_code)) - ); - return OpValResult_Fail; - } - - is_member_symbol = true; - break; - - case Op_Assign_Add: - case Op_Assign_Subtract: - case Op_Assign_Multiply: - case Op_Assign_Divide: - case Op_Assign_Modulo: - case Op_Assign_BAnd: - case Op_Assign_BOr: - case Op_Assign_BXOr: - case Op_Assign_LShift: - case Op_Assign_RShift: - check_params(); - - if (gen_params_code->NumEntries == 1) - is_member_symbol = true; - - else - check_param_eq_ret(); - - if (gen_params_code->NumEntries > 2) - { - gen_log_failure( - "gen::gen_def_operator: operator %S may not be defined with more than two parametes - param count; %d\n%S", - gen_operator_to_str(op), - gen_params_code->NumEntries, - gen_code_debug_str(gen_cast(gen_Code, gen_params_code)) - ); - return OpValResult_Fail; - } - break; - - case Op_Increment: - case Op_Decrement: - // If its not set, it just means its a prefix member op. - if (gen_params_code) - { - if (gen_params_code->Type != CT_Parameters) - { - gen_log_failure( - "gen::gen_def_operator: operator %S params code provided is not of Parameters type - %S", - gen_operator_to_str(op), - gen_code_debug_str(gen_cast(gen_Code, gen_params_code)) - ); - return OpValResult_Fail; - } - - switch (gen_params_code->NumEntries) - { - case 1: - if (gen_code_is_equal((gen_Code)gen_params_code->ValueType, (gen_Code)gen_t_int)) - is_member_symbol = true; - - else - check_param_eq_ret(); - break; - - case 2: - check_param_eq_ret(); - - if (! gen_code_is_equal((gen_Code)gen_params_get(gen_params_code, 1), (gen_Code)gen_t_int)) - { - gen_log_failure( - "gen::gen_def_operator: " - "operator %S requires second parameter of non-member definition to be int for post-decrement", - gen_operator_to_str(op) - ); - return OpValResult_Fail; - } - break; - - default: - gen_log_failure( - "gen::gen_def_operator: operator %S recieved unexpected number of parameters recived %d instead of 0-2", - gen_operator_to_str(op), - gen_params_code->NumEntries - ); - return OpValResult_Fail; - } - } - break; - - case Op_Unary_Plus: - case Op_Unary_Minus: - if (! gen_params_code) - is_member_symbol = true; - - else - { - if (gen_params_code->Type != CT_Parameters) - { - gen_log_failure("gen::gen_def_operator: params is not of Parameters type - %S", gen_code_debug_str((gen_Code)gen_params_code)); - return OpValResult_Fail; - } - - if (gen_code_is_equal((gen_Code)gen_params_code->ValueType, (gen_Code)ret_type)) - { - gen_log_failure( - "gen::gen_def_operator: " - "operator %S is non-member symbol yet first paramter does not equal return type\n" - "param type: %S\n" - "return type: %S\n", - gen_code_debug_str((gen_Code)gen_params_code), - gen_code_debug_str((gen_Code)ret_type) - ); - return OpValResult_Fail; - } - - if (gen_params_code->NumEntries > 1) - { - gen_log_failure( - "gen::gen_def_operator: operator %S may not have more than one parameter - param count: %d", - gen_operator_to_str(op), - gen_params_code->NumEntries - ); - return OpValResult_Fail; - } - } - break; - - case Op_BNot: - { - // Some compilers let you do this... -#if 0 - if ( ! ret_type.is_equal( gen_t_bool) ) - { - gen_log_failure( "gen::gen_def_operator: operator %S return type is not a boolean - %S", gen_operator_to_str(op) gen_code_debug_str(gen_params_code) ); - return OpValidateResult::Fail; - } -#endif - - if (! gen_params_code) - is_member_symbol = true; - - else - { - if (gen_params_code->Type != CT_Parameters) - { - gen_log_failure( - "gen::gen_def_operator: operator %S - params is not of Parameters type - %S", - gen_operator_to_str(op), - gen_code_debug_str((gen_Code)gen_params_code) - ); - return OpValResult_Fail; - } - - if (gen_params_code->NumEntries > 1) - { - gen_log_failure( - "gen::gen_def_operator: operator %S may not have more than one parameter - param count: %d", - gen_operator_to_str(op), - gen_params_code->NumEntries - ); - return OpValResult_Fail; - } - } - break; - } - - case Op_Add: - case Op_Subtract: - case Op_Multiply: - case Op_Divide: - case Op_Modulo: - case Op_BAnd: - case Op_BOr: - case Op_BXOr: - case Op_LShift: - case Op_RShift: - check_params(); - - switch (gen_params_code->NumEntries) - { - case 1: - is_member_symbol = true; - break; - - case 2: - // This is allowed for arithemtic operators - // if ( ! gen_code_is_equal((gen_Code)gen_params_code->ValueType, (gen_Code)ret_type ) ) - // { - // gen_log_failure("gen::gen_def_operator: " - // "operator %S is non-member symbol yet first paramter does not equal return type\n" - // "param type: %S\n" - // "return type: %S\n" - // , gen_code_debug_str((gen_Code)gen_params_code) - // , gen_code_debug_str((gen_Code)ret_type) - // ); - // return OpValResult_Fail; - // } - break; - - default: - gen_log_failure( - "gen::gen_def_operator: operator %S recieved unexpected number of paramters recived %d instead of 0-2", - gen_operator_to_str(op), - gen_params_code->NumEntries - ); - return OpValResult_Fail; - } - break; - - case Op_UnaryNot: - if (! gen_params_code) - is_member_symbol = true; - - else - { - if (gen_params_code->Type != CT_Parameters) - { - gen_log_failure( - "gen::gen_def_operator: operator %S - params is not of Parameters type - %S", - gen_operator_to_str(op), - gen_code_debug_str((gen_Code)gen_params_code) - ); - return OpValResult_Fail; - } - - if (gen_params_code->NumEntries != 1) - { - gen_log_failure( - "gen::gen_def_operator: operator %S recieved unexpected number of paramters recived %d instead of 0-1", - gen_operator_to_str(op), - gen_params_code->NumEntries - ); - return OpValResult_Fail; - } - } - - if (! gen_code_is_equal((gen_Code)ret_type, (gen_Code)gen_t_bool)) - { - gen_log_failure( - "gen::gen_def_operator: operator %S return type must be of type bool - %S", - gen_operator_to_str(op), - gen_code_debug_str((gen_Code)ret_type) - ); - return OpValResult_Fail; - } - break; - - case Op_LAnd: - case Op_LOr: - case Op_LEqual: - case Op_LNot: - case Op_Lesser: - case Op_Greater: - case Op_LesserEqual: - case Op_GreaterEqual: - check_params(); - - switch (gen_params_code->NumEntries) - { - case 1: - is_member_symbol = true; - break; - - case 2: - break; - - default: - gen_log_failure( - "gen::gen_def_operator: operator %S recieved unexpected number of paramters recived %d instead of 1-2", - gen_operator_to_str(op), - gen_params_code->NumEntries - ); - return OpValResult_Fail; - } - break; - - case Op_Indirection: - case Op_AddressOf: - case Op_MemberOfPointer: - if (gen_params_code && gen_params_code->NumEntries > 1) - { - gen_log_failure( - "gen::gen_def_operator: operator %S recieved unexpected number of paramters recived %d instead of 0-1", - gen_operator_to_str(op), - gen_params_code->NumEntries - ); - return OpValResult_Fail; - } - else - { - is_member_symbol = true; - } - break; - - case Op_PtrToMemOfPtr: - if (gen_params_code) - { - gen_log_failure( - "gen::gen_def_operator: operator %S expects no paramters - %S", - gen_operator_to_str(op), - gen_code_debug_str((gen_Code)gen_params_code) - ); - return OpValResult_Fail; - } - break; - - case Op_Subscript: - case Op_FunctionCall: - case Op_Comma: - check_params(); - break; - - case Op_New: - case Op_Delete: - // This library doesn't support validating new and delete yet. - break; -#undef specs - } - - return is_member_symbol ? OpValResult_Member : OpValResult_Global; -#undef check_params -#undef check_ret_type -#undef check_param_eq_ret -} - -gen_forceinline bool name__check(char const* context, gen_Str name) -{ - if (name.Len <= 0) - { - gen_log_failure("gen::%s: Invalid name length provided - %d", name.Len); - return false; - } - if (name.Ptr == gen_nullptr) - { - gen_log_failure("gen::%s: name is null"); - return false; - } - return true; -} - -#define name_check(context, name) name__check(#context, name) - -gen_forceinline bool null__check(char const* context, char const* gen_code_id, gen_Code code) -{ - if (code == gen_nullptr) - { - gen_log_failure("gen::%s: %s provided is null", context, gen_code_id); - return false; - } - return true; -} - -#define null_check(context, code) null__check(#context, #code, gen_cast(gen_Code, code)) - -/* -The implementation of the upfront gen_constructor_s involves doing three things: -* Validate the arguments given to construct the intended type of gen_AST is valid. -* Construct said gen_AST type. -* Lock the gen_AST (set to readonly) and return the valid object. - -If any of the validation fails, it triggers a call to gen_log_failure with as much info the give the user so that they can hopefully -identify the issue without having to debug too much (at least they can debug though...) - -The largest of the functions is related to operator overload definitions. -The library validates a good protion of their form and thus the argument processing for is quite a gen_bit. -*/ -gen_CodeAttributes gen_def_attributes(gen_Str content) -{ - if (content.Len <= 0 || content.Ptr == gen_nullptr) - { - gen_log_failure("gen::gen_def_attributes: Invalid attributes provided"); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_Code result = gen_make_code(); - result->Type = CT_PlatformAttributes; - result->Name = gen_cache_str(content); - result->Content = result->Name; - return (gen_CodeAttributes)result; -} - -gen_CodeComment gen_def_comment(gen_Str content) -{ - if (content.Len <= 0 || content.Ptr == gen_nullptr) - { - gen_log_failure("gen::gen_def_comment: Invalid comment provided:"); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - gen_StrBuilder cmt_formatted = gen_strbuilder_make_reserve(gen__ctx->Allocator_Temp, gen_kilobytes(1)); - char const* end = content.Ptr + content.Len; - char const* scanner = content.Ptr; - gen_s32 curr = 0; - do - { - char const* next = scanner; - gen_s32 length = 0; - while (next != end && scanner[length] != '\n') - { - next = scanner + length; - length++; - } - length++; - - gen_strbuilder_append_fmt(&cmt_formatted, "//%.*s", length, scanner); - scanner += length; - } while (scanner <= end); - - if (*gen_strbuilder_back(cmt_formatted) != '\n') - gen_strbuilder_append_str(&cmt_formatted, gen_txt("\n")); - - gen_Str name = gen_strbuilder_to_str(cmt_formatted); - - gen_Code result = gen_make_code(); - result->Type = CT_Comment; - result->Name = gen_cache_str(name); - result->Content = result->Name; - - gen_strbuilder_free(&cmt_formatted); - - return (gen_CodeComment)result; -} - -gen_CodeConstructor gen_def__constructor(gen_Opts_def_constructor* opt) -{ - gen_Opts_def_constructor p = get_optional(opt); - - if (p.params && p.params->Type != CT_Parameters) - { - gen_log_failure("gen::gen_def_constructor: params must be of Parameters type - %s", gen_code_debug_str((gen_Code)p.params)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - gen_CodeConstructor result = (gen_CodeConstructor)gen_make_code(); - if (p.params) - { - result->Params = p.params; - } - if (p.initializer_list) - { - result->InitializerList = p.initializer_list; - } - if (p.body) - { - switch (p.body->Type) - { - case CT_Function_Body: - case CT_Untyped: - break; - - default: - gen_log_failure("gen::gen_def_constructor: body must be either of Function_Body or Untyped type - %s", gen_code_debug_str(p.body)); - return gen_InvalidCode; - } - - result->Type = CT_Constructor; - result->Body = p.body; - } - else - { - result->Type = CT_Constructor_Fwd; - } - return result; -} - -gen_CodeClass gen_def__class(gen_Str name, gen_Opts_def_struct* opt) -{ - gen_Opts_def_struct p = get_optional(opt); - - if (! name_check(gen_def_class, name)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.attributes && p.attributes->Type != CT_PlatformAttributes) - { - gen_log_failure("gen::gen_def_class: attributes was not a 'PlatformAttributes' type: %s", gen_code_debug_str(p.attributes)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.parent && (p.parent->Type != CT_Class && p.parent->Type != CT_Struct && p.parent->Type != CT_Typename && p.parent->Type != CT_Untyped)) - { - gen_log_failure("gen::gen_def_class: parent provided is not type 'Class', 'Struct', 'Typeanme', or 'Untyped': %s", gen_code_debug_str(p.parent)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - gen_CodeClass result = (gen_CodeClass)gen_make_code(); - result->Name = gen_cache_str(name); - result->ModuleFlags = p.mflags; - result->Attributes = p.attributes; - result->Specs = p.specifiers; - result->ParentAccess = p.parent_access; - result->ParentType = p.parent; - if (p.body) - { - switch (p.body->Type) - { - case CT_Class_Body: - case CT_Untyped: - break; - - default: - gen_log_failure("gen::gen_def_class: body must be either of Class_Body or Untyped type - %s", gen_code_debug_str(p.body)); - return gen_InvalidCode; - } - - result->Type = CT_Class; - result->Body = p.body; - result->Body->Parent = gen_cast(gen_Code, result); - } - else - { - result->Type = CT_Class_Fwd; - } - for (gen_s32 idx = 0; idx < p.num_interfaces; idx++) - { - gen_class_add_interface(result, p.interfaces[idx]); - } - return result; -} - -gen_CodeDefine gen_def__define(gen_Str name, gen_MacroType type, gen_Opts_def_define* opt) -{ - gen_Opts_def_define p = get_optional(opt); - - if (! name_check(gen_def_define, name)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodeDefine result = (gen_CodeDefine)gen_make_code(); - result->Type = CT_Preprocess_Define; - result->Name = gen_cache_str(name); - result->Params = p.params; - if (p.content.Len <= 0 || p.content.Ptr == gen_nullptr) - result->Body = gen_untyped_str(gen_txt("\n")); - else - result->Body = gen_untyped_str(gen_strbuilder_to_str(gen_strbuilder_fmt_buf(gen__ctx->Allocator_Temp, "%S\n", p.content))); - - gen_b32 register_define = ! p.dont_register_to_preprocess_macros; - if (register_define) - { - gen_Macro gen_macro_entry = { result->Name, type, p.flags }; - gen_register_macro(gen_macro_entry); - } - return result; -} - -gen_CodeDestructor gen_def__destructor(gen_Opts_def_destructor* opt) -{ - gen_Opts_def_destructor p = get_optional(opt); - - if (p.specifiers && p.specifiers->Type != CT_Specifiers) - { - gen_log_failure("gen::gen_def_destructor: specifiers was not a 'Specifiers' type: %s", gen_code_debug_str(p.specifiers)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - gen_CodeDestructor result = (gen_CodeDestructor)gen_make_code(); - result->Specs = p.specifiers; - if (p.body) - { - switch (p.body->Type) - { - case CT_Function_Body: - case CT_Untyped: - break; - - default: - gen_log_failure("gen::gen_def_destructor: body must be either of Function_Body or Untyped type - %s", gen_code_debug_str(p.body)); - return gen_InvalidCode; - } - - result->Type = CT_Destructor; - result->Body = p.body; - } - else - { - result->Type = CT_Destructor_Fwd; - } - return result; -} - -gen_CodeEnum gen_def__enum(gen_Str name, gen_Opts_def_enum* opt) -{ - gen_Opts_def_enum p = get_optional(opt); - - if (! name_check(gen_def_enum, name)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.type && p.type->Type != CT_Typename) - { - gen_log_failure("gen::gen_def_enum: enum underlying type provided was not of type Typename: %s", gen_code_debug_str(p.type)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.attributes && p.attributes->Type != CT_PlatformAttributes) - { - gen_log_failure("gen::gen_def_enum: attributes was not a 'PlatformAttributes' type: %s", gen_code_debug_str(p.attributes)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - gen_CodeEnum result = (gen_CodeEnum)gen_make_code(); - result->Name = gen_cache_str(name); - result->ModuleFlags = p.mflags; - if (p.body) - { - switch (p.body->Type) - { - case CT_Enum_Body: - case CT_Untyped: - break; - - default: - gen_log_failure("gen::gen_def_enum: body must be of Enum_Body or Untyped type %s", gen_code_debug_str(p.body)); - return gen_InvalidCode; - } - - result->Type = p.specifier == EnumDecl_Class ? CT_Enum_Class : CT_Enum; - - result->Body = p.body; - } - else - { - result->Type = p.specifier == EnumDecl_Class ? CT_Enum_Class_Fwd : CT_Enum_Fwd; - } - result->Attributes = p.attributes; - - if (p.type) - { - result->UnderlyingType = p.type; - } - else if (p.type_macro) - { - result->UnderlyingTypeMacro = p.type_macro; - } - else if (result->Type != CT_Enum_Class_Fwd && result->Type != CT_Enum_Fwd) - { - gen_log_failure("gen::gen_def_enum: enum forward declaration must have an underlying type"); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - return result; -} - -gen_CodeExec gen_def_execution(gen_Str content) -{ - if (content.Len <= 0 || content.Ptr == gen_nullptr) - { - gen_log_failure("gen::gen_def_execution: Invalid execution provided"); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodeExec result = (gen_CodeExec)gen_make_code(); - result->Type = CT_Execution; - result->Content = gen_cache_str(content); - return result; -} - -gen_CodeExtern gen_def_extern_link(gen_Str name, gen_CodeBody body) -{ - if (! name_check(gen_def_extern_link, name) || ! null_check(gen_def_extern_link, body)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (body->Type != CT_Extern_Linkage_Body && body->Type != CT_Untyped) - { - gen_log_failure("gen::gen_def_extern_linkage: body is not of gen_extern_linkage or untyped type %s", gen_code_debug_str(body)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodeExtern result = (gen_CodeExtern)gen_make_code(); - result->Type = CT_Extern_Linkage; - result->Name = gen_cache_str(name); - result->Body = body; - return result; -} - -gen_CodeFriend gen_def_friend(gen_Code declaration) -{ - if (! null_check(gen_def_friend, declaration)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - switch (declaration->Type) - { - case CT_Class_Fwd: - case CT_Function_Fwd: - case CT_Operator_Fwd: - case CT_Struct_Fwd: - case CT_Class: - case CT_Function: - case CT_Operator: - case CT_Struct: - break; - - default: - gen_log_failure("gen::gen_def_friend: requires declartion to have class, function, operator, or struct - %s", gen_code_debug_str(declaration)); - return gen_InvalidCode; - } - gen_CodeFriend result = (gen_CodeFriend)gen_make_code(); - result->Type = CT_Friend; - result->Declaration = declaration; - return result; -} - -gen_CodeFn gen_def__function(gen_Str name, gen_Opts_def_function* opt) -{ - gen_Opts_def_function p = get_optional(opt); - - if (! name_check(gen_def_function, name)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.params && p.params->Type != CT_Parameters) - { - gen_log_failure("gen::gen_def_function: params was not a `Parameters` type: %s", gen_code_debug_str(p.params)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.ret_type && p.ret_type->Type != CT_Typename) - { - gen_log_failure("gen::gen_def_function: ret_type was not a Typename: %s", gen_code_debug_str(p.ret_type)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.specs && p.specs->Type != CT_Specifiers) - { - gen_log_failure("gen::gen_def_function: specifiers was not a `Specifiers` type: %s", gen_code_debug_str(p.specs)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.attrs && p.attrs->Type != CT_PlatformAttributes) - { - gen_log_failure("gen::gen_def_function: attributes was not a `PlatformAttributes` type: %s", gen_code_debug_str(p.attrs)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - gen_CodeFn result = (gen_CodeFn)gen_make_code(); - result->Name = gen_cache_str(name); - result->ModuleFlags = p.mflags; - if (p.body) - { - switch (p.body->Type) - { - case CT_Function_Body: - case CT_Execution: - case CT_Untyped: - break; - - default: - { - gen_log_failure("gen::gen_def_function: body must be either of Function_Body, Execution, or Untyped type. %s", gen_code_debug_str(p.body)); - return gen_InvalidCode; - } - } - result->Type = CT_Function; - result->Body = p.body; - } - else - { - result->Type = CT_Function_Fwd; - } - result->Attributes = p.attrs; - result->Specs = p.specs; - result->Params = p.params; - result->ReturnType = p.ret_type ? p.ret_type : gen_t_void; - return result; -} - -gen_CodeInclude gen_def__include(gen_Str path, gen_Opts_def_include* opt) -{ - gen_Opts_def_include p = get_optional(opt); - - if (path.Len <= 0 || path.Ptr == gen_nullptr) - { - gen_log_failure("gen::gen_def_include: Invalid path provided - %d"); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_StrBuilder content = p.foreign ? gen_strbuilder_fmt_buf(gen__ctx->Allocator_Temp, "<%.*s>", path.Len, path.Ptr) - : gen_strbuilder_fmt_buf(gen__ctx->Allocator_Temp, "\"%.*s\"", path.Len, path.Ptr); - - gen_CodeInclude result = (gen_CodeInclude)gen_make_code(); - result->Type = CT_Preprocess_Include; - result->Name = gen_cache_str(gen_strbuilder_to_str(content)); - result->Content = result->Name; - return result; -} - -gen_CodeModule gen_def__module(gen_Str name, gen_Opts_def_module* opt) -{ - gen_Opts_def_module p = get_optional(opt); - - if (! name_check(gen_def_module, name)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodeModule result = (gen_CodeModule)gen_make_code(); - result->Type = CT_Module; - result->Name = gen_cache_str(name); - result->ModuleFlags = p.mflags; - return result; -} - -gen_CodeNS gen_def__namespace(gen_Str name, gen_CodeBody body, gen_Opts_def_namespace* opt) -{ - gen_Opts_def_namespace p = get_optional(opt); - - if (! name_check(gen_def_namespace, name)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (! null_check(gen_def_namespace, body)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (body && body->Type != CT_Namespace_Body && body->Type != CT_Untyped) - { - gen_log_failure("gen::gen_def_namespace: body is not of namespace or untyped type %s", gen_code_debug_str(body)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodeNS result = (gen_CodeNS)gen_make_code(); - result->Type = CT_Namespace; - result->Name = gen_cache_str(name); - result->ModuleFlags = p.mflags; - result->Body = body; - return result; -} - -gen_CodeOperator gen_def__operator(gen_Operator op, gen_Str nspace, gen_Opts_def_operator* opt) -{ - gen_Opts_def_operator p = get_optional(opt); - - if (p.attributes && p.attributes->Type != CT_PlatformAttributes) - { - gen_log_failure("gen::gen_def_operator: PlatformAttributes was provided but its not of attributes type: %s", gen_code_debug_str(p.attributes)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.specifiers && p.specifiers->Type != CT_Specifiers) - { - gen_log_failure("gen::gen_def_operator: Specifiers was provided but its not of specifiers type: %s", gen_code_debug_str(p.specifiers)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - OpValidateResult check_result = gen_operator__validate(op, p.params, p.ret_type, p.specifiers); - if (check_result == OpValResult_Fail) - { - return gen_InvalidCode; - } - - char const* name = gen_nullptr; - - gen_Str op_str = gen_operator_to_str(op); - if (nspace.Len > 0) - name = gen_c_str_fmt_buf("%.*soperator %.*s", nspace.Len, nspace.Ptr, op_str.Len, op_str.Ptr); - else - name = gen_c_str_fmt_buf("operator %.*s", op_str.Len, op_str.Ptr); - - gen_Str name_resolved = { name, gen_c_str_len(name) }; - - gen_CodeOperator result = (gen_CodeOperator)gen_make_code(); - result->Name = gen_cache_str(name_resolved); - result->ModuleFlags = p.mflags; - result->Op = op; - if (p.body) - { - switch (p.body->Type) - { - case CT_Function_Body: - case CT_Execution: - case CT_Untyped: - break; - - default: - { - gen_log_failure("gen::gen_def_operator: body must be either of Function_Body, Execution, or Untyped type. %s", gen_code_debug_str(p.body)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - } - - result->Type = check_result == OpValResult_Global ? CT_Operator : CT_Operator_Member; - - result->Body = p.body; - } - else - { - result->Type = check_result == OpValResult_Global ? CT_Operator_Fwd : CT_Operator_Member_Fwd; - } - result->Attributes = p.attributes; - result->Specs = p.specifiers; - result->ReturnType = p.ret_type; - result->Params = p.params; - return result; -} - -gen_CodeOpCast gen_def__operator_cast(gen_CodeTypename type, gen_Opts_def_operator_cast* opt) -{ - gen_Opts_def_operator_cast p = get_optional(opt); - - if (! null_check(gen_def_operator_cast, type)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (type->Type != CT_Typename) - { - gen_log_failure("gen::gen_def_operator_cast: type is not a typename - %s", gen_code_debug_str(type)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - gen_CodeOpCast result = (gen_CodeOpCast)gen_make_code(); - if (p.body) - { - result->Type = CT_Operator_Cast; - - if (p.body->Type != CT_Function_Body && p.body->Type != CT_Execution) - { - gen_log_failure("gen::gen_def_operator_cast: body is not of function body or execution type - %s", gen_code_debug_str(p.body)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - result->Body = p.body; - } - else - { - result->Type = CT_Operator_Cast_Fwd; - } - result->Specs = p.specs; - result->ValueType = type; - return result; -} - -gen_CodeParams gen_def__param(gen_CodeTypename type, gen_Str name, gen_Opts_def_param* opt) -{ - gen_Opts_def_param p = get_optional(opt); - - if (! name_check(gen_def_param, name) || ! null_check(gen_def_param, type)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (type->Type != CT_Typename) - { - gen_log_failure("gen::gen_def_param: type is not a typename - %s", gen_code_debug_str(type)); - return gen_InvalidCode; - } - if (p.value && p.value->Type != CT_Untyped) - { - gen_log_failure("gen::gen_def_param: value is not untyped - %s", gen_code_debug_str(p.value)); - return gen_InvalidCode; - } - gen_CodeParams result = (gen_CodeParams)gen_make_code(); - result->Type = CT_Parameters; - result->Name = gen_cache_str(name); - result->ValueType = type; - result->Value = p.value; - result->NumEntries++; - return result; -} - -gen_CodePragma gen_def_pragma(gen_Str directive) -{ - if (directive.Len <= 0 || directive.Ptr == gen_nullptr) - { - gen_log_failure("gen::gen_def_comment: Invalid comment provided:"); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodePragma result = (gen_CodePragma)gen_make_code(); - result->Type = CT_Preprocess_Pragma; - result->Content = gen_cache_str(directive); - return result; -} - -gen_CodePreprocessCond gen_def_preprocess_cond(gen_EPreprocessCOnd type, gen_Str expr) -{ - if (expr.Len <= 0 || expr.Ptr == gen_nullptr) - { - gen_log_failure("gen::gen_def_comment: Invalid comment provided:"); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodePreprocessCond result = (gen_CodePreprocessCond)gen_make_code(); - result->Content = gen_cache_str(expr); - switch (type) - { - case PreprocessCond_If: - result->Type = CT_Preprocess_If; - break; - case PreprocessCond_IfDef: - result->Type = CT_Preprocess_IfDef; - break; - case PreprocessCond_IfNotDef: - result->Type = CT_Preprocess_IfNotDef; - break; - case PreprocessCond_ElIf: - result->Type = CT_Preprocess_ElIf; - break; - } - return result; -} - -gen_CodeSpecifiers gen_def_specifier(gen_Specifier spec) -{ - gen_CodeSpecifiers result = (gen_CodeSpecifiers)gen_make_code(); - result->Type = CT_Specifiers; - gen_specifiers_append(result, spec); - return result; -} - -gen_CodeStruct gen_def__struct(gen_Str name, gen_Opts_def_struct* opt) -{ - gen_Opts_def_struct p = get_optional(opt); - - if (p.attributes && p.attributes->Type != CT_PlatformAttributes) - { - gen_log_failure("gen::gen_def_struct: attributes was not a `PlatformAttributes` type - %s", gen_code_debug_str(gen_cast(gen_Code, p.attributes))); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.parent && p.parent->Type != CT_Typename) - { - gen_log_failure("gen::gen_def_struct: parent was not a `Struct` type - %s", gen_code_debug_str(p.parent)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.body && p.body->Type != CT_Struct_Body) - { - gen_log_failure("gen::gen_def_struct: body was not a Struct_Body type - %s", gen_code_debug_str(p.body)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - gen_CodeStruct result = (gen_CodeStruct)gen_make_code(); - result->ModuleFlags = p.mflags; - if (name.Len) - result->Name = gen_cache_str(name); - - if (p.body) - { - result->Type = CT_Struct; - result->Body = p.body; - } - else - { - result->Type = CT_Struct_Fwd; - } - result->Attributes = p.attributes; - result->Specs = p.specifiers; - result->ParentAccess = p.parent_access; - result->ParentType = p.parent; - - for (gen_s32 idx = 0; idx < p.num_interfaces; idx++) - { - gen_struct_add_interface(result, p.interfaces[idx]); - } - return result; -} - -gen_CodeTemplate gen_def__template(gen_CodeParams params, gen_Code declaration, gen_Opts_def_template* opt) -{ - gen_Opts_def_template p = get_optional(opt); - - if (! null_check(gen_def_template, declaration)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (params && params->Type != CT_Parameters) - { - gen_log_failure("gen::gen_def_template: params is not of parameters type - %s", gen_code_debug_str(params)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - switch (declaration->Type) - { - case CT_Class: - case CT_Function: - case CT_Struct: - case CT_Variable: - case CT_Using: - break; - - default: - gen_log_failure( - "gen::gen_def_template: declaration is not of class, function, struct, variable, or using type - %s", - gen_code_debug_str(declaration) - ); - } - gen_CodeTemplate result = (gen_CodeTemplate)gen_make_code(); - result->Type = CT_Template; - result->ModuleFlags = p.mflags; - result->Params = params; - result->Declaration = declaration; - return result; -} - -gen_CodeTypename gen_def__type(gen_Str name, gen_Opts_def_type* opt) -{ - gen_Opts_def_type p = get_optional(opt); - - if (! name_check(gen_def_type, name)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - 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)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.specifiers && p.specifiers->Type != CT_Specifiers) - { - gen_log_failure("gen::gen_def_type: specifiers is not of specifiers type - %s", gen_code_debug_str((gen_Code)p.specifiers)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - 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.gen_array_expr)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodeTypename result = (gen_CodeTypename)gen_make_code(); - result->Name = gen_cache_str(name); - result->Type = CT_Typename; - result->Attributes = p.attributes; - result->Specs = p.specifiers; - result->ArrExpr = p.gen_array_expr; - result->TypeTag = p.type_tag; - return result; -} - -gen_CodeTypedef gen_def__typedef(gen_Str name, gen_Code type, gen_Opts_def_typedef* opt) -{ - gen_Opts_def_typedef p = get_optional(opt); - - if (! null_check(gen_def_typedef, type)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - switch (type->Type) - { - case CT_Class: - case CT_Class_Fwd: - case CT_Enum: - case CT_Enum_Fwd: - case CT_Enum_Class: - case CT_Enum_Class_Fwd: - case CT_Function_Fwd: - case CT_Struct: - case CT_Struct_Fwd: - case CT_Union: - case CT_Typename: - break; - default: - gen_log_failure( - "gen::gen_def_typedef: type was not a Class, Enum, Function Forward, Struct, Typename, or Union - %s", - gen_code_debug_str((gen_Code)type) - ); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.attributes && p.attributes->Type != CT_PlatformAttributes) - { - gen_log_failure("gen::gen_def_typedef: attributes was not a PlatformAttributes - %s", gen_code_debug_str((gen_Code)p.attributes)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - // Registering the type. - gen_CodeTypename registered_type = gen_def_type(name); - if (! registered_type) - { - gen_log_failure("gen::gen_def_typedef: failed to register type"); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - gen_CodeTypedef result = (gen_CodeTypedef)gen_make_code(); - result->Type = CT_Typedef; - result->ModuleFlags = p.mflags; - result->UnderlyingType = type; - - if (name.Len <= 0) - { - if (type->Type != CT_Untyped) - { - gen_log_failure("gen::gen_def_typedef: name was empty and type was not untyped (indicating its a function typedef) - %s", gen_code_debug_str(type)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - result->Name = gen_cache_str(type->Name); - result->IsFunction = true; - } - else - { - result->Name = gen_cache_str(name); - result->IsFunction = false; - } - return result; -} - -gen_CodeUnion gen_def__union(gen_Str name, gen_CodeBody body, gen_Opts_def_union* opt) -{ - gen_Opts_def_union p = get_optional(opt); - - if (! null_check(gen_def_union, body)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (body->Type != CT_Union_Body) - { - gen_log_failure("gen::gen_def_union: body was not a Union_Body type - %s", gen_code_debug_str(body)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.attributes && p.attributes->Type != CT_PlatformAttributes) - { - gen_log_failure("gen::gen_def_union: attributes was not a PlatformAttributes type - %s", gen_code_debug_str(p.attributes)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodeUnion result = (gen_CodeUnion)gen_make_code(); - result->ModuleFlags = p.mflags; - result->Type = CT_Union; - result->Body = body; - result->Attributes = p.attributes; - if (name.Ptr) - result->Name = gen_cache_str(name); - return result; -} - -gen_CodeUsing gen_def__using(gen_Str name, gen_CodeTypename type, gen_Opts_def_using* opt) -{ - gen_Opts_def_using p = get_optional(opt); - - if (! name_check(gen_def_using, name) || null_check(gen_def_using, type)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - - gen_CodeTypename register_type = gen_def_type(name); - if (! register_type) - { - gen_log_failure("gen::gen_def_using: failed to register type"); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.attributes && p.attributes->Type != CT_PlatformAttributes) - { - gen_log_failure("gen::gen_def_using: attributes was not a PlatformAttributes type - %s", gen_code_debug_str(p.attributes)); - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodeUsing result = (gen_CodeUsing)gen_make_code(); - result->Name = gen_cache_str(name); - result->ModuleFlags = p.mflags; - result->Type = CT_Using; - result->UnderlyingType = type; - result->Attributes = p.attributes; - return result; -} - -gen_CodeUsing gen_def_using_namespace(gen_Str name) -{ - if (! name_check(gen_def_using_namespace, name)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - gen_CodeUsing result = (gen_CodeUsing)gen_make_code(); - result->Name = gen_cache_str(name); - result->Type = CT_Using_Namespace; - return result; -} - -gen_CodeVar gen_def__variable(gen_CodeTypename type, gen_Str name, gen_Opts_def_variable* opt) -{ - gen_Opts_def_variable p = get_optional(opt); - - if (! name_check(gen_def_variable, name) || ! null_check(gen_def_variable, type)) - { - GEN_DEBUG_TRAP(); - return gen_InvalidCode; - } - if (p.attributes && p.attributes->Type != CT_PlatformAttributes) - { - gen_log_failure("gen::gen_def_variable: attributes was not a `PlatformAttributes` type - %s", gen_code_debug_str(p.attributes)); - return gen_InvalidCode; - } - if (p.specifiers && p.specifiers->Type != CT_Specifiers) - { - gen_log_failure("gen::gen_def_variable: specifiers was not a `Specifiers` type - %s", gen_code_debug_str(p.specifiers)); - return gen_InvalidCode; - } - if (type->Type != CT_Typename) - { - gen_log_failure("gen::gen_def_variable: type was not a Typename - %s", gen_code_debug_str(type)); - return gen_InvalidCode; - } - if (p.value && p.value->Type != CT_Untyped) - { - gen_log_failure("gen::gen_def_variable: value was not a `Untyped` type - %s", gen_code_debug_str(p.value)); - return gen_InvalidCode; - } - gen_CodeVar result = (gen_CodeVar)gen_make_code(); - result->Name = gen_cache_str(name); - result->Type = CT_Variable; - result->ModuleFlags = p.mflags; - result->ValueType = type; - result->Attributes = p.attributes; - result->Specs = p.specifiers; - result->Value = p.value; - return result; -} - -#pragma region Helper Macros for gen_def_**_body functions - -#define gen_def_body_start(Name_) \ - if (num <= 0) \ - { \ - gen_log_failure("gen::" gen_stringize(Name_) ": num cannot be zero or negative"); \ - return gen_InvalidCode; \ - } - -#define gen_def_body_code_array_start(Name_) \ - if (num <= 0) \ - { \ - gen_log_failure("gen::" gen_stringize(Name_) ": num cannot be zero or negative"); \ - return gen_InvalidCode; \ - } \ - if (codes == gen_nullptr) \ - { \ - gen_log_failure("gen::" gen_stringize(Name_) " : Provided a null array of codes"); \ - return gen_InvalidCode; \ - } - -#pragma endregion Helper Macros for gen_def_** _body functions - -gen_CodeBody gen_def_class_body(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_class_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Class_Body; - - va_list va; - va_start(va, num); - do - { - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_Code entry = gen_pcast(gen_Code, pod); - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_class_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_CLASS_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_class_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - va_end(va); - - return result; -} - -gen_CodeBody gen_def_class_body_arr(gen_s32 num, gen_Code* codes) -{ - gen_def_body_code_array_start(gen_def_class_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Function_Body; - do - { - gen_Code entry = *codes; - codes++; - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_class_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_CLASS_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_class_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - - return result; -} - -gen_CodeDefineParams gen_def_define_params(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_define_params); - - va_list va; - va_start(va, num); - - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_CodeDefineParams param = gen_pcast(gen_CodeDefineParams, pod); - - null_check(gen_def_define_params, param); - if (param->Type != CT_Parameters_Define) - { - gen_log_failure("gen::gen_def_define_params: param %d is not a parameter for a preprocessor define", num - num + 1); - return gen_InvalidCode; - } - - gen_CodeDefineParams result = (gen_CodeDefineParams)gen_code_duplicate(param); - while (--num) - { - pod = va_arg(va, gen_Code_POD); - param = gen_pcast(gen_CodeDefineParams, pod); - if (param->Type != CT_Parameters_Define) - { - gen_log_failure("gen::gen_def_define_params: param %d is not a parameter for a preprocessor define", num - num + 1); - return gen_InvalidCode; - } - gen_define_params_append(result, param); - } - va_end(va); - - return result; -} - -gen_CodeDefineParams gen_def_define_params_arr(gen_s32 num, gen_CodeDefineParams* codes) -{ - gen_def_body_code_array_start(gen_def_define_params); - -#define check_current(current) \ - if (current == gen_nullptr) \ - { \ - gen_log_failure("gen::gen_def_define_params: Provide a null code in codes array"); \ - return gen_InvalidCode; \ - } \ - if (current->Type != CT_Parameters_Define) \ - { \ - gen_log_failure( \ - "gen::gen_def_define_params: gen_Code in coes array is not of paramter for preprocessor define type - %s", \ - gen_code_debug_str(current) \ - ); \ - return gen_InvalidCode; \ - } - gen_CodeDefineParams current = (gen_CodeDefineParams)gen_code_duplicate(*codes); - check_current(current); - - gen_CodeDefineParams result = (gen_CodeDefineParams)gen_make_code(); - result->Name = current->Name; - result->Type = current->Type; - while (codes++, current = *codes, num--, num > 0) - { - check_current(current); - gen_define_params_append(result, current); - } -#undef check_current - - return result; -} - -gen_CodeBody gen_def_enum_body(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_enum_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Enum_Body; - - va_list va; - va_start(va, num); - do - { - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_Code entry = gen_pcast(gen_Code, pod); - if (! entry) - { - gen_log_failure("gen::gen_def_enum_body: Provided a null entry"); - return gen_InvalidCode; - } - if (entry->Type != CT_Untyped && entry->Type != CT_Comment) - { - gen_log_failure("gen::gen_def_enum_body: Entry type is not allowed - %s. Must be of untyped or comment type.", gen_code_debug_str(entry)); - return gen_InvalidCode; - } - gen_body_append(result, entry); - } while (num--, num > 0); - va_end(va); - - return (gen_CodeBody)result; -} - -gen_CodeBody gen_def_enum_body_arr(gen_s32 num, gen_Code* codes) -{ - gen_def_body_code_array_start(gen_def_enum_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Enum_Body; - do - { - gen_Code entry = *codes; - if (! entry) - { - gen_log_failure("gen::gen_def_enum_body: Provided a null entry"); - return gen_InvalidCode; - } - if (entry->Type != CT_Untyped && entry->Type != CT_Comment) - { - gen_log_failure("gen::gen_def_enum_body: Entry type is not allowed: %s", gen_code_debug_str(entry)); - return gen_InvalidCode; - } - gen_body_append(result, entry); - } while (codes++, num--, num > 0); - - return result; -} - -gen_CodeBody gen_def_export_body(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_export_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Export_Body; - - va_list va; - va_start(va, num); - do - { - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_Code entry = gen_pcast(gen_Code, pod); - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_export_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_EXPORT_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_export_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - va_end(va); - - return result; -} - -gen_CodeBody gen_def_export_body_arr(gen_s32 num, gen_Code* codes) -{ - gen_def_body_code_array_start(gen_def_export_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Export_Body; - do - { - gen_Code entry = *codes; - codes++; - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_export_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_EXPORT_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_export_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - - return result; -} - -gen_CodeBody gen_def_extern_link_body(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_extern_linkage_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Extern_Linkage_Body; - - va_list va; - va_start(va, num); - do - { - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_Code entry = gen_pcast(gen_Code, pod); - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_extern_linkage_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_extern_linkage_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - va_end(va); - - return result; -} - -gen_CodeBody gen_def_extern_link_body_arr(gen_s32 num, gen_Code* codes) -{ - gen_def_body_code_array_start(gen_def_extern_linkage_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Extern_Linkage_Body; - do - { - gen_Code entry = *codes; - codes++; - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_extern_linkage_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_extern_linkage_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - - return result; -} - -gen_CodeBody gen_def_function_body(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_function_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Function_Body; - - va_list va; - va_start(va, num); - do - { - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_Code entry = gen_pcast(gen_Code, pod); - if (! entry) - { - gen_log_failure("gen::" gen_stringize(gen_def_function_body) ": Provided an null entry"); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES_CASES: - gen_log_failure("gen::" gen_stringize(gen_def_function_body) ": Entry type is not allowed: %s", gen_code_debug_str(entry)); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - va_end(va); - - return result; -} - -gen_CodeBody gen_def_function_body_arr(gen_s32 num, gen_Code* codes) -{ - gen_def_body_code_array_start(gen_def_function_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Function_Body; - do - { - gen_Code entry = *codes; - codes++; - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_function_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_function_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - - return result; -} - -gen_CodeBody gen_def_global_body(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_global_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Global_Body; - - va_list va; - va_start(va, num); - do - { - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_Code entry = gen_pcast(gen_Code, pod); - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_global_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - case CT_Global_Body: - // result.gen_body_append( entry.gen_code_cast() ) ; - gen_body_append_body(result, gen_cast(gen_CodeBody, entry)); - continue; - - GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_global_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - va_end(va); - - return result; -} - -gen_CodeBody gen_def_global_body_arr(gen_s32 num, gen_Code* codes) -{ - gen_def_body_code_array_start(gen_def_global_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Global_Body; - do - { - gen_Code entry = *codes; - codes++; - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_global_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - case CT_Global_Body: - gen_body_append_body(result, gen_cast(gen_CodeBody, entry)); - continue; - - GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_global_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - - gen_body_append(result, entry); - } while (num--, num > 0); - - return result; -} - -gen_CodeBody gen_def_namespace_body(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_namespace_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Namespace_Body; - - va_list va; - va_start(va, num); - do - { - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_Code entry = gen_pcast(gen_Code, pod); - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_namespace_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_namespace_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - va_end(va); - - return result; -} - -gen_CodeBody gen_def_namespace_body_arr(gen_s32 num, gen_Code* codes) -{ - gen_def_body_code_array_start(gen_def_namespace_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Global_Body; - do - { - gen_Code entry = *codes; - codes++; - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_namespace_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_namespace_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - - return result; -} - -gen_CodeParams gen_def_params(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_params); - - va_list va; - va_start(va, num); - - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_CodeParams param = gen_pcast(gen_CodeParams, pod); - - null_check(gen_def_params, param); - if (param->Type != CT_Parameters) - { - gen_log_failure("gen::gen_def_params: param %d is not a Parameters", num - num + 1); - return gen_InvalidCode; - } - - gen_CodeParams result = (gen_CodeParams)gen_code_duplicate(param); - while (--num) - { - pod = va_arg(va, gen_Code_POD); - param = gen_pcast(gen_CodeParams, pod); - if (param->Type != CT_Parameters) - { - gen_log_failure("gen::gen_def_params: param %d is not a Parameters", num - num + 1); - return gen_InvalidCode; - } - gen_params_append(result, param); - } - va_end(va); - - return result; -} - -gen_CodeParams gen_def_params_arr(gen_s32 num, gen_CodeParams* codes) -{ - gen_def_body_code_array_start(gen_def_params); - -#define check_current(current) \ - if (current == gen_nullptr) \ - { \ - gen_log_failure("gen::gen_def_params: Provide a null code in codes array"); \ - return gen_InvalidCode; \ - } \ - if (current->Type != CT_Parameters) \ - { \ - gen_log_failure("gen::gen_def_params: gen_Code in coes array is not of paramter type - %s", gen_code_debug_str(current)); \ - return gen_InvalidCode; \ - } - gen_CodeParams current = (gen_CodeParams)gen_code_duplicate(*codes); - check_current(current); - - gen_CodeParams result = (gen_CodeParams)gen_make_code(); - result->Name = current->Name; - result->Type = current->Type; - result->ValueType = current->ValueType; - while (codes++, current = *codes, num--, num > 0) - { - check_current(current); - gen_params_append(result, current); - } -#undef check_current - - return result; -} - -gen_CodeSpecifiers gen_def_specifiers(gen_s32 num, ...) -{ - if (num <= 0) - { - gen_log_failure("gen::gen_def_specifiers: num cannot be zero or less"); - return gen_InvalidCode; - } - if (num > gen_AST_ArrSpecs_Cap) - { - gen_log_failure("gen::gen_def_specifiers: num of speciifers to define gen_AST larger than gen_AST specicifier capacity - %d", num); - return gen_InvalidCode; - } - gen_CodeSpecifiers result = (gen_CodeSpecifiers)gen_make_code(); - result->Type = CT_Specifiers; - - va_list va; - va_start(va, num); - do - { - gen_Specifier type = (gen_Specifier)va_arg(va, int); - gen_specifiers_append(result, type); - } while (--num, num); - va_end(va); - - return result; -} - -gen_CodeSpecifiers gen_def_specifiers_arr(gen_s32 num, gen_Specifier* specs) -{ - if (num <= 0) - { - gen_log_failure("gen::gen_def_specifiers: num cannot be zero or less"); - return gen_InvalidCode; - } - if (num > gen_AST_ArrSpecs_Cap) - { - gen_log_failure("gen::gen_def_specifiers: num of speciifers to define gen_AST larger than gen_AST specicifier capacity - %d", num); - return gen_InvalidCode; - } - gen_CodeSpecifiers result = (gen_CodeSpecifiers)gen_make_code(); - result->Type = CT_Specifiers; - - gen_s32 idx = 0; - do - { - gen_specifiers_append(result, specs[idx]); - idx++; - } while (--num, num); - - return result; -} - -gen_CodeBody gen_def_struct_body(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_struct_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Struct_Body; - - va_list va; - va_start(va, num); - do - { - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_Code entry = gen_pcast(gen_Code, pod); - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_struct_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_STRUCT_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_struct_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - va_end(va); - - return result; -} - -gen_CodeBody gen_def_struct_body_arr(gen_s32 num, gen_Code* codes) -{ - gen_def_body_code_array_start(gen_def_struct_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Struct_Body; - do - { - gen_Code entry = *codes; - codes++; - if (! entry) - { - gen_log_failure( - "gen::" - "gen_def_struct_body" - ": Provided an null entry" - ); - return gen_InvalidCode; - } - switch (entry->Type) - { - GEN_AST_BODY_STRUCT_UNALLOWED_TYPES_CASES: - gen_log_failure( - "gen::" - "gen_def_struct_body" - ": Entry type is not allowed: %s", - gen_code_debug_str(entry) - ); - return gen_InvalidCode; - - default: - break; - } - gen_body_append(result, entry); - } while (num--, num > 0); - - return result; -} - -gen_CodeBody gen_def_union_body(gen_s32 num, ...) -{ - gen_def_body_start(gen_def_union_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Union_Body; - - va_list va; - va_start(va, num); - do - { - gen_Code_POD pod = va_arg(va, gen_Code_POD); - gen_Code entry = gen_pcast(gen_Code, pod); - if (! entry) - { - gen_log_failure("gen::gen_def_union_body: Provided a null entry"); - return gen_InvalidCode; - } - if (entry->Type != CT_Untyped && entry->Type != CT_Comment) - { - gen_log_failure("gen::gen_def_union_body: Entry type is not allowed - %s. Must be of untyped or comment type.", gen_code_debug_str(entry)); - return gen_InvalidCode; - } - gen_body_append(result, entry); - } while (num--, num > 0); - va_end(va); - - return result; -} - -gen_CodeBody gen_def_union_body_arr(gen_s32 num, gen_Code* codes) -{ - gen_def_body_code_array_start(gen_def_union_body); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Union_Body; - do - { - gen_Code entry = *codes; - if (! entry) - { - gen_log_failure("gen::gen_def_union_body: Provided a null entry"); - return gen_InvalidCode; - } - if (entry->Type != CT_Untyped && entry->Type != CT_Comment) - { - gen_log_failure("gen::gen_def_union_body: Entry type is not allowed: %s", gen_code_debug_str(entry)); - return gen_InvalidCode; - } - gen_body_append(result, entry); - } while (codes++, num--, num > 0); - - return (gen_CodeBody)result; -} - -#undef name_check -#undef null_check -#undef gen_def_body_start -#undef gen_def_body_code_array_start - -#pragma endregion Upfront - -#pragma region Parsing - - -gen_StrBuilder gen_tok_to_strbuilder(gen_AllocatorInfo ainfo, gen_Token tok) -{ - gen_StrBuilder result = gen_strbuilder_make_reserve(ainfo, gen_kilobytes(4)); - gen_Str type_str = gen_toktype_to_str(tok.Type); - - gen_strbuilder_append_fmt( - &result, - "Line: %d Column: %d, Type: %.*s Content: %.*s", - tok.Line, - tok.Column, - type_str.Len, - type_str.Ptr, - tok.Text.Len, - tok.Text.Ptr - ); - return result; -} - -bool gen_lex__eat(gen_Context* ctx, gen_ParseContext* self, gen_TokType type); - -gen_Token* gen_lex_current(gen_ParseContext* self, bool skip_formatting) -{ - if (skip_formatting) - { - while (self->tokens.ptr[self->gen_token_id].Type == Tok_NewLine || self->tokens.ptr[self->gen_token_id].Type == Tok_Comment) - self->gen_token_id++; - } - return &self->tokens.ptr[self->gen_token_id]; -} - -gen_Token* gen_lex_peek(gen_ParseContext const* self, bool skip_formatting) -{ - gen_s32 idx = self->gen_token_id; - if (skip_formatting) - { - while (self->tokens.ptr[idx].Type == Tok_NewLine) - idx++; - - return &self->tokens.ptr[idx]; - } - return &self->tokens.ptr[idx]; -} - -gen_Token* gen_lex_previous(gen_ParseContext const* self, bool skip_formatting) -{ - gen_s32 idx = self->gen_token_id; - if (skip_formatting) - { - while (self->tokens.ptr[idx].Type == Tok_NewLine) - idx--; - - return &self->tokens.ptr[idx]; - } - return &self->tokens.ptr[idx - 1]; -} - -gen_Token* gen_lex_next(gen_ParseContext const* self, bool skip_formatting) -{ - gen_s32 idx = self->gen_token_id; - if (skip_formatting) - { - while (self->tokens.ptr[idx].Type == Tok_NewLine) - idx++; - - return &self->tokens.ptr[idx + 1]; - } - return &self->tokens.ptr[idx + 1]; -} - -enum -{ - Lex_Continue, - Lex_ReturnNull, -}; - -gen_forceinline void lexer_move_forward(gen_LexContext* ctx) -{ - if (*ctx->scanner == '\n') - { - ctx->line += 1; - ctx->column = 1; - } - else - { - ++ctx->column; - } - --ctx->left; - ++ctx->scanner; -} - -#define move_forward() lexer_move_forward(ctx) - -gen_forceinline void lexer_skip_whitespace(gen_LexContext* ctx) -{ - while (ctx->left && gen_char_is_space(*ctx->scanner)) - move_forward(); -} - -#define skip_whitespace() lexer_skip_whitespace(ctx) - -gen_forceinline void lexer_end_line(gen_LexContext* ctx) -{ - while (ctx->left && (*ctx->scanner) == ' ') - move_forward(); - - if (ctx->left && (*ctx->scanner) == '\r') - { - move_forward(); - move_forward(); - } - else if (ctx->left && (*ctx->scanner) == '\n') - move_forward(); -} - -#define gen_end_line() lexer_end_line(ctx) - -// TODO(Ed): We need to to attempt to recover from a gen_lex failure? -gen_s32 gen_lex_preprocessor_define(gen_LexContext* ctx) -{ - gen_Token name = { - { ctx->scanner, 1 }, - Tok_Identifier, - ctx->line, - ctx->column, - TF_Preprocess - }; - move_forward(); - - while (ctx->left && (gen_char_is_alphanumeric((*ctx->scanner)) || (*ctx->scanner) == '_')) - { - move_forward(); - name.Text.Len++; - } - - gen_Specifier spec = gen_str_to_specifier(name.Text); - gen_TokType attrib = gen_str_to_toktype(name.Text); - gen_b32 not_specifier = spec == Spec_Invalid; - gen_b32 not_attribute = attrib <= Tok___Attributes_Start; - - gen_Macro macro = { name.Text, MT_Expression, (gen_MacroFlags)0 }; - gen_Macro* registered_macro = lookup_macro(name.Text); - - if (registered_macro == gen_nullptr && not_specifier && not_attribute) - { - gen_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 - ); - // GEN_DEBUG_TRAP(); - } - gen_array_append(ctx->tokens, name); - - if (ctx->left && (*ctx->scanner) == '(') - { - if (registered_macro && ! gen_macro_is_functional(*registered_macro)) - { - gen_log_fmt( - "Warning: %S registered macro is not flagged as functional yet the definition detects opening parenthesis '(' for arguments\n", - name.Text - ); - // GEN_DEBUG_TRAP(); - } - else - { - macro.Flags |= MF_Functional; - } - - gen_Token opening_paren = { - { ctx->scanner, 1 }, - Tok_Paren_Open, - ctx->line, - ctx->column, - TF_Preprocess - }; - gen_array_append(ctx->tokens, opening_paren); - move_forward(); - - gen_Token last_parameter = {}; - // We need to tokenize the define's arguments now: - while (ctx->left && *ctx->scanner != ')') - { - skip_whitespace(); - - gen_Str possible_varadic = { ctx->scanner, 3 }; - if (ctx->left > 3 && gen_str_are_equal(gen_txt("..."), possible_varadic)) - { - gen_Token parameter = { - { ctx->scanner, 3 }, - Tok_Preprocess_Define_Param, - ctx->line, - ctx->column, - TF_Preprocess - }; - move_forward(); - move_forward(); - move_forward(); - - gen_array_append(ctx->tokens, parameter); - skip_whitespace(); - last_parameter = parameter; - - while ((*ctx->scanner) == '\\') - { - move_forward(); - skip_whitespace(); - } - if (*ctx->scanner != ')') - { - gen_log_failure( - "gen_lex_preprocessor_define(%d, %d): Expected a ')' after '...' (varaidc macro param) %S\n", - ctx->line, - ctx->column, - name.Text - ); - return Lex_ReturnNull; - } - break; - } - else if ((*ctx->scanner) == '\\') - { - move_forward(); - skip_whitespace(); - continue; - } - else if (gen_char_is_alpha((*ctx->scanner)) || (*ctx->scanner) == '_') - { - gen_Token parameter = { - { ctx->scanner, 1 }, - Tok_Preprocess_Define_Param, - ctx->line, - ctx->column, - TF_Preprocess - }; - move_forward(); - - while (ctx->left && (gen_char_is_alphanumeric((*ctx->scanner)) || (*ctx->scanner) == '_')) - { - move_forward(); - parameter.Text.Len++; - } - gen_array_append(ctx->tokens, parameter); - skip_whitespace(); - last_parameter = parameter; - } - else - { - gen_log_failure( - "gen_lex_preprocessor_define(%d, %d): Expected a '_' or alpha character for a parameter name for %S\n", - ctx->line, - ctx->column, - name.Text - ); - return Lex_ReturnNull; - } - - if (*ctx->scanner == ')') - break; - - // There should be a comma - if (*ctx->scanner != ',') - { - gen_log_failure( - "gen_lex_preprocessor_define(%d, %d): Expected a comma after parameter %S for %S\n", - ctx->line, - ctx->column, - last_parameter.Text, - name.Text - ); - return Lex_ReturnNull; - } - gen_Token comma = { - { ctx->scanner, 1 }, - Tok_Comma, - ctx->line, - ctx->column, - TF_Preprocess - }; - gen_array_append(ctx->tokens, comma); - move_forward(); - } - - if (*ctx->scanner != ')') - { - gen_log_failure( - "gen_lex_preprocessor_define(%d, %d): Expected a ')' after last_parameter %S for %S (ran out of characters...)\n", - ctx->line, - ctx->column, - last_parameter.Text, - name.Text - ); - return Lex_ReturnNull; - } - gen_Token closing_paren = { - { ctx->scanner, 1 }, - Tok_Paren_Close, - ctx->line, - ctx->column, - TF_Preprocess - }; - gen_array_append(ctx->tokens, closing_paren); - move_forward(); - } - else if (registered_macro && gen_macro_is_functional(*registered_macro)) - { - if (registered_macro && ! gen_macro_is_functional(*registered_macro)) - { - gen_log_fmt( - "Warning: %S registered macro is flagged as functional yet the definition detects no opening parenthesis '(' for arguments\n", - name.Text - ); - GEN_DEBUG_TRAP(); - } - } - - if (registered_macro == gen_nullptr) - { - gen_register_macro(macro); - } - - // Define's content handled by gen_lex_preprocessor_directive (the original caller of this) - return Lex_Continue; -} - -// TODO(Ed): We need to to attempt to recover from a gen_lex failure? -gen_s32 gen_lex_preprocessor_directive(gen_LexContext* ctx) -{ - char const* gen_hash = ctx->scanner; - gen_Token hash_tok = { - { gen_hash, 1 }, - Tok_Preprocess_Hash, - ctx->line, - ctx->column, - TF_Preprocess - }; - gen_array_append(ctx->tokens, hash_tok); - - move_forward(); - skip_whitespace(); - - ctx->token.Text.Ptr = ctx->scanner; - while (ctx->left && ! gen_char_is_space((*ctx->scanner))) - { - move_forward(); - ctx->token.Text.Len++; - } - - ctx->token.Type = gen_str_to_toktype(ctx->token.Text); - - bool is_preprocessor = ctx->token.Type >= Tok_Preprocess_Define && ctx->token.Type <= Tok_Preprocess_Pragma; - if (! is_preprocessor) - { - ctx->token.Type = Tok_Preprocess_Unsupported; - - // Its an unsupported directive, skip it - gen_s32 within_string = false; - gen_s32 within_char = false; - while (ctx->left) - { - if (*ctx->scanner == '"' && ! within_char) - within_string ^= true; - - if (*ctx->scanner == '\'' && ! within_string) - within_char ^= true; - - if (*ctx->scanner == '\\' && ! within_string && ! within_char) - { - move_forward(); - ctx->token.Text.Len++; - - if ((*ctx->scanner) == '\r') - { - move_forward(); - ctx->token.Text.Len++; - } - - if ((*ctx->scanner) == '\n') - { - move_forward(); - ctx->token.Text.Len++; - continue; - } - else - { - gen_log_failure( - "gen::Parser::gen_lex: Invalid escape sequence '\\%c' (%d, %d)" - " in preprocessor directive (%d, %d)\n%.100s", - (*ctx->scanner), - ctx->line, - ctx->column, - ctx->token.Line, - ctx->token.Column, - ctx->token.Text - ); - break; - } - } - - if ((*ctx->scanner) == '\r') - { - move_forward(); - ctx->token.Text.Len++; - } - - if ((*ctx->scanner) == '\n') - { - move_forward(); - ctx->token.Text.Len++; - break; - } - - move_forward(); - ctx->token.Text.Len++; - } - - ctx->token.Text.Len = ctx->token.Text.Len + ctx->token.Text.Ptr - gen_hash; - ctx->token.Text.Ptr = gen_hash; - gen_array_append(ctx->tokens, ctx->token); - return Lex_Continue; // Skip found token, its all handled here. - } - - if (ctx->token.Type == Tok_Preprocess_Else || ctx->token.Type == Tok_Preprocess_EndIf) - { - ctx->token.Flags |= TF_Preprocess_Cond; - gen_array_append(ctx->tokens, ctx->token); - gen_end_line(); - return Lex_Continue; - } - else if (ctx->token.Type >= Tok_Preprocess_If && ctx->token.Type <= Tok_Preprocess_ElIf) - { - ctx->token.Flags |= TF_Preprocess_Cond; - } - - gen_array_append(ctx->tokens, ctx->token); - - skip_whitespace(); - - if (ctx->token.Type == Tok_Preprocess_Define) - { - gen_u32 result = gen_lex_preprocessor_define(ctx); // handles: #define ( ) - define's content handled later on within this scope. - if (result != Lex_Continue) - return Lex_ReturnNull; - } - - gen_Token gen_preprocess_content = { - { ctx->scanner, 0 }, - Tok_Preprocess_Content, - ctx->line, - ctx->column, - TF_Preprocess - }; - - if (ctx->token.Type == Tok_Preprocess_Include) - { - gen_preprocess_content.Type = Tok_String; - - if ((*ctx->scanner) != '"' && (*ctx->scanner) != '<') - { - gen_StrBuilder directive_str = - gen_strbuilder_fmt_buf(ctx->allocator_temp, "%.*s", gen_min(80, ctx->left + gen_preprocess_content.Text.Len), ctx->token.Text.Ptr); - - gen_log_failure( - "gen::Parser::gen_lex: Expected '\"' or '<' after #include, not '%c' (%d, %d)\n%s", - (*ctx->scanner), - gen_preprocess_content.Line, - gen_preprocess_content.Column, - (char*)directive_str - ); - return Lex_ReturnNull; - } - move_forward(); - gen_preprocess_content.Text.Len++; - - while (ctx->left && (*ctx->scanner) != '"' && (*ctx->scanner) != '>') - { - move_forward(); - gen_preprocess_content.Text.Len++; - } - - move_forward(); - gen_preprocess_content.Text.Len++; - - if ((*ctx->scanner) == '\r' && ctx->scanner[1] == '\n') - { - move_forward(); - move_forward(); - } - else if ((*ctx->scanner) == '\n') - { - move_forward(); - } - - gen_array_append(ctx->tokens, gen_preprocess_content); - return Lex_Continue; // Skip found token, its all handled here. - } - - gen_s32 within_string = false; - gen_s32 within_char = false; - - // Consume preprocess content - while (ctx->left) - { - if ((*ctx->scanner) == '"' && ! within_char) - within_string ^= true; - - if ((*ctx->scanner) == '\'' && ! within_string) - within_char ^= true; - - if ((*ctx->scanner) == '\\' && ! within_string && ! within_char) - { - move_forward(); - gen_preprocess_content.Text.Len++; - - if ((*ctx->scanner) == '\r') - { - move_forward(); - gen_preprocess_content.Text.Len++; - } - - if ((*ctx->scanner) == '\n') - { - move_forward(); - gen_preprocess_content.Text.Len++; - continue; - } - else - { - gen_StrBuilder directive_str = gen_strbuilder_make_length(ctx->allocator_temp, ctx->token.Text.Ptr, ctx->token.Text.Len); - gen_StrBuilder content_str = gen_strbuilder_fmt_buf( - ctx->allocator_temp, - "%.*s", - gen_min(400, ctx->left + gen_preprocess_content.Text.Len), - gen_preprocess_content.Text.Ptr - ); - - gen_log_failure( - "gen::Parser::gen_lex: Invalid escape sequence '\\%c' (%d, %d)" - " in preprocessor directive '%s' (%d, %d)\n%s", - (*ctx->scanner), - ctx->line, - ctx->column, - directive_str, - gen_preprocess_content.Line, - gen_preprocess_content.Column, - content_str - ); - return Lex_ReturnNull; - break; - } - } - - if ((*ctx->scanner) == '\r') - { - break; - //move_forward(); - } - - if ((*ctx->scanner) == '\n') - { - //move_forward(); - break; - } - - move_forward(); - gen_preprocess_content.Text.Len++; - } - - gen_array_append(ctx->tokens, gen_preprocess_content); - return Lex_Continue; // Skip found token, its all handled here. -} - -void gen_lex_found_token(gen_LexContext* ctx) -{ - if (ctx->token.Type != Tok_Invalid) - { - gen_array_append(ctx->tokens, ctx->token); - return; - } - - 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; - } - if (type > Tok___Attributes_Start) - { - ctx->token.Flags |= TF_Attribute; - } - if (type == Tok_Decl_Extern_Linkage) - { - skip_whitespace(); - - if ((*ctx->scanner) != '"') - { - type = Tok_Spec_Extern; - ctx->token.Flags |= TF_Specifier; - } - - ctx->token.Type = type; - gen_array_append(ctx->tokens, ctx->token); - return; - } - if ((type <= Tok_Star && type >= Tok_Spec_Alignas) || type == Tok_Ampersand || type == Tok_Ampersand_DBL) - { - ctx->token.Type = type; - ctx->token.Flags |= TF_Specifier; - gen_array_append(ctx->tokens, ctx->token); - return; - } - if (type != Tok_Invalid) - { - ctx->token.Type = type; - gen_array_append(ctx->tokens, ctx->token); - return; - } - - gen_Macro* macro = lookup_macro(ctx->token.Text); - gen_b32 has_args = ctx->left && (*ctx->scanner) == '('; - gen_b32 resolved_to_macro = false; - if (macro) - { - ctx->token.Type = gen_macrotype__to_toktype(macro->Type); - gen_b32 is_functional = gen_macro_is_functional(*macro); - resolved_to_macro = has_args ? is_functional : ! is_functional; - if (! resolved_to_macro && GEN_BUILD_DEBUG) - { - gen_log_fmt( - "Info(%d, %d): %S identified as a macro but usage here does not resolve to one (interpreting as identifier)\n", - ctx->token.Line, - ctx->token.Line, - macro->Name - ); - } - } - if (resolved_to_macro) - { - // TODO(Ed): When we introduce a macro gen_AST (and expression support), we'll properly gen_lex this section. - // Want to ignore any arguments the define may have as they can be execution expressions. - if (has_args) - { - ctx->token.Flags |= TF_Macro_Functional; - } - if (gen_bitfield_is_set(gen_MacroFlags, macro->Flags, MF_Allow_As_Attribute)) - { - ctx->token.Flags |= TF_Attribute; - } - if (gen_bitfield_is_set(gen_MacroFlags, macro->Flags, MF_Allow_As_Specifier)) - { - ctx->token.Flags |= TF_Specifier; - } - } - else - { - ctx->token.Type = Tok_Identifier; - } - - gen_array_append(ctx->tokens, ctx->token); -} - -// TODO(Ed): We should dynamically allocate the lexer's array in Allocator_DyanmicContainers. - -// TODO(Ed): We need to to attempt to recover from a gen_lex failure? - -gen_neverinline LexedInfo gen_lex(gen_Context* lib_ctx, gen_Str content) -{ - LexedInfo info = gen_struct_zero(LexedInfo); - - gen_LexContext c = gen_struct_zero(gen_LexContext); - gen_LexContext* ctx = &c; - c.allocator_temp = lib_ctx->Allocator_Temp; - c.content = content; - c.left = content.Len; - c.scanner = content.Ptr; - c.line = 1; - c.column = 1; - c.tokens = gen_array_init_reserve(gen_Token, lib_ctx->Allocator_DyanmicContainers, lib_ctx->InitSize_LexerTokens); - - // TODO(Ed): Re-implement to new constraints: - // 1. Ability to continue on error - // 2. Return a lexed info. - - skip_whitespace(); - if (c.left <= 0) - { - gen_log_failure("gen::gen_lex: no tokens found (only whitespace provided)"); - return info; - } - - gen_b32 gen_preprocess_args = true; - - while (c.left) - { - c.token = gen_struct_init(gen_Token) { - { c.scanner, 0 }, - Tok_Invalid, - c.line, - c.column, - TF_Null - }; - - bool is_define = false; - - if (c.column == 1) - { - if ((*ctx->scanner) == '\r') - { - move_forward(); - c.token.Text.Len = 1; - } - - if ((*ctx->scanner) == '\n') - { - move_forward(); - - c.token.Type = Tok_NewLine; - c.token.Text.Len++; - - gen_array_append(c.tokens, c.token); - continue; - } - } - - c.token.Text.Len = 0; - - skip_whitespace(); - if (c.left <= 0) - break; - - switch ((*ctx->scanner)) - { - case '#': - { - gen_s32 result = gen_lex_preprocessor_directive(ctx); - switch (result) - { - case Lex_Continue: - { - //gen_TokType last_type = Tokens[gen_array_get_header(Tokens)->Num - 2].Type; - //if ( last_type == Tok_Preprocess_Pragma ) - { - { - gen_Token thanks_c = { - { c.scanner, 0 }, - Tok_Invalid, - c.line, - c.column, - TF_Null - }; - c.token = thanks_c; - } - if ((*ctx->scanner) == '\r') - { - move_forward(); - c.token.Text.Len = 1; - } - - if ((*ctx->scanner) == '\n') - { - c.token.Type = Tok_NewLine; - c.token.Text.Len++; - move_forward(); - - gen_array_append(c.tokens, c.token); - } - } - continue; - } - - case Lex_ReturnNull: - { - return info; - } - } - } - case '.': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Access_MemberSymbol; - c.token.Flags = TF_AccessOperator; - - if (c.left) - { - move_forward(); - } - - if ((*ctx->scanner) == '.') - { - move_forward(); - if ((*ctx->scanner) == '.') - { - c.token.Text.Len = 3; - c.token.Type = Tok_Varadic_Argument; - c.token.Flags = TF_Null; - move_forward(); - } - else - { - gen_StrBuilder context_str = gen_strbuilder_fmt_buf(lib_ctx->Allocator_Temp, "%s", c.scanner, gen_min(100, c.left)); - - gen_log_failure( - "gen::gen_lex: invalid varadic argument, expected '...' got '..%c' (%d, %d)\n%s", - (*ctx->scanner), - c.line, - c.column, - context_str - ); - } - } - - goto FoundToken; - } - case '&': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Ampersand; - c.token.Flags |= TF_Operator; - c.token.Flags |= TF_Specifier; - - if (c.left) - move_forward(); - - if ((*ctx->scanner) == '&') // && - { - c.token.Text.Len = 2; - c.token.Type = Tok_Ampersand_DBL; - - if (c.left) - move_forward(); - } - - goto FoundToken; - } - case ':': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Assign_Classifer; - // Can be either a classifier (ParentType, Bitfield width), or ternary else - // token.Type = Tok_Colon; - - if (c.left) - move_forward(); - - if ((*ctx->scanner) == ':') - { - move_forward(); - c.token.Type = Tok_Access_StaticSymbol; - c.token.Text.Len++; - } - goto FoundToken; - } - case '{': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_BraceCurly_Open; - - if (c.left) - move_forward(); - goto FoundToken; - } - case '}': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_BraceCurly_Close; - c.token.Flags = TF_EndDefinition; - - if (c.left) - move_forward(); - - gen_end_line(); - goto FoundToken; - } - case '[': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_BraceSquare_Open; - if (c.left) - { - move_forward(); - - if ((*ctx->scanner) == ']') - { - c.token.Text.Len = 2; - c.token.Type = Tok_Operator; - move_forward(); - } - } - goto FoundToken; - } - case ']': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_BraceSquare_Close; - - if (c.left) - move_forward(); - goto FoundToken; - } - case '(': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Paren_Open; - - if (c.left) - move_forward(); - goto FoundToken; - } - case ')': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Paren_Close; - - if (c.left) - move_forward(); - goto FoundToken; - } - case '\'': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Char; - c.token.Flags = TF_Literal; - - move_forward(); - - if (c.left && (*ctx->scanner) == '\\') - { - move_forward(); - c.token.Text.Len++; - - if ((*ctx->scanner) == '\'') - { - move_forward(); - c.token.Text.Len++; - } - } - - while (c.left && (*ctx->scanner) != '\'') - { - move_forward(); - c.token.Text.Len++; - } - - if (c.left) - { - move_forward(); - c.token.Text.Len++; - } - goto FoundToken; - } - case ',': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Comma; - c.token.Flags = TF_Operator; - - if (c.left) - move_forward(); - goto FoundToken; - } - case '*': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Star; - c.token.Flags |= TF_Specifier; - c.token.Flags |= TF_Operator; - - if (c.left) - move_forward(); - - if ((*ctx->scanner) == '=') - { - c.token.Text.Len++; - c.token.Flags |= TF_Assign; - // c.token.Type = Tok_Assign_Multiply; - - if (c.left) - move_forward(); - } - - goto FoundToken; - } - case ';': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Statement_End; - c.token.Flags = TF_EndDefinition; - - if (c.left) - move_forward(); - - gen_end_line(); - goto FoundToken; - } - case '"': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_String; - c.token.Flags |= TF_Literal; - - move_forward(); - while (c.left) - { - if ((*ctx->scanner) == '"') - { - move_forward(); - break; - } - - if ((*ctx->scanner) == '\\') - { - move_forward(); - c.token.Text.Len++; - - if (c.left) - { - move_forward(); - c.token.Text.Len++; - } - continue; - } - - move_forward(); - c.token.Text.Len++; - } - goto FoundToken; - } - case '?': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Operator; - // c.token.Type = Tok_Ternary; - c.token.Flags = TF_Operator; - - if (c.left) - move_forward(); - - goto FoundToken; - } - case '=': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Operator; - // c.token.Type = Tok_Assign; - c.token.Flags = TF_Operator; - c.token.Flags |= TF_Assign; - - if (c.left) - move_forward(); - - if ((*ctx->scanner) == '=') - { - c.token.Text.Len++; - c.token.Flags = TF_Operator; - - if (c.left) - move_forward(); - } - - goto FoundToken; - } - case '+': - { - // c.token.Type = Tok_Add - } - case '%': - { - // c.token.Type = Tok_Modulo; - } - case '^': - { - // c.token.Type = Tok_B_XOr; - } - case '~': - { - // c.token.Type = Tok_Unary_Not; - } - case '!': - { - // c.token.Type = Tok_L_Not; - } - case '<': - { - // c.token.Type = Tok_Lesser; - } - case '>': - { - // c.token.Type = Tok_Greater; - } - case '|': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Operator; - c.token.Flags = TF_Operator; - // token.Type = Tok_L_Or; - - if (c.left) - move_forward(); - - if ((*ctx->scanner) == '=') - { - c.token.Text.Len++; - c.token.Flags |= TF_Assign; - // token.Flags |= TokFlags::Assignment; - // token.Type = Tok_Assign_L_Or; - - if (c.left) - move_forward(); - } - else - while (c.left && (*ctx->scanner) == *(c.scanner - 1) && c.token.Text.Len < 3) - { - c.token.Text.Len++; - - if (c.left) - move_forward(); - } - goto FoundToken; - } - - // Dash is unfortunately a gen_bit more complicated... - case '-': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Operator; - // token.Type = Tok_Subtract; - c.token.Flags = TF_Operator; - if (c.left) - { - move_forward(); - - if ((*ctx->scanner) == '>') - { - c.token.Text.Len++; - // token.Type = Tok_Access_PointerToMemberSymbol; - c.token.Flags |= TF_AccessOperator; - move_forward(); - - if ((*ctx->scanner) == '*') - { - // token.Type = Tok_Access_PointerToMemberOfPointerSymbol; - c.token.Text.Len++; - move_forward(); - } - } - else if ((*ctx->scanner) == '=') - { - c.token.Text.Len++; - // token.Type = Tok_Assign_Subtract; - c.token.Flags |= TF_Assign; - - if (c.left) - move_forward(); - } - else - while (c.left && (*ctx->scanner) == *(c.scanner - 1) && c.token.Text.Len < 3) - { - c.token.Text.Len++; - - if (c.left) - move_forward(); - } - } - goto FoundToken; - } - case '/': - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Operator; - // token.Type = Tok_Divide; - c.token.Flags = TF_Operator; - move_forward(); - - if (c.left) - { - if ((*ctx->scanner) == '=') - { - // token.Type = TokeType::Assign_Divide; - move_forward(); - c.token.Text.Len++; - c.token.Flags = TF_Assign; - } - else if ((*ctx->scanner) == '/') - { - c.token.Type = Tok_Comment; - c.token.Text.Len = 2; - c.token.Flags = TF_Null; - move_forward(); - - while (c.left && (*ctx->scanner) != '\n' && (*ctx->scanner) != '\r') - { - move_forward(); - c.token.Text.Len++; - } - - if ((*ctx->scanner) == '\r') - { - move_forward(); - c.token.Text.Len++; - } - if ((*ctx->scanner) == '\n') - { - move_forward(); - c.token.Text.Len++; - } - gen_array_append(c.tokens, c.token); - continue; - } - else if ((*ctx->scanner) == '*') - { - c.token.Type = Tok_Comment; - c.token.Text.Len = 2; - c.token.Flags = TF_Null; - move_forward(); - - bool star = (*ctx->scanner) == '*'; - bool slash = c.scanner[1] == '/'; - bool at_end = star && slash; - while (c.left && ! at_end) - { - move_forward(); - c.token.Text.Len++; - - star = (*ctx->scanner) == '*'; - slash = c.scanner[1] == '/'; - at_end = star && slash; - } - c.token.Text.Len += 2; - move_forward(); - move_forward(); - - if ((*ctx->scanner) == '\r') - { - move_forward(); - c.token.Text.Len++; - } - if ((*ctx->scanner) == '\n') - { - move_forward(); - c.token.Text.Len++; - } - gen_array_append(c.tokens, c.token); - // gen_end_line(); - continue; - } - } - goto FoundToken; - } - } - - if (gen_char_is_alpha((*ctx->scanner)) || (*ctx->scanner) == '_') - { - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - move_forward(); - - while (c.left && (gen_char_is_alphanumeric((*ctx->scanner)) || (*ctx->scanner) == '_')) - { - move_forward(); - c.token.Text.Len++; - } - - goto FoundToken; - } - else if (gen_char_is_digit((*ctx->scanner))) - { - // This is a very brute force gen_lex, no checks are done for validity of literal. - - gen_Str text = { c.scanner, 1 }; - c.token.Text = text; - c.token.Type = Tok_Number; - c.token.Flags = TF_Literal; - move_forward(); - - if (c.left - && ((*ctx->scanner) == 'x' || (*ctx->scanner) == 'X' || (*ctx->scanner) == 'b' || (*ctx->scanner) == 'B' || (*ctx->scanner) == 'o' - || (*ctx->scanner) == 'O')) - { - move_forward(); - c.token.Text.Len++; - - while (c.left && gen_char_is_hex_digit((*ctx->scanner))) - { - move_forward(); - c.token.Text.Len++; - } - - goto FoundToken; - } - - while (c.left && gen_char_is_digit((*ctx->scanner))) - { - move_forward(); - c.token.Text.Len++; - } - - if (c.left && (*ctx->scanner) == '.') - { - move_forward(); - c.token.Text.Len++; - - while (c.left && gen_char_is_digit((*ctx->scanner))) - { - move_forward(); - c.token.Text.Len++; - } - - // Handle number literal suffixes in a botched way - if (c.left - && ((*ctx->scanner) == 'l' || (*ctx->scanner) == 'L' || // long/long long - (*ctx->scanner) == 'u' || (*ctx->scanner) == 'U' || // unsigned - (*ctx->scanner) == 'f' || (*ctx->scanner) == 'F' || // float - (*ctx->scanner) == 'i' || (*ctx->scanner) == 'I' || // imaginary - (*ctx->scanner) == 'z' || (*ctx->scanner) == 'Z')) // complex - { - char prev = (*ctx->scanner); - move_forward(); - c.token.Text.Len++; - - // Handle 'll'/'LL' as a special case when we just processed an 'l'/'L' - if (c.left && (prev == 'l' || prev == 'L') && ((*ctx->scanner) == 'l' || (*ctx->scanner) == 'L')) - { - move_forward(); - c.token.Text.Len++; - } - } - } - - goto FoundToken; - } - else - { - gen_s32 start = gen_max(0, gen_array_num(c.tokens) - 100); - gen_log_fmt("\n%d\n", start); - for (gen_s32 idx = start; idx < gen_array_num(c.tokens); idx++) - { - gen_log_fmt("gen_Token %d Type: %s : %.*s\n", idx, gen_toktype_to_str(c.tokens[idx].Type).Ptr, c.tokens[idx].Text.Len, c.tokens[idx].Text.Ptr); - } - - gen_StrBuilder context_str = gen_strbuilder_fmt_buf(gen__ctx->Allocator_Temp, "%.*s", gen_min(100, c.left), c.scanner); - gen_log_failure("Failed to gen_lex token '%c' (%d, %d)\n%s", (*ctx->scanner), c.line, c.column, context_str); - - // Skip to next whitespace since we can't know if anything else is valid until then. - while (c.left && ! gen_char_is_space((*ctx->scanner))) - { - move_forward(); - } - } - - FoundToken: - { - gen_lex_found_token(ctx); - gen_TokType last_type = gen_array_back(c.tokens)->Type; - if (last_type == Tok_Preprocess_Macro_Stmt || last_type == Tok_Preprocess_Macro_Expr) - { - gen_Token thanks_c = { - { c.scanner, 0 }, - Tok_Invalid, - c.line, - c.column, - TF_Null - }; - c.token = thanks_c; - if ((*ctx->scanner) == '\r') - { - move_forward(); - c.token.Text.Len = 1; - } - if ((*ctx->scanner) == '\n') - { - c.token.Type = Tok_NewLine; - c.token.Text.Len++; - move_forward(); - - gen_array_append(c.tokens, c.token); - continue; - } - } - } - } - - if (gen_array_num(c.tokens) == 0) - { - gen_log_failure("Failed to gen_lex any tokens"); - return info; - } - - info.messages = c.messages; - info.text = content; - info.tokens = gen_struct_init(TokenSlice) { gen_pcast(gen_Token*, c.tokens), gen_scast(gen_s32, gen_array_num(c.tokens)) }; - return info; -} - -#undef move_forward -#undef skip_whitespace -#undef gen_end_line - -#pragma region gen_Array_gen_CodeTypename - -#define GEN_GENERIC_SLOT_10__array_init gen_CodeTypename, gen_Array_gen_CodeTypename_init -#define GEN_GENERIC_SLOT_10__array_init_reserve gen_CodeTypename, gen_Array_gen_CodeTypename_init_reserve -#define GEN_GENERIC_SLOT_10__array_append gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_append -#define GEN_GENERIC_SLOT_10__array_append_items gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_append_items -#define GEN_GENERIC_SLOT_10__array_append_at gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_append_at -#define GEN_GENERIC_SLOT_10__array_append_items_at gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_append_items_at -#define GEN_GENERIC_SLOT_10__array_back gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_back -#define GEN_GENERIC_SLOT_10__array_clear gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_clear -#define GEN_GENERIC_SLOT_10__array_fill gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_fill -#define GEN_GENERIC_SLOT_10__array_free gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_free -#define GEN_GENERIC_SLOT_10__array_grow gen_Array_gen_CodeTypename*, gen_Array_gen_CodeTypename_grow -#define GEN_GENERIC_SLOT_10__array_num gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_num -#define GEN_GENERIC_SLOT_10__array_pop gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_pop -#define GEN_GENERIC_SLOT_10__array_remove_at gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_remove_at -#define GEN_GENERIC_SLOT_10__array_reserve gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_reserve -#define GEN_GENERIC_SLOT_10__array_resize gen_Array_gen_CodeTypename, gen_Array_gen_CodeTypename_resize -#define GEN_GENERIC_SLOT_10__array_set_capacity gen_Array_gen_CodeTypename*, gen_Array_gen_CodeTypename_set_capacity - -typedef gen_CodeTypename* gen_Array_gen_CodeTypename; -gen_Array_gen_CodeTypename gen_Array_gen_CodeTypename_init(gen_AllocatorInfo allocator); -gen_Array_gen_CodeTypename gen_Array_gen_CodeTypename_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity); -bool gen_Array_gen_CodeTypename_append_array(gen_Array_gen_CodeTypename* self, gen_Array_gen_CodeTypename other); -bool gen_Array_gen_CodeTypename_append(gen_Array_gen_CodeTypename* self, gen_CodeTypename value); -bool gen_Array_gen_CodeTypename_append_items(gen_Array_gen_CodeTypename* self, gen_CodeTypename* items, gen_usize item_num); -bool gen_Array_gen_CodeTypename_append_at(gen_Array_gen_CodeTypename* self, gen_CodeTypename item, gen_usize idx); -bool gen_Array_gen_CodeTypename_append_items_at(gen_Array_gen_CodeTypename* self, gen_CodeTypename* items, gen_usize item_num, gen_usize idx); -gen_CodeTypename* gen_Array_gen_CodeTypename_back(gen_Array_gen_CodeTypename self); -void gen_Array_gen_CodeTypename_clear(gen_Array_gen_CodeTypename self); -bool gen_Array_gen_CodeTypename_fill(gen_Array_gen_CodeTypename self, gen_usize begin, gen_usize end, gen_CodeTypename value); -void gen_Array_gen_CodeTypename_free(gen_Array_gen_CodeTypename* self); -bool gen_Array_gen_CodeTypename_grow(gen_Array_gen_CodeTypename* self, gen_usize min_capacity); -gen_usize gen_Array_gen_CodeTypename_num(gen_Array_gen_CodeTypename self); -gen_CodeTypename gen_Array_gen_CodeTypename_pop(gen_Array_gen_CodeTypename self); -void gen_Array_gen_CodeTypename_remove_at(gen_Array_gen_CodeTypename self, gen_usize idx); -bool gen_Array_gen_CodeTypename_reserve(gen_Array_gen_CodeTypename* self, gen_usize new_capacity); -bool gen_Array_gen_CodeTypename_resize(gen_Array_gen_CodeTypename* self, gen_usize num); -bool gen_Array_gen_CodeTypename_set_capacity(gen_Array_gen_CodeTypename* self, gen_usize new_capacity); - -gen_forceinline gen_Array_gen_CodeTypename gen_Array_gen_CodeTypename_init(gen_AllocatorInfo allocator) -{ - size_t initial_size = gen_array_grow_formula(0); - return gen_array_init_reserve(gen_CodeTypename, allocator, initial_size); -} - -inline gen_Array_gen_CodeTypename gen_Array_gen_CodeTypename_init_reserve(gen_AllocatorInfo allocator, gen_usize capacity) -{ - GEN_ASSERT(capacity > 0); - gen_ArrayHeader* header = gen_rcast(gen_ArrayHeader*, gen_alloc(allocator, sizeof(gen_ArrayHeader) + sizeof(gen_CodeTypename) * capacity)); - if (header == gen_nullptr) - return gen_nullptr; - header->Allocator = allocator; - header->Capacity = capacity; - header->Num = 0; - return gen_rcast(gen_CodeTypename*, header + 1); -} - -gen_forceinline bool gen_Array_gen_CodeTypename_append_array(gen_Array_gen_CodeTypename* self, gen_Array_gen_CodeTypename other) -{ - return gen_array_append_items(*self, (gen_Array_gen_CodeTypename)other, gen_Array_gen_CodeTypename_num(other)); -} - -inline bool gen_Array_gen_CodeTypename_append(gen_Array_gen_CodeTypename* self, gen_CodeTypename value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num == header->Capacity) - { - if (! gen_array_grow(self, header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - (*self)[header->Num] = value; - header->Num++; - return true; -} - -inline bool gen_Array_gen_CodeTypename_append_items(gen_Array_gen_CodeTypename* self, gen_CodeTypename* items, gen_usize item_num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(items != gen_nullptr); - GEN_ASSERT(item_num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Num + item_num > header->Capacity) - { - if (! gen_array_grow(self, header->Capacity + item_num)) - return false; - header = gen_array_get_header(*self); - } - gen_mem_copy((*self) + header->Num, items, sizeof(gen_CodeTypename) * item_num); - header->Num += item_num; - return true; -} - -inline bool gen_Array_gen_CodeTypename_append_at(gen_Array_gen_CodeTypename* self, gen_CodeTypename item, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - idx = header->Num - 1; - if (idx < 0) - idx = 0; - if (header->Capacity < header->Num + 1) - { - if (! gen_array_grow(self, header->Capacity + 1)) - return false; - header = gen_array_get_header(*self); - } - gen_Array_gen_CodeTypename target = (*self) + idx; - gen_mem_move(target + 1, target, (header->Num - idx) * sizeof(gen_CodeTypename)); - header->Num++; - return true; -} - -inline bool gen_Array_gen_CodeTypename_append_items_at(gen_Array_gen_CodeTypename* self, gen_CodeTypename* items, gen_usize item_num, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (idx >= header->Num) - { - return gen_array_append_items(*self, items, item_num); - } - if (item_num > header->Capacity) - { - if (! gen_array_grow(self, item_num + header->Capacity)) - return false; - header = gen_array_get_header(*self); - } - gen_CodeTypename* target = (*self) + idx + item_num; - gen_CodeTypename* src = (*self) + idx; - gen_mem_move(target, src, (header->Num - idx) * sizeof(gen_CodeTypename)); - gen_mem_copy(src, items, item_num * sizeof(gen_CodeTypename)); - header->Num += item_num; - return true; -} - -inline gen_CodeTypename* gen_Array_gen_CodeTypename_back(gen_Array_gen_CodeTypename self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - if (header->Num == 0) - return 0; - return self + header->Num - 1; -} - -inline void gen_Array_gen_CodeTypename_clear(gen_Array_gen_CodeTypename self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - header->Num = 0; -} - -inline bool gen_Array_gen_CodeTypename_fill(gen_Array_gen_CodeTypename self, gen_usize begin, gen_usize end, gen_CodeTypename value) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(begin <= end); - gen_ArrayHeader* header = gen_array_get_header(self); - if (begin < 0 || end > header->Num) - return false; - for (gen_ssize idx = (gen_ssize)begin; idx < (gen_ssize)end; idx++) - self[idx] = value; - return true; -} - -inline void gen_Array_gen_CodeTypename_free(gen_Array_gen_CodeTypename* self) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_allocator_free(header->Allocator, header); - self = 0; -} - -inline bool gen_Array_gen_CodeTypename_grow(gen_Array_gen_CodeTypename* self, gen_usize min_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(min_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - gen_usize new_capacity = gen_array_grow_formula(header->Capacity); - if (new_capacity < min_capacity) - new_capacity = min_capacity; - return gen_array_set_capacity(self, new_capacity); -} - -gen_forceinline gen_usize gen_Array_gen_CodeTypename_num(gen_Array_gen_CodeTypename self) -{ - GEN_ASSERT(self != gen_nullptr); - return gen_array_get_header(self)->Num; -} - -inline gen_CodeTypename gen_Array_gen_CodeTypename_pop(gen_Array_gen_CodeTypename self) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(header->Num > 0); - gen_CodeTypename result = self[header->Num - 1]; - header->Num--; - return result; -} - -gen_forceinline void gen_Array_gen_CodeTypename_remove_at(gen_Array_gen_CodeTypename self, gen_usize idx) -{ - GEN_ASSERT(self != gen_nullptr); - gen_ArrayHeader* header = gen_array_get_header(self); - GEN_ASSERT(idx < header->Num); - gen_mem_move(self + idx, self + idx + 1, sizeof(gen_CodeTypename) * (header->Num - idx - 1)); - header->Num--; -} - -inline bool gen_Array_gen_CodeTypename_reserve(gen_Array_gen_CodeTypename* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < new_capacity) - return gen_array_set_capacity(self, new_capacity); - return true; -} - -inline bool gen_Array_gen_CodeTypename_resize(gen_Array_gen_CodeTypename* self, gen_usize num) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(num > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (header->Capacity < num) - { - if (! gen_array_grow(self, num)) - return false; - header = gen_array_get_header(*self); - } - header->Num = num; - return true; -} - -inline bool gen_Array_gen_CodeTypename_set_capacity(gen_Array_gen_CodeTypename* self, gen_usize new_capacity) -{ - GEN_ASSERT(self != gen_nullptr); - GEN_ASSERT(*self != gen_nullptr); - GEN_ASSERT(new_capacity > 0); - gen_ArrayHeader* header = gen_array_get_header(*self); - if (new_capacity == header->Capacity) - return true; - if (new_capacity < header->Num) - { - header->Num = new_capacity; - return true; - } - gen_usize size = sizeof(gen_ArrayHeader) + sizeof(gen_CodeTypename) * new_capacity; - gen_ArrayHeader* new_header = gen_cast(gen_ArrayHeader*, gen_alloc(header->Allocator, size)); - if (new_header == 0) - return false; - gen_mem_move(new_header, header, sizeof(gen_ArrayHeader) + sizeof(gen_CodeTypename) * header->Num); - new_header->Capacity = new_capacity; - gen_allocator_free(header->Allocator, &header); - *self = gen_cast(gen_CodeTypename*, new_header + 1); - return true; -} - -#pragma endregion gen_Array_gen_CodeTypename - -// These macros are used in the swtich cases within parser.cpp - -#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIER_CASES \ -case Tok_Spec_Consteval: \ -case Tok_Spec_Constexpr: \ -case Tok_Spec_Constinit: \ -case Tok_Spec_Explicit: \ -case Tok_Spec_ForceInline: \ -case Tok_Spec_Inline: \ -case Tok_Spec_Mutable: \ -case Tok_Spec_NeverInline: \ -case Tok_Spec_Static: \ -case Tok_Spec_Volatile: \ -case Tok_Spec_Virtual - -#define GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIER_CASES \ -case Spec_Constexpr: \ -case Spec_Constinit: \ -case Spec_Explicit: \ -case Spec_Inline: \ -case Spec_ForceInline: \ -case Spec_Mutable: \ -case Spec_NeverInline: \ -case Spec_Static: \ -case Spec_Volatile: \ -case Spec_Virtual - -#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_TOK_SPECIFIER_CASES \ -case Tok_Spec_Consteval: \ -case Tok_Spec_Constexpr: \ -case Tok_Spec_Constinit: \ -case Tok_Spec_Extern: \ -case Tok_Spec_ForceInline: \ -case Tok_Spec_Global: \ -case Tok_Spec_Inline: \ -case Tok_Spec_Internal_Linkage: \ -case Tok_Spec_NeverInline: \ -case Tok_Spec_Static - -#define GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_SPECIFIER_CASES \ -case Spec_Constexpr: \ -case Spec_Constinit: \ -case Spec_ForceInline: \ -case Spec_Global: \ -case Spec_External_Linkage: \ -case Spec_Internal_Linkage: \ -case Spec_Inline: \ -case Spec_Mutable: \ -case Spec_NeverInline: \ -case Spec_Static: \ -case Spec_Volatile - -#define GEN_PARSER_FRIEND_ALLOWED_SPECIFIER_CASES \ -case Spec_Const: \ -case Spec_Inline: \ -case Spec_ForceInline - -#define GEN_PARSER_FUNCTION_ALLOWED_SPECIFIER_CASES \ -case Spec_Const: \ -case Spec_Consteval: \ -case Spec_Constexpr: \ -case Spec_External_Linkage: \ -case Spec_Internal_Linkage: \ -case Spec_ForceInline: \ -case Spec_Inline: \ -case Spec_NeverInline: \ -case Spec_Static - -#define GEN_PARSER_OPERATOR_ALLOWED_SPECIFIER_CASES \ -case Spec_Const: \ -case Spec_Constexpr: \ -case Spec_ForceInline: \ -case Spec_Inline: \ -case Spec_NeverInline: \ -case Spec_Static - -#define GEN_PARSER_TEMPLATE_ALLOWED_SPECIFIER_CASES \ -case Spec_Const: \ -case Spec_Constexpr: \ -case Spec_Constinit: \ -case Spec_External_Linkage: \ -case Spec_Global: \ -case Spec_Inline: \ -case Spec_ForceInline: \ -case Spec_Local_Persist: \ -case Spec_Mutable: \ -case Spec_Static: \ -case Spec_Thread_Local: \ -case Spec_Volatile - -#define GEN_PARSER_VARIABLE_ALLOWED_SPECIFIER_CASES \ -case Spec_Const: \ -case Spec_Constexpr: \ -case Spec_Constinit: \ -case Spec_External_Linkage: \ -case Spec_Global: \ -case Spec_Inline: \ -case Spec_Local_Persist: \ -case Spec_Mutable: \ -case Spec_Restrict: \ -case Spec_Static: \ -case Spec_Thread_Local: \ -case Spec_Volatile - -#define GEN_PARSER_TYPENAME_ALLOWED_SUFFIX_SPECIFIER_CASES \ -case Spec_Const: \ -case Spec_Ptr: \ -case Spec_Restrict: \ -case Spec_Ref: \ -case Spec_RValue - - - -// TODO(Ed) : Rename ETok_Capture_Start, ETok_Capture_End to Open_Parenthesis adn Close_Parenthesis - -#define gen_lex_dont_skip_formatting (bool)false -#define gen_lex_skip_formatting (bool)true - -void gen_parser_push(gen_ParseContext* ctx, gen_ParseStackNode* node) -{ - node->prev = ctx->scope; - ctx->scope = node; - -#if 0 && GEN_BUILD_DEBUG - gen_log_fmt("\tEntering parser: %.*s\n", Scope->ProcName.Len, Scope->ProcName.Ptr ); -#endif -} - -void gen_parser_pop(gen_ParseContext* ctx) -{ -#if 0 && GEN_BUILD_DEBUG - gen_log_fmt("\tPopping parser: %.*s\n", Scope->ProcName.Len, Scope->ProcName.Ptr ); -#endif - ctx->scope = ctx->scope->prev; -} - -gen_StrBuilder gen_parser_to_strbuilder(gen_ParseContext const* ctx, gen_AllocatorInfo temp) -{ - gen_StrBuilder result = gen_strbuilder_make_reserve(temp, gen_kilobytes(4)); - - gen_Token scope_start = *ctx->scope->start; - gen_Token last_valid = (ctx->gen_token_id >= ctx->tokens.num) ? ctx->tokens.ptr[ctx->tokens.num - 1] : (*gen_lex_peek(ctx, true)); - - gen_sptr length = scope_start.Text.Len; - char const* current = scope_start.Text.Ptr + length; - while (current <= ctx->tokens.ptr[ctx->tokens.num - 1].Text.Ptr && (*current) != '\n' && length < 74) - { - current++; - length++; - } - - gen_Str scope_str = { scope_start.Text.Ptr, length }; - gen_StrBuilder line = gen_strbuilder_make_str(temp, scope_str); - gen_strbuilder_append_fmt(&result, "\tScope : %s\n", line); - gen_strbuilder_free(&line); - - gen_sptr dist = (gen_sptr)last_valid.Text.Ptr - (gen_sptr)scope_start.Text.Ptr + 2; - gen_sptr length_from_err = dist; - - gen_Str err_str = { last_valid.Text.Ptr, length_from_err }; - gen_StrBuilder line_from_err = gen_strbuilder_make_str(temp, err_str); - - if (length_from_err < 100) - gen_strbuilder_append_fmt(&result, "\t(%d, %d):%*c\n", last_valid.Line, last_valid.Column, length_from_err, '^'); - else - gen_strbuilder_append_fmt(&result, "\t(%d, %d)\n", last_valid.Line, last_valid.Column); - - gen_ParseStackNode* curr_scope = ctx->scope; - gen_s32 level = 0; - do - { - if (curr_scope->name.Ptr) - { - gen_strbuilder_append_fmt(&result, "\t%d: %S, gen_AST Name: %S\n", level, curr_scope->proc_name, curr_scope->name); - } - else - { - gen_strbuilder_append_fmt(&result, "\t%d: %S\n", level, curr_scope->proc_name); - } - - curr_scope = curr_scope->prev; - level++; - } while (curr_scope); - return result; -} - -bool gen_lex__eat(gen_Context* ctx, gen_ParseContext* parser, gen_TokType type) -{ - if (parser->tokens.num - parser->gen_token_id <= 0) - { - gen_log_failure("No tokens left.\n%SB", gen_parser_to_strbuilder(parser, ctx->Allocator_Temp)); - return false; - } - - gen_Token at_idx = parser->tokens.ptr[parser->gen_token_id]; - - if ((at_idx.Type == Tok_NewLine && type != Tok_NewLine) || (at_idx.Type == Tok_Comment && type != Tok_Comment)) - { - parser->gen_token_id++; - } - - gen_b32 not_accepted = at_idx.Type != type; - gen_b32 is_identifier = at_idx.Type == Tok_Identifier; - if (not_accepted) - { - gen_Macro* macro = lookup_macro(at_idx.Text); - gen_b32 accept_as_identifier = macro && gen_bitfield_is_set(gen_MacroFlags, macro->Flags, MF_Allow_As_Identifier); - not_accepted = type == Tok_Identifier && accept_as_identifier ? false : true; - } - if (not_accepted) - { - gen_Token tok = *gen_lex_current(parser, gen_lex_skip_formatting); - gen_log_failure( - "Parse Error, gen_TokArray::eat, Expected: ' %S ' not ' %S ' (%d, %d)`\n%SB", - gen_toktype_to_str(type), - at_idx.Text, - tok.Line, - tok.Column, - gen_parser_to_strbuilder(parser, ctx->Allocator_Temp) - ); - GEN_DEBUG_TRAP(); - return false; - } - -#if 0 && GEN_BUILD_DEBUG - gen_log_fmt("Ate: %SB\n", self->Arr[Idx].to_strbuilder() ); -#endif - - parser->gen_token_id++; - return true; -} - -gen_internal void gen_parser_init(gen_Context* ctx) -{ -} - -gen_internal void gen_parser_deinit(gen_Context* ctx) -{ -} - -#pragma region Helper Macros - - -#define check_parse_args(def) _check_parse_args(&ctx->parser, def, gen_stringize(_func_)) - -bool _check_parse_args(gen_ParseContext* parser, gen_Str def, char const* func_name) -{ - if (def.Len <= 0) - { - gen_log_failure(gen_c_str_fmt_buf("gen::%s: length must greater than 0", func_name)); - gen_parser_pop(parser); - return false; - } - if (def.Ptr == gen_nullptr) - { - gen_log_failure(gen_c_str_fmt_buf("gen::%s: def was null", func_name)); - gen_parser_pop(parser); - return false; - } - return true; -} - -#define currtok_noskip (*gen_lex_current(&ctx->parser, gen_lex_dont_skip_formatting)) -#define currtok (*gen_lex_current(&ctx->parser, gen_lex_skip_formatting)) -#define peektok (*gen_lex_peek(&ctx->parser, gen_lex_skip_formatting)) -#define prevtok (*gen_lex_previous(&ctx->parser, gen_lex_dont_skip_formatting)) -#define nexttok (*gen_lex_next(&ctx->parser, gen_lex_skip_formatting)) -#define nexttok_noskip (*gen_lex_next(&ctx->parser, gen_lex_dont_skip_formatting)) -#define eat(Type_) gen_lex__eat(ctx, &ctx->parser, Type_) -#define left (ctx->parser.tokens.num - ctx->parser.gen_token_id) - -#if GEN_COMPILER_CPP -#define gen_def_assign(...) { __VA_ARGS__ } -#else -#define gen_def_assign(...) __VA_ARGS__ -#endif - -#ifdef check - -#define CHECK_WAS_DEFINED - -#pragma push_macro("check") - -#undef check -#endif - -#define check_noskip(Type_) (left && currtok_noskip.Type == Type_) -#define check(Type_) (left && currtok.Type == Type_) - -#if GEN_COMPILER_CPP -#define NullScope \ - { \ - gen_nullptr, { gen_nullptr, 0 }, gen_lex_current(&ctx->parser, gen_lex_dont_skip_formatting), gen_Str { gen_nullptr, 0 }, gen_txt(__func__), \ - { \ - gen_nullptr \ - } \ - } -#else -#define NullScope \ - (gen_ParseStackNode) \ - { \ - gen_nullptr, { gen_nullptr, 0 }, gen_lex_current(&ctx->parser, gen_lex_dont_skip_formatting), (gen_Str) { gen_nullptr, 0 }, gen_txt(__func__), \ - { \ - gen_nullptr \ - } \ - } -#endif - -#pragma endregion Helper Macros - - -// Procedure Forwards ( Entire parser gen_internal parser interface ) - -gen_internal gen_Code gen_parse_array_decl(gen_Context* ctx); -gen_internal gen_CodeAttributes gen_parse_attributes(gen_Context* ctx); -gen_internal gen_CodeComment gen_parse_comment(gen_Context* ctx); -gen_internal gen_Code gen_parse_complicated_definition(gen_Context* ctx, gen_TokType which); -gen_internal gen_CodeBody gen_parse_class_struct_body(gen_Context* ctx, gen_TokType which, gen_Token name); -gen_internal gen_Code gen_parse_class_struct(gen_Context* ctx, gen_TokType which, bool inplace_def); -gen_internal gen_Code gen_parse_expression(gen_Context* ctx); -gen_internal gen_Code gen_parse_forward_or_definition(gen_Context* ctx, gen_TokType which, bool is_inplace); -gen_internal gen_CodeFn gen_parse_function_after_name( - gen_Context* ctx, - gen_ModuleFlag mflags, - gen_CodeAttributes attributes, - gen_CodeSpecifiers specifiers, - gen_CodeTypename ret_type, - gen_Token name - ); -gen_internal gen_Code gen_parse_function_body(gen_Context* ctx); -gen_internal gen_CodeBody gen_parse_global_nspace(gen_Context* ctx, gen_CodeType which); -gen_internal gen_Code gen_parse_global_nspace_constructor_destructor(gen_Context* ctx, gen_CodeSpecifiers specifiers); -gen_internal gen_Token gen_parse_identifier(gen_Context* ctx, bool* possible_member_function); -gen_internal gen_CodeInclude gen_parse_include(gen_Context* ctx); -gen_internal gen_Code gen_parse_macro_as_definiton(gen_Context* ctx, gen_CodeAttributes attributes, gen_CodeSpecifiers specifiers); -gen_internal gen_CodeOperator gen_parse_operator_after_ret_type( - gen_Context* ctx, - gen_ModuleFlag mflags, - gen_CodeAttributes attributes, - gen_CodeSpecifiers specifiers, - gen_CodeTypename ret_type -); -gen_internal gen_Code - gen_parse_operator_function_or_variable(gen_Context* ctx, bool expects_function, gen_CodeAttributes attributes, gen_CodeSpecifiers specifiers); -gen_internal gen_CodePragma gen_parse_pragma(gen_Context* ctx); -gen_internal gen_CodeParams gen_parse_params(gen_Context* ctx, bool use_template_capture); -gen_internal gen_CodePreprocessCond gen_parse_preprocess_cond(gen_Context* ctx); -gen_internal gen_Code gen_parse_simple_preprocess(gen_Context* ctx, gen_TokType which); -gen_internal gen_Code gen_parse_static_assert(gen_Context* ctx); -gen_internal void gen_parse_template_args(gen_Context* ctx, gen_Token* token); -gen_internal gen_CodeVar gen_parse_variable_after_name( - gen_Context* ctx, - gen_ModuleFlag mflags, - gen_CodeAttributes attributes, - gen_CodeSpecifiers specifiers, - gen_CodeTypename type, - gen_Str name - ); -gen_internal gen_CodeVar gen_parse_variable_declaration_list(gen_Context* ctx); - -gen_internal gen_CodeClass gen_parser_parse_class(gen_Context* ctx, bool inplace_def); -gen_internal gen_CodeConstructor gen_parser_parse_constructor(gen_Context* ctx, gen_CodeSpecifiers specifiers); -gen_internal gen_CodeDefine gen_parser_parse_define(gen_Context* ctx); -gen_internal gen_CodeDestructor gen_parser_parse_destructor(gen_Context* ctx, gen_CodeSpecifiers specifiers); -gen_internal gen_CodeEnum gen_parser_parse_enum(gen_Context* ctx, bool inplace_def); -gen_internal gen_CodeBody gen_parser_parse_export_body(gen_Context* ctx); -gen_internal gen_CodeBody gen_parser_parse_extern_link_body(gen_Context* ctx); -gen_internal gen_CodeExtern gen_parser_parse_extern_link(gen_Context* ctx); -gen_internal gen_CodeFriend gen_parser_parse_friend(gen_Context* ctx); -gen_internal gen_CodeFn gen_parser_parse_function(gen_Context* ctx); -gen_internal gen_CodeNS gen_parser_parse_namespace(gen_Context* ctx); -gen_internal gen_CodeOpCast gen_parser_parse_operator_cast(gen_Context* ctx, gen_CodeSpecifiers specifiers); -gen_internal gen_CodeStruct gen_parser_parse_struct(gen_Context* ctx, bool inplace_def); -gen_internal gen_CodeVar gen_parser_parse_variable(gen_Context* ctx); -gen_internal gen_CodeTemplate gen_parser_parse_template(gen_Context* ctx); -gen_internal gen_CodeTypename gen_parser_parse_type(gen_Context* ctx, bool from_template, bool* is_function); -gen_internal gen_CodeTypedef gen_parser_parse_typedef(gen_Context* ctx); -gen_internal gen_CodeUnion gen_parser_parse_union(gen_Context* ctx, bool inplace_def); -gen_internal gen_CodeUsing gen_parser_parse_using(gen_Context* ctx); - -#define gen_parser_inplace_def (bool)true -#define gen_parser_not_inplace_def (bool)false -#define gen_parser_dont_consume_braces (bool)true -#define gen_parser_consume_braces (bool)false -#define gen_parser_not_from_template (bool)false - -#define gen_parser_use_parenthesis (bool)false - -// Internal parsing functions - -#define gen_parser_strip_formatting_dont_preserve_newlines (bool)false - -/* - This function was an attempt at stripping formatting from any c++ code. - It has edge case failures that prevent it from being used in function bodies. -*/ -gen_internal gen_StrBuilder gen_parser_strip_formatting(gen_Context* ctx, gen_Str raw_text, bool preserve_newlines) -{ - gen_StrBuilder content = gen_strbuilder_make_reserve(ctx->Allocator_Temp, raw_text.Len); - - if (raw_text.Len == 0) - return content; - -#define cut_length (scanner - raw_text.Ptr - last_cut) -#define cut_ptr (raw_text.Ptr + last_cut) -#define pos (gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr)) -#define move_fwd() \ - do \ - { \ - scanner++; \ - tokleft--; \ - } while (0) - - gen_s32 tokleft = raw_text.Len; - gen_sptr last_cut = 0; - char const* scanner = raw_text.Ptr; - - if (scanner[0] == ' ') - { - move_fwd(); - last_cut = 1; - } - - bool within_string = false; - bool within_char = false; - bool must_keep_newline = false; - while (tokleft) - { - // Skip over the content of string literals - if (scanner[0] == '"') - { - move_fwd(); - - while (tokleft && (scanner[0] != '"' || *(scanner - 1) == '\\')) - { - if (scanner[0] == '\\' && tokleft > 1) - { - scanner += 2; - tokleft -= 2; - } - else - { - move_fwd(); - } - } - - // Skip the closing " - if (tokleft) - move_fwd(); - - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - continue; - } - - // Skip over the content of character literals - if (scanner[0] == '\'') - { - move_fwd(); - - while (tokleft && (scanner[0] != '\'' || (*(scanner - 1) == '\\'))) - { - move_fwd(); - } - - // Skip the closing ' - if (tokleft) - move_fwd(); - - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - continue; - } - - // Block comments - if (tokleft > 1 && scanner[0] == '/' && scanner[1] == '*') - { - while (tokleft > 1 && ! (scanner[0] == '*' && scanner[1] == '/')) - move_fwd(); - - scanner += 2; - tokleft -= 2; - - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - continue; - } - - // Line comments - if (tokleft > 1 && scanner[0] == '/' && scanner[1] == '/') - { - must_keep_newline = true; - - scanner += 2; - tokleft -= 2; - - while (tokleft && scanner[0] != '\n') - move_fwd(); - - if (tokleft) - move_fwd(); - - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - continue; - } - - // Tabs - if (scanner[0] == '\t') - { - if (pos > last_cut) - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - - if (*gen_strbuilder_back(content) != ' ') - gen_strbuilder_append_char(&content, ' '); - - move_fwd(); - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - continue; - } - - if (tokleft > 1 && scanner[0] == '\r' && scanner[1] == '\n') - { - if (must_keep_newline || preserve_newlines) - { - must_keep_newline = false; - - scanner += 2; - tokleft -= 2; - - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - continue; - } - - if (pos > last_cut) - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - - // Replace with a space - if (*gen_strbuilder_back(content) != ' ') - gen_strbuilder_append_char(&content, ' '); - - scanner += 2; - tokleft -= 2; - - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - continue; - } - - if (scanner[0] == '\n') - { - if (must_keep_newline || preserve_newlines) - { - must_keep_newline = false; - - move_fwd(); - - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - continue; - } - - if (pos > last_cut) - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - - // Replace with a space - if (*gen_strbuilder_back(content) != ' ') - gen_strbuilder_append_char(&content, ' '); - - move_fwd(); - - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - continue; - } - - // Escaped newlines - if (scanner[0] == '\\') - { - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - - gen_s32 amount_to_skip = 1; - if (tokleft > 1 && scanner[1] == '\n') - { - amount_to_skip = 2; - } - else if (tokleft > 2 && scanner[1] == '\r' && scanner[2] == '\n') - { - amount_to_skip = 3; - } - - if (amount_to_skip > 1 && pos == last_cut) - { - scanner += amount_to_skip; - tokleft -= amount_to_skip; - } - else - move_fwd(); - - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - continue; - } - - // Consectuive spaces - if (tokleft > 1 && gen_char_is_space(scanner[0]) && gen_char_is_space(scanner[1])) - { - gen_strbuilder_append_c_str_len(&content, cut_ptr, cut_length); - do - { - move_fwd(); - } while (tokleft && gen_char_is_space(scanner[0])); - - last_cut = gen_rcast(gen_sptr, scanner) - gen_rcast(gen_sptr, raw_text.Ptr); - - // Preserve only 1 space of formattting - char* last = gen_strbuilder_back(content); - if (last == gen_nullptr || *last != ' ') - gen_strbuilder_append_char(&content, ' '); - - continue; - } - - move_fwd(); - } - - if (last_cut < raw_text.Len) - { - gen_strbuilder_append_c_str_len(&content, cut_ptr, raw_text.Len - last_cut); - } - -#undef cut_ptr -#undef cut_length -#undef pos -#undef move_fwd - - return content; -} - -gen_StrBuilder gen_parser_strip_formatting_2(TokenSlice tokens) -{ - // TODO(Ed): Use this to produce strings for validation purposes. We shouldn't serialize down from tokens once we start storing token slices for content. - gen_StrBuilder result = gen_struct_zero(gen_StrBuilder); - return result; -} - -gen_internal gen_Code gen_parse_array_decl(gen_Context* ctx) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - if (check(Tok_Operator) && currtok.Text.Ptr[0] == '[' && currtok.Text.Ptr[1] == ']') - { - gen_Code gen_array_expr = gen_untyped_str(gen_txt(" ")); - eat(Tok_Operator); - // [] - - gen_parser_pop(&ctx->parser); - return gen_array_expr; - } - - if (check(Tok_BraceSquare_Open)) - { - eat(Tok_BraceSquare_Open); - // [ - - if (left == 0) - { - gen_log_failure( - "Error, unexpected end of array declaration ( '[]' scope started )\n%SB", - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - - if (currtok.Type == Tok_BraceSquare_Close) - { - gen_log_failure("Error, empty array expression in definition\n%SB", gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp)); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - - TokenSlice tokens = { &currtok, 1 }; - gen_Token gen_untyped_tok = currtok; - - while (left && currtok.Type != Tok_BraceSquare_Close) - { - eat(currtok.Type); - ++tokens.num; - } - - // gen_untyped_tok.Text.Len = ( (gen_sptr)prevtok.Text.Ptr + prevtok.Text.Len ) - (gen_sptr)gen_untyped_tok.Text.Ptr; - gen_untyped_tok.Text = gen_token_range_to_str(gen_untyped_tok, prevtok); - - gen_Code gen_array_expr = gen_untyped_str(gen_untyped_tok.Text); - // gen_Code gen_array_expr = gen_untyped_toks( tokens ); // TODO(Ed): Use token slice instead of untyped strings. - // [ - - if (left == 0) - { - gen_log_failure("Error, unexpected end of array declaration, expected ]\n%SB", gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp)); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - - if (currtok.Type != Tok_BraceSquare_Close) - { - gen_log_failure( - "%s: Error, expected ] in array declaration, not %S\n%SB", - gen_toktype_to_str(currtok.Type), - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - - eat(Tok_BraceSquare_Close); - // [ ] - - // Its a multi-dimensional array - if (check(Tok_BraceSquare_Open)) - { - gen_Code adjacent_arr_expr = gen_parse_array_decl(ctx); - // [ ][ ]... - - gen_array_expr->Next = adjacent_arr_expr; - } - - gen_parser_pop(&ctx->parser); - return gen_array_expr; - } - - gen_parser_pop(&ctx->parser); - return gen_NullCode; -} - -gen_internal inline gen_CodeAttributes gen_parse_attributes(gen_Context* ctx) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - gen_Token start = currtok; - gen_s32 len = 0; - - // There can be more than one attribute. If there is flatten them to a single string. - // TODO(Ed): Support chaining attributes (Use parameter linkage pattern) - while (left && gen_tok_is_attribute(currtok)) - { - if (check(Tok_Attribute_Open)) - { - eat(Tok_Attribute_Open); - // [[ - - while (left && currtok.Type != Tok_Attribute_Close) - { - eat(currtok.Type); - } - // [[ - - eat(Tok_Attribute_Close); - // [[ ]] - - len = ((gen_sptr)prevtok.Text.Ptr + prevtok.Text.Len) - (gen_sptr)start.Text.Ptr; - } - else if (check(Tok_Decl_GNU_Attribute)) - { - eat(Tok_Decl_GNU_Attribute); - eat(Tok_Paren_Open); - eat(Tok_Paren_Open); - // __attribute__(( - - while (left && currtok.Type != Tok_Paren_Close) - { - eat(currtok.Type); - } - // __attribute__(( - - eat(Tok_Paren_Close); - eat(Tok_Paren_Close); - // __attribute__(( )) - - len = ((gen_sptr)prevtok.Text.Ptr + prevtok.Text.Len) - (gen_sptr)start.Text.Ptr; - } - else if (check(Tok_Decl_MSVC_Attribute)) - { - eat(Tok_Decl_MSVC_Attribute); - eat(Tok_Paren_Open); - // __declspec( - - while (left && currtok.Type != Tok_Paren_Close) - { - eat(currtok.Type); - } - // __declspec( - - eat(Tok_Paren_Close); - // __declspec( ) - - len = ((gen_sptr)prevtok.Text.Ptr + prevtok.Text.Len) - (gen_sptr)start.Text.Ptr; - } - else if (gen_tok_is_attribute(currtok)) - { - eat(currtok.Type); - // - - // If its a macro based attribute, this could be a functional macro such as Unreal's UE_DEPRECATED(...) - if (check(Tok_Paren_Open)) - { - eat(Tok_Paren_Open); - - gen_s32 level = 0; - while (left && currtok.Type != Tok_Paren_Close && level == 0) - { - if (currtok.Type == Tok_Paren_Open) - ++level; - if (currtok.Type == Tok_Paren_Close) - --level; - eat(currtok.Type); - } - eat(Tok_Paren_Close); - } - - len = ((gen_sptr)prevtok.Text.Ptr + prevtok.Text.Len) - (gen_sptr)start.Text.Ptr; - // ( ... ) - } - } - - if (len > 0) - { - gen_Str attribute_txt = { start.Text.Ptr, len }; - gen_parser_pop(&ctx->parser); - - gen_StrBuilder name_stripped = gen_parser_strip_formatting(ctx, attribute_txt, gen_parser_strip_formatting_dont_preserve_newlines); - - gen_Code result = gen_make_code(); - result->Type = CT_PlatformAttributes; - result->Name = gen_cache_str(gen_strbuilder_to_str(name_stripped)); - result->Content = result->Name; - // result->gen_Token = - return (gen_CodeAttributes)result; - } - - gen_parser_pop(&ctx->parser); - return gen_NullCode; -} - -gen_internal gen_Code gen_parse_class_struct(gen_Context* ctx, gen_TokType which, bool inplace_def) -{ - if (which != Tok_Decl_Class && which != Tok_Decl_Struct) - { - gen_log_failure("Error, expected class or struct, not %S\n%SB", gen_toktype_to_str(which), gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp)); - return gen_InvalidCode; - } - - gen_Token name = gen_NullToken; - - gen_AccessSpec access = AccessSpec_Default; - gen_CodeTypename parent = { gen_nullptr }; - gen_CodeBody body = { gen_nullptr }; - gen_CodeAttributes attributes = { gen_nullptr }; - gen_ModuleFlag mflags = ModuleFlag_None; - - gen_Code result = gen_InvalidCode; - - if (check(Tok_Module_Export)) - { - mflags = ModuleFlag_Export; - eat(Tok_Module_Export); - } - // - - eat(which); - // - - attributes = gen_parse_attributes(ctx); - // - - if (check(Tok_Identifier)) - { - name = gen_parse_identifier(ctx, gen_nullptr); - ctx->parser.scope->name = name.Text; - } - // - - gen_CodeSpecifiers specifiers = gen_NullCode; - if (check(Tok_Spec_Final)) - { - specifiers = gen_def_specifier(Spec_Final); - eat(Tok_Spec_Final); - } - // - - gen_local_persist char interface_arr_mem[gen_kilobytes(4)] = { 0 }; - gen_Array(gen_CodeTypename) interfaces = { gen_nullptr }; - - // TODO(Ed) : Make an gen_AST_DerivedType, we'll store any arbitary derived type into there as a linear linked list of them. - if (check(Tok_Assign_Classifer)) - { - eat(Tok_Assign_Classifer); - // : - - if (gen_tok_is_access_specifier(currtok)) - { - access = gen_tok_to_access_specifier(currtok); - // : - eat(currtok.Type); - } - - gen_Token parent_tok = gen_parse_identifier(ctx, gen_nullptr); - parent = gen_def_type(parent_tok.Text); - // : - - if (check(Tok_Comma)) - { - gen_Arena arena = gen_arena_init_from_memory(interface_arr_mem, gen_kilobytes(4)); - interfaces = gen_array_init_reserve(gen_CodeTypename, gen_arena_allocator_info(&arena), 4); - do - { - eat(Tok_Comma); - // : , - - if (gen_tok_is_access_specifier(currtok)) - { - eat(currtok.Type); - } - gen_Token interface_tok = gen_parse_identifier(ctx, gen_nullptr); - - gen_array_append(interfaces, gen_def_type(interface_tok.Text)); - // : , ... - } while (check(Tok_Comma)); - } - } - - if (check(Tok_BraceCurly_Open)) - { - body = gen_parse_class_struct_body(ctx, which, name); - } - // : , ... { } - - gen_CodeComment inline_cmt = gen_NullCode; - if (! inplace_def) - { - gen_Token stmt_end = currtok; - eat(Tok_Statement_End); - // : , ... { }; - - if (currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line) - inline_cmt = gen_parse_comment(ctx); - // : , ... { }; - } - - gen_s32 num_interfaces = gen_scast(gen_s32, interfaces ? gen_array_num(interfaces) : 0); - - if (which == Tok_Decl_Class) - result = gen_cast(gen_Code, gen_def_class(name.Text, gen_def_assign(body, parent, access, attributes, interfaces, num_interfaces, specifiers, mflags))); - - else - result = gen_cast( - gen_Code, - gen_def_struct(name.Text, gen_def_assign(body, (gen_CodeTypename)parent, access, attributes, interfaces, num_interfaces, specifiers, mflags)) - ); - - if (inline_cmt) - result->InlineCmt = gen_cast(gen_Code, inline_cmt); - - if (interfaces) - gen_array_free(interfaces); - return result; -} - -gen_internal gen_neverinline gen_CodeBody gen_parse_class_struct_body(gen_Context* ctx, gen_TokType which, gen_Token name) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - eat(Tok_BraceCurly_Open); - // { - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - - if (which == Tok_Decl_Class) - result->Type = CT_Class_Body; - else - result->Type = CT_Struct_Body; - - while (left && currtok_noskip.Type != Tok_BraceCurly_Close) - { - gen_Code member = gen_Code_Invalid; - gen_CodeAttributes attributes = { gen_nullptr }; - gen_CodeSpecifiers specifiers = { gen_nullptr }; - - bool expects_function = false; - - // ctx->parser.Scope->Start = currtok_noskip; - - if (currtok_noskip.Type == Tok_Preprocess_Hash) - eat(Tok_Preprocess_Hash); - - switch (currtok_noskip.Type) - { - case Tok_Statement_End: - { - // TODO(Ed): Convert this to a general warning procedure - gen_log_fmt("Dangling end statement found %SB\n", gen_tok_to_strbuilder(ctx->Allocator_Temp, currtok_noskip)); - eat(Tok_Statement_End); - continue; - } - case Tok_NewLine: - { - member = gen_fmt_newline; - eat(Tok_NewLine); - break; - } - case Tok_Comment: - { - member = gen_cast(gen_Code, gen_parse_comment(ctx)); - break; - } - case Tok_Access_Public: - { - member = gen_access_public; - eat(Tok_Access_Public); - eat(Tok_Assign_Classifer); - // public: - break; - } - case Tok_Access_Protected: - { - member = gen_access_protected; - eat(Tok_Access_Protected); - eat(Tok_Assign_Classifer); - // protected: - break; - } - case Tok_Access_Private: - { - member = gen_access_private; - eat(Tok_Access_Private); - eat(Tok_Assign_Classifer); - // private: - break; - } - case Tok_Decl_Class: - { - member = gen_parse_complicated_definition(ctx, Tok_Decl_Class); - // class - break; - } - case Tok_Decl_Enum: - { - member = gen_parse_complicated_definition(ctx, Tok_Decl_Enum); - // enum - break; - } - case Tok_Decl_Friend: - { - member = gen_cast(gen_Code, gen_parser_parse_friend(ctx)); - // friend - break; - } - case Tok_Decl_Operator: - { - member = gen_cast(gen_Code, gen_parser_parse_operator_cast(ctx, gen_NullCode)); - // operator () - break; - } - case Tok_Decl_Struct: - { - member = gen_parse_complicated_definition(ctx, Tok_Decl_Struct); - // struct - break; - } - case Tok_Decl_Template: - { - member = gen_cast(gen_Code, gen_parser_parse_template(ctx)); - // template< ... > - break; - } - case Tok_Decl_Typedef: - { - member = gen_cast(gen_Code, gen_parser_parse_typedef(ctx)); - // typedef - break; - } - case Tok_Decl_Union: - { - member = gen_parse_complicated_definition(ctx, Tok_Decl_Union); - // union - break; - } - case Tok_Decl_Using: - { - member = gen_cast(gen_Code, gen_parser_parse_using(ctx)); - // using - break; - } - case Tok_Operator: - { - //if ( currtok.Text[0] != '~' ) - //{ - // gen_log_failure( "gen_Operator token found in gen_global body but not gen_destructor_ unary negation\n%s", to_strbuilder(ctx->parser) ); - // return gen_InvalidCode; - //} - - member = gen_cast(gen_Code, gen_parser_parse_destructor(ctx, gen_NullCode)); - // ~() - break; - } - case Tok_Preprocess_Define: - { - member = gen_cast(gen_Code, gen_parser_parse_define(ctx)); - // #define - break; - } - case Tok_Preprocess_Include: - { - member = gen_cast(gen_Code, gen_parse_include(ctx)); - // #include - break; - } - - case Tok_Preprocess_If: - case Tok_Preprocess_IfDef: - case Tok_Preprocess_IfNotDef: - case Tok_Preprocess_ElIf: - member = gen_cast(gen_Code, gen_parse_preprocess_cond(ctx)); - // # - break; - - case Tok_Preprocess_Else: - { - member = gen_cast(gen_Code, gen_preprocess_else); - eat(Tok_Preprocess_Else); - // #else - break; - } - case Tok_Preprocess_EndIf: - { - member = gen_cast(gen_Code, gen_preprocess_endif); - eat(Tok_Preprocess_EndIf); - // #endif - break; - } - - case Tok_Preprocess_Macro_Stmt: - { - member = gen_cast(gen_Code, gen_parse_simple_preprocess(ctx, Tok_Preprocess_Macro_Stmt)); - break; - } - - // case Tok_Preprocess_Macro: - // // - // gen_macro_found = true; - // goto Preprocess_Macro_Bare_In_Body; - // break; - - case Tok_Preprocess_Pragma: - { - member = gen_cast(gen_Code, gen_parse_pragma(ctx)); - // #pragma - break; - } - - case Tok_Preprocess_Unsupported: - { - member = gen_cast(gen_Code, gen_parse_simple_preprocess(ctx, Tok_Preprocess_Unsupported)); - // # - break; - } - - case Tok_StaticAssert: - { - member = gen_parse_static_assert(ctx); - // gen_static_assert - break; - } - - case Tok_Preprocess_Macro_Expr: - { - if (! gen_tok_is_attribute(currtok)) - { - gen_log_failure( - "Unbounded macro expression residing in class/struct body\n%S", - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - return gen_InvalidCode; - } - } - //! Fallthrough intended - case Tok_Attribute_Open: - case Tok_Decl_GNU_Attribute: - case Tok_Decl_MSVC_Attribute: -#define Entry(attribute, str) case attribute: - GEN_DEFINE_ATTRIBUTE_TOKENS -#undef Entry - { - attributes = gen_parse_attributes(ctx); - // - } - //! Fallthrough intended - GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_TOK_SPECIFIER_CASES: - { - gen_Specifier specs_found[16] = { Spec_NumSpecifiers }; - gen_s32 NumSpecifiers = 0; - - while (left && gen_tok_is_specifier(currtok)) - { - gen_Specifier spec = gen_str_to_specifier(currtok.Text); - - gen_b32 ignore_spec = false; - - switch (spec) - { - GEN_PARSER_CLASS_STRUCT_BODY_ALLOWED_MEMBER_SPECIFIER_CASES: - break; - - case Spec_Consteval: - expects_function = true; - break; - - case Spec_Const: - ignore_spec = true; - break; - - default: - gen_log_failure( - "Invalid specifier %S for class/struct member\n%S", - gen_spec_to_str(spec), - gen_strbuilder_to_str(gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp)) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - - // Every specifier after would be considered part of the type type signature - if (ignore_spec) - break; - - specs_found[NumSpecifiers] = spec; - NumSpecifiers++; - eat(currtok.Type); - } - - if (NumSpecifiers) - { - specifiers = gen_def_specifiers_arr(NumSpecifiers, specs_found); - } - // - - if (gen_tok_is_attribute(currtok)) - { - // Unfortuantely Unreal has code where there is attirbutes before specifiers - gen_CodeAttributes more_attributes = gen_parse_attributes(ctx); - - if (attributes) - { - gen_StrBuilder fused = gen_strbuilder_make_reserve(ctx->Allocator_Temp, attributes->Content.Len + more_attributes->Content.Len); - gen_strbuilder_append_fmt(&fused, "%SB %SB", attributes->Content, more_attributes->Content); - - gen_Str attrib_name = gen_strbuilder_to_str(fused); - attributes->Name = gen_cache_str(attrib_name); - attributes->Content = attributes->Name; - // - } - - attributes = more_attributes; - } - - if (currtok.Type == Tok_Operator && currtok.Text.Ptr[0] == '~') - { - member = gen_cast(gen_Code, gen_parser_parse_destructor(ctx, specifiers)); - // ~() - break; - } - - if (currtok.Type == Tok_Decl_Operator) - { - member = gen_cast(gen_Code, gen_parser_parse_operator_cast(ctx, specifiers)); - // operator () - break; - } - } - //! Fallthrough intentional - case Tok_Identifier: - case Tok_Preprocess_Macro_Typename: - case Tok_Spec_Const: - case Tok_Type_Unsigned: - case Tok_Type_Signed: - case Tok_Type_Short: - case Tok_Type_Long: - case Tok_Type_bool: - case Tok_Type_char: - case Tok_Type_int: - case Tok_Type_double: - { - if (nexttok.Type == Tok_Paren_Open && name.Text.Len && currtok.Type == Tok_Identifier) - { - if (gen_c_str_compare_len(name.Text.Ptr, currtok.Text.Ptr, name.Text.Len) == 0) - { - member = gen_cast(gen_Code, gen_parser_parse_constructor(ctx, specifiers)); - // () - break; - } - } - - member = gen_parse_operator_function_or_variable(ctx, expects_function, attributes, specifiers); - // operator ... - // or - // ... - } - break; - - default: - gen_Token gen_untyped_tok = currtok; - while (left && currtok.Type != Tok_BraceCurly_Close) - { - gen_untyped_tok.Text.Len = ((gen_sptr)currtok.Text.Ptr + currtok.Text.Len) - (gen_sptr)gen_untyped_tok.Text.Ptr; - eat(currtok.Type); - } - member = gen_untyped_str(gen_untyped_tok.Text); - // Something unknown - break; - } - - if (member == gen_Code_Invalid) - { - gen_log_failure("Failed to parse member\n%SB", gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp)); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - gen_body_append(result, member); - } - - eat(Tok_BraceCurly_Close); - // { } - gen_parser_pop(&ctx->parser); - return result; -} - -gen_internal gen_CodeComment gen_parse_comment(gen_Context* ctx) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - gen_CodeComment result = (gen_CodeComment)gen_make_code(); - result->Type = CT_Comment; - result->Content = gen_cache_str(currtok_noskip.Text); - // result->gen_Token = currtok_noskip; - eat(Tok_Comment); - - gen_parser_pop(&ctx->parser); - return result; -} - -gen_internal gen_Code gen_parse_complicated_definition(gen_Context* ctx, gen_TokType which) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - gen_b32 is_inplace = false; - gen_b32 is_fn_def = false; - - TokenSlice tokens = ctx->parser.tokens; - - gen_s32 idx = ctx->parser.gen_token_id; - gen_s32 level = 0; - gen_b32 had_def = false; - gen_b32 had_paren = false; - for (; idx < tokens.num; idx++) - { - if (tokens.ptr[idx].Type == Tok_BraceCurly_Open) - level++; - - if (tokens.ptr[idx].Type == Tok_BraceCurly_Close) - { - level--; - had_def = level == 0; - } - - gen_b32 found_fn_def = had_def && had_paren; - - if (level == 0 && (tokens.ptr[idx].Type == Tok_Statement_End || found_fn_def)) - break; - } - - is_fn_def = had_def && had_paren; - if (is_fn_def) - { - // Function definition with on return type - gen_Code result = gen_parse_operator_function_or_variable(ctx, false, gen_NullCode, gen_NullCode); - // (...) ... { ... } - gen_parser_pop(&ctx->parser); - return result; - } - - if ((idx - 2) == ctx->parser.gen_token_id) - { - // It's a forward declaration only - gen_Code result = gen_parse_forward_or_definition(ctx, which, is_inplace); - // ; - gen_parser_pop(&ctx->parser); - return result; - } - - gen_Token tok = tokens.ptr[idx - 1]; - if (gen_tok_is_specifier(tok) && gen_spec_is_trailing(gen_str_to_specifier(tok.Text))) - { - // (...) ...; - - gen_s32 gen_spec_idx = idx - 1; - gen_Token spec = tokens.ptr[gen_spec_idx]; - while (gen_tok_is_specifier(spec) && gen_spec_is_trailing(gen_str_to_specifier(spec.Text))) - { - --gen_spec_idx; - spec = tokens.ptr[gen_spec_idx]; - } - - if (tokens.ptr[gen_spec_idx].Type == Tok_Paren_Close) - { - // Forward declaration with trailing specifiers for a procedure - tok = tokens.ptr[gen_spec_idx]; - - gen_Code result = gen_parse_operator_function_or_variable(ctx, false, gen_NullCode, gen_NullCode); - // , or Name> ... - gen_parser_pop(&ctx->parser); - return result; - } - - gen_log_failure( - "Unsupported or bad member definition after %S declaration\n%SB", - gen_toktype_to_str(which), - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - if (tok.Type == Tok_Identifier) - { - tok = tokens.ptr[idx - 2]; - bool is_indirection = tok.Type == Tok_Ampersand || tok.Type == Tok_Star; - bool ok_to_parse = false; - - if (tok.Type == Tok_BraceCurly_Close) - { - // Its an inplace definition - // { ... } ; - ok_to_parse = true; - is_inplace = true; - - gen_CodeTypename type = gen_cast(gen_CodeTypename, gen_parse_forward_or_definition(ctx, which, is_inplace)); - - // Should be a name right after the type. - gen_Token name = gen_parse_identifier(ctx, gen_nullptr); - ctx->parser.scope->name = name.Text; - - gen_CodeVar result = gen_parse_variable_after_name(ctx, ModuleFlag_None, gen_NullCode, gen_NullCode, type, name.Text); - gen_parser_pop(&ctx->parser); - return (gen_Code)result; - } - else if (tok.Type == Tok_Identifier && tokens.ptr[idx - 3].Type == which) - { - // Its a variable with type ID using namespace. - // ; - ok_to_parse = true; - } - else if (tok.Type == Tok_Assign_Classifer - && ((tokens.ptr[idx - 5].Type == which && tokens.ptr[idx - 4].Type == Tok_Decl_Class) || (tokens.ptr[idx - 4].Type == which))) - { - // Its a forward declaration of an enum - // : ; - // : ; - ok_to_parse = true; - gen_Code result = gen_cast(gen_Code, gen_parser_parse_enum(ctx, ! gen_parser_inplace_def)); - gen_parser_pop(&ctx->parser); - return result; - } - else if (is_indirection) - { - // Its a indirection type with type ID using struct namespace. - // * ; - ok_to_parse = true; - } - - if (! ok_to_parse) - { - gen_log_failure( - "Unsupported or bad member definition after %S declaration\n%SB", - gen_toktype_to_str(which), - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - - gen_Code result = gen_parse_operator_function_or_variable(ctx, false, gen_NullCode, gen_NullCode); - // , or Name> ... - gen_parser_pop(&ctx->parser); - return result; - } - else if (tok.Type >= Tok_Type_Unsigned && tok.Type <= Tok_Type_MS_W64) - { - tok = tokens.ptr[idx - 2]; - - if (tok.Type != Tok_Assign_Classifer - || ((tokens.ptr[idx - 5].Type != which && tokens.ptr[idx - 4].Type != Tok_Decl_Class) && (tokens.ptr[idx - 4].Type != which))) - { - gen_log_failure( - "Unsupported or bad member definition after %S declaration\n%SB", - gen_toktype_to_str(which), - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - - // Its a forward declaration of an enum class - // : ; - // : ; - gen_Code result = gen_cast(gen_Code, gen_parser_parse_enum(ctx, ! gen_parser_inplace_def)); - gen_parser_pop(&ctx->parser); - return result; - } - else if (tok.Type == Tok_BraceCurly_Close) - { - // Its a definition - gen_Code result = gen_parse_forward_or_definition(ctx, which, is_inplace); - // { ... }; - gen_parser_pop(&ctx->parser); - return result; - } - else if (tok.Type == Tok_BraceSquare_Close) - { - // Its an array definition - gen_Code result = gen_parse_operator_function_or_variable(ctx, false, gen_NullCode, gen_NullCode); - // [ ... ]; - gen_parser_pop(&ctx->parser); - return result; - } - else - { - gen_log_failure( - "Unsupported or bad member definition after %S declaration\n%SB", - gen_toktype_to_str(which).Ptr, - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } -} - -gen_internal inline gen_Code gen_parse_assignment_expression(gen_Context* ctx) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - gen_Code expr = { gen_nullptr }; - - eat(Tok_Operator); - // = - - gen_Token expr_tok = currtok; - - if (currtok.Type == Tok_Statement_End && currtok.Type != Tok_Comma) - { - gen_log_failure("Expected expression after assignment operator\n%SB", gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp)); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - - gen_s32 level = 0; - while (left && currtok.Type != Tok_Statement_End && (currtok.Type != Tok_Comma || level > 0)) - { - if (currtok.Type == Tok_BraceCurly_Open) - level++; - if (currtok.Type == Tok_BraceCurly_Close) - level--; - if (currtok.Type == Tok_Paren_Open) - level++; - else if (currtok.Type == Tok_Paren_Close) - level--; - - eat(currtok.Type); - } - - 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); - // = - - gen_parser_pop(&ctx->parser); - return expr; -} - -gen_internal inline gen_Code gen_parse_forward_or_definition(gen_Context* ctx, gen_TokType which, bool is_inplace) -{ - gen_Code result = gen_InvalidCode; - - switch (which) - { - case Tok_Decl_Class: - result = gen_cast(gen_Code, gen_parser_parse_class(ctx, is_inplace)); - return result; - - case Tok_Decl_Enum: - result = gen_cast(gen_Code, gen_parser_parse_enum(ctx, is_inplace)); - return result; - - case Tok_Decl_Struct: - result = gen_cast(gen_Code, gen_parser_parse_struct(ctx, is_inplace)); - return result; - - case Tok_Decl_Union: - result = gen_cast(gen_Code, gen_parser_parse_union(ctx, is_inplace)); - return result; - - default: - gen_log_failure( - "Error, wrong token type given to gen_parse_complicated_definition " - "(only supports class, enum, struct, union) \n%SB", - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - - return gen_InvalidCode; - } -} - -// Function parsing is handled in multiple places because its initial signature is shared with variable parsing -gen_internal inline gen_CodeFn gen_parse_function_after_name( - gen_Context* ctx, - gen_ModuleFlag mflags, - gen_CodeAttributes attributes, - gen_CodeSpecifiers specifiers, - gen_CodeTypename ret_type, - gen_Token name -) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - gen_CodeParams params = gen_parse_params(ctx, gen_parser_use_parenthesis); - // ( ) - - gen_Code suffix_specs = gen_NullCode; - - // TODO(Ed), Review old comment : These have to be kept separate from the return type's specifiers. - while (left && gen_tok_is_specifier(currtok)) - { - // For Unreal's PURE_VIRTUAL Support - gen_Macro* macro = lookup_macro(currtok.Text); - if (macro && gen_tok_is_specifier(currtok)) - { - suffix_specs = gen_parse_simple_preprocess(ctx, Tok_Preprocess_Macro_Expr); - continue; - } - if (specifiers == gen_nullptr) - { - specifiers = gen_def_specifier(gen_str_to_specifier(currtok.Text)); - eat(currtok.Type); - continue; - } - - gen_specifiers_append(specifiers, gen_str_to_specifier(currtok.Text)); - eat(currtok.Type); - } - // ( ) - - // Check for trailing specifiers... - gen_CodeAttributes post_rt_attributes = gen_parse_attributes(ctx); - if (post_rt_attributes) - { - if (attributes) - { - gen_StrBuilder merged = gen_strbuilder_fmt_buf(ctx->Allocator_Temp, "%S %S", attributes->Content, post_rt_attributes->Content); - attributes->Content = gen_cache_str(gen_strbuilder_to_str(merged)); - } - else - { - attributes = post_rt_attributes; - } - } - // ( ) - - gen_CodeBody body = gen_NullCode; - gen_CodeComment inline_cmt = gen_NullCode; - if (check(Tok_BraceCurly_Open)) - { - body = gen_cast(gen_CodeBody, gen_parse_function_body(ctx)); - if (gen_cast(gen_Code, body) == gen_Code_Invalid) - { - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - // ( ) { } - } - else if (check(Tok_Operator) && currtok.Text.Ptr[0] == '=') - { - eat(Tok_Operator); - if (specifiers == gen_nullptr) - { - specifiers = (gen_CodeSpecifiers)gen_make_code(); - specifiers->Type = CT_Specifiers; - } - if (gen_str_are_equal(nexttok.Text, gen_txt("delete"))) - { - gen_specifiers_append(specifiers, Spec_Delete); - eat(currtok.Type); - // ( ) = delete - } - else - { - gen_specifiers_append(specifiers, Spec_Pure); - - eat(Tok_Number); - // ( ) = 0 - } - gen_Token stmt_end = currtok; - eat(Tok_Statement_End); - - if (currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line) - inline_cmt = gen_parse_comment(ctx); - // ( ) < = 0 or delete > ; - } - - - if (body == gen_nullptr) - { - gen_Token stmt_end = currtok; - eat(Tok_Statement_End); - // ( ) < = 0 or delete > ; - - if (currtok_noskip.Type == Tok_Comment && currtok_noskip.Line == stmt_end.Line) - inline_cmt = gen_parse_comment(ctx); - // ( ) < = 0 or delete > ; - } - - gen_StrBuilder name_stripped = gen_strbuilder_make_str(ctx->Allocator_Temp, name.Text); - gen_strbuilder_strip_space(name_stripped); - - gen_CodeFn result = (gen_CodeFn)gen_make_code(); - result->Name = gen_cache_str(gen_strbuilder_to_str(name_stripped)); - result->ModuleFlags = mflags; - - if (body) - { - switch (body->Type) - { - case CT_Function_Body: - case CT_Untyped: - break; - - default: - { - gen_log_failure( - "Body must be either of Function_Body or Untyped type, %S\n%SB", - gen_code_debug_str(body), - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - } - - result->Type = CT_Function; - result->Body = body; - } - else - { - result->Type = CT_Function_Fwd; - } - - if (attributes) - result->Attributes = attributes; - - if (specifiers) - result->Specs = specifiers; - - if (suffix_specs) - result->SuffixSpecs = suffix_specs; - - result->ReturnType = ret_type; - - if (params) - result->Params = params; - - if (inline_cmt) - result->InlineCmt = inline_cmt; - - gen_parser_pop(&ctx->parser); - return result; -} - -gen_internal gen_Code gen_parse_function_body(gen_Context* ctx) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - eat(Tok_BraceCurly_Open); - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = CT_Function_Body; - - // TODO : Support actual parsing of function body - gen_Token start = currtok_noskip; - - gen_s32 level = 0; - while (left && (currtok_noskip.Type != Tok_BraceCurly_Close || level > 0)) - { - if (currtok_noskip.Type == Tok_BraceCurly_Open) - level++; - - else if (currtok_noskip.Type == Tok_BraceCurly_Close && level > 0) - level--; - - eat(currtok_noskip.Type); - } - - gen_Token past = prevtok; - - gen_s32 len = ((gen_sptr)prevtok.Text.Ptr + prevtok.Text.Len) - (gen_sptr)start.Text.Ptr; - - if (len > 0) - { - gen_Str str = { start.Text.Ptr, len }; - gen_body_append(result, gen_cast(gen_Code, gen_def_execution(str))); - } - - eat(Tok_BraceCurly_Close); - - gen_parser_pop(&ctx->parser); - return gen_cast(gen_Code, result); -} - -gen_internal gen_neverinline gen_CodeBody gen_parse_global_nspace(gen_Context* ctx, gen_CodeType which) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - if (which != CT_Namespace_Body && which != CT_Global_Body && which != CT_Export_Body && which != CT_Extern_Linkage_Body) - return gen_InvalidCode; - - if (which != CT_Global_Body) - eat(Tok_BraceCurly_Open); - // { - - gen_CodeBody result = (gen_CodeBody)gen_make_code(); - result->Type = which; - - while (left && currtok_noskip.Type != Tok_BraceCurly_Close) - { - gen_Code member = gen_Code_Invalid; - gen_CodeAttributes attributes = { gen_nullptr }; - gen_CodeSpecifiers specifiers = { gen_nullptr }; - - bool expects_function = false; - - // ctx->parser.Scope->Start = currtok_noskip; - - if (currtok_noskip.Type == Tok_Preprocess_Hash) - eat(Tok_Preprocess_Hash); - - gen_b32 gen_macro_found = false; - - switch (currtok_noskip.Type) - { - case Tok_Comma: - { - gen_log_failure( - "Dangling comma found: %SB\nContext:\n%SB", - gen_tok_to_strbuilder(ctx->Allocator_Temp, currtok), - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - break; - case Tok_Statement_End: - { - // TODO(Ed): Convert this to a general warning procedure - gen_log_fmt("Dangling end statement found %SB\n", gen_tok_to_strbuilder(ctx->Allocator_Temp, currtok_noskip)); - eat(Tok_Statement_End); - continue; - } - case Tok_NewLine: - // Empty lines are auto skipped by Tokens.current() - member = gen_fmt_newline; - eat(Tok_NewLine); - break; - - case Tok_Comment: - member = gen_cast(gen_Code, gen_parse_comment(ctx)); - break; - - case Tok_Decl_Class: - member = gen_parse_complicated_definition(ctx, Tok_Decl_Class); - // class - break; - - case Tok_Decl_Enum: - member = gen_parse_complicated_definition(ctx, Tok_Decl_Enum); - // enum - break; - - case Tok_Decl_Extern_Linkage: - if (which == CT_Extern_Linkage_Body) - gen_log_failure("Nested extern linkage\n%SB", gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp)); - - member = gen_cast(gen_Code, gen_parser_parse_extern_link(ctx)); - // extern "..." { ... } - break; - - case Tok_Decl_Namespace: - member = gen_cast(gen_Code, gen_parser_parse_namespace(ctx)); - // namespace { ... } - break; - - case Tok_Decl_Struct: - member = gen_parse_complicated_definition(ctx, Tok_Decl_Struct); - // struct ... - break; - - case Tok_Decl_Template: - member = gen_cast(gen_Code, gen_parser_parse_template(ctx)); - // template<...> ... - break; - - case Tok_Decl_Typedef: - member = gen_cast(gen_Code, gen_parser_parse_typedef(ctx)); - // typedef ... - break; - - case Tok_Decl_Union: - member = gen_parse_complicated_definition(ctx, Tok_Decl_Union); - // union ... - break; - - case Tok_Decl_Using: - member = gen_cast(gen_Code, gen_parser_parse_using(ctx)); - // using ... - break; - - case Tok_Preprocess_Define: - member = gen_cast(gen_Code, gen_parser_parse_define(ctx)); - // #define ... - break; - - case Tok_Preprocess_Include: - member = gen_cast(gen_Code, gen_parse_include(ctx)); - // #include ... - break; - - case Tok_Preprocess_If: - case Tok_Preprocess_IfDef: - case Tok_Preprocess_IfNotDef: - case Tok_Preprocess_ElIf: - member = gen_cast(gen_Code, gen_parse_preprocess_cond(ctx)); - // # ... - break; - - case Tok_Preprocess_Else: - member = gen_cast(gen_Code, gen_preprocess_else); - eat(Tok_Preprocess_Else); - // #else - break; - - case Tok_Preprocess_EndIf: - member = gen_cast(gen_Code, gen_preprocess_endif); - eat(Tok_Preprocess_EndIf); - // #endif - break; - - case Tok_Preprocess_Macro_Stmt: - { - member = gen_cast(gen_Code, gen_parse_simple_preprocess(ctx, Tok_Preprocess_Macro_Stmt)); - break; - } - - case Tok_Preprocess_Pragma: - { - member = gen_cast(gen_Code, gen_parse_pragma(ctx)); - // #pragma ... - } - break; - - case Tok_Preprocess_Unsupported: - { - member = gen_cast(gen_Code, gen_parse_simple_preprocess(ctx, Tok_Preprocess_Unsupported)); - // # ... - } - break; - - case Tok_StaticAssert: - { - member = gen_cast(gen_Code, gen_parse_static_assert(ctx)); - // gen_static_assert( , ... ); - } - break; - - case Tok_Module_Export: - { - if (which == CT_Export_Body) - gen_log_failure("Nested export declaration\n%SB", gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp)); - - member = gen_cast(gen_Code, gen_parser_parse_export_body(ctx)); - // export { ... } - } - break; - - case Tok_Module_Import: - { - // import ... - gen_log_failure("gen::%s: This function is not implemented"); - return gen_InvalidCode; - } - break; - - case Tok_Preprocess_Macro_Expr: - { - if (! gen_tok_is_attribute(currtok)) - { - gen_log_failure( - "Unbounded macro expression residing in class/struct body\n%SB", - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - return gen_InvalidCode; - } - } - //! Fallthrough intentional - case Tok_Attribute_Open: - case Tok_Decl_GNU_Attribute: - case Tok_Decl_MSVC_Attribute: -#define Entry(attribute, str) case attribute: - GEN_DEFINE_ATTRIBUTE_TOKENS -#undef Entry - { - attributes = gen_parse_attributes(ctx); - // - } - //! Fallthrough intentional - GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_TOK_SPECIFIER_CASES: - { - gen_Specifier specs_found[16] = { Spec_NumSpecifiers }; - gen_s32 NumSpecifiers = 0; - - while (left && gen_tok_is_specifier(currtok)) - { - gen_Specifier spec = gen_str_to_specifier(currtok.Text); - - bool ignore_spec = false; - - switch (spec) - { - GEN_PARSER_CLASS_GLOBAL_NSPACE_ALLOWED_MEMBER_SPECIFIER_CASES: - break; - - case Spec_Consteval: - expects_function = true; - break; - - case Spec_Const: - ignore_spec = true; - break; - - default: - gen_Str gen_spec_str = gen_spec_to_str(spec); - - gen_log_failure( - "Invalid specifier %S for variable\n%S", - gen_spec_str, - gen_strbuilder_to_str(gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp)) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - - if (ignore_spec) - break; - - specs_found[NumSpecifiers] = spec; - NumSpecifiers++; - eat(currtok.Type); - } - - if (NumSpecifiers) - { - specifiers = gen_def_specifiers_arr(NumSpecifiers, specs_found); - } - // - } - //! Fallthrough intentional - case Tok_Identifier: - case Tok_Preprocess_Macro_Typename: - case Tok_Spec_Const: - case Tok_Type_Long: - case Tok_Type_Short: - case Tok_Type_Signed: - case Tok_Type_Unsigned: - case Tok_Type_bool: - case Tok_Type_char: - case Tok_Type_double: - case Tok_Type_int: - { - // This s only in a scope so that Preprocess_Macro_Bare_In_Body works without microsoft extension warnings - { - gen_Code gen_constructor__destructor = gen_parse_global_nspace_constructor_destructor(ctx, specifiers); - // Possible gen_constructor_ implemented at gen_global file scope. - if (gen_constructor__destructor) - { - member = gen_constructor__destructor; - break; - } - - bool found_operator_cast_outside_class_implmentation = false; - gen_s32 idx = ctx->parser.gen_token_id; - - for (; idx < ctx->parser.tokens.num; idx++) - { - gen_Token tok = ctx->parser.tokens.ptr[idx]; - - if (tok.Type == Tok_Identifier) - { - idx++; - tok = ctx->parser.tokens.ptr[idx]; - if (tok.Type == Tok_Access_StaticSymbol) - continue; - - break; - } - - if (tok.Type == Tok_Decl_Operator) - found_operator_cast_outside_class_implmentation = true; - - break; - } - - if (found_operator_cast_outside_class_implmentation) - { - member = gen_cast(gen_Code, gen_parser_parse_operator_cast(ctx, specifiers)); - // ::operator () { ... } - break; - } - } - - member = gen_parse_operator_function_or_variable(ctx, expects_function, attributes, specifiers); - // ... - } - } - - if (member == gen_Code_Invalid) - { - gen_log_failure( - "Failed to parse member\nToken: %SB\nContext:\n%SB", - gen_tok_to_strbuilder(ctx->Allocator_Temp, currtok_noskip), - gen_parser_to_strbuilder(&ctx->parser, ctx->Allocator_Temp) - ); - gen_parser_pop(&ctx->parser); - return gen_InvalidCode; - } - - // gen_log_fmt("Global Body Member: %s", member->debug_str()); - gen_body_append(result, member); - } - - if (which != CT_Global_Body) - eat(Tok_BraceCurly_Close); - // { } - - gen_parser_pop(&ctx->parser); - return result; -} - -gen_internal inline gen_Code gen_parse_global_nspace_constructor_destructor(gen_Context* ctx, gen_CodeSpecifiers specifiers) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - gen_Code result = { gen_nullptr }; - - /* - To check if a definition is for a gen_constructor_ we can go straight to the opening parenthesis for its parameters - From There we work backwards to see if we come across two identifiers with the same name between an member access - :: operator, there can be template parameters on the left of the :: so we ignore those. - Whats important is that its back to back. - - This has multiple possible faults. What we parse using this method may not filter out if something has a "return type" - This is bad since technically you could have a namespace nested into another namespace with the same name. - If this awful pattern is done the only way to distiguish with this coarse parse is to know there is no return type defined. - - TODO(Ed): We could fix this by attempting to parse a type, but we would have to have a way to have it soft fail and rollback. - */ - TokenSlice tokens = ctx->parser.tokens; - - gen_s32 idx = ctx->parser.gen_token_id; - gen_Token nav = tokens.ptr[idx]; - for (; idx < tokens.num; idx++, nav = tokens.ptr[idx]) - { - if (nav.Text.Ptr[0] == '<') - { - // Skip templated expressions as they mey have expressions with the () operators - gen_s32 capture_level = 0; - gen_s32 gen_template_level = 0; - for (; idx < tokens.num; idx++, nav = tokens.ptr[idx]) - { - if (nav.Text.Ptr[0] == '<') - ++gen_template_level; - - if (nav.Text.Ptr[0] == '>') - --gen_template_level; - if (nav.Type == Tok_Operator && nav.Text.Ptr[1] == '>') - --gen_template_level; - - if (nav.Type == Tok_Paren_Open) - { - if (gen_template_level != 0) - ++capture_level; - else - break; - } - - if (gen_template_level != 0 && nav.Type == Tok_Paren_Close) - --capture_level; - } - } - - if (nav.Type == Tok_Paren_Open) - break; - } - - --idx; - gen_Token gen_tok_right = tokens.ptr[idx]; - gen_Token gen_tok_left = gen_NullToken; - - if (gen_tok_right.Type != Tok_Identifier) - { - gen_parser_pop(&ctx->parser); - // We're not dealing with a gen_constructor_ if there is no identifier right before the opening of a parameter's scope. - return result; - } - - --idx; - gen_tok_left = tokens.ptr[idx]; - // ... - - bool possible_destructor = false; - if (gen_tok_left.Type == Tok_Operator && gen_tok_left.Text.Ptr[0] == '~') - { - possible_destructor = true; - --idx; - gen_tok_left = tokens.ptr[idx]; - } - - if (gen_tok_left.Type != Tok_Access_StaticSymbol) - { - gen_parser_pop(&ctx->parser); - return result; - } - - --idx; - gen_tok_left = tokens.ptr[idx]; - // ... :: - - // We search toward the left until we find the next valid identifier - gen_s32 capture_level = 0; - gen_s32 gen_template_level = 0; - while (idx != ctx->parser.gen_token_id) - { - if (gen_tok_left.Text.Ptr[0] == '<') - ++gen_template_level; - - if (gen_tok_left.Text.Ptr[0] == '>') - --gen_template_level; - if (gen_tok_left.Type == Tok_Operator && gen_tok_left.Text.Ptr[1] == '>') - --gen_template_level; - - if (gen_template_level != 0 && gen_tok_left.Type == Tok_Paren_Open) - ++capture_level; - - if (gen_template_level != 0 && gen_tok_left.Type == Tok_Paren_Close) - --capture_level; - - if (capture_level == 0 && gen_template_level == 0 && gen_tok_left.Type == Tok_Identifier) - break; - - --idx; - gen_tok_left = tokens.ptr[idx]; - } - - bool is_same = gen_c_str_compare_len(gen_tok_right.Text.Ptr, gen_tok_left.Text.Ptr, gen_tok_right.Text.Len) == 0; - if (gen_tok_left.Type == Tok_Identifier && is_same) - { - // We have found the pattern we desired - if (possible_destructor) - { - // :: ~ ( - result = gen_cast(gen_Code, gen_parser_parse_destructor(ctx, specifiers)); - } - else - { - // :: ( - result = gen_cast(gen_Code, gen_parser_parse_constructor(ctx, specifiers)); - } - } - - gen_parser_pop(&ctx->parser); - return result; -} - -// TODO(Ed): I want to eventually change the identifier to its own gen_AST type. -// This would allow distinction of the qualifier for a symbol :: -// This would also allow -gen_internal gen_Token gen_parse_identifier(gen_Context* ctx, bool* possible_member_function) -{ - gen_ParseStackNode scope = NullScope; - gen_parser_push(&ctx->parser, &scope); - - gen_Token name = currtok; - ctx->parser.scope->name = name.Text; - - gen_Macro* macro = lookup_macro(currtok.Text); - gen_b32 accept_as_identifier = macro && gen_bitfield_is_set(gen_MacroFlags, macro->Flags, MF_Allow_As_Identifier); - gen_b32 is_decarator = macro && gen_bitfield_is_set(gen_MacroFlags, macro->Flags, MF_Identifier_Decorator); - - // Typename can be: '::' - // If that is the case first option will be Tok_Access_StaticSymbol below - if (check(Tok_Identifier) || accept_as_identifier) - { - if (is_decarator) - { - gen_Code name_macro = gen_parse_simple_preprocess(ctx, currtok.Type); - name.Text.Len = ((gen_sptr)prevtok.Text.Ptr + prevtok.Text.Len) - (gen_sptr)name.Text.Ptr; - } - else - { - eat(Tok_Identifier); - } - } - // - - gen_parse_template_args(ctx, &name); - //