Ctrl K
ComunidadGuías…

src/ast/ast.h

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// SPDX-License-Identifier: MIT

/**
 * @file ast.h
 * @brief AST node types, Type system, type introspection helpers.
 */

#ifndef ZC_ALLOW_INTERNAL
#error "ast/ast.h is internal to Zen C. Include the appropriate public header instead."
#endif

#ifndef AST_H
#define AST_H

#include "token.h"
#include <stdlib.h>

typedef struct ParserContext ParserContext;

// Forward declarations.
struct ASTNode;
typedef struct ASTNode ASTNode;

// ** Formal Type System **
// Used for Generics, Type Inference, and robust pointer handling.

/**
 * @brief Kind of literal value.
 */
typedef enum
{
    LITERAL_INT = 0,       ///< Integer literal.
    LITERAL_FLOAT = 1,     ///< Floating point literal.
    LITERAL_STRING = 2,    ///< String literal.
    LITERAL_CHAR = 3,      ///< Character literal.
    LITERAL_RAW_STRING = 4 ///< Raw string literal.
} LiteralKind;

/**
 * @brief Formal type system kinds.
 */
typedef enum
{
    TYPE_VOID,   ///< `void` type.
    TYPE_BOOL,   ///< `bool` type.
    TYPE_CHAR,   ///< `char` type.
    TYPE_STRING, ///< `string` type.
    TYPE_U0,     ///< `u0` type.
    TYPE_I8,     ///< `i8` type.
    TYPE_U8,     ///< `u8` type.
    TYPE_I16,    ///< `i16` type.
    TYPE_U16,    ///< `u16` type.
    TYPE_I32,    ///< `i32` type.
    TYPE_U32,    ///< `u32` type.
    TYPE_I64,    ///< `i64` type.
    TYPE_U64,    ///< `u64` type.
    TYPE_I128,   ///< `i128` type.
    TYPE_U128,   ///< `u128` type.
    TYPE_F32,    ///< `f32` type.
    TYPE_F64,    ///< `f64` type.
    TYPE_INT,    ///< `int` (alias, usually i32).
    TYPE_FLOAT,  ///< `float` (alias).
    TYPE_USIZE,  ///< `usize` (pointer size unsigned).
    TYPE_ISIZE,  ///< `isize` (pointer size signed).
    TYPE_BYTE,   ///< `byte`.
    TYPE_RUNE,   ///< `rune`.
    TYPE_UINT,   ///< `uint` (alias).
    // Portable C Types (FFI)
    TYPE_C_INT,       ///< `c_int` (int).
    TYPE_C_UINT,      ///< `c_uint` (unsigned int).
    TYPE_C_LONG,      ///< `c_long` (long).
    TYPE_C_ULONG,     ///< `c_ulong` (unsigned long).
    TYPE_C_LONGLONG,  ///< `c_longlong` (long long).
    TYPE_C_ULONGLONG, ///< `c_ulonglong` (unsigned long long).
    TYPE_C_SHORT,     ///< `c_short` (short).
    TYPE_C_USHORT,    ///< `c_ushort` (unsigned short).
    TYPE_C_CHAR,      ///< `c_char` (char).
    TYPE_C_UCHAR,     ///< `c_uchar` (unsigned char).

    TYPE_STRUCT,     ///< Struct type.
    TYPE_ENUM,       ///< Enum type.
    TYPE_POINTER,    ///< Pointer type (*).
    TYPE_ARRAY,      ///< Fixed size array [N].
    TYPE_VECTOR,     ///< SIMD vector type.
    TYPE_FUNCTION,   ///< Function pointer or reference.
    TYPE_GENERIC,    ///< Generic type parameter (T).
    TYPE_ALIAS,      ///< Opaque type alias.
    TYPE_BITINT,     ///< C23 _BitInt(N).
    TYPE_UBITINT,    ///< C23 unsigned _BitInt(N).
    TYPE_UNSAFE_ANY, ///< Internal unsafe ANY type for match bindings.
    TYPE_UNKNOWN     ///< Unknown/unresolved type.
} TypeKind;

/**
 * @brief Represents a formal type in the type system.
 */
