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

#include "semantic.h"

void semantic(void);

/**
 * semantic.mc - Semantic analysis pass (phase 1: declaration collection).
 *
 * Walks the AST, builds scoped symbol tables, detects duplicate names.
 * Expression type-checking and const-expressions enforcement come later.
 */
#include "arena.h"
#include "symbol.h"
#include "symtab.h"
#include "mh_reader.h"
#include "symkind.h"
#include "ttype.h"
#include "stddef.h"
#include "string.h"
#include "stdlib.h"
#include "strings.h"
#include "stdio.h"
#include "Lexer.h"
#include "node.h"
static const cardinal SEMANTIC_MH_PATH_MAX = 4096u;
/** Analysis context */
typedef struct TProcSymName TProcSymName;
typedef struct TProcSymName {
    const char* name;
    size_t length;
} TProcSymName;
typedef const char* pcchar;
static pTType semantic_type_of_designator(pTSemanticContext ctx, pNode n);
static pTType semantic_type_of_expr(pTSemanticContext ctx, pNode n);
static integer semantic_eval_const_expr(pTSemanticContext ctx, pNode n);
static bool semantic_try_eval_const_expr(pTSemanticContext ctx, pNode n, integer* out_val, pcchar* msg);
static void semantic_resolve_expr(pTSemanticContext ctx, pNode n);
static void semantic_analyze_block_body(pTSemanticContext ctx, pNode block);
static char* semantic_mangle_method(Arena* arena, const char* owner, size_t owner_len, const char* method, size_t method_len);
static TProcSymName semantic_proc_sym_name(pTSemanticContext ctx, pNode decl);
static bool semantic_method_is_instance(pTSemanticContext ctx, pNode decl);
static void semantic_verify_method_self(pTSemanticContext ctx, pNode decl);
static pNode semantic_method_type_node(pTSemanticContext ctx, pTType ty);
static pTType semantic_field_type_on(pTSemanticContext ctx, pTType recv_ty, const char* fname, size_t flen);
static bool semantic_sym_is_method_value(pTSemanticContext ctx, pTSymbol sym);
/**
* Fatal semantic error with source location from the node's token.
*/
void semantic_error_at(pNode n, const char* msg)
{
    if (n != nil)
    {
        node_print(n, 0);
        fprintf(stderr, "ERROR: line %d col %d: %s\n", (((*n)).token).line, (((*n)).token).column, msg);
    }
    else
    {
        fprintf(stderr, "ERROR: %s\n", msg);
    }
    exit(1);
}

/**
 * Merge use-site qualifiers (^ / CONST) onto an already-resolved base type.
 */
static pTType type_apply_use_qualifiers(pTSemanticContext ctx, pTType use_ty, pTType resolved_base)
{
    pTType result = nil;
    if (resolved_base == nil)
    {
        /* return value captured before defers */
        pTType __ret_l129 = nil;
        return __ret_l129;
    }
    result = type_copy_shell(((*ctx)).arena, resolved_base);
    if (use_ty != nil && ((*use_ty)).is_const)
    {
        ((*result)).is_const = true;
    }
    if (use_ty != nil && ((*use_ty)).is_pointer)
    {
        ((*result)).is_pointer = true;
    }
    /* return value captured before defers */
    pTType __ret_l142 = result;
    return __ret_l142;
}

/**
 * Resolve type TType tree to its concrete form; return a new TType copy.
 * at = AST node for error location (may be nil).
 */
static pTType semantic_resolve_type_inner(pTSemanticContext ctx, pTType ty, size_t depth, pNode at)
{
    pTType elem = nil;
    pTType result = nil;
    pTSymbol sym = nil;
    pTType base = nil;
    pTType resolved_base = nil;
    if (ty == nil)
    {
        /* return value captured before defers */
        pTType __ret_l159 = nil;
        return __ret_l159;
    }
    if (depth > 64)
    {
        semantic_error_at(at, "semantic_resolve_type_inner: cicular type alias");
    }
    if (((*ty)).is_array && ((*ty)).element_type != nil)
    {
        elem = semantic_resolve_type_inner(ctx, ((*ty)).element_type, depth, at);
        if (((*ty)).size_expr != nil)
        {
            integer sz = 0;
            sz = semantic_eval_const_expr(ctx, (pNode)((*ty)).size_expr);
            if (sz < 0)
            {
                semantic_error_at(at, "semantic_resolve_type_inner: array size must be non-negative");
            }
            ((*ty)).array_size = (size_t)sz;
            ((*ty)).size_expr = nil;
        }
        result = type_copy_shell(((*ctx)).arena, ty);
        ((*result)).element_type = elem;
        /* return value captured before defers */
        pTType __ret_l190 = result;
        return __ret_l190;
    }
    if (((*ty)).name != nil && ((*ty)).name_len > 0 && !type_is_builtin_name(((*ty)).name, ((*ty)).name_len))
    {
        sym = symtab_lookup(((*ctx)).scope, ((*ty)).name, ((*ty)).name_len);
        if (sym == nil)
        {
            size_t i = 0;
            bool is_compound = false;
            while (i < ((*ty)).name_len)
            {
                {
                    if (((*ty)).name[i] == ' ')
                    {
                        is_compound = true;
                                                /* INVARIANT (on loop exit) */
                        break;
                    }
                    i = i + 1;
                }
            }
            if (!is_compound)
            {
                semantic_error_at(at, "semantic_resolve_type_inner: unknown type");
            }
            /* return value captured before defers */
            pTType __ret_l218 = type_copy_shell(((*ctx)).arena, ty);
            return __ret_l218;
        }
        else if (((*sym)).kind != SYM_KIND_TYPE)
        {
            if (((*sym)).kind == SYM_KIND_IMPORT)
            {
                /* return value captured before defers */
                pTType __ret_l221 = type_copy_shell(((*ctx)).arena, ty);
                return __ret_l221;
            }
            semantic_error_at(at, "semantic_resolve_type_inner: identifier is not a type");
        }
        if (((*sym)).decl != nil && ((*((*sym)).decl)).kind == NODE_TYPE_DECL)
        {
            if ((((*((*sym)).decl)).type_decl).is_forward || (((*((*sym)).decl)).type_decl).struct_body != nil || (((*((*sym)).decl)).type_decl).method_type != nil || (((*((*sym)).decl)).type_decl).enum_type != nil)
            {
                resolved_base = type_create_named(((*ctx)).arena, ((*sym)).name, ((*sym)).name_len);
                /* return value captured before defers */
                pTType __ret_l233 = type_apply_use_qualifiers(ctx, ty, resolved_base);
                return __ret_l233;
            }
        }
        if (((*sym)).decl != nil && ((*((*sym)).decl)).kind == NODE_IMPORT_ITEM)
        {
            resolved_base = type_create_named(((*ctx)).arena, ((*sym)).name, ((*sym)).name_len);
            /* return value captured before defers */
            pTType __ret_l240 = type_apply_use_qualifiers(ctx, ty, resolved_base);
            return __ret_l240;
        }
        base = ((*sym)).symbol_type;
        if (base == nil)
        {
            if (((*sym)).decl != nil && ((*((*sym)).decl)).kind == NODE_TYPE_DECL && (((*((*sym)).decl)).type_decl).is_extern)
            {
                resolved_base = type_create_named(((*ctx)).arena, ((*sym)).name, ((*sym)).name_len);
                /* return value captured before defers */
                pTType __ret_l248 = type_apply_use_qualifiers(ctx, ty, resolved_base);
                return __ret_l248;
            }
            semantic_error_at(at, "semantic_resolve_type_inner: TYPE has no defined_type");
        }
        resolved_base = semantic_resolve_type_inner(ctx, base, depth + 1, at);
        /* return value captured before defers */
        pTType __ret_l258 = type_apply_use_qualifiers(ctx, ty, resolved_base);
        return __ret_l258;
    }
    /* return value captured before defers */
    pTType __ret_l264 = type_copy_shell(((*ctx)).arena, ty);
    return __ret_l264;
}

/**
 * Resolve ty in place; sets ty^.resolved_type (idempotent).
 */
static void semantic_resolve_type(pTSemanticContext ctx, pTType ty, pNode at)
{
    if (ty == nil)
    {
                return;
    }
    if (((*ty)).resolved_type != nil)
    {
                return;
    }
    ((*ty)).resolved_type = semantic_resolve_type_inner(ctx, ty, 0, at);
}

/**
 * Name equality (reuse enum style)
 */
static bool semantic_names_equal(const char* a, size_t a_len, const char* b, size_t b_len)
{
    if (a == nil || b == nil || a_len != b_len)
    {
        /* return value captured before defers */
        bool __ret_l291 = false;
        return __ret_l291;
    }
    /* return value captured before defers */
    bool __ret_l293 = memcmp(a, b, a_len) == 0;
    return __ret_l293;
}

/**
 * Struct body for a type name
 */
static pNode semantic_struct_body_named(pTSemanticContext ctx, const char* name, size_t name_len)
{
    pTSymbol sym = nil;
    if (ctx == nil || name == nil || name_len == 0)
    {
        /* return value captured before defers */
        pNode __ret_l305 = nil;
        return __ret_l305;
    }
    sym = symtab_lookup(((*ctx)).scope, name, name_len);
    if (sym == nil || ((*sym)).kind != SYM_KIND_TYPE || ((*sym)).decl == nil)
    {
        /* return value captured before defers */
        pNode __ret_l309 = nil;
        return __ret_l309;
    }
    if (((*((*sym)).decl)).kind != NODE_TYPE_DECL)
    {
        /* return value captured before defers */
        pNode __ret_l312 = nil;
        return __ret_l312;
    }
    /* return value captured before defers */
    pNode __ret_l314 = (((*((*sym)).decl)).type_decl).struct_body;
    return __ret_l314;
}

/**
 * Strip pointer layers (for ^Child formals later; harmless now)
 */
/**
 * Struct body of type 
 */
static pNode semantic_struct_body_of_type(pTSemanticContext ctx, pTType body_type)
{
    pTType ty = body_type;
    if (ty == nil)
    {
        /* return value captured before defers */
        pNode __ret_l348 = nil;
        return __ret_l348;
    }
    if (((*ty)).resolved_type != nil)
    {
        ty = ((*ty)).resolved_type;
    }
    if (((*ty)).name == nil || ((*ty)).name_len == 0)
    {
        /* return value captured before defers */
        pNode __ret_l356 = nil;
        return __ret_l356;
    }
    /* return value captured before defers */
    pNode __ret_l358 = semantic_struct_body_named(ctx, ((*ty)).name, ((*ty)).name_len);
    return __ret_l358;
}

/**
 * By-value EXTENDS upcast distance.
 * Returns N >= 1 if *actual* may be used where *expected is required by
 * walking N synthetic ".base" members (option A layout).
 * Returns 0 if same type, not both named structs, pointer/array, or not an ancestor.
 */
static size_t semantic_extends_upcast_depth(pTSemanticContext ctx, pTType actual_type, pTType expected_type)
{
    pNode st = nil;
    size_t depth = 0;
    pTType parent_ty = nil;
    pTType actual = actual_type;
    pTType expected = expected_type;
    if (ctx == nil || actual == nil || expected == nil)
    {
        /* return value captured before defers */
        size_t __ret_l377 = 0;
        return __ret_l377;
    }
    if (((*actual)).resolved_type != nil)
    {
        actual = ((*actual)).resolved_type;
    }
    if (((*expected)).resolved_type != nil)
    {
        expected = ((*expected)).resolved_type;
    }
    if (((*actual)).is_pointer != ((*expected)).is_pointer)
    {
        /* return value captured before defers */
        size_t __ret_l389 = 0;
        return __ret_l389;
    }
    if (((*actual)).is_array || ((*expected)).is_array)
    {
        /* return value captured before defers */
        size_t __ret_l392 = 0;
        return __ret_l392;
    }
    if (((*actual)).name == nil || ((*actual)).name_len == 0)
    {
        /* return value captured before defers */
        size_t __ret_l395 = 0;
        return __ret_l395;
    }
    if (((*expected)).name == nil || ((*expected)).name_len == 0)
    {
        /* return value captured before defers */
        size_t __ret_l398 = 0;
        return __ret_l398;
    }
    if (semantic_names_equal(((*actual)).name, ((*actual)).name_len, ((*expected)).name, ((*expected)).name_len))
    {
        /* return value captured before defers */
        size_t __ret_l402 = 0;
        return __ret_l402;
    }
    st = semantic_struct_body_of_type(ctx, actual);
    if (st == nil)
    {
        /* return value captured before defers */
        size_t __ret_l406 = 0;
        return __ret_l406;
    }
    depth = 0;
    while (st != nil && (((*st)).struct_decl).extends_type != nil)
    {
        {
            parent_ty = (((*st)).struct_decl).extends_type;
            depth = depth + 1;
            if (((*parent_ty)).name != nil && semantic_names_equal(((*parent_ty)).name, ((*parent_ty)).name_len, ((*expected)).name, ((*expected)).name_len))
            {
                /* return value captured before defers */
                size_t __ret_l414 = depth;
                return __ret_l414;
            }
            st = semantic_struct_body_of_type(ctx, parent_ty);
        }
    }
    /* return value captured before defers */
    size_t __ret_l418 = 0;
    return __ret_l418;
}

/**
 * If expr's type exrends expected, record upcast_depth on *expr* for codegen.
 * Does not error on mismatch (assignability still soft elsewhere).
 */
static void semantic_maybe_upcast(pTSemanticContext ctx, pNode expr, pTType expected)
{
    pTType actual = nil;
    size_t d = 0;
    if (ctx == nil || expr == nil || expected == nil)
    {
                return;
    }
    actual = semantic_type_of_expr(ctx, expr);
    if (actual == nil)
    {
                return;
    }
    d = semantic_extends_upcast_depth(ctx, actual, expected);
    if (d > 0)
    {
        ((*expr)).upcast_depth = d;
        ((*expr)).upcast_ptr = ((*actual)).is_pointer;
    }
}

/**
 * Pointer at the use type or its resolved_type. Do not chase first
 * (^Child would become Child).
 */
static bool semantic_type_is_pointer(pTType ty)
{
    if (ty == nil)
    {
        /* return value captured before defers */
        bool __ret_l453 = false;
        return __ret_l453;
    }
    if (((*ty)).is_pointer)
    {
        /* return value captured before defers */
        bool __ret_l456 = true;
        return __ret_l456;
    }
    if (((*ty)).resolved_type != nil && ((*((*ty)).resolved_type)).is_pointer)
    {
        /* return value captured before defers */
        bool __ret_l459 = true;
        return __ret_l459;
    }
    /* return value captured before defers */
    bool __ret_l461 = false;
    return __ret_l461;
}

/**
 * Pointer-to-array (Oberon p[i] peel). Not array-of-pointer (^char[] argv).
 */
static bool semantic_type_is_pointer_to_array(pTType ty)
{
    pTType t = ty;
    if (t == nil)
    {
        /* return value captured before defers */
        bool __ret_l473 = false;
        return __ret_l473;
    }
    if (!((*t)).is_pointer)
    {
        if (((*t)).resolved_type == nil || !((*((*t)).resolved_type)).is_pointer)
        {
            /* return value captured before defers */
            bool __ret_l477 = false;
            return __ret_l477;
        }
        t = ((*t)).resolved_type;
    }
    if (((*t)).is_array)
    {
        /* return value captured before defers */
        bool __ret_l482 = true;
        return __ret_l482;
    }
    if (((*t)).resolved_type != nil && ((*((*t)).resolved_type)).is_array)
    {
        /* return value captured before defers */
        bool __ret_l485 = true;
        return __ret_l485;
    }
    /* return value captured before defers */
    bool __ret_l487 = false;
    return __ret_l487;
}

/**
 * Designator type
 */
