2024-08-01 13:34:36 +10:00
/*
2024-02-26 00:15:09 +11:00
////////////////////////////////////////////////////////////////////////////////////////////////////
//
/ / $ $ $ $ $ $ \ $ $ $ $ $ $ \ $ $ $ $ $ $ $ $ \ $ $ \ $ $ \
// $$ __$$\ $$ __$$\ $$ _____|$$$\ $$ |
// $$ / \__|$$ / \__|$$ | $$$$\ $$ |
// $$ | $$ |$$$$\ $$$$$\ $$ $$\$$ |
// $$ | $$ |\_$$ |$$ __| $$ \$$$$ |
// $$ | $$\ $$ | $$ |$$ | $$ |\$$$ |
// \$$$$$$ |\$$$$$$ |$$$$$$$$\ $$ | \$$ |
// \______/ \______/ \________|\__| \__|
//
// dqn_cgen.cpp
//
////////////////////////////////////////////////////////////////////////////////////////////////////
2024-08-01 13:34:36 +10:00
*/
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
DN_CGenMapNodeToEnum const DN_CGEN_TABLE_KEY_LIST [ ] =
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
{ DN_CGenTableKeyType_Name , DN_STR8 ( " name " ) } ,
{ DN_CGenTableKeyType_Type , DN_STR8 ( " type " ) } ,
2024-02-26 00:15:09 +11:00
} ;
2025-02-14 00:27:42 +11:00
DN_CGenMapNodeToEnum const DN_CGEN_TABLE_TYPE_LIST [ ] =
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
{ DN_CGenTableType_Data , DN_STR8 ( " data " ) } ,
{ DN_CGenTableType_CodeGenBuiltinTypes , DN_STR8 ( " code_gen_builtin_types " ) } ,
{ DN_CGenTableType_CodeGenStruct , DN_STR8 ( " code_gen_struct " ) } ,
{ DN_CGenTableType_CodeGenEnum , DN_STR8 ( " code_gen_enum " ) } ,
2024-02-26 00:15:09 +11:00
} ;
2025-02-14 00:27:42 +11:00
DN_CGenMapNodeToEnum const DN_CGEN_TABLE_ROW_TAG_LIST [ ] =
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
{ DN_CGenTableRowTagType_CommentDivider , DN_STR8 ( " comment_divider " ) } ,
{ DN_CGenTableRowTagType_EmptyLine , DN_STR8 ( " empty_line " ) } ,
2024-02-26 00:15:09 +11:00
} ;
2025-02-14 00:27:42 +11:00
DN_CGenMapNodeToEnum const DN_CGEN_TABLE_ROW_TAG_COMMENT_DIVIDER_KEY_LIST [ ] =
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
{ DN_CGenTableRowTagCommentDivider_Label , DN_STR8 ( " label " ) } ,
2024-02-26 00:15:09 +11:00
} ;
2025-02-14 00:27:42 +11:00
DN_CGenTableHeaderType const DN_CGEN_TABLE_CODE_GEN_STRUCT_HEADER_LIST [ ] =
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
DN_CGenTableHeaderType_Name ,
DN_CGenTableHeaderType_Table ,
DN_CGenTableHeaderType_CppType ,
DN_CGenTableHeaderType_CppName ,
DN_CGenTableHeaderType_CppIsPtr ,
DN_CGenTableHeaderType_CppOpEquals ,
DN_CGenTableHeaderType_CppArraySize ,
DN_CGenTableHeaderType_CppArraySizeField ,
DN_CGenTableHeaderType_CppLabel ,
DN_CGenTableHeaderType_GenTypeInfo ,
2024-02-26 00:15:09 +11:00
} ;
2025-02-14 00:27:42 +11:00
DN_CGenTableHeaderType const DN_CGEN_TABLE_CODE_GEN_ENUM_HEADER_LIST [ ] =
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
DN_CGenTableHeaderType_Name ,
DN_CGenTableHeaderType_Table ,
DN_CGenTableHeaderType_CppName ,
DN_CGenTableHeaderType_CppValue ,
DN_CGenTableHeaderType_CppLabel ,
DN_CGenTableHeaderType_GenTypeInfo ,
DN_CGenTableHeaderType_GenEnumCount ,
2024-02-26 00:15:09 +11:00
} ;
2025-02-14 00:27:42 +11:00
DN_CGenTableHeaderType const DN_CGEN_TABLE_CODE_GEN_BUILTIN_TYPES_HEADER_LIST [ ] =
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
DN_CGenTableHeaderType_Name ,
2024-02-26 00:15:09 +11:00
} ;
2025-02-14 00:27:42 +11:00
static bool DN_CGen_GatherTables_ ( DN_CGen * cgen , DN_ErrSink * err )
2024-02-26 00:15:09 +11:00
{
bool result = false ;
if ( ! cgen | | ! cgen - > file_list | | ! cgen - > arena )
return result ;
// NOTE: Gather the tables /////////////////////////////////////////////////////////////////////
for ( MD_EachNode ( ref , cgen - > file_list - > first_child ) ) {
MD_Node * root = MD_ResolveNodeFromReference ( ref ) ;
for ( MD_EachNode ( node , root - > first_child ) ) {
MD_Node * table_tag = MD_TagFromString ( node , MD_S8Lit ( " table " ) , 0 ) ;
if ( MD_NodeIsNil ( table_tag ) )
continue ;
2025-02-14 00:27:42 +11:00
DN_CGenTable * table = MD_PushArray ( cgen - > arena , DN_CGenTable , 1 ) ;
2024-02-26 00:15:09 +11:00
table - > node = node ;
2025-02-14 00:27:42 +11:00
table - > name = DN_CGen_MDToDNStr8 ( table_tag - > first_child - > first_child - > string ) ;
MD_MapInsert ( cgen - > arena , & cgen - > table_map , MD_MapKeyStr ( DN_CGen_DNToMDStr8 ( table - > name ) ) , table ) ;
2024-02-26 00:15:09 +11:00
MD_QueuePush ( cgen - > first_table , cgen - > last_table , table ) ;
for ( MD_EachNode ( key , table_tag - > first_child ) ) {
2025-02-14 00:27:42 +11:00
DN_CGenMapNodeToEnum key_mapping = DN_CGen_MapNodeToEnumOrExit ( key ,
DN_CGEN_TABLE_KEY_LIST ,
DN_ARRAY_UCOUNT ( DN_CGEN_TABLE_KEY_LIST ) ,
2024-02-26 00:15:09 +11:00
" Table specified invalid key " ) ;
2025-02-14 00:27:42 +11:00
switch ( DN_CAST ( DN_CGenTableKeyType ) key_mapping . enum_val ) {
case DN_CGenTableKeyType_Nil : DN_INVALID_CODE_PATH ;
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
case DN_CGenTableKeyType_Name : {
table - > name = DN_CGen_MDToDNStr8 ( key - > first_child - > string ) ;
2024-02-26 00:15:09 +11:00
} break ;
2025-02-14 00:27:42 +11:00
case DN_CGenTableKeyType_Type : {
2024-02-26 00:15:09 +11:00
MD_Node * table_type_value = key - > first_child ;
2025-02-14 00:27:42 +11:00
DN_CGenMapNodeToEnum table_type_validator = DN_CGen_MapNodeToEnumOrExit ( table_type_value ,
DN_CGEN_TABLE_TYPE_LIST ,
DN_ARRAY_UCOUNT ( DN_CGEN_TABLE_TYPE_LIST ) ,
2024-02-26 00:15:09 +11:00
" Table 'type' specified invalid value " ) ;
2025-02-14 00:27:42 +11:00
table - > type = DN_CAST ( DN_CGenTableType ) table_type_validator . enum_val ;
2024-03-19 23:11:00 +11:00
2025-02-14 00:27:42 +11:00
DN_ASSERT ( table - > type < = DN_CGenTableType_Count ) ;
2024-03-19 23:11:00 +11:00
cgen - > table_counts [ table - > type ] + + ;
2024-02-26 00:15:09 +11:00
} break ;
}
}
}
}
// NOTE: Parse the tables //////////////////////////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
DN_USize const BEGIN_COLUMN_INDEX = 1 ; /*Reserve 0th slot for nil-entry*/
for ( DN_CGenTable * table = cgen - > first_table ; table ; table = table - > next ) {
2024-02-26 00:15:09 +11:00
table - > column_count = BEGIN_COLUMN_INDEX ;
table - > headers_node = table - > node - > first_child ;
for ( MD_EachNode ( column_node , table - > headers_node - > first_child ) )
table - > column_count + + ;
if ( table - > column_count = = BEGIN_COLUMN_INDEX )
continue ;
MD_Node * row_it = table - > headers_node - > next ;
for ( MD_EachNode ( row_node , row_it ) )
table - > row_count + + ;
2025-02-14 00:27:42 +11:00
table - > rows = MD_PushArray ( cgen - > arena , DN_CGenTableRow , table - > row_count ) ;
table - > headers = MD_PushArray ( cgen - > arena , DN_CGenTableHeader , table - > column_count ) ;
for ( DN_USize index = 0 ; index < table - > row_count ; index + + ) {
DN_CGenTableRow * row = table - > rows + index ;
row - > columns = MD_PushArray ( cgen - > arena , DN_CGenTableColumn , table - > column_count ) ;
2024-02-26 00:15:09 +11:00
}
// NOTE: Collect table headers /////////////////////////////////////////////////////////////
table - > headers_map = MD_MapMake ( cgen - > arena ) ;
2025-02-14 00:27:42 +11:00
DN_USize column_index = BEGIN_COLUMN_INDEX ;
2024-02-26 00:15:09 +11:00
for ( MD_EachNode ( header_column , table - > headers_node - > first_child ) ) {
2025-02-14 00:27:42 +11:00
DN_ASSERT ( column_index < table - > column_count ) ;
2024-02-26 00:15:09 +11:00
// NOTE: Detect builtin headers and cache the index for that table /////////////////////
2025-02-14 00:27:42 +11:00
for ( DN_USize enum_index = 0 ; enum_index < DN_CGenTableHeaderType_Count ; enum_index + + ) {
DN_Str8 decl_str8 = DN_CGen_TableHeaderTypeToDeclStr8 ( DN_CAST ( DN_CGenTableHeaderType ) enum_index ) ;
if ( decl_str8 ! = DN_Str8_Init ( header_column - > string . str , header_column - > string . size ) )
2024-02-26 00:15:09 +11:00
continue ;
table - > column_indexes [ enum_index ] = column_index ;
break ;
}
2025-02-14 00:27:42 +11:00
MD_MapInsert ( cgen - > arena , & table - > headers_map , MD_MapKeyStr ( header_column - > string ) , DN_CAST ( void * ) column_index ) ;
2024-02-26 00:15:09 +11:00
table - > headers [ column_index + + ] . name = header_column - > string ;
}
// NOTE: Validate table headers ////////////////////////////////////////////////////////////
switch ( table - > type ) {
2025-02-14 00:27:42 +11:00
case DN_CGenTableType_Nil : DN_INVALID_CODE_PATH ;
case DN_CGenTableType_Count : DN_INVALID_CODE_PATH ;
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
case DN_CGenTableType_Data : {
2024-02-26 00:15:09 +11:00
} break ;
2025-02-14 00:27:42 +11:00
case DN_CGenTableType_CodeGenStruct : {
for ( DN_CGenTableHeaderType enum_val : DN_CGEN_TABLE_CODE_GEN_STRUCT_HEADER_LIST ) {
2024-02-26 00:15:09 +11:00
if ( table - > column_indexes [ enum_val ] = = 0 ) {
2025-02-14 00:27:42 +11:00
DN_Str8 expected_value = DN_CGen_TableHeaderTypeToDeclStr8 ( enum_val ) ;
DN_CGen_LogF ( MD_MessageKind_Error , table - > headers_node , err , " Struct code generation table is missing column '%.*s' " , DN_STR_FMT ( expected_value ) ) ;
2024-02-26 00:15:09 +11:00
return false ;
}
}
} break ;
2025-02-14 00:27:42 +11:00
case DN_CGenTableType_CodeGenEnum : {
for ( DN_CGenTableHeaderType enum_val : DN_CGEN_TABLE_CODE_GEN_ENUM_HEADER_LIST ) {
2024-02-26 00:15:09 +11:00
if ( table - > column_indexes [ enum_val ] = = 0 ) {
2025-02-14 00:27:42 +11:00
DN_Str8 expected_value = DN_CGen_TableHeaderTypeToDeclStr8 ( enum_val ) ;
DN_CGen_LogF ( MD_MessageKind_Error , table - > headers_node , err , " Enum code generation table is missing column '%.*s' " , DN_STR_FMT ( expected_value ) ) ;
2024-02-26 00:15:09 +11:00
return false ;
}
}
} break ;
2025-02-14 00:27:42 +11:00
case DN_CGenTableType_CodeGenBuiltinTypes : {
for ( DN_CGenTableHeaderType enum_val : DN_CGEN_TABLE_CODE_GEN_BUILTIN_TYPES_HEADER_LIST ) {
2024-02-26 00:15:09 +11:00
if ( table - > column_indexes [ enum_val ] = = 0 ) {
2025-02-14 00:27:42 +11:00
DN_Str8 expected_value = DN_CGen_TableHeaderTypeToDeclStr8 ( enum_val ) ;
DN_CGen_LogF ( MD_MessageKind_Error , table - > headers_node , err , " Enum code generation table is missing column '%.*s' " , DN_STR_FMT ( expected_value ) ) ;
2024-02-26 00:15:09 +11:00
return false ;
}
}
} break ;
}
// NOTE: Parse each row in table ///////////////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
DN_USize row_index = 0 ;
2024-02-26 00:15:09 +11:00
for ( MD_EachNode ( row_node , row_it ) ) {
column_index = BEGIN_COLUMN_INDEX ;
2025-02-14 00:27:42 +11:00
DN_ASSERT ( row_index < table - > row_count ) ;
2024-02-26 00:15:09 +11:00
// NOTE: Parse any tags set on the row /////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
DN_CGenTableRow * row = table - > rows + row_index + + ;
2024-02-26 00:15:09 +11:00
for ( MD_EachNode ( row_tag , row_node - > first_tag ) ) {
2025-02-14 00:27:42 +11:00
DN_CGenMapNodeToEnum row_mapping = DN_CGen_MapNodeToEnumOrExit ( row_tag ,
DN_CGEN_TABLE_ROW_TAG_LIST ,
DN_ARRAY_UCOUNT ( DN_CGEN_TABLE_ROW_TAG_LIST ) ,
2024-02-26 00:15:09 +11:00
" Table specified invalid row tag " ) ;
2025-02-14 00:27:42 +11:00
DN_CGenTableRowTag * tag = MD_PushArray ( cgen - > arena , DN_CGenTableRowTag , 1 ) ;
tag - > type = DN_CAST ( DN_CGenTableRowTagType ) row_mapping . enum_val ;
2024-02-26 00:15:09 +11:00
MD_QueuePush ( row - > first_tag , row - > last_tag , tag ) ;
switch ( tag - > type ) {
2025-02-14 00:27:42 +11:00
case DN_CGenTableRowTagType_Nil : DN_INVALID_CODE_PATH ;
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
case DN_CGenTableRowTagType_CommentDivider : {
2024-02-26 00:15:09 +11:00
for ( MD_EachNode ( tag_key , row_tag - > first_child ) ) {
2025-02-14 00:27:42 +11:00
DN_CGenMapNodeToEnum tag_mapping = DN_CGen_MapNodeToEnumOrExit ( tag_key ,
DN_CGEN_TABLE_ROW_TAG_COMMENT_DIVIDER_KEY_LIST ,
DN_ARRAY_UCOUNT ( DN_CGEN_TABLE_ROW_TAG_COMMENT_DIVIDER_KEY_LIST ) ,
2024-02-26 00:15:09 +11:00
" Table specified invalid row tag " ) ;
2025-02-14 00:27:42 +11:00
switch ( DN_CAST ( DN_CGenTableRowTagCommentDivider ) tag_mapping . enum_val ) {
case DN_CGenTableRowTagCommentDivider_Nil : DN_INVALID_CODE_PATH ;
case DN_CGenTableRowTagCommentDivider_Label : {
2024-02-26 00:15:09 +11:00
tag - > comment = tag_key - > first_child - > string ;
} break ;
}
}
} break ;
2025-02-14 00:27:42 +11:00
case DN_CGenTableRowTagType_EmptyLine : break ;
2024-02-26 00:15:09 +11:00
}
}
for ( MD_EachNode ( column_node , row_node - > first_child ) ) {
2025-02-14 00:27:42 +11:00
table - > headers [ column_index ] . longest_string = DN_MAX ( table - > headers [ column_index ] . longest_string , DN_CAST ( int ) column_node - > string . size ) ;
row - > columns [ column_index ] . string = DN_CGen_MDToDNStr8 ( column_node - > string ) ;
2024-02-26 00:15:09 +11:00
row - > columns [ column_index ] . node = column_node ;
column_index + + ;
}
}
}
// NOTE: Validate codegen //////////////////////////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
DN_CGenTableHeaderType const CHECK_COLUMN_LINKS [ ] = {
DN_CGenTableHeaderType_CppName ,
DN_CGenTableHeaderType_CppType ,
DN_CGenTableHeaderType_CppValue ,
DN_CGenTableHeaderType_CppIsPtr ,
DN_CGenTableHeaderType_CppArraySize ,
DN_CGenTableHeaderType_CppArraySizeField ,
2024-02-26 00:15:09 +11:00
} ;
result = true ;
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ; table = table - > next ) {
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
for ( DN_CGenTableHeaderType check_column : CHECK_COLUMN_LINKS ) {
DN_CGenTableColumn column = it . cgen_table_row - > columns [ table - > column_indexes [ check_column ] ] ;
2024-02-26 00:15:09 +11:00
if ( column . string . size = = 0 ) {
// NOTE: The code generation table did not bind a code generation parameter to
// a column in the target table. We skip it.
continue ;
}
// NOTE: Check if the column to bind to exists in the target table.
2025-02-14 00:27:42 +11:00
if ( ! MD_MapLookup ( & it . table - > headers_map , MD_MapKeyStr ( DN_CGen_DNToMDStr8 ( column . string ) ) ) ) {
2024-02-26 00:15:09 +11:00
result = false ;
2025-02-14 00:27:42 +11:00
DN_Str8 header_type_str8 = DN_CGen_TableHeaderTypeToDeclStr8 ( check_column ) ;
DN_CGen_LogF ( MD_MessageKind_Error , column . node , err ,
2024-02-26 00:15:09 +11:00
" Code generation table binds '%.*s' to '%.*s', but the column '%.*s' does not exist in table '%.*s' \n "
" NOTE: If you want '%.*s' to omit the column '%.*s' you can bind to the empty string `` to skip it, otherwise, please ensure the table '%.*s' has the column '%.*s' "
,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( column . string ) ,
DN_STR_FMT ( header_type_str8 ) ,
DN_STR_FMT ( column . string ) ,
DN_STR_FMT ( it . table - > name ) ,
DN_STR_FMT ( it . table - > name ) ,
DN_STR_FMT ( header_type_str8 ) ,
DN_STR_FMT ( it . table - > name ) ,
DN_STR_FMT ( header_type_str8 ) ) ;
2024-02-26 00:15:09 +11:00
}
}
}
}
return result ;
}
2025-02-14 00:27:42 +11:00
DN_API DN_CGen DN_CGen_InitFilesArgV ( int argc , char const * * argv , DN_ErrSink * err )
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
DN_CGen result = { } ;
2024-02-26 00:15:09 +11:00
result . arena = MD_ArenaAlloc ( ) ;
result . file_list = MD_MakeList ( result . arena ) ;
result . table_map = MD_MapMake ( result . arena ) ;
bool has_error = false ;
2025-02-14 00:27:42 +11:00
for ( DN_ISize arg_index = 0 ; arg_index < argc ; arg_index + + ) {
MD_String8 file_name = MD_S8CString ( DN_CAST ( char * ) argv [ arg_index ] ) ;
2024-02-26 00:15:09 +11:00
MD_ParseResult parse_result = MD_ParseWholeFile ( result . arena , file_name ) ;
for ( MD_Message * message = parse_result . errors . first ; message ! = 0 ; message = message - > next ) {
has_error = true ;
2025-02-14 00:27:42 +11:00
DN_CGen_LogF ( message - > kind , message - > node , err , " %.*s " , MD_S8VArg ( message - > string ) ) ;
2024-02-26 00:15:09 +11:00
}
MD_PushNewReference ( result . arena , result . file_list , parse_result . node ) ;
}
if ( ! has_error )
2025-02-14 00:27:42 +11:00
DN_CGen_GatherTables_ ( & result , err ) ;
2024-02-26 00:15:09 +11:00
return result ;
}
2025-02-14 00:27:42 +11:00
DN_API DN_Str8 DN_CGen_TableHeaderTypeToDeclStr8 ( DN_CGenTableHeaderType type )
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
DN_Str8 result = { } ;
2024-02-26 00:15:09 +11:00
switch ( type ) {
2025-02-14 00:27:42 +11:00
case DN_CGenTableHeaderType_Name : result = DN_STR8 ( " name " ) ; break ;
case DN_CGenTableHeaderType_Table : result = DN_STR8 ( " table " ) ; break ;
case DN_CGenTableHeaderType_CppType : result = DN_STR8 ( " cpp_type " ) ; break ;
case DN_CGenTableHeaderType_CppName : result = DN_STR8 ( " cpp_name " ) ; break ;
case DN_CGenTableHeaderType_CppValue : result = DN_STR8 ( " cpp_value " ) ; break ;
case DN_CGenTableHeaderType_CppIsPtr : result = DN_STR8 ( " cpp_is_ptr " ) ; break ;
case DN_CGenTableHeaderType_CppOpEquals : result = DN_STR8 ( " cpp_op_equals " ) ; break ;
case DN_CGenTableHeaderType_CppArraySize : result = DN_STR8 ( " cpp_array_size " ) ; break ;
case DN_CGenTableHeaderType_CppArraySizeField : result = DN_STR8 ( " cpp_array_size_field " ) ; break ;
case DN_CGenTableHeaderType_CppLabel : result = DN_STR8 ( " cpp_label " ) ; break ;
case DN_CGenTableHeaderType_GenTypeInfo : result = DN_STR8 ( " gen_type_info " ) ; break ;
case DN_CGenTableHeaderType_GenEnumCount : result = DN_STR8 ( " gen_enum_count " ) ; break ;
case DN_CGenTableHeaderType_Count : result = DN_STR8 ( " XX BAD ENUM VALUE XX " ) ; break ;
default : result = DN_STR8 ( " XX INVALID ENUM VALUE XX " ) ; break ;
2024-02-26 00:15:09 +11:00
}
return result ;
}
2025-02-14 00:27:42 +11:00
DN_API DN_CGenMapNodeToEnum DN_CGen_MapNodeToEnumOrExit ( MD_Node const * node , DN_CGenMapNodeToEnum const * valid_keys , DN_USize valid_keys_size , char const * fmt , . . . )
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
DN_CGenMapNodeToEnum result = { } ;
for ( DN_USize index = 0 ; index < valid_keys_size ; index + + ) {
DN_CGenMapNodeToEnum const * validator = valid_keys + index ;
if ( DN_Str8_Init ( node - > string . str , node - > string . size ) = = validator - > node_string ) {
2024-02-26 00:15:09 +11:00
result = * validator ;
break ;
}
}
if ( result . enum_val = = 0 ) {
2025-02-14 00:27:42 +11:00
MD_CodeLoc loc = MD_CodeLocFromNode ( DN_CAST ( MD_Node * ) node ) ;
DN_TLSTMem tmem = DN_TLS_TMem ( nullptr ) ;
2024-02-26 00:15:09 +11:00
va_list args ;
va_start ( args , fmt ) ;
2025-02-14 00:27:42 +11:00
DN_Str8 user_msg = DN_Str8_InitFV ( tmem . arena , fmt , args ) ;
2024-02-26 00:15:09 +11:00
va_end ( args ) ;
2025-02-14 00:27:42 +11:00
DN_Str8Builder builder = { } ;
2024-08-01 13:34:36 +10:00
builder . arena = tmem . arena ;
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder , " %.*s: '%.*s' is not recognised, the supported values are " , DN_STR_FMT ( user_msg ) , MD_S8VArg ( node - > string ) ) ;
for ( DN_USize index = 0 ; index < valid_keys_size ; index + + ) {
DN_CGenMapNodeToEnum const * validator = valid_keys + index ;
DN_Str8Builder_AppendF ( & builder , DN_CAST ( char * ) " %s'%.*s' " , index ? " , " : " " , DN_STR_FMT ( validator - > node_string ) ) ;
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
DN_Str8 error_msg = DN_Str8Builder_Build ( & builder , tmem . arena ) ;
MD_PrintMessageFmt ( stderr , loc , MD_MessageKind_Error , DN_CAST ( char * ) " %.*s " , DN_STR_FMT ( error_msg ) ) ;
DN_OS_Exit ( DN_CAST ( uint32_t ) - 1 ) ;
2024-02-26 00:15:09 +11:00
}
return result ;
}
2025-02-14 00:27:42 +11:00
DN_API DN_USize DN_CGen_NodeChildrenCount ( MD_Node const * node )
2024-08-01 13:34:36 +10:00
{
2025-02-14 00:27:42 +11:00
DN_USize result = 0 ;
2024-08-01 13:34:36 +10:00
for ( MD_EachNode ( item , node - > first_child ) )
result + + ;
return result ;
}
2025-02-14 00:27:42 +11:00
DN_API void DN_CGen_LogF ( MD_MessageKind kind , MD_Node * node , DN_ErrSink * err , char const * fmt , . . . )
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
if ( ! err )
2024-02-26 00:15:09 +11:00
return ;
2025-02-14 00:27:42 +11:00
DN_TLSTMem tmem = DN_TLS_PushTMem ( nullptr ) ;
DN_Str8Builder builder = DN_Str8Builder_Init_TLS ( ) ;
2024-02-26 00:15:09 +11:00
MD_String8 kind_string = MD_StringFromMessageKind ( kind ) ;
MD_CodeLoc loc = MD_CodeLocFromNode ( node ) ;
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder , " " MD_FmtCodeLoc " %.*s: " , MD_CodeLocVArg ( loc ) , MD_S8VArg ( kind_string ) ) ;
2024-02-26 00:15:09 +11:00
va_list args ;
va_start ( args , fmt ) ;
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendFV ( & builder , fmt , args ) ;
2024-02-26 00:15:09 +11:00
va_end ( args ) ;
2025-02-14 00:27:42 +11:00
DN_Str8 msg = DN_Str8Builder_Build ( & builder , tmem . arena ) ;
DN_ErrSink_AppendF ( err , DN_CAST ( uint32_t ) - 1 , " %.*s " , DN_STR_FMT ( msg ) ) ;
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
DN_API bool DN_CGen_TableHasHeaders ( DN_CGenTable const * table , DN_Str8 const * headers , DN_USize header_count , DN_ErrSink * err )
2024-02-26 00:15:09 +11:00
{
bool result = true ;
2025-02-14 00:27:42 +11:00
DN_TLSTMem tmem = DN_TLS_TMem ( nullptr ) ;
DN_Str8Builder builder = { } ;
2024-08-01 13:34:36 +10:00
builder . arena = tmem . arena ;
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
for ( DN_USize index = 0 ; index < header_count ; index + + ) {
DN_Str8 header = headers [ index ] ;
MD_String8 header_md = { DN_CAST ( MD_u8 * ) header . data , header . size } ;
MD_MapSlot * slot = MD_MapLookup ( DN_CAST ( MD_Map * ) & table - > headers_map , MD_MapKeyStr ( header_md ) ) ;
2024-02-26 00:15:09 +11:00
if ( ! slot ) {
result = false ;
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder , " %s%.*s " , builder . count ? " , " : " " , DN_STR_FMT ( header ) ) ;
2024-02-26 00:15:09 +11:00
}
}
if ( ! result ) {
2025-02-14 00:27:42 +11:00
DN_Str8 missing_headers = DN_Str8Builder_Build ( & builder , tmem . arena ) ;
DN_CGen_LogF ( MD_MessageKind_Error ,
2024-02-29 21:30:06 +11:00
table - > headers_node ,
2025-02-14 00:27:42 +11:00
err ,
2024-02-29 21:30:06 +11:00
" Table '%.*s' is missing the header(s): %.*s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( table - > name ) ,
DN_STR_FMT ( missing_headers ) ) ;
2024-02-26 00:15:09 +11:00
}
return result ;
}
2025-02-14 00:27:42 +11:00
DN_API DN_CGenLookupColumnAtHeader DN_CGen_LookupColumnAtHeader ( DN_CGenTable * table , DN_Str8 header , DN_CGenTableRow const * row )
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
DN_CGenLookupColumnAtHeader result = { } ;
2024-02-26 00:15:09 +11:00
if ( ! table | | ! row )
return result ;
2025-02-14 00:27:42 +11:00
MD_String8 header_md = { DN_CAST ( MD_u8 * ) header . data , header . size } ;
2024-02-26 00:15:09 +11:00
MD_MapSlot * slot = MD_MapLookup ( & table - > headers_map , MD_MapKeyStr ( header_md ) ) ;
if ( ! slot )
return result ;
2025-02-14 00:27:42 +11:00
DN_USize column_index = DN_CAST ( DN_USize ) slot - > val ;
DN_ASSERT ( column_index < table - > column_count ) ;
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
DN_USize begin = DN_CAST ( uintptr_t ) ( table - > rows ) ;
DN_USize end = DN_CAST ( uintptr_t ) ( table - > rows + table - > row_count ) ;
DN_USize ptr = DN_CAST ( uintptr_t ) row ;
DN_ASSERTF ( ptr > = begin & & ptr < = end , " The row to lookup does not belong to the table passed in " ) ;
2024-02-26 00:15:09 +11:00
}
result . index = column_index ;
result . column = row - > columns [ column_index ] ;
result . header = table - > headers [ column_index ] ;
return result ;
}
2025-02-14 00:27:42 +11:00
DN_API bool DN_CGen_LookupNextTableInCodeGenTable ( DN_CGen * cgen , DN_CGenTable * cgen_table , DN_CGenLookupTableIterator * it )
2024-02-26 00:15:09 +11:00
{
if ( ! cgen_table )
return false ;
if ( it - > row_index > = cgen_table - > row_count )
return false ;
2025-02-14 00:27:42 +11:00
if ( cgen_table - > type ! = DN_CGenTableType_CodeGenEnum & & cgen_table - > type ! = DN_CGenTableType_CodeGenStruct & & cgen_table - > type ! = DN_CGenTableType_CodeGenBuiltinTypes )
2024-02-26 00:15:09 +11:00
return false ;
// NOTE: Lookup the table in this row that we will code generate from. Not
// applicable when we are doing builtin types as the types are just put
// in-line into the code generation table itself.
2024-03-19 23:11:00 +11:00
it - > cgen_table = cgen_table ;
2024-02-26 00:15:09 +11:00
it - > cgen_table_row = cgen_table - > rows + it - > row_index + + ;
2025-02-14 00:27:42 +11:00
if ( cgen_table - > type ! = DN_CGenTableType_CodeGenBuiltinTypes ) {
DN_CGenTableColumn cgen_table_column = it - > cgen_table_row - > columns [ cgen_table - > column_indexes [ DN_CGenTableHeaderType_Table ] ] ;
MD_String8 key = { DN_CAST ( MD_u8 * ) cgen_table_column . string . data , cgen_table_column . string . size } ;
2024-02-26 00:15:09 +11:00
MD_MapSlot * table_slot = MD_MapLookup ( & cgen - > table_map , MD_MapKeyStr ( key ) ) ;
if ( ! table_slot ) {
MD_CodeLoc loc = MD_CodeLocFromNode ( cgen_table_column . node ) ;
MD_PrintMessageFmt ( stderr ,
loc ,
MD_MessageKind_Warning ,
2025-02-14 00:27:42 +11:00
DN_CAST ( char * ) " Code generation table references non-existent table '%.*s' " ,
DN_STR_FMT ( cgen_table_column . string ) ) ;
2024-02-26 00:15:09 +11:00
return false ;
}
2025-02-14 00:27:42 +11:00
it - > table = DN_CAST ( DN_CGenTable * ) table_slot - > val ;
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
for ( DN_USize type = 0 ; type < DN_CGenTableHeaderType_Count ; type + + )
2024-02-26 00:15:09 +11:00
it - > cgen_table_column [ type ] = it - > cgen_table_row - > columns [ cgen_table - > column_indexes [ type ] ] ;
return true ;
}
2025-02-14 00:27:42 +11:00
DN_API bool DN_CGen_WillCodeGenTypeName ( DN_CGen const * cgen , DN_Str8 name )
2024-08-01 13:34:36 +10:00
{
2025-02-14 00:27:42 +11:00
if ( ! DN_Str8_HasData ( name ) )
2024-08-01 13:34:36 +10:00
return false ;
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
if ( table - > type ! = DN_CGenTableType_CodeGenStruct & & table - > type ! = DN_CGenTableType_CodeGenEnum )
2024-08-01 13:34:36 +10:00
continue ;
2025-02-14 00:27:42 +11:00
for ( DN_USize row_index = 0 ; row_index < table - > row_count ; row_index + + ) {
DN_CGenTableRow const * row = table - > rows + row_index ;
DN_CGenTableColumn const * column = row - > columns + table - > column_indexes [ DN_CGenTableHeaderType_Name ] ;
2024-08-01 13:34:36 +10:00
if ( column - > string = = name )
return true ;
}
}
return false ;
}
2025-02-14 00:27:42 +11:00
static void DN_CGen_EmitRowWhitespace_ ( DN_CGenTableRow const * row , DN_CppFile * cpp )
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
for ( DN_CGenTableRowTag * tag = row - > first_tag ; tag ; tag = tag - > next ) {
2024-02-26 00:15:09 +11:00
switch ( tag - > type ) {
2025-02-14 00:27:42 +11:00
case DN_CGenTableRowTagType_Nil : DN_INVALID_CODE_PATH ;
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
case DN_CGenTableRowTagType_CommentDivider : {
2024-02-26 00:15:09 +11:00
if ( tag - > comment . size < = 0 )
break ;
2025-02-14 00:27:42 +11:00
DN_TLSTMem tmem = DN_TLS_TMem ( nullptr ) ;
DN_Str8 prefix = DN_Str8_InitF ( tmem . arena , " // NOTE: %.*s " , MD_S8VArg ( tag - > comment ) ) ;
int line_padding = DN_MAX ( 100 - ( DN_CAST ( int ) prefix . size + ( DN_CppSpacePerIndent ( cpp ) * cpp - > indent ) ) , 0 ) ;
DN_CppPrint ( cpp , " %.*s " , DN_STR_FMT ( prefix ) ) ;
2024-02-26 00:15:09 +11:00
for ( int index = 0 ; index < line_padding ; index + + )
2025-02-14 00:27:42 +11:00
DN_CppAppend ( cpp , " / " ) ;
DN_CppAppend ( cpp , " \n " ) ;
2024-02-26 00:15:09 +11:00
} break ;
2025-02-14 00:27:42 +11:00
case DN_CGenTableRowTagType_EmptyLine : {
DN_CppAppend ( cpp , " \n " ) ;
2024-02-26 00:15:09 +11:00
} break ;
}
}
}
2025-02-14 00:27:42 +11:00
DN_Str8 DN_CGen_StripQualifiersOnCppType_ ( DN_Arena * arena , DN_Str8 type )
2024-02-26 00:15:09 +11:00
{
2025-02-14 00:27:42 +11:00
DN_TLSTMem tmem = DN_TLS_TMem ( arena ) ;
DN_Str8 result = DN_Str8_TrimWhitespaceAround ( type ) ;
result = DN_Str8_Replace ( result , /*find*/ DN_STR8 ( " * " ) , /*replace*/ DN_STR8 ( " " ) , /*start_index*/ 0 , tmem . arena , DN_Str8EqCase_Sensitive ) ;
result = DN_Str8_Replace ( result , /*find*/ DN_STR8 ( " constexpr " ) , /*replace*/ DN_STR8 ( " " ) , /*start_index*/ 0 , tmem . arena , DN_Str8EqCase_Sensitive ) ;
result = DN_Str8_Replace ( result , /*find*/ DN_STR8 ( " const " ) , /*replace*/ DN_STR8 ( " " ) , /*start_index*/ 0 , tmem . arena , DN_Str8EqCase_Sensitive ) ;
result = DN_Str8_Replace ( result , /*find*/ DN_STR8 ( " static " ) , /*replace*/ DN_STR8 ( " " ) , /*start_index*/ 0 , tmem . arena , DN_Str8EqCase_Sensitive ) ;
result = DN_Str8_Replace ( result , /*find*/ DN_STR8 ( " " ) , /*replace*/ DN_STR8 ( " " ) , /*start_index*/ 0 , arena , DN_Str8EqCase_Sensitive ) ;
result = DN_Str8_TrimWhitespaceAround ( result ) ;
2024-08-01 13:34:36 +10:00
return result ;
}
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
DN_API void DN_CGen_EmitCodeForTables ( DN_CGen * cgen , DN_CGenEmit emit , DN_CppFile * cpp , DN_Str8 emit_prefix )
2024-08-01 13:34:36 +10:00
{
2025-02-14 00:27:42 +11:00
if ( emit & DN_CGenEmit_Prototypes ) {
2024-02-26 00:15:09 +11:00
// NOTE: Generate type info enums //////////////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
DN_CppEnumBlock ( cpp , " %.*sType " , DN_STR_FMT ( emit_prefix ) ) {
DN_CppLine ( cpp , " %.*sType_Nil, " , DN_STR_FMT ( emit_prefix ) ) ;
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; )
DN_CppLine ( cpp , " %.*sType_%.*s, " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ) ) ;
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
DN_CppLine ( cpp , " %.*sType_Count, " , DN_STR_FMT ( emit_prefix ) ) ;
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
DN_CppNewLine ( cpp ) ;
2024-02-26 00:15:09 +11:00
// NOTE: Generate structs + enums //////////////////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
2024-02-26 00:15:09 +11:00
switch ( table - > type ) {
2025-02-14 00:27:42 +11:00
case DN_CGenTableType_Nil : DN_INVALID_CODE_PATH ;
case DN_CGenTableType_Count : DN_INVALID_CODE_PATH ;
case DN_CGenTableType_CodeGenBuiltinTypes : continue ;
case DN_CGenTableType_Data : continue ;
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
case DN_CGenTableType_CodeGenStruct : {
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
2024-02-26 00:15:09 +11:00
// TODO(doyle): Verify the codegen table has the headers from the table it references
2024-08-01 13:34:36 +10:00
int longest_type_name = 0 ;
2025-02-14 00:27:42 +11:00
for ( DN_USize row_index = 0 ; row_index < it . table - > row_count ; row_index + + ) {
DN_TLSTMem tmem = DN_TLS_TMem ( nullptr ) ;
DN_CGenTableRow const * row = it . table - > rows + row_index ;
DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppType ] . string , row ) ;
DN_USize length = cpp_type . column . string . size ;
DN_Str8 find_name = DN_CGen_StripQualifiersOnCppType_ ( tmem . arena , cpp_type . column . string ) ;
if ( DN_CGen_WillCodeGenTypeName ( cgen , find_name ) )
2024-08-01 13:34:36 +10:00
length + = emit_prefix . size ;
2025-02-14 00:27:42 +11:00
longest_type_name = DN_MAX ( longest_type_name , DN_CAST ( int ) length ) ;
2024-08-01 13:34:36 +10:00
}
2025-02-14 00:27:42 +11:00
DN_CppStructBlock ( cpp , " %.*s%.*s " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ) ) {
for ( DN_USize row_index = 0 ; row_index < it . table - > row_count ; row_index + + ) {
DN_CGenTableRow const * row = it . table - > rows + row_index ;
DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppName ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppType ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_array_size = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppArraySize ] . string , row ) ;
2024-02-26 00:15:09 +11:00
if ( cpp_name . column . string . size < = 0 | | cpp_type . column . string . size < = 0 )
continue ;
2024-08-01 13:34:36 +10:00
// NOTE: Generate cpp array size ///////////////////////////////////
2025-02-14 00:27:42 +11:00
DN_TLSTMem tmem = DN_TLS_TMem ( nullptr ) ;
DN_Str8 array_size = { } ;
2024-02-26 00:15:09 +11:00
if ( cpp_array_size . column . string . size )
2025-02-14 00:27:42 +11:00
array_size = DN_Str8_InitF ( tmem . arena , " [%.*s] " , DN_STR_FMT ( cpp_array_size . column . string ) ) ;
2024-08-01 13:34:36 +10:00
// NOTE: Check if we're referencing a code generated type. If we
// are, append the `emit_prefix`
2025-02-14 00:27:42 +11:00
DN_Str8 emit_cpp_type = cpp_type . column . string ;
2024-08-01 13:34:36 +10:00
{
2025-02-14 00:27:42 +11:00
DN_Str8 find_name = DN_CGen_StripQualifiersOnCppType_ ( tmem . arena , emit_cpp_type ) ;
if ( DN_CGen_WillCodeGenTypeName ( cgen , find_name ) )
emit_cpp_type = DN_Str8_InitF ( tmem . arena , " %.*s%.*s " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( cpp_type . column . string ) ) ;
2024-08-01 13:34:36 +10:00
}
2025-02-14 00:27:42 +11:00
int name_to_type_padding = 1 + longest_type_name - DN_CAST ( int ) emit_cpp_type . size ;
2024-02-26 00:15:09 +11:00
2024-08-01 13:34:36 +10:00
// NOTE: Emit decl /////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
DN_CGen_EmitRowWhitespace_ ( row , cpp ) ;
DN_CppLine ( cpp ,
2024-02-26 00:15:09 +11:00
" %.*s%*s%.*s%.*s; " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( emit_cpp_type ) ,
2024-02-26 00:15:09 +11:00
name_to_type_padding ,
" " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( cpp_name . column . string ) ,
DN_STR_FMT ( array_size ) ) ;
2024-02-26 00:15:09 +11:00
}
}
2025-02-14 00:27:42 +11:00
DN_CppNewLine ( cpp ) ;
DN_CppNewLine ( cpp ) ;
2024-02-26 00:15:09 +11:00
}
} break ;
2025-02-14 00:27:42 +11:00
case DN_CGenTableType_CodeGenEnum : {
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
DN_CppEnumBlock ( cpp , " %.*s%.*s " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ) ) {
DN_USize enum_count = 0 ;
for ( DN_USize row_index = 0 ; row_index < it . table - > row_count ; row_index + + ) {
DN_CGenTableRow const * row = it . table - > rows + row_index ;
DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppName ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_value = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppValue ] . string , row ) ;
2024-02-26 00:15:09 +11:00
if ( cpp_name . column . string . size < = 0 )
continue ;
2025-02-14 00:27:42 +11:00
DN_CGen_EmitRowWhitespace_ ( row , cpp ) ;
2024-02-26 00:15:09 +11:00
if ( cpp_value . column . string . size ) {
2025-02-14 00:27:42 +11:00
DN_CppLine ( cpp ,
2024-08-01 13:34:36 +10:00
" %.*s%.*s_%.*s = %.*s, " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ) ,
DN_STR_FMT ( cpp_name . column . string ) ,
DN_STR_FMT ( cpp_value . column . string ) ) ;
2024-02-26 00:15:09 +11:00
} else {
2025-02-14 00:27:42 +11:00
DN_CppLine ( cpp ,
2024-08-01 13:34:36 +10:00
" %.*s%.*s_%.*s = %zu, " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ) ,
DN_STR_FMT ( cpp_name . column . string ) ,
2024-02-26 00:15:09 +11:00
row_index ) ;
}
enum_count + + ;
}
2025-02-14 00:27:42 +11:00
DN_CGenTableColumn gen_enum_count_column = it . cgen_table_column [ DN_CGenTableHeaderType_GenEnumCount ] ;
2024-02-26 00:15:09 +11:00
if ( gen_enum_count_column . string . size )
2025-02-14 00:27:42 +11:00
DN_CppLine ( cpp ,
2024-08-01 13:34:36 +10:00
" %.*s%.*s_%.*s = %zu, " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ) ,
DN_STR_FMT ( gen_enum_count_column . string ) ,
2024-02-26 00:15:09 +11:00
enum_count ) ;
}
2025-02-14 00:27:42 +11:00
DN_CppNewLine ( cpp ) ;
2024-02-26 00:15:09 +11:00
}
} break ;
}
}
// NOTE: Generate enums for struct fields //////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
2024-02-26 00:15:09 +11:00
switch ( table - > type ) {
2025-02-14 00:27:42 +11:00
case DN_CGenTableType_Nil : DN_INVALID_CODE_PATH ;
case DN_CGenTableType_Count : DN_INVALID_CODE_PATH ;
case DN_CGenTableType_Data : continue ;
case DN_CGenTableType_CodeGenBuiltinTypes : continue ;
case DN_CGenTableType_CodeGenEnum : continue ;
case DN_CGenTableType_CodeGenStruct : {
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
DN_Str8 struct_name = it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ;
DN_CppEnumBlock ( cpp , " %.*s%.*sTypeField " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( struct_name ) ) {
for ( DN_USize row_index = 0 ; row_index < it . table - > row_count ; row_index + + ) {
DN_CGenTableRow const * row = it . table - > rows + row_index ;
DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppName ] . string , row ) ;
2024-02-26 00:15:09 +11:00
if ( cpp_name . column . string . size < = 0 )
continue ;
2025-02-14 00:27:42 +11:00
DN_CGen_EmitRowWhitespace_ ( row , cpp ) ;
DN_CppLine ( cpp , " %.*s%.*sTypeField_%.*s, " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( struct_name ) , DN_STR_FMT ( cpp_name . column . string ) ) ;
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
DN_CppLine ( cpp , " %.*s%.*sTypeField_Count, " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( struct_name ) ) ;
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
DN_CppNewLine ( cpp ) ;
2024-02-26 00:15:09 +11:00
}
} break ;
}
}
2024-04-18 22:59:11 +10:00
// NOTE: Str8 to enum conversion ////////////////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
if ( table - > type ! = DN_CGenTableType_CodeGenEnum )
2024-04-18 22:59:11 +10:00
continue ;
2025-02-14 00:27:42 +11:00
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
DN_Str8 type_name = it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ;
DN_CppStructBlock ( cpp , " %.*s%.*sStr8ToEnumResult " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) {
DN_CppLine ( cpp , " bool success; " ) ;
DN_CppLine ( cpp , " %.*s%.*s value; " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) ;
2024-04-18 22:59:11 +10:00
}
2025-02-14 00:27:42 +11:00
DN_CppNewLine ( cpp ) ;
2024-04-18 22:59:11 +10:00
}
}
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
if ( table - > type ! = DN_CGenTableType_CodeGenEnum )
2024-04-18 22:59:11 +10:00
continue ;
2025-02-14 00:27:42 +11:00
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
DN_Str8 type_name = it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ;
DN_CppLine ( cpp ,
" %.*s%.*sStr8ToEnumResult %.*s%.*s_NameStr8ToEnum(DN_Str8 string); " ,
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( type_name ) ,
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( type_name ) ) ;
DN_CppLine ( cpp ,
" %.*s%.*sStr8ToEnumResult %.*s%.*s_LabelStr8ToEnum(DN_Str8 string); " ,
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( type_name ) ,
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( type_name ) ) ;
2024-04-18 22:59:11 +10:00
}
}
// NOTE: Operator == and != ////////////////////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
if ( table - > type ! = DN_CGenTableType_CodeGenStruct )
2024-04-18 22:59:11 +10:00
continue ;
2025-02-14 00:27:42 +11:00
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
DN_Str8 cpp_op_equals = it . cgen_table_column [ DN_CGenTableHeaderType_CppOpEquals ] . string ;
if ( cpp_op_equals ! = DN_STR8 ( " true " ) )
2024-04-18 22:59:11 +10:00
continue ;
2025-02-14 00:27:42 +11:00
DN_Str8 type_name = it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ;
DN_CppLine ( cpp ,
2024-08-01 13:34:36 +10:00
" bool operator==(%.*s%.*s const &lhs, %.*s%.*s const &rhs); " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( type_name ) ,
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( type_name ) ) ;
DN_CppLine ( cpp ,
2024-08-01 13:34:36 +10:00
" bool operator!=(%.*s%.*s const &lhs, %.*s%.*s const &rhs); " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( type_name ) ,
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( type_name ) ) ;
2024-04-18 22:59:11 +10:00
}
}
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
if ( emit & DN_CGenEmit_Implementation ) {
2024-02-26 00:15:09 +11:00
// NOTE: Generate type info ////////////////////////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
if ( table - > type = = DN_CGenTableType_CodeGenBuiltinTypes )
2024-02-26 00:15:09 +11:00
continue ;
2025-02-14 00:27:42 +11:00
DN_Str8 struct_or_enum_name = it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ;
DN_CppBlock ( cpp , " ; \n \n " , " DN_TypeField const g_%.*s%.*s_type_fields[] = " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( struct_or_enum_name ) ) {
if ( table - > type = = DN_CGenTableType_CodeGenStruct ) {
2024-08-01 13:34:36 +10:00
// NOTE: Construct the cpp type string first. We will prepend `emit_prefix`
// for types that are declared in the same mdesk file. We will also
// calculate the longest type name that we will generate for whitespace
// padding purposes.
2025-02-14 00:27:42 +11:00
DN_TLSTMem tmem = DN_TLS_PushTMem ( nullptr ) ;
DN_USize longest_cpp_type_name = 0 ;
auto cpp_type_list = DN_SArray_Init < DN_Str8 > ( tmem . arena , it . table - > row_count , DN_ZeroMem_Yes ) ;
for ( DN_USize row_index = 0 ; row_index < it . table - > row_count ; row_index + + ) {
DN_CGenTableRow const * row = it . table - > rows + row_index ;
DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppType ] . string , row ) ;
DN_Str8 cpp_type_name = DN_CGen_StripQualifiersOnCppType_ ( tmem . arena , cpp_type . column . string ) ;
if ( DN_CGen_WillCodeGenTypeName ( cgen , cpp_type_name ) )
cpp_type_name = DN_Str8_InitF_TLS ( " %.*s%.*s " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( cpp_type_name ) ) ;
longest_cpp_type_name = DN_MAX ( longest_cpp_type_name , cpp_type_name . size ) ;
DN_SArray_Add ( & cpp_type_list , cpp_type_name ) ;
2024-08-01 13:34:36 +10:00
}
// NOTE: Iterate each row and emit the C++ declarations ////////////////////
2025-02-14 00:27:42 +11:00
for ( DN_USize row_index = 0 ; row_index < it . table - > row_count ; row_index + + ) {
DN_CGenTableRow const * row = it . table - > rows + row_index ;
DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppName ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_type = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppType ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_is_ptr = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppIsPtr ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_array_size = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppArraySize ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_array_size_field = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppArraySizeField ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_label = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppLabel ] . string , row ) ;
bool cpp_is_ptr_b32 = cpp_is_ptr . column . string = = DN_STR8 ( " true " ) ;
DN_Str8 cpp_array_size_str8 = DN_Str8_HasData ( cpp_array_size . column . string ) ? cpp_array_size . column . string : DN_STR8 ( " 0 " ) ;
DN_CGenTableColumn struct_name = it . cgen_table_row - > columns [ table - > column_indexes [ DN_CGenTableHeaderType_Name ] ] ;
DN_Str8 cpp_array_size_field_str8 = DN_STR8 ( " NULL " ) ;
2024-02-26 00:15:09 +11:00
if ( cpp_array_size_field . column . string . size ) {
// TODO(doyle): Check that array_size_field references a valid field in the table
// NOTE: We use a raw index for the reference because the struct might
// not have type info being generated so we can't rely on the enum.
2025-02-14 00:27:42 +11:00
DN_USize index_the_field_references = 0 ;
for ( DN_USize sub_row_index = 0 ; sub_row_index < it . table - > row_count ; sub_row_index + + ) {
DN_CGenTableRow const * sub_row = it . table - > rows + sub_row_index ;
DN_CGenTableColumn sub_cpp_name = sub_row - > columns [ cpp_name . index ] ;
2024-02-26 00:15:09 +11:00
if ( sub_cpp_name . string = = cpp_array_size_field . column . string )
index_the_field_references = sub_row_index ;
}
2024-08-01 13:34:36 +10:00
cpp_array_size_field_str8 =
2025-02-14 00:27:42 +11:00
DN_Str8_InitF_TLS ( " &g_%.*s%.*s_type_fields[%zu] " ,
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( struct_name . string ) ,
2024-08-01 13:34:36 +10:00
index_the_field_references ) ;
}
2025-02-14 00:27:42 +11:00
DN_Str8 cpp_type_name = cpp_type_list . data [ row_index ] ;
DN_Str8 orig_cpp_type = DN_CGen_StripQualifiersOnCppType_ ( tmem . arena , cpp_type . column . string ) ;
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
DN_USize cpp_name_padding = 1 + it . table - > headers [ cpp_name . index ] . longest_string - cpp_name . column . string . size ;
DN_USize cpp_type_padding = 1 + longest_cpp_type_name - cpp_type_name . size ;
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
DN_Str8 cpp_type_enum = DN_Str8_InitF_TLS ( " %.*sType_%.*s " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( orig_cpp_type ) ) ;
DN_USize cpp_type_enum_padding = cpp_type_padding + ( orig_cpp_type . size - cpp_type_name . size ) ;
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
DN_Str8 cpp_label_str8 = cpp_name . column . string ;
DN_USize cpp_label_str8_padding = cpp_name_padding ;
2024-08-01 13:34:36 +10:00
if ( cpp_label . column . string . size ) {
cpp_label_str8 = cpp_label . column . string ;
cpp_label_str8_padding = 1 + it . table - > headers [ cpp_label . index ] . longest_string - cpp_label . column . string . size ;
}
2025-02-14 00:27:42 +11:00
DN_Str8Builder builder = DN_Str8Builder_Init ( tmem . arena ) ;
2024-08-01 13:34:36 +10:00
// NOTE: row
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder , " {%2d, " , row_index ) ;
2024-08-01 13:34:36 +10:00
// NOTE: name
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
" DN_STR8( \" %.*s \" ),%*s " ,
DN_STR_FMT ( cpp_name . column . string ) ,
2024-08-01 13:34:36 +10:00
cpp_name_padding , " " ) ;
// NOTE: label
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
" DN_STR8( \" %.*s \" ),%*s " ,
DN_STR_FMT ( cpp_label_str8 ) ,
2024-08-01 13:34:36 +10:00
cpp_label_str8_padding , " " ) ;
// NOTE: value
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" /*value*/ 0, " ) ;
// NOTE: offsetof(a, b)
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" offsetof(%.*s%.*s, %.*s),%*s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( struct_or_enum_name ) ,
DN_STR_FMT ( cpp_name . column . string ) ,
2024-08-01 13:34:36 +10:00
cpp_name_padding , " " ) ;
// NOTE: sizeof(a->b)
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" sizeof(((%.*s%.*s*)0)->%.*s),%*s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( struct_or_enum_name ) ,
DN_STR_FMT ( cpp_name . column . string ) ,
2024-08-01 13:34:36 +10:00
cpp_name_padding , " " ) ;
// NOTE: alignof(a)
2025-02-14 00:27:42 +11:00
if ( cpp_type_name = = DN_STR8 ( " void " ) ) {
DN_Str8 proxy_type = DN_STR8 ( " char " ) ;
DN_USize proxy_type_padding = 1 + longest_cpp_type_name - proxy_type . size ;
DN_Str8Builder_AppendF ( & builder , " alignof(%.*s),%*s " , DN_STR_FMT ( proxy_type ) , proxy_type_padding , " " ) ;
2024-08-01 13:34:36 +10:00
} else {
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" alignof(%.*s),%*s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( cpp_type_name ) ,
2024-08-01 13:34:36 +10:00
cpp_type_padding , " " ) ;
2024-02-26 00:15:09 +11:00
}
2024-08-01 13:34:36 +10:00
// NOTE: Type string
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
" DN_STR8( \" %.*s \" ),%*s " ,
DN_STR_FMT ( cpp_type_name ) ,
2024-08-01 13:34:36 +10:00
cpp_type_padding , " " ) ;
// NOTE: Type as enum
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" %.*s,%*s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( cpp_type_enum ) ,
2024-08-01 13:34:36 +10:00
cpp_type_enum_padding , " " ) ;
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" /*is_pointer*/ %s,%s /*array_size*/ %.*s, /*array_size_field*/ %.*s}, " ,
cpp_is_ptr_b32 ? " true " : " false " ,
cpp_is_ptr_b32 ? " " : " " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( cpp_array_size_str8 ) ,
DN_STR_FMT ( cpp_array_size_field_str8 ) ) ;
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
DN_Str8 line = DN_Str8Builder_Build ( & builder , tmem . arena ) ;
DN_CppLine ( cpp , " %.*s " , DN_STR_FMT ( line ) ) ;
2024-02-26 00:15:09 +11:00
}
} else {
2025-02-14 00:27:42 +11:00
DN_ASSERT ( table - > type = = DN_CGenTableType_CodeGenEnum ) ;
for ( DN_USize row_index = 0 ; row_index < it . table - > row_count ; row_index + + ) {
DN_CGenTableRow const * row = it . table - > rows + row_index ;
DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppName ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_value = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppValue ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_label = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppLabel ] . string , row ) ;
2024-02-26 00:15:09 +11:00
if ( cpp_name . column . string . size < = 0 )
continue ;
2025-02-14 00:27:42 +11:00
DN_TLSTMem tmem = DN_TLS_PushTMem ( nullptr ) ;
DN_USize cpp_name_padding = 1 + it . table - > headers [ cpp_name . index ] . longest_string - cpp_name . column . string . size ;
DN_Str8 cpp_value_str8 = DN_Str8_HasData ( cpp_value . column . string ) ? cpp_value . column . string : DN_Str8_InitF_TLS ( " %zu " , row_index ) ;
DN_Str8 cpp_type_enum = DN_Str8_InitF_TLS ( " %.*sType_%.*s " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( struct_or_enum_name ) ) ;
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
DN_Str8 cpp_label_str8 = cpp_name . column . string ;
DN_USize cpp_label_str8_padding = cpp_name_padding ;
2024-08-01 13:34:36 +10:00
if ( cpp_label . column . string . size ) {
cpp_label_str8 = cpp_label . column . string ;
cpp_label_str8_padding = 1 + it . table - > headers [ cpp_label . index ] . longest_string - cpp_label . column . string . size ;
}
2025-02-14 00:27:42 +11:00
DN_Str8Builder builder = DN_Str8Builder_Init_TLS ( ) ;
2024-08-01 13:34:36 +10:00
// NOTE: row
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder , " {%2d, " , row_index ) ;
2024-08-01 13:34:36 +10:00
// NOTE: name
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
" DN_STR8( \" %.*s \" ),%*s " ,
DN_STR_FMT ( cpp_name . column . string ) ,
2024-08-01 13:34:36 +10:00
cpp_name_padding , " " ) ;
// NOTE: label
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
" DN_STR8( \" %.*s \" ),%*s " ,
DN_STR_FMT ( cpp_label_str8 ) ,
2024-08-01 13:34:36 +10:00
cpp_label_str8_padding , " " ) ;
2024-02-26 00:15:09 +11:00
2024-08-01 13:34:36 +10:00
// NOTE: value
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder , " /*value*/ %.*s, " , DN_STR_FMT ( cpp_value_str8 ) ) ;
2024-02-26 00:15:09 +11:00
2024-08-01 13:34:36 +10:00
// NOTE: offsetof(a, b)
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder , " /*offsetof*/ 0, " ) ;
2024-02-26 00:15:09 +11:00
2024-08-01 13:34:36 +10:00
// NOTE: sizeof(a->b)
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" sizeof(%.*s%.*s), " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( struct_or_enum_name ) ) ;
2024-02-26 00:15:09 +11:00
2024-08-01 13:34:36 +10:00
// NOTE: alignof(a->b)
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" alignof(%.*s%.*s), " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( emit_prefix ) ,
DN_STR_FMT ( struct_or_enum_name ) ) ;
2024-04-18 22:59:11 +10:00
2024-08-01 13:34:36 +10:00
// TODO: Type string
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder , " DN_STR8( \" \" ), " ) ;
2024-08-01 13:34:36 +10:00
// NOTE: Type as enum
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder , " %.*s, " , DN_STR_FMT ( cpp_type_enum ) ) ;
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder , " /*is_pointer*/ false, " ) ;
DN_Str8Builder_AppendF ( & builder , " /*array_size*/ 0, " ) ;
DN_Str8Builder_AppendF ( & builder , " /*array_size_field*/ NULL}, " ) ;
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
DN_Str8 line = DN_Str8Builder_Build_TLS ( & builder ) ;
DN_CppLine ( cpp , " %.*s " , DN_STR_FMT ( line ) ) ;
2024-02-26 00:15:09 +11:00
}
}
}
}
}
int longest_name_across_all_tables = 0 ;
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
DN_TLSTMem tmem = DN_TLS_TMem ( nullptr ) ;
DN_Str8 type_name = it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ;
if ( DN_CGen_WillCodeGenTypeName ( cgen , type_name ) )
type_name = DN_Str8_InitF ( tmem . arena , " %.*s%.*s " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) ;
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
longest_name_across_all_tables = DN_MAX ( longest_name_across_all_tables , DN_CAST ( int ) type_name . size ) ;
2024-02-26 00:15:09 +11:00
}
}
2025-02-14 00:27:42 +11:00
DN_CppBlock ( cpp , " ; \n \n " , " DN_TypeInfo const g_%.*stypes[] = " , DN_STR_FMT ( emit_prefix ) ) {
DN_CppLine ( cpp , " {DN_STR8( \" \" ),%*sDN_TypeKind_Nil, 0, /*fields*/ NULL, /*count*/ 0}, " , 1 + longest_name_across_all_tables , " " ) ;
DN_USize longest_type_name = 0 ;
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
DN_TLSTMem tmem = DN_TLS_TMem ( nullptr ) ;
DN_Str8 type_name = it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ;
if ( DN_CGen_WillCodeGenTypeName ( cgen , type_name ) )
type_name = DN_Str8_InitF ( tmem . arena , " %.*s%.*s " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) ;
longest_type_name = DN_MAX ( longest_type_name , type_name . size ) ;
2024-08-01 13:34:36 +10:00
}
}
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
DN_TLSTMem tmem = DN_TLS_PushTMem ( nullptr ) ;
DN_Str8 type_name = it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ;
if ( DN_CGen_WillCodeGenTypeName ( cgen , type_name ) )
type_name = DN_Str8_InitF_TLS ( " %.*s%.*s " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) ;
2024-02-26 00:15:09 +11:00
2025-02-14 00:27:42 +11:00
int name_padding = 1 + longest_name_across_all_tables - DN_CAST ( int ) type_name . size ;
DN_Str8 type_info_kind = { } ;
2024-02-26 00:15:09 +11:00
char const * type_info_kind_padding = " " ;
2025-02-14 00:27:42 +11:00
if ( table - > type = = DN_CGenTableType_CodeGenEnum ) {
type_info_kind = DN_STR8 ( " DN_TypeKind_Enum " ) ;
2024-02-26 00:15:09 +11:00
type_info_kind_padding = " " ;
2025-02-14 00:27:42 +11:00
} else if ( table - > type = = DN_CGenTableType_CodeGenStruct ) {
type_info_kind = DN_STR8 ( " DN_TypeKind_Struct " ) ;
2024-02-26 00:15:09 +11:00
} else {
2025-02-14 00:27:42 +11:00
DN_ASSERT ( table - > type = = DN_CGenTableType_CodeGenBuiltinTypes ) ;
type_info_kind = DN_STR8 ( " DN_TypeKind_Basic " ) ;
2024-02-26 00:15:09 +11:00
type_info_kind_padding = " " ;
}
2025-02-14 00:27:42 +11:00
DN_Str8 fields_count = { } ;
if ( table - > type = = DN_CGenTableType_CodeGenBuiltinTypes ) {
fields_count = DN_STR8 ( " 0 " ) ;
2024-02-26 00:15:09 +11:00
} else {
2025-02-14 00:27:42 +11:00
DN_ASSERT ( table - > type = = DN_CGenTableType_CodeGenStruct | | table - > type = = DN_CGenTableType_CodeGenEnum ) ;
2024-02-26 00:15:09 +11:00
int fields_count_int = 0 ;
2025-02-14 00:27:42 +11:00
for ( DN_USize row_index = 0 ; row_index < it . table - > row_count ; row_index + + ) {
DN_CGenTableRow const * row = it . table - > rows + row_index ;
DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppName ] . string , row ) ;
fields_count_int + = DN_Str8_HasData ( cpp_name . column . string ) ;
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
fields_count = DN_Str8_InitF_TLS ( " %d " , fields_count_int ) ;
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
DN_Str8 fields = DN_STR8 ( " NULL " ) ;
2024-02-26 00:15:09 +11:00
int fields_padding = 1 ;
2025-02-14 00:27:42 +11:00
if ( table - > type ! = DN_CGenTableType_CodeGenBuiltinTypes ) {
2024-02-26 00:15:09 +11:00
fields_padding = name_padding ;
2025-02-14 00:27:42 +11:00
fields = DN_Str8_InitF ( tmem . arena , " g_%.*s_type_fields " , DN_STR_FMT ( type_name ) ) ;
2024-08-01 13:34:36 +10:00
}
2025-02-14 00:27:42 +11:00
DN_Str8Builder builder = DN_Str8Builder_Init_TLS ( ) ;
2024-08-01 13:34:36 +10:00
// NOTE: name
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
" {DN_STR8( \" %.*s \" ),%*s " ,
DN_STR_FMT ( type_name ) ,
2024-08-01 13:34:36 +10:00
name_padding ,
" " ) ;
2025-02-14 00:27:42 +11:00
// NOTE: DN_TypeKind_{Nil|Basic|Enum|Struct}
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" %.*s,%s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( type_info_kind ) ,
2024-08-01 13:34:36 +10:00
type_info_kind_padding ) ;
// NOTE: sizeof(T)
2025-02-14 00:27:42 +11:00
if ( type_name = = DN_STR8 ( " void " ) ) {
DN_Str8Builder_AppendF ( & builder , " 0,%*s " , name_padding , " " ) ;
2024-08-01 13:34:36 +10:00
} else {
2025-02-14 00:27:42 +11:00
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" sizeof(%.*s),%*s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( type_name ) ,
2024-08-01 13:34:36 +10:00
name_padding ,
" " ) ;
2024-02-26 00:15:09 +11:00
}
2025-02-14 00:27:42 +11:00
// NOTE: Pointer to DN_TypeField[]
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" /*fields*/ %.*s,%*s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( fields ) ,
2024-08-01 13:34:36 +10:00
fields_padding ,
" " ) ;
2025-02-14 00:27:42 +11:00
// NOTE: DN_TypeField length
DN_Str8Builder_AppendF ( & builder ,
2024-08-01 13:34:36 +10:00
" /*count*/ %.*s}, " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( fields_count ) ) ;
2024-08-01 13:34:36 +10:00
2025-02-14 00:27:42 +11:00
DN_Str8 line = DN_Str8Builder_Build_TLS ( & builder ) ;
DN_CppLine ( cpp , " %.*s " , DN_STR_FMT ( line ) ) ;
2024-02-26 00:15:09 +11:00
}
}
}
2024-03-19 23:11:00 +11:00
2024-04-18 22:59:11 +10:00
// NOTE: Str8 to enum conversion ////////////////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
if ( table - > type ! = DN_CGenTableType_CodeGenEnum )
2024-03-19 23:11:00 +11:00
continue ;
2025-02-14 00:27:42 +11:00
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
DN_Str8 type_name = it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ;
DN_CppFuncBlock ( cpp , " %.*s%.*sStr8ToEnumResult %.*s%.*s_NameStr8ToEnum(DN_Str8 string) " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) {
DN_CppLine ( cpp , " %.*s%.*sStr8ToEnumResult result = {}; " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) ;
DN_CppForBlock ( cpp , " DN_USize index = 0; !result.success && index < DN_ARRAY_UCOUNT(g_%.*s%.*s_type_fields); index++ " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) {
DN_CppIfChain ( cpp ) {
DN_CppLine ( cpp , " DN_TypeField field = g_%.*s%.*s_type_fields[index]; " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) ;
DN_CppIfOrElseIfBlock ( cpp , " DN_Str8_EqInsensitive(string, field.name) " ) {
DN_CppLine ( cpp , " result.success = true; " ) ;
DN_CppLine ( cpp , " result.value = (%.*s%.*s)index; " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) ;
2024-03-19 23:11:00 +11:00
}
}
}
2025-02-14 00:27:42 +11:00
DN_CppLine ( cpp , " return result; " ) ;
2024-03-19 23:11:00 +11:00
}
2025-02-14 00:27:42 +11:00
DN_CppNewLine ( cpp ) ;
DN_CppFuncBlock ( cpp , " %.*s%.*sStr8ToEnumResult %.*s%.*s_LabelStr8ToEnum(DN_Str8 string) " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) {
DN_CppLine ( cpp , " %.*s%.*sStr8ToEnumResult result = {}; " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) ;
DN_CppForBlock ( cpp , " DN_USize index = 0; !result.success && index < DN_ARRAY_UCOUNT(g_%.*s%.*s_type_fields); index++ " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) {
DN_CppIfChain ( cpp ) {
DN_CppLine ( cpp , " DN_TypeField field = g_%.*s%.*s_type_fields[index]; " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) ;
DN_CppIfOrElseIfBlock ( cpp , " DN_Str8_EqInsensitive(string, field.label) " ) {
DN_CppLine ( cpp , " result.success = true; " ) ;
DN_CppLine ( cpp , " result.value = (%.*s%.*s)index; " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) ;
}
}
}
DN_CppLine ( cpp , " return result; " ) ;
}
DN_CppNewLine ( cpp ) ;
2024-03-19 23:11:00 +11:00
}
}
2024-04-18 22:59:11 +10:00
// NOTE: Operator == and != ////////////////////////////////////////////////////////////////
2025-02-14 00:27:42 +11:00
for ( DN_CGenTable * table = cgen - > first_table ; table ! = 0 ; table = table - > next ) {
if ( table - > type ! = DN_CGenTableType_CodeGenStruct )
2024-04-18 22:59:11 +10:00
continue ;
2025-02-14 00:27:42 +11:00
for ( DN_CGenLookupTableIterator it = { } ; DN_CGen_LookupNextTableInCodeGenTable ( cgen , table , & it ) ; ) {
DN_Str8 cpp_op_equals = it . cgen_table_column [ DN_CGenTableHeaderType_CppOpEquals ] . string ;
if ( cpp_op_equals ! = DN_STR8 ( " true " ) )
2024-04-18 22:59:11 +10:00
continue ;
2025-02-14 00:27:42 +11:00
DN_Str8 type_name = it . cgen_table_column [ DN_CGenTableHeaderType_Name ] . string ;
DN_CppFuncBlock ( cpp , " bool operator==(%.*s%.*s const &lhs, %.*s%.*s const &rhs) " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) {
for ( DN_USize row_index = 0 ; row_index < it . table - > row_count ; row_index + + ) {
DN_CGenTableRow const * row = it . table - > rows + row_index ;
DN_CGenLookupColumnAtHeader cpp_name = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppName ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_is_ptr = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppIsPtr ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_array_size = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppArraySize ] . string , row ) ;
DN_CGenLookupColumnAtHeader cpp_array_size_field = DN_CGen_LookupColumnAtHeader ( it . table , it . cgen_table_column [ DN_CGenTableHeaderType_CppArraySizeField ] . string , row ) ;
2024-04-18 22:59:11 +10:00
// TODO(doyle): Check if we're an integral type or not to double check if we
// can use memcmp or operator==
2025-02-14 00:27:42 +11:00
if ( DN_Str8_HasData ( cpp_array_size_field . column . string ) ) {
DN_CppIfChain ( cpp ) {
DN_CppIfOrElseIfBlock ( cpp ,
2024-04-18 22:59:11 +10:00
" lhs.%.*s != rhs.%.*s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( cpp_array_size_field . column . string ) ,
DN_STR_FMT ( cpp_array_size_field . column . string ) ) {
DN_CppLine ( cpp , " return false; " ) ;
2024-04-18 22:59:11 +10:00
}
}
2025-02-14 00:27:42 +11:00
DN_CppIfChain ( cpp ) {
DN_CppIfOrElseIfBlock ( cpp ,
" DN_MEMCMP(lhs.%.*s, rhs.%.*s, lhs.%.*s) != 0 " ,
DN_STR_FMT ( cpp_name . column . string ) ,
DN_STR_FMT ( cpp_name . column . string ) ,
DN_STR_FMT ( cpp_array_size_field . column . string ) ) {
DN_CppLine ( cpp , " return false; " ) ;
2024-04-18 22:59:11 +10:00
}
}
2025-02-14 00:27:42 +11:00
} else if ( DN_Str8_HasData ( cpp_array_size . column . string ) ) {
DN_CppIfChain ( cpp ) {
DN_CppIfOrElseIfBlock ( cpp ,
" DN_MEMCMP(lhs.%.*s, rhs.%.*s, %.*s) != 0 " ,
DN_STR_FMT ( cpp_name . column . string ) ,
DN_STR_FMT ( cpp_name . column . string ) ,
DN_STR_FMT ( cpp_array_size . column . string ) ) {
DN_CppLine ( cpp , " return false; " ) ;
2024-04-18 22:59:11 +10:00
}
}
2025-02-14 00:27:42 +11:00
} else if ( cpp_is_ptr . column . string = = DN_STR8 ( " true " ) ) {
DN_CppIfChain ( cpp ) {
DN_CppIfOrElseIfBlock ( cpp ,
2024-04-18 22:59:11 +10:00
" *lhs.%.*s != *rhs.%.*s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( cpp_name . column . string ) ,
DN_STR_FMT ( cpp_name . column . string ) ) {
DN_CppLine ( cpp , " return false; " ) ;
2024-04-18 22:59:11 +10:00
}
}
} else {
2025-02-14 00:27:42 +11:00
DN_CppIfChain ( cpp ) {
DN_CppIfOrElseIfBlock ( cpp ,
2024-04-18 22:59:11 +10:00
" lhs.%.*s != rhs.%.*s " ,
2025-02-14 00:27:42 +11:00
DN_STR_FMT ( cpp_name . column . string ) ,
DN_STR_FMT ( cpp_name . column . string ) ) {
DN_CppLine ( cpp , " return false; " ) ;
2024-04-18 22:59:11 +10:00
}
}
}
}
2025-02-14 00:27:42 +11:00
DN_CppLine ( cpp , " return true; " ) ;
2024-04-18 22:59:11 +10:00
}
2025-02-14 00:27:42 +11:00
DN_CppNewLine ( cpp ) ;
2024-04-18 22:59:11 +10:00
2025-02-14 00:27:42 +11:00
DN_CppFuncBlock ( cpp , " bool operator!=(%.*s%.*s const &lhs, %.*s%.*s const &rhs) " , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) , DN_STR_FMT ( emit_prefix ) , DN_STR_FMT ( type_name ) ) {
DN_CppLine ( cpp , " bool result = !(lhs == rhs); " ) ;
DN_CppLine ( cpp , " return result; " ) ;
2024-04-18 22:59:11 +10:00
}
2025-02-14 00:27:42 +11:00
DN_CppNewLine ( cpp ) ;
2024-04-18 22:59:11 +10:00
}
}
2024-02-26 00:15:09 +11:00
}
}