/* =====================================
 * Generated by Mod-c 0.26.5
 * MODULE ttype
 * ===================================== */

#include "ttype.h"

void ttype(void);

/**
 * Mod-c
 * By M. Scott Reynolds
 * 20 February 2026
 *
 * type.mc - Basic type representations.
 * 13 May 2026 - Extend for floating-point support.
 */
#include "arena.h"
#include "stddef.h"
#include "stdio.h"
#include "string.h"
#include "stdbool.h"
/**
 * Simple type descriptor (v1 - string-based)
 * Later can become a tagged union with primitive, pointer, record, etc.
 * Future extensions:
 * fields, generics, etc.
 */
/**
 * Shallow arena copy of src.
 */
TType* type_copy_shell(Arena* arena, const TType* src)
{
    TType* t = arena_alloc(arena, ((integer)sizeof(TType)));
    ((*t)).name = ((*src)).name;
    ((*t)).name_len = ((*src)).name_len;
    ((*t)).is_pointer = ((*src)).is_pointer;
    ((*t)).is_array = ((*src)).is_array;
    ((*t)).is_const = ((*src)).is_const;
    ((*t)).is_opaque = ((*src)).is_opaque;
    ((*t)).array_size = ((*src)).array_size;
    ((*t)).size_expr = ((*src)).size_expr;
    ((*t)).element_type = ((*src)).element_type;
    ((*t)).base_type = ((*src)).base_type;
    ((*t)).width = ((*src)).width;
    ((*t)).resolved_type = nil;
    /* return value captured before defers */
    TType* __ret_l70 = t;
    return __ret_l70;
}

/**
 * True for a builtin type spelling (grammar prelude). Case-sensitive: only
 * lowercase spellings are reserved; e.g. String may be a user TYPE name.
 */
bool type_is_builtin_name(const char* name, size_t name_len)
{
    if (name == nil || name_len == 0)
    {
        /* return value captured before defers */
        bool __ret_l81 = false;
        return __ret_l81;
    }
    else if (name_len == 3)
    {
        /* return value captured before defers */
        bool __ret_l83 = memcmp(name, "bit", 3) == 0 || memcmp(name, "int", 3) == 0;
        return __ret_l83;
    }
    else if (name_len == 4)
    {
        /* return value captured before defers */
        bool __ret_l86 = memcmp(name, "bool", 4) == 0 || memcmp(name, "byte", 4) == 0 || memcmp(name, "char", 4) == 0 || memcmp(name, "real", 4) == 0 || memcmp(name, "long", 4) == 0;
        return __ret_l86;
    }
    else if (name_len == 5)
    {
        /* return value captured before defers */
        bool __ret_l92 = memcmp(name, "float", 5) == 0 || memcmp(name, "short", 5) == 0;
        return __ret_l92;
    }
    else if (name_len == 6)
    {
        /* return value captured before defers */
        bool __ret_l95 = memcmp(name, "string", 6) == 0 || memcmp(name, "double", 6) == 0;
        return __ret_l95;
    }
    else if (name_len == 7)
    {
        /* return value captured before defers */
        bool __ret_l98 = memcmp(name, "integer", 7) == 0;
        return __ret_l98;
    }
    else if (name_len == 8)
    {
        /* return value captured before defers */
        bool __ret_l100 = memcmp(name, "cardinal", 8) == 0;
        return __ret_l100;
    }
    else
    {
        /* return value captured before defers */
        bool __ret_l102 = false;
        return __ret_l102;
    }
}

/**
 * Portable names that may be bound once per compilation unit (Language Report 5.5)
 * Not C names -- only integer/ cardinal / real / string.
 */
bool type_is_portable_rebindable(const char* name, size_t name_len)
{
    if (name == nil || name_len == 0)
    {
        /* return value captured before defers */
        bool __ret_l114 = false;
        return __ret_l114;
    }
    else if (name_len == 4)
    {
        /* return value captured before defers */
        bool __ret_l116 = memcmp(name, "real", 4) == 0;
        return __ret_l116;
    }
    else if (name_len == 6)
    {
        /* return value captured before defers */
        bool __ret_l118 = memcmp(name, "string", 6) == 0;
        return __ret_l118;
    }
    else if (name_len == 7)
    {
        /* return value captured before defers */
        bool __ret_l120 = memcmp(name, "integer", 7) == 0;
        return __ret_l120;
    }
    else if (name_len == 8)
    {
        /* return value captured before defers */
        bool __ret_l122 = memcmp(name, "cardinal", 8) == 0;
        return __ret_l122;
    }
    else
    {
        /* return value captured before defers */
        bool __ret_l124 = false;
        return __ret_l124;
    }
}

/**
 * Width constructors: integer N / cardinal n /real N (Langauge Report 10.1).
 */