static pTType semantic_type_of_designator(pTSemanticContext ctx, pNode n)
{
    pTSymbol sym = nil;
    pNode st = nil;
    size_t i = 0;
    pNode f = nil;
    pTType ety = nil;
    if (n == nil)
    {
        /* return value captured before defers */
        pTType __ret_l503 = nil;
        return __ret_l503;
    }
    switch (((*n)).kind)
    {
        case NODE_PAREN:
        {
            /* return value captured before defers */
            pTType __ret_l508 = semantic_type_of_designator(ctx, (((*n)).paren).expr);
            return __ret_l508;
        }
        break;
        case NODE_IDENT:
        {
            sym = ((*n)).resolved_sym;
            if (sym == nil)
            {
                /* return value captured before defers */
                pTType __ret_l513 = nil;
                return __ret_l513;
            }
            /* return value captured before defers */
            pTType __ret_l515 = ((*sym)).symbol_type;
            return __ret_l515;
        }
        break;
        case NODE_FIELD_ACCESS:
        {
            ety = semantic_type_of_designator(ctx, (((*n)).field_access).record_);
            st = semantic_struct_body_of_type(ctx, ety);
            if (st == nil)
            {
                /* return value captured before defers */
                pTType __ret_l524 = nil;
                return __ret_l524;
            }
            if (semantic_names_equal((((*n)).field_access).field_name, (((*n)).field_access).field_len, "base", 4))
            {
                if ((((*st)).struct_decl).extends_type != nil)
                {
                    /* return value captured before defers */
                    pTType __ret_l529 = (((*st)).struct_decl).extends_type;
                    return __ret_l529;
                }
            }
            while (st != nil)
            {
                {
                    {
                        const long long __for_end_l534 = (long long)((((*st)).struct_decl).field_count);
                        for (i = 1; (long long)(i) <= __for_end_l534; i++)
                        {
                            {
                                f = (((*st)).struct_decl).fields[i - 1];
                                if (f != nil && semantic_names_equal((((*f)).field_decl).name, (((*f)).field_decl).name_len, (((*n)).field_access).field_name, (((*n)).field_access).field_len))
                                {
                                    /* return value captured before defers */
                                    pTType __ret_l538 = (((*f)).field_decl).field_type;
                                    return __ret_l538;
                                }
                            }
                        }
                    }
                    if ((((*st)).struct_decl).extends_type == nil)
                    {
                        /* return value captured before defers */
                        pTType __ret_l542 = nil;
                        return __ret_l542;
                    }
                    st = semantic_struct_body_of_type(ctx, (((*st)).struct_decl).extends_type);
                }
            }
            /* return value captured before defers */
            pTType __ret_l546 = nil;
            return __ret_l546;
        }
        break;
        case NODE_ARRAY_INDEX:
        {
            ety = semantic_type_of_designator(ctx, (((*n)).array_index).array_);
            if (ety == nil)
            {
                /* return value captured before defers */
                pTType __ret_l551 = nil;
                return __ret_l551;
            }
            if (((*ety)).resolved_type != nil)
            {
                ety = ((*ety)).resolved_type;
            }
            if (((*ety)).is_array && ((*ety)).element_type != nil)
            {
                /* return value captured before defers */
                pTType __ret_l557 = ((*ety)).element_type;
                return __ret_l557;
            }
            /* return value captured before defers */
            pTType __ret_l559 = nil;
            return __ret_l559;
        }
        break;
        case NODE_UNARY:
        {
            if ((((*n)).unary).op == TOK_CARET)
            {
                /* return value captured before defers */
                pTType __ret_l564 = semantic_type_of_expr(ctx, n);
                return __ret_l564;
            }
            /* return value captured before defers */
            pTType __ret_l566 = nil;
            return __ret_l566;
        }
        break;
        case NODE_CAST:
        {
            /* return value captured before defers */
            pTType __ret_l569 = semantic_type_of_expr(ctx, n);
            return __ret_l569;
        }
        break;
        default:
        {
            /* return value captured before defers */
            pTType __ret_l572 = nil;
            return __ret_l572;
        }
        break;
    }
}

/**
 * True if ty is a named type with the given spelling.
 */
static bool semantic_type_name_is(pTType ty, const char* name, size_t name_len)
{
    if (ty == nil || name == nil || ((*ty)).name == nil)
    {
        /* return value captured before defers */
        bool __ret_l583 = false;
        return __ret_l583;
    }
    if (((*ty)).is_pointer || ((*ty)).is_array)
    {
        /* return value captured before defers */
        bool __ret_l586 = false;
        return __ret_l586;
    }
    if (((*ty)).name_len != name_len)
    {
        /* return value captured before defers */
        bool __ret_l589 = false;
        return __ret_l589;
    }
    /* return value captured before defers */
    bool __ret_l591 = memcmp(((*ty)).name, name, name_len) == 0;
    return __ret_l591;
}

/**
 * Everyday integer-ish names for thin binary/unary typing (not full promotion).
 */
static bool semantic_type_is_integerish(pTType param_type)
{
    pTType ty = param_type;
    if (ty == nil)
    {
        /* return value captured before defers */
        bool __ret_l603 = false;
        return __ret_l603;
    }
    if (((*ty)).resolved_type != nil)
    {
        ty = ((*ty)).resolved_type;
    }
    /* return value captured before defers */
    bool __ret_l608 = semantic_type_name_is(ty, "integer", 7) || semantic_type_name_is(ty, "int", 3) || semantic_type_name_is(ty, "cardinal", 8);
    return __ret_l608;
}

static bool semantic_type_is_realish(pTType param_type)
{
    pTType ty = param_type;
    if (ty == nil)
    {
        /* return value captured before defers */
        bool __ret_l619 = false;
        return __ret_l619;
    }
    if (((*ty)).resolved_type != nil)
    {
        ty = ((*ty)).resolved_type;
    }
    /* return value captured before defers */
    bool __ret_l624 = semantic_type_name_is(ty, "real", 4) || semantic_type_name_is(ty, "float", 5) || semantic_type_name_is(ty, "double", 6);
    return __ret_l624;
}

/**
 * Thin expression typing (item 21a). Not full type-checking.
 * Returns a type descriptor or nil when unknown.
 * Prerequisite: semantic_resolve_expr has been run on n when idents/calls matter.
 */
static pTType semantic_type_of_expr(pTSemanticContext ctx, pNode n)
{
    pTSymbol sym = nil;
    if (n == nil)
    {
        /* return value captured before defers */
        pTType __ret_l642 = nil;
        return __ret_l642;
    }
    switch (((*n)).kind)
    {
        case NODE_PAREN:
        {
            /* return value captured before defers */
            pTType __ret_l647 = semantic_type_of_expr(ctx, (((*n)).paren).expr);
            return __ret_l647;
        }
        break;
        case NODE_IDENT:
        case NODE_FIELD_ACCESS:
        case NODE_ARRAY_INDEX:
        {
            /* return value captured before defers */
            pTType __ret_l650 = semantic_type_of_designator(ctx, n);
            return __ret_l650;
        }
        break;
        case NODE_LITERAL:
        {
            if ((((*n)).token).kind == TOK_NUMBER)
            {
                /* return value captured before defers */
                pTType __ret_l654 = type_create_named(((*ctx)).arena, "integer", 7);
                return __ret_l654;
            }
            else if ((((*n)).token).kind == TOK_REAL)
            {
                /* return value captured before defers */
                pTType __ret_l656 = type_create_named(((*ctx)).arena, "real", 4);
                return __ret_l656;
            }
            else if ((((*n)).token).kind == TOK_CHAR)
            {
                /* return value captured before defers */
                pTType __ret_l658 = type_create_named(((*ctx)).arena, "char", 4);
                return __ret_l658;
            }
            else if ((((*n)).token).kind == TOK_STRING)
            {
                /* return value captured before defers */
                pTType __ret_l660 = type_create_named(((*ctx)).arena, "string", 6);
                return __ret_l660;
            }
            else
            {
                /* return value captured before defers */
                pTType __ret_l662 = nil;
                return __ret_l662;
            }
        }
        break;
        case NODE_CAST:
        {
            /* return value captured before defers */
            pTType __ret_l666 = (((*n)).cast_expr).target_type;
            return __ret_l666;
        }
        break;
        case NODE_SIZEOF:
        {
            /* return value captured before defers */
            pTType __ret_l669 = type_create_named(((*ctx)).arena, "integer", 7);
            return __ret_l669;
        }
        break;
        case NODE_CALL:
        {
            if ((((*n)).call).callee_expr != nil)
            {
                pTType cty = nil;
                pNode mtn = nil;
                cty = semantic_type_of_expr(ctx, (((*n)).call).callee_expr);
                mtn = semantic_method_type_node(ctx, cty);
                if (mtn != nil && (((*mtn)).method_type).return_type != nil)
                {
                    /* return value captured before defers */
                    pTType __ret_l680 = (((*mtn)).method_type).return_type;
                    return __ret_l680;
                }
                /* return value captured before defers */
                pTType __ret_l682 = nil;
                return __ret_l682;
            }
            sym = ((*n)).resolved_sym;
            if (sym == nil)
            {
                /* return value captured before defers */
                pTType __ret_l687 = nil;
                return __ret_l687;
            }
            if (((*sym)).kind == SYM_KIND_FUNC)
            {
                /* return value captured before defers */
                pTType __ret_l690 = ((*sym)).symbol_type;
                return __ret_l690;
            }
            if (semantic_sym_is_method_value(ctx, sym))
            {
                {
                    pNode mtn2 = nil;
                    mtn2 = semantic_method_type_node(ctx, ((*sym)).symbol_type);
                    if (mtn2 != nil && (((*mtn2)).method_type).return_type != nil)
                    {
                        /* return value captured before defers */
                        pTType __ret_l699 = (((*mtn2)).method_type).return_type;
                        return __ret_l699;
                    }
                    /* return value captured before defers */
                    pTType __ret_l701 = nil;
                    return __ret_l701;
                }
            }
            if (((*sym)).kind == SYM_KIND_IMPORT && ((*sym)).symbol_type != nil)
            {
                /* return value captured before defers */
                pTType __ret_l706 = ((*sym)).symbol_type;
                return __ret_l706;
            }
            if (((*sym)).decl != nil && ((*((*sym)).decl)).kind == NODE_FUNC_DECL)
            {
                /* return value captured before defers */
                pTType __ret_l709 = (((*((*sym)).decl)).proc_decl).return_type;
                return __ret_l709;
            }
            /* return value captured before defers */
            pTType __ret_l711 = nil;
            return __ret_l711;
        }
        break;
        case NODE_UNARY:
        {
            if ((((*n)).unary).op == TOK_SUB || (((*n)).unary).op == TOK_KEYWORD_NOT || (((*n)).unary).op == TOK_BITWISE_NOT)
            {
                /* return value captured before defers */
                pTType __ret_l719 = semantic_type_of_expr(ctx, (((*n)).unary).operand);
                return __ret_l719;
            }
            else if ((((*n)).unary).op == TOK_AT)
            {
                {
                    pTType base = nil;
                    pTType ptr = nil;
                    base = semantic_type_of_expr(ctx, (((*n)).unary).operand);
                    if (base == nil)
                    {
                        /* return value captured before defers */
                        pTType __ret_l727 = nil;
                        return __ret_l727;
                    }
                    ptr = type_copy_shell(((*ctx)).arena, base);
                    ((*ptr)).is_pointer = true;
                    /* return value captured before defers */
                    pTType __ret_l731 = ptr;
                    return __ret_l731;
                }
            }
            else if ((((*n)).unary).op == TOK_CARET)
            {
                {
                    pTType ptr = nil;
                    pTType base = nil;
                    ptr = semantic_type_of_expr(ctx, (((*n)).unary).operand);
                    if (ptr == nil)
                    {
                        /* return value captured before defers */
                        pTType __ret_l740 = nil;
                        return __ret_l740;
                    }
                    if (((*ptr)).resolved_type != nil)
                    {
                        ptr = ((*ptr)).resolved_type;
                    }
                    if (!((*ptr)).is_pointer)
                    {
                        /* return value captured before defers */
                        pTType __ret_l746 = nil;
                        return __ret_l746;
                    }
                    base = type_copy_shell(((*ctx)).arena, ptr);
                    ((*base)).is_pointer = false;
                    /* return value captured before defers */
                    pTType __ret_l750 = base;
                    return __ret_l750;
                }
            }
            /* return value captured before defers */
            pTType __ret_l753 = nil;
            return __ret_l753;
        }
        break;
        case NODE_BINARY:
        {
            {
                pTType lt = nil;
                pTType rt = nil;
                TokenKind op = {0};
                lt = semantic_type_of_expr(ctx, (((*n)).binary).left);
                rt = semantic_type_of_expr(ctx, (((*n)).binary).right);
                op = (((*n)).binary).op;
                if (op == TOK_EQ_EQ || op == TOK_NOT_EQ || op == TOK_LESS || op == TOK_LESS_EQ || op == TOK_GREATER || op == TOK_GREATER_EQ)
                {
                    if (lt != nil && rt != nil)
                    {
                        /* return value captured before defers */
                        pTType __ret_l769 = type_create_named(((*ctx)).arena, "bool", 4);
                        return __ret_l769;
                    }
                    /* return value captured before defers */
                    pTType __ret_l771 = nil;
                    return __ret_l771;
                }
                if (semantic_type_is_integerish(lt) && semantic_type_is_integerish(rt))
                {
                    if (op == TOK_ADD || op == TOK_SUB || op == TOK_MUL || op == TOK_DIV || op == TOK_MOD || op == TOK_KEYWORD_MOD || op == TOK_KEYWORD_DIV || op == TOK_POWER || op == TOK_BITWISE_AND || op == TOK_BITWISE_OR || op == TOK_KEYWORD_XOR || op == TOK_KEYWORD_AND || op == TOK_KEYWORD_OR || op == TOK_BITWISE_LSHIFT || op == TOK_BITWISE_RSHIFT)
                    {
                        /* return value captured before defers */
                        pTType __ret_l781 = type_create_named(((*ctx)).arena, "integer", 7);
                        return __ret_l781;
                    }
                }
                if (semantic_type_is_realish(lt) && semantic_type_is_realish(rt))
                {
                    if (op == TOK_ADD || op == TOK_SUB || op == TOK_MUL || op == TOK_DIV)
                    {
                        /* return value captured before defers */
                        pTType __ret_l788 = type_create_named(((*ctx)).arena, "real", 4);
                        return __ret_l788;
                    }
                }
                /* return value captured before defers */
                pTType __ret_l792 = nil;
                return __ret_l792;
            }
        }
        break;
        case NODE_TERNARY:
        case NODE_ARRAY_LITERAL:
        {
            /* return value captured before defers */
            pTType __ret_l797 = nil;
            return __ret_l797;
        }
        break;
        default:
        {
            /* return value captured before defers */
            pTType __ret_l800 = nil;
            return __ret_l800;
        }
        break;
    }
}

/**
 * Find field => set base_depth
 * Returns true if found; out_depth = # of .base prefixes before field_name
 */
static bool semantic_find_field_depth(pTSemanticContext ctx, pNode sem_type, const char* name, size_t name_len, size_t* out_depth)
{
    size_t depth = 0;
    size_t i = 0;
    pNode f = nil;
    pNode parent = nil;
    pNode st = sem_type;
    if (st == nil || name == nil || name_len == 0 || out_depth == nil)
    {
        /* return value captured before defers */
        bool __ret_l819 = false;
        return __ret_l819;
    }
    while (st != nil)
    {
        {
            if (depth == 0 && (((*st)).struct_decl).extends_type != nil && semantic_names_equal(name, name_len, "base", 4))
            {
                (*out_depth) = 0;
                /* return value captured before defers */
                bool __ret_l827 = true;
                return __ret_l827;
            }
            {
                const long long __for_end_l830 = (long long)((((*st)).struct_decl).field_count);
                for (i = 1; (long long)(i) <= __for_end_l830; i++)
                {
                    {
                        f = (((*st)).struct_decl).fields[i - 1];
                        if (f != nil && semantic_names_equal((((*f)).field_decl).name, (((*f)).field_decl).name_len, name, name_len))
                        {
                            (*out_depth) = depth;
                            /* return value captured before defers */
                            bool __ret_l834 = true;
                            return __ret_l834;
                        }
                    }
                }
            }
            if ((((*st)).struct_decl).extends_type == nil)
            {
                /* return value captured before defers */
                bool __ret_l839 = false;
                return __ret_l839;
            }
            parent = semantic_struct_body_of_type(ctx, (((*st)).struct_decl).extends_type);
            if (parent == nil)
            {
                /* return value captured before defers */
                bool __ret_l843 = false;
                return __ret_l843;
            }
            st = parent;
            depth = depth + 1;
        }
    }
    /* return value captured before defers */
    bool __ret_l848 = false;
    return __ret_l848;
}

/**
 * Check extends clashes
 */
static void semantic_check_extends_clashes(pTSemanticContext ctx, pNode st, pNode at)
{
    size_t i = 0;
    size_t j = 0;
    pNode f = nil;
    pNode g = nil;
    pNode anc = nil;
    size_t depth = 0;
    if (st == nil)
    {
                return;
    }
    {
        const long long __for_end_l869 = (long long)((((*st)).struct_decl).field_count);
        for (i = 1; (long long)(i) <= __for_end_l869; i++)
        {
            {
                f = (((*st)).struct_decl).fields[i - 1];
                if (f == nil)
                {
                                        /* INVARIANT (on loop exit) */
                    continue;
                }
                {
                    const long long __for_end_l877 = (long long)((((*st)).struct_decl).field_count);
                    for (j = i + 1; (long long)(j) <= __for_end_l877; j++)
                    {
                        {
                            g = (((*st)).struct_decl).fields[j - 1];
                            if (g != nil && semantic_names_equal((((*f)).field_decl).name, (((*f)).field_decl).name_len, (((*g)).field_decl).name, (((*g)).field_decl).name_len))
                            {
                                semantic_error_at(at, "semantic_check_extends_clashes: duplicate field name in STRUCT");
                            }
                        }
                    }
                }
            }
        }
    }
    if ((((*st)).struct_decl).extends_type == nil)
    {
                return;
    }
    anc = semantic_struct_body_of_type(ctx, (((*st)).struct_decl).extends_type);
    if (anc == nil)
    {
        semantic_error_at(at, "semantic_check_extends_clashes: EXTENDS base must be a STRUCT type");
    }
    if ((((*anc)).struct_decl).is_union)
    {
        semantic_error_at(at, "semantic_check_extends_clashes: EXTENDS base cannot be a UNION");
    }
    {
        const long long __for_end_l900 = (long long)((((*st)).struct_decl).field_count);
        for (i = 1; (long long)(i) <= __for_end_l900; i++)
        {
            {
                f = (((*st)).struct_decl).fields[i - 1];
                if (f == nil)
                {
                                        /* INVARIANT (on loop exit) */
                    continue;
                }
                if (semantic_names_equal((((*f)).field_decl).name, (((*f)).field_decl).name_len, "base", 4))
                {
                    semantic_error_at(at, "semantic_check_extends_clashes: field name 'base' is reserved for EXTENDS");
                }
                if (semantic_find_field_depth(ctx, anc, (((*f)).field_decl).name, (((*f)).field_decl).name_len, &depth))
                {
                    semantic_error_at(at, "semantic_check_extends_clashes: field name clashes with EXTENDS base");
                }
            }
        }
    }
}