typedef struct Type
{
    TypeKind kind;          ///< The kind of type.
    int lifetime_depth;     ///< Nesting depth of this type's lifetime (0 = static, >0 = local).
    char *name;             ///< Name of the type (for STRUCT, GENERIC, ENUM).
    char *link_name;        ///< Optional linkage override (from @link_name).
    struct Type *inner;     ///< Inner type (for POINTER, ARRAY).
    struct Type **args;     ///< Generic arguments (for GENERIC instantiations).
    int count;              ///< Count of generic arguments.
    int is_const;           ///< 1 if const-qualified.
    int is_explicit_struct; ///< 1 if defined with "struct" keyword explicitly.
    int is_raw;             // Raw function pointer (fn*)
    int array_size;         ///< Size for fixed-size arrays. For TYPE_BITINT, this is the bit width.
    struct
    {
        int has_drop;     ///< 1 if type implements Drop trait (RAII).
        int has_iterable; ///< 1 if type implements Iterable trait.
    } traits;
    union
    {
        int is_varargs;  ///< 1 if function type is variadic.
        int is_restrict; ///< 1 if pointer is restrict-qualified.
        struct
        {
            int is_opaque_alias;
            char *alias_defined_in_file;
        } alias;
    };
} Type;

// ** AST Node Types **
/**
 * @brief AST Node Types.
 */
typedef enum
{
    NODE_ROOT,               ///< Root of the AST.
    NODE_FUNCTION,           ///< Function definition.
    NODE_BLOCK,              ///< Code block { ... }.
    NODE_RETURN,             ///< Return statement.
    NODE_VAR_DECL,           ///< Variable declaration.
    NODE_CONST,              ///< Constant definition.
    NODE_TYPE_ALIAS,         ///< Type alias (typedef).
    NODE_IF,                 ///< If statement.
    NODE_WHILE,              ///< While loop.
    NODE_FOR,                ///< For loop.
    NODE_FOR_RANGE,          ///< For-range loop (iterator).
    NODE_LOOP,               ///< Infinite loop.
    NODE_BREAK,              ///< Break statement.
    NODE_CONTINUE,           ///< Continue statement.
    NODE_MATCH,              ///< Match statement.
    NODE_MATCH_CASE,         ///< Case within match.
    NODE_EXPR_BINARY,        ///< Binary expression (a + b).
    NODE_EXPR_UNARY,         ///< Unary expression (!a).
    NODE_EXPR_LITERAL,       ///< Literal value.
    NODE_EXPR_VAR,           ///< Variable reference.
    NODE_EXPR_CALL,          ///< Function call.
    NODE_EXPR_MEMBER,        ///< Member access (a.b).
    NODE_EXPR_INDEX,         ///< Array index (a[b]).
    NODE_EXPR_CAST,          ///< Type cast.
    NODE_EXPR_SIZEOF,        ///< Sizeof expression.
    NODE_EXPR_STRUCT_INIT,   ///< Struct initializer.
    NODE_FIELD_INIT,         ///< Field of a struct initializer (var_decl: name, init_expr).
    NODE_EXPR_ARRAY_LITERAL, ///< Array literal.
    NODE_EXPR_TUPLE_LITERAL, ///< Tuple literal.
    NODE_EXPR_SLICE,         ///< Slice operation.
    NODE_STRUCT,             ///< Struct definition.
    NODE_FIELD,              ///< Struct field.
    NODE_ENUM,               ///< Enum definition.
    NODE_ENUM_VARIANT,       ///< Enum variant.
    NODE_TRAIT,              ///< Trait definition.
    NODE_IMPL,               ///< Impl block.
    NODE_IMPL_TRAIT,         ///< Trait implementation.
    NODE_INCLUDE,            ///< Include directive.
    NODE_LINK,               ///< Link directive (@link("path")).
    NODE_RAW_STMT,           ///< Raw statement (transpiler bypass).
    NODE_TEST,               ///< Test block.
    NODE_ASSERT,             ///< Assert statement.
    NODE_EXPECT,             ///< Expect statement (non-fatal assert).
    NODE_DEFER,              ///< Defer statement.
    NODE_DESTRUCT_VAR,       ///< Destructuring declaration.
    NODE_TERNARY,            ///< Ternary expression (?:).
    NODE_ASM,                ///< Assembly block.
    NODE_LAMBDA,             ///< Lambda function.
    NODE_PLUGIN,             ///< Plugin invocation.
    NODE_GOTO,               ///< Goto statement.
    NODE_LABEL,              ///< Label.
    NODE_TYPEOF,             ///< Typeof operator.
    NODE_TRY,                ///< Try statement (error handling).
    NODE_REFLECTION,         ///< Reflection info.
    NODE_REPL_PRINT,         ///< Implicit print (REPL).
    NODE_CUDA_LAUNCH,        ///< CUDA kernel launch (<<<...>>>).
    NODE_VA_START,           ///< va_start intrinsic.
    NODE_VA_END,             ///< va_end intrinsic.
    NODE_VA_COPY,            ///< va_copy intrinsic.
    NODE_VA_ARG,             ///< va_arg intrinsic.
    NODE_PREPROC_DIRECTIVE,  ///< C-style preprocessor directive (#define, etc).
    NODE_IMPORT,             ///< Import statement (recursive).
    NODE_COMPTIME,           ///< Comptime block (interpreted at compile time).
    NODE_AST_COMMENT,        ///< Comment node.
    NODE_ERRONEOUS           ///< Error sentinel (safe no-op node).
} NodeType;

