summaryrefslogtreecommitdiff
path: root/src/parser/parser_struct.c
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-02-02 00:48:12 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-02-02 00:48:12 +0000
commit6bbcd9536522386a53cd2f87ece7aa6cf423829f (patch)
tree55d6dc2b4e2a9d84c09a67acb36f1ab4131e290c /src/parser/parser_struct.c
parentec140e5e1823ed72e1ac8ab4af121dbe1b3f85d7 (diff)
parentdadabf8b9d11d099777acc261068a3ed8ca06f24 (diff)
Merge branch 'main' of https://github.com/z-libs/Zen-C into patch-1
Diffstat (limited to 'src/parser/parser_struct.c')
-rw-r--r--src/parser/parser_struct.c133
1 files changed, 129 insertions, 4 deletions
diff --git a/src/parser/parser_struct.c b/src/parser/parser_struct.c
index 82dd346..0c984a6 100644
--- a/src/parser/parser_struct.c
+++ b/src/parser/parser_struct.c
@@ -12,6 +12,114 @@
#include "zprep_plugin.h"
#include "../codegen/codegen.h"
+extern char *g_current_filename;
+
+/**
+ * @brief Auto-imports std/mem.zc if not already imported.
+ *
+ * This is called when the Drop trait is used (impl Drop for X).
+ */
+static void auto_import_std_mem(ParserContext *ctx)
+{
+ // Check if Drop trait is already registered (means mem.zc was imported)
+ if (check_impl(ctx, "Drop", "__trait_marker__"))
+ {
+ // Check_impl returns 0 if not found, but we need a different check
+ // Let's check if we can find any indicator that mem.zc was loaded
+ }
+
+ // Try to find and import std/mem.zc
+ static const char *std_paths[] = {"std/mem.zc", "./std/mem.zc", NULL};
+ static const char *system_paths[] = {"/usr/local/share/zenc", "/usr/share/zenc", NULL};
+
+ char resolved_path[1024];
+ int found = 0;
+
+ // First, try relative to current file
+ if (g_current_filename)
+ {
+ char *current_dir = xstrdup(g_current_filename);
+ char *last_slash = strrchr(current_dir, '/');
+ if (last_slash)
+ {
+ *last_slash = 0;
+ snprintf(resolved_path, sizeof(resolved_path), "%s/std/mem.zc", current_dir);
+ if (access(resolved_path, R_OK) == 0)
+ {
+ found = 1;
+ }
+ }
+ free(current_dir);
+ }
+
+ // Try relative paths
+ if (!found)
+ {
+ for (int i = 0; std_paths[i] && !found; i++)
+ {
+ if (access(std_paths[i], R_OK) == 0)
+ {
+ strncpy(resolved_path, std_paths[i], sizeof(resolved_path) - 1);
+ resolved_path[sizeof(resolved_path) - 1] = '\0';
+ found = 1;
+ }
+ }
+ }
+
+ // Try system paths
+ if (!found)
+ {
+ for (int i = 0; system_paths[i] && !found; i++)
+ {
+ snprintf(resolved_path, sizeof(resolved_path), "%s/std/mem.zc", system_paths[i]);
+ if (access(resolved_path, R_OK) == 0)
+ {
+ found = 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ return; // Could not find std/mem.zc
+ }
+
+ // Canonicalize path
+ char *real_fn = realpath(resolved_path, NULL);
+ if (real_fn)
+ {
+ strncpy(resolved_path, real_fn, sizeof(resolved_path) - 1);
+ resolved_path[sizeof(resolved_path) - 1] = '\0';
+ free(real_fn);
+ }
+
+ // Check if already imported
+ if (is_file_imported(ctx, resolved_path))
+ {
+ return;
+ }
+ mark_file_imported(ctx, resolved_path);
+
+ // Load and parse the file
+ char *src = load_file(resolved_path);
+ if (!src)
+ {
+ return; // Could not load file
+ }
+
+ Lexer i;
+ lexer_init(&i, src);
+
+ // Save and restore filename context
+ char *saved_fn = g_current_filename;
+ g_current_filename = resolved_path;
+
+ // Parse the mem module contents
+ parse_program_nodes(ctx, &i);
+
+ g_current_filename = saved_fn;
+}
+
// Trait Parsing
ASTNode *parse_trait(ParserContext *ctx, Lexer *l)
{
@@ -100,7 +208,7 @@ ASTNode *parse_trait(ParserContext *ctx, Lexer *l)
char **param_names = NULL;
int is_varargs = 0;
char *args = parse_and_convert_args(ctx, l, &defaults, &arg_count, &arg_types, &param_names,
- &is_varargs);
+ &is_varargs, NULL);
char *ret = xstrdup("void");
if (lexer_peek(l).type == TOK_ARROW)
@@ -149,6 +257,7 @@ ASTNode *parse_trait(ParserContext *ctx, Lexer *l)
}
register_trait(name);
+ add_to_global_list(ctx, n_node); // Track for codegen (VTable emission)
return n_node;
}
@@ -206,6 +315,22 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l)
register_generic(ctx, target_gen_param);
}
+ // Check for common error: swapped Struct and Trait
+ // impl MyStruct for MyTrait (Wrong) vs impl MyTrait for MyStruct (Correct)
+ if (!is_trait(name1) && is_trait(name2))
+ {
+ zpanic_at(t1,
+ "Incorrect usage of impl. Did you mean 'impl %s for %s'? Syntax is 'impl "
+ "<Trait> for <Struct>'",
+ name2, name1);
+ }
+
+ // Auto-import std/mem.zc if implementing Drop, Copy, or Clone traits
+ if (strcmp(name1, "Drop") == 0 || strcmp(name1, "Copy") == 0 || strcmp(name1, "Clone") == 0)
+ {
+ auto_import_std_mem(ctx);
+ }
+
register_impl(ctx, name1, name2);
// RAII: Check for "Drop" trait implementation
@@ -748,7 +873,7 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union, int is_opaque)
Token field_name = lexer_next(l);
lexer_next(l); // eat :
Type *ft = parse_type_formal(ctx, l);
- char *field_type_str = type_to_string(ft);
+ char *field_type_str = type_to_c_string(ft);
expect(l, TOK_SEMICOLON, "Expected ;");
ASTNode *nf = ast_create(NODE_FIELD);
@@ -832,7 +957,7 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union, int is_opaque)
Token f_name = lexer_next(l);
expect(l, TOK_COLON, "Expected :");
Type *ft = parse_type_formal(ctx, l);
- char *f_type = type_to_string(ft);
+ char *f_type = type_to_c_string(ft);
ASTNode *f = ast_create(NODE_FIELD);
f->field.name = token_strdup(f_name);
@@ -1005,7 +1130,7 @@ ASTNode *parse_enum(ParserContext *ctx, Lexer *l)
while (lexer_peek(l).type == TOK_COMMA)
{
lexer_next(l); // eat ,
- strcat(sig, "_");
+ strcat(sig, "__");
Type *next_t = parse_type_obj(ctx, l);
char *ns = type_to_string(next_t);
if (strlen(sig) + strlen(ns) + 2 > 510)