mirror of
https://github.com/Ed94/gencpp.git
synced 2024-12-22 15:54:45 -08:00
Compare commits
4 Commits
76257123da
...
956ab73130
Author | SHA1 | Date | |
---|---|---|---|
956ab73130 | |||
f93250da07 | |||
1b4f9a2e77 | |||
c8cf55403b |
@ -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;
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ struct AST_Define
|
||||
char _PAD_PROPERTIES_ [ sizeof(AST*) * 4 ];
|
||||
CodeDefineParams Params;
|
||||
Code Body; // Should be completely serialized for now to a: StrCached Content.
|
||||
char _PAD_PROPERTIES_ [ sizeof(AST*) * 1 ];
|
||||
char _PAD_PROPERTIES_2_ [ sizeof(AST*) * 1 ];
|
||||
};
|
||||
};
|
||||
StrCached Name;
|
||||
|
@ -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 self, 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 ( CodeDefineParams param = begin_CodeDefineParams(self->Next); param != end_CodeDefineParams(self->Next); param = next_CodeDefineParams(self->Next, param) )
|
||||
{
|
||||
strbuilder_append_fmt( result, ", %SB", define_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 )
|
||||
|
@ -202,7 +202,7 @@ struct CodeParams
|
||||
{
|
||||
#if ! GEN_C_LIKE_CPP
|
||||
Using_Code( CodeParams );
|
||||
forceinline void append( CodeParams other ) { return params_append(* this, other) }
|
||||
forceinline void append( CodeParams other ) { return params_append(* this, other); }
|
||||
forceinline CodeParams get( s32 idx ) { return params_get( * this, idx); }
|
||||
forceinline bool has_entries() { return params_has_entries(* this); }
|
||||
forceinline StrBuilder to_strbuilder() { return params_to_strbuilder(* this); }
|
||||
@ -225,22 +225,22 @@ struct CodeDefineParams
|
||||
{
|
||||
#if ! GEN_C_LIKE_CPP
|
||||
Using_Code( CodeDefineParams );
|
||||
forceinline void append( CodeDefineParams other ) { return params_append( cast(CodeParams, * this), other) }
|
||||
forceinline CodeDefineParams get( s32 idx ) { return params_get( cast(CodeParams, * this), idx); }
|
||||
forceinline void append( CodeDefineParams other ) { return params_append( cast(CodeParams, * this), cast(CodeParams, other)); }
|
||||
forceinline CodeDefineParams get( s32 idx ) { return (CodeDefineParams) (Code) params_get( cast(CodeParams, * this), idx); }
|
||||
forceinline bool has_entries() { return params_has_entries( cast(CodeParams, * this)); }
|
||||
forceinline StrBuilder to_strbuilder() { return define_params_to_strbuilder(* this); }
|
||||
forceinline void to_strbuilder( StrBuilder& result ) { return define_params_to_strbuilder_ref(* this, & result); }
|
||||
#endif
|
||||
Using_CodeOps( CodeDefineParams );
|
||||
forceinline CodeDefineParams begin() { return begin_CodeParams( cast(CodeParams, * this)); }
|
||||
forceinline CodeDefineParams end() { return end_CodeParams( cast(CodeParams, * this)); }
|
||||
forceinline CodeDefineParams begin() { return (CodeDefineParams) (Code) begin_CodeParams( cast(CodeParams, * this)); }
|
||||
forceinline CodeDefineParams end() { return (CodeDefineParams) (Code) end_CodeParams( cast(CodeParams, * this)); }
|
||||
forceinline operator Code() { return { (AST*)ast }; }
|
||||
forceinline CodeDefineParams operator *() { return * this; } // Required to support for-range iteration.
|
||||
forceinline AST_DefineParams* operator->() {
|
||||
GEN_ASSERT(ast);
|
||||
return ast;
|
||||
}
|
||||
forceinline CodeDefineParams& operator++() { return cast(CodeParams, * this).operator ++() };
|
||||
forceinline CodeDefineParams& operator++();
|
||||
AST_DefineParams* ast;
|
||||
};
|
||||
|
||||
@ -1058,9 +1058,9 @@ forceinline StrBuilder to_strbuilder ( CodeClass self )
|
||||
forceinline void to_strbuilder_def( CodeClass self, StrBuilder& result ) { return class_to_strbuilder_def(self, & result); }
|
||||
forceinline void to_strbuilder_fwd( CodeClass self, StrBuilder& result ) { return class_to_strbuilder_fwd(self, & result); }
|
||||
|
||||
forceinline void append (CodeDefineParams appendee, CodeDefineParams other ) { return params_append(cast(CodeParam, appendee), other); }
|
||||
forceinline CodeDefineParams get (CodeDefineParams params, s32 idx) { return params_get(cast(CodeParam, params), idx); }
|
||||
forceinline bool has_entries (CodeDefineParams params ) { return params_has_entries(cast(CodeParam, params)); }
|
||||
forceinline void append (CodeDefineParams appendee, CodeDefineParams other ) { params_append(cast(CodeParams, appendee), cast(CodeParams, other)); }
|
||||
forceinline CodeDefineParams get (CodeDefineParams params, s32 idx) { return (CodeDefineParams) (Code) params_get(cast(CodeParams, params), idx); }
|
||||
forceinline bool has_entries (CodeDefineParams params ) { return params_has_entries(cast(CodeParams, params)); }
|
||||
forceinline StrBuilder to_strbuilder(CodeDefineParams params ) { return define_params_to_strbuilder(params); }
|
||||
forceinline void to_strbuilder(CodeDefineParams params, StrBuilder& result ) { return define_params_to_strbuilder_ref(params, & result); }
|
||||
|
||||
|
@ -179,6 +179,22 @@ inline AST_Define* CodeDefine::operator->()
|
||||
return ast;
|
||||
}
|
||||
|
||||
inline CodeDefineParams& CodeDefineParams::operator=( Code other )
|
||||
{
|
||||
if ( other.ast != nullptr && other->Parent != nullptr )
|
||||
{
|
||||
ast = rcast( decltype( ast ), code_duplicate( other ).ast );
|
||||
ast->Parent = { nullptr };
|
||||
}
|
||||
ast = rcast( decltype( ast ), other.ast );
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline CodeDefineParams::operator bool()
|
||||
{
|
||||
return ast != nullptr;
|
||||
}
|
||||
|
||||
inline CodeDestructor& CodeDestructor::operator=( Code other )
|
||||
{
|
||||
if ( other.ast != nullptr && other->Parent != nullptr )
|
||||
@ -851,6 +867,11 @@ forceinline Code::operator CodeDefine() const
|
||||
return { (AST_Define*)ast };
|
||||
}
|
||||
|
||||
forceinline Code::operator CodeDefineParams() const
|
||||
{
|
||||
return { (AST_DefineParams*)ast };
|
||||
}
|
||||
|
||||
forceinline Code::operator CodeDestructor() const
|
||||
{
|
||||
return { (AST_Destructor*)ast };
|
||||
|
@ -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,
|
||||
@ -74,7 +75,7 @@ enum CodeType : u32
|
||||
|
||||
inline Str codetype_to_str( CodeType type )
|
||||
{
|
||||
local_persist Str lookup[61] = {
|
||||
local_persist Str lookup[] = {
|
||||
{ "Invalid", sizeof( "Invalid" ) - 1 },
|
||||
{ "Untyped", sizeof( "Untyped" ) - 1 },
|
||||
{ "NewLine", sizeof( "NewLine" ) - 1 },
|
||||
@ -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 },
|
||||
@ -142,7 +144,7 @@ inline Str codetype_to_str( CodeType type )
|
||||
|
||||
inline Str codetype_to_keyword_str( CodeType type )
|
||||
{
|
||||
local_persist Str lookup[61] = {
|
||||
local_persist Str lookup[] = {
|
||||
{ "__NA__", sizeof( "__NA__" ) - 1 },
|
||||
{ "__NA__", sizeof( "__NA__" ) - 1 },
|
||||
{ "__NA__", sizeof( "__NA__" ) - 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 },
|
||||
|
@ -60,7 +60,7 @@ enum Operator : u32
|
||||
|
||||
inline Str operator_to_str( Operator op )
|
||||
{
|
||||
local_persist Str lookup[47] = {
|
||||
local_persist Str lookup[] = {
|
||||
{ "INVALID", sizeof( "INVALID" ) - 1 },
|
||||
{ "=", sizeof( "=" ) - 1 },
|
||||
{ "+=", sizeof( "+=" ) - 1 },
|
||||
|
@ -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 },
|
||||
|
@ -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;
|
||||
|
@ -259,12 +259,21 @@ CodeParams next_CodeParams(CodeParams params, CodeParams param_iter)
|
||||
|
||||
#pragma region CodeDefineParams
|
||||
forceinline void define_params_append (CodeDefineParams appendee, CodeDefineParams other ) { params_append( cast(CodeParams, appendee), cast(CodeParams, other) ); }
|
||||
forceinline CodeDefineParams define_params_get (CodeDefineParams self, s32 idx ) { return params_get( cast(CodeParams, self), idx); }
|
||||
forceinline CodeDefineParams define_params_get (CodeDefineParams self, s32 idx ) { return (CodeDefineParams) (Code) params_get( cast(CodeParams, self), idx); }
|
||||
forceinline bool define_params_has_entries(CodeDefineParams self) { return params_has_entries( cast(CodeParams, self)); }
|
||||
|
||||
CodeDefineParams begin_CodeDefineParams(CodeDefineParams params) { return begin_CodeParams( cast(CodeParams, params)); }
|
||||
CodeDefineParams end_CodeDefineParams (CodeDefineParams params) { return end_CodeParams ( cast(CodeParams, params)); }
|
||||
CodeDefineParams next_CodeDefineParams (CodeDefineParams params, CodeDefineParams entry_iter) { return next_CodeParams ( cast(CodeParams, params), cast(CoeParams, entry_iter)); }
|
||||
CodeDefineParams begin_CodeDefineParams(CodeDefineParams params) { return (CodeDefineParams) (Code) begin_CodeParams( cast(CodeParams, (Code)params)); }
|
||||
CodeDefineParams end_CodeDefineParams (CodeDefineParams params) { return (CodeDefineParams) (Code) end_CodeParams ( cast(CodeParams, (Code)params)); }
|
||||
CodeDefineParams next_CodeDefineParams (CodeDefineParams params, CodeDefineParams entry_iter) { return (CodeDefineParams) (Code) next_CodeParams ( cast(CodeParams, (Code)params), cast(CodeParams, (Code)entry_iter)); }
|
||||
|
||||
#if GEN_COMPILER_CPP
|
||||
forceinline
|
||||
CodeDefineParams& CodeDefineParams::operator ++()
|
||||
{
|
||||
* this = ast->Next;
|
||||
return * this;
|
||||
}
|
||||
#endif
|
||||
#pragma endregion CodeDefineParams
|
||||
|
||||
#pragma region CodeSpecifiers
|
||||
|
@ -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)
|
||||
@ -270,8 +272,8 @@ void init(Context* ctx)
|
||||
ctx->CodePool_NumBlocks = kilobytes(16);
|
||||
}
|
||||
|
||||
if (ctx->InitSize_LexArena == 0 ) {
|
||||
ctx->InitSize_LexArena = megabytes(4);
|
||||
if (ctx->InitSize_LexerTokens == 0 ) {
|
||||
ctx->InitSize_LexerTokens = kilobytes(64);
|
||||
}
|
||||
if (ctx->SizePer_StringArena == 0) {
|
||||
ctx->SizePer_StringArena = megabytes(1);
|
||||
@ -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(PreprocessorMacro, 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();
|
||||
}
|
||||
|
||||
@ -469,6 +470,42 @@ PreprocessorMacro* lookup_preprocess_macro( Str name ) {
|
||||
}
|
||||
|
||||
void register_preprocess_macro( PreprocessorMacro macro ) {
|
||||
GEN_ASSERT_NOT_NULL(macro.Name.Ptr);
|
||||
GEN_ASSERT(macro.Name.Len > 0);
|
||||
u32 key = crc32( macro.Name.Ptr, macro.Name.Len );
|
||||
hashtable_set( _ctx->PreprocessorMacros, key, macro );
|
||||
}
|
||||
|
||||
void register_preprocess_macros( s32 num, ... )
|
||||
{
|
||||
GEN_ASSERT(num > 0);
|
||||
va_list va;
|
||||
va_start(va, num);
|
||||
do
|
||||
{
|
||||
PreprocessorMacro macro = va_arg(va, PreprocessorMacro);
|
||||
GEN_ASSERT_NOT_NULL(macro.Name.Ptr);
|
||||
GEN_ASSERT(macro.Name.Len > 0);
|
||||
|
||||
u32 key = crc32( macro.Name.Ptr, macro.Name.Len );
|
||||
hashtable_set( _ctx->PreprocessorMacros, key, macro );
|
||||
}
|
||||
while (num--, num > 0);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void register_preprocess_macros( s32 num, PreprocessorMacro* macros )
|
||||
{
|
||||
GEN_ASSERT(num > 0);
|
||||
do
|
||||
{
|
||||
PreprocessorMacro macro = * macros;
|
||||
GEN_ASSERT_NOT_NULL(macro.Name.Ptr);
|
||||
GEN_ASSERT(macro.Name.Len > 0);
|
||||
|
||||
u32 key = crc32( macro.Name.Ptr, macro.Name.Len );
|
||||
hashtable_set( _ctx->PreprocessorMacros, key, macro );
|
||||
++ macros;
|
||||
}
|
||||
while (num--, num > 0);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ struct Context
|
||||
u32 CodePool_NumBlocks;
|
||||
|
||||
// TODO(Ed): Review these... (No longer needed if using the proper allocation strategy)
|
||||
u32 InitSize_LexArena;
|
||||
u32 InitSize_LexerTokens;
|
||||
u32 SizePer_StringArena;
|
||||
|
||||
// TODO(Ed): Symbol Table
|
||||
@ -87,9 +87,6 @@ struct Context
|
||||
StringTable StrCache;
|
||||
|
||||
// TODO(Ed): This needs to be just handled by a parser context
|
||||
|
||||
// Arena LexArena;
|
||||
// StringTable Lexer_defines;
|
||||
Array(Token) Lexer_Tokens;
|
||||
|
||||
// TODO(Ed): Active parse context vs a parse result need to be separated conceptually
|
||||
@ -109,14 +106,18 @@ GEN_API void reset(Context* ctx);
|
||||
|
||||
GEN_API void set_context(Context* ctx);
|
||||
|
||||
// Mostly used to verify a macro entry exists for the given name
|
||||
GEN_API PreprocessMacro* lookup_preprocess_macro( Str Name );
|
||||
// Mostly intended for the parser
|
||||
GEN_API PreprocessorMacro* lookup_preprocess_macro( Str Name );
|
||||
|
||||
// Alternative way to add a preprocess define entry for the lexer & parser to utilize
|
||||
// if the user doesn't want to use def_define
|
||||
// Macros are tracked by name so if the name already exists the entry will be overwritten.
|
||||
GEN_API void register_preprocess_macro( PreprocessorMacro macro );
|
||||
|
||||
// Ease of use batch registration
|
||||
GEN_API void register_preprocess_macros( s32 num, ... );
|
||||
GEN_API void register_preprocess_macros( s32 num, PreprocessorMacro* 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 StrCached cache_str( Str str );
|
||||
@ -154,8 +155,9 @@ struct Opts_def_constructor {
|
||||
GEN_API CodeConstructor def_constructor( Opts_def_constructor opts GEN_PARAM_DEFAULT );
|
||||
|
||||
struct Opts_def_define {
|
||||
MacroFlags flags;
|
||||
CodeDefineParams params;
|
||||
Str content;
|
||||
MacroFlags flags;
|
||||
b32 dont_register_to_preprocess_macros;
|
||||
};
|
||||
GEN_API CodeDefine def_define( Str name, MacroType type, Opts_def_define opts GEN_PARAM_DEFAULT );
|
||||
@ -271,6 +273,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, ... );
|
||||
|
@ -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->Body = untyped_str( txt("\n") );
|
||||
else
|
||||
result->Content = cache_str( strbuilder_to_str(strbuilder_fmt_buf(_ctx->Allocator_Temp, "%S\n", content)) );
|
||||
result->Body = untyped_str( strbuilder_to_str(strbuilder_fmt_buf(_ctx->Allocator_Temp, "%S\n", p.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 ) {
|
||||
PreprocessorMacro 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 );
|
||||
|
@ -112,6 +112,158 @@ 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();
|
||||
|
||||
while ( ctx->left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) ) {
|
||||
move_forward();
|
||||
name.Text.Len++;
|
||||
}
|
||||
|
||||
Specifier spec = str_to_specifier( name.Text );
|
||||
TokType attrib = str_to_toktype( name.Text );
|
||||
b32 not_specifier = spec == Spec_Invalid;
|
||||
b32 not_attribute = attrib <= Tok___Attributes_Start;
|
||||
|
||||
PreprocessorMacro macro = { name.Text, MT_Statement, (MacroFlags)0 };
|
||||
PreprocessorMacro* registered_macro = lookup_preprocess_macro(name.Text);
|
||||
|
||||
if ( registered_macro == nullptr && not_specifier && not_attribute ) {
|
||||
log_fmt("Warning: '%S' was not registered before the lexer processed its #define directive, it will be registered as a statement macro\n"
|
||||
, name.Text
|
||||
);
|
||||
GEN_DEBUG_TRAP();
|
||||
}
|
||||
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\n"
|
||||
, name.Text
|
||||
);
|
||||
GEN_DEBUG_TRAP();
|
||||
}
|
||||
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();
|
||||
|
||||
Token last_parameter;
|
||||
// We need to tokenize the define's arguments now:
|
||||
while( ctx->left && * ctx->scanner != ')')
|
||||
{
|
||||
skip_whitespace();
|
||||
|
||||
Str possible_varadic = { ctx->scanner, 3 };
|
||||
if ( ctx->left > 3 && str_are_equal( txt("..."), possible_varadic ) ) {
|
||||
Token parameter = { { ctx->scanner, 3 }, Tok_Preprocess_Define_Param, ctx->line, ctx->column, TF_Preprocess };
|
||||
move_forward();
|
||||
move_forward();
|
||||
move_forward();
|
||||
|
||||
array_append(_ctx->Lexer_Tokens, parameter);
|
||||
skip_whitespace();
|
||||
last_parameter = parameter;
|
||||
|
||||
while ( (* ctx->scanner) == '\\' ) {
|
||||
move_forward();
|
||||
skip_whitespace();
|
||||
}
|
||||
if (* ctx->scanner != ')' )
|
||||
{
|
||||
log_failure("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 ( 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();
|
||||
last_parameter = parameter;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (* ctx->scanner == ')' )
|
||||
break;
|
||||
|
||||
// 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
|
||||
, last_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
|
||||
, last_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();
|
||||
}
|
||||
else if ( registered_macro && macro_is_functional( * registered_macro) ) {
|
||||
if (registered_macro && ! macro_is_functional(* registered_macro)) {
|
||||
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 == 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 +367,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 +419,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 +455,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;
|
||||
}
|
||||
}
|
||||
@ -352,30 +483,24 @@ s32 lex_preprocessor_directive( LexContext* ctx )
|
||||
forceinline
|
||||
void lex_found_token( LexContext* ctx )
|
||||
{
|
||||
if ( ctx->token.Type != Tok_Invalid )
|
||||
{
|
||||
if ( ctx->token.Type != Tok_Invalid ) {
|
||||
array_append( _ctx->Lexer_Tokens, ctx->token );
|
||||
return;
|
||||
}
|
||||
|
||||
TokType type = str_to_toktype( tok_to_str(ctx->token) );
|
||||
|
||||
if (type <= Tok_Access_Public && type >= Tok_Access_Private )
|
||||
{
|
||||
if (type <= Tok_Access_Public && type >= Tok_Access_Private ) {
|
||||
ctx->token.Flags |= TF_AccessSpecifier;
|
||||
}
|
||||
|
||||
if ( type > Tok___Attributes_Start )
|
||||
{
|
||||
if ( type > Tok___Attributes_Start ) {
|
||||
ctx->token.Flags |= TF_Attribute;
|
||||
}
|
||||
|
||||
if ( type == Tok_Decl_Extern_Linkage )
|
||||
{
|
||||
skip_whitespace();
|
||||
|
||||
if ( (* ctx->scanner) != '"' )
|
||||
{
|
||||
if ( (* ctx->scanner) != '"' ) {
|
||||
type = Tok_Spec_Extern;
|
||||
ctx->token.Flags |= TF_Specifier;
|
||||
}
|
||||
@ -384,7 +509,6 @@ void lex_found_token( LexContext* ctx )
|
||||
array_append( _ctx->Lexer_Tokens, ctx->token );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( type <= Tok_Star && type >= Tok_Spec_Alignas)
|
||||
|| type == Tok_Ampersand
|
||||
|| type == Tok_Ampersand_DBL )
|
||||
@ -394,8 +518,6 @@ void lex_found_token( LexContext* ctx )
|
||||
array_append( _ctx->Lexer_Tokens, ctx->token );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ( type != Tok_Invalid )
|
||||
{
|
||||
ctx->token.Type = type;
|
||||
@ -403,20 +525,17 @@ void lex_found_token( LexContext* ctx )
|
||||
return;
|
||||
}
|
||||
|
||||
u64 key = 0;
|
||||
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 );
|
||||
if ( define )
|
||||
PreprocessorMacro* macro = lookup_preprocess_macro( ctx->token.Text );
|
||||
if ( macro )
|
||||
{
|
||||
ctx->token.Type = Tok_Preprocess_Macro;
|
||||
ctx->token.Type = macrotype_to_toktype(macro->Type);
|
||||
|
||||
// TODO(Ed): When we introduce a macro AST (and expression support), we'll properly lex this section.
|
||||
// Want to ignore any arguments the define may have as they can be execution expressions.
|
||||
if ( ctx->left && (* ctx->scanner) == '(' )
|
||||
{
|
||||
ctx->token.Flags |= TF_Macro_Functional;
|
||||
|
||||
move_forward();
|
||||
ctx->token.Text.Len++;
|
||||
|
||||
@ -436,7 +555,6 @@ void lex_found_token( LexContext* ctx )
|
||||
move_forward();
|
||||
ctx->token.Text.Len++;
|
||||
}
|
||||
|
||||
//if ( (* ctx->scanner) == '\r' && ctx->scanner[1] == '\n' )
|
||||
//{
|
||||
// move_forward();
|
||||
@ -456,6 +574,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 )
|
||||
@ -464,7 +583,6 @@ TokArray lex( Str content )
|
||||
c.content = content;
|
||||
c.left = content.Len;
|
||||
c.scanner = content.Ptr;
|
||||
c.defines = _ctx->Lexer_defines;
|
||||
|
||||
char const* word = c.scanner;
|
||||
s32 word_length = 0;
|
||||
@ -480,27 +598,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
|
||||
@ -942,7 +1043,7 @@ TokArray lex( Str content )
|
||||
goto FoundToken;
|
||||
}
|
||||
|
||||
// Dash is unfortunatlly a bit more complicated...
|
||||
// Dash is unfortunately a bit more complicated...
|
||||
case '-':
|
||||
{
|
||||
Str text = { c.scanner, 1 };
|
||||
@ -1079,8 +1180,7 @@ TokArray lex( Str content )
|
||||
c.token.Text = text;
|
||||
move_forward();
|
||||
|
||||
while ( c.left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) )
|
||||
{
|
||||
while ( c.left && ( char_is_alphanumeric((* ctx->scanner)) || (* ctx->scanner) == '_' ) ) {
|
||||
move_forward();
|
||||
c.token.Text.Len++;
|
||||
}
|
||||
@ -1106,8 +1206,7 @@ TokArray lex( Str content )
|
||||
move_forward();
|
||||
c.token.Text.Len++;
|
||||
|
||||
while ( c.left && char_is_hex_digit((* ctx->scanner)) )
|
||||
{
|
||||
while ( c.left && char_is_hex_digit((* ctx->scanner)) ) {
|
||||
move_forward();
|
||||
c.token.Text.Len++;
|
||||
}
|
||||
@ -1115,8 +1214,7 @@ TokArray lex( Str content )
|
||||
goto FoundToken;
|
||||
}
|
||||
|
||||
while ( c.left && char_is_digit((* ctx->scanner)) )
|
||||
{
|
||||
while ( c.left && char_is_digit((* ctx->scanner)) ) {
|
||||
move_forward();
|
||||
c.token.Text.Len++;
|
||||
}
|
||||
@ -1126,8 +1224,7 @@ TokArray lex( Str content )
|
||||
move_forward();
|
||||
c.token.Text.Len++;
|
||||
|
||||
while ( c.left && char_is_digit((* ctx->scanner)) )
|
||||
{
|
||||
while ( c.left && char_is_digit((* ctx->scanner)) ) {
|
||||
move_forward();
|
||||
c.token.Text.Len++;
|
||||
}
|
||||
@ -1145,8 +1242,7 @@ TokArray lex( Str content )
|
||||
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'))
|
||||
{
|
||||
if (c.left && (prev == 'l' || prev == 'L') && ((* ctx->scanner) == 'l' || (* ctx->scanner) == 'L')) {
|
||||
move_forward();
|
||||
c.token.Text.Len++;
|
||||
}
|
||||
@ -1172,8 +1268,7 @@ TokArray lex( Str content )
|
||||
log_failure( "Failed to 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 && ! char_is_space( (* ctx->scanner) ) )
|
||||
{
|
||||
while ( c.left && ! char_is_space( (* ctx->scanner) ) ) {
|
||||
move_forward();
|
||||
}
|
||||
}
|
||||
@ -1182,16 +1277,14 @@ TokArray lex( Str content )
|
||||
{
|
||||
lex_found_token( ctx );
|
||||
TokType last_type = array_back(_ctx->Lexer_Tokens)->Type;
|
||||
if ( last_type == Tok_Preprocess_Macro )
|
||||
if ( last_type == Tok_Preprocess_Macro_Stmt )
|
||||
{
|
||||
Token thanks_c = { { c.scanner, 0 }, Tok_Invalid, c.line, c.column, TF_Null };
|
||||
c.token = thanks_c;
|
||||
if ( (* ctx->scanner) == '\r')
|
||||
{
|
||||
if ( (* ctx->scanner) == '\r') {
|
||||
move_forward();
|
||||
c.token.Text.Len = 1;
|
||||
}
|
||||
|
||||
if ( (* ctx->scanner) == '\n' )
|
||||
{
|
||||
c.token.Type = Tok_NewLine;
|
||||
@ -1205,18 +1298,16 @@ TokArray lex( Str content )
|
||||
}
|
||||
}
|
||||
|
||||
if ( array_num(_ctx->Lexer_Tokens) == 0 )
|
||||
{
|
||||
if ( array_num(_ctx->Lexer_Tokens) == 0 ) {
|
||||
log_failure( "Failed to lex any tokens" );
|
||||
{
|
||||
TokArray tok_array = {};
|
||||
return tok_array;
|
||||
}
|
||||
}
|
||||
|
||||
TokArray result = { _ctx->Lexer_Tokens, 0 };
|
||||
return result;
|
||||
}
|
||||
|
||||
#undef move_forward
|
||||
#undef skip_whitespace
|
||||
#undef end_line
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,36 +4,9 @@
|
||||
#include "gen/ecode.hpp"
|
||||
#include "gen/eoperator.hpp"
|
||||
#include "gen/especifier.hpp"
|
||||
#include "gen/etoktype.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 +55,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 +126,76 @@ 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_Attribute, // More of a note to the parser than anythign else (attributes should be defined in the user attribues def).
|
||||
MT_Specifier, // More of a note to the parser than anythign else (specifiers should be defined in the user attribues def).
|
||||
MT_Block_Start, // Not Supported yet
|
||||
MT_Block_End, // Not Supported yet
|
||||
MT_Case_Statement, // Not Supported yet
|
||||
|
||||
MT_UnderlyingType = GEN_U16_MAX,
|
||||
};
|
||||
|
||||
forceinline
|
||||
TokType macrotype_to_toktype( 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;
|
||||
}
|
||||
|
||||
Str macrotype_to_str( MacroType type )
|
||||
{
|
||||
local_persist
|
||||
Str lookup[] = {
|
||||
{ "Statement", sizeof("Statement") - 1 },
|
||||
{ "Expression", sizeof("Expression") - 1 },
|
||||
{ "Typename", sizeof("Typename") - 1 },
|
||||
{ "Attribute(Macro)", sizeof("Attribute(Macro)") - 1 },
|
||||
{ "Specifier(Macro)", sizeof("Specifier(Macro)") - 1 },
|
||||
{ "Block_Start", sizeof("Block_Start") - 1 },
|
||||
{ "Block_End", sizeof("Block_End") - 1 },
|
||||
{ "Case_Statement", sizeof("Case_Statement") - 1 },
|
||||
};
|
||||
local_persist
|
||||
Str invalid = { "Invalid", sizeof("Invalid") };
|
||||
if ( type > MT_Case_Statement )
|
||||
return invalid;
|
||||
|
||||
return lookup[ type ];
|
||||
}
|
||||
|
||||
enum EMacroFlags : 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,
|
||||
};
|
||||
typedef u16 MacroFlags;
|
||||
|
||||
struct PreprocessorMacro
|
||||
{
|
||||
StrCached Name;
|
||||
MacroType Type;
|
||||
MacroFlags Flags;
|
||||
};
|
||||
|
||||
forceinline
|
||||
b32 macro_is_functional( PreprocessorMacro macro ) {
|
||||
return bitfield_is_set( b16, macro.Flags, MF_Functional );
|
||||
}
|
||||
|
||||
forceinline
|
||||
b32 macro_expects_body( PreprocessorMacro macro ) {
|
||||
return bitfield_is_set( b16, macro.Flags, MF_Expects_Body );
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
@ -248,9 +248,9 @@
|
||||
# if ! GEN_COMPILER_C
|
||||
# define typeof decltype
|
||||
# elif defined(_MSC_VER)
|
||||
# define typeof(x) __typeof__(x)
|
||||
# define typeof __typeof__
|
||||
# elif defined(__GNUC__) || defined(__clang__)
|
||||
# define typeof(x) __typeof__(x)
|
||||
# define typeof __typeof__
|
||||
# else
|
||||
# error "Compiler not supported"
|
||||
# endif
|
||||
|
@ -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"
|
||||
|
|
@ -47,7 +47,7 @@ CodeBody gen_ecode( char const* path, bool use_c_definition = false )
|
||||
Str codetype_to_str( CodeType type )
|
||||
{
|
||||
local_persist
|
||||
Str lookup[<num>] = {
|
||||
Str lookup[] = {
|
||||
<entries>
|
||||
};
|
||||
return lookup[ type ];
|
||||
@ -57,7 +57,7 @@ CodeBody gen_ecode( char const* path, bool use_c_definition = false )
|
||||
Str codetype_to_keyword_str( CodeType type )
|
||||
{
|
||||
local_persist
|
||||
Str lookup[ <num> ] = {
|
||||
Str lookup[] = {
|
||||
<keywords>
|
||||
};
|
||||
return lookup[ type ];
|
||||
@ -139,7 +139,7 @@ CodeBody gen_eoperator( char const* path, bool use_c_definition = false )
|
||||
Str operator_to_str( Operator op )
|
||||
{
|
||||
local_persist
|
||||
Str lookup[<num>] = {
|
||||
Str lookup[] = {
|
||||
<entries>
|
||||
};
|
||||
|
||||
@ -353,7 +353,7 @@ CodeBody gen_etoktype( char const* etok_path, char const* attr_path, bool use_c_
|
||||
|
||||
#pragma push_macro("GEN_DEFINE_ATTRIBUTE_TOKENS")
|
||||
#undef GEN_DEFINE_ATTRIBUTE_TOKENS
|
||||
CodeDefine attribute_entires_def = def_define( name(GEN_DEFINE_ATTRIBUTE_TOKENS), strbuilder_to_str(attribute_define_entries) );
|
||||
CodeDefine attribute_entires_def = def_define( name(GEN_DEFINE_ATTRIBUTE_TOKENS), MT_Statement, { {}, strbuilder_to_str(attribute_define_entries) } );
|
||||
#pragma pop_macro("GEN_DEFINE_ATTRIBUTE_TOKENS")
|
||||
|
||||
// We cannot parse this enum, it has Attribute names as enums
|
||||
@ -506,6 +506,7 @@ CodeBody gen_ast_inlines()
|
||||
CodeBody impl_code_constr = parse_global_body( token_fmt( "typename", Str name(CodeConstructor), code_impl_tmpl ));
|
||||
CodeBody impl_code_class = parse_global_body( token_fmt( "typename", Str name(CodeClass), code_impl_tmpl ));
|
||||
CodeBody impl_code_define = parse_global_body( token_fmt( "typename", Str name(CodeDefine), code_impl_tmpl ));
|
||||
CodeBody impl_code_define_params = parse_global_body( token_fmt( "typename", Str name(CodeDefineParams), code_impl_tmpl ));
|
||||
CodeBody impl_code_destruct = parse_global_body( token_fmt( "typename", Str name(CodeDestructor), code_impl_tmpl ));
|
||||
CodeBody impl_code_enum = parse_global_body( token_fmt( "typename", Str name(CodeEnum), code_impl_tmpl ));
|
||||
CodeBody impl_code_exec = parse_global_body( token_fmt( "typename", Str name(CodeExec), code_impl_tmpl ));
|
||||
@ -569,6 +570,7 @@ CodeBody gen_ast_inlines()
|
||||
CodeBody impl_cast_constr = parse_global_body( token_fmt( "typename", Str name(Constructor), cast_tmpl ));
|
||||
CodeBody impl_cast_class = parse_global_body( token_fmt( "typename", Str name(Class), cast_tmpl ));
|
||||
CodeBody impl_cast_define = parse_global_body( token_fmt( "typename", Str name(Define), cast_tmpl ));
|
||||
CodeBody impl_cast_define_params = parse_global_body( token_fmt( "typename", Str name(DefineParams), cast_tmpl ));
|
||||
CodeBody impl_cast_destruct = parse_global_body( token_fmt( "typename", Str name(Destructor), cast_tmpl ));
|
||||
CodeBody impl_cast_enum = parse_global_body( token_fmt( "typename", Str name(Enum), cast_tmpl ));
|
||||
CodeBody impl_cast_exec = parse_global_body( token_fmt( "typename", Str name(Exec), cast_tmpl ));
|
||||
@ -602,6 +604,7 @@ CodeBody gen_ast_inlines()
|
||||
impl_code_constr,
|
||||
impl_code_class,
|
||||
impl_code_define,
|
||||
impl_code_define_params,
|
||||
impl_code_destruct,
|
||||
impl_code_enum,
|
||||
impl_code_exec,
|
||||
@ -636,6 +639,7 @@ CodeBody gen_ast_inlines()
|
||||
impl_cast_constr,
|
||||
impl_cast_class,
|
||||
impl_cast_define,
|
||||
impl_cast_define_params,
|
||||
impl_cast_destruct,
|
||||
impl_cast_enum,
|
||||
impl_cast_exec,
|
||||
|
@ -41,7 +41,7 @@
|
||||
#undef local_persist
|
||||
|
||||
#undef bit
|
||||
#undef bitfield_is_equal
|
||||
#undef bitfield_is_set
|
||||
|
||||
#undef cast
|
||||
|
||||
|
@ -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
|
||||
|
@ -51,7 +51,9 @@ Preprocess_EndIf, "endif"
|
||||
Preprocess_Include, "include"
|
||||
Preprocess_Pragma, "pragma"
|
||||
Preprocess_Content, "__macro_content__"
|
||||
Preprocess_Macro, "__macro__"
|
||||
Preprocess_Macro_Expr, "__macro_expression__"
|
||||
Preprocess_Macro_Stmt, "__macro_statment__"
|
||||
Preprocess_Macro_Typename, "__macro_typename__"
|
||||
Preprocess_Unsupported, "__unsupported__"
|
||||
Spec_Alignas, "alignas"
|
||||
Spec_Const, "const"
|
||||
|
|
@ -64,6 +64,45 @@ int gen_main()
|
||||
Code ue_forceinline = code_str(FORCEINLINE);
|
||||
// Code
|
||||
|
||||
register_preprocess_macros( args(
|
||||
(PreprocessorMacro { txt("bit"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("bitfield_is_set"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("GEN_C_LIKE_CPP"), MT_Expression, MF_Null }),
|
||||
(PreprocessorMacro { txt("cast"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("ccast"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("rcast"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("pcast"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("scast"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("stringize_va"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("stringize"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("do_once"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("do_once_defer"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("do_once_start"), MT_Statement, MF_Null }),
|
||||
(PreprocessorMacro { txt("do_once_end"), MT_Statement, MF_Null }),
|
||||
(PreprocessorMacro { txt("labeled_scope_start"), MT_Statement, MF_Null }),
|
||||
(PreprocessorMacro { txt("labeled_scope_end"), MT_Statement, MF_Null }),
|
||||
(PreprocessorMacro { txt("compiler_decorated_func_name"), MT_Expression, MF_Null }),
|
||||
(PreprocessorMacro { txt("num_args_impl"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("num_args"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("count_of"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("clamp"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("is_between"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("size_of"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("min"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("max"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("offset_of"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("static_assert"), MT_Statement, MF_Functional }),
|
||||
(PreprocessorMacro { txt("typeof"), MT_Expression, MF_Null }),
|
||||
(PreprocessorMacro { txt("GEN_API_C_BEGIN"), MT_Statement, MF_Null }),
|
||||
(PreprocessorMacro { txt("GEN_API_C_END"), MT_Statement, MF_Null }),
|
||||
(PreprocessorMacro { txt("nullptr"), MT_Expression, MF_Null }),
|
||||
(PreprocessorMacro { txt("GEN_REMOVE_PTR"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("GEN_PARAM_DEFAULT"), MT_Expression, MF_Null }),
|
||||
(PreprocessorMacro { txt("struct_init"), MT_Expression, MF_Functional }),
|
||||
(PreprocessorMacro { txt("GEN_OPTIMIZE_MAPPINGS_BEGIN"), MT_Statement, MF_Null }),
|
||||
(PreprocessorMacro { txt("GEN_OPITMIZE_MAPPINGS_END"), MT_Statement, MF_Null })
|
||||
));
|
||||
|
||||
// gen_dep.hpp
|
||||
{
|
||||
CodeBody macros = def_body( CT_Global_Body );
|
||||
|
Loading…
Reference in New Issue
Block a user