/**
 * Resolve field types inside a STRUCT ... END type body. 
 */
static void semantic_resolve_struct_type(pTSemanticContext ctx, pNode st, pNode at)
{
    size_t i = 0;
    pNode f = nil;
    if (st == nil || ((*st)).kind != NODE_STRUCT_DECL)
    {
                return;
    }
    if ((((*st)).struct_decl).extends_type != nil)
    {
        if ((((*st)).struct_decl).is_union)
        {
            semantic_error_at(at, "semantic_resolve_struct_type: UNION cannot have EXTENDS");
        }
        else
        {
            semantic_resolve_type(ctx, (((*st)).struct_decl).extends_type, at);
        }
    }
    {
        const long long __for_end_l935 = (long long)((((*st)).struct_decl).field_count);
        for (i = 1; (long long)(i) <= __for_end_l935; i++)
        {
            {
                f = (((*st)).struct_decl).fields[i - 1];
                if (f != nil && (((*f)).field_decl).field_type != nil)
                {
                    semantic_resolve_type(ctx, (((*f)).field_decl).field_type, at);
                }
            }
        }
    }
    semantic_check_extends_clashes(ctx, st, at);
}

/**
 * Parse integer literal token (deciman / 0x hex); strip '_' separators.
 */
static integer semantic_parse_integer_literal(pNode n)
{
    char buf[128] = {0};
    size_t i = 0;
    size_t j = 0;
    char* endptr = nil;
    long v = 0;
    if (n == nil || ((*n)).kind != NODE_LITERAL || (((*n)).token).kind != TOK_NUMBER)
    {
        semantic_error_at(n, "semantic_parse_integer_literal: expected integer literal");
    }
    if ((((*n)).token).length >= ((integer)sizeof(buf)))
    {
        semantic_error_at(n, "semantic_parse_integer_literal: integer literal too long");
    }
    while (i < (((*n)).token).length)
    {
        {
            if ((((*n)).token).start[i] != '_')
            {
                buf[j] = (((*n)).token).start[i];
                j++;
            }
            i++;
        }
    }
    buf[j] = '\0';
    v = strtol(&buf[0], &endptr, 0);
    if (endptr == &buf[0])
    {
        semantic_error_at(n, "semantic_parse_integer_literal: invalid integer literal");
    }
    /* return value captured before defers */
    integer __ret_l979 = (integer)v;
    return __ret_l979;
}

/**
 * Evaluate a compile-time integer expression.
 * Implementation lives in semantic_try_eval_const_expr
 */
static integer semantic_eval_const_expr(pTSemanticContext ctx, pNode n)
{
    integer val = 0;
    pcchar msg = nil;
    if (!semantic_try_eval_const_expr(ctx, n, &val, &msg))
    {
        if (msg == nil)
        {
            msg = "semantic_eval_const_expr: not an integer constant expression";
        }
        semantic_error_at(n, msg);
    }
    /* return value captured before defers */
    integer __ret_l998 = val;
    return __ret_l998;
}

/**
 * Try integer const-fold. true + out_val^ on success.
 * Non-integer CONST (strings, pointers, ...) return false -- not an error.
 */
static bool semantic_try_eval_const_expr(pTSemanticContext ctx, pNode n, integer* out_val, pcchar* msg)
{
    pTSymbol sym = nil;
    integer left = 0;
    integer right = 0;
    if (n == nil || out_val == nil)
    {
        if (msg != nil)
        {
            (*msg) = "semantic_eval_const_expr: missing expression";
        }
        /* return value captured before defers */
        bool __ret_l1016 = false;
        return __ret_l1016;
    }
    switch (((*n)).kind)
    {
        case NODE_LITERAL:
        {
            if ((((*n)).token).kind != TOK_NUMBER)
            {
                if (msg != nil)
                {
                    (*msg) = "semantic_eval_const_expr: not an integer constant expression";
                }
                /* return value captured before defers */
                bool __ret_l1025 = false;
                return __ret_l1025;
            }
            (*out_val) = semantic_parse_integer_literal(n);
            /* return value captured before defers */
            bool __ret_l1028 = true;
            return __ret_l1028;
        }
        break;
        case NODE_IDENT:
        {
            sym = symtab_lookup(((*ctx)).scope, (((*n)).token).start, (((*n)).token).length);
            if (sym == nil || ((*sym)).kind != SYM_KIND_CONST || !((*sym)).has_const_value)
            {
                if (msg != nil)
                {
                    (*msg) = "semantic_eval_const_expr: expected constant value";
                }
                /* return value captured before defers */
                bool __ret_l1036 = false;
                return __ret_l1036;
            }
            (*out_val) = ((*sym)).const_value;
            /* return value captured before defers */
            bool __ret_l1039 = true;
            return __ret_l1039;
        }
        break;
        case NODE_PAREN:
        {
            /* return value captured before defers */
            bool __ret_l1042 = semantic_try_eval_const_expr(ctx, (((*n)).paren).expr, out_val, msg);
            return __ret_l1042;
        }
        break;
        case NODE_UNARY:
        {
            if ((((*n)).unary).op != TOK_SUB)
            {
                if (msg != nil)
                {
                    (*msg) = "semantic_eval_const_expr: unsupported unary operator";
                }
                /* return value captured before defers */
                bool __ret_l1049 = false;
                return __ret_l1049;
            }
            if (!semantic_try_eval_const_expr(ctx, (((*n)).unary).operand, out_val, msg))
            {
                /* return value captured before defers */
                bool __ret_l1052 = false;
                return __ret_l1052;
            }
            (*out_val) = -((*out_val));
            /* return value captured before defers */
            bool __ret_l1055 = true;
            return __ret_l1055;
        }
        break;
        case NODE_BINARY:
        {
            if (!semantic_try_eval_const_expr(ctx, (((*n)).binary).left, &left, msg))
            {
                /* return value captured before defers */
                bool __ret_l1059 = false;
                return __ret_l1059;
            }
            if (!semantic_try_eval_const_expr(ctx, (((*n)).binary).right, &right, msg))
            {
                /* return value captured before defers */
                bool __ret_l1062 = false;
                return __ret_l1062;
            }
            if ((((*n)).binary).op == TOK_ADD)
            {
                (*out_val) = left + right;
            }
            else if ((((*n)).binary).op == TOK_SUB)
            {
                (*out_val) = left - right;
            }
            else if ((((*n)).binary).op == TOK_MUL)
            {
                (*out_val) = left * right;
            }
            else if ((((*n)).binary).op == TOK_DIV)
            {
                if (right == 0)
                {
                    if (msg != nil)
                    {
                        (*msg) = "semantic_eval_const_expr: division by zero";
                    }
                    /* return value captured before defers */
                    bool __ret_l1075 = false;
                    return __ret_l1075;
                }
                (*out_val) = left / right;
            }
            else if ((((*n)).binary).op == TOK_MOD || (((*n)).binary).op == TOK_KEYWORD_MOD)
            {
                if (right == 0)
                {
                    if (msg != nil)
                    {
                        (*msg) = "semantic_eval_const_expr: division by zero";
                    }
                    /* return value captured before defers */
                    bool __ret_l1083 = false;
                    return __ret_l1083;
                }
                (*out_val) = left % right;
            }
            else
            {
                if (msg != nil)
                {
                    (*msg) = "semantic_eval_const_expr: unsupported binary operator";
                }
                /* return value captured before defers */
                bool __ret_l1090 = false;
                return __ret_l1090;
            }
            /* return value captured before defers */
            bool __ret_l1092 = true;
            return __ret_l1092;
        }
        break;
        default:
        {
            if (msg != nil)
            {
                (*msg) = "semantic_eval_const_expr: not a constant expression";
            }
            /* return value captured before defers */
            bool __ret_l1098 = false;
            return __ret_l1098;
        }
        break;
    }
    /* return value captured before defers */
    bool __ret_l1100 = false;
    return __ret_l1100;
}

/**
 * Register enum members as CONST symbols; set TYPE symbol_type.
 * Called from semantic_resolve_type_decls (Pass  1 1/2).
 */
static void semantic_register_enum_type(pTSemanticContext ctx, pNode en, pNode type_decl)
{
    size_t i = 0;
    size_t j = 0;
    pNode item = nil;
    pNode other = nil;
    integer val = 0;
    integer next_val = 0;
    pTSymbol sym = nil;
    pTType int_ty = nil;
    pTSymbol type_sym = nil;
    if (en == nil || ((*en)).kind != NODE_ENUM_TYPE)
    {
                return;
    }
    if (type_decl == nil || ((*type_decl)).kind != NODE_TYPE_DECL)
    {
                return;
    }
    int_ty = type_create_named(((*ctx)).arena, "integer", 7);
    next_val = 0;
    {
        const long long __for_end_l1132 = (long long)((((*en)).enum_type).count);
        for (i = 1; (long long)(i) <= __for_end_l1132; i++)
        {
            {
                item = (((*en)).enum_type).elements[i - 1];
                if (item == nil || ((*item)).kind != NODE_ENUM_ITEM)
                {
                    semantic_error_at(en, "semantic_register_enum_type: invalid enum number");
                }
                if ((((*item)).enum_item).name == nil || (((*item)).enum_item).name_len == 0)
                {
                    semantic_error_at(item, "semantic_register_enum_type: enum member has no name");
                }
                {
                    const long long __for_end_l1141 = (long long)(i - 1);
                    for (j = 1; (long long)(j) <= __for_end_l1141; j++)
                    {
                        {
                            other = (((*en)).enum_type).elements[j - 1];
                            if (other != nil && (((*other)).enum_item).name_len == (((*item)).enum_item).name_len && memcmp((((*other)).enum_item).name, (((*item)).enum_item).name, (((*item)).enum_item).name_len) == 0)
                            {
                                semantic_error_at(item, "semantic_register_enum_type: duplicate enum member");
                            }
                        }
                    }
                }
                if ((((*item)).enum_item).value != nil)
                {
                    val = semantic_eval_const_expr(ctx, (((*item)).enum_item).value);
                }
                else
                {
                    val = next_val;
                }
                (((*item)).enum_item).value_known = true;
                (((*item)).enum_item).int_value = val;
                next_val = val + 1;
                if (symtab_lookup_current(((*ctx)).scope, (((*item)).enum_item).name, (((*item)).enum_item).name_len) != nil)
                {
                    semantic_error_at(item, "semantic_register_enum_type: enum member conflics with existing symbol");
                }
                sym = symbol_create(((*ctx)).arena, SYM_KIND_CONST, (((*item)).enum_item).name, (((*item)).enum_item).name_len, item);
                ((*sym)).symbol_type = int_ty;
                ((*sym)).has_const_value = true;
                ((*sym)).const_value = val;
                ((*sym)).is_exported = (((*type_decl)).type_decl).is_exported;
                symtab_define(((*ctx)).arena, ((*ctx)).scope, sym);
            }
        }
    }
    type_sym = symtab_lookup(((*ctx)).scope, (((*type_decl)).type_decl).name, (((*type_decl)).type_decl).name_len);
    if (type_sym != nil)
    {
        ((*type_sym)).symbol_type = type_create_named(((*ctx)).arena, (((*type_decl)).type_decl).name, (((*type_decl)).type_decl).name_len);
    }
}

/** 
 * Resolve param / return types inside PROCEDURE/FUNCTION method types.
 */
static void semantic_resolve_method_type(pTSemanticContext ctx, pNode mt, pNode at)
{
    pNode* params = nil;
    size_t count = 0;
    size_t i = 0;
    pNode p = nil;
    if (mt == nil || ((*mt)).kind != NODE_METHOD_TYPE)
    {
                return;
    }
    if ((((*mt)).method_type).return_type != nil)
    {
        semantic_resolve_type(ctx, (((*mt)).method_type).return_type, at);
    }
    if ((((*mt)).method_type).params != nil && ((*(((*mt)).method_type).params)).kind == NODE_PARAM_LIST)
    {
        params = (((*(((*mt)).method_type).params)).param_list).params;
        count = (((*(((*mt)).method_type).params)).param_list).count;
        {
            const long long __for_end_l1199 = (long long)(count);
            for (i = 1; (long long)(i) <= __for_end_l1199; i++)
            {
                {
                    p = params[i - 1];
                    if (p != nil && (((*p)).param).param_type != nil)
                    {
                        semantic_resolve_type(ctx, (((*p)).param).param_type, p);
                    }
                }
            }
        }
    }
}

/**
 * Pass 1 1/2: resolve all top-level TYPE bodies; refresh sym^.symbol_type.
 */
static void semantic_resolve_type_decls(pTSemanticContext ctx, pNode root)
{
    size_t i = 0;
    pNode decl = nil;
    pTSymbol sym = nil;
    if (root == nil || ((*root)).kind != NODE_PROGRAM)
    {
                return;
    }
    {
        const long long __for_end_l1222 = (long long)((((*root)).program_decl).count);
        for (i = 1; (long long)(i) <= __for_end_l1222; i++)
        {
            {
                decl = (((*root)).program_decl).decls[i - 1];
                if (decl == nil || ((*decl)).kind != NODE_TYPE_DECL)
                {
                                        /* INVARIANT (on loop exit) */
                    continue;
                }
                if ((((*decl)).type_decl).is_forward)
                {
                                        /* INVARIANT (on loop exit) */
                    continue;
                }
                if ((((*decl)).type_decl).defined_type != nil)
                {
                    semantic_resolve_type(ctx, (((*decl)).type_decl).defined_type, decl);
                }
                else if ((((*decl)).type_decl).struct_body != nil)
                {
                    semantic_resolve_struct_type(ctx, (((*decl)).type_decl).struct_body, decl);
                }
                else if ((((*decl)).type_decl).enum_type != nil)
                {
                    semantic_register_enum_type(ctx, (((*decl)).type_decl).enum_type, decl);
                }
                else if ((((*decl)).type_decl).method_type != nil)
                {
                    semantic_resolve_method_type(ctx, (((*decl)).type_decl).method_type, decl);
                }
                sym = symtab_lookup(((*ctx)).scope, (((*decl)).type_decl).name, (((*decl)).type_decl).name_len);
                if (sym != nil && (((*decl)).type_decl).defined_type != nil && ((*(((*decl)).type_decl).defined_type)).resolved_type != nil)
                {
                    ((*sym)).symbol_type = ((*(((*decl)).type_decl).defined_type)).resolved_type;
                }
            }
        }
    }
}

/**
 * FOR control matches
 */
static bool semantic_for_control_matches(pTSemanticContext ctx, const char* name, size_t name_len)
{
    if (ctx == nil || ((*ctx)).for_var_name == nil || ((*ctx)).for_var_len == 0)
    {
        /* return value captured before defers */
        bool __ret_l1260 = false;
        return __ret_l1260;
    }
    else if (name == nil || name_len == 0)
    {
        /* return value captured before defers */
        bool __ret_l1262 = false;
        return __ret_l1262;
    }
    else
    {
        /* return value captured before defers */
        bool __ret_l1264 = name_len == ((*ctx)).for_var_len && memcmp(name, ((*ctx)).for_var_name, name_len) == 0;
        return __ret_l1264;
    }
}

/**
 * If designator is rooted at a forma, return that NODE_PARAM; else nil.
 * Walks IDENT, FIELD_ACCESS, ARRAY_INDEX, and postfix ^ (unary CARET).
 */
static pNode semantic_designator_param_root(pNode d)
{
    if (d == nil)
    {
        /* return value captured before defers */
        pNode __ret_l1276 = nil;
        return __ret_l1276;
    }
    if (((*d)).kind == NODE_IDENT)
    {
        if (((*d)).resolved_sym != nil && ((*((*d)).resolved_sym)).kind == SYM_KIND_PARAM && ((*((*d)).resolved_sym)).decl != nil && ((*((*((*d)).resolved_sym)).decl)).kind == NODE_PARAM)
        {
            /* return value captured before defers */
            pNode __ret_l1281 = ((*((*d)).resolved_sym)).decl;
            return __ret_l1281;
        }
        /* return value captured before defers */
        pNode __ret_l1283 = nil;
        return __ret_l1283;
    }
    if (((*d)).kind == NODE_FIELD_ACCESS)
    {
        /* return value captured before defers */
        pNode __ret_l1286 = semantic_designator_param_root((((*d)).field_access).record_);
        return __ret_l1286;
    }
    if (((*d)).kind == NODE_ARRAY_INDEX)
    {
        /* return value captured before defers */
        pNode __ret_l1289 = semantic_designator_param_root((((*d)).array_index).array_);
        return __ret_l1289;
    }
    if (((*d)).kind == NODE_UNARY && (((*d)).unary).op == TOK_CARET)
    {
        /* return value captured before defers */
        pNode __ret_l1292 = semantic_designator_param_root((((*d)).unary).operand);
        return __ret_l1292;
    }
    if (((*d)).kind == NODE_PAREN)
    {
        /* return value captured before defers */
        pNode __ret_l1295 = semantic_designator_param_root((((*d)).paren).expr);
        return __ret_l1295;
    }
    /* return value captured before defers */
    pNode __ret_l1297 = nil;
    return __ret_l1297;
}

