gencpp/base/components/ast.cpp

1289 lines
47 KiB
C++
Raw Normal View History

#ifdef GEN_INTELLISENSE_DIRECTIVES
#pragma once
#include "static_data.cpp"
#endif
2024-12-01 21:03:38 -08:00
global Code Code_Global;
global Code Code_Invalid;
// This serializes all the data-members in a "debug" format, where each member is printed with its associated value.
Str code_debug_str(Code self)
{
GEN_ASSERT(self != nullptr);
StrBuilder result_stack = strbuilder_make_reserve( GlobalAllocator, kilobytes(1) );
StrBuilder* result = & result_stack;
if ( self->Parent )
strbuilder_append_fmt( result, "\n\tParent : %S %S", code_type_str(self->Parent), self->Name.Len ? self->Name : txt("Null") );
else
strbuilder_append_fmt( result, "\n\tParent : %S", txt("Null") );
strbuilder_append_fmt( result, "\n\tName : %S", self->Name.Len ? self->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tType : %S", code_type_str(self) );
strbuilder_append_fmt( result, "\n\tModule Flags : %S", module_flag_to_str( self->ModuleFlags ) );
switch ( self->Type )
{
2024-12-03 12:19:39 -08:00
case CT_Invalid:
case CT_NewLine:
case CT_Access_Private:
case CT_Access_Protected:
case CT_Access_Public:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Untyped:
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:
case CT_Preprocess_ElIf:
case CT_Preprocess_Else:
case CT_Preprocess_IfDef:
case CT_Preprocess_IfNotDef:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tContent: %S", self->Content );
break;
2024-12-03 12:19:39 -08:00
case CT_Class:
case CT_Struct:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tParentAccess: %S", self->ParentType ? access_spec_to_str( self->ParentAccess ) : txt("No Parent") );
strbuilder_append_fmt( result, "\n\tParentType : %S", self->ParentType ? code_type_str(self->ParentType) : txt("Null") );
strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? code_debug_str(self->Body) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Class_Fwd:
case CT_Struct_Fwd:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tParentAccess: %S", self->ParentType ? access_spec_to_str( self->ParentAccess ) : txt("No Parent") );
strbuilder_append_fmt( result, "\n\tParentType : %S", self->ParentType ? code_type_str(self->ParentType) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Constructor:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tInitializerList: %S", self->InitializerList ? strbuilder_to_str( code_to_string(self->InitializerList) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? strbuilder_to_str( code_to_string(self->Params) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? code_debug_str(self->Body) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Constructor_Fwd:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tInitializerList: %S", self->InitializerList ? strbuilder_to_str( code_to_string(self->InitializerList) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? strbuilder_to_str( code_to_string(self->Params) ) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Destructor:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? code_debug_str(self->Body) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Destructor_Fwd:
break;
2024-12-03 12:19:39 -08:00
case CT_Enum:
case CT_Enum_Class:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tUnderlying Type : %S", self->UnderlyingType ? strbuilder_to_str( code_to_string(self->UnderlyingType)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? code_debug_str(self->Body) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Enum_Fwd:
case CT_Enum_Class_Fwd:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tUnderlying Type : %S", self->UnderlyingType ? strbuilder_to_str( code_to_string(self->UnderlyingType)) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Extern_Linkage:
case CT_Namespace:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tBody: %S", self->Body ? code_debug_str(self->Body) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Friend:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tDeclaration: %S", self->Declaration ? strbuilder_to_str( code_to_string(self->Declaration)) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Function:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? strbuilder_to_str( code_to_string(self->ReturnType)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? strbuilder_to_str( code_to_string(self->Params)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? code_debug_str(self->Body) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Function_Fwd:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? strbuilder_to_str( code_to_string(self->ReturnType)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? strbuilder_to_str( code_to_string(self->Params)) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Module:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Operator:
case CT_Operator_Member:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? strbuilder_to_str( code_to_string(self->ReturnType)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? strbuilder_to_str( code_to_string(self->Params)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? code_debug_str(self->Body) : txt("Null") );
strbuilder_append_fmt( result, "\n\tOp : %S", operator_to_str( self->Op ) );
break;
2024-12-03 12:19:39 -08:00
case CT_Operator_Fwd:
case CT_Operator_Member_Fwd:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tReturnType: %S", self->ReturnType ? strbuilder_to_str( code_to_string(self->ReturnType) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? strbuilder_to_str( code_to_string(self->Params) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tOp : %S", operator_to_str( self->Op ) );
break;
2024-12-03 12:19:39 -08:00
case CT_Operator_Cast:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tValueType : %S", self->ValueType ? strbuilder_to_str( code_to_string(self->ValueType)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? code_debug_str(self->Body) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Operator_Cast_Fwd:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tValueType : %S", self->ValueType ? strbuilder_to_str( code_to_string(self->ValueType)) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Parameters:
strbuilder_append_fmt( result, "\n\tNumEntries: %d", self->NumEntries );
strbuilder_append_fmt( result, "\n\tLast : %S", self->Last->Name );
strbuilder_append_fmt( result, "\n\tNext : %S", self->Next->Name );
strbuilder_append_fmt( result, "\n\tValueType : %S", self->ValueType ? strbuilder_to_str( code_to_string(self->ValueType)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tValue : %S", self->Value ? strbuilder_to_str( code_to_string(self->Value)) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Specifiers:
{
strbuilder_append_fmt( result, "\n\tNumEntries: %d", self->NumEntries );
strbuilder_append_str( result, txt("\n\tArrSpecs: ") );
s32 idx = 0;
s32 left = self->NumEntries;
while ( left-- )
{
Str spec = spec_to_str( self->ArrSpecs[idx] );
strbuilder_append_fmt( result, "%.*s, ", spec.Len, spec.Ptr );
idx++;
}
strbuilder_append_fmt( result, "\n\tNextSpecs: %S", self->NextSpecs ? code_debug_str(self->NextSpecs) : txt("Null") );
}
break;
2024-12-03 12:19:39 -08:00
case CT_Template:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? strbuilder_to_str( code_to_string(self->Params)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tDeclaration: %S", self->Declaration ? strbuilder_to_str( code_to_string(self->Declaration)) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Typedef:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tUnderlyingType: %S", self->UnderlyingType ? strbuilder_to_str( code_to_string(self->UnderlyingType)) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Typename:
strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tReturnType : %S", self->ReturnType ? strbuilder_to_str( code_to_string(self->ReturnType)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tParams : %S", self->Params ? strbuilder_to_str( code_to_string(self->Params)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tArrExpr : %S", self->ArrExpr ? strbuilder_to_str( code_to_string(self->ArrExpr)) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Union:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes: %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tBody : %S", self->Body ? code_debug_str(self->Body) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Using:
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tUnderlyingType: %S", self->UnderlyingType ? strbuilder_to_str( code_to_string(self->UnderlyingType)) : txt("Null") );
break;
2024-12-03 12:19:39 -08:00
case CT_Variable:
2024-12-03 12:19:39 -08:00
if ( self->Parent && self->Parent->Type == CT_Variable )
{
// Its a NextVar
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tValue : %S", self->Value ? strbuilder_to_str( code_to_string(self->Value)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tBitfieldSize: %S", self->BitfieldSize ? strbuilder_to_str( code_to_string(self->BitfieldSize)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tNextVar : %S", self->NextVar ? code_debug_str(self->NextVar) : txt("Null") );
break;
}
if ( self->Prev )
strbuilder_append_fmt( result, "\n\tPrev: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
if ( self->Next )
strbuilder_append_fmt( result, "\n\tNext: %S %S", code_type_str(self->Prev), self->Prev->Name.Len ? self->Prev->Name : txt("Null") );
strbuilder_append_fmt( result, "\n\tInlineCmt : %S", self->InlineCmt ? self->InlineCmt->Content : txt("Null") );
strbuilder_append_fmt( result, "\n\tAttributes : %S", self->Attributes ? strbuilder_to_str( code_to_string(self->Attributes) ) : txt("Null") );
strbuilder_append_fmt( result, "\n\tSpecs : %S", self->Specs ? strbuilder_to_str( code_to_string(self->Specs)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tValueType : %S", self->ValueType ? strbuilder_to_str( code_to_string(self->ValueType)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tBitfieldSize: %S", self->BitfieldSize ? strbuilder_to_str( code_to_string(self->BitfieldSize)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tValue : %S", self->Value ? strbuilder_to_str( code_to_string(self->Value)) : txt("Null") );
strbuilder_append_fmt( result, "\n\tNextVar : %S", self->NextVar ? code_debug_str(self->NextVar) : txt("Null") );
break;
}
return strbuilder_to_str( * result );
}
Code code_duplicate(Code self)
{
Code result = make_code();
void* mem_result = rcast(void*, cast(AST*, result));
void* mem_self = rcast(void*, cast(AST*, self));
mem_copy( mem_result, mem_self, sizeof( AST ) );
2024-12-08 20:10:10 -08:00
result->Parent = NullCode;
return result;
}
StrBuilder code_to_string(Code self)
{
StrBuilder result = strbuilder_make_str( GlobalAllocator, txt("") );
code_to_strbuilder_ptr( self, & result );
return result;
}
void code_to_strbuilder_ptr( Code self, StrBuilder* result )
{
2024-12-02 00:18:52 -08:00
GEN_ASSERT(self != nullptr);
local_persist thread_local
char SerializationLevel = 0;
2024-12-02 00:18:52 -08:00
switch ( self->Type )
{
2024-12-03 12:19:39 -08:00
case CT_Invalid:
#ifdef GEN_DONT_ALLOW_INVALID_CODE
log_failure("Attempted to serialize invalid code! - %S", Parent ? Parent->code_debug_str() : Name );
#else
strbuilder_append_fmt( result, "Invalid Code!" );
#endif
break;
2024-12-03 12:19:39 -08:00
case CT_NewLine:
strbuilder_append_str( result, txt("\n"));
break;
2024-12-03 12:19:39 -08:00
case CT_Untyped:
case CT_Execution:
case CT_Comment:
case CT_PlatformAttributes:
strbuilder_append_str( result, self->Content );
break;
2024-12-03 12:19:39 -08:00
case CT_Access_Private:
case CT_Access_Protected:
case CT_Access_Public:
strbuilder_append_str( result, self->Name );
break;
2024-12-03 12:19:39 -08:00
case CT_Class:
class_to_strbuilder_def(cast(CodeClass, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Class_Fwd:
class_to_strbuilder_fwd(cast(CodeClass, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Constructor:
constructor_to_strbuilder_def(cast(CodeConstructor, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Constructor_Fwd:
constructor_to_strbuilder_fwd(cast(CodeConstructor, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Destructor:
destructor_to_strbuilder_def(cast(CodeDestructor, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Destructor_Fwd:
destructor_to_strbuilder_fwd(cast(CodeDestructor, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Enum:
enum_to_strbuilder_def(cast(CodeEnum, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Enum_Fwd:
enum_to_strbuilder_fwd(cast(CodeEnum, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Enum_Class:
enum_to_strbuilder_class_def(cast(CodeEnum, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Enum_Class_Fwd:
enum_to_strbuilder_class_fwd(cast(CodeEnum, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Export_Body:
body_to_strbuilder_export(cast(CodeBody, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Extern_Linkage:
extern_to_string(cast(CodeExtern, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Friend:
friend_to_strbuilder_ref(cast(CodeFriend, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Function:
fn_to_strbuilder_def(cast(CodeFn, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Function_Fwd:
fn_to_strbuilder_fwd(cast(CodeFn, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Module:
module_to_strbuilder_ref(cast(CodeModule, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Namespace:
namespace_to_strbuilder_ref(cast(CodeNS, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Operator:
case CT_Operator_Member:
code_op_to_strbuilder_def(cast(CodeOperator, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Operator_Fwd:
case CT_Operator_Member_Fwd:
code_op_to_strbuilder_fwd(cast(CodeOperator, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Operator_Cast:
opcast_to_strbuilder_def(cast(CodeOpCast, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Operator_Cast_Fwd:
opcast_to_strbuilder_fwd(cast(CodeOpCast, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Parameters:
params_to_strbuilder_ref(cast(CodeParams, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Preprocess_Define:
define_to_strbuilder_ref(cast(CodeDefine, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Preprocess_If:
preprocess_to_strbuilder_if(cast(CodePreprocessCond, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Preprocess_IfDef:
preprocess_to_strbuilder_ifdef(cast(CodePreprocessCond, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Preprocess_IfNotDef:
preprocess_to_strbuilder_ifndef(cast(CodePreprocessCond, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Preprocess_Include:
include_to_strbuilder_ref(cast(CodeInclude, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Preprocess_ElIf:
preprocess_to_strbuilder_elif(cast(CodePreprocessCond, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Preprocess_Else:
preprocess_to_strbuilder_else(cast(CodePreprocessCond, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Preprocess_EndIf:
preprocess_to_strbuilder_endif(cast(CodePreprocessCond, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Preprocess_Pragma:
pragma_to_strbuilder_ref(cast(CodePragma, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Specifiers:
specifiers_to_strbuilder_ref(cast(CodeSpecifiers, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Struct:
struct_to_strbuilder_def(cast(CodeStruct, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Struct_Fwd:
struct_to_strbuilder_fwd(cast(CodeStruct, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Template:
template_to_strbuilder_ref(cast(CodeTemplate, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Typedef:
typedef_to_strbuilder_ref(cast(CodeTypedef, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Typename:
typename_to_strbuilder_ref(cast(CodeTypename, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Union:
union_to_strbuilder_def( cast(CodeUnion, self), result );
break;
case CT_Union_Fwd:
union_to_strbuilder_fwd( cast(CodeUnion, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Using:
using_to_strbuilder_ref(cast(CodeUsing, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Using_Namespace:
using_to_strbuilder_ns(cast(CodeUsing, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Variable:
var_to_strbuilder_ref(cast(CodeVar, self), result );
break;
2024-12-03 12:19:39 -08:00
case CT_Enum_Body:
case CT_Class_Body:
case CT_Extern_Linkage_Body:
case CT_Function_Body:
case CT_Global_Body:
case CT_Namespace_Body:
case CT_Struct_Body:
case CT_Union_Body:
body_to_strbuilder_ref( cast(CodeBody, self), result );
break;
}
}
bool code_is_equal( Code self, Code other )
{
/*
AST values are either some u32 value, a cached string, or a pointer to another AST.
u32 values are compared by value.
Cached strings are compared by pointer.
AST nodes are compared with AST::is_equal.
*/
if ( other == nullptr )
{
log_fmt( "AST::is_equal: other is null\nAST: %S", code_debug_str(self) );
return false;
}
2024-12-01 21:34:40 -08:00
if ( self->Type != other->Type )
{
log_fmt("AST::is_equal: Type check failure with other\nAST: %S\nOther: %S"
, code_debug_str(self)
,code_debug_str(other)
);
return false;
}
2024-12-01 21:34:40 -08:00
switch ( self->Type )
{
#define check_member_val( val ) \
2024-12-01 21:34:40 -08:00
if ( self->val != other->val ) \
{ \
log_fmt("\nAST::is_equal: Member - " #val " failed\n" \
"AST : %S\n" \
"Other: %S\n" \
2024-12-07 14:17:02 -08:00
, code_debug_str(self) \
,code_debug_str(other) \
); \
\
return false; \
}
#define check_member_str( str ) \
if ( ! str_are_equal( self->str, other->str ) ) \
{ \
log_fmt("\nAST::is_equal: Member string - "#str " failed\n" \
"AST : %S\n" \
"Other: %S\n" \
2024-12-07 14:17:02 -08:00
, code_debug_str(self) \
,code_debug_str(other) \
); \
\
return false; \
}
#define check_member_content( content ) \
if ( ! str_are_equal( self->content, other->content )) \
{ \
log_fmt("\nAST::is_equal: Member content - "#content " failed\n" \
"AST : %S\n" \
"Other: %S\n" \
2024-12-07 14:17:02 -08:00
, code_debug_str(self) \
, code_debug_str(other) \
); \
\
log_fmt("Content cannot be trusted to be unique with this check " \
"so it must be verified by eye for now\n" \
"AST Content:\n%S\n" \
"Other Content:\n%S\n" \
, str_visualize_whitespace(self->content, GlobalAllocator) \
, str_visualize_whitespace(other->content, GlobalAllocator) \
); \
}
#define check_member_ast( ast ) \
2024-12-01 21:34:40 -08:00
if ( self->ast ) \
{ \
if ( other->ast == nullptr ) \
{ \
log_fmt("\nAST::is_equal: Failed for member " #ast " other equivalent param is null\n" \
"AST : %S\n" \
"Other: %S\n" \
"For ast member: %S\n" \
2024-12-07 14:17:02 -08:00
, code_debug_str(self) \
, code_debug_str(other) \
, code_debug_str(self->ast) \
); \
\
return false; \
} \
\
2024-12-07 14:17:02 -08:00
if ( ! code_is_equal(self->ast, other->ast ) ) \
{ \
log_fmt( "\nAST::is_equal: Failed for " #ast"\n" \
"AST : %S\n" \
"Other: %S\n" \
"For ast member: %S\n" \
"other's ast member: %S\n" \
2024-12-07 14:17:02 -08:00
, code_debug_str(self) \
, code_debug_str(other) \
, code_debug_str(self->ast) \
, code_debug_str(other->ast) \
); \
\
return false; \
} \
}
2024-12-03 12:19:39 -08:00
case CT_NewLine:
case CT_Access_Public:
case CT_Access_Protected:
case CT_Access_Private:
case CT_Preprocess_Else:
case CT_Preprocess_EndIf:
return true;
// Comments are not validated.
2024-12-03 12:19:39 -08:00
case CT_Comment:
return true;
2024-12-03 12:19:39 -08:00
case CT_Execution:
case CT_PlatformAttributes:
case CT_Untyped:
{
check_member_content( Content );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Class_Fwd:
case CT_Struct_Fwd:
{
check_member_str( Name );
check_member_ast( ParentType );
check_member_val( ParentAccess );
check_member_ast( Attributes );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Class:
case CT_Struct:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( ParentType );
check_member_val( ParentAccess );
check_member_ast( Attributes );
check_member_ast( Body );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Constructor:
{
check_member_ast( InitializerList );
check_member_ast( Params );
check_member_ast( Body );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Constructor_Fwd:
{
check_member_ast( InitializerList );
check_member_ast( Params );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Destructor:
{
check_member_ast( Specs );
check_member_ast( Body );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Destructor_Fwd:
{
check_member_ast( Specs );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Enum:
case CT_Enum_Class:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( Attributes );
check_member_ast( UnderlyingType );
check_member_ast( Body );
check_member_ast( UnderlyingTypeMacro );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Enum_Fwd:
case CT_Enum_Class_Fwd:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( Attributes );
check_member_ast( UnderlyingType );
check_member_ast( UnderlyingTypeMacro );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Extern_Linkage:
{
check_member_str( Name );
check_member_ast( Body );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Friend:
{
check_member_str( Name );
check_member_ast( Declaration );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Function:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( ReturnType );
check_member_ast( Attributes );
check_member_ast( Specs );
check_member_ast( Params );
check_member_ast( Body );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Function_Fwd:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( ReturnType );
check_member_ast( Attributes );
check_member_ast( Specs );
check_member_ast( Params );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Module:
{
check_member_val( ModuleFlags );
check_member_str( Name );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Namespace:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( Body );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Operator:
case CT_Operator_Member:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( ReturnType );
check_member_ast( Attributes );
check_member_ast( Specs );
check_member_ast( Params );
check_member_ast( Body );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Operator_Fwd:
case CT_Operator_Member_Fwd:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( ReturnType );
check_member_ast( Attributes );
check_member_ast( Specs );
check_member_ast( Params );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Operator_Cast:
{
check_member_str( Name );
check_member_ast( Specs );
check_member_ast( ValueType );
check_member_ast( Body );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Operator_Cast_Fwd:
{
check_member_str( Name );
check_member_ast( Specs );
check_member_ast( ValueType );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Parameters:
{
2024-12-01 21:34:40 -08:00
if ( self->NumEntries > 1 )
{
Code curr = self;
Code curr_other = other;
while ( curr != nullptr )
{
if ( curr )
{
if ( curr_other == nullptr )
{
log_fmt("\nAST::is_equal: Failed for parameter, other equivalent param is null\n"
"AST : %S\n"
"Other: %S\n"
"For ast member: %S\n"
2024-12-07 14:17:02 -08:00
, code_debug_str(curr)
);
return false;
}
if ( str_are_equal(curr->Name, curr_other->Name) )
{
log_fmt( "\nAST::is_equal: Failed for parameter name check\n"
"AST : %S\n"
"Other: %S\n"
"For ast member: %S\n"
"other's ast member: %S\n"
, code_debug_str(self)
, code_debug_str(other)
, code_debug_str(curr)
, code_debug_str(curr_other)
);
return false;
}
if ( curr->ValueType && ! code_is_equal(curr->ValueType, curr_other->ValueType) )
{
log_fmt( "\nAST::is_equal: Failed for parameter value type check\n"
"AST : %S\n"
"Other: %S\n"
"For ast member: %S\n"
"other's ast member: %S\n"
, code_debug_str(self)
, code_debug_str(other)
, code_debug_str(curr)
, code_debug_str(curr_other)
);
return false;
}
if ( curr->Value && ! code_is_equal(curr->Value, curr_other->Value) )
{
log_fmt( "\nAST::is_equal: Failed for parameter value check\n"
"AST : %S\n"
"Other: %S\n"
"For ast member: %S\n"
"other's ast member: %S\n"
, code_debug_str(self)
, code_debug_str(other)
, code_debug_str(curr)
, code_debug_str(curr_other)
);
Work on AST::is_equal. The NumEntries checks need to be deferred until the end as a final unresolved check on valdiation. As if there really is a discrepancy of entires it should be revealed by the specific entry failing. Right now the latest failure with the single header check involves a define directive specifically the define does omit whitespace properly and so the check interprets the different cached content to be non-equivalent. This will happen with all unvalidated aspects of the AST ( expressions, function bodies, etc ) There are two ways to resolve, either make an AST that can tokenize all items (not realistic), or I need to strip non-syntax important whitespace and then cache the string. This would mean removing everything but a single whitespace for all content within a content string. Otherwise, I would have to somehow make sure the content of the string has the exact formatting between both files for the definitions that matter. AST types with this issue: * Define Directive * Pragma Directive * Comment * Execution * Platform Attributes * Untyped Comments can technically be left unverified as they do not matter semantically. When the serialization is first emitted, the content these strings should for the most part be equivalent. However I do see some possible failures for that if a different style of bracket placment is used (between the serialization). At that point what I could do is just leave those unverified and just emit the content to the user as warning that the ast and the other compared could not be verified. Those technically can be handled on a per-eye basis, and worst case the tests with the compiler will in the determine if any critical defintions are missing for the user.
2023-08-25 15:40:13 -07:00
return false;
}
}
curr = curr->Next;
curr_other = curr_other->Next;
}
Work on AST::is_equal. The NumEntries checks need to be deferred until the end as a final unresolved check on valdiation. As if there really is a discrepancy of entires it should be revealed by the specific entry failing. Right now the latest failure with the single header check involves a define directive specifically the define does omit whitespace properly and so the check interprets the different cached content to be non-equivalent. This will happen with all unvalidated aspects of the AST ( expressions, function bodies, etc ) There are two ways to resolve, either make an AST that can tokenize all items (not realistic), or I need to strip non-syntax important whitespace and then cache the string. This would mean removing everything but a single whitespace for all content within a content string. Otherwise, I would have to somehow make sure the content of the string has the exact formatting between both files for the definitions that matter. AST types with this issue: * Define Directive * Pragma Directive * Comment * Execution * Platform Attributes * Untyped Comments can technically be left unverified as they do not matter semantically. When the serialization is first emitted, the content these strings should for the most part be equivalent. However I do see some possible failures for that if a different style of bracket placment is used (between the serialization). At that point what I could do is just leave those unverified and just emit the content to the user as warning that the ast and the other compared could not be verified. Those technically can be handled on a per-eye basis, and worst case the tests with the compiler will in the determine if any critical defintions are missing for the user.
2023-08-25 15:40:13 -07:00
check_member_val( NumEntries );
return true;
}
check_member_str( Name );
check_member_ast( ValueType );
check_member_ast( Value );
check_member_ast( ArrExpr );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Preprocess_Define:
{
check_member_str( Name );
check_member_content( Content );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Preprocess_If:
case CT_Preprocess_IfDef:
case CT_Preprocess_IfNotDef:
case CT_Preprocess_ElIf:
{
check_member_content( Content );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Preprocess_Include:
case CT_Preprocess_Pragma:
{
check_member_content( Content );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Specifiers:
{
check_member_val( NumEntries );
check_member_str( Name );
2024-12-01 21:34:40 -08:00
for ( s32 idx = 0; idx < self->NumEntries; ++idx )
{
check_member_val( ArrSpecs[ idx ] );
}
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Template:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( Params );
check_member_ast( Declaration );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Typedef:
{
check_member_val( IsFunction );
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( Specs );
check_member_ast( UnderlyingType );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Typename:
{
check_member_val( IsParamPack );
check_member_str( Name );
check_member_ast( Specs );
check_member_ast( ArrExpr );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Union:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( Attributes );
check_member_ast( Body );
return true;
}
2024-12-07 14:17:02 -08:00
case CT_Union_Fwd:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( Attributes );
}
2024-12-03 12:19:39 -08:00
case CT_Using:
case CT_Using_Namespace:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( UnderlyingType );
check_member_ast( Attributes );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Variable:
{
check_member_val( ModuleFlags );
check_member_str( Name );
check_member_ast( ValueType );
check_member_ast( BitfieldSize );
check_member_ast( Value );
check_member_ast( Attributes );
check_member_ast( Specs );
check_member_ast( NextVar );
return true;
}
2024-12-03 12:19:39 -08:00
case CT_Class_Body:
case CT_Enum_Body:
case CT_Export_Body:
case CT_Global_Body:
case CT_Namespace_Body:
case CT_Struct_Body:
case CT_Union_Body:
{
check_member_ast( Front );
check_member_ast( Back );
Code curr = self->Front;
Code curr_other = other->Front;
while ( curr != nullptr )
{
if ( curr_other == nullptr )
{
log_fmt("\nAST::is_equal: Failed for body, other equivalent param is null\n"
"AST : %S\n"
"Other: %S\n"
2024-12-07 14:17:02 -08:00
, code_debug_str(curr)
2024-12-08 20:10:10 -08:00
, code_debug_str(other)
);
return false;
}
if ( ! code_is_equal( curr, curr_other ) )
{
log_fmt( "\nAST::is_equal: Failed for body\n"
"AST : %S\n"
"Other: %S\n"
"For ast member: %S\n"
"other's ast member: %S\n"
, code_debug_str(self)
, code_debug_str(other)
, code_debug_str(curr)
, code_debug_str(curr_other)
);
return false;
}
curr = curr->Next;
curr_other = curr_other->Next;
}
Work on AST::is_equal. The NumEntries checks need to be deferred until the end as a final unresolved check on valdiation. As if there really is a discrepancy of entires it should be revealed by the specific entry failing. Right now the latest failure with the single header check involves a define directive specifically the define does omit whitespace properly and so the check interprets the different cached content to be non-equivalent. This will happen with all unvalidated aspects of the AST ( expressions, function bodies, etc ) There are two ways to resolve, either make an AST that can tokenize all items (not realistic), or I need to strip non-syntax important whitespace and then cache the string. This would mean removing everything but a single whitespace for all content within a content string. Otherwise, I would have to somehow make sure the content of the string has the exact formatting between both files for the definitions that matter. AST types with this issue: * Define Directive * Pragma Directive * Comment * Execution * Platform Attributes * Untyped Comments can technically be left unverified as they do not matter semantically. When the serialization is first emitted, the content these strings should for the most part be equivalent. However I do see some possible failures for that if a different style of bracket placment is used (between the serialization). At that point what I could do is just leave those unverified and just emit the content to the user as warning that the ast and the other compared could not be verified. Those technically can be handled on a per-eye basis, and worst case the tests with the compiler will in the determine if any critical defintions are missing for the user.
2023-08-25 15:40:13 -07:00
check_member_val( NumEntries );
return true;
}
#undef check_member_val
#undef check_member_str
#undef check_member_ast
}
return true;
}
bool code_validate_body(Code self)
{
2024-12-02 00:18:52 -08:00
switch ( self->Type )
{
2024-12-03 12:19:39 -08:00
case CT_Class_Body:
{
CodeBody body = cast(CodeBody, self);
for (Code code_entry = begin_CodeBody(body); code_entry != end_CodeBody(body); next_CodeBody(body, code_entry)) switch (code_entry->Type)
{
GEN_AST_BODY_CLASS_UNALLOWED_TYPES:
log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(code_entry));
return false;
default:
continue;
}
}
break;
2024-12-03 12:19:39 -08:00
case CT_Enum_Body:
{
CodeBody body = cast(CodeBody, self);
for ( Code entry = begin_CodeBody(body); entry != end_CodeBody(body); next_CodeBody(body, entry) )
{
2024-12-03 12:19:39 -08:00
if ( entry->Type != CT_Untyped )
{
log_failure( "AST::validate_body: Invalid entry in enum body (needs to be untyped or comment) %S", code_debug_str(entry) );
return false;
}
}
}
break;
2024-12-03 12:19:39 -08:00
case CT_Export_Body:
{
CodeBody body = cast(CodeBody, self);
for (Code code_entry = begin_CodeBody(body); code_entry != end_CodeBody(body); next_CodeBody(body, code_entry)) switch (code_entry->Type)
{
GEN_AST_BODY_EXPORT_UNALLOWED_TYPES:
log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(code_entry));
return false;
default:
continue;
}
}
break;
2024-12-03 12:19:39 -08:00
case CT_Extern_Linkage:
{
CodeBody body = cast(CodeBody, self);
for (Code code_entry = begin_CodeBody(body); code_entry != end_CodeBody(body); next_CodeBody(body, code_entry)) switch (code_entry->Type)
{
GEN_AST_BODY_EXTERN_LINKAGE_UNALLOWED_TYPES:
log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(code_entry));
return false;
default:
continue;
}
}
break;
2024-12-03 12:19:39 -08:00
case CT_Function_Body:
{
CodeBody body = cast(CodeBody, self);
for (Code code_entry = begin_CodeBody(body); code_entry != end_CodeBody(body); next_CodeBody(body, code_entry)) switch (code_entry->Type)
{
GEN_AST_BODY_FUNCTION_UNALLOWED_TYPES:
log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(code_entry));
return false;
default:
continue;
}
}
break;
2024-12-03 12:19:39 -08:00
case CT_Global_Body:
{
CodeBody body = cast(CodeBody, self);
for ( Code entry = begin_CodeBody(body); entry != end_CodeBody(body); next_CodeBody(body, entry) )switch (entry->Type)
{
GEN_AST_BODY_GLOBAL_UNALLOWED_TYPES:
log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(entry));
return false;
}
}
break;
2024-12-03 12:19:39 -08:00
case CT_Namespace_Body:
{
CodeBody body = cast(CodeBody, self);
for ( Code entry = begin_CodeBody(body); entry != end_CodeBody(body); next_CodeBody(body, entry) ) switch (entry->Type)
{
GEN_AST_BODY_NAMESPACE_UNALLOWED_TYPES:
log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(entry));
return false;
}
}
break;
2024-12-03 12:19:39 -08:00
case CT_Struct_Body:
{
CodeBody body = cast(CodeBody, self);
for ( Code entry = begin_CodeBody(body); entry != end_CodeBody(body); next_CodeBody(body, entry) ) switch (entry->Type)
{
GEN_AST_BODY_STRUCT_UNALLOWED_TYPES:
log_failure("AST::validate_body: Invalid entry in body %S", code_debug_str(entry));
return false;
}
}
break;
2024-12-03 12:19:39 -08:00
case CT_Union_Body:
{
CodeBody body = cast(CodeBody, self);
for ( Code entry = begin_CodeBody(body); entry != end_CodeBody(body); next_CodeBody(body, entry) )
{
2024-12-03 12:19:39 -08:00
if ( entry->Type != CT_Untyped )
{
log_failure( "AST::validate_body: Invalid entry in union body (needs to be untyped or comment) %S", code_debug_str(entry) );
return false;
}
}
}
break;
default:
log_failure( "AST::validate_body: Invalid this AST does not have a body %S", code_debug_str(self) );
return false;
}
return false;
}