summaryrefslogtreecommitdiff
path: root/src/ast
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast')
-rw-r--r--src/ast/ast.c445
-rw-r--r--src/ast/ast.h975
2 files changed, 662 insertions, 758 deletions
diff --git a/src/ast/ast.c b/src/ast/ast.c
index f34370e..023180d 100644
--- a/src/ast/ast.c
+++ b/src/ast/ast.c
@@ -5,279 +5,242 @@
#include <stdlib.h>
#include <string.h>
-typedef struct TraitReg
-{
- char *name;
- struct TraitReg *next;
+typedef struct TraitReg {
+ char *name;
+ struct TraitReg *next;
} TraitReg;
static TraitReg *registered_traits = NULL;
-void register_trait(const char *name)
-{
- TraitReg *r = xmalloc(sizeof(TraitReg));
- r->name = xstrdup(name);
- r->next = registered_traits;
- registered_traits = r;
+void register_trait(const char *name) {
+ TraitReg *r = xmalloc(sizeof(TraitReg));
+ r->name = xstrdup(name);
+ r->next = registered_traits;
+ registered_traits = r;
}
-int is_trait(const char *name)
-{
- TraitReg *r = registered_traits;
- while (r)
- {
- if (0 == strcmp(r->name, name))
- {
- return 1;
- }
- r = r->next;
+int is_trait(const char *name) {
+ TraitReg *r = registered_traits;
+ while (r) {
+ if (0 == strcmp(r->name, name)) {
+ return 1;
}
- return 0;
+ r = r->next;
+ }
+ return 0;
}
-ASTNode *ast_create(NodeType type)
-{
- ASTNode *node = xmalloc(sizeof(ASTNode));
- memset(node, 0, sizeof(ASTNode));
- node->type = type;
- return node;
+ASTNode *ast_create(NodeType type) {
+ ASTNode *node = xmalloc(sizeof(ASTNode));
+ memset(node, 0, sizeof(ASTNode));
+ node->type = type;
+ return node;
}
-void ast_free(ASTNode *node)
-{
- (void)node;
- return;
+void ast_free(ASTNode *node) {
+ (void)node;
+ return;
}
-Type *type_new(TypeKind kind)
-{
- Type *t = xmalloc(sizeof(Type));
- t->kind = kind;
- t->name = NULL;
- t->inner = NULL;
- t->args = NULL;
- t->arg_count = 0;
- t->is_const = 0;
- t->array_size = 0;
- return t;
+Type *type_new(TypeKind kind) {
+ Type *t = xmalloc(sizeof(Type));
+ t->kind = kind;
+ t->name = NULL;
+ t->inner = NULL;
+ t->args = NULL;
+ t->arg_count = 0;
+ t->is_const = 0;
+ t->array_size = 0;
+ return t;
}
-Type *type_new_ptr(Type *inner)
-{
- Type *t = type_new(TYPE_POINTER);
- t->inner = inner;
- return t;
+Type *type_new_ptr(Type *inner) {
+ Type *t = type_new(TYPE_POINTER);
+ t->inner = inner;
+ return t;
}
-int is_char_ptr(Type *t)
-{
- // Handle both primitive char* and legacy struct char*.
- if (TYPE_POINTER == t->kind && TYPE_CHAR == t->inner->kind)
- {
- return 1;
- }
- if (TYPE_POINTER == t->kind && TYPE_STRUCT == t->inner->kind &&
- 0 == strcmp(t->inner->name, "char"))
- {
- return 1;
- }
- return 0;
+int is_char_ptr(Type *t) {
+ // Handle both primitive char* and legacy struct char*.
+ if (TYPE_POINTER == t->kind && TYPE_CHAR == t->inner->kind) {
+ return 1;
+ }
+ if (TYPE_POINTER == t->kind && TYPE_STRUCT == t->inner->kind &&
+ 0 == strcmp(t->inner->name, "char")) {
+ return 1;
+ }
+ return 0;
}
-int is_integer_type(Type *t)
-{
- if (!t)
- {
- return 0;
- }
-
- return (t->kind == TYPE_INT || t->kind == TYPE_CHAR || t->kind == TYPE_BOOL ||
- t->kind == TYPE_I8 || t->kind == TYPE_U8 || t->kind == TYPE_I16 ||
- t->kind == TYPE_U16 || t->kind == TYPE_I32 || t->kind == TYPE_U32 ||
- t->kind == TYPE_I64 || t->kind == TYPE_U64 || t->kind == TYPE_USIZE ||
- t->kind == TYPE_ISIZE || t->kind == TYPE_BYTE || t->kind == TYPE_RUNE ||
- t->kind == TYPE_UINT || t->kind == TYPE_I128 || t->kind == TYPE_U128);
+int is_integer_type(Type *t) {
+ if (!t) {
+ return 0;
+ }
+
+ return (t->kind == TYPE_INT || t->kind == TYPE_CHAR || t->kind == TYPE_BOOL ||
+ t->kind == TYPE_I8 || t->kind == TYPE_U8 || t->kind == TYPE_I16 ||
+ t->kind == TYPE_U16 || t->kind == TYPE_I32 || t->kind == TYPE_U32 ||
+ t->kind == TYPE_I64 || t->kind == TYPE_U64 || t->kind == TYPE_USIZE ||
+ t->kind == TYPE_ISIZE || t->kind == TYPE_BYTE ||
+ t->kind == TYPE_RUNE || t->kind == TYPE_UINT ||
+ t->kind == TYPE_I128 || t->kind == TYPE_U128);
}
-int is_float_type(Type *t)
-{
- if (!t)
- {
- return 0;
- }
+int is_float_type(Type *t) {
+ if (!t) {
+ return 0;
+ }
- return (t->kind == TYPE_FLOAT || t->kind == TYPE_F32 || t->kind == TYPE_F64);
+ return (t->kind == TYPE_FLOAT || t->kind == TYPE_F32 || t->kind == TYPE_F64);
}
-int type_eq(Type *a, Type *b)
-{
- if (!a || !b)
- {
- return 0;
- }
-
- if (a == b)
- {
- return 1;
- }
-
- // Lax integer matching (bool == int, char == i8, etc.).
- if (is_integer_type(a) && is_integer_type(b))
- {
- return 1;
- }
-
- // Lax float matching.
- if (is_float_type(a) && is_float_type(b))
- {
- return 1;
- }
-
- // String Literal vs char*
- if (a->kind == TYPE_STRING && is_char_ptr(b))
- {
- return 1;
- }
-
- if (b->kind == TYPE_STRING && is_char_ptr(a))
- {
- return 1;
- }
-
- if (a->kind != b->kind)
- {
- return 0;
- }
+int type_eq(Type *a, Type *b) {
+ if (!a || !b) {
+ return 0;
+ }
- if (a->kind == TYPE_STRUCT || a->kind == TYPE_GENERIC)
- {
- return 0 == strcmp(a->name, b->name);
- }
- if (a->kind == TYPE_POINTER || a->kind == TYPE_ARRAY)
- {
- return type_eq(a->inner, b->inner);
- }
+ if (a == b) {
+ return 1;
+ }
+ // Lax integer matching (bool == int, char == i8, etc.).
+ if (is_integer_type(a) && is_integer_type(b)) {
return 1;
-}
+ }
-char *type_to_string(Type *t)
-{
- if (!t)
- {
- return xstrdup("void");
- }
+ // Lax float matching.
+ if (is_float_type(a) && is_float_type(b)) {
+ return 1;
+ }
- switch (t->kind)
- {
- case TYPE_VOID:
- return xstrdup("void");
- case TYPE_BOOL:
- return xstrdup("bool");
- case TYPE_STRING:
- return xstrdup("string");
- case TYPE_CHAR:
- return xstrdup("char");
- case TYPE_I8:
- return xstrdup("int8_t");
- case TYPE_U8:
- return xstrdup("uint8_t");
- case TYPE_I16:
- return xstrdup("int16_t");
- case TYPE_U16:
- return xstrdup("uint16_t");
- case TYPE_I32:
- return xstrdup("int32_t");
- case TYPE_U32:
- return xstrdup("uint32_t");
- case TYPE_I64:
- return xstrdup("int64_t");
- case TYPE_U64:
- return xstrdup("uint64_t");
- case TYPE_F32:
- return xstrdup("float");
- case TYPE_F64:
- return xstrdup("double");
- case TYPE_USIZE:
- return xstrdup("size_t");
- case TYPE_ISIZE:
- return xstrdup("ptrdiff_t");
- case TYPE_BYTE:
- return xstrdup("uint8_t");
- case TYPE_I128:
- return xstrdup("__int128");
- case TYPE_U128:
- return xstrdup("unsigned __int128");
- case TYPE_RUNE:
- return xstrdup("int32_t");
- case TYPE_UINT:
- return xstrdup("unsigned int");
- case TYPE_INT:
- return xstrdup("int");
- case TYPE_FLOAT:
- return xstrdup("float");
-
- case TYPE_POINTER:
- {
- char *inner = type_to_string(t->inner);
- if (t->is_restrict)
- {
- char *res = xmalloc(strlen(inner) + 16);
- sprintf(res, "%s* __restrict", inner);
- return res;
- }
- else
- {
- char *res = xmalloc(strlen(inner) + 2);
- sprintf(res, "%s*", inner);
- return res;
- }
- }
+ // String Literal vs char*
+ if (a->kind == TYPE_STRING && is_char_ptr(b)) {
+ return 1;
+ }
- case TYPE_ARRAY:
- {
- char *inner = type_to_string(t->inner);
+ if (b->kind == TYPE_STRING && is_char_ptr(a)) {
+ return 1;
+ }
- if (t->array_size > 0)
- {
- char *res = xmalloc(strlen(inner) + 20);
- sprintf(res, "%s[%d]", inner, t->array_size);
- return res;
- }
+ if (a->kind != b->kind) {
+ return 0;
+ }
- char *res = xmalloc(strlen(inner) + 7);
- sprintf(res, "Slice_%s", inner);
- return res;
- }
+ if (a->kind == TYPE_STRUCT || a->kind == TYPE_GENERIC) {
+ return 0 == strcmp(a->name, b->name);
+ }
+ if (a->kind == TYPE_POINTER || a->kind == TYPE_ARRAY) {
+ return type_eq(a->inner, b->inner);
+ }
- case TYPE_FUNCTION:
- if (t->inner)
- {
- free(type_to_string(t->inner));
- }
-
- return xstrdup("z_closure_T");
-
- case TYPE_STRUCT:
- case TYPE_GENERIC:
- {
- if (t->arg_count > 0)
- {
- char *base = t->name;
- char *arg = type_to_string(t->args[0]);
- char *clean_arg = sanitize_mangled_name(arg);
-
- char *res = xmalloc(strlen(base) + strlen(clean_arg) + 2);
- sprintf(res, "%s_%s", base, clean_arg);
-
- free(arg);
- free(clean_arg);
- return res;
- }
- return xstrdup(t->name);
- }
+ return 1;
+}
- default:
- return xstrdup("unknown");
- }
+char *type_to_string(Type *t) {
+ if (!t) {
+ return xstrdup("void");
+ }
+
+ switch (t->kind) {
+ case TYPE_VOID:
+ return xstrdup("void");
+ case TYPE_BOOL:
+ return xstrdup("bool");
+ case TYPE_STRING:
+ return xstrdup("string");
+ case TYPE_CHAR:
+ return xstrdup("char");
+ case TYPE_I8:
+ return xstrdup("int8_t");
+ case TYPE_U8:
+ return xstrdup("uint8_t");
+ case TYPE_I16:
+ return xstrdup("int16_t");
+ case TYPE_U16:
+ return xstrdup("uint16_t");
+ case TYPE_I32:
+ return xstrdup("int32_t");
+ case TYPE_U32:
+ return xstrdup("uint32_t");
+ case TYPE_I64:
+ return xstrdup("int64_t");
+ case TYPE_U64:
+ return xstrdup("uint64_t");
+ case TYPE_F32:
+ return xstrdup("float");
+ case TYPE_F64:
+ return xstrdup("double");
+ case TYPE_USIZE:
+ return xstrdup("size_t");
+ case TYPE_ISIZE:
+ return xstrdup("ptrdiff_t");
+ case TYPE_BYTE:
+ return xstrdup("uint8_t");
+ case TYPE_I128:
+ return xstrdup("__int128");
+ case TYPE_U128:
+ return xstrdup("unsigned __int128");
+ case TYPE_RUNE:
+ return xstrdup("int32_t");
+ case TYPE_UINT:
+ return xstrdup("unsigned int");
+ case TYPE_INT:
+ return xstrdup("int");
+ case TYPE_FLOAT:
+ return xstrdup("float");
+
+ case TYPE_POINTER: {
+ char *inner = type_to_string(t->inner);
+ if (t->is_restrict) {
+ char *res = xmalloc(strlen(inner) + 16);
+ sprintf(res, "%s* __restrict", inner);
+ return res;
+ } else {
+ char *res = xmalloc(strlen(inner) + 2);
+ sprintf(res, "%s*", inner);
+ return res;
+ }
+ }
+
+ case TYPE_ARRAY: {
+ char *inner = type_to_string(t->inner);
+
+ if (t->array_size > 0) {
+ char *res = xmalloc(strlen(inner) + 20);
+ sprintf(res, "%s[%d]", inner, t->array_size);
+ return res;
+ }
+
+ char *res = xmalloc(strlen(inner) + 7);
+ sprintf(res, "Slice_%s", inner);
+ return res;
+ }
+
+ case TYPE_FUNCTION:
+ if (t->inner) {
+ free(type_to_string(t->inner));
+ }
+
+ return xstrdup("z_closure_T");
+
+ case TYPE_STRUCT:
+ case TYPE_GENERIC: {
+ if (t->arg_count > 0) {
+ char *base = t->name;
+ char *arg = type_to_string(t->args[0]);
+ char *clean_arg = sanitize_mangled_name(arg);
+
+ char *res = xmalloc(strlen(base) + strlen(clean_arg) + 2);
+ sprintf(res, "%s_%s", base, clean_arg);
+
+ free(arg);
+ free(clean_arg);
+ return res;
+ }
+ return xstrdup(t->name);
+ }
+
+ default:
+ return xstrdup("unknown");
+ }
}
diff --git a/src/ast/ast.h b/src/ast/ast.h
index a5d3d0a..0fa2e24 100644
--- a/src/ast/ast.h
+++ b/src/ast/ast.h
@@ -11,531 +11,472 @@ typedef struct ASTNode ASTNode;
// ** Formal Type System **
// Used for Generics, Type Inference, and robust pointer handling.
-typedef enum
-{
- TYPE_VOID,
- TYPE_BOOL,
- TYPE_CHAR,
- TYPE_STRING,
- TYPE_U0,
- TYPE_I8,
- TYPE_U8,
- TYPE_I16,
- TYPE_U16,
- TYPE_I32,
- TYPE_U32,
- TYPE_I64,
- TYPE_U64,
- TYPE_I128,
- TYPE_U128,
- TYPE_F32,
- TYPE_F64,
- TYPE_INT,
- TYPE_FLOAT,
- TYPE_USIZE,
- TYPE_ISIZE,
- TYPE_BYTE,
- TYPE_RUNE,
- TYPE_UINT,
- TYPE_STRUCT,
- TYPE_ENUM,
- TYPE_POINTER,
- TYPE_ARRAY,
- TYPE_FUNCTION,
- TYPE_GENERIC,
- TYPE_UNKNOWN
+typedef enum {
+ TYPE_VOID,
+ TYPE_BOOL,
+ TYPE_CHAR,
+ TYPE_STRING,
+ TYPE_U0,
+ TYPE_I8,
+ TYPE_U8,
+ TYPE_I16,
+ TYPE_U16,
+ TYPE_I32,
+ TYPE_U32,
+ TYPE_I64,
+ TYPE_U64,
+ TYPE_I128,
+ TYPE_U128,
+ TYPE_F32,
+ TYPE_F64,
+ TYPE_INT,
+ TYPE_FLOAT,
+ TYPE_USIZE,
+ TYPE_ISIZE,
+ TYPE_BYTE,
+ TYPE_RUNE,
+ TYPE_UINT,
+ TYPE_STRUCT,
+ TYPE_ENUM,
+ TYPE_POINTER,
+ TYPE_ARRAY,
+ TYPE_FUNCTION,
+ TYPE_GENERIC,
+ TYPE_UNKNOWN
} TypeKind;
-typedef struct Type
-{
- TypeKind kind;
- char *name; // For STRUCT, GENERIC, ENUM.
- struct Type *inner; // For POINTER, ARRAY.
- struct Type **args; // For GENERIC args.
- int arg_count;
- int is_const;
- union
- {
- int array_size; // For fixed-size arrays [T; N].
- int is_varargs; // For function types (...).
- int is_restrict; // For restrict pointers.
- int has_drop; // For RAII: does this type implement Drop?
- };
+typedef struct Type {
+ TypeKind kind;
+ char *name; // For STRUCT, GENERIC, ENUM.
+ struct Type *inner; // For POINTER, ARRAY.
+ struct Type **args; // For GENERIC args.
+ int arg_count;
+ int is_const;
+ union {
+ int array_size; // For fixed-size arrays [T; N].
+ int is_varargs; // For function types (...).
+ int is_restrict; // For restrict pointers.
+ int has_drop; // For RAII: does this type implement Drop?
+ };
} Type;
// ** AST Node Types **
-typedef enum
-{
- NODE_ROOT,
- NODE_FUNCTION,
- NODE_BLOCK,
- NODE_RETURN,
- NODE_VAR_DECL,
- NODE_CONST,
- NODE_TYPE_ALIAS,
- NODE_IF,
- NODE_WHILE,
- NODE_FOR,
- NODE_FOR_RANGE,
- NODE_LOOP,
- NODE_REPEAT,
- NODE_UNLESS,
- NODE_GUARD,
- NODE_BREAK,
- NODE_CONTINUE,
- NODE_MATCH,
- NODE_MATCH_CASE,
- NODE_EXPR_BINARY,
- NODE_EXPR_UNARY,
- NODE_EXPR_LITERAL,
- NODE_EXPR_VAR,
- NODE_EXPR_CALL,
- NODE_EXPR_MEMBER,
- NODE_EXPR_INDEX,
- NODE_EXPR_CAST,
- NODE_EXPR_SIZEOF,
- NODE_EXPR_STRUCT_INIT,
- NODE_EXPR_ARRAY_LITERAL,
- NODE_EXPR_SLICE,
- NODE_STRUCT,
- NODE_FIELD,
- NODE_ENUM,
- NODE_ENUM_VARIANT,
- NODE_TRAIT,
- NODE_IMPL,
- NODE_IMPL_TRAIT,
- NODE_INCLUDE,
- NODE_RAW_STMT,
- NODE_TEST,
- NODE_ASSERT,
- NODE_DEFER,
- NODE_DESTRUCT_VAR,
- NODE_TERNARY,
- NODE_ASM,
- NODE_LAMBDA,
- NODE_PLUGIN,
- NODE_GOTO,
- NODE_LABEL,
- NODE_DO_WHILE,
- NODE_TYPEOF,
- NODE_TRY,
- NODE_REFLECTION,
- NODE_AWAIT,
- NODE_REPL_PRINT
+typedef enum {
+ NODE_ROOT,
+ NODE_FUNCTION,
+ NODE_BLOCK,
+ NODE_RETURN,
+ NODE_VAR_DECL,
+ NODE_CONST,
+ NODE_TYPE_ALIAS,
+ NODE_IF,
+ NODE_WHILE,
+ NODE_FOR,
+ NODE_FOR_RANGE,
+ NODE_LOOP,
+ NODE_REPEAT,
+ NODE_UNLESS,
+ NODE_GUARD,
+ NODE_BREAK,
+ NODE_CONTINUE,
+ NODE_MATCH,
+ NODE_MATCH_CASE,
+ NODE_EXPR_BINARY,
+ NODE_EXPR_UNARY,
+ NODE_EXPR_LITERAL,
+ NODE_EXPR_VAR,
+ NODE_EXPR_CALL,
+ NODE_EXPR_MEMBER,
+ NODE_EXPR_INDEX,
+ NODE_EXPR_CAST,
+ NODE_EXPR_SIZEOF,
+ NODE_EXPR_STRUCT_INIT,
+ NODE_EXPR_ARRAY_LITERAL,
+ NODE_EXPR_SLICE,
+ NODE_STRUCT,
+ NODE_FIELD,
+ NODE_ENUM,
+ NODE_ENUM_VARIANT,
+ NODE_TRAIT,
+ NODE_IMPL,
+ NODE_IMPL_TRAIT,
+ NODE_INCLUDE,
+ NODE_RAW_STMT,
+ NODE_TEST,
+ NODE_ASSERT,
+ NODE_DEFER,
+ NODE_DESTRUCT_VAR,
+ NODE_TERNARY,
+ NODE_ASM,
+ NODE_LAMBDA,
+ NODE_PLUGIN,
+ NODE_GOTO,
+ NODE_LABEL,
+ NODE_DO_WHILE,
+ NODE_TYPEOF,
+ NODE_TRY,
+ NODE_REFLECTION,
+ NODE_AWAIT,
+ NODE_REPL_PRINT
} NodeType;
// ** AST Node Structure **
-struct ASTNode
-{
- NodeType type;
- ASTNode *next;
- int line; // Source line number for debugging.
-
- // 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.
-
- union
- {
- struct
- {
- ASTNode *children;
- } root;
-
- struct
- {
- char *name;
- char *args; // Legacy string args.
- char *ret_type; // Legacy string return type.
- ASTNode *body;
- Type **arg_types;
- char **defaults;
- char **param_names; // Explicit parameter names.
- int arg_count;
- Type *ret_type_info;
- int is_varargs;
- int is_inline;
- int must_use; // @must_use: 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_async; // async function
- int is_comptime; // @comptime function
- } func;
-
- struct
- {
- ASTNode *statements;
- } block;
-
- struct
- {
- ASTNode *value;
- } ret;
-
- struct
- {
- char *name;
- char *type_str;
- ASTNode *init_expr;
- Type *type_info;
- int is_autofree;
- int is_mutable;
- int is_static;
- } var_decl;
-
- struct
- {
- char *name;
- Type *payload;
- int tag_id;
- } variant;
-
- struct
- {
- char *name;
- ASTNode *variants;
- int is_template;
- char *generic_param;
- } enm;
-
- struct
- {
- char *alias;
- char *original_type;
- } 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;
- ASTNode *body;
- } for_range;
-
- struct
- {
- ASTNode *body;
- char *loop_label;
- } loop_stmt;
-
- struct
- {
- char *count;
- ASTNode *body;
- } repeat_stmt;
-
- struct
- {
- ASTNode *condition;
- ASTNode *body;
- } unless_stmt;
-
- struct
- {
- ASTNode *condition;
- ASTNode *body;
- } guard_stmt;
-
- struct
- {
- ASTNode *condition;
- ASTNode *body;
- char *loop_label;
- } do_while_stmt;
-
- struct
- {
- ASTNode *expr;
- ASTNode *cases;
- } match_stmt;
-
- struct
- {
- char *pattern;
- char *binding_name;
- 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;
- } unary;
-
- struct
- {
- int type_kind;
- unsigned long long int_val;
- double float_val;
- char *string_val;
- } literal;
-
- struct
- {
- char *name;
- char *suggestion;
- } var_ref;
-
- struct
- {
- ASTNode *callee;
- ASTNode *args;
- char **arg_names;
- int arg_count;
- } call;
-
- struct
- {
- ASTNode *target;
- char *field;
- int is_pointer_access;
- } member;
-
- struct
- {
- ASTNode *array;
- ASTNode *index;
- } 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
- {
- char *name;
- ASTNode *fields;
- int is_template;
- char *generic_param;
- char *parent;
- int is_union;
- int is_packed; // @packed attribute.
- int align; // @align(N) attribute, 0 = default.
- int is_incomplete; // Forward declaration (prototype)
- } strct;
-
- struct
- {
- char *name;
- char *type;
- int bit_width;
- } field;
-
- struct
- {
- char *name;
- ASTNode *methods;
- } 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 *content;
- char **used_symbols;
- int used_symbol_count;
- } raw_stmt;
-
- struct
- {
- char *name;
- ASTNode *body;
- } test_stmt;
-
- struct
- {
- ASTNode *condition;
- char *message;
- } assert_stmt;
-
- struct
- {
- ASTNode *stmt;
- } defer_stmt;
-
- struct
- {
- char *plugin_name;
- char *body;
- } plugin_stmt;
-
- struct
- {
- char **names;
- 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;
- char **outputs;
- char **output_modes;
- char **inputs;
- char **clobbers;
- int num_outputs;
- int num_inputs;
- int num_clobbers;
- } asm_stmt;
-
- struct
- {
- char **param_names;
- char **param_types;
- char *return_type;
- ASTNode *body;
- int num_params;
- int lambda_id;
- int is_expression;
- char **captured_vars;
- char **captured_types;
- int num_captures;
- } lambda;
-
- struct
- {
- char *target_type;
- ASTNode *expr;
- } 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 {
+ NodeType type;
+ ASTNode *next;
+ int line; // Source line number for debugging.
+
+ // 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.
+
+ union {
+ struct {
+ ASTNode *children;
+ } root;
+
+ struct {
+ char *name;
+ char *args; // Legacy string args.
+ char *ret_type; // Legacy string return type.
+ ASTNode *body;
+ Type **arg_types;
+ char **defaults;
+ char **param_names; // Explicit parameter names.
+ int arg_count;
+ Type *ret_type_info;
+ int is_varargs;
+ int is_inline;
+ int must_use; // @must_use: 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_async; // async function
+ int is_comptime; // @comptime function
+ } func;
+
+ struct {
+ ASTNode *statements;
+ } block;
+
+ struct {
+ ASTNode *value;
+ } ret;
+
+ struct {
+ char *name;
+ char *type_str;
+ ASTNode *init_expr;
+ Type *type_info;
+ int is_autofree;
+ int is_mutable;
+ int is_static;
+ } var_decl;
+
+ struct {
+ char *name;
+ Type *payload;
+ int tag_id;
+ } variant;
+
+ struct {
+ char *name;
+ ASTNode *variants;
+ int is_template;
+ char *generic_param;
+ } enm;
+
+ struct {
+ char *alias;
+ char *original_type;
+ } 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;
+ ASTNode *body;
+ } for_range;
+
+ struct {
+ ASTNode *body;
+ char *loop_label;
+ } loop_stmt;
+
+ struct {
+ char *count;
+ ASTNode *body;
+ } repeat_stmt;
+
+ struct {
+ ASTNode *condition;
+ ASTNode *body;
+ } unless_stmt;
+
+ struct {
+ ASTNode *condition;
+ ASTNode *body;
+ } guard_stmt;
+
+ struct {
+ ASTNode *condition;
+ ASTNode *body;
+ char *loop_label;
+ } do_while_stmt;
+
+ struct {
+ ASTNode *expr;
+ ASTNode *cases;
+ } match_stmt;
+
+ struct {
+ char *pattern;
+ char *binding_name;
+ 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;
+ } unary;
+
+ struct {
+ int type_kind;
+ unsigned long long int_val;
+ double float_val;
+ char *string_val;
+ } literal;
+
+ struct {
+ char *name;
+ char *suggestion;
+ } var_ref;
+
+ struct {
+ ASTNode *callee;
+ ASTNode *args;
+ char **arg_names;
+ int arg_count;
+ } call;
+
+ struct {
+ ASTNode *target;
+ char *field;
+ int is_pointer_access;
+ } member;
+
+ struct {
+ ASTNode *array;
+ ASTNode *index;
+ } 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 {
+ char *name;
+ ASTNode *fields;
+ int is_template;
+ char *generic_param;
+ char *parent;
+ int is_union;
+ int is_packed; // @packed attribute.
+ int align; // @align(N) attribute, 0 = default.
+ int is_incomplete; // Forward declaration (prototype)
+ } strct;
+
+ struct {
+ char *name;
+ char *type;
+ int bit_width;
+ } field;
+
+ struct {
+ char *name;
+ ASTNode *methods;
+ } 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 *content;
+ char **used_symbols;
+ int used_symbol_count;
+ } raw_stmt;
+
+ struct {
+ char *name;
+ ASTNode *body;
+ } test_stmt;
+
+ struct {
+ ASTNode *condition;
+ char *message;
+ } assert_stmt;
+
+ struct {
+ ASTNode *stmt;
+ } defer_stmt;
+
+ struct {
+ char *plugin_name;
+ char *body;
+ } plugin_stmt;
+
+ struct {
+ char **names;
+ 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;
+ char **outputs;
+ char **output_modes;
+ char **inputs;
+ char **clobbers;
+ int num_outputs;
+ int num_inputs;
+ int num_clobbers;
+ } asm_stmt;
+
+ struct {
+ char **param_names;
+ char **param_types;
+ char *return_type;
+ ASTNode *body;
+ int num_params;
+ int lambda_id;
+ int is_expression;
+ char **captured_vars;
+ char **captured_types;
+ int num_captures;
+ } lambda;
+
+ struct {
+ char *target_type;
+ ASTNode *expr;
+ } 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;
+ };
};
// ** Functions **