/**
 * Forbid writes that violate parameter modes.
 * - CONST formal: no rebind and no mutation through the parameter.
 * - Non-VAR formal: no rebind of the binding (are name on LHS of :=).
 */
static void semantic_forbid_param_mode_write(pNode lhs)
{
    pNode param = nil;
    if (lhs == nil)
    {
                return;
    }
    param = semantic_designator_param_root(lhs);
    if (param == nil)
    {
                return;
    }
    if ((((*param)).param).is_const)
    {
        semantic_error_at(lhs, "semantic_forbid_param_mode_write: cannot write through CONST parameter");
    }
    if (((*lhs)).kind == NODE_IDENT && !(((*param)).param).is_var)
    {
        semantic_error_at(lhs, "semantic_forbid_param_mode_write: cannot assign to non-VAR parameter; use VAR");
    }
}

/**
 * Forbid FOR control write
 */
static void semantic_forbid_for_control_write(pTSemanticContext ctx, pNode d)
{
    if (d == nil)
    {
                return;
    }
    else if (((*d)).kind == NODE_IDENT)
    {
        if (semantic_for_control_matches(ctx, (((*d)).token).start, (((*d)).token).length))
        {
            semantic_error_at(d, "semantic_forbid_for_control_write: FOR control variable is read-only in loop body");
        }
    }
}

/** 
* Define one symbol in the current scope.
*/
static void semantic_define(pTSemanticContext ctx, SymbolKind kind, const char* name, size_t name_len, TType* symbol_type, pNode decl, bool is_exported)
{
    pTSymbol sym = nil;
    if (ctx == nil || ((*ctx)).scope == nil)
    {
        semantic_error_at(decl, "semantic_define: internal error: no active scope");
    }
    if (type_is_builtin_name(name, name_len))
    {
        fprintf(stderr, "WARNING: semantic_define: cannot shadow builtin types\n");
    }
    sym = symbol_create(((*ctx)).arena, kind, name, name_len, decl);
    ((*sym)).symbol_type = symbol_type;
    ((*sym)).is_exported = is_exported;
    if (kind == SYM_KIND_LET)
    {
        symtab_define_let(((*ctx)).arena, ((*ctx)).scope, sym);
    }
    else
    {
        symtab_define(((*ctx)).arena, ((*ctx)).scope, sym);
    }
}

/**
 * Define a symbol, or refine an existing IMPORT in the current scope.
 */
static void semantic_define_or_refine(pTSemanticContext ctx, SymbolKind kind, const char* name, size_t name_len, TType* symbol_type, pNode decl, bool is_exported)
{
    pTSymbol existing = nil;
    pTSymbol sym = nil;
    if (ctx == nil || ((*ctx)).scope == nil)
    {
        semantic_error_at(decl, "semantic_define_or_refine: internal error: no active scope");
    }
    if (type_is_builtin_name(name, name_len))
    {
        semantic_error_at(decl, "semantic_define_or_refine: cannot shadow builtin types");
    }
    existing = symtab_lookup_current(((*ctx)).scope, name, name_len);
    sym = symbol_create(((*ctx)).arena, kind, name, name_len, decl);
    ((*sym)).symbol_type = symbol_type;
    ((*sym)).is_exported = is_exported;
    if (existing == nil)
    {
        symtab_define(((*ctx)).arena, ((*ctx)).scope, sym);
    }
    else if (((*existing)).kind == SYM_KIND_IMPORT)
    {
        symtab_refine_symbol(((*ctx)).arena, ((*ctx)).scope, existing, sym);
    }
    else
    {
        semantic_error_at(decl, "semantic_define_or_refine: duplicate symbol");
    }
}

static void semantic_bind_portable_import(pTSemanticContext ctx, pNode loc, const char* name, size_t name_len)
{
    pTSymbol existing = nil;
    pTSymbol sym = nil;
    if (ctx == nil || ((*ctx)).scope == nil)
    {
        semantic_error_at(loc, "semantic_bind_portable_import: internal error: no active scope");
    }
    existing = symtab_lookup_current(((*ctx)).scope, name, name_len);
    sym = symbol_create(((*ctx)).arena, SYM_KIND_TYPE, name, name_len, loc);
    ((*sym)).symbol_type = nil;
    ((*sym)).is_exported = false;
    if (existing == nil)
    {
        symtab_define(((*ctx)).arena, ((*ctx)).scope, sym);
    }
    else if (((*existing)).kind == SYM_KIND_TYPE && ((*existing)).decl == nil)
    {
        symtab_refine_symbol(((*ctx)).arena, ((*ctx)).scope, existing, sym);
    }
    else if (((*existing)).kind == SYM_KIND_TYPE && ((*existing)).decl != nil)
    {
        semantic_error_at(loc, "semantic_bind_portable_import: portable type already bound in this unit");
    }
    else
    {
        semantic_error_at(loc, "semantic_bind_portable_import: cannot bind portable type over existing symbol");
    }
}

static void semantic_define_or_complete_forward(pTSemanticContext ctx, SymbolKind kind, const char* name, size_t name_len, TType* symbol_type, pNode decl, bool is_exported)
{
    pTSymbol existing = nil;
    pTSymbol sym = nil;
    if (ctx == nil || ((*ctx)).scope == nil)
    {
        semantic_error_at(decl, "semantic_define_or_complete_forward: internal error: no active scope");
    }
    if (type_is_builtin_name(name, name_len))
    {
        if (!(kind == SYM_KIND_TYPE && type_is_portable_rebindable(name, name_len)))
        {
            semantic_error_at(decl, "semantic_define_or_complete_forward: cannot rebind or shadow this builtin type");
        }
    }
    existing = symtab_lookup_current(((*ctx)).scope, name, name_len);
    sym = symbol_create(((*ctx)).arena, kind, name, name_len, decl);
    ((*sym)).symbol_type = symbol_type;
    ((*sym)).is_exported = is_exported;
    if (existing == nil)
    {
        symtab_define(((*ctx)).arena, ((*ctx)).scope, sym);
    }
    else if (((*existing)).kind == SYM_KIND_IMPORT)
    {
        symtab_refine_symbol(((*ctx)).arena, ((*ctx)).scope, existing, sym);
    }
    else if ((((*existing)).kind == SYM_KIND_PROC || ((*existing)).kind == SYM_KIND_FUNC) && ((*existing)).decl != nil && (((*((*existing)).decl)).proc_decl).is_forward && (((*decl)).proc_decl).is_forward == false)
    {
        symtab_refine_symbol(((*ctx)).arena, ((*ctx)).scope, existing, sym);
    }
    else if (((*existing)).kind == SYM_KIND_TYPE && ((*existing)).decl != nil && ((*((*existing)).decl)).kind == NODE_TYPE_DECL && (((*((*existing)).decl)).type_decl).is_forward && decl != nil && ((*decl)).kind == NODE_TYPE_DECL && (((*decl)).type_decl).is_forward == false)
    {
        symtab_refine_symbol(((*ctx)).arena, ((*ctx)).scope, existing, sym);
    }
    else if (kind == SYM_KIND_TYPE && type_is_portable_rebindable(name, name_len) && ((*existing)).kind == SYM_KIND_TYPE)
    {
        if (((*existing)).decl == nil && decl != nil && ((*decl)).kind == NODE_TYPE_DECL && (((*decl)).type_decl).is_forward == false)
        {
            symtab_refine_symbol(((*ctx)).arena, ((*ctx)).scope, existing, sym);
        }
        else if (((*existing)).decl != nil)
        {
            semantic_error_at(decl, "semantic_define_or_complete_forward: portable type already bound in this unit");
        }
        else
        {
            semantic_error_at(decl, "semantic_define_or_complete_forward: invalid portable type binding");
        }
    }
    else
    {
        semantic_error_at(decl, "semantic_define_or_complete_forward: duplicate symbol");
    }
}

/**
 * Register one IMPORT item in the current scope (foreign / minimal symbol).
 */
static void semantic_register_import_item(pTSemanticContext ctx, pNode item)
{
    const char* name = nil;
    size_t name_len = 0;
    if (item == nil || ((*item)).kind != NODE_IMPORT_ITEM)
    {
        semantic_error_at(item, "semantic_register_import_item: expected import item");
    }
    if ((((*item)).import_item).import_alias != nil && (((*item)).import_item).import_alias_len > 0)
    {
        name = (((*item)).import_item).import_alias;
        name_len = (((*item)).import_item).import_alias_len;
    }
    else
    {
        name = (((*item)).import_item).qualident;
        name_len = (((*item)).import_item).qualident_len;
    }
    if (name == nil || name_len == 0)
    {
        semantic_error_at(item, "semantic_register_import_item: import item has no name");
    }
    semantic_define(ctx, SYM_KIND_IMPORT, name, name_len, nil, item, false);
}

static char* semantic_arena_strndup(Arena* arena, const char* s, size_t n)
{
    char* p = nil;
    if (arena == nil || s == nil || n == 0)
    {
        /* return value captured before defers */
        char* __ret_l1544 = nil;
        return __ret_l1544;
    }
    p = (char*)arena_alloc(arena, n + 1);
    memcpy(p, s, n);
    p[n] = '\0';
    /* return value captured before defers */
    char* __ret_l1549 = p;
    return __ret_l1549;
}

static pTType semantic_mh_make_type(pTSemanticContext ctx, bool is_const, bool is_pointer, const char* name, size_t name_len, int width)
{
    pTType ty = nil;
    char* nm = nil;
    if (ctx == nil || name == nil || name_len == 0)
    {
        /* return value captured before defers */
        pTType __ret_l1564 = nil;
        return __ret_l1564;
    }
    nm = semantic_arena_strndup(((*ctx)).arena, name, name_len);
    ty = type_create_named(((*ctx)).arena, nm, name_len);
    ((*ty)).is_const = is_const;
    ((*ty)).is_pointer = is_pointer;
    ((*ty)).width = width;
    /* return value captured before defers */
    pTType __ret_l1571 = ty;
    return __ret_l1571;
}

static pNode semantic_mh_make_proc_decl(pTSemanticContext ctx, const MhExport* exp, pNode loc, const char* name, size_t name_len, SymbolKind kind)
{
    pNode decl = nil;
    pNode pl = nil;
    pNode param = nil;
    pTType ty = nil;
    size_t i = 0;
    const MhFormal* f = nil;
    char* pname = nil;
    char pbuf[32] = {0};
    NodeKind nkind = NODE_PROC_DECL;
    TToken tok = {0};
    if (ctx == nil || exp == nil || !((*exp)).has_signature)
    {
        /* return value captured before defers */
        pNode __ret_l1596 = nil;
        return __ret_l1596;
    }
    if (kind != SYM_KIND_PROC && kind != SYM_KIND_FUNC)
    {
        /* return value captured before defers */
        pNode __ret_l1599 = nil;
        return __ret_l1599;
    }
    if (loc != nil)
    {
        tok = ((*loc)).token;
    }
    else
    {
        (tok).kind = 0;
        (tok).start = nil;
        (tok).length = 0;
        (tok).line = 0;
        (tok).column = 0;
        (tok).error_msg = nil;
    }
    if (kind == SYM_KIND_FUNC)
    {
        nkind = NODE_FUNC_DECL;
    }
    decl = node_create(((*ctx)).arena, nkind, tok);
    (((*decl)).proc_decl).name = name;
    (((*decl)).proc_decl).name_len = name_len;
    (((*decl)).proc_decl).method_owner = nil;
    (((*decl)).proc_decl).method_owner_len = 0;
    (((*decl)).proc_decl).params = nil;
    (((*decl)).proc_decl).return_type = nil;
    (((*decl)).proc_decl).body = nil;
    (((*decl)).proc_decl).is_exported = false;
    (((*decl)).proc_decl).is_recursive = false;
    (((*decl)).proc_decl).is_extern = ((*exp)).is_extern;
    (((*decl)).proc_decl).is_forward = false;
    (((*decl)).proc_decl).is_function = (kind == SYM_KIND_FUNC);
    (((*decl)).proc_decl).receiver = nil;
    if (((*exp)).is_method && ((*exp)).method_owner != nil && ((*exp)).method_owner_len > 0)
    {
        (((*decl)).proc_decl).method_owner = semantic_arena_strndup(((*ctx)).arena, ((*exp)).method_owner, ((*exp)).method_owner_len);
        (((*decl)).proc_decl).method_owner_len = ((*exp)).method_owner_len;
    }
    pl = node_create(((*ctx)).arena, NODE_PARAM_LIST, tok);
    (((*pl)).param_list).params = nil;
    (((*pl)).param_list).count = 0;
    (((*pl)).param_list).capacity = 0;
    {
        const long long __for_end_l1645 = (long long)(((*exp)).formal_count);
        for (i = 1; (long long)(i) <= __for_end_l1645; i++)
        {
            {
                f = &((*exp)).formals[i - 1];
                if (f == nil || ((*f)).type_name == nil || ((*f)).type_name_len == 0)
                {
                    semantic_error_at(loc, "semantic_mh_make_proc_decl: formal missing type name");
                }
                ty = semantic_mh_make_type(ctx, ((*f)).type_is_const, ((*f)).type_is_pointer, ((*f)).type_name, ((*f)).type_name_len, ((*f)).type_width);
                if (ty == nil)
                {
                    semantic_error_at(loc, "semantic_mh_make_proc_decl: cannot build formal type");
                }
                snprintf(&pbuf[0], 32, "_%zu", i - 1);
                pname = semantic_arena_strndup(((*ctx)).arena, &pbuf[0], strlen(&pbuf[0]));
                param = node_create(((*ctx)).arena, NODE_PARAM, tok);
                (((*param)).param).name = pname;
                (((*param)).param).name_len = strlen(pname);
                (((*param)).param).param_type = ty;
                (((*param)).param).is_var = ((*f)).is_var;
                (((*param)).param).is_ref = ((*f)).is_ref;
                (((*param)).param).is_const = ((*f)).is_const;
                arena_append_ptr(((*ctx)).arena, (ppvoid)(&(((*pl)).param_list).params), &(((*pl)).param_list).count, &(((*pl)).param_list).capacity, param);
            }
        }
    }
    (((*decl)).proc_decl).params = pl;
    if (((*exp)).has_result && ((*exp)).result_name != nil && ((*exp)).result_name_len > 0)
    {
        (((*decl)).proc_decl).return_type = semantic_mh_make_type(ctx, ((*exp)).result_is_const, ((*exp)).result_is_pointer, ((*exp)).result_name, ((*exp)).result_name_len, ((*exp)).result_width);
    }
    /* return value captured before defers */
    pNode __ret_l1684 = decl;
    return __ret_l1684;
}

static pNode semantic_mh_make_type_decl(pTSemanticContext ctx, const MhExport* exp, pNode loc, const char* bind_name, size_t bind_len)
{
    pNode decl = nil;
    pNode st = nil;
    pNode field = nil;
    size_t i = 0;
    const MhField* f = nil;
    TToken tok = {0};
    if (ctx == nil || exp == nil)
    {
        /* return value captured before defers */
        pNode __ret_l1703 = nil;
        return __ret_l1703;
    }
    if (!((*exp)).is_struct && !((*exp)).is_union)
    {
        /* return value captured before defers */
        pNode __ret_l1706 = nil;
        return __ret_l1706;
    }
    if (loc != nil)
    {
        tok = ((*loc)).token;
    }
    else
    {
        (tok).kind = 0;
        (tok).start = nil;
        (tok).length = 0;
        (tok).line = 0;
        (tok).column = 0;
        (tok).error_msg = nil;
    }
    st = node_create(((*ctx)).arena, NODE_STRUCT_DECL, tok);
    (((*st)).struct_decl).name = bind_name;
    (((*st)).struct_decl).name_len = bind_len;
    (((*st)).struct_decl).extends_type = nil;
    (((*st)).struct_decl).fields = nil;
    (((*st)).struct_decl).field_count = 0;
    (((*st)).struct_decl).field_capacity = 0;
    (((*st)).struct_decl).is_exported = false;
    (((*st)).struct_decl).is_packed = false;
    (((*st)).struct_decl).is_union = ((*exp)).is_union;
    if (((*exp)).extends_name != nil && ((*exp)).extends_name_len > 0)
    {
        (((*st)).struct_decl).extends_type = semantic_mh_make_type(ctx, false, false, ((*exp)).extends_name, ((*exp)).extends_name_len, 0);
    }
    {
        const long long __for_end_l1736 = (long long)(((*exp)).field_count);
        for (i = 1; (long long)(i) <= __for_end_l1736; i++)
        {
            {
                f = &((*exp)).fields[i - 1];
                if (f == nil || ((*f)).name == nil || ((*f)).name_len == 0)
                {
                    semantic_error_at(loc, "semantic_mh_make_type_decl: field missing name");
                }
                field = node_create(((*ctx)).arena, NODE_FIELD_DECL, tok);
                (((*field)).field_decl).name = semantic_arena_strndup(((*ctx)).arena, ((*f)).name, ((*f)).name_len);
                (((*field)).field_decl).name_len = ((*f)).name_len;
                (((*field)).field_decl).field_type = semantic_mh_make_type(ctx, ((*f)).type_is_const, ((*f)).type_is_pointer, ((*f)).type_name, ((*f)).type_name_len, ((*f)).type_width);
                (((*field)).field_decl).initializer = nil;
                arena_append_ptr(((*ctx)).arena, (ppvoid)(&(((*st)).struct_decl).fields), &(((*st)).struct_decl).field_count, &(((*st)).struct_decl).field_capacity, field);
            }
        }
    }
    decl = node_create(((*ctx)).arena, NODE_TYPE_DECL, tok);
    (((*decl)).type_decl).name = bind_name;
    (((*decl)).type_decl).name_len = bind_len;
    (((*decl)).type_decl).defined_type = nil;
    (((*decl)).type_decl).struct_body = st;
    (((*decl)).type_decl).method_type = nil;
    (((*decl)).type_decl).enum_type = nil;
    (((*decl)).type_decl).initializer = nil;
    (((*decl)).type_decl).is_exported = false;
    (((*decl)).type_decl).is_extern = ((*exp)).is_extern;
    (((*decl)).type_decl).is_forward = false;
    /* return value captured before defers */
    pNode __ret_l1768 = decl;
    return __ret_l1768;
}