// ** AST Node Structure **
typedef struct Attribute
{
    char *name;
    char **args;
    int count;
    struct Attribute *next;
} Attribute;

struct ASTNode
{
    NodeType kind;
    ASTNode *next;
    int line;          // Source line number for debugging.
    char *doc_comment; // Attached documentation comment.

    // Type information.
    char *resolved_type; // Legacy string representation (for example: "int",
                         // "User*"). > Yes, 'legacy' is a thing, this is the
                         // third iteration > of this project (for now).
    Type *type_info;     // Formal type object (for inference/generics).
    Token token;
    Token definition_token; // For LSP: Location where the symbol used in this
                            // node was defined.
    char *cfg_condition;    // C preprocessor condition from @cfg
    char *link_name;        // Optional override for external C name
    int is_checked;         // Flag to track semantic analysis (avoid redundant passes).

    union
    {
        struct
        {
            ASTNode *children;
        } root;

        struct
        {
            char *name;
            char *generic_params; // <T, U>
            char *args;           // Legacy string args.
            char *ret_type;       // Legacy string return type.
            ASTNode *body;
            Type **arg_types;
            char **defaults;
            ASTNode **default_values; // AST representation (for robust substitution)
            char **param_names;       // Explicit parameter names.
            int count;
            Type *ret_type_info;
            int is_varargs;
            int is_inline;
            int required; // @required: warn if return value is discarded.
            // GCC attributes
            int noinline;    // @noinline
            int constructor; // @constructor
            int destructor;  // @destructor
            int unused;      // @unused
            int weak;        // @weak
            int is_export;   // @export (visibility default).
            int cold;        // @cold
            int hot;         // @hot
            int noreturn;    // @noreturn
            int pure;        // @pure
            char *section;   // @section("name")
            int is_comptime; // @comptime function
            int is_extern;   // extern fn (C linkage in C++ mode)
            // CUDA qualifiers
            int cuda_global; // @global -> __global__
            int cuda_device; // @device -> __device__
            int cuda_host;   // @host -> __host__

            char **c_type_overrides; // @ctype("...") per parameter
            int elide_from_idx;      // Index of parameter for lifetime elision (-1 if none)

            Attribute *attributes; // Custom attributes

            // Declaration context (to parse a deferred body)
            char *module_prefix;  // C prefix of the declaring module (NULL if none)
            char *impl_struct;    // Type of the enclosing impl block (NULL for free function)
            const char *filename; // Source file that declares the function
        } func;

        struct
        {
            ASTNode *statements;
        } block;

        struct
        {
            ASTNode *value;
        } ret;

        struct
        {
            char *name;
            char *type_str;
            ASTNode *init_expr;
            Type *type_info;
            int is_static;
            int is_thread_local;
            int is_export;
        } var_decl;

        struct
        {
            char *name;
            Type *payload;
            int payload_count; ///< Values the variant carries; several make a tuple payload.
            int tag_id;
        } variant;

        struct
        {
            char *name;
            ASTNode *variants;
            int is_template;
            char *generic_param;
            int is_export;
        } enm;

        struct
        {
            char *alias;
            char *original_type;
            int is_opaque;
            char *defined_in_file;
            int is_export;
        } type_alias;

        struct
        {
            ASTNode *condition;
            ASTNode *then_body;
            ASTNode *else_body;
        } if_stmt;

        struct
        {
            ASTNode *condition;
            ASTNode *body;
            char *loop_label;
        } while_stmt;

        struct
        {
            ASTNode *init;
            ASTNode *condition;
            ASTNode *step;
            ASTNode *body;
            char *loop_label;
        } for_stmt;

        struct
        {
            char *var_name;
            ASTNode *start;
            ASTNode *end;
            char *step;
            int is_inclusive;
            ASTNode *body;
            char *loop_label;
        } for_range;

        struct
        {
            ASTNode *body;
            char *loop_label;
        } loop_stmt;

