Updated AST::to_string to latest api changes with modules and attributes.

This commit is contained in:
Edward R. Gonzalez 2023-05-06 00:18:44 -04:00
parent 0edc3c57b6
commit e8264c560f
3 changed files with 419 additions and 163 deletions

View File

@ -89,7 +89,6 @@ using zpl::string_length;
using zpl::string_make;
using zpl::str_len;
#if __clang__
# pragma clang diagnostic pop
#endif
@ -147,7 +146,7 @@ using zpl::str_len;
#define macro_expand( Expanded_ ) Expanded_
#define bit( Value_ ) ( 1 << Value_ )
#define bitfield_is_equal( Field_, Mask_ ) ( ( (Mask_) & (Field_) ) == (Mask_) )
#define bitfield_is_equal( Type_, Field_, Mask_ ) ( (Type_(Mask_) & Type_(Field_)) == Type_(Mask_) )
#define forceinline ZPL_ALWAYS_INLINE
#define print_nl( _) zpl_printf("\n")
#define ccast( Type_, Value_ ) * const_cast< Type_* >( & (Value_) )
@ -184,6 +183,94 @@ while(0);
constexpr
char const* Msg_Invalid_Value = "INVALID VALUE PROVIDED";
#pragma region Memory
#pragma endregion Memory
#pragma region String
#if 0
struct String
{
struct Header
{
AllocatorInfo Allocator;
sw Length;
sw Capacity;
};
static String make ( AllocatorInfo allocator, char const* str )
{
sw length = str ? str_len( str ) : 0;
return make_length( allocator, str, length );
}
static String make_reserve( AllocatorInfo allocator, sw capacity )
{
constexpr sw header_size = sizeof( Header );
s32 alloc_size = header_size + capacity + 1;
void* allocation = alloc( allocator, alloc_size );
if ( allocation == nullptr )
return { nullptr };
mem_set( allocation, 0, alloc_size );
Header*
header = rcast(Header*, allocation);
header->Allocator = allocator;
header->Capacity = capacity;
header->Length = 0;
String result = { (char*)allocation + header_size };
return result;
}
static String make_length( AllocatorInfo allocator, char const* str, sw length );
static String fmt ( AllocatorInfo allocator, char* buf, sw buf_size, char const* fmt, ... );
static String fmt_buf( AllocatorInfo allocator, char const* fmt, ... );
static String join( AllocatorInfo allocator, char const** parts, sw num_parts, char const* glue );
static bool are_equal( String lhs, String rhs );
void append( char c );
void append( char const* str );
void append( char const* str, sw length );
void append( const String other );
void append( char const* fmt, ... );
void append( const String other );
sw avail_space();
sw capacity();
void clear();
String duplicate( AllocatorInfo allocator );
void free();
Header& header();
sw length();
void trim( char const* cut_set );
void trim_space();
char* Data = nullptr;
};
struct String_POD
{
char* Data;
};
static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" );
#endif
#pragma endregion String
namespace Memory
{
constexpr uw Initial_Reserve = megabytes(10);

View File

@ -488,8 +488,31 @@ namespace gen
String AST::to_string()
{
# define ProcessModuleFlags() \
if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Export )) \
result = string_append_fmt( result, "export " ); \
\
if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Import )) \
result = string_append_fmt( result, "import " ); \
\
if ( bitfield_is_equal( u32, ModuleFlags, ModuleFlag::Private )) \
result = string_append_fmt( result, "private " );
String result = string_make( g_allocator, "" );
// Scope indentation.
char indent_str[128] = {0}; // Should be more than enough...
s32 tab_count = 0;
{
AST* curr_parent = Parent;
while ( Parent )
{
indent_str[tab_count] = '\t';
tab_count++;
}
}
switch ( Type )
{
using namespace ECode;
@ -504,6 +527,8 @@ namespace gen
case Comment:
{
result = string_append_length( result, indent_str, tab_count );
static char line[MaxCommentLineLength];
s32 left = string_length( ccast(String, Content) );
@ -526,141 +551,219 @@ namespace gen
case Access_Private:
case Access_Protected:
case Access_Public:
result = string_append_length( result, indent_str, tab_count );
result = string_append_length( result, Name, string_length( ccast(String, Name)) );
break;
case Attributes:
result = string_append_fmt( result, "%s", Content );
result = string_append_length( result, Content, string_length( ccast(String, Content)) );
case Class:
{
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
result = string_append_fmt( result, "class ");
s32 idx = 1;
if ( Entries[idx]->Type == Specifiers )
if ( Entries[idx]->Type == Attributes )
{
result = string_append_fmt( result, "%s ", Entries[idx]->to_string() );
idx++;
}
result = string_append_fmt( result, " %s", Name );
result = string_append_length( result, Name, string_length( ccast(String, Name)) );
if ( parent() )
result = string_append_fmt( result, " : %s", parent()->to_string() );
AST* parent = Entries[idx];
result = string_append_fmt( result, "\n{\n%s\n};\n", body()->to_string() );
if ( parent )
{
char const* access_level = to_str( ParentAccess );
result = string_append_fmt( result, ": %s %s\n%s{\n"
, access_level
, parent
, indent_str
);
}
result = string_append_fmt( result, "%s\n%s};\n", body()->to_string(), indent_str );
}
break;
case Class_Fwd:
{
result = string_append_fmt( result, "class");
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
result = string_append_fmt( result, "class %s;", Name );
}
break;
case Enum:
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
string_append_length( result, "enum ", 5);
s32 idx = 1;
if ( Entries[idx]->Type == Specifiers )
if ( Entries[idx]->Type == Attributes )
{
result = string_append_fmt( result, "%s ", Entries[idx]->to_string() );
idx++;
}
result = string_append_fmt( result, " %s;", Name );
}
break;
case Enum:
if ( underlying_type() )
if ( Entries[idx]->Type == Typename)
{
result = string_append_fmt( result, "enum %s : %s\n{\n%s\n};\n"
result = string_append_fmt( result, "%s : %s\n%s{\n"
, Name
, underlying_type()->to_string()
, body()->to_string()
, Entries[idx]->to_string()
, indent_str
);
}
else
{
result = string_append_fmt( result, "enum %s\n{\n%s\n};\n"
result = string_append_fmt( result, "%s\n%s{\n"
, Name
, body()->to_string()
, indent_str
);
}
result = string_append_fmt( result, "%s\n%s};"
, body()->to_string()
, indent_str
);
break;
case Enum_Fwd:
result = string_append_fmt( result, "enum %s : %s;\n", Name, underlying_type()->to_string() );
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
result = string_append_fmt( result, "enum %s : %s;\n", Name, Entries[1]->to_string() );
break;
case Enum_Class:
if ( underlying_type() )
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
result = string_append_fmt( result, "enum class " );
s32 idx = 0;
if ( Entries[idx]->Type == Attributes )
{
result = string_append_fmt( result, "enum class %s : %s\n{\n%s\n};\n"
result = string_append_fmt( result, "%s ", Entries[idx]->to_string() );
idx++;
}
if ( Entries[idx]->Type == Typename )
{
result = string_append_fmt( result, ": %s\n%s{\n"
, Name
, underlying_type()->to_string()
, body()->to_string()
, Entries[idx]->to_string()
, indent_str
);
}
else
{
result = string_append_fmt( result, "enum class %s\n{\n%s\n};\n"
result = string_append_fmt( result, "%s\n%s{\n"
, Name
, body()->to_string()
, indent_str
);
}
result = string_append_fmt( result, "%s\n%s};"
, body()->to_string()
, indent_str
);
break;
case Enum_Class_Fwd:
result = string_append_fmt( result, "enum class %s : %s;\n", Name, underlying_type()->to_string() );
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
result = string_append_fmt( result, "enum class " );
s32 idx = 0;
if ( Entries[idx]->Type == Attributes )
{
result = string_append_fmt( result, "%s ", Entries[idx]->to_string() );
idx++;
}
result = string_append_fmt( result, ": %s;\n", Name, Entries[idx]->to_string() );
break;
case Execution:
result = string_append_fmt( result, "%s\n", Entries[0]->to_string() );
result = string_append_length( result, Content, string_length( ccast(String, Content)) );
break;
case Export_Body:
{
result = string_append_fmt( result, "export\n{\n" );
result = string_append_fmt( result, "%sexport\n%s{\n", indent_str, indent_str );
s32 index = 0;
s32 left = num_entries();
while ( left -- )
{
result = string_append_fmt( result, "%s\n", Entries[index]->to_string() );
result = string_append_fmt( result, "%s\t%s\n", indent_str, Entries[index]->to_string() );
index++;
}
result = string_append_fmt( result, "};\n" );
result = string_append_fmt( result, "%s};\n", indent_str );
}
break;
case Extern_Linkage:
result = string_append_fmt( result, "extern %s\n{\n%s\n};\n", Name, body()->to_string() );
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
result = string_append_fmt( result, "extern %s\n%s{\n%s\n%s};\n"
, Name
, indent_str
, body()->to_string()
, indent_str
);
break;
case Friend:
result = string_append_fmt( result, "friend %s;\n", Entries[0]->to_string() );
result = string_append_fmt( result, "%sfriend %s;\n", indent_str, Entries[0]->to_string() );
break;
case Function:
{
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
u32 idx = 1;
u32 left = num_entries();
if ( left <= 0 )
log_failure( "Code::to_string - Name: %s Type: %s, expected definition", Name, Type );
if ( Entries[idx]->Type == Specifiers )
if ( Entries[idx]->Type == Attributes )
{
result = string_append_fmt( result, "%s ", Entries[idx]->to_string() );
idx++;
left--;
}
if ( left <= 0 )
log_failure( "Code::to_string - Name: %s Type: %s, expected return type", Name, Type );
if ( Entries[idx]->Type == Specifiers )
{
result = string_append_fmt( result, "%s\n", Entries[idx]->to_string() );
idx++;
left--;
}
result = string_append_fmt( result, "\n%s %s(", Entries[idx]->to_string(), Name );
result = string_append_fmt( result, "%s %s(", Entries[idx]->to_string(), Name );
idx++;
left--;
@ -675,18 +778,21 @@ namespace gen
result = string_append_fmt( result, "void" );
}
result = string_append_fmt( result, ")\n{\n%s\n}", body()->to_string() );
result = string_append_fmt( result, ")\n%s{\n%s\n%s}"
, indent_str
, body()->to_string()
, indent_str
);
}
break;
case Function_Fwd:
{
result = string_append_length( result, indent_str, tab_count );
u32 idx = 0;
u32 left = array_count( Entries );
if ( left <= 0 )
log_failure( "Code::to_string - Name: %s Type: %s, expected definition", Name, Type );
if ( Entries[idx]->Type == Specifiers )
{
result = string_append_fmt( result, "%s\n", Entries[idx]->to_string() );
@ -694,9 +800,6 @@ namespace gen
left--;
}
if ( left <= 0 )
log_failure( "Code::to_string - Name: %s Type: %s, expected return type", Name, Type );
result = string_append_fmt( result, "\n%s %s(", Entries[idx]->to_string(), Name );
idx++;
left--;
@ -717,24 +820,44 @@ namespace gen
break;
case Module:
// TODO: Add export condition
// if ( )
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
result = string_append_fmt( result, "module %s", Content );
break;
case Namespace:
result = string_append_fmt( result, "namespace %s\n{\n%s\n};\n", Name, body()->to_string() );
result = string_append_length( result, indent_str, tab_count);
ProcessModuleFlags();
result = string_append_fmt( result, "namespace %s\n%s{\n%s\n%s};\n"
, Name
, indent_str
, body()->to_string()
, indent_str
);
break;
case Operator:
case Operator_Member:
{
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
s32 idx = 1;
if ( Entries[idx]->Type == Attributes )
{
result = string_append_fmt( result, "%s ", Entries[idx]->to_string() );
idx++;
}
if ( Entries[idx]->Type == Specifiers )
{
result = string_append_fmt( result, "%s", Entries[idx]->to_string() );
result = string_append_fmt( result, "%s\n", Entries[idx]->to_string() );
idx++;
}
@ -751,13 +874,21 @@ namespace gen
result = string_append_fmt( result, "void" );
}
result = string_append_fmt( result, ")\n{\n%s\n}", body()->to_string() );
result = string_append_fmt( result, ")\n%s{\n%s\n%s}"
, indent_str
, body()->to_string()
, indent_str
);
}
break;
case Operator_Fwd:
case Operator_Member_Fwd:
{
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
s32 idx;
if ( Entries[idx]->Type == Specifiers )
@ -811,11 +942,15 @@ namespace gen
case Struct:
{
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
result = string_append_fmt( result, "struct ");
s32 idx = 1;
if ( Entries[idx]->Type == Specifiers )
if ( Entries[idx]->Type == Attributes )
{
result = string_append_fmt( result, "%s ", Entries[idx]->to_string() );
idx++;
@ -823,8 +958,12 @@ namespace gen
result = string_append_fmt( result, "%s ", Name );
if ( parent() )
result = string_append_fmt( result, " : %s", parent()->to_string() );
if ( Entries[idx] )
{
char const* access_str = to_str( ParentAccess );
result = string_append_fmt( result, ": %s %s", access_str, Entries[idx]->to_string() );
}
result = string_append_fmt( result, "\n{\n%s\n};\n", body()->to_string() );
}
@ -832,6 +971,10 @@ namespace gen
case Struct_Fwd:
{
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
result = string_append_fmt( result, "struct ");
s32 idx = 1;
@ -848,6 +991,10 @@ namespace gen
case Variable:
{
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
s32 idx = 1;
if ( Entries[idx]->Type == Specifiers )
@ -864,27 +1011,87 @@ namespace gen
break;
case Typedef:
// TODO: Check for array expression
result = string_append_length( result, indent_str, tab_count );
result = string_append_fmt( result, "typedef %s %s", Entries[0]->to_string(), Name );
ProcessModuleFlags();
AST* type = Entries[0];
if ( Entries[1] && Entries[1]->Type == Attributes )
{
result = string_append_fmt( result, "%s ", Entries[1]->to_string() );
}
result = string_append_fmt( result, "typedef %s %s", type->to_string(), Name );
if ( type->Entries[1] )
{
result = string_append_fmt( result, "[%s];", type->Entries[1]->to_string() );
}
else
{
result = string_append_length( result, ";", 1);
}
break;
case Typename:
if ( Entries[0] )
{
result = string_append_fmt( result, "%s %s", Name, Entries[0]->to_string() );
}
else
{
result = string_append_fmt( result, "%s", Name );
}
break;
case Union:
result = string_append_fmt( result, "union %s\n{\n%s\n};\n", Name, body()->to_string() );
result = string_append_length( result, indent_str, tab_count );
ProcessModuleFlags();
s32 idx = 0;
result = string_append_length( result, "union ", 6 );
if ( Entries[idx]->Type == Attributes )
{
result = string_append_fmt( result, "%s ", Entries[idx]->to_string() );
idx++;
}
result = string_append_fmt( result, "%s\n%s{\n%s\n%s};\n"
, Name
, indent_str
, body()->to_string()
, indent_str
);
break;
case Using:
// TODO: Check for array expression
result = string_append_length( result, indent_str, tab_count );
if ( Entries[0] )
result = string_append_fmt( result, "using %s = %s", Name, Entries[0] );
ProcessModuleFlags();
AST* type = Entries[0];
if ( Entries[1] && Entries[1]->Type == Attributes )
{
result = string_append_fmt( result, "%s ", Entries[1]->to_string() );
}
if ( type )
{
result = string_append_fmt( result, "using %s = %s", Name, type->to_string() );
if ( type->Entries[1] )
result = string_append_fmt( result, "[%s]", type->Entries[1]->to_string() );
}
else
result = string_append_fmt( result, "using %s", Name );
result = string_append_fmt( result, ";" );
break;
case Using_Namespace:
@ -904,7 +1111,7 @@ namespace gen
s32 left = num_entries();
while ( left -- )
{
result = string_append_fmt( result, "%s\n", Entries[index]->to_string() );
result = string_append_fmt( result, "%s%s\n", indent_str, Entries[index]->to_string() );
index++;
}
}
@ -912,6 +1119,8 @@ namespace gen
}
return result;
#undef ProcessModuleFlags
}
#pragma endregion AST
@ -1128,12 +1337,13 @@ namespace gen
result->Content = nullptr;
result->Parent = nullptr;
result->Name = nullptr;
result->Comment = nullptr;
result->Type = ECode::Invalid;
result->Op = EOperator::Invalid;
result->ModuleFlags = ModuleFlag::Invalid;
result->ParentAccess = AccessSpec::Invalid;
result->StaticIndex = 0;
result->Readonly = false;
result->DynamicEntries = false;
result->StaticIndex = 0;
return result;
}
@ -1621,7 +1831,7 @@ namespace gen
Code def_class( s32 length, char const* name
, Code body
, Code parent, AccessSpec parent_access
, Code specifiers, Code attributes
, Code attributes
, ModuleFlag mflags )
{
using namespace ECode;
@ -1634,15 +1844,9 @@ namespace gen
return Code::Invalid;
}
if ( specifiers && specifiers->Type != Specifiers )
if ( parent && parent->Type != Class || parent->Type != Struct || parent->Type != Typename || parent->Type != Untyped )
{
log_failure( "gen::def_class: specifiers was not a 'Specifiers' type: %s", specifiers->debug_str() );
return Code::Invalid;
}
if ( parent && parent->Type != Class || parent->Type != Struct )
{
log_failure( "gen::def_class: parent provided is not type 'Class' or 'Struct': %s", parent->debug_str() );
log_failure( "gen::def_class: parent provided is not type 'Class', 'Struct', 'Typeanme', or 'Untyped': %s", parent->debug_str() );
return Code::Invalid;
}
@ -1675,11 +1879,11 @@ namespace gen
if ( attributes )
result->add_entry( attributes );
if ( specifiers )
result->add_entry( specifiers );
if ( parent )
{
result->ParentAccess = parent_access;
result->add_entry( parent );
}
result.lock();
return result;
@ -1742,7 +1946,7 @@ namespace gen
{
result->add_entry( type );
}
else if ( result->Type == Enum_Class_Fwd || result->Type == Enum_Fwd )
else if ( result->Type != Enum_Class_Fwd && result->Type != Enum_Fwd )
{
log_failure( "gen::def_enum: enum forward declaration must have an underlying type" );
return Code::Invalid;
@ -2068,8 +2272,8 @@ namespace gen
Code def_struct( u32 length, char const* name
, Code body
, Code parent, Code parent_access
, Code specifiers, Code attributes
, Code parent, AccessSpec parent_access
, Code attributes
, ModuleFlag mflags )
{
using namespace ECode;
@ -2082,12 +2286,6 @@ namespace gen
return Code::Invalid;
}
if ( specifiers && specifiers->Type != Specifiers )
{
log_failure( "gen::def_struct: specifiers was not a `Specifiers` type" );
return Code::Invalid;
}
if ( parent && parent->Type != Struct )
{
log_failure( "gen::def_struct: parent was not a `Struct` type" );
@ -2118,11 +2316,11 @@ namespace gen
if ( attributes )
result->add_entry( attributes );
if ( specifiers )
result->add_entry( specifiers );
if ( parent )
{
result->ParentAccess = parent_access;
result->add_entry( parent );
}
result.lock();
return result;
@ -2239,6 +2437,7 @@ namespace gen
Code
result = make_code();
result->Name = get_cached_string( name, length );
result->ModuleFlags = mflags;
switch ( specifier )
{
@ -2254,6 +2453,9 @@ namespace gen
break;
}
if ( attributes )
result->add_entry( attributes );
result.lock();
return result;
}
@ -3218,14 +3420,6 @@ namespace gen
#ifdef GEN_FEATURE_PARSING
/*
These constructors are the most implementation intensive other than the edtior or scanner.
The current implementation is very convervative and does not use a lexer to process the input first.
Instead, it just sifts through the content directly looking for the syntax pattern for the code type
and then constructs the AST after.
Eventually I will problably end up using a dedicated lexer for parser constructors to lower the sloc.
It uses the upfront constructors to help keep code from getitng to large since the target is to keep the sloc low
*/
namespace Parser
@ -4151,9 +4345,7 @@ namespace gen
{
case ESpecifier::Constexpr:
case ESpecifier::Constinit:
case ESpecifier::Export:
case ESpecifier::External_Linkage:
case ESpecifier::Import:
case ESpecifier::Local_Persist:
case ESpecifier::Mutable:
case ESpecifier::Static_Member:
@ -4340,10 +4532,6 @@ namespace gen
member = parse_variable( toks, context );
break;
case TokType::Spec_API:
log_failure( "gen::%s: %s not allowed in function body", context, str_tok_type( currtok.Type ) );
return Code::Invalid;
default:
Token untyped_tok = currtok;
@ -4395,9 +4583,6 @@ namespace gen
switch ( spec )
{
case ESpecifier::API_Macro:
case ESpecifier::API_Export:
case ESpecifier::API_Import:
case ESpecifier::External_Linkage:
case ESpecifier::Local_Persist:
case ESpecifier::Mutable:
@ -4685,9 +4870,6 @@ namespace gen
switch ( spec )
{
case ESpecifier::API_Macro:
case ESpecifier::API_Export:
case ESpecifier::API_Import:
case ESpecifier::Constexpr:
case ESpecifier::External_Linkage:
case ESpecifier::Local_Persist:

View File

@ -291,6 +291,7 @@ namespace gen
enum class AccessSpec : u32
{
Default,
Public,
Protected,
Private,
@ -304,6 +305,7 @@ namespace gen
{
local_persist
char const* lookup[ (u32)AccessSpec::Num_AccessSpec ] = {
"",
"private",
"protected",
"public",
@ -420,22 +422,6 @@ namespace gen
return DynamicEntries ? array_count(Entries) : StaticIndex;
}
// Class/Struct
inline
AST* parent()
{
return Entries[1];
}
// Enum
inline
AST* underlying_type()
{
return Entries[1];
}
// Parameter
bool add_param( AST* type, s32 length, char const* name );
@ -533,7 +519,6 @@ namespace gen
, Readonly ? "true" : "false"
, Parent ? Parent->Name : ""
, Name ? Name : ""
, Comment ? Comment : ""
);
}
@ -554,9 +539,10 @@ namespace gen
- sizeof(CodeT) // Type
- sizeof(OperatorT) // Op
- sizeof(ModuleFlag) // ModuleFlags
- sizeof(AccessSpec) // ParentAccess
- sizeof(u32) // StaticIndex
- sizeof(bool) * 2 // Readonly, DynamicEntries
- sizeof(u8) * 6 ) // _Align_Pad
- sizeof(u8) * 2 ) // _Align_Pad
/ sizeof(AST*);
constexpr static
@ -574,10 +560,11 @@ namespace gen
CodeT Type; \
OperatorT Op; \
ModuleFlag ModuleFlags; \
AccessSpec ParentAccess; \
u32 StaticIndex; \
bool Readonly; \
bool DynamicEntries; \
u8 _Align_Pad[6];
u8 _Align_Pad[2];
Using_Code_POD
};
@ -786,7 +773,7 @@ namespace gen
Code def_class( s32 length, char const* name
, Code body = NoCode
, Code parent = NoCode, AccessSpec access = AccessSpec::Public
, Code specifiers = NoCode, Code attributes = NoCode
, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_enum( s32 length, char const* name
@ -817,8 +804,8 @@ namespace gen
Code def_struct( s32 length, char const* name
, Code body
, Code parent = NoCode, AccessSpec access
, Code specifiers = NoCode, Code attributes = NoCode
, Code parent = NoCode, AccessSpec access = AccessSpec::Public
, Code attributes = NoCode
, ModuleFlag mflags = ModuleFlag::None );
Code def_typedef( s32 length, char const* name, Code type, Code attributes = NoCode, ModuleFlag mflags = ModuleFlag::None );