static pNode semantic_mh_make_method_type_decl(pTSemanticContext ctx, const MhExport* exp, pNode loc, const char* bind_name, size_t bind_len)
{
    pNode decl = nil;
    pNode mt = nil;
    pNode pl = nil;
    pNode param = nil;
    pTType ty = nil;
    size_t i = 0;
    const MhFormal* f = nil;
    char* pname = nil;
    char pbuf[32] = {0};
    TToken tok = {0};
    if (ctx == nil || exp == nil || !((*exp)).has_signature)
    {
        /* return value captured before defers */
        pNode __ret_l1787 = nil;
        return __ret_l1787;
    }
    if (((*exp)).is_struct || ((*exp)).is_union)
    {
        /* return value captured before defers */
        pNode __ret_l1790 = nil;
        return __ret_l1790;
    }
    if (loc != nil)
    {
        tok = ((*loc)).token;
    }
    else
    {
        (tok).kind = 0;
        (tok).start = nil;
        (tok).length = 0;
        (tok).line = 0;
        (tok).column = 0;
        (tok).error_msg = nil;
    }
    pl = node_create(((*ctx)).arena, NODE_PARAM_LIST, tok);
    (((*pl)).param_list).params = nil;
    (((*pl)).param_list).count = 0;
    (((*pl)).param_list).capacity = 0;
    {
        const long long __for_end_l1809 = (long long)(((*exp)).formal_count);
        for (i = 1; (long long)(i) <= __for_end_l1809; i++)
        {
            {
                f = &((*exp)).formals[i - 1];
                if (f == nil || ((*f)).type_name == nil || ((*f)).type_name_len == 0)
                {
                    semantic_error_at(loc, "semantic_mh_make_method_type_decl: formal missing type name");
                }
                ty = semantic_mh_make_type(ctx, ((*f)).type_is_const, ((*f)).type_is_pointer, ((*f)).type_name, ((*f)).type_name_len, ((*f)).type_width);
                snprintf(&pbuf[0], 32, "_%zu", i - 1);
                pname = semantic_arena_strndup(((*ctx)).arena, &pbuf[0], strlen(&pbuf[0]));
                param = node_create(((*ctx)).arena, NODE_PARAM, tok);
                (((*param)).param).name = pname;
                (((*param)).param).name_len = strlen(pname);
                (((*param)).param).param_type = ty;
                (((*param)).param).is_var = ((*f)).is_var;
                (((*param)).param).is_ref = ((*f)).is_ref;
                (((*param)).param).is_const = ((*f)).is_const;
                arena_append_ptr(((*ctx)).arena, (ppvoid)(&(((*pl)).param_list).params), &(((*pl)).param_list).count, &(((*pl)).param_list).capacity, param);
            }
        }
    }
    mt = node_create(((*ctx)).arena, NODE_METHOD_TYPE, tok);
    (((*mt)).method_type).params = pl;
    (((*mt)).method_type).is_function = ((*exp)).is_func_type;
    (((*mt)).method_type).return_type = nil;
    if (((*exp)).has_result && ((*exp)).result_name != nil && ((*exp)).result_name_len > 0)
    {
        (((*mt)).method_type).return_type = semantic_mh_make_type(ctx, ((*exp)).result_is_const, ((*exp)).result_is_pointer, ((*exp)).result_name, ((*exp)).result_name_len, ((*exp)).result_width);
    }
    decl = node_create(((*ctx)).arena, NODE_TYPE_DECL, tok);
    (((*decl)).type_decl).name = bind_name;
    (((*decl)).type_decl).name_len = bind_len;
    (((*decl)).type_decl).defined_type = nil;
    (((*decl)).type_decl).struct_body = nil;
    (((*decl)).type_decl).method_type = mt;
    (((*decl)).type_decl).enum_type = nil;
    (((*decl)).type_decl).initializer = nil;
    (((*decl)).type_decl).is_exported = false;
    (((*decl)).type_decl).is_extern = ((*exp)).is_extern;
    (((*decl)).type_decl).is_forward = false;
    /* return value captured before defers */
    pNode __ret_l1854 = decl;
    return __ret_l1854;
}

/**
 * bind one .mh export into the current scope (listed import or 7a unit entry).
 */
static void semantic_bind_mh_export(pTSemanticContext ctx, pNode loc, const MhExport* exp, const char* bind_name, size_t bind_len)
{
    SymbolKind kind = SYM_KIND_IMPORT;
    pTSymbol sym = nil;
    pNode synth = nil;
    char* owned = nil;
    if (ctx == nil || exp == nil || bind_name == nil || bind_len == 0)
    {
                return;
    }
    kind = mh_export_to_symkind(((*exp)).kind);
    if (kind == SYM_KIND_UNKNOWN)
    {
        semantic_error_at(loc, "semantic_bind_mh_export: unknown export kind in .mh");
    }
    owned = semantic_arena_strndup(((*ctx)).arena, bind_name, bind_len);
    if (kind == SYM_KIND_TYPE && type_is_portable_rebindable(owned, bind_len))
    {
        semantic_bind_portable_import(ctx, loc, owned, bind_len);
    }
    else
    {
        semantic_define(ctx, kind, owned, bind_len, nil, loc, false);
    }
    sym = symtab_lookup_current(((*ctx)).scope, owned, bind_len);
    if (sym == nil)
    {
        semantic_error_at(loc, "semantic_bind_mh_export: internal: symbol not defined");
    }
    if (((*exp)).has_signature && (kind == SYM_KIND_PROC || kind == SYM_KIND_FUNC))
    {
        synth = semantic_mh_make_proc_decl(ctx, exp, loc, owned, bind_len, kind);
        if (synth != nil)
        {
            ((*sym)).decl = synth;
        }
    }
    if (kind == SYM_KIND_TYPE && (((*exp)).is_struct || ((*exp)).is_union))
    {
        synth = semantic_mh_make_type_decl(ctx, exp, loc, owned, bind_len);
        if (synth != nil)
        {
            ((*sym)).decl = synth;
        }
    }
    if (kind == SYM_KIND_TYPE && ((*exp)).has_signature && !((*exp)).is_struct && !((*exp)).is_union)
    {
        synth = semantic_mh_make_method_type_decl(ctx, exp, loc, owned, bind_len);
        if (synth != nil)
        {
            ((*sym)).decl = synth;
        }
    }
    if (((*exp)).is_method && ((*exp)).is_instance)
    {
        ((*sym)).is_method_instance = true;
    }
}

/**
 * Register all names from an IMPORT ... FROM statement.
 * .mh paths: parse export table and register real symbol kinds.
 * .h paths: minimal SYM_KIND_IMPORT placeholders (unchanged).
 */
static void semantic_register_import(pTSemanticContext ctx, pNode decl)
{
    size_t i = 0;
    char resolved[4096] = {0};
    MhModule m = {0};
    size_t mname_len = 0;
    const MhExport* unit_exp = nil;
    if (decl == nil || ((*decl)).kind != NODE_IMPORT)
    {
                return;
    }
    if ((((*decl)).import_stmt).from_path == nil || (((*decl)).import_stmt).path_len == 0)
    {
        semantic_error_at(decl, "semantic_register_import: IMPORT requires FROM import-source");
    }
    if (mh_path_is_mh((((*decl)).import_stmt).from_path, (((*decl)).import_stmt).path_len))
    {
        if (((*ctx)).source_path == nil)
        {
            semantic_error_at(decl, "semantic_register_import: internal error: missing source_path for .mh");
        }
        if (!mh_resolve_import_path(((*ctx)).source_path, (((*decl)).import_stmt).from_path, (((*decl)).import_stmt).path_len, &resolved[0], SEMANTIC_MH_PATH_MAX))
        {
            semantic_error_at(decl, "semantic_register_import: cannot resolve .mh path");
        }
        if (!mh_reader_load(&resolved[0], &m))
        {
            semantic_error_at(decl, "semantic_register_import: failed to read .mh file");
        }
        {
            const long long __for_end_l1956 = (long long)((((*decl)).import_stmt).count);
            for (i = 1; (long long)(i) <= __for_end_l1956; i++)
            {
                {
                    pNode item = (((*decl)).import_stmt).items[i - 1];
                    const char* lookup_name = nil;
                    size_t lookup_len = 0;
                    const char* bind_name = nil;
                    size_t bind_len = 0;
                    char* mangled = nil;
                    const MhExport* exp = nil;
                    if (item == nil || ((*item)).kind != NODE_IMPORT_ITEM)
                    {
                        semantic_error_at(decl, "semantic_register_import: expected import item");
                    }
                    if ((((*item)).import_item).method_owner != nil && (((*item)).import_item).method_owner_len > 0)
                    {
                        mangled = semantic_mangle_method(((*ctx)).arena, (((*item)).import_item).method_owner, (((*item)).import_item).method_owner_len, (((*item)).import_item).qualident, (((*item)).import_item).qualident_len);
                        lookup_name = mangled;
                        lookup_len = (((*item)).import_item).method_owner_len + 2 + (((*item)).import_item).qualident_len;
                    }
                    else
                    {
                        lookup_name = (((*item)).import_item).qualident;
                        lookup_len = (((*item)).import_item).qualident_len;
                    }
                    if (lookup_name == nil || lookup_len == 0)
                    {
                        semantic_error_at(item, "semantic_register_import: import item has no name");
                    }
                    exp = mh_module_find(&m, lookup_name, lookup_len);
                    if (exp == nil)
                    {
                        char buf[256] = {0};
                        snprintf(&buf[0], 256, "semantic_register_import: name not exported in .mh: %.*s", (int)lookup_len, lookup_name);
                        semantic_error_at(item, &buf[0]);
                    }
                    if ((((*item)).import_item).import_alias != nil && (((*item)).import_item).import_alias_len > 0)
                    {
                        bind_name = (((*item)).import_item).import_alias;
                        bind_len = (((*item)).import_item).import_alias_len;
                    }
                    else
                    {
                        bind_name = lookup_name;
                        bind_len = lookup_len;
                    }
                    semantic_bind_mh_export(ctx, item, exp, bind_name, bind_len);
                }
            }
        }
        if ((((*decl)).import_stmt).count > 0 && (m).module_name != nil)
        {
            mname_len = (m).module_name_len;
            unit_exp = mh_module_find(&m, (m).module_name, mname_len);
            if (unit_exp != nil)
            {
                if (symtab_lookup_current(((*ctx)).scope, (m).module_name, mname_len) == nil)
                {
                    semantic_bind_mh_export(ctx, decl, unit_exp, (m).module_name, mname_len);
                }
            }
        }
        mh_module_free(&m);
    }
    else
    {
        {
            const long long __for_end_l2066 = (long long)((((*decl)).import_stmt).count);
            for (i = 1; (long long)(i) <= __for_end_l2066; i++)
            {
                {
                    semantic_register_import_item(ctx, (((*decl)).import_stmt).items[i - 1]);
                }
            }
        }
    }
}

/**
 * Register a parameter list (NODE_PARAM_LIST or program_decl.params array).
 */
static void semantic_register_param_list(pTSemanticContext ctx, pNode* params, size_t count)
{
    size_t i = 0;
    {
        const long long __for_end_l2080 = (long long)(count);
        for (i = 1; (long long)(i) <= __for_end_l2080; i++)
        {
            {
                const pNode param_l2081_c12 = params[i - 1];
                if (param_l2081_c12 == nil || ((*param_l2081_c12)).kind != NODE_PARAM)
                {
                    semantic_error_at(param_l2081_c12, "semantic_register_param_list: internal error: expected parameter");
                }
                if ((((*param_l2081_c12)).param).name == nil || (((*param_l2081_c12)).param).name_len == 0)
                {
                    semantic_error_at(param_l2081_c12, "semantic_register_param_list: parameter has no name");
                }
                if ((((*param_l2081_c12)).param).param_type != nil)
                {
                    semantic_resolve_type(ctx, (((*param_l2081_c12)).param).param_type, param_l2081_c12);
                }
                semantic_define(ctx, SYM_KIND_PARAM, (((*param_l2081_c12)).param).name, (((*param_l2081_c12)).param).name_len, (((*param_l2081_c12)).param).param_type, param_l2081_c12, false);
            }
        }
    }
}

/**
 * Register one builtin type in the semantic prelude (global scop).
 */
static void semantic_register_prelude_builtin(pTSemanticContext ctx, const char* name, size_t name_len)
{
    pTSymbol sym = nil;
    TType* ty = nil;
    if (ctx == nil || ((*ctx)).scope == nil)
    {
        semantic_error_at(nil, "semantic_register_prelude_builtin: internal error: no active scope");
    }
    ty = type_create_named(((*ctx)).arena, name, name_len);
    sym = symbol_create(((*ctx)).arena, SYM_KIND_TYPE, name, name_len, nil);
    ((*sym)).symbol_type = ty;
    symtab_define(((*ctx)).arena, ((*ctx)).scope, sym);
}

/**
 * Install builtin types into the program/module global scope.
 * See docs/grammar.md - bool, byte, char, integer, cardinal, real, string.
 */
static void semantic_register_prelude(pTSemanticContext ctx)
{
    semantic_register_prelude_builtin(ctx, "bool", 4);
    semantic_register_prelude_builtin(ctx, "bit", 3);
    semantic_register_prelude_builtin(ctx, "int", 3);
    semantic_register_prelude_builtin(ctx, "byte", 4);
    semantic_register_prelude_builtin(ctx, "char", 4);
    semantic_register_prelude_builtin(ctx, "real", 4);
    semantic_register_prelude_builtin(ctx, "long", 4);
    semantic_register_prelude_builtin(ctx, "float", 5);
    semantic_register_prelude_builtin(ctx, "short", 5);
    semantic_register_prelude_builtin(ctx, "double", 6);
    semantic_register_prelude_builtin(ctx, "string", 6);
    semantic_register_prelude_builtin(ctx, "integer", 7);
    semantic_register_prelude_builtin(ctx, "cardinal", 8);
}

/**
 * True for literal spellings the parser still emits as NODE_IDENT.
 * Case-insensitive (Mod-c keyword rules). Remove when lexer owns NIL/TRUE/FALSE.
 */
static bool semantic_is_literal_ident(const char* name, size_t name_len)
{
    if (name == nil || name_len == 0)
    {
        /* return value captured before defers */
        bool __ret_l2148 = false;
        return __ret_l2148;
    }
    else if (name_len == 3)
    {
        /* return value captured before defers */
        bool __ret_l2150 = strncasecmp(name, "nil", 3) == 0 || memcmp(name, "NaN", 3) == 0;
        return __ret_l2150;
    }
    else if (name_len == 4)
    {
        /* return value captured before defers */
        bool __ret_l2153 = strncasecmp(name, "true", 4) == 0;
        return __ret_l2153;
    }
    else if (name_len == 5)
    {
        /* return value captured before defers */
        bool __ret_l2155 = strncasecmp(name, "false", 5) == 0;
        return __ret_l2155;
    }
    else
    {
        /* return value captured before defers */
        bool __ret_l2157 = false;
        return __ret_l2157;
    }
}

/**
 * Resolve one identifier use.
 */
static void semantic_resolve_ident(pTSemanticContext ctx, pNode n)
{
    pTSymbol sym = nil;
    const char* name = nil;
    size_t name_len = 0;
    if (n == nil || ((*n)).kind != NODE_IDENT)
    {
                return;
    }
    name = (((*n)).token).start;
    name_len = (((*n)).token).length;
    if (name == nil || name_len == 0)
    {
        semantic_error_at(n, "semantic_resolve_ident: internal error: identifier has no token text");
    }
    if (semantic_is_literal_ident(name, name_len))
    {
                return;
    }
    sym = symtab_lookup(((*ctx)).scope, name, name_len);
    if (sym == nil)
    {
        semantic_error_at(n, "semantic_resolve_ident: undefined identifier");
    }
    ((*n)).resolved_sym = sym;
}

/**
 * Build linker name Type__method in arena storage.
 */
static char* semantic_mangle_method(Arena* arena, const char* owner, size_t owner_len, const char* method, size_t method_len)
{
    size_t total = owner_len + 2 + method_len;
    char* buf = (char*)arena_alloc(arena, total + 1);
    memcpy(buf, owner, owner_len);
    buf[owner_len] = '_';
    buf[owner_len + 1] = '_';
    memcpy(buf + owner_len + 2, method, method_len);
    buf[total] = '\0';
    /* return value captured before defers */
    char* __ret_l2208 = buf;
    return __ret_l2208;
}

