// 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 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; // 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