        struct
        {
            ASTNode *expr;
            ASTNode *cases;
        } match_stmt;

        struct
        {
            char *pattern;
            char **binding_names; // Multiple bindings
            int binding_count;    // Count
            int *binding_refs;    // Ref flags per binding
            int is_destructuring;
            ASTNode *guard;
            ASTNode *body;
            int is_default;
        } match_case;

        struct
        {
            char *op;
            ASTNode *left;
            ASTNode *right;
        } binary;

        struct
        {
            char *op;
            ASTNode *operand;
            int owns_temp; ///< `&_rval` of a temporary that the enclosing call must drop.
            int temp_id;   ///< While emitting that call: 1 + id of the named temporary.
        } unary;

        struct
        {
            LiteralKind kind;
            unsigned long long int_val;
            double float_val;
            char *string_val;
        } literal;

        struct
        {
            char *name;
            char *suggestion;
            struct ZenSymbol *symbol;
        } var_ref;

        struct
        {
            ASTNode *callee;
            ASTNode *args;
            char **arg_names;
            int count;
        } call;

        struct
        {
            ASTNode *target;
            char *field;
            int is_pointer_access;
        } member;

        struct
        {
            ASTNode *array;
            ASTNode *index;
            ASTNode *extra_indices; // Linked list of additional indices (for v[i, j, k])
            int index_count;        // Total index count (1 for v[i], 2 for v[i,j], etc.)
        } index;

        struct
        {
            ASTNode *array;
            ASTNode *start;
            ASTNode *end;
        } slice;

        struct
        {
            char *target_type;
            ASTNode *expr;
        } cast;

        struct
        {
            char *struct_name;
            ASTNode *fields;
        } struct_init;

        struct
        {
            ASTNode *elements;
            int count;
        } array_literal;

        struct
        {
            ASTNode *elements;
            int count;
        } tuple_literal;

        struct
        {
            char *name;
            ASTNode *fields;
            int is_template;
            char **generic_params;   // Array of generic parameter names (for example, ["K", "V"])
            int generic_param_count; // Number of generic parameters
            char *parent;
            int is_union;
            int is_packed;         // @packed attribute.
            int align;             // @align(N) attribute, 0 = default.
            int is_incomplete;     // Forward declaration (prototype)
            int is_export;         // @export attribute
            Attribute *attributes; // Custom attributes
            char **used_structs;   // Names of structs used/mixed-in
            int used_struct_count;
            int is_opaque;
            char *defined_in_file; // File where the struct is defined (for privacy check)
            char *crepr_c_type;    // @crepr("C.kind") - use C type instead of redefining
        } strct;

        struct
        {
            char *name;
            char *type;
            int bit_width;
        } field;

        struct
        {
            char *name;
            ASTNode *methods;
            char **generic_params;
            int generic_param_count;
        } trait;

        struct
        {
            char *struct_name;
            ASTNode *methods;
        } impl;

        struct
        {
            char *trait_name;
            char *target_type;
            ASTNode *methods;
        } impl_trait;

        struct
        {
            char *path;
            int is_system;
        } include;

        struct
        {
            char *path;
        } link;

        struct
        {
            char *content;
            char **used_symbols;
            int used_symbol_count;
            struct ASTNode **interp_exprs; ///< Parsed `{...}` expressions of an f-string.
            int interp_expr_count;
        } raw_stmt;

        struct
        {
            char *name;
            ASTNode *body;

            // Declaration context
            char *module_prefix;  // C prefix of the declaring module
            const char *filename; // Source file that declares the test
        } test_stmt;

        struct
        {
            ASTNode *condition;
            char *message;
            int message_is_literal; ///< 1 if message was a string literal, 0 if variable
        } assert_stmt;

        struct
        {
            ASTNode *stmt;
        } defer_stmt;

        struct
        {
            char *plugin_name;
            char *body;
            int start_line;
            int start_col;
            int end_line;
            int end_col;
        } plugin_stmt;

        struct
        {
            char **names;
            char **types;      // Explicit types (NULL entries if inferred)
            Type **type_infos; // Formal type objects (NULL entries if inferred)
            int count;
            ASTNode *init_expr;
            int is_struct_destruct;
            char *struct_name;  // "Point" (or NULL if unchecked/inferred).
            char **field_names; // NULL if same as 'names', otherwise mapped.
            int is_guard;
            char *guard_variant; // "Some", "Ok".
            ASTNode *else_block;
        } destruct;

        struct
        {
            ASTNode *cond;
            ASTNode *true_expr;
            ASTNode *false_expr;
        } ternary;