/**
 * Symtab registration name: Type__method for qualified decls, plan name otherwise.
 */
static TProcSymName semantic_proc_sym_name(pTSemanticContext ctx, pNode decl)
{
    TProcSymName result = {0};
    if ((((*decl)).proc_decl).method_owner != nil && (((*decl)).proc_decl).method_owner_len > 0)
    {
        (result).name = semantic_mangle_method(((*ctx)).arena, (((*decl)).proc_decl).method_owner, (((*decl)).proc_decl).method_owner_len, (((*decl)).proc_decl).name, (((*decl)).proc_decl).name_len);
        (result).length = (((*decl)).proc_decl).method_owner_len + 2 + (((*decl)).proc_decl).name_len;
    }
    else
    {
        (result).name = (((*decl)).proc_decl).name;
        (result).length = (((*decl)).proc_decl).name_len;
    }
    /* return value captured before defers */
    TProcSymName __ret_l2229 = result;
    return __ret_l2229;
}

/**
 * True if decl is a Type:: method whose first formal type is the owner type
 * (instance method). Formal name is free (Oberon-style; need not be "self").
 * False => static / factory: no formals, or first formal type <> owner, or
 * not a type-qualified method. Poitner first formals are not instance in v1.
 */
static bool semantic_method_is_instance(pTSemanticContext ctx, pNode decl)
{
    pNode params_list = nil;
    pNode self_param = nil;
    pTType pt = nil;
    const char* owner = nil;
    size_t owner_len = 0;
    if (decl == nil)
    {
        /* return value captured before defers */
        bool __ret_l2248 = false;
        return __ret_l2248;
    }
    if (((*decl)).kind != NODE_PROC_DECL && ((*decl)).kind != NODE_FUNC_DECL)
    {
        /* return value captured before defers */
        bool __ret_l2252 = false;
        return __ret_l2252;
    }
    owner = (((*decl)).proc_decl).method_owner;
    owner_len = (((*decl)).proc_decl).method_owner_len;
    if (owner == nil || owner_len == 0)
    {
        /* return value captured before defers */
        bool __ret_l2258 = false;
        return __ret_l2258;
    }
    params_list = (((*decl)).proc_decl).params;
    if (params_list == nil || ((*params_list)).kind != NODE_PARAM_LIST || (((*params_list)).param_list).count == 0)
    {
        /* return value captured before defers */
        bool __ret_l2264 = false;
        return __ret_l2264;
    }
    self_param = (((*params_list)).param_list).params[0];
    if (self_param == nil || ((*self_param)).kind != NODE_PARAM)
    {
        /* return value captured before defers */
        bool __ret_l2269 = false;
        return __ret_l2269;
    }
    pt = (((*self_param)).param).param_type;
    if (pt == nil)
    {
        /* return value captured before defers */
        bool __ret_l2274 = false;
        return __ret_l2274;
    }
    semantic_resolve_type(ctx, pt, self_param);
    if (((*pt)).resolved_type != nil)
    {
        pt = ((*pt)).resolved_type;
    }
    if (((*pt)).is_pointer || ((*pt)).is_array)
    {
        /* return value captured before defers */
        bool __ret_l2284 = false;
        return __ret_l2284;
    }
    if (((*pt)).name == nil || ((*pt)).name_len == 0)
    {
        /* return value captured before defers */
        bool __ret_l2287 = false;
        return __ret_l2287;
    }
    /* return value captured before defers */
    bool __ret_l2289 = semantic_names_equal(((*pt)).name, ((*pt)).name_len, owner, owner_len);
    return __ret_l2289;
}

/**
 * Type:: methods: instance vs static is determined by first formal type
 * (see semantic_method_is_instance). Both forms are legal at declaration;
 * resolve first formal type early so bad type names still fail here.
 */
static void semantic_verify_method_self(pTSemanticContext ctx, pNode decl)
{
    (semantic_method_is_instance(ctx, decl));
}

/**
 * If ty names TYPE ... = PROCEDURE/FUNCTION ... return NODE_METHOD_TYPE (else nil).
 */
static pNode semantic_method_type_node(pTSemanticContext ctx, pTType ty)
{
    pTType t = ty;
    pTSymbol sym = nil;
    if (ctx == nil || t == nil)
    {
        /* return value captured before defers */
        pNode __ret_l2318 = nil;
        return __ret_l2318;
    }
    if (((*t)).resolved_type != nil)
    {
        t = ((*t)).resolved_type;
    }
    if (((*t)).name == nil || ((*t)).name_len == 0)
    {
        /* return value captured before defers */
        pNode __ret_l2324 = nil;
        return __ret_l2324;
    }
    sym = symtab_lookup(((*ctx)).scope, ((*t)).name, ((*t)).name_len);
    if (sym == nil || ((*sym)).kind != SYM_KIND_TYPE || ((*sym)).decl == nil)
    {
        /* return value captured before defers */
        pNode __ret_l2328 = nil;
        return __ret_l2328;
    }
    if (((*((*sym)).decl)).kind != NODE_TYPE_DECL)
    {
        /* return value captured before defers */
        pNode __ret_l2331 = nil;
        return __ret_l2331;
    }
    /* return value captured before defers */
    pNode __ret_l2333 = (((*((*sym)).decl)).type_decl).method_type;
    return __ret_l2333;
}

/**
 * semantic_field_type_on
 */
static pTType semantic_field_type_on(pTSemanticContext ctx, pTType recv_ty, const char* fname, size_t flen)
{
    pNode st = nil;
    size_t i = 0;
    pNode f = nil;
    if (ctx == nil || recv_ty == nil || fname == nil)
    {
        /* return value captured before defers */
        pTType __ret_l2348 = nil;
        return __ret_l2348;
    }
    st = semantic_struct_body_of_type(ctx, recv_ty);
    while (st != nil)
    {
        {
            {
                const long long __for_end_l2352 = (long long)((((*st)).struct_decl).field_count);
                for (i = 1; (long long)(i) <= __for_end_l2352; i++)
                {
                    {
                        f = (((*st)).struct_decl).fields[i - 1];
                        if (f != nil && semantic_names_equal((((*f)).field_decl).name, (((*f)).field_decl).name_len, fname, flen))
                        {
                            /* return value captured before defers */
                            pTType __ret_l2356 = (((*f)).field_decl).field_type;
                            return __ret_l2356;
                        }
                    }
                }
            }
            if ((((*st)).struct_decl).extends_type == nil)
            {
                /* return value captured before defers */
                pTType __ret_l2360 = nil;
                return __ret_l2360;
            }
            st = semantic_struct_body_of_type(ctx, (((*st)).struct_decl).extends_type);
        }
    }
    /* return value captured before defers */
    pTType __ret_l2364 = nil;
    return __ret_l2364;
}

/**
 * semantic_sym_is_method_value
 */
static bool semantic_sym_is_method_value(pTSemanticContext ctx, pTSymbol sym)
{
    if (sym == nil)
    {
        /* return value captured before defers */
        bool __ret_l2374 = false;
        return __ret_l2374;
    }
    if (((*sym)).kind != SYM_KIND_VAR && ((*sym)).kind != SYM_KIND_PARAM && ((*sym)).kind != SYM_KIND_LET && ((*sym)).kind != SYM_KIND_CONST)
    {
        /* return value captured before defers */
        bool __ret_l2378 = false;
        return __ret_l2378;
    }
    /* return value captured before defers */
    bool __ret_l2380 = semantic_method_type_node(ctx, ((*sym)).symbol_type) != nil;
    return __ret_l2380;
}

/**
 * Resolve a call target (procedure/function) and its arguments.
 * Type::name uses method_owner from the parser.
 * obj.method (item 21): instance Type__method; receiver prepended in codegen.
 * obj.field: method-typed field call-through (Oberon: no auto-self); callee_expr
 * Ambiguity if both instance method and method-typed field share the name
 * Free name: PROC/FUNC/IMPORT, or VAR/PARAM/LET/CONST of method type.
 * Unresolved free names and Type::name are errors (0.26).
 */
static void semantic_resolve_call(pTSemanticContext ctx, pNode n)
{
    pTSymbol sym = nil;
    const char* lookup_name = nil;
    size_t lookup_len = 0;
    char* mangled = nil;
    size_t i = 0;
    pTType recv_ty = nil;
    const char* owner = nil;
    size_t owner_len = 0;
    pNode pl = nil;
    pNode* formals = nil;
    size_t fcount = 0;
    size_t fi = 0;
    pNode formal = nil;
    size_t formal_index = 0;
    bool has_receiver = false;
    pTType field_ty = nil;
    pNode mt = nil;
    bool is_instance = false;
    bool field_callable = false;
    if (n == nil || ((*n)).kind != NODE_CALL)
    {
                return;
    }
    if ((((*n)).call).receiver_expr != nil)
    {
        has_receiver = true;
        semantic_resolve_expr(ctx, (((*n)).call).receiver_expr);
        recv_ty = semantic_type_of_expr(ctx, (((*n)).call).receiver_expr);
        if (recv_ty == nil)
        {
            semantic_error_at(n, "semantic_resolve_call: cannot determine type of method receiver");
        }
        (((*n)).call).auto_deref = semantic_type_is_pointer(recv_ty);
        if (((*recv_ty)).resolved_type != nil)
        {
            recv_ty = ((*recv_ty)).resolved_type;
        }
        if (((*recv_ty)).name == nil || ((*recv_ty)).name_len == 0)
        {
            semantic_error_at(n, "semantic_resolve_call: method receiver has no named type");
        }
        owner = ((*recv_ty)).name;
        owner_len = ((*recv_ty)).name_len;
        mangled = semantic_mangle_method(((*ctx)).arena, owner, owner_len, (((*n)).call).name, (((*n)).call).name_len);
        sym = symtab_lookup(((*ctx)).scope, mangled, owner_len + 2 + (((*n)).call).name_len);
        is_instance = (sym != nil && (((*sym)).is_method_instance || (((*sym)).decl != nil && semantic_method_is_instance(ctx, ((*sym)).decl))));
        field_ty = semantic_field_type_on(ctx, recv_ty, (((*n)).call).name, (((*n)).call).name_len);
        mt = semantic_method_type_node(ctx, field_ty);
        field_callable = (mt != nil);
        if (is_instance && field_callable)
        {
            semantic_error_at(n, "semantic_resolve_call: ambiguous obj.name(...): instance method and callable field; use Type::name(obj, ...)");
        }
        if (is_instance)
        {
            (((*n)).call).method_owner = owner;
            (((*n)).call).method_owner_len = owner_len;
            (((*n)).call).callee_expr = nil;
            ((*n)).resolved_sym = sym;
        }
        else if (field_callable)
        {
            if ((((*n)).call).callee_expr == nil)
            {
                semantic_error_at(n, "semantic_resolve_call: integernal: missing field callee_expr");
            }
            semantic_resolve_expr(ctx, (((*n)).call).callee_expr);
            (((*n)).call).receiver_expr = nil;
            (((*n)).call).method_owner = nil;
            (((*n)).call).method_owner_len = 0;
            (((*n)).call).auto_deref = false;
            ((*n)).resolved_sym = nil;
            sym = nil;
            has_receiver = false;
        }
        else if (sym != nil)
        {
            semantic_error_at(n, "semantic_resolve_call: static method cannot be called with instance syntax: use Type::name(...)");
        }
        else
        {
            semantic_error_at(n, "semantic_resolve_call: undefined type-bound method or non-callable field");
        }
    }
    else
    {
        if ((((*n)).call).method_owner != nil && (((*n)).call).method_owner_len > 0)
        {
            mangled = semantic_mangle_method(((*ctx)).arena, (((*n)).call).method_owner, (((*n)).call).method_owner_len, (((*n)).call).name, (((*n)).call).name_len);
            lookup_name = mangled;
            lookup_len = (((*n)).call).method_owner_len + 2 + (((*n)).call).name_len;
        }
        else
        {
            lookup_name = (((*n)).call).name;
            lookup_len = (((*n)).call).name_len;
        }
        sym = symtab_lookup(((*ctx)).scope, lookup_name, lookup_len);
        if (sym != nil)
        {
            if (((*sym)).kind != SYM_KIND_PROC && ((*sym)).kind != SYM_KIND_FUNC && ((*sym)).kind != SYM_KIND_IMPORT && !semantic_sym_is_method_value(ctx, sym))
            {
                semantic_error_at(n, "semantic_resolve_call: identifier isnot callable");
            }
        }
        else
        {
            if ((((*n)).call).method_owner != nil && (((*n)).call).method_owner_len > 0)
            {
                semantic_error_at(n, "semantic_resolve_call: undefined type-bound method");
            }
            else
            {
                semantic_error_at(n, "semantic_resolve_call: undefined procedure or function");
            }
        }
        ((*n)).resolved_sym = sym;
    }
    {
        const long long __for_end_l2557 = (long long)((((*n)).call).argc);
        for (i = 1; (long long)(i) <= __for_end_l2557; i++)
        {
            {
                semantic_resolve_expr(ctx, (((*n)).call).args[i - 1]);
            }
        }
    }
    if ((((*n)).call).receiver_expr == nil && (((*n)).call).method_owner != nil && (((*n)).call).argc > 0 && ((*n)).resolved_sym != nil && (((*((*n)).resolved_sym)).is_method_instance || (((*((*n)).resolved_sym)).decl != nil && semantic_method_is_instance(ctx, ((*((*n)).resolved_sym)).decl))))
    {
        (((*n)).call).auto_deref = false;
        {
            pTType arg_ty = nil;
            pNode arg0 = (((*n)).call).args[0];
            if (((*arg0)).kind == NODE_UNARY && (((*arg0)).unary).op == TOK_AT)
            {
            }
            else
            {
                arg_ty = semantic_type_of_expr(ctx, (((*n)).call).args[0]);
                if (semantic_type_is_pointer(arg_ty))
                {
                    if (((*arg_ty)).resolved_type != nil)
                    {
                        arg_ty = ((*arg_ty)).resolved_type;
                    }
                    if (((*arg_ty)).name != nil && semantic_names_equal(((*arg_ty)).name, ((*arg_ty)).name_len, (((*n)).call).method_owner, (((*n)).call).method_owner_len))
                    {
                        (((*n)).call).auto_deref = true;
                    }
                }
            }
        }
    }
    sym = ((*n)).resolved_sym;
    if (((*ctx)).enclosing_func != nil && (((*((*ctx)).enclosing_func)).kind == NODE_PROC_DECL || ((*((*ctx)).enclosing_func)).kind == NODE_FUNC_DECL) && sym != nil && ((*sym)).decl == ((*ctx)).enclosing_func && !(((*((*ctx)).enclosing_func)).proc_decl).is_recursive)
    {
        semantic_error_at(n, "semantic_resolve_call: direct recursion requires RECURSIVE");
    }
    if (sym != nil && ((*sym)).decl != nil && (((*((*sym)).decl)).kind == NODE_PROC_DECL || ((*((*sym)).decl)).kind == NODE_FUNC_DECL))
    {
        pl = (((*((*sym)).decl)).proc_decl).params;
        formals = nil;
        fcount = 0;
        if (pl != nil && ((*pl)).kind == NODE_PARAM_LIST)
        {
            formals = (((*pl)).param_list).params;
            fcount = (((*pl)).param_list).count;
        }
        if (has_receiver && fcount > 0 && formals != nil)
        {
            formal = formals[0];
            if (formal != nil && ((*formal)).kind == NODE_PARAM && (((*formal)).param).param_type != nil)
            {
                semantic_maybe_upcast(ctx, (((*n)).call).receiver_expr, (((*formal)).param).param_type);
            }
            formal_index = 1;
        }
        else
        {
            formal_index = 0;
        }
        {
            const long long __for_end_l2629 = (long long)((((*n)).call).argc);
            for (fi = 1; (long long)(fi) <= __for_end_l2629; fi++)
            {
                {
                    if (formal_index >= fcount)
                    {
                                                /* INVARIANT (on loop exit) */
                        break;
                    }
                    formal = formals[formal_index];
                    if (formal != nil && ((*formal)).kind == NODE_PARAM && (((*formal)).param).param_type != nil)
                    {
                        semantic_maybe_upcast(ctx, (((*n)).call).args[fi - 1], (((*formal)).param).param_type);
                    }
                    formal_index = formal_index + 1;
                }
            }
        }
    }
}

/**
 * Resolve SIZEOF operand: validate type names; designators must not be types.
 */