bool type_is_width_base(const char* name, size_t name_len)
{
    if (name == nil || name_len == 0)
    {
        /* return value captured before defers */
        bool __ret_l136 = false;
        return __ret_l136;
    }
    else if (name_len == 4)
    {
        /* return value captured before defers */
        bool __ret_l138 = memcmp(name, "real", 4) == 0;
        return __ret_l138;
    }
    else if (name_len == 7)
    {
        /* return value captured before defers */
        bool __ret_l140 = memcmp(name, "integer", 7) == 0;
        return __ret_l140;
    }
    else if (name_len == 8)
    {
        /* return value captured before defers */
        bool __ret_l142 = memcmp(name, "cardinal", 8) == 0;
        return __ret_l142;
    }
    else
    {
        /* return value captured before defers */
        bool __ret_l144 = false;
        return __ret_l144;
    }
}

bool type_width_allowed(const char* name, size_t name_len, int n)
{
    if (!type_is_width_base(name, name_len))
    {
        /* return value captured before defers */
        bool __ret_l152 = false;
        return __ret_l152;
    }
    if (name_len == 4)
    {
        /* return value captured before defers */
        bool __ret_l155 = n == 32 || n == 64;
        return __ret_l155;
    }
    /* return value captured before defers */
    bool __ret_l157 = n == 8 || n == 16 || n == 32 || n == 64;
    return __ret_l157;
}

/**
 * C spelling for codegen. Width forms -> stdint / float / double.
 * Unqualified names stay as stored (integer, long long, ...).
 */
bool type_c_spelling(const TType* t, string* out_s, size_t* out_len)
{
    if (t == nil || out_s == nil || out_len == nil)
    {
        /* return value captured before defers */
        bool __ret_l168 = false;
        return __ret_l168;
    }
    if (((*t)).width > 0 && type_is_width_base(((*t)).name, ((*t)).name_len))
    {
        if (((*t)).name_len == 7)
        {
            if (((*t)).width == 8)
            {
                (*out_s) = "int8_t";
                (*out_len) = 6;
            }
            else if (((*t)).width == 16)
            {
                (*out_s) = "int16_t";
                (*out_len) = 7;
            }
            else if (((*t)).width == 32)
            {
                (*out_s) = "int32_t";
                (*out_len) = 7;
            }
            else if (((*t)).width == 64)
            {
                (*out_s) = "int64_t";
                (*out_len) = 7;
            }
            else
            {
                /* return value captured before defers */
                bool __ret_l182 = false;
                return __ret_l182;
            }
            /* return value captured before defers */
            bool __ret_l184 = true;
            return __ret_l184;
        }
        else if (((*t)).name_len == 8)
        {
            if (((*t)).width == 8)
            {
                (*out_s) = "uint8_t";
                (*out_len) = 7;
            }
            else if (((*t)).width == 16)
            {
                (*out_s) = "uint16_t";
                (*out_len) = 8;
            }
            else if (((*t)).width == 32)
            {
                (*out_s) = "uint32_t";
                (*out_len) = 8;
            }
            else if (((*t)).width == 64)
            {
                (*out_s) = "uint64_t";
                (*out_len) = 8;
            }
            else
            {
                /* return value captured before defers */
                bool __ret_l195 = false;
                return __ret_l195;
            }
            /* return value captured before defers */
            bool __ret_l197 = true;
            return __ret_l197;
        }
        else if (((*t)).name_len == 4)
        {
            if (((*t)).width == 32)
            {
                (*out_s) = "float";
                (*out_len) = 5;
            }
            else if (((*t)).width == 64)
            {
                (*out_s) = "double";
                (*out_len) = 6;
            }
            else
            {
                /* return value captured before defers */
                bool __ret_l204 = false;
                return __ret_l204;
            }
            /* return value captured before defers */
            bool __ret_l206 = true;
            return __ret_l206;
        }
        /* return value captured before defers */
        bool __ret_l208 = false;
        return __ret_l208;
    }
    (*out_s) = ((*t)).name;
    (*out_len) = ((*t)).name_len;
    /* return value captured before defers */
    bool __ret_l213 = ((*t)).name != nil && ((*t)).name_len > 0;
    return __ret_l213;
}

/**
 * Create a simple named type (copies name pointer + length)
 * Uses arena for allocation.
 */
TType* type_create_named(Arena* arena, const char* name_start, size_t name_len)
{
    TType* t = arena_alloc(arena, ((integer)sizeof(TType)));
    ((*t)).name = name_start;
    ((*t)).name_len = name_len;
    ((*t)).is_pointer = false;
    ((*t)).is_array = false;
    ((*t)).is_const = false;
    ((*t)).is_opaque = false;
    ((*t)).array_size = 0;
    ((*t)).size_expr = nil;
    ((*t)).element_type = nil;
    ((*t)).base_type = nil;
    ((*t)).resolved_type = nil;
    ((*t)).width = 0;
    /* return value captured before defers */
    TType* __ret_l245 = t;
    return __ret_l245;
}

/**
 * Create an array type (array_of_T or fixed-size).
 */
