From d7b24c552305f1bd8c49e253d14dcf4b1581df2c Mon Sep 17 00:00:00 2001 From: Zuhaitz Méndez Fernández de Aránguiz Date: Fri, 23 Jan 2026 17:29:30 +0000 Subject: Fix for #94 --- src/parser/parser.h | 15 ++++++++++ src/parser/parser_expr.c | 5 +++- src/parser/parser_struct.c | 28 +++++++++++++++-- src/parser/parser_type.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++ src/parser/parser_utils.c | 56 +++++++++++++++++++++++++++++----- 5 files changed, 168 insertions(+), 11 deletions(-) (limited to 'src/parser') diff --git a/src/parser/parser.h b/src/parser/parser.h index 6f62435..6ac55bf 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -268,8 +268,23 @@ struct ParserContext int is_repl; // REPL mode flag int has_async; // Track if async features are used int in_defer_block; // Track if currently parsing inside a defer block + + // Type Validation + struct TypeUsage *pending_type_validations; + int is_speculative; // Flag to suppress side effects during speculative parsing }; +typedef struct TypeUsage +{ + char *name; + Token location; + struct TypeUsage *next; +} TypeUsage; + +// Type validation prototypes +void register_type_usage(ParserContext *ctx, const char *name, Token t); +int validate_types(ParserContext *ctx); + // Token helpers char *token_strdup(Token t); int is_token(Token t, const char *s); diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c index 990942d..ae7abe9 100644 --- a/src/parser/parser_expr.c +++ b/src/parser/parser_expr.c @@ -1611,6 +1611,8 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) lexer_next(&lookahead); int valid_generic = 0; + int saved_speculative = ctx->is_speculative; + ctx->is_speculative = 1; while (1) { parse_type(ctx, &lookahead); @@ -1625,6 +1627,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) } break; } + ctx->is_speculative = saved_speculative; if (valid_generic) { @@ -2433,7 +2436,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) register_tuple(ctx, sig); - char tuple_name[256]; + char tuple_name[1024]; sprintf(tuple_name, "Tuple_%s", sig); char *code = xmalloc(4096); diff --git a/src/parser/parser_struct.c b/src/parser/parser_struct.c index 600d60d..01d1156 100644 --- a/src/parser/parser_struct.c +++ b/src/parser/parser_struct.c @@ -166,6 +166,11 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) } } + if (gen_param) + { + register_generic(ctx, gen_param); + } + // Check for "for" (Trait impl) Token pk = lexer_peek(l); if (pk.type == TOK_FOR || @@ -324,6 +329,10 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) register_impl_template(ctx, name2, gp, n); } + if (gen_param) + { + ctx->known_generics_count--; + } return n; } else @@ -463,6 +472,10 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) n->impl.methods = h; register_impl_template(ctx, name1, gen_param, n); ctx->current_impl_struct = NULL; + if (gen_param) + { + ctx->known_generics_count--; + } return NULL; // Do not emit generic template } else @@ -549,6 +562,11 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) n->impl.struct_name = name1; n->impl.methods = h; add_to_impl_list(ctx, n); + + if (gen_param) + { + ctx->known_generics_count--; + } return n; } } @@ -588,7 +606,11 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union) zpanic_at(next, "Expected ',' or '>' in generic parameter list"); } } - register_generic(ctx, name); + + for (int i = 0; i < gp_count; i++) + { + register_generic(ctx, gps[i]); + } } // Check for prototype (forward declaration) @@ -798,6 +820,7 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union) if (gp_count > 0) { node->strct.is_template = 1; + ctx->known_generics_count -= gp_count; register_template(ctx, name, node); } @@ -841,7 +864,7 @@ ASTNode *parse_enum(ParserContext *ctx, Lexer *l) Token g = lexer_next(l); gp = token_strdup(g); lexer_next(l); // eat > - register_generic(ctx, n.start ? token_strdup(n) : "anon"); + register_generic(ctx, gp); } lexer_next(l); // eat { @@ -934,6 +957,7 @@ ASTNode *parse_enum(ParserContext *ctx, Lexer *l) if (gp) { node->enm.is_template = 1; + ctx->known_generics_count--; register_template(ctx, node->enm.name, node); } diff --git a/src/parser/parser_type.c b/src/parser/parser_type.c index 4e44c00..b11bedb 100644 --- a/src/parser/parser_type.c +++ b/src/parser/parser_type.c @@ -368,6 +368,76 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l) free(name); return type_new(TYPE_CHAR); } + if (strcmp(name, "long") == 0) + { + free(name); + return type_new(TYPE_I64); + } + if (strcmp(name, "short") == 0) + { + free(name); + return type_new(TYPE_I16); + } + if (strcmp(name, "unsigned") == 0) + { + free(name); + return type_new(TYPE_UINT); + } + if (strcmp(name, "signed") == 0) + { + free(name); + return type_new(TYPE_INT); + } + if (strcmp(name, "int8_t") == 0) + { + free(name); + return type_new(TYPE_I8); + } + if (strcmp(name, "uint8_t") == 0) + { + free(name); + return type_new(TYPE_U8); + } + if (strcmp(name, "int16_t") == 0) + { + free(name); + return type_new(TYPE_I16); + } + if (strcmp(name, "uint16_t") == 0) + { + free(name); + return type_new(TYPE_U16); + } + if (strcmp(name, "int32_t") == 0) + { + free(name); + return type_new(TYPE_I32); + } + if (strcmp(name, "uint32_t") == 0) + { + free(name); + return type_new(TYPE_U32); + } + if (strcmp(name, "int64_t") == 0) + { + free(name); + return type_new(TYPE_I64); + } + if (strcmp(name, "uint64_t") == 0) + { + free(name); + return type_new(TYPE_U64); + } + if (strcmp(name, "size_t") == 0) + { + free(name); + return type_new(TYPE_USIZE); + } + if (strcmp(name, "ssize_t") == 0) + { + free(name); + return type_new(TYPE_ISIZE); + } // Selective imports ONLY apply when we're NOT in a module context if (!ctx->current_module_prefix) @@ -395,6 +465,11 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l) name = prefixed_name; } + if (!is_known_generic(ctx, name) && strcmp(name, "Self") != 0) + { + register_type_usage(ctx, name, t); + } + Type *ty = type_new(TYPE_STRUCT); ty->name = name; ty->is_explicit_struct = explicit_struct; diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index 97e6e78..b322881 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -876,10 +876,10 @@ char *replace_in_string(const char *src, const char *old_w, const char *new_w) while (*p_ptr && *c_ptr) { char *p_end = strchr(p_ptr, ','); - int p_len = p_end ? (p_end - p_ptr) : strlen(p_ptr); + int p_len = p_end ? (int)(p_end - p_ptr) : (int)strlen(p_ptr); char *c_end = strchr(c_ptr, ','); - int c_len = c_end ? (c_end - c_ptr) : strlen(c_ptr); + int c_len = c_end ? (int)(c_end - c_ptr) : (int)strlen(c_ptr); char *curr_p = xmalloc(p_len + 1); strncpy(curr_p, p_ptr, p_len); @@ -1007,12 +1007,12 @@ char *replace_type_str(const char *src, const char *param, const char *concrete, while (*p_ptr && *c_ptr) { char *p_end = strchr(p_ptr, ','); - int p_len = p_end ? (p_end - p_ptr) : strlen(p_ptr); + int p_len = p_end ? (int)(p_end - p_ptr) : (int)strlen(p_ptr); char *c_end = strchr(c_ptr, ','); - int c_len = c_end ? (c_end - c_ptr) : strlen(c_ptr); + int c_len = c_end ? (int)(c_end - c_ptr) : (int)strlen(c_ptr); - if (strlen(src) == p_len && strncmp(src, p_ptr, p_len) == 0) + if ((int)strlen(src) == p_len && strncmp(src, p_ptr, p_len) == 0) { char *ret = xmalloc(c_len + 1); strncpy(ret, c_ptr, c_len); @@ -1299,11 +1299,11 @@ Type *replace_type_formal(Type *t, const char *p, const char *c, const char *os, while (*p_ptr && *c_ptr) { char *p_end = strchr(p_ptr, ','); - int p_len = p_end ? (p_end - p_ptr) : strlen(p_ptr); + int p_len = p_end ? (int)(p_end - p_ptr) : (int)strlen(p_ptr); char *c_end = strchr(c_ptr, ','); - int c_len = c_end ? (c_end - c_ptr) : strlen(c_ptr); + int c_len = c_end ? (int)(c_end - c_ptr) : (int)strlen(c_ptr); - if (strlen(t->name) == p_len && strncmp(t->name, p_ptr, p_len) == 0) + if ((int)strlen(t->name) == p_len && strncmp(t->name, p_ptr, p_len) == 0) { char *c_part = xmalloc(c_len + 1); strncpy(c_part, c_ptr, c_len); @@ -1991,6 +1991,8 @@ char *instantiate_function_template(ParserContext *ctx, const char *name, const char *process_fstring(ParserContext *ctx, const char *content, char ***used_syms, int *count) { + (void)used_syms; + (void)count; char *gen = xmalloc(8192); // Increased buffer size strcpy(gen, "({ static char _b[4096]; _b[0]=0; char _t[1024]; "); @@ -3435,3 +3437,41 @@ const char *resolve_plugin(ParserContext *ctx, const char *name_or_alias) } return NULL; // Plugin not found } + +// Type Validation +void register_type_usage(ParserContext *ctx, const char *name, Token t) +{ + if (ctx->is_speculative) + { + return; + } + + TypeUsage *u = xmalloc(sizeof(TypeUsage)); + u->name = xstrdup(name); + u->location = t; + u->next = ctx->pending_type_validations; + ctx->pending_type_validations = u; +} + +int validate_types(ParserContext *ctx) +{ + int errors = 0; + TypeUsage *u = ctx->pending_type_validations; + while (u) + { + ASTNode *def = find_struct_def(ctx, u->name); + const char *alias = find_type_alias(ctx, u->name); + + if (!def && !alias) + { + SelectiveImport *si = find_selective_import(ctx, u->name); + if (!si && !is_trait(u->name)) + { + zpanic_at(u->location, "Unknown type '%s'", u->name); + errors++; + } + } + u = u->next; + } + return errors == 0; +} -- cgit v1.2.3