static void semantic_resolve_sizeof(pTSemanticContext ctx, pNode n)
{
    pTSymbol sym = nil;
    pTType ty = nil;
    const char* name = nil;
    size_t name_len = 0;
    pNode d = nil;
    if (n == nil || ((*n)).kind != NODE_SIZEOF)
    {
                return;
    }
    if ((((*n)).sizeof_expr).is_type)
    {
        ty = ((((*n)).sizeof_expr).target).sizeof_type;
        if (ty == nil || ((*ty)).name == nil || ((*ty)).name_len == 0)
        {
            semantic_error_at(n, "semantic_resolve_sizeof: SIZEOF type operand has no name");
        }
        name = ((*ty)).name;
        name_len = ((*ty)).name_len;
        if (!type_is_builtin_name(name, name_len))
        {
            sym = symtab_lookup(((*ctx)).scope, name, name_len);
            if (sym == nil || ((*sym)).kind != SYM_KIND_TYPE)
            {
                semantic_error_at(n, "semantic_resolve_sizeof: unknown type in SIZEOF");
            }
        }
        semantic_resolve_type(ctx, ty, n);
    }
    else
    {
        d = ((((*n)).sizeof_expr).target).designator;
        if (d == nil)
        {
            semantic_error_at(n, "semantic_resolve_sizeof: SIZEOF designator missing");
        }
        if (((*d)).kind == NODE_IDENT)
        {
            name = (((*d)).token).start;
            name_len = (((*d)).token).length;
            if (name != nil && name_len > 0)
            {
                if (type_is_builtin_name(name, name_len))
                {
                    semantic_error_at(n, "semantic_resolve_sizeof: builtin type name requires SIZEOF(type), not a value");
                }
                sym = symtab_lookup(((*ctx)).scope, name, name_len);
                if (sym != nil && ((*sym)).kind == SYM_KIND_TYPE)
                {
                    semantic_error_at(n, "semantic_resolve_sizeof: type name requires SIZEOF(type), not a value");
                }
            }
        }
        semantic_resolve_expr(ctx, d);
    }
}

/**
 * Walk an expression tree and resole identifier/call uses.
 */
static void semantic_resolve_expr(pTSemanticContext ctx, pNode n)
{
    if (n == nil)
    {
                return;
    }
    switch (((*n)).kind)
    {
        case NODE_IDENT:
        {
            semantic_resolve_ident(ctx, n);
        }
        break;
        case NODE_CALL:
        {
            semantic_resolve_call(ctx, n);
        }
        break;
        case NODE_BINARY:
        {
            semantic_resolve_expr(ctx, (((*n)).binary).left);
            semantic_resolve_expr(ctx, (((*n)).binary).right);
        }
        break;
        case NODE_UNARY:
        {
            semantic_resolve_expr(ctx, (((*n)).unary).operand);
        }
        break;
        case NODE_PAREN:
        {
            semantic_resolve_expr(ctx, (((*n)).paren).expr);
        }
        break;
        case NODE_CAST:
        {
            if ((((*n)).cast_expr).target_type != nil)
            {
                semantic_resolve_type(ctx, (((*n)).cast_expr).target_type, n);
            }
            semantic_resolve_expr(ctx, (((*n)).cast_expr).expr);
            if ((((*n)).cast_expr).target_type != nil)
            {
                pTType inner_ty = nil;
                size_t d = 0;
                inner_ty = semantic_type_of_expr(ctx, (((*n)).cast_expr).expr);
                d = semantic_extends_upcast_depth(ctx, inner_ty, (((*n)).cast_expr).target_type);
                if (d > 0)
                {
                    ((*n)).upcast_depth = d;
                    ((*n)).upcast_ptr = ((*inner_ty)).is_pointer;
                }
            }
        }
        break;
        case NODE_TERNARY:
        {
            semantic_resolve_expr(ctx, (((*n)).ternary).cond);
            semantic_resolve_expr(ctx, (((*n)).ternary).then_expr);
            semantic_resolve_expr(ctx, (((*n)).ternary).else_expr);
        }
        break;
        case NODE_ARRAY_INDEX:
        {
            semantic_resolve_expr(ctx, (((*n)).array_index).array_);
            semantic_resolve_expr(ctx, (((*n)).array_index).index);
            (((*n)).array_index).auto_deref = false;
            {
                pTType arr_ty = nil;
                arr_ty = semantic_type_of_designator(ctx, (((*n)).array_index).array_);
                if (semantic_type_is_pointer_to_array(arr_ty))
                {
                    (((*n)).array_index).auto_deref = true;
                }
            }
        }
        break;
        case NODE_FIELD_ACCESS:
        {
            semantic_resolve_expr(ctx, (((*n)).field_access).record_);
            {
                pTType rec_ty = nil;
                pNode st = nil;
                size_t depth = 0;
                (((*n)).field_access).base_depth = 0;
                (((*n)).field_access).auto_deref = false;
                rec_ty = semantic_type_of_designator(ctx, (((*n)).field_access).record_);
                if (semantic_type_is_pointer(rec_ty))
                {
                    (((*n)).field_access).auto_deref = true;
                }
                st = semantic_struct_body_of_type(ctx, rec_ty);
                if (st != nil)
                {
                    if (semantic_find_field_depth(ctx, st, (((*n)).field_access).field_name, (((*n)).field_access).field_len, &depth))
                    {
                        (((*n)).field_access).base_depth = depth;
                    }
                    else
                    {
                        semantic_error_at(n, "semantic_resolve_expr, unknown field for STRUCT type");
                    }
                }
            }
        }
        break;
        case NODE_SIZEOF:
        {
            semantic_resolve_sizeof(ctx, n);
        }
        break;
        case NODE_LITERAL:
        case NODE_ARRAY_LITERAL:
        {
        }
        break;
        case NODE_INC:
        case NODE_DEC:
        {
            semantic_resolve_expr(ctx, (((*n)).binary).left);
            if ((((*n)).binary).right != nil)
            {
                semantic_resolve_expr(ctx, (((*n)).binary).right);
            }
        }
        break;
        default:
        {
        }
        break;
    }
}

/**
 * Register VAR / CONST / LET items from a declaration node.
 */
static void semantic_register_var_decl(pTSemanticContext ctx, pNode decl, SymbolKind kind)
{
    size_t i = 0;
    size_t count = 0;
    pNode* items = nil;
    bool is_exported = false;
    if (decl == nil)
    {
                return;
    }
    if (kind == SYM_KIND_VAR && ((*decl)).kind == NODE_VAR_DECL)
    {
        count = (((*decl)).var_decl).count;
        items = (((*decl)).var_decl).items;
        is_exported = (((*decl)).var_decl).is_exported;
    }
    else if (kind == SYM_KIND_CONST && ((*decl)).kind == NODE_CONST_DECL)
    {
        count = (((*decl)).const_decl).count;
        items = (((*decl)).const_decl).items;
        is_exported = (((*decl)).const_decl).is_exported;
    }
    else if (kind == SYM_KIND_LET && ((*decl)).kind == NODE_LET_DECL)
    {
        count = (((*decl)).let_decl).count;
        items = (((*decl)).let_decl).items;
        is_exported = (((*decl)).let_decl).is_exported;
    }
    else
    {
        semantic_error_at(decl, "semantic_register_var_decl: internal error: unexpected var/const/let decl");
    }
    {
        const long long __for_end_l2844 = (long long)(count);
        for (i = 1; (long long)(i) <= __for_end_l2844; i++)
        {
            {
                const pNode item_l2845_c11 = items[i - 1];
                if (item_l2845_c11 == nil || (((*item_l2845_c11)).var_item).name == nil || (((*item_l2845_c11)).var_item).name_len == 0)
                {
                    semantic_error_at(decl, "semantic_register_var_decl: declaration item has no name");
                }
                if ((((*item_l2845_c11)).var_item).initializer != nil)
                {
                    semantic_resolve_expr(ctx, (((*item_l2845_c11)).var_item).initializer);
                }
                if ((((*item_l2845_c11)).var_item).item_type == nil && (((*item_l2845_c11)).var_item).initializer != nil)
                {
                    (((*item_l2845_c11)).var_item).item_type = semantic_type_of_expr(ctx, (((*item_l2845_c11)).var_item).initializer);
                    if ((((*item_l2845_c11)).var_item).item_type == nil)
                    {
                        semantic_error_at(item_l2845_c11, "semantic_register_var_decl: cannot infer type from initializer");
                    }
                }
                if ((((*item_l2845_c11)).var_item).item_type != nil)
                {
                    semantic_resolve_type(ctx, (((*item_l2845_c11)).var_item).item_type, item_l2845_c11);
                }
                if ((((*item_l2845_c11)).var_item).initializer != nil && (((*item_l2845_c11)).var_item).item_type != nil)
                {
                    semantic_maybe_upcast(ctx, (((*item_l2845_c11)).var_item).initializer, (((*item_l2845_c11)).var_item).item_type);
                }
                if (((*decl)).kind == NODE_VAR_DECL && (((*decl)).var_decl).is_extern)
                {
                    semantic_define_or_refine(ctx, kind, (((*item_l2845_c11)).var_item).name, (((*item_l2845_c11)).var_item).name_len, (((*item_l2845_c11)).var_item).item_type, item_l2845_c11, is_exported);
                }
                else
                {
                    semantic_define(ctx, kind, (((*item_l2845_c11)).var_item).name, (((*item_l2845_c11)).var_item).name_len, (((*item_l2845_c11)).var_item).item_type, item_l2845_c11, is_exported);
                }
                if (kind == SYM_KIND_CONST && (((*item_l2845_c11)).var_item).initializer != nil)
                {
                    pTSymbol csym = nil;
                    integer cval = 0;
                    csym = symtab_lookup_current(((*ctx)).scope, (((*item_l2845_c11)).var_item).name, (((*item_l2845_c11)).var_item).name_len);
                    if (csym == nil)
                    {
                        semantic_error_at(item_l2845_c11, "semantic_register_var_decl: CONST not in scope after define");
                    }
                    if (semantic_try_eval_const_expr(ctx, (((*item_l2845_c11)).var_item).initializer, &cval, nil))
                    {
                        ((*csym)).has_const_value = true;
                        ((*csym)).const_value = cval;
                    }
                }
            }
        }
    }
}

/**
 * Resolve uses in one statement (no declaration registration).
 */
static void semantic_resolve_stmt(pTSemanticContext ctx, pNode n)
{
    size_t i = 0;
    size_t j = 0;
    SwitchCase* sc = nil;
    if (n == nil)
    {
                return;
    }
    switch (((*n)).kind)
    {
        case NODE_EXPR_STMT:
        {
            {
                pNode e = (((*n)).expr_stmt).expr;
                pTType ty = nil;
                semantic_resolve_expr(ctx, e);
                if (e != nil && ((*e)).kind == NODE_CALL)
                {
                    ty = semantic_type_of_expr(ctx, e);
                    if (ty != nil)
                    {
                        semantic_error_at(e, "semantic_resolve_stmt: bare call discards a known result; use (f()) to discard");
                    }
                }
            }
        }
        break;
        case NODE_ASSIGN:
        {
            semantic_forbid_for_control_write(ctx, (((*n)).binary).left);
            semantic_resolve_expr(ctx, (((*n)).binary).left);
            semantic_forbid_param_mode_write((((*n)).binary).left);
            semantic_resolve_expr(ctx, (((*n)).binary).right);
            {
                pTType lhs_ty = nil;
                lhs_ty = semantic_type_of_expr(ctx, (((*n)).binary).left);
                semantic_maybe_upcast(ctx, (((*n)).binary).right, lhs_ty);
            }
        }
        break;
        case NODE_IF:
        {
            semantic_resolve_expr(ctx, (((*n)).if_stmt).cond);
            semantic_analyze_stmt_or_block(ctx, (((*n)).if_stmt).then_);
            semantic_resolve_elsif_chain(ctx, (((*n)).if_stmt).elsif_);
            semantic_analyze_stmt_or_block(ctx, (((*n)).if_stmt).else_);
        }
        break;
        case NODE_FOR:
        {
            const char* saved_name = nil;
            size_t saved_len = 0;
            semantic_resolve_expr(ctx, (((*n)).for_stmt).start_);
            semantic_resolve_expr(ctx, (((*n)).for_stmt).end_);
            {
                const long long __for_end_l2952 = (long long)((((*n)).for_stmt).invariant_count);
                for (i = 1; (long long)(i) <= __for_end_l2952; i++)
                {
                    {
                        semantic_resolve_expr(ctx, (((*n)).for_stmt).invariants[i - 1]);
                    }
                }
            }
            saved_name = ((*ctx)).for_var_name;
            saved_len = ((*ctx)).for_var_len;
            ((*ctx)).for_var_name = (((*n)).for_stmt).var_name;
            ((*ctx)).for_var_len = (((*n)).for_stmt).var_len;
            semantic_analyze_stmt_or_block(ctx, (((*n)).for_stmt).body);
            ((*ctx)).for_var_name = saved_name;
            ((*ctx)).for_var_len = saved_len;
        }
        break;
        case NODE_WHILE:
        {
            semantic_resolve_expr(ctx, (((*n)).while_stmt).cond);
            {
                const long long __for_end_l2966 = (long long)((((*n)).while_stmt).invariant_count);
                for (i = 1; (long long)(i) <= __for_end_l2966; i++)
                {
                    {
                        semantic_resolve_expr(ctx, (((*n)).while_stmt).invariants[i - 1]);
                    }
                }
            }
            semantic_analyze_stmt_or_block(ctx, (((*n)).while_stmt).body);
        }
        break;
        case NODE_REPEAT_UNTIL:
        {
            semantic_analyze_stmt_or_block(ctx, (((*n)).repeat_until).body);
            semantic_resolve_expr(ctx, (((*n)).repeat_until).cond);
            {
                const long long __for_end_l2974 = (long long)((((*n)).repeat_until).invariant_count);
                for (i = 1; (long long)(i) <= __for_end_l2974; i++)
                {
                    {
                        semantic_resolve_expr(ctx, (((*n)).repeat_until).invariants[i - 1]);
                    }
                }
            }
        }
        break;
        case NODE_LOOP:
        {
            {
                const long long __for_end_l2979 = (long long)((((*n)).loop_stmt).invariant_count);
                for (i = 1; (long long)(i) <= __for_end_l2979; i++)
                {
                    {
                        semantic_resolve_expr(ctx, (((*n)).loop_stmt).invariants[i - 1]);
                    }
                }
            }
            semantic_analyze_stmt_or_block(ctx, (((*n)).loop_stmt).body);
        }
        break;
        case NODE_RETURN:
        {
            if ((((*n)).ret).expr != nil)
            {
                semantic_resolve_expr(ctx, (((*n)).ret).expr);
                {
                    pTType ret_ty = nil;
                    pNode enc = ((*ctx)).enclosing_func;
                    if (enc != nil)
                    {
                        if (((*enc)).kind == NODE_FUNC_DECL || ((*enc)).kind == NODE_PROC_DECL)
                        {
                            ret_ty = (((*enc)).proc_decl).return_type;
                        }
                        else if (((*enc)).kind == NODE_PROGRAM)
                        {
                            ret_ty = (((*enc)).program_decl).return_type;
                        }
                    }
                    semantic_maybe_upcast(ctx, (((*n)).ret).expr, ret_ty);
                }
            }
        }
        break;
        case NODE_ASSERT:
        {
            semantic_resolve_expr(ctx, (((*n)).assert_stmt).condition);
            if ((((*n)).assert_stmt).const_expr != nil)
            {
                semantic_resolve_expr(ctx, (((*n)).assert_stmt).const_expr);
            }
        }
        break;
        case NODE_INC:
        case NODE_DEC:
        {
            semantic_forbid_for_control_write(ctx, (((*n)).binary).left);
            semantic_resolve_expr(ctx, (((*n)).binary).left);
            semantic_forbid_param_mode_write((((*n)).binary).left);
            if ((((*n)).binary).right != nil)
            {
                semantic_resolve_expr(ctx, (((*n)).binary).right);
            }
        }
        break;
        case NODE_DEFER:
        case NODE_DEBUG:
        {
            semantic_analyze_stmt_or_block(ctx, (((*n)).defer_stmt).action);
        }
        break;
        case NODE_SWITCH:
        {
            semantic_resolve_expr(ctx, (((*n)).switch_stmt).expr);
            {
                const long long __for_end_l3020 = (long long)((((*n)).switch_stmt).case_count);
                for (i = 1; (long long)(i) <= __for_end_l3020; i++)
                {
                    {
                        sc = (((*n)).switch_stmt).cases[i - 1];
                        if (sc != nil)
                        {
                            {
                                const long long __for_end_l3023 = (long long)(((*sc)).label_count);
                                for (j = 1; (long long)(j) <= __for_end_l3023; j++)
                                {
                                    {
                                        semantic_resolve_expr(ctx, ((*sc)).labels[j - 1]);
                                    }
                                }
                            }
                            semantic_analyze_stmt_or_block(ctx, ((*sc)).body);
                        }
                    }
                }
            }
            semantic_analyze_stmt_or_block(ctx, (((*n)).switch_stmt).else_body);
        }
        break;
        case NODE_BREAK:
        case NODE_CONTINUE:
        case NODE_DOC_COMMENT:
        case NODE_PREPROCESSOR:
        {
        }
        break;
        default:
        {
        }
        break;
    }
}

/**
 * Walk block statements: register local VAR/CONST/LET; recurese into nested BEGIN blocks.
 */
