WIP: more progress on new macro handling

This commit is contained in:
Edward R. Gonzalez 2024-12-14 18:49:41 -05:00
parent 76257123da
commit c8cf55403b
16 changed files with 400 additions and 189 deletions

View File

@ -36,7 +36,6 @@ Str code_debug_str(Code self)
case CT_Execution:
case CT_Comment:
case CT_PlatformAttributes:
case CT_Preprocess_Define:
case CT_Preprocess_Include:
case CT_Preprocess_Pragma:
case CT_Preprocess_If:
@ -52,6 +51,11 @@ Str code_debug_str(Code self)
strbuilder_append_fmt( result, "\n\tContent: %S", self->Content );
break;
case CT_Preprocess_Define:
// TODO(ED): Needs implementaton
log_failure("code_debug_str: NOT IMPLEMENTED for CT_Preprocess_Define");
break;
case CT_Class:
case CT_Struct:
if ( self->Prev )
@ -259,6 +263,11 @@ Str code_debug_str(Code self)
strbuilder_append_fmt( result, "\n\tValue : %S", self->Value ? strbuilder_to_str( code_to_strbuilder(self->Value)) : txt("Null") );
break;
case CT_Parameters_Define:
// TODO(ED): Needs implementaton
log_failure("code_debug_str: NOT IMPLEMENTED for CT_Parameters_Define");
break;
case CT_Specifiers:
{
strbuilder_append_fmt( result, "\n\tNumEntries: %d", self->NumEntries );
@ -497,6 +506,10 @@ void code_to_strbuilder_ptr( Code self, StrBuilder* result )
params_to_strbuilder_ref(cast(CodeParams, self), result );
break;
case CT_Parameters_Define:
define_params_to_strbuilder_ref(cast(CodeDefineParams, self), result);
break;
case CT_Preprocess_Define:
define_to_strbuilder_ref(cast(CodeDefine, self), result );
break;
@ -987,11 +1000,17 @@ bool code_is_equal( Code self, Code other )
return true;
}
case CT_Parameters_Define:
{
// TODO(ED): Needs implementaton
log_failure("code_is_equal: NOT IMPLEMENTED for CT_Parameters_Define");
return false;
}
case CT_Preprocess_Define:
{
check_member_str( Name );
check_member_content( Content );
check_member_content( Body->Content );
return true;
}

View File