TType* type_create_array(Arena* arena, TType* element, size_t fixed_size)
{
    TType* t = arena_alloc(arena, ((integer)sizeof(TType)));
    ((*t)).is_array = true;
    ((*t)).array_size = fixed_size;
    ((*t)).size_expr = nil;
    ((*t)).element_type = element;
    ((*t)).is_const = (element ? ((*element)).is_const : false);
    ((*t)).is_opaque = false;
    ((*t)).base_type = nil;
    ((*t)).resolved_type = nil;
    /* return value captured before defers */
    TType* __ret_l267 = t;
    return __ret_l267;
}

/**
 * Create a fixed array whose size is a const-expression (folded in semantic).
 * size_expr is a Node* stored as ^void (avoids ttype <==> node import cycle).
 */
TType* type_create_array_expr(Arena* arena, TType* element, pvoid size_expr)
{
    TType* t = arena_alloc(arena, ((integer)sizeof(TType)));
    ((*t)).is_array = true;
    ((*t)).array_size = 0;
    ((*t)).size_expr = size_expr;
    ((*t)).element_type = element;
    ((*t)).is_const = (element ? ((*element)).is_const : false);
    ((*t)).is_opaque = false;
    ((*t)).base_type = nil;
    ((*t)).resolved_type = nil;
    /* return value captured before defers */
    TType* __ret_l289 = t;
    return __ret_l289;
}

/**
 * Create opaque
 */
TType* type_create_opaque(Arena* arena)
{
    assert(arena != nil); /* precondition */
    TType* t = arena_alloc(arena, ((integer)sizeof(TType)));
    ((*t)).is_opaque = true;
    /* return value captured before defers */
    TType* __ret_l305 = t;
    return __ret_l305;
}

/**
 * Compare two types (name + structure).
 */
bool type_equals(const TType* a, const TType* b)
{
    if (a == b)
    {
        /* return value captured before defers */
        bool __ret_l316 = true;
        return __ret_l316;
    }
    else if (a == nil || b == nil)
    {
        /* return value captured before defers */
        bool __ret_l318 = false;
        return __ret_l318;
    }
    else if (((*a)).is_pointer != ((*b)).is_pointer)
    {
        /* return value captured before defers */
        bool __ret_l320 = false;
        return __ret_l320;
    }
    else if (((*a)).is_const != ((*b)).is_const)
    {
        /* return value captured before defers */
        bool __ret_l322 = false;
        return __ret_l322;
    }
    else if (((*a)).is_opaque != ((*b)).is_opaque)
    {
        /* return value captured before defers */
        bool __ret_l324 = false;
        return __ret_l324;
    }
    else if (((*a)).is_array != ((*b)).is_array)
    {
        /* return value captured before defers */
        bool __ret_l326 = false;
        return __ret_l326;
    }
    else if (((*a)).is_array)
    {
        if (((*a)).size_expr != nil || ((*b)).size_expr != nil)
        {
            /* return value captured before defers */
            bool __ret_l330 = false;
            return __ret_l330;
        }
        if (((*a)).array_size != ((*b)).array_size)
        {
            /* return value captured before defers */
            bool __ret_l333 = false;
            return __ret_l333;
        }
        else
        {
            /* return value captured before defers */
            bool __ret_l335 = type_equals(((*a)).element_type, ((*b)).element_type);
            return __ret_l335;
        }
    }
    if (((*a)).name_len != ((*b)).name_len)
    {
        /* return value captured before defers */
        bool __ret_l340 = false;
        return __ret_l340;
    }
    if (((*a)).width != ((*b)).width)
    {
        /* return value captured before defers */
        bool __ret_l343 = false;
        return __ret_l343;
    }
    /* return value captured before defers */
    bool __ret_l345 = memcmp(((*a)).name, ((*b)).name, ((*a)).name_len) == 0;
    return __ret_l345;
}

/**
 * Print type
 */
void type_print(const TType* t)
{
    if (t == nil)
    {
        printf("(unknown)");
                return;
    }
    if (((*t)).is_const)
    {
        printf("CONST ");
    }
    if (((*t)).is_pointer)
    {
        printf("^");
    }
    if (((*t)).is_opaque)
    {
        printf("OPAQUE ");
    }
    if (((*t)).is_array)
    {
        printf("ARRAY");
        if (((*t)).size_expr != nil)
        {
            printf("[...]");
        }
        else if (((*t)).array_size > 0)
        {
            printf("[%zu]", ((*t)).array_size);
        }
        printf(" OF ");
        type_print(((*t)).element_type);
    }
    else if (((*t)).name != nil)
    {
        printf("%.*s", (int)((*t)).name_len, ((*t)).name);
        if (((*t)).width > 0)
        {
            printf(" %d", ((*t)).width);
        }
    }
    if (((*t)).resolved_type != nil)
    {
        printf(" => ");
        type_print(((*t)).resolved_type);
    }
}


void ttype(void)
{
}