static void semantic_analyze_block_body(pTSemanticContext ctx, pNode block)
{
    size_t i = 0;
    pTSymbolTable saved = nil;
    pTSymbolTable inner = nil;
    if (block == nil || ((*block)).kind != NODE_BLOCK)
    {
                return;
    }
    {
        const long long __for_end_l3054 = (long long)((((*block)).block).require_count);
        for (i = 1; (long long)(i) <= __for_end_l3054; i++)
        {
            {
                semantic_resolve_expr(ctx, (((*block)).block).requires[i - 1]);
            }
        }
    }
    {
        const long long __for_end_l3058 = (long long)((((*block)).block).count);
        for (i = 1; (long long)(i) <= __for_end_l3058; i++)
        {
            {
                const pNode stmt_l3059_c11 = (((*block)).block).stmts[i - 1];
                if (stmt_l3059_c11 == nil)
                {
                                        /* INVARIANT (on loop exit) */
                    continue;
                }
                switch (((*stmt_l3059_c11)).kind)
                {
                    case NODE_VAR_DECL:
                    {
                        semantic_register_var_decl(ctx, stmt_l3059_c11, SYM_KIND_VAR);
                    }
                    break;
                    case NODE_CONST_DECL:
                    {
                        semantic_register_var_decl(ctx, stmt_l3059_c11, SYM_KIND_CONST);
                    }
                    break;
                    case NODE_LET_DECL:
                    {
                        semantic_register_var_decl(ctx, stmt_l3059_c11, SYM_KIND_LET);
                    }
                    break;
                    case NODE_BLOCK:
                    {
                        inner = symtab_create(((*ctx)).arena, ((*ctx)).scope);
                        saved = ((*ctx)).scope;
                        ((*ctx)).scope = inner;
                        semantic_analyze_block_body(ctx, stmt_l3059_c11);
                        ((*ctx)).scope = saved;
                    }
                    break;
                    default:
                    {
                        semantic_resolve_stmt(ctx, stmt_l3059_c11);
                    }
                    break;
                }
            }
        }
    }
    {
        const long long __for_end_l3100 = (long long)((((*block)).block).ensure_count);
        for (i = 1; (long long)(i) <= __for_end_l3100; i++)
        {
            {
                semantic_resolve_expr(ctx, (((*block)).block).ensures[i - 1]);
            }
        }
    }
}

/**
 * Analyze a statement body that may be a BLOCK or a single statement
 */
void semantic_analyze_stmt_or_block(pTSemanticContext ctx, pNode n)
{
    pTSymbolTable saved = nil;
    pTSymbolTable inner = nil;
    if (n == nil)
    {
                return;
    }
    else if (((*n)).kind == NODE_BLOCK)
    {
        inner = symtab_create(((*ctx)).arena, ((*ctx)).scope);
        saved = ((*ctx)).scope;
        ((*ctx)).scope = inner;
        semantic_analyze_block_body(ctx, n);
        ((*ctx)).scope = saved;
    }
    else
    {
        semantic_resolve_stmt(ctx, n);
    }
}

/**
 * Walk ELSIF chain o an IF node.
 */
void semantic_resolve_elsif_chain(pTSemanticContext ctx, pNode elsif_node)
{
    pNode last = nil;
    pNode elsif_ = elsif_node;
    while (elsif_ != nil)
    {
        {
            semantic_resolve_expr(ctx, (((*elsif_)).if_stmt).cond);
            semantic_analyze_stmt_or_block(ctx, (((*elsif_)).if_stmt).then_);
            last = elsif_;
            elsif_ = (((*elsif_)).if_stmt).elsif_;
        }
    }
    if (last != nil && (((*last)).if_stmt).else_ != nil)
    {
        semantic_analyze_stmt_or_block(ctx, (((*last)).if_stmt).else_);
    }
}

/**
 * Analyze a procedure or function body (params + locals in one scope).
 */
static void semantic_analyze_proc(pTSemanticContext ctx, pNode decl, pTSymbolTable global)
{
    pTSymbolTable body_scope = nil;
    pTSymbolTable saved = nil;
    pNode* params = nil;
    size_t param_count = 0;
    if (decl == nil)
    {
                return;
    }
    else if (((*decl)).kind != NODE_PROC_DECL && ((*decl)).kind != NODE_FUNC_DECL)
    {
        semantic_error_at(decl, "semantic_analyze_proc: internal error: expected procedure or function");
    }
    if ((((*decl)).proc_decl).body == nil)
    {
                return;
    }
    body_scope = symtab_create(((*ctx)).arena, global);
    saved = ((*ctx)).scope;
    ((*ctx)).scope = body_scope;
    ((*ctx)).enclosing_func = decl;
    semantic_verify_method_self(ctx, decl);
    if ((((*decl)).proc_decl).params != nil && ((*(((*decl)).proc_decl).params)).kind == NODE_PARAM_LIST)
    {
        params = (((*(((*decl)).proc_decl).params)).param_list).params;
        param_count = (((*(((*decl)).proc_decl).params)).param_list).count;
        semantic_register_param_list(ctx, params, param_count);
    }
    semantic_analyze_block_body(ctx, (((*decl)).proc_decl).body);
    ((*ctx)).enclosing_func = nil;
    ((*ctx)).scope = saved;
}

/**
 * Synthetic PROC/FUNC decl for this MODULE's entry (same formals as program_decl).
 * Codegen auto-& only looks at NODE_PROC_DECL / NODE_FUNC_DECL.
 */
static pNode semantic_make_unit_entry_decl(pTSemanticContext ctx, pNode root)
{
    pNode decl = nil;
    pNode pl = nil;
    NodeKind nkind = NODE_PROC_DECL;
    if (ctx == nil || root == nil || ((*root)).kind != NODE_PROGRAM)
    {
        /* return value captured before defers */
        pNode __ret_l3200 = nil;
        return __ret_l3200;
    }
    if ((((*root)).program_decl).unit_kind != TOK_KEYWORD_MODULE)
    {
        /* return value captured before defers */
        pNode __ret_l3203 = nil;
        return __ret_l3203;
    }
    if ((((*root)).program_decl).name == nil || (((*root)).program_decl).name_len == 0)
    {
        /* return value captured before defers */
        pNode __ret_l3206 = nil;
        return __ret_l3206;
    }
    if ((((*root)).program_decl).return_type != nil)
    {
        nkind = NODE_FUNC_DECL;
    }
    decl = node_create(((*ctx)).arena, nkind, ((*root)).token);
    (((*decl)).proc_decl).name = (((*root)).program_decl).name;
    (((*decl)).proc_decl).name_len = (((*root)).program_decl).name_len;
    (((*decl)).proc_decl).method_owner = nil;
    (((*decl)).proc_decl).method_owner_len = 0;
    (((*decl)).proc_decl).body = nil;
    (((*decl)).proc_decl).is_exported = true;
    (((*decl)).proc_decl).is_recursive = false;
    (((*decl)).proc_decl).is_extern = false;
    (((*decl)).proc_decl).is_forward = false;
    (((*decl)).proc_decl).is_function = (nkind == NODE_FUNC_DECL);
    (((*decl)).proc_decl).receiver = nil;
    (((*decl)).proc_decl).return_type = (((*root)).program_decl).return_type;
    pl = node_create(((*ctx)).arena, NODE_PARAM_LIST, ((*root)).token);
    (((*pl)).param_list).params = (((*root)).program_decl).params;
    (((*pl)).param_list).count = (((*root)).program_decl).param_count;
    (((*pl)).param_list).capacity = (((*root)).program_decl).param_capacity;
    (((*decl)).proc_decl).params = pl;
    /* return value captured before defers */
    pNode __ret_l3233 = decl;
    return __ret_l3233;
}

/**
 * Analyze PROGRAM / MODULE unit
 */
static void semantic_analyze_program(pTSemanticContext ctx, pNode root)
{
    size_t i = 0;
    pTSymbolTable global = nil;
    pTSymbolTable body_scope = nil;
    pTSymbolTable saved = nil;
    pNode unit_entry = nil;
    SymbolKind unit_kind = SYM_KIND_PROC;
    if (root == nil || ((*root)).kind != NODE_PROGRAM)
    {
        semantic_error_at(root, "semantic_analye_program: expected PROGRAM or MODULE root node");
    }
    global = symtab_create(((*ctx)).arena, nil);
    ((*ctx)).scope = global;
    semantic_register_prelude(ctx);
    {
        const long long __for_end_l3259 = (long long)((((*root)).program_decl).count);
        for (i = 1; (long long)(i) <= __for_end_l3259; i++)
        {
            {
                const pNode decl_l3260_c11 = (((*root)).program_decl).decls[i - 1];
                if (decl_l3260_c11 != nil && ((*decl_l3260_c11)).kind == NODE_IMPORT)
                {
                    semantic_register_import(ctx, decl_l3260_c11);
                }
            }
        }
    }
    {
        const long long __for_end_l3267 = (long long)((((*root)).program_decl).count);
        for (i = 1; (long long)(i) <= __for_end_l3267; i++)
        {
            {
                const pNode decl_l3268_c11 = (((*root)).program_decl).decls[i - 1];
                if (decl_l3268_c11 != nil && ((*decl_l3268_c11)).kind != NODE_IMPORT)
                {
                    semantic_register_decl(ctx, decl_l3268_c11);
                }
            }
        }
    }
    if ((((*root)).program_decl).unit_kind == TOK_KEYWORD_MODULE)
    {
        unit_entry = semantic_make_unit_entry_decl(ctx, root);
        if (unit_entry != nil)
        {
            if ((((*root)).program_decl).return_type != nil)
            {
                unit_kind = SYM_KIND_FUNC;
            }
            semantic_define(ctx, unit_kind, (((*root)).program_decl).name, (((*root)).program_decl).name_len, (((*root)).program_decl).return_type, unit_entry, true);
        }
    }
    semantic_resolve_type_decls(ctx, root);
    {
        const long long __for_end_l3291 = (long long)((((*root)).program_decl).count);
        for (i = 1; (long long)(i) <= __for_end_l3291; i++)
        {
            {
                const pNode decl_l3292_c11 = (((*root)).program_decl).decls[i - 1];
                if (decl_l3292_c11 != nil)
                {
                    if (((*decl_l3292_c11)).kind == NODE_PROC_DECL || ((*decl_l3292_c11)).kind == NODE_FUNC_DECL)
                    {
                        semantic_analyze_proc(ctx, decl_l3292_c11, global);
                    }
                }
            }
        }
    }
    if ((((*root)).program_decl).block != nil)
    {
        body_scope = symtab_create(((*ctx)).arena, global);
        saved = ((*ctx)).scope;
        ((*ctx)).scope = body_scope;
        ((*ctx)).enclosing_func = root;
        if ((((*root)).program_decl).param_count > 0)
        {
            if ((((*root)).program_decl).return_type != nil)
            {
                semantic_resolve_type(ctx, (((*root)).program_decl).return_type, root);
            }
            semantic_register_param_list(ctx, (((*root)).program_decl).params, (((*root)).program_decl).param_count);
        }
        semantic_analyze_block_body(ctx, (((*root)).program_decl).block);
        ((*ctx)).enclosing_func = nil;
        ((*ctx)).scope = saved;
    }
}

/**
 * Register one top-level (or scope-level) declaration.
 */
void semantic_register_decl(pTSemanticContext ctx, pNode decl)
{
    if (decl == nil)
    {
                return;
    }
    switch (((*decl)).kind)
    {
        case NODE_TYPE_DECL:
        {
            if ((((*decl)).type_decl).name == nil || (((*decl)).type_decl).name_len == 0)
            {
                semantic_error_at(decl, "semantic_register_decl: TYPE declaration has no name");
            }
            if ((((*decl)).type_decl).is_extern)
            {
                if ((((*decl)).type_decl).defined_type != nil)
                {
                    semantic_resolve_type(ctx, (((*decl)).type_decl).defined_type, decl);
                }
                semantic_define_or_refine(ctx, SYM_KIND_TYPE, (((*decl)).type_decl).name, (((*decl)).type_decl).name_len, (((*decl)).type_decl).defined_type, decl, (((*decl)).type_decl).is_exported);
            }
            else if ((((*decl)).type_decl).is_forward)
            {
                semantic_define_or_complete_forward(ctx, SYM_KIND_TYPE, (((*decl)).type_decl).name, (((*decl)).type_decl).name_len, nil, decl, (((*decl)).type_decl).is_exported);
            }
            else
            {
                semantic_define_or_complete_forward(ctx, SYM_KIND_TYPE, (((*decl)).type_decl).name, (((*decl)).type_decl).name_len, (((*decl)).type_decl).defined_type, decl, (((*decl)).type_decl).is_exported);
            }
        }
        break;
        case NODE_VAR_DECL:
        {
            semantic_register_var_decl(ctx, decl, SYM_KIND_VAR);
        }
        break;
        case NODE_CONST_DECL:
        {
            semantic_register_var_decl(ctx, decl, SYM_KIND_CONST);
        }
        break;
        case NODE_LET_DECL:
        {
            semantic_register_var_decl(ctx, decl, SYM_KIND_LET);
        }
        break;
        case NODE_PROC_DECL:
        {
            {
                TProcSymName sym = {0};
                if ((((*decl)).proc_decl).name == nil || (((*decl)).proc_decl).name_len == 0)
                {
                    semantic_error_at(decl, "semantic_register_decl: PROCEDURE has no name");
                }
                if ((((*decl)).proc_decl).return_type != nil)
                {
                    semantic_resolve_type(ctx, (((*decl)).proc_decl).return_type, decl);
                }
                sym = semantic_proc_sym_name(ctx, decl);
                if ((((*decl)).proc_decl).is_extern)
                {
                    semantic_define_or_refine(ctx, SYM_KIND_PROC, (sym).name, (sym).length, (((*decl)).proc_decl).return_type, decl, (((*decl)).proc_decl).is_exported);
                }
                else if ((((*decl)).proc_decl).is_forward || (((*decl)).proc_decl).body == nil)
                {
                    semantic_define_or_complete_forward(ctx, SYM_KIND_PROC, (sym).name, (sym).length, (((*decl)).proc_decl).return_type, decl, (((*decl)).proc_decl).is_exported);
                }
                else
                {
                    semantic_define_or_complete_forward(ctx, SYM_KIND_PROC, (sym).name, (sym).length, (((*decl)).proc_decl).return_type, decl, (((*decl)).proc_decl).is_exported);
                }
            }
        }
        break;
        case NODE_FUNC_DECL:
        {
            {
                TProcSymName sym = {0};
                if ((((*decl)).proc_decl).name == nil || (((*decl)).proc_decl).name_len == 0)
                {
                    semantic_error_at(decl, "semantic_register_decl: FUNCTION has no name");
                }
                if ((((*decl)).proc_decl).return_type != nil)
                {
                    semantic_resolve_type(ctx, (((*decl)).proc_decl).return_type, decl);
                }
                sym = semantic_proc_sym_name(ctx, decl);
                if ((((*decl)).proc_decl).is_extern)
                {
                    semantic_define_or_refine(ctx, SYM_KIND_FUNC, (sym).name, (sym).length, (((*decl)).proc_decl).return_type, decl, (((*decl)).proc_decl).is_exported);
                }
                else if ((((*decl)).proc_decl).is_forward || (((*decl)).proc_decl).body == nil)
                {
                    semantic_define_or_complete_forward(ctx, SYM_KIND_FUNC, (sym).name, (sym).length, (((*decl)).proc_decl).return_type, decl, (((*decl)).proc_decl).is_exported);
                }
                else
                {
                    semantic_define_or_complete_forward(ctx, SYM_KIND_FUNC, (sym).name, (sym).length, (((*decl)).proc_decl).return_type, decl, (((*decl)).proc_decl).is_exported);
                }
            }
        }
        break;
        case NODE_DOC_COMMENT:
        case NODE_PREPROCESSOR:
        case NODE_IMPORT:
        {
        }
        break;
        case NODE_PROGRAM:
        case NODE_VAR_ITEM:
        case NODE_CONST_ITEM:
        case NODE_LET_ITEM:
        case NODE_PARAM:
        case NODE_PARAM_LIST:
        case NODE_IMPORT_ITEM:
        case NODE_STRUCT_DECL:
        case NODE_FIELD_DECL:
        case NODE_METHOD_TYPE:
        case NODE_ARRAY_TYPE:
        case NODE_ARRAY_LITERAL:
        case NODE_ARRAY_INDEX:
        case NODE_FIELD_ACCESS:
        case NODE_BLOCK:
        case NODE_IF:
        case NODE_ELSIF:
        case NODE_ELSE:
        case NODE_FOR:
        case NODE_WHILE:
        case NODE_REPEAT_UNTIL:
        case NODE_LOOP:
        case NODE_BREAK:
        case NODE_CONTINUE:
        case NODE_RETURN:
        case NODE_EXPR_STMT:
        case NODE_ASSIGN:
        case NODE_ASSERT:
        case NODE_SIZEOF:
        case NODE_INC:
        case NODE_DEC:
        case NODE_DEFER:
        case NODE_DEBUG:
        case NODE_SWITCH:
        case NODE_PAREN:
        case NODE_BINARY:
        case NODE_UNARY:
        case NODE_CAST:
        case NODE_LITERAL:
        case NODE_IDENT:
        case NODE_CALL:
        case NODE_TERNARY:
        {
        }
        break;
        default:
        {
        }
        break;
    }
}

/**
 * Entry point: analyze AST after parsing, before codegen.
 * Exits on error; returns normally on success.
 */
void semantic_analyze(Arena* arena, pNode root, const char* source_path)
{
    TSemanticContext ctx = {0};
    if (arena == nil)
    {
        semantic_error_at(nil, "semantic_analyze: NULL arena");
    }
    else if (root == nil)
    {
        semantic_error_at(nil, "semantic_analyze: NULL AST root");
    }
    (ctx).arena = arena;
    (ctx).source_path = source_path;
    (ctx).scope = nil;
    (ctx).enclosing_func = nil;
    semantic_analyze_program(&ctx, root);
}


void semantic(void)
{
}