@ -176,7 +176,7 @@ void class_to_strbuilder_def( CodeClass self, StrBuilder* result )
{
GEN_ASSERT(self);
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
strbuilder_append_str( result, txt("class ") );
@ -221,7 +221,7 @@ void class_to_strbuilder_fwd( CodeClass self, StrBuilder* result )
{
GEN_ASSERT(self);
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Attributes )
@ -241,12 +241,48 @@ void class_to_strbuilder_fwd( CodeClass self, StrBuilder* result )
StrBuilder define_to_strbuilder(CodeDefine define)
{
return strbuilder_fmt_buf( _ctx->Allocator_Temp, "#define %S %S", define->Name, define->Content );
StrBuilder result = strbuilder_make_reserve( _ctx->Allocator_Temp, 512 );
define_to_strbuilder_ref(define, & result);
return result;
}
void define_to_strbuilder_ref(CodeDefine define, StrBuilder* result )
{
strbuilder_append_fmt( result, "#define %S %S", define->Name, define->Content );
GEN_ASSERT(define);
GEN_ASSERT(define->Body);
GEN_ASSERT(define->Body->Content);
if (define->Params) {
StrBuilder params_builder = define_params_to_strbuilder(define->Params)
strbuilder_append_fmt( result, "#define %S(%S) %S", define->Name, strbuilder_to_str(params_builder), define->Body->Content );
}
else {
strbuilder_append_fmt( result, "#define %S %S", define->Name, define->Body->Content );
}
}
StrBuilder define_params_to_strbuilder(CodeDefineParams params)
{
GEN_ASSERT(params);
StrBuilder result = strbuilder_make_reserve( _ctx->Allocator_Temp, 128 );
define_params_to_strbuilder_ref( params, & result );
return result;
}
void define_params_to_strbuilder_ref(CodeDefineParams params, StrBuilder* result)
{
GEN_ASSERT(self);
GEN_ASSERT(result);
if ( self->Name.Ptr && self->Name.Len )
{
strbuilder_append_fmt( result, " %S", self->Name );
}
if ( self->NumEntries - 1 > 0 )
{
for ( CodeParams param = begin_CodeDefineParams(self->Next); param != end_CodeDefineParams(self->Next); param = next_CodeDefineParams(self->Next, param) )
{
strbuilder_append_fmt( result, ", %SB", params_to_strbuilder(param) );
}
}
}
StrBuilder destructor_to_strbuilder(CodeDestructor self)
@ -329,7 +365,7 @@ StrBuilder enum_to_strbuilder(CodeEnum self)
void enum_to_strbuilder_def(CodeEnum self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Attributes || self->UnderlyingType || self->UnderlyingTypeMacro )
@ -362,7 +398,7 @@ void enum_to_strbuilder_def(CodeEnum self, StrBuilder* result )
void enum_to_strbuilder_fwd(CodeEnum self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Attributes )
@ -389,7 +425,7 @@ void enum_to_strbuilder_fwd(CodeEnum self, StrBuilder* result )
void enum_to_strbuilder_class_def(CodeEnum self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Attributes || self->UnderlyingType )
@ -421,7 +457,7 @@ void enum_to_strbuilder_class_def(CodeEnum self, StrBuilder* result )
void enum_to_strbuilder_class_fwd(CodeEnum self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
strbuilder_append_str( result, txt("enum class ") );
@ -505,7 +541,7 @@ StrBuilder fn_to_strbuilder(CodeFn self)
void fn_to_strbuilder_def(CodeFn self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export") );
if ( self->Attributes )
@ -558,7 +594,7 @@ void fn_to_strbuilder_def(CodeFn self, StrBuilder* result )
void fn_to_strbuilder_fwd(CodeFn self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Attributes )
@ -646,7 +682,7 @@ StrBuilder namespace_to_strbuilder(CodeNS self)
void namespace_to_strbuilder_ref(CodeNS self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
strbuilder_append_fmt( result, "namespace %S\n{\n%SB\n}\n", self->Name, body_to_strbuilder(self->Body) );
@ -671,7 +707,7 @@ StrBuilder code_op_to_strbuilder(CodeOperator self)
void code_op_to_strbuilder_def(CodeOperator self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Attributes )
@ -725,7 +761,7 @@ void code_op_to_strbuilder_def(CodeOperator self, StrBuilder* result )
void code_op_to_strbuilder_fwd(CodeOperator self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Attributes )
@ -865,7 +901,6 @@ void opcast_to_strbuilder_fwd(CodeOpCast self, StrBuilder* result )
StrBuilder params_to_strbuilder(CodeParams self)
{
GEN_ASSERT(self);
GEN_ASSERT(self);
StrBuilder result = strbuilder_make_reserve( _ctx->Allocator_Temp, 128 );
params_to_strbuilder_ref( self, & result );
@ -1030,7 +1065,7 @@ void struct_to_strbuilder_def( CodeStruct self, StrBuilder* result )
{
GEN_ASSERT(self);
GEN_ASSERT(result);
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
strbuilder_append_str( result, txt("struct ") );
@ -1076,7 +1111,7 @@ void struct_to_strbuilder_fwd( CodeStruct self, StrBuilder* result )
{
GEN_ASSERT(self);
GEN_ASSERT(result);
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Attributes )
@ -1105,7 +1140,7 @@ void template_to_strbuilder_ref(CodeTemplate self, StrBuilder* result )
{
GEN_ASSERT(self);
GEN_ASSERT(result);
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Params )
@ -1123,7 +1158,7 @@ StrBuilder typedef_to_strbuilder(CodeTypedef self)
void typedef_to_strbuilder_ref(CodeTypedef self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
strbuilder_append_str( result, txt("typedef "));
@ -1236,7 +1271,7 @@ StrBuilder union_to_strbuilder(CodeUnion self)
void union_to_strbuilder_def(CodeUnion self, StrBuilder* result )
{
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
strbuilder_append_str( result, txt("union ") );
@ -1267,7 +1302,7 @@ void union_to_strbuilder_fwd(CodeUnion self, StrBuilder* result )
{
GEN_ASSERT(self);
GEN_ASSERT(result);
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
strbuilder_append_str( result, txt("union ") );
@ -1304,7 +1339,7 @@ void using_to_strbuilder_ref(CodeUsing self, StrBuilder* result )
{
GEN_ASSERT(self);
GEN_ASSERT(result);
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Attributes )
@ -1401,7 +1436,7 @@ void var_to_strbuilder_ref(CodeVar self, StrBuilder* result )
return;
}
if ( bitfield_is_equal( u32, self->ModuleFlags, ModuleFlag_Export ))
if ( bitfield_is_set( u32, self->ModuleFlags, ModuleFlag_Export ))
strbuilder_append_str( result, txt("export ") );
if ( self->Attributes || self->Specs )

View File

@ -46,6 +46,7 @@ enum CodeType : u32
CT_Operator_Cast,
CT_Operator_Cast_Fwd,
CT_Parameters,
CT_Parameters_Define,
CT_Preprocess_Define,
CT_Preprocess_Include,
CT_Preprocess_If,
@ -114,6 +115,7 @@ inline Str codetype_to_str( CodeType type )
{ "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 },
@ -182,6 +184,7 @@ inline Str codetype_to_keyword_str( CodeType type )
{ "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 },

View File

@ -53,6 +53,7 @@ enum TokType : u32
Tok_Operator,
Tok_Preprocess_Hash,
Tok_Preprocess_Define,
Tok_Preprocess_Define_Param,
Tok_Preprocess_If,
Tok_Preprocess_IfDef,
Tok_Preprocess_IfNotDef,
@ -62,7 +63,9 @@ enum TokType : u32
Tok_Preprocess_Include,
Tok_Preprocess_Pragma,
Tok_Preprocess_Content,
Tok_Preprocess_Macro,
Tok_Preprocess_Macro_Expr,
Tok_Preprocess_Macro_Stmt,
Tok_Preprocess_Macro_Typename,
Tok_Preprocess_Unsupported,
Tok_Spec_Alignas,
Tok_Spec_Const,
@ -155,6 +158,7 @@ inline Str toktype_to_str( TokType type )
{ "__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 },
@ -164,7 +168,9 @@ inline Str toktype_to_str( TokType type )
{ "include", sizeof( "include" ) - 1 },
{ "pragma", sizeof( "pragma" ) - 1 },
{ "__macro_content__", sizeof( "__macro_content__" ) - 1 },
{ "__macro__", sizeof( "__macro__" ) - 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 },

View File

@ -6,7 +6,7 @@
#pragma region Constants
extern Str enum_underlying_sig;
extern PreprocessorMacro enum_underlying_macro;
extern Code access_public;
extern Code access_protected;

View File

@ -206,10 +206,12 @@ void define_constants()
spec_local_persist = def_specifiers( 1, Spec_Local_Persist );
code_set_global(cast(Code, spec_local_persist));
if (enum_underlying_sig.Len == 0) {
enum_underlying_sig = txt("enum_underlying(");
if (enum_underlying_macro.Name.Len == 0) {
enum_underlying_macro.Name = txt("enum_underlying(");
enum_underlying_macro.Type = MT_Expression;
enum_underlying_macro.Flags = MF_Functional;
}
array_append( _ctx->PreprocessorDefines, enum_underlying_sig);
register_preprocess_macro(enum_underlying_macro);
}
void init(Context* ctx)
@ -301,9 +303,6 @@ void init(Context* ctx)
GEN_FATAL( "gen::init: Failed to initialize the code pool" );
array_append( ctx->CodePools, code_pool );
// TODO(Ed): This is going to be phased out most likely.
ctx->LexArena = arena_init_from_allocator( ctx->Allocator_DyanmicContainers, ctx->InitSize_LexArena );
// TODO(Ed): Eventually the string arenas needs to be phased out for a dedicated string slab allocator
Arena strbuilder_arena = arena_init_from_allocator( ctx->Allocator_StrCache, ctx->SizePer_StringArena );
if ( strbuilder_arena.PhysicalStart == nullptr )
@ -315,9 +314,12 @@ void init(Context* ctx)
ctx->StrCache = hashtable_init(StrCached, ctx->Allocator_DyanmicContainers);
if ( ctx->StrCache.Entries == nullptr )
GEN_FATAL( "gen::init: Failed to initialize the StringCache");
ctx->PreprocessorMacros = hashtable_init(PreprocessorMacros, ctx->Allocator_DyanmicContainers);
if (ctx->PreprocessorMacros.Hashes == nullptr || ctx->PreprocessorMacros.Entries == nullptr) {
GEN_FATAL( "gen::init: Failed to initialize the PreprocessMacros table" );
}
}
// Preprocessor Defines
ctx->PreprocessorDefines = array_init_reserve(StrCached, ctx->Allocator_DyanmicContainers, kilobytes(1) );
define_constants();
parser_init();
@ -354,9 +356,7 @@ void deinit(Context* ctx)
array_free( ctx->CodePools);
array_free( ctx->StringArenas);
// arena_free(& ctx->LexArena);
array_free(ctx->PreprocessorDefines);
hashtable_destroy(ctx->PreprocessorMacros);
left = array_num( ctx->Fallback_AllocatorBuckets);
if (left)
@ -401,6 +401,7 @@ void reset(Context* ctx)
while ( left--, left );
hashtable_clear(ctx->StrCache);
hashtable_clear(ctx->PreprocessorMacros);
define_constants();
}

View File

@ -156,6 +156,7 @@ GEN_API CodeConstructor def_constructor( Opts_def_constructor opts GEN_PARAM_DEF
struct Opts_def_define {
MacroFlags flags;
CodeDefineParams params;
Str content;
b32 dont_register_to_preprocess_macros;
};
GEN_API CodeDefine def_define( Str name, MacroType type, Opts_def_define opts GEN_PARAM_DEFAULT );
@ -271,6 +272,8 @@ GEN_API CodeBody def_body( CodeType type );
GEN_API CodeBody def_class_body ( s32 num, ... );
GEN_API CodeBody def_class_body ( s32 num, Code* codes );
GEN_API CodeDefineParams def_define_params ( s32 num, ... );
GEN_API CodeDefineParams def_define_params ( s32 num, CodeDefineParams* codes )
GEN_API CodeBody def_enum_body ( s32 num, ... );
GEN_API CodeBody def_enum_body ( s32 num, Code* codes );
GEN_API CodeBody def_export_body ( s32 num, ... );

View File

@ -516,7 +516,6 @@ CodeClass def_class( Str name, Opts_def_struct p )
GEN_DEBUG_TRAP();
return InvalidCode;
}
if ( p.attributes && p.attributes->Type != CT_PlatformAttributes ) {
log_failure( "gen::def_class: attributes was not a 'PlatformAttributes' type: %s", code_debug_str(p.attributes) );
GEN_DEBUG_TRAP();
@ -532,6 +531,9 @@ CodeClass def_class( Str name, Opts_def_struct p )
result = (CodeClass) make_code();
result->Name = cache_str( name );
result->ModuleFlags = p.mflags;
result->Attributes = p.attributes;
result->ParentAccess = p.parent_access;
result->ParentType = p.parent;
if ( p.body )
{
switch ( p.body->Type )
@ -552,44 +554,32 @@ CodeClass def_class( Str name, Opts_def_struct p )
else {
result->Type = CT_Class_Fwd;
}
result->Attributes = p.attributes;
result->ParentAccess = p.parent_access;
result->ParentType = p.parent;
for (s32 idx = 0; idx < p.num_interfaces; idx++ ) {
class_add_interface(result, p.interfaces[idx] );
}
return result;
}
CodeDefine def_define( Str name, Str content, Opts_def_define p )
CodeDefine def_define( Str name, MacroType type, Opts_def_define p )
{
if ( ! name_check( def_define, name ) ) {
GEN_DEBUG_TRAP();
return InvalidCode;
}
CodeDefine
result = (CodeDefine) make_code();
result->Type = CT_Preprocess_Define;
result->Name = cache_str( name );
if ( content.Len <= 0 || content.Ptr == nullptr )
result->Content = cache_str( txt("") );
result->Params = p.params;
if ( p.content.Len <= 0 || p.content.Ptr == nullptr )
result->Content = cache_str( txt("\n") );
else
result->Content = cache_str( strbuilder_to_str(strbuilder_fmt_buf(_ctx->Allocator_Temp, "%S\n", content)) );
b32 append_preprocess_defines = ! p.dont_append_preprocess_defines;
if ( append_preprocess_defines ) {
// Add the define to PreprocessorDefines for usage in parsing
s32 lex_id_len = 0;
for (; lex_id_len < result->Name.Len; ++ lex_id_len ) {
if ( result->Name.Ptr[lex_id_len] == '(' )
break;
}
Str lex_id = { result->Name.Ptr, lex_id_len };
array_append(_ctx->PreprocessorDefines, cache_str(lex_id) );
b32 register_define = ! p.dont_register_to_preprocess_macros;
if ( register_define ) {
macro_entry = { result->Name, type, p.flags };
register_preprocess_macro(macro_entry);
}
return result;
}
@ -1410,6 +1400,67 @@ CodeBody def_class_body( s32 num, Code* codes )
return result;
}
CodeDefineParams def_define_params( s32 num, ... )
{
def_body_start( def_define_params );
va_list va;
va_start(va, num);
Code_POD pod = va_arg(va, Code_POD);
CodeDefineParams param = pcast( CodeDefineParams, pod );
null_check( def_define_params, param );
if ( param->Type != CT_Parameters_Define ) {
log_failure( "gen::def_define_params: param %d is not a parameter for a preprocessor define", num - num + 1 );
return InvalidCode;
}
CodeDefineParams result = (CodeDefineParams) code_duplicate(param);
while ( -- num )
{
pod = va_arg(va, Code_POD);
param = pcast( CodeDefineParams, pod );
if ( param->Type != CT_Parameters_Define ) {
log_failure( "gen::def_define_params: param %d is not a parameter for a preprocessor define", num - num + 1 );
return InvalidCode;
}
define_params_append(result, param );
}
va_end(va);
return result;
}
CodeDefineParams def_define_params( s32 num, CodeDefineParams* codes )
{
def_body_code_array_start( def_define_params );
# define check_current(current) \
if ( current == nullptr ) { \
log_failure("gen::def_define_params: Provide a null code in codes array"); \
return InvalidCode; \
} \
if (current->Type != CT_Parameters_Define ) { \
log_failure("gen::def_define_params: Code in coes array is not of paramter for preprocessor define type - %s", code_debug_str(current) ); \
return InvalidCode; \
}
CodeDefineParams current = (CodeDefineParams)code_duplicate(* codes);
check_current(current);
CodeDefineParams
result = (CodeDefineParams) make_code();
result->Name = current->Name;
result->Type = current->Type;
while( codes++, current = * codes, num--, num > 0 ) {
check_current(current);
define_params_append(result, current );
}
# undef check_current
return result;
}
CodeBody def_enum_body( s32 num, ... )
{
def_body_start( def_enum_body );

View File

@ -112,6 +112,102 @@ void lexer_end_line( LexContext* ctx )
}
#define end_line() lexer_end_line(ctx)
// TODO(Ed): We need to to attempt to recover from a lex failure?
s32 lex_preprocessor_define( LexContext* ctx )
{
Token name = { { ctx->scanner, 1 }, Tok_Identifier, ctx->line, ctx->column, TF_Preprocess };
move_forward();
PreprocessorMacro macro = { name.Text, MT_Statement, 0 };
PreprocessorMacro* registered_macro = lookup_preprocess_macro(name.Text);
if ( registered_macro == nullptr ) {
log_fmt("Warning: %S is was not registered before the lexer processed its #define directive, it will be registered as a statement macro"
, name.Text
);
}
while ( ctx->left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) ) {
move_forward();
name.Text.Len++;
}
array_append( _ctx->Lexer_Tokens, name );
if ( ctx->left && (* ctx->scanner) == '(' )
{
if (registered_macro && ! macro_is_functional(* registered_macro)) {
log_fmt("Warning: %S registered macro is not flagged as functional yet the definition detects opening parenthesis '(' for arguments"
, name.Text
);
}
else {
macro.Flags |= MF_Functional;
}
Token opening_paren = { { ctx->scanner, 1 }, Tok_Capture_Start, ctx->line, ctx->column, TF_Preprocess };
array_append( _ctx->Lexer_Tokens, opening_paren );
move_forward();
// We need to tokenize the define's arguments now:
while( ctx->left && * ctx->scanner != ')')
{
skip_whitespace();
if ( char_is_alpha( (* ctx->scanner) ) || (* ctx->scanner) == '_' )
{
Token parameter = { { ctx->scanner, 1 }, Tok_Preprocess_Define_Param, ctx->line, ctx->column, TF_Preprocess };
move_forward();
while ( ctx->left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) )
{
move_forward();
parameter.Text.Len++;
}
array_append(_ctx->Lexer_Tokens, parameter);
skip_whitespace();
}
else {
log_failure("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;
}
// There should be a comma
if ( * ctx->scanner != ',' ) {
log_failure("lex_preprocessor_define(%d, %d): Expected a comma after parameter %S for %S\n"
, ctx->line
, ctx->column
, parameter.Text
, name.Text
);
return Lex_ReturnNull;
}
Token comma = { { ctx->scanner, 1 }, Tok_Comma, ctx->line, ctx->column, TF_Preprocess };
array_append(_ctx->Lexer_Tokens, comma);
move_forward();
}
if ( * ctx->scanner != ')' ) {
log_failure("lex_preprocessor_define(%d, %d): Expected a ')' after last_parameter %S for %S (ran out of characters...)\n"
, ctx->line
, ctx->column
, parameter.Text
, name.Text
);
return Lex_ReturnNull;
}
Token closing_paren = { { ctx->scanner, 1 }, Tok_Capture_End, ctx->line, ctx->column, TF_Preprocess };
array_append(_ctx->Lexer_Tokens, closing_paren);
move_forward();
}
if ( registered_macro == nullptr ) {
register_preprocess_macro(macro);
}
// Define's content handled by lex_preprocessor_directive (the original caller of this)
return Lex_Continue;
}
// TODO(Ed): We need to to attempt to recover from a lex failure?
forceinline
s32 lex_preprocessor_directive( LexContext* ctx )
{
@ -215,31 +311,9 @@ s32 lex_preprocessor_directive( LexContext* ctx )
if ( ctx->token.Type == Tok_Preprocess_Define )
{
Token name = { { ctx->scanner, 0 }, Tok_Identifier, ctx->line, ctx->column, TF_Preprocess };
name.Text.Ptr = ctx->scanner;
name.Text.Len = 1;
move_forward();
PreprocessorMacro* registered_macro = lookup_preprocess_macro(name.Text);
while ( ctx->left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) )
{
move_forward();
name.Text.Len++;
}
if ( ctx->left && (* ctx->scanner) == '(' )
{
move_forward();
name.Text.Len++;
}
array_append( _ctx->Lexer_Tokens, name );
u64 key = crc32( name.Text.Ptr, name.Text.Len );
hashtable_set(ctx->defines, key, tok_to_str(name) );
u32 result = lex_preprocessor_define(ctx); // handles: #define <name>( <params> ) - define's content handled later on within this scope.
if (result != Lex_Continue)
return Lex_ReturnNull;
}
Token preprocess_content = { { ctx->scanner, 0 }, Tok_Preprocess_Content, ctx->line, ctx->column, TF_Preprocess };
@ -289,7 +363,7 @@ s32 lex_preprocessor_directive( LexContext* ctx )
s32 within_string = false;
s32 within_char = false;
// SkipWhitespace();
// Consume preprocess content
while ( ctx->left )
{
if ( (* ctx->scanner) == '"' && ! within_char )
@ -325,6 +399,7 @@ s32 lex_preprocessor_directive( LexContext* ctx )
, (* ctx->scanner), ctx->line, ctx->column
, directive_str, preprocess_content.Line, preprocess_content.Column
, content_str );
return Lex_ReturnNull;
break;
}
}
@ -404,14 +479,15 @@ void lex_found_token( LexContext* ctx )
}
u64 key = 0;
if ( (* ctx->scanner) == '(')
key = crc32( ctx->token.Text.Ptr, ctx->token.Text.Len + 1 );
else
// if ( (* ctx->scanner) == '(')
// key = crc32( ctx->token.Text.Ptr, ctx->token.Text.Len + 1 );
// else
key = crc32( ctx->token.Text.Ptr, ctx->token.Text.Len );
Str* define = hashtable_get(ctx->defines, key );
Str* define = hashtable_get(_ctx->PreprocessMacros, key );
if ( define )
{
// TODO(Ed): Needs updating (Macros)
ctx->token.Type = Tok_Preprocess_Macro;
// Want to ignore any arguments the define may have as they can be execution expressions.
@ -456,6 +532,7 @@ void lex_found_token( LexContext* ctx )
array_append( _ctx->Lexer_Tokens, ctx->token );
}
// TODO(Ed): We need to to attempt to recover from a lex failure?
neverinline
// TokArray lex( Array<Token> tokens, Str content )
TokArray lex( Str content )
@ -480,27 +557,10 @@ TokArray lex( Str content )
return null_array;
}
// TODO(ED): Remove this when preprocess defines has been converted
// for ( StrCached* entry = array_begin(_ctx->PreprocessorDefines); entry != array_end(_ctx->PreprocessorDefines); entry = array_next(_ctx->PreprocessorDefines, entry))
// {
// s32 length = 0;
// char const* entry_scanner = (*entry).Ptr;
// while ( entry->Len > length && (char_is_alphanumeric( *entry_scanner ) || *entry_scanner == '_') )
// {
// entry_scanner++;
// length ++;
// }
// if ( entry_scanner[0] == '(' )
// {
// length++;
// }
// u64 key = crc32( entry->Ptr, length );
// hashtable_set(c.defines, key, * entry );
// }
array_clear(_ctx->Lexer_Tokens);
b32 preprocess_args = true;
while (c.left )
{
#if 0
@ -1182,6 +1242,7 @@ TokArray lex( Str content )
{
lex_found_token( ctx );
TokType last_type = array_back(_ctx->Lexer_Tokens)->Type;
// TODO(Ed): Change this to just detect if its a MACRO THAT SHOULD ACCEPT NEWLINES
if ( last_type == Tok_Preprocess_Macro )
{
Token thanks_c = { { c.scanner, 0 }, Tok_Invalid, c.line, c.column, TF_Null };
@ -1217,6 +1278,7 @@ TokArray lex( Str content )
TokArray result = { _ctx->Lexer_Tokens, 0 };
return result;
}
#undef move_forward
#undef skip_whitespace
#undef end_line

View File

@ -825,22 +825,21 @@ CodeBody parse_class_struct_body( TokType which, Token name )
switch ( currtok_noskip.Type )
{
case Tok_Statement_End:
{
case Tok_Statement_End: {
// TODO(Ed): Convert this to a general warning procedure
log_fmt("Dangling end statement found %SB\n", tok_to_strbuilder(currtok_noskip));
eat( Tok_Statement_End );
continue;
}
case Tok_NewLine:
case Tok_NewLine: {
member = fmt_newline;
eat( Tok_NewLine );
break;
case Tok_Comment:
}
case Tok_Comment: {
member = cast(Code, parse_comment());
break;
}
case Tok_Access_Public:
member = access_public;
eat( Tok_Access_Public );
@ -1727,8 +1726,8 @@ CodeBody parse_global_nspace( CodeType which )
// <Macro>
macro_found = true;
goto Preprocess_Macro_Bare_In_Body;
// TODO(Ed): MACRO UPDATE
}
break;
case Tok_Preprocess_Pragma: {
member = cast(Code, parse_pragma());
@ -2727,7 +2726,7 @@ CodeParams parse_params( bool use_template_capture )
// In template captures you can have a typename have direct assignment without a name
// typename = typename ...
// Which would result in a static value type from a struct expansion (traditionally)
if ( ( name.Text.Ptr || use_template_capture ) && bitfield_is_equal( u32, currtok.Flags, TF_Assign ) )
if ( ( name.Text.Ptr || use_template_capture ) && bitfield_is_set( u32, currtok.Flags, TF_Assign ) )
{
eat( Tok_Operator );
// ( <Macro> <ValueType> <Name> =
@ -2839,7 +2838,7 @@ CodeParams parse_params( bool use_template_capture )
// In template captures you can have a typename have direct assignment without a name
// typename = typename ...
// Which would result in a static value type from a struct expansion (traditionally)
if ( ( name.Text.Ptr || use_template_capture ) && bitfield_is_equal( u32, currtok.Flags, TF_Assign ) )
if ( ( name.Text.Ptr || use_template_capture ) && bitfield_is_set( u32, currtok.Flags, TF_Assign ) )
{
eat( Tok_Operator );
// ( <Macro> <ValueType> <Name> = <Expression>, <Macro> <ValueType> <Name> =
@ -3166,7 +3165,7 @@ CodeVar parse_variable_after_name(
b32 using_constructor_initializer = false;
if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) )
if ( bitfield_is_set( u32, currtok.Flags, TF_Assign ) )
{
// <Attributes> <Specifiers> <ValueType> <Name> = <Expression>
expr = parse_assignment_expression();
@ -4645,6 +4644,7 @@ else if ( currtok.Type == Tok_DeclType )
}
}
}
// TODO(Ed): This needs updating
else if ( currtok.Type == Tok_Preprocess_Macro ) {
// Typename is a macro
name = currtok;
@ -4988,6 +4988,7 @@ CodeTypedef parser_parse_typedef()
const bool from_typedef = true;
// TODO(Ed): UPDATE MACRO USAGE HERE
#if GEN_PARSER_DISABLE_MACRO_TYPEDEF
if ( false )
#else
@ -5365,7 +5366,7 @@ CodeUsing parser_parse_using()
if ( ! is_namespace )
{
if ( bitfield_is_equal( u32, currtok.Flags, TF_Assign ) )
if ( bitfield_is_set( u32, currtok.Flags, TF_Assign ) )
{
attributes = parse_attributes();
// <ModuleFlags> using <Name> <Attributes>

View File

@ -6,34 +6,6 @@
#include "gen/especifier.hpp"
#endif
enum MacroTypes : u16
{
MT_Block_Start, // Not Supported yet
MT_Block_End, // Not Supported yet
MT_Case_Statement, // Not Supported yet
MT_Expression,
MT_Statement,
MT_Typename,
MF_UnderlyingType = GEN_U16_Max,
};
enum MacroFlags : u16
{
MF_Functional = bit(0), // Macro has parameters (args expected to be passed)
MF_Expects_Body = bit(1), // Expects to assign a braced scope to its body.
MF_Null = 0,
MF_UnderlyingType = GEN_U16_Max,
};
struct PreprocessorMacro
{
StrCached Name;
MacroTypes Type;
MacroFlags Flags;
};
enum TokFlags : u32
{
TF_Operator = bit(0),
@ -82,42 +54,42 @@ bool tok_is_valid( Token tok ) {
forceinline
bool tok_is_access_operator(Token tok) {
return bitfield_is_equal( u32, tok.Flags, TF_AccessOperator );
return bitfield_is_set( u32, tok.Flags, TF_AccessOperator );
}
forceinline
bool tok_is_access_specifier(Token tok) {
return bitfield_is_equal( u32, tok.Flags, TF_AccessSpecifier );
return bitfield_is_set( u32, tok.Flags, TF_AccessSpecifier );
}
forceinline
bool tok_is_attribute(Token tok) {
return bitfield_is_equal( u32, tok.Flags, TF_Attribute );
return bitfield_is_set( u32, tok.Flags, TF_Attribute );
}
forceinline
bool tok_is_operator(Token tok) {
return bitfield_is_equal( u32, tok.Flags, TF_Operator );
return bitfield_is_set( u32, tok.Flags, TF_Operator );
}
forceinline
bool tok_is_preprocessor(Token tok) {
return bitfield_is_equal( u32, tok.Flags, TF_Preprocess );
return bitfield_is_set( u32, tok.Flags, TF_Preprocess );
}
forceinline
bool tok_is_preprocess_cond(Token tok) {
return bitfield_is_equal( u32, tok.Flags, TF_Preprocess_Cond );
return bitfield_is_set( u32, tok.Flags, TF_Preprocess_Cond );
}
forceinline
bool tok_is_specifier(Token tok) {
return bitfield_is_equal( u32, tok.Flags, TF_Specifier );
return bitfield_is_set( u32, tok.Flags, TF_Specifier );
}
forceinline
bool tok_is_end_definition(Token tok) {
return bitfield_is_equal( u32, tok.Flags, TF_EndDefinition );
return bitfield_is_set( u32, tok.Flags, TF_EndDefinition );
}
StrBuilder tok_to_strbuilder(Token tok);
@ -153,3 +125,60 @@ struct ParseContext
TokArray Tokens;
StackNode* Scope;
};
enum MacroType : u16
{
MT_Statement, // A macro is assumed to be a statement if not resolved.
MT_Expression,
MT_Typename,
MT_Block_Start, // Not Supported yet
MT_Block_End, // Not Supported yet
MT_Case_Statement, // Not Supported yet
MF_UnderlyingType = GEN_U16_Max,
};
Str macro_type_to_str( MacroType type )
{
local_persist
Str lookup[ (u32)Num_ModuleFlags ] = {
{ "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 },
};
local_persist
Str invalid_flag = { "Invalid", sizeof("Invalid") };
if ( flag > ModuleFlag_Import )
return invalid_flag;
return lookup[ (u32)flag ];
}
enum MacroFlags : u16
{
MF_Functional = bit(0), // Macro has parameters (args expected to be passed)
MF_Expects_Body = bit(1), // Expects to assign a braced scope to its body.
MF_Null = 0,
MF_UnderlyingType = GEN_U16_Max,
};
struct PreprocessorMacro
{
StrCached Name;
MacroType Type;
MacroFlags Flags;
};
forceinine
b32 macro_is_functional( PreprocessorMacro macro ) {
return bitfield_is_set( macro->Flags, MF_Functional );
}
forceinline
b32 macro_expects_body( PreprocessorMacro macro ) {
return bitfield_is_set( macro->Flags, MF_Expects_Body );
}

View File

@ -9,7 +9,7 @@ global Context* _ctx;
#pragma region Constants
global u32 context_counter;
global Str enum_underlying_sig;
global PreprocessorMacro enum_underlying_macro;
global Code Code_Global;
global Code Code_Invalid;

View File

@ -35,7 +35,7 @@
#ifndef bit
#define bit( Value ) ( 1 << Value )
#define bitfield_is_equal( Type, Field, Mask ) ( (scast(Type, Mask) & scast(Type, Field)) == scast(Type, Mask) )
#define bitfield_is_set( Type, Field, Mask ) ( (scast(Type, Mask) & scast(Type, Field)) == scast(Type, Mask) )
#endif
// Mainly intended for forcing the base library to utilize only C-valid constructs or type coercion

View File

@ -42,6 +42,7 @@ Number, "__number__"
Operator, "__operator__"
Preprocess_Hash, "#"
Preprocess_Define, "define"
Preprocess_Define_Param, "__define_param__"
Preprocess_If, "if"
Preprocess_IfDef, "ifdef"
Preprocess_IfNotDef, "ifndef"

1 Invalid __invalid__
42 Operator __operator__
43 Preprocess_Hash #
44 Preprocess_Define define
45 Preprocess_Define_Param __define_param__
46 Preprocess_If if
47 Preprocess_IfDef ifdef
48 Preprocess_IfNotDef ifndef

View File

@ -41,7 +41,7 @@
#undef local_persist
#undef bit
#undef bitfield_is_equal
#undef bitfield_is_set
#undef cast

View File

@ -21,7 +21,7 @@ word global, gen_global
word internal, gen_internal
word local_persist, gen_local_persist
word bit, gen_bit
word bitfield_is_equal, gen_bitfield_is_equal
word bitfield_is_set, gen_bitfield_is_set
word cast, gen_cast
word ccast, gen_ccast
word pcast, gen_pcast