        struct
        {
            char *code;
            int is_volatile;
            int register_size; // The register size to use of 32/64/128 bits
            char **outputs;
            char **output_modes;
            char **inputs;
            char **clobbers;
            int output_count;
            int input_count;
            int clobber_count;
        } asm_stmt;

        struct
        {
            char *path;
            ASTNode *module_root;
        } import_stmt;

        struct
        {
            char **param_names;
            char **param_types;
            char *return_type;
            ASTNode *body;
            int count;
            int lambda_id;
            int is_expression;
            int is_bare; // 1 if should be emitted without void* ctx (for fn*)
            char **captured_vars;
            char **captured_types;
            Type **captured_types_info;
            int capture_count;
            int *capture_modes;
            int default_capture_mode;
            char **explicit_captures;
            int *explicit_capture_modes;
            int explicit_capture_count;
        } lambda;

        struct
        {
            char *target_type;
            ASTNode *expr;
            Type *target_type_info;
            int is_type;
        } size_of;

        struct
        {
            char *label_name;
            ASTNode *goto_expr;
        } goto_stmt;

        struct
        {
            char *label_name;
        } label_stmt;

        struct
        {
            char *target_label;
        } break_stmt;

        struct
        {
            char *target_label;
        } continue_stmt;

        struct
        {
            ASTNode *expr;
        } try_stmt;

        struct
        {
            int kind; // 0=type_name, 1=fields.
            Type *target_type;
        } reflection;

        struct
        {
            ASTNode *expr;
        } repl_print;

        struct
        {
            ASTNode *call;       // The kernel call (NODE_EXPR_CALL)
            ASTNode *grid;       // Grid dimensions expression
            ASTNode *block;      // Block dimensions expression
            ASTNode *shared_mem; // Optional shared memory size (NULL = default)
            ASTNode *stream;     // Optional CUDA stream (NULL = default)
        } cuda_launch;

        struct
        {
            ASTNode *ap;
            ASTNode *last_arg;
        } va_start_args;

        struct
        {
            ASTNode *ap;
        } va_end_args;

        struct
        {
            ASTNode *dest;
            ASTNode *src;
        } va_copy_args;

        struct
        {
            ASTNode *ap;
            Type *type_info;
        } va_arg_val;

        struct
        {
            char *content;
        } comment;

        struct
        {
            ASTNode *body;      ///< The comptime block body (parsed statements).
            ASTNode *generated; ///< Generated AST nodes (from yield() output).
            int in_block;       ///< Inside a function body: the output is statements.
        } comptime;
    };
};

ASTNode *ast_create(NodeType type);
void ast_free(ASTNode *node);

/// Most child fields a node kind has (NODE_CUDA_LAUNCH has 5).
#define AST_MAX_CHILDREN 8

/**
 * @brief Where the children of a node are stored.
 *
 * Each slot is the address of a child field of the node; the field holds the
 * head of a list linked by `next`, or NULL. Through a slot a walker can read
 * the child (`*slot`) or replace it (`*slot = other`).
 */
typedef struct
{
    ASTNode **slots[AST_MAX_CHILDREN];
    int count;
} ASTChildren;

/**
 * @brief The child fields of a node, in source order.
 *
 * Not included: the tree of an imported module (`import_stmt.module_root`,
 * shared between importers; walk it yourself with a visited set), and the two
 * arrays that are not lists (`func.default_values`, `raw_stmt.interp_exprs`).
 * For NODE_COMPTIME, both `body` (the code written) and `generated` (the code
 * it produced).
 */
ASTChildren ast_children(ASTNode *node);

Type *type_new(TypeKind kind);
Type *type_new_ptr(Type *inner);
Type *type_new_array(Type *inner, int size);
Type *type_clone(Type *t);
int type_eq(Type *a, Type *b);
int is_integer_type(Type *t);
int is_incomplete_type(struct ParserContext *ctx, Type *t);
int is_unsigned_type(Type *t);
int is_signed_type(Type *t);
int is_boolean_type(Type *t);
int is_float_type(Type *t);
int is_composite_expression(ASTNode *node);
char *type_to_string(Type *t);
char *type_to_c_string(Type *t, int misra_mode);
char *infer_type(struct ParserContext *ctx, struct ASTNode *node);
char *get_field_type_str(struct ParserContext *ctx, const char *struct_name,
                         const char *field_name);
Type *get_inner_type(Type *t);

typedef struct TraitReg
{
    char *name;
    struct TraitReg *next;
} TraitReg;

#endif