2023-08-28 20:46:50 -07:00
|
|
|
#ifdef GEN_INTELLISENSE_DIRECTIVES
|
2023-08-21 17:30:13 -07:00
|
|
|
#pragma once
|
2023-08-21 20:02:20 -07:00
|
|
|
#include "interface.hpp"
|
2023-08-28 20:46:50 -07:00
|
|
|
#endif
|
2023-08-21 17:30:13 -07:00
|
|
|
|
2024-12-02 17:20:30 -08:00
|
|
|
#pragma region Code
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2024-12-02 17:20:30 -08:00
|
|
|
void append( Code self, Code other )
|
2023-08-03 08:01:43 -07:00
|
|
|
{
|
2024-12-02 17:20:30 -08:00
|
|
|
GEN_ASSERT(self.ast != nullptr);
|
|
|
|
GEN_ASSERT(other.ast != nullptr);
|
2024-12-01 15:50:37 -08:00
|
|
|
|
2023-08-03 08:01:43 -07:00
|
|
|
if ( other->Parent )
|
2024-12-01 15:50:37 -08:00
|
|
|
other = duplicate(other);
|
2023-08-03 08:01:43 -07:00
|
|
|
|
2024-12-01 15:50:37 -08:00
|
|
|
other->Parent = self;
|
2023-08-03 08:01:43 -07:00
|
|
|
|
2024-12-01 15:50:37 -08:00
|
|
|
if ( self->Front == nullptr )
|
2023-08-03 08:01:43 -07:00
|
|
|
{
|
2024-12-01 15:50:37 -08:00
|
|
|
self->Front = other;
|
|
|
|
self->Back = other;
|
2023-08-03 08:01:43 -07:00
|
|
|
|
2024-12-01 15:50:37 -08:00
|
|
|
self->NumEntries++;
|
2023-08-03 08:01:43 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-12-02 17:20:30 -08:00
|
|
|
Code
|
2024-12-01 15:50:37 -08:00
|
|
|
Current = self->Back;
|
2023-08-03 08:01:43 -07:00
|
|
|
Current->Next = other;
|
|
|
|
other->Prev = Current;
|
2024-12-01 15:50:37 -08:00
|
|
|
self->Back = other;
|
|
|
|
self->NumEntries++;
|
2023-08-03 08:01:43 -07:00
|
|
|
}
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2024-12-02 17:20:30 -08:00
|
|
|
bool is_body(Code self)
|
2024-12-01 10:29:33 -08:00
|
|
|
{
|
2024-12-01 15:50:37 -08:00
|
|
|
GEN_ASSERT(self != nullptr);
|
|
|
|
switch (self->Type)
|
2024-12-01 10:29:33 -08:00
|
|
|
{
|
|
|
|
case ECode::Enum_Body:
|
|
|
|
case ECode::Class_Body:
|
|
|
|
case ECode::Union_Body:
|
|
|
|
case ECode::Export_Body:
|
|
|
|
case ECode::Global_Body:
|
|
|
|
case ECode::Struct_Body:
|
|
|
|
case ECode::Function_Body:
|
|
|
|
case ECode::Namespace_Body:
|
|
|
|
case ECode::Extern_Linkage_Body:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2024-12-01 21:10:24 -08:00
|
|
|
inline
|
2024-12-02 17:20:30 -08:00
|
|
|
Code* entry( Code self, u32 idx )
|
2024-12-01 21:10:24 -08:00
|
|
|
{
|
2024-12-02 17:20:30 -08:00
|
|
|
GEN_ASSERT(self.ast != nullptr);
|
|
|
|
Code* current = & self->Front;
|
|
|
|
while ( idx >= 0 && current != nullptr )
|
2024-12-01 21:16:11 -08:00
|
|
|
{
|
2024-12-02 17:20:30 -08:00
|
|
|
if ( idx == 0 )
|
|
|
|
return rcast( Code*, current);
|
2024-12-01 21:16:11 -08:00
|
|
|
|
2024-12-02 17:20:30 -08:00
|
|
|
current = & ( * current )->Next;
|
|
|
|
idx--;
|
2024-12-01 21:18:54 -08:00
|
|
|
}
|
2024-12-02 17:20:30 -08:00
|
|
|
|
|
|
|
return rcast( Code*, current);
|
2024-12-01 21:18:54 -08:00
|
|
|
}
|
2024-12-01 21:34:40 -08:00
|
|
|
inline
|
2024-12-02 17:20:30 -08:00
|
|
|
bool is_valid(Code self)
|
2024-12-01 21:34:40 -08:00
|
|
|
{
|
2024-12-02 17:20:30 -08:00
|
|
|
return self.ast != nullptr && self.ast->Type != CodeT::Invalid;
|
2024-12-01 21:34:40 -08:00
|
|
|
}
|
2024-12-01 21:41:41 -08:00
|
|
|
inline
|
2024-12-02 17:20:30 -08:00
|
|
|
bool has_entries(AST* self)
|
2024-12-01 21:41:41 -08:00
|
|
|
{
|
2024-12-02 17:20:30 -08:00
|
|
|
GEN_ASSERT(self != nullptr);
|
|
|
|
return self->NumEntries > 0;
|
2024-12-01 21:41:41 -08:00
|
|
|
}
|
2024-12-01 21:43:57 -08:00
|
|
|
inline
|
|
|
|
void set_global(Code self)
|
|
|
|
{
|
|
|
|
if ( self.ast == nullptr )
|
|
|
|
{
|
|
|
|
log_failure("Code::set_global: Cannot set code as global, AST is null!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-12-02 17:20:30 -08:00
|
|
|
self->Parent.ast = Code_Global.ast;
|
2024-12-01 21:43:57 -08:00
|
|
|
}
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2023-08-03 08:01:43 -07:00
|
|
|
Code& Code::operator ++()
|
|
|
|
{
|
|
|
|
if ( ast )
|
2024-12-02 17:20:30 -08:00
|
|
|
ast = ast->Next.ast;
|
2023-08-03 08:01:43 -07:00
|
|
|
|
2024-12-02 17:20:30 -08:00
|
|
|
return * this;
|
|
|
|
}
|
|
|
|
inline
|
|
|
|
char const* type_str(Code self)
|
|
|
|
{
|
|
|
|
GEN_ASSERT(self != nullptr);
|
|
|
|
return ECode::to_str( self->Type );
|
2023-08-03 08:01:43 -07:00
|
|
|
}
|
2024-12-01 21:10:24 -08:00
|
|
|
#pragma endregion Code
|
|
|
|
|
2024-12-02 07:58:24 -08:00
|
|
|
#pragma region CodeBody
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2024-12-02 01:12:09 -08:00
|
|
|
void append( CodeBody self, Code other )
|
2023-08-03 08:01:43 -07:00
|
|
|
{
|
2024-12-02 01:12:09 -08:00
|
|
|
GEN_ASSERT(other.ast != nullptr);
|
|
|
|
|
|
|
|
if (is_body(other)) {
|
|
|
|
append( self, cast(CodeBody, other) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-12-02 17:20:30 -08:00
|
|
|
append( cast(Code, self), other );
|
2024-12-02 01:12:09 -08:00
|
|
|
}
|
|
|
|
inline
|
|
|
|
void append( CodeBody self, CodeBody body )
|
|
|
|
{
|
2024-12-02 07:58:24 -08:00
|
|
|
GEN_ASSERT(self.ast != nullptr);
|
|
|
|
|
2024-12-02 01:12:09 -08:00
|
|
|
for ( Code entry : body ) {
|
|
|
|
append( self, entry );
|
|
|
|
}
|
|
|
|
}
|
2024-12-02 07:58:24 -08:00
|
|
|
inline
|
|
|
|
Code begin( CodeBody body) {
|
|
|
|
if ( body.ast )
|
|
|
|
return { rcast( AST*, body.ast)->Front };
|
|
|
|
return { nullptr };
|
|
|
|
}
|
|
|
|
inline
|
|
|
|
Code end(CodeBody body ){
|
|
|
|
return { rcast(AST*, body.ast)->Back->Next };
|
|
|
|
}
|
|
|
|
#pragma endregion CodeBody
|
2024-12-02 01:12:09 -08:00
|
|
|
|
2024-12-02 07:58:24 -08:00
|
|
|
#pragma region CodeClass
|
2024-12-02 01:12:09 -08:00
|
|
|
inline
|
|
|
|
void add_interface( CodeClass self, CodeType type )
|
|
|
|
{
|
|
|
|
GEN_ASSERT(self.ast !=nullptr);
|
|
|
|
CodeType possible_slot = self->ParentType;
|
2023-09-06 00:06:30 -07:00
|
|
|
if ( possible_slot.ast )
|
2023-08-03 08:01:43 -07:00
|
|
|
{
|
2023-09-06 00:06:30 -07:00
|
|
|
// Were adding an interface to parent type, so we need to make sure the parent type is public.
|
2024-12-02 01:12:09 -08:00
|
|
|
self->ParentAccess = AccessSpec_Public;
|
2023-09-06 00:06:30 -07:00
|
|
|
// If your planning on adding a proper parent,
|
|
|
|
// then you'll need to move this over to ParentType->next and update ParentAccess accordingly.
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( possible_slot.ast != nullptr )
|
|
|
|
{
|
|
|
|
possible_slot.ast = (AST_Type*) possible_slot->Next.ast;
|
2023-08-03 08:01:43 -07:00
|
|
|
}
|
|
|
|
|
2023-09-06 00:06:30 -07:00
|
|
|
possible_slot.ast = type.ast;
|
2023-08-03 08:01:43 -07:00
|
|
|
}
|
2024-12-02 07:58:24 -08:00
|
|
|
#pragma endregion CodeClass
|
2023-08-03 08:01:43 -07:00
|
|
|
|
2024-12-02 07:58:24 -08:00
|
|
|
#pragma region CodeParam
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2024-12-02 07:58:24 -08:00
|
|
|
void append( CodeParam appendee, CodeParam other )
|
2023-08-03 08:01:43 -07:00
|
|
|
{
|
2024-12-02 07:58:24 -08:00
|
|
|
GEN_ASSERT(appendee.ast != nullptr);
|
2024-12-02 17:20:30 -08:00
|
|
|
Code self = cast(Code, appendee);
|
|
|
|
Code entry = cast(Code, other);
|
2023-08-03 08:01:43 -07:00
|
|
|
|
|
|
|
if ( entry->Parent )
|
2024-12-01 15:50:37 -08:00
|
|
|
entry = GEN_NS duplicate( entry );
|
2023-08-03 08:01:43 -07:00
|
|
|
|
|
|
|
entry->Parent = self;
|
|
|
|
|
|
|
|
if ( self->Last == nullptr )
|
|
|
|
{
|
|
|
|
self->Last = entry;
|
|
|
|
self->Next = entry;
|
|
|
|
self->NumEntries++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
self->Last->Next = entry;
|
|
|
|
self->Last = entry;
|
|
|
|
self->NumEntries++;
|
|
|
|
}
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2024-12-02 07:58:24 -08:00
|
|
|
CodeParam get(CodeParam self, s32 idx )
|
2023-08-03 08:01:43 -07:00
|
|
|
{
|
2024-12-02 07:58:24 -08:00
|
|
|
GEN_ASSERT(self.ast != nullptr);
|
|
|
|
CodeParam param = * self;
|
2023-08-03 08:01:43 -07:00
|
|
|
do
|
|
|
|
{
|
|
|
|
if ( ! ++ param )
|
|
|
|
return { nullptr };
|
|
|
|
|
2024-12-02 17:20:30 -08:00
|
|
|
param = cast(Code, param)->Next;
|
2023-08-03 08:01:43 -07:00
|
|
|
}
|
|
|
|
while ( --idx );
|
|
|
|
|
2024-10-25 02:01:37 -07:00
|
|
|
return param;
|
2023-08-03 08:01:43 -07:00
|
|
|
}
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2024-12-02 07:58:24 -08:00
|
|
|
bool has_entries(CodeParam self)
|
2023-08-03 08:01:43 -07:00
|
|
|
{
|
2024-12-02 07:58:24 -08:00
|
|
|
GEN_ASSERT(self.ast != nullptr);
|
|
|
|
return self->NumEntries > 0;
|
2023-08-03 08:01:43 -07:00
|
|
|
}
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2023-08-03 08:01:43 -07:00
|
|
|
CodeParam& CodeParam::operator ++()
|
|
|
|
{
|
|
|
|
ast = ast->Next.ast;
|
|
|
|
return * this;
|
|
|
|
}
|
2024-12-02 13:59:13 -08:00
|
|
|
inline
|
|
|
|
CodeParam begin(CodeParam params)
|
|
|
|
{
|
|
|
|
if ( params.ast )
|
|
|
|
return { params.ast };
|
|
|
|
|
|
|
|
return { nullptr };
|
|
|
|
}
|
|
|
|
inline
|
|
|
|
CodeParam end(CodeParam params)
|
|
|
|
{
|
|
|
|
// return { (AST_Param*) rcast( AST*, ast)->Last };
|
|
|
|
return { nullptr };
|
|
|
|
}
|
2024-12-02 07:58:24 -08:00
|
|
|
#pragma endregion CodeParam
|
|
|
|
|
|
|
|
#pragma region CodeSpecifiers
|
|
|
|
inline
|
2024-12-03 10:14:14 -08:00
|
|
|
bool append(CodeSpecifiers self, Specifier spec )
|
2024-12-02 07:58:24 -08:00
|
|
|
{
|
|
|
|
if ( self.ast == nullptr )
|
|
|
|
{
|
|
|
|
log_failure("CodeSpecifiers: Attempted to append to a null specifiers AST!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if ( self->NumEntries == AST_ArrSpecs_Cap )
|
|
|
|
{
|
|
|
|
log_failure("CodeSpecifiers: Attempted to append over %d specifiers to a specifiers AST!", AST_ArrSpecs_Cap );
|
|
|
|
return false;
|
|
|
|
}
|
2023-08-03 08:01:43 -07:00
|
|
|
|
2024-12-02 07:58:24 -08:00
|
|
|
self->ArrSpecs[ self->NumEntries ] = spec;
|
|
|
|
self->NumEntries++;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
inline
|
2024-12-03 10:14:14 -08:00
|
|
|
s32 has(CodeSpecifiers self, Specifier spec)
|
2024-12-02 07:58:24 -08:00
|
|
|
{
|
|
|
|
GEN_ASSERT(self.ast != nullptr);
|
|
|
|
for ( s32 idx = 0; idx < self->NumEntries; idx++ ) {
|
|
|
|
if ( self->ArrSpecs[ idx ] == spec )
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
inline
|
2024-12-03 10:14:14 -08:00
|
|
|
s32 remove( CodeSpecifiers self, Specifier to_remove )
|
2024-12-02 07:58:24 -08:00
|
|
|
{
|
|
|
|
AST_Specifiers* ast = self.ast;
|
|
|
|
if ( ast == nullptr )
|
|
|
|
{
|
|
|
|
log_failure("CodeSpecifiers: Attempted to append to a null specifiers AST!");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if ( self->NumEntries == AST_ArrSpecs_Cap )
|
|
|
|
{
|
|
|
|
log_failure("CodeSpecifiers: Attempted to append over %d specifiers to a specifiers AST!", AST_ArrSpecs_Cap );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
s32 result = -1;
|
|
|
|
|
|
|
|
s32 curr = 0;
|
|
|
|
s32 next = 0;
|
|
|
|
for(; next < self->NumEntries; ++ curr, ++ next)
|
|
|
|
{
|
2024-12-03 10:14:14 -08:00
|
|
|
Specifier spec = self->ArrSpecs[next];
|
2024-12-02 07:58:24 -08:00
|
|
|
if (spec == to_remove)
|
|
|
|
{
|
|
|
|
result = next;
|
|
|
|
|
|
|
|
next ++;
|
|
|
|
if (next >= self->NumEntries)
|
|
|
|
break;
|
|
|
|
|
|
|
|
spec = self->ArrSpecs[next];
|
|
|
|
}
|
|
|
|
|
|
|
|
self->ArrSpecs[ curr ] = spec;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result > -1) {
|
|
|
|
self->NumEntries --;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
inline
|
2024-12-03 10:14:14 -08:00
|
|
|
Specifier* begin(CodeSpecifiers self)
|
2024-12-02 07:58:24 -08:00
|
|
|
{
|
|
|
|
if ( self.ast )
|
|
|
|
return & self->ArrSpecs[0];
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
inline
|
2024-12-03 10:14:14 -08:00
|
|
|
Specifier* end(CodeSpecifiers self)
|
2024-12-02 07:58:24 -08:00
|
|
|
{
|
|
|
|
return self->ArrSpecs + self->NumEntries;
|
|
|
|
}
|
|
|
|
#pragma endregion CodeSpecifiers
|
|
|
|
|
|
|
|
#pragma region CodeStruct
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2024-12-02 08:20:31 -08:00
|
|
|
void add_interface(CodeStruct self, CodeType type )
|
2023-08-03 08:01:43 -07:00
|
|
|
{
|
2024-12-02 08:20:31 -08:00
|
|
|
CodeType possible_slot = self->ParentType;
|
2023-09-06 00:06:30 -07:00
|
|
|
if ( possible_slot.ast )
|
|
|
|
{
|
|
|
|
// Were adding an interface to parent type, so we need to make sure the parent type is public.
|
2024-12-02 08:20:31 -08:00
|
|
|
self->ParentAccess = AccessSpec_Public;
|
2023-09-06 00:06:30 -07:00
|
|
|
// If your planning on adding a proper parent,
|
|
|
|
// then you'll need to move this over to ParentType->next and update ParentAccess accordingly.
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( possible_slot.ast != nullptr )
|
2023-08-03 08:01:43 -07:00
|
|
|
{
|
2023-09-06 00:06:30 -07:00
|
|
|
possible_slot.ast = (AST_Type*) possible_slot->Next.ast;
|
2023-08-03 08:01:43 -07:00
|
|
|
}
|
|
|
|
|
2023-09-06 00:06:30 -07:00
|
|
|
possible_slot.ast = type.ast;
|
2023-08-03 08:01:43 -07:00
|
|
|
}
|
2024-12-02 07:58:24 -08:00
|
|
|
#pragma endregion Code
|
2023-08-03 08:01:43 -07:00
|
|
|
|
2024-12-02 07:58:24 -08:00
|
|
|
#pragma region Interface
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2023-08-03 08:01:43 -07:00
|
|
|
CodeBody def_body( CodeT type )
|
|
|
|
{
|
|
|
|
switch ( type )
|
|
|
|
{
|
|
|
|
using namespace ECode;
|
|
|
|
case Class_Body:
|
|
|
|
case Enum_Body:
|
|
|
|
case Export_Body:
|
|
|
|
case Extern_Linkage:
|
|
|
|
case Function_Body:
|
|
|
|
case Global_Body:
|
|
|
|
case Namespace_Body:
|
|
|
|
case Struct_Body:
|
|
|
|
case Union_Body:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
log_failure( "def_body: Invalid type %s", (char const*)ECode::to_str(type) );
|
2024-12-01 21:03:38 -08:00
|
|
|
return (CodeBody)Code_Invalid;
|
2023-08-03 08:01:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Code
|
|
|
|
result = make_code();
|
|
|
|
result->Type = type;
|
|
|
|
return (CodeBody)result;
|
|
|
|
}
|
|
|
|
|
2024-10-24 22:04:17 -07:00
|
|
|
inline
|
2024-10-27 15:58:37 -07:00
|
|
|
StrC token_fmt_impl( ssize num, ... )
|
2023-08-03 08:01:43 -07:00
|
|
|
{
|
|
|
|
local_persist thread_local
|
|
|
|
char buf[GEN_PRINTF_MAXLEN] = { 0 };
|
|
|
|
mem_set( buf, 0, GEN_PRINTF_MAXLEN );
|
|
|
|
|
|
|
|
va_list va;
|
|
|
|
va_start(va, num );
|
2024-10-27 15:58:37 -07:00
|
|
|
ssize result = token_fmt_va(buf, GEN_PRINTF_MAXLEN, num, va);
|
2023-08-03 08:01:43 -07:00
|
|
|
va_end(va);
|
|
|
|
|
|
|
|
return { result, buf };
|
|
|
|
}
|
2024-12-02 07:58:24 -08:00
|
|
|
#pragma endregion Interface
|