diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-14 14:25:11 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-14 14:25:11 +0000 |
| commit | a918df69269a39ef7350a645b5db025d66ecb18a (patch) | |
| tree | 4ecb93f26e7e3ee2e256dd215c214b966df2d905 | |
| parent | df70f5bea676eb27e0ada10116d62f8c242c03a1 (diff) | |
Moving from to for improved error handling.
| -rw-r--r-- | src/parser/parser.h | 2 | ||||
| -rw-r--r-- | src/parser/parser_core.c | 22 | ||||
| -rw-r--r-- | src/parser/parser_expr.c | 98 | ||||
| -rw-r--r-- | src/parser/parser_stmt.c | 138 | ||||
| -rw-r--r-- | src/parser/parser_type.c | 12 | ||||
| -rw-r--r-- | src/parser/parser_utils.c | 23 |
6 files changed, 152 insertions, 143 deletions
diff --git a/src/parser/parser.h b/src/parser/parser.h index 9cdd0d2..4d105cf 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -312,7 +312,7 @@ void add_to_impl_list(ParserContext *ctx, ASTNode *node); void add_to_global_list(ParserContext *ctx, ASTNode *node); void register_builtins(ParserContext *ctx); void add_instantiated_func(ParserContext *ctx, ASTNode *fn); -void instantiate_generic(ParserContext *ctx, const char *name, const char *concrete_type); +void instantiate_generic(ParserContext *ctx, const char *name, const char *concrete_type, Token t); char *sanitize_mangled_name(const char *s); void register_impl(ParserContext *ctx, const char *trait, const char *strct); int check_impl(ParserContext *ctx, const char *trait, const char *strct); diff --git a/src/parser/parser_core.c b/src/parser/parser_core.c index 1a47275..7d5bc32 100644 --- a/src/parser/parser_core.c +++ b/src/parser/parser_core.c @@ -76,7 +76,7 @@ ASTNode *parse_program_nodes(ParserContext *ctx, Lexer *l) Token attr = lexer_next(l); if (attr.type != TOK_IDENT && attr.type != TOK_COMPTIME) { - zpanic("Expected attribute name after @"); + zpanic_at(attr, "Expected attribute name after @"); } if (0 == strncmp(attr.start, "must_use", 8) && 8 == attr.len) @@ -98,7 +98,7 @@ ASTNode *parse_program_nodes(ParserContext *ctx, Lexer *l) } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ) after deprecated message"); + zpanic_at(lexer_peek(l), "Expected ) after deprecated message"); } } } @@ -164,12 +164,12 @@ ASTNode *parse_program_nodes(ParserContext *ctx, Lexer *l) } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ) after section name"); + zpanic_at(lexer_peek(l), "Expected ) after section name"); } } else { - zpanic("@section requires a name: @section(\"name\")"); + zpanic_at(lexer_peek(l), "@section requires a name: @section(\"name\")"); } } else if (0 == strncmp(attr.start, "packed", 6) && 6 == attr.len) @@ -188,12 +188,12 @@ ASTNode *parse_program_nodes(ParserContext *ctx, Lexer *l) } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ) after align value"); + zpanic_at(lexer_peek(l), "Expected ) after align value"); } } else { - zpanic("@align requires a value: @align(N)"); + zpanic_at(lexer_peek(l), "@align requires a value: @align(N)"); } } else if (0 == strncmp(attr.start, "derive", 6) && 6 == attr.len) @@ -206,7 +206,7 @@ ASTNode *parse_program_nodes(ParserContext *ctx, Lexer *l) Token t = lexer_next(l); if (t.type != TOK_IDENT) { - zpanic("Expected trait name in @derive"); + zpanic_at(t, "Expected trait name in @derive"); } if (derived_count < 32) { @@ -223,12 +223,12 @@ ASTNode *parse_program_nodes(ParserContext *ctx, Lexer *l) } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ) after derive traits"); + zpanic_at(lexer_peek(l), "Expected ) after derive traits"); } } else { - zpanic("@derive requires traits: @derive(Debug, Clone)"); + zpanic_at(lexer_peek(l), "@derive requires traits: @derive(Debug, Clone)"); } } else @@ -372,7 +372,7 @@ ASTNode *parse_program_nodes(ParserContext *ctx, Lexer *l) lexer_next(l); if (lexer_peek(l).type != TOK_LBRACE) { - zpanic("Expected { after raw"); + zpanic_at(lexer_peek(l), "Expected { after raw"); } lexer_next(l); @@ -384,7 +384,7 @@ ASTNode *parse_program_nodes(ParserContext *ctx, Lexer *l) Token t = lexer_next(l); if (t.type == TOK_EOF) { - zpanic("Unexpected EOF in raw block"); + zpanic_at(t, "Unexpected EOF in raw block"); } if (t.type == TOK_LBRACE) { diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c index b9a1c35..40d6ae0 100644 --- a/src/parser/parser_expr.c +++ b/src/parser/parser_expr.c @@ -648,7 +648,7 @@ ASTNode *parse_lambda(ParserContext *ctx, Lexer *l) if (lexer_peek(l).type != TOK_LPAREN) { - zpanic("Expected '(' after 'fn' in lambda"); + zpanic_at(lexer_peek(l), "Expected '(' after 'fn' in lambda"); } lexer_next(l); @@ -663,7 +663,7 @@ ASTNode *parse_lambda(ParserContext *ctx, Lexer *l) { if (lexer_peek(l).type != TOK_COMMA) { - zpanic("Expected ',' between parameters"); + zpanic_at(lexer_peek(l), "Expected ',' between parameters"); } lexer_next(l); @@ -672,14 +672,14 @@ ASTNode *parse_lambda(ParserContext *ctx, Lexer *l) Token name_tok = lexer_next(l); if (name_tok.type != TOK_IDENT) { - zpanic("Expected parameter name"); + zpanic_at(name_tok, "Expected parameter name"); } param_names[num_params] = token_strdup(name_tok); if (lexer_peek(l).type != TOK_COLON) { - zpanic("Expected ':' after parameter name"); + zpanic_at(lexer_peek(l), "Expected ':' after parameter name"); } lexer_next(l); @@ -704,7 +704,7 @@ ASTNode *parse_lambda(ParserContext *ctx, Lexer *l) } else { - zpanic("Expected '{' for lambda body"); + zpanic_at(lexer_peek(l), "Expected '{' for lambda body"); } ASTNode *lambda = ast_create(NODE_LAMBDA); @@ -966,7 +966,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) { if (lexer_peek(l).type != TOK_LPAREN) { - zpanic("Expected ( after sizeof"); + zpanic_at(lexer_peek(l), "Expected ( after sizeof"); } lexer_next(l); @@ -992,7 +992,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) ASTNode *ex = parse_expression(ctx, l); if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ) after sizeof identifier"); + zpanic_at(lexer_peek(l), "Expected ) after sizeof identifier"); } node = ast_create(NODE_EXPR_SIZEOF); node->size_of.target_type = NULL; @@ -1005,7 +1005,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) { if (lexer_peek(l).type != TOK_LPAREN) { - zpanic("Expected ( after typeof"); + zpanic_at(lexer_peek(l), "Expected ( after typeof"); } lexer_next(l); @@ -1030,7 +1030,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) ASTNode *ex = parse_expression(ctx, l); if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ) after typeof expression"); + zpanic_at(lexer_peek(l), "Expected ) after typeof expression"); } node = ast_create(NODE_TYPEOF); node->size_of.target_type = NULL; @@ -1043,7 +1043,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) Token ident = lexer_next(l); if (ident.type != TOK_IDENT) { - zpanic("Expected intrinsic name after @"); + zpanic_at(ident, "Expected intrinsic name after @"); } int kind = -1; @@ -1057,19 +1057,25 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) } else { - zpanic("Unknown intrinsic @%.*s", ident.len, ident.start); + zpanic_at(ident, "Unknown intrinsic @%.*s", ident.len, ident.start); } - if (lexer_next(l).type != TOK_LPAREN) { - zpanic("Expected ( after intrinsic"); + Token t = lexer_next(l); + if (t.type != TOK_LPAREN) + { + zpanic_at(t, "Expected ( after intrinsic"); + } } Type *target = parse_type_formal(ctx, l); - if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ) after intrinsic type"); + Token t = lexer_next(l); + if (t.type != TOK_RPAREN) + { + zpanic_at(t, "Expected ) after intrinsic type"); + } } node = ast_create(NODE_REFLECTION); @@ -1082,9 +1088,12 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) { ASTNode *expr = parse_expression(ctx, l); skip_comments(l); - if (lexer_next(l).type != TOK_LBRACE) { - zpanic("Expected { after match expression"); + Token t = lexer_next(l); + if (t.type != TOK_LBRACE) + { + zpanic_at(t, "Expected { after match expression"); + } } ASTNode *h = 0, *tl = 0; @@ -1119,12 +1128,12 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) Token b = lexer_next(l); if (b.type != TOK_IDENT) { - zpanic("Expected binding name"); + zpanic_at(b, "Expected binding name"); } binding = token_strdup(b); if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected )"); + zpanic_at(lexer_peek(l), "Expected )"); } is_destructure = 1; } @@ -1140,7 +1149,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) skip_comments(l); if (lexer_next(l).type != TOK_ARROW) { - zpanic("Expected '=>'"); + zpanic_at(lexer_peek(l), "Expected '=>'"); } ASTNode *body; @@ -1224,7 +1233,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) Token suffix = lexer_next(l); if (suffix.type != TOK_IDENT) { - zpanic("Expected identifier after ::"); + zpanic_at(suffix, "Expected identifier after ::"); } SelectiveImport *si = @@ -1302,7 +1311,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) if (is_struct) { - instantiate_generic(ctx, acc, concrete_type); + instantiate_generic(ctx, acc, concrete_type, t); char *clean_type = sanitize_mangled_name(concrete_type); @@ -1323,7 +1332,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) } else { - zpanic("Unknown generic %s", acc); + zpanic_at(t, "Unknown generic %s", acc); } } changed = 1; @@ -1394,7 +1403,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) Token fn = lexer_next(l); if (lexer_next(l).type != TOK_COLON) { - zpanic("Expected :"); + zpanic_at(lexer_peek(l), "Expected :"); } ASTNode *val = parse_expression(ctx, l); ASTNode *assign = ast_create(NODE_VAR_DECL); @@ -1447,7 +1456,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected )"); + zpanic_at(lexer_peek(l), "Expected )"); } if (ac == 0) @@ -1593,7 +1602,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected )"); + zpanic_at(lexer_peek(l), "Expected )"); } for (int i = args_provided; i < sig->total_args; i++) { @@ -1696,7 +1705,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected )"); + zpanic_at(lexer_peek(l), "Expected )"); } node = ast_create(NODE_EXPR_CALL); @@ -1825,9 +1834,12 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) Type *cast_type_obj = parse_type_formal(ctx, l); char *cast_type = type_to_string(cast_type_obj); - if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ) after cast"); + Token t = lexer_next(l); + if (t.type != TOK_RPAREN) + { + zpanic_at(t, "Expected ) after cast"); + } } ASTNode *target = parse_expr_prec(ctx, l, PREC_UNARY); @@ -1844,7 +1856,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) ASTNode *expr = parse_expression(ctx, l); if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected )"); + zpanic_at(lexer_peek(l), "Expected )"); } node = expr; } @@ -1878,7 +1890,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) } if (lexer_next(l).type != TOK_RBRACKET) { - zpanic("Expected ] after array literal"); + zpanic_at(lexer_peek(l), "Expected ] after array literal"); } node = ast_create(NODE_EXPR_ARRAY_LITERAL); node->array_literal.elements = head; @@ -1952,9 +1964,12 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) } } } - if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ) after call arguments"); + Token t = lexer_next(l); + if (t.type != TOK_RPAREN) + { + zpanic_at(t, "Expected ) after call arguments"); + } } ASTNode *call = ast_create(NODE_EXPR_CALL); @@ -1980,9 +1995,12 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) { Token bracket = lexer_next(l); // consume '[' ASTNode *index = parse_expression(ctx, l); - if (lexer_next(l).type != TOK_RBRACKET) { - zpanic("Expected ] after index"); + Token t = lexer_next(l); + if (t.type != TOK_RBRACKET) + { + zpanic_at(t, "Expected ] after index"); + } } // Static Array Bounds Check @@ -2268,7 +2286,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected )"); + zpanic_at(lexer_peek(l), "Expected )"); } char fmt[256]; @@ -2581,7 +2599,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) Token tk = lexer_peek(l); if (tk.type == TOK_EOF) { - zpanic("Unterminated sizeof"); + zpanic_at(tk, "Unterminated sizeof"); } if (tk.type == TOK_LPAREN) { @@ -2607,7 +2625,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) } else { - zpanic("sizeof must be followed by ("); + zpanic_at(lexer_peek(l), "sizeof must be followed by ("); } } else @@ -2843,7 +2861,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected )"); + zpanic_at(lexer_peek(l), "Expected )"); } call->call.args = head; call->call.arg_names = has_named ? arg_names : NULL; @@ -2893,7 +2911,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) if (lexer_next(l).type != TOK_RBRACKET) { - zpanic("Expected ]"); + zpanic_at(lexer_peek(l), "Expected ]"); } if (is_slice) diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c index 484d742..227b5aa 100644 --- a/src/parser/parser_stmt.c +++ b/src/parser/parser_stmt.c @@ -56,7 +56,7 @@ ASTNode *parse_function(ParserContext *ctx, Lexer *l, int is_async) gen_param = token_strdup(gt); if (lexer_next(l).type != TOK_RANGLE) { - zpanic("Expected >"); + zpanic_at(lexer_peek(l), "Expected >"); } } @@ -193,9 +193,10 @@ ASTNode *parse_match(ParserContext *ctx, Lexer *l) lexer_next(l); // eat 'match' ASTNode *expr = parse_expression(ctx, l); - if (lexer_next(l).type != TOK_LBRACE) + Token t_brace = lexer_next(l); + if (t_brace.type != TOK_LBRACE) { - zpanic("Expected { in match"); + zpanic_at(t_brace, "Expected { in match"); } ASTNode *h = 0, *tl = 0; @@ -272,12 +273,12 @@ ASTNode *parse_match(ParserContext *ctx, Lexer *l) Token b = lexer_next(l); if (b.type != TOK_IDENT) { - zpanic("Expected variable name in pattern"); + zpanic_at(b, "Expected variable name in pattern"); } binding = token_strdup(b); if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected )"); + zpanic_at(lexer_peek(l), "Expected )"); } is_destructure = 1; } @@ -293,7 +294,7 @@ ASTNode *parse_match(ParserContext *ctx, Lexer *l) if (lexer_next(l).type != TOK_ARROW) { - zpanic("Expected =>"); + zpanic_at(lexer_peek(l), "Expected =>"); } ASTNode *body; @@ -386,7 +387,7 @@ ASTNode *parse_guard(ParserContext *ctx, Lexer *l) Token t = lexer_peek(l); if (t.type != TOK_IDENT || strncmp(t.start, "else", 4) != 0) { - zpanic("Expected 'else' after guard condition"); + zpanic_at(t, "Expected 'else' after guard condition"); } lexer_next(l); // consume 'else' @@ -445,7 +446,7 @@ ASTNode *parse_asm(ParserContext *ctx, Lexer *l) // Expect { if (lexer_peek(l).type != TOK_LBRACE) { - zpanic("Expected { after asm"); + zpanic_at(lexer_peek(l), "Expected { after asm"); } lexer_next(l); @@ -564,7 +565,7 @@ ASTNode *parse_asm(ParserContext *ctx, Lexer *l) } else { - zpanic("Expected assembly string, instruction, or ':' in asm block"); + zpanic_at(t, "Expected assembly string, instruction, or ':' in asm block"); } } @@ -601,19 +602,19 @@ ASTNode *parse_asm(ParserContext *ctx, Lexer *l) if (lexer_peek(l).type != TOK_LPAREN) { - zpanic("Expected ( after output mode"); + zpanic_at(lexer_peek(l), "Expected ( after output mode"); } lexer_next(l); Token var = lexer_next(l); if (var.type != TOK_IDENT) { - zpanic("Expected variable name"); + zpanic_at(var, "Expected variable name"); } if (lexer_peek(l).type != TOK_RPAREN) { - zpanic("Expected ) after variable"); + zpanic_at(lexer_peek(l), "Expected ) after variable"); } lexer_next(l); @@ -658,19 +659,19 @@ ASTNode *parse_asm(ParserContext *ctx, Lexer *l) if (lexer_peek(l).type != TOK_LPAREN) { - zpanic("Expected ( after in"); + zpanic_at(lexer_peek(l), "Expected ( after in"); } lexer_next(l); Token var = lexer_next(l); if (var.type != TOK_IDENT) { - zpanic("Expected variable name"); + zpanic_at(var, "Expected variable name"); } if (lexer_peek(l).type != TOK_RPAREN) { - zpanic("Expected ) after variable"); + zpanic_at(lexer_peek(l), "Expected ) after variable"); } lexer_next(l); @@ -726,7 +727,7 @@ ASTNode *parse_asm(ParserContext *ctx, Lexer *l) // Expect closing } if (lexer_peek(l).type != TOK_RBRACE) { - zpanic("Expected } at end of asm block"); + zpanic_at(lexer_peek(l), "Expected } at end of asm block"); } lexer_next(l); @@ -751,7 +752,7 @@ ASTNode *parse_test(ParserContext *ctx, Lexer *l) Token t = lexer_next(l); if (t.type != TOK_STRING) { - zpanic("Test name must be a string literal"); + zpanic_at(t, "Test name must be a string literal"); } // Strip quotes for AST storage @@ -784,7 +785,7 @@ ASTNode *parse_assert(ParserContext *ctx, Lexer *l) Token st = lexer_next(l); if (st.type != TOK_STRING) { - zpanic("Expected message string"); + zpanic_at(st, "Expected message string"); } msg = xmalloc(st.len + 1); strncpy(msg, st.start, st.len); @@ -895,12 +896,12 @@ ASTNode *parse_var_decl(ParserContext *ctx, Lexer *l) } if (next.type != TOK_COMMA) { - zpanic("Expected comma"); + zpanic_at(next, "Expected comma"); } } if (lexer_next(l).type != TOK_OP) { - zpanic("Expected ="); + zpanic_at(lexer_peek(l), "Expected ="); } ASTNode *init = parse_expression(ctx, l); if (lexer_peek(l).type == TOK_SEMICOLON) @@ -960,13 +961,13 @@ ASTNode *parse_var_decl(ParserContext *ctx, Lexer *l) } if (next.type != TOK_COMMA) { - zpanic("Expected comma in struct pattern"); + zpanic_at(next, "Expected comma in struct pattern"); } } if (lexer_next(l).type != TOK_OP) { - zpanic("Expected ="); + zpanic_at(lexer_peek(l), "Expected ="); } ASTNode *init = parse_expression(ctx, l); if (lexer_peek(l).type == TOK_SEMICOLON) @@ -993,12 +994,12 @@ ASTNode *parse_var_decl(ParserContext *ctx, Lexer *l) if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ')' in guard pattern"); + zpanic_at(lexer_peek(l), "Expected ')' in guard pattern"); } if (lexer_next(l).type != TOK_OP) { - zpanic("Expected '=' after guard pattern"); + zpanic_at(lexer_peek(l), "Expected '=' after guard pattern"); } ASTNode *init = parse_expression(ctx, l); @@ -1006,7 +1007,7 @@ ASTNode *parse_var_decl(ParserContext *ctx, Lexer *l) Token t = lexer_next(l); if (t.type != TOK_IDENT || strncmp(t.start, "else", 4) != 0) { - zpanic("Expected 'else' in guard statement"); + zpanic_at(t, "Expected 'else' in guard statement"); } ASTNode *else_blk; @@ -1141,7 +1142,7 @@ ASTNode *parse_var_decl(ParserContext *ctx, Lexer *l) } else if (init->type == NODE_EXPR_SLICE) { - zpanic("Slice Node has NO Type Info!"); + zpanic_at(init->token, "Slice Node has NO Type Info!"); } // Fallbacks for literals else if (init->type == NODE_EXPR_LITERAL) @@ -1963,7 +1964,7 @@ ASTNode *parse_macro_call(ParserContext *ctx, Lexer *l, char *macro_name) // Expect { if (lexer_peek(l).type != TOK_LBRACE) { - zpanic("Expected { after macro invocation"); + zpanic_at(lexer_peek(l), "Expected { after macro invocation"); } lexer_next(l); // consume { @@ -1979,7 +1980,7 @@ ASTNode *parse_macro_call(ParserContext *ctx, Lexer *l, char *macro_name) Token t = lexer_peek(l); if (t.type == TOK_EOF) { - zpanic("Unexpected EOF in macro block"); + zpanic_at(t, "Unexpected EOF in macro block"); } if (t.type == TOK_LBRACE) @@ -2025,7 +2026,7 @@ ASTNode *parse_macro_call(ParserContext *ctx, Lexer *l, char *macro_name) char err[256]; snprintf(err, sizeof(err), "Unknown plugin: %s (did you forget 'import plugin \"%s\"'?)", macro_name, macro_name); - zpanic(err); + zpanic_at(start_tok, err); } // Find Plugin Definition @@ -2036,14 +2037,14 @@ ASTNode *parse_macro_call(ParserContext *ctx, Lexer *l, char *macro_name) { char err[256]; snprintf(err, sizeof(err), "Plugin implementation not found: %s", plugin_name); - zpanic(err); + zpanic_at(start_tok, err); } // Execute Plugin Immediately (Expansion) FILE *capture = tmpfile(); if (!capture) { - zpanic("Failed to create capture buffer for plugin expansion"); + zpanic_at(start_tok, "Failed to create capture buffer for plugin expansion"); } ZApi api = {.filename = g_current_filename ? g_current_filename : "input.zc", @@ -2166,7 +2167,7 @@ ASTNode *parse_statement(ParserContext *ctx, Lexer *l) lexer_next(l); if (lexer_peek(l).type != TOK_IDENT || strncmp(lexer_peek(l).start, "var", 3) != 0) { - zpanic("Expected 'var' after autofree"); + zpanic_at(lexer_peek(l), "Expected 'var' after autofree"); } s = parse_var_decl(ctx, l); s->var_decl.is_autofree = 1; @@ -2260,7 +2261,7 @@ ASTNode *parse_statement(ParserContext *ctx, Lexer *l) lexer_next(l); // eat raw if (lexer_peek(l).type != TOK_LBRACE) { - zpanic("Expected { after raw"); + zpanic_at(lexer_peek(l), "Expected { after raw"); } lexer_next(l); // eat { @@ -2271,7 +2272,7 @@ ASTNode *parse_statement(ParserContext *ctx, Lexer *l) Token t = lexer_next(l); if (t.type == TOK_EOF) { - zpanic("Unexpected EOF in raw block"); + zpanic_at(t, "Unexpected EOF in raw block"); } if (t.type == TOK_LBRACE) { @@ -2518,7 +2519,7 @@ ASTNode *parse_statement(ParserContext *ctx, Lexer *l) Token t = lexer_next(l); if (t.type != TOK_STRING && t.type != TOK_FSTRING) { - zpanic("Expected string literal after print/eprint"); + zpanic_at(t, "Expected string literal after print/eprint"); } char *inner = xmalloc(t.len); @@ -2751,7 +2752,7 @@ ASTNode *parse_trait(ParserContext *ctx, Lexer *l) Token n = lexer_next(l); if (n.type != TOK_IDENT) { - zpanic("Expected trait name"); + zpanic_at(n, "Expected trait name"); } char *name = xmalloc(n.len + 1); strncpy(name, n.start, n.len); @@ -2778,7 +2779,7 @@ ASTNode *parse_trait(ParserContext *ctx, Lexer *l) Token ft = lexer_next(l); if (ft.type != TOK_IDENT || strncmp(ft.start, "fn", 2) != 0) { - zpanic("Expected fn in trait"); + zpanic_at(ft, "Expected fn in trait"); } Token mn = lexer_next(l); @@ -2825,7 +2826,7 @@ ASTNode *parse_trait(ParserContext *ctx, Lexer *l) else { // Default implementation? Not supported yet. - zpanic("Trait methods must end with ; for now"); + zpanic_at(lexer_peek(l), "Trait methods must end with ; for now"); } } @@ -2852,7 +2853,7 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) gen_param = token_strdup(gt); if (lexer_next(l).type != TOK_RANGLE) { - zpanic("Expected >"); + zpanic_at(lexer_peek(l), "Expected >"); } } @@ -2954,7 +2955,7 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) } else { - zpanic("Expected 'fn' after 'async'"); + zpanic_at(lexer_peek(l), "Expected 'fn' after 'async'"); } } else @@ -2990,7 +2991,7 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) // GENERIC IMPL TEMPLATE: impl Box<T> if (lexer_next(l).type != TOK_LBRACE) { - zpanic("Expected {"); + zpanic_at(lexer_peek(l), "Expected {"); } ASTNode *h = 0, *tl = 0; while (1) @@ -3051,7 +3052,7 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) } else { - zpanic("Expected 'fn' after 'async'"); + zpanic_at(lexer_peek(l), "Expected 'fn' after 'async'"); } } else @@ -3138,7 +3139,7 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) } else { - zpanic("Expected 'fn' after 'async'"); + zpanic_at(lexer_peek(l), "Expected 'fn' after 'async'"); } } else @@ -3284,7 +3285,7 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union) Token width_tok = lexer_next(l); if (width_tok.type != TOK_INT) { - zpanic("Expected bit width integer"); + zpanic_at(width_tok, "Expected bit width integer"); } f->field.bit_width = atoi(token_strdup(width_tok)); } @@ -3422,7 +3423,7 @@ ASTNode *parse_enum(ParserContext *ctx, Lexer *l) payload = parse_type_obj(ctx, l); if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected )"); + zpanic_at(lexer_peek(l), "Expected )"); } } @@ -3541,7 +3542,7 @@ ASTNode *parse_import(ParserContext *ctx, Lexer *l) Token plugin_tok = lexer_next(l); if (plugin_tok.type != TOK_STRING) { - zpanic("Expected string literal after 'import plugin'"); + zpanic_at(plugin_tok, "Expected string literal after 'import plugin'"); } // Extract plugin name (strip quotes) @@ -3559,7 +3560,7 @@ ASTNode *parse_import(ParserContext *ctx, Lexer *l) Token alias_tok = lexer_next(l); if (alias_tok.type != TOK_IDENT) { - zpanic("Expected identifier after 'as'"); + zpanic_at(alias_tok, "Expected identifier after 'as'"); } alias = token_strdup(alias_tok); } @@ -3600,7 +3601,7 @@ ASTNode *parse_import(ParserContext *ctx, Lexer *l) Token sym_tok = lexer_next(l); if (sym_tok.type != TOK_IDENT) { - zpanic("Expected identifier in selective import"); + zpanic_at(sym_tok, "Expected identifier in selective import"); } symbols[symbol_count] = xmalloc(sym_tok.len + 1); @@ -3615,7 +3616,7 @@ ASTNode *parse_import(ParserContext *ctx, Lexer *l) Token alias_tok = lexer_next(l); if (alias_tok.type != TOK_IDENT) { - zpanic("Expected identifier after 'as'"); + zpanic_at(alias_tok, "Expected identifier after 'as'"); } aliases[symbol_count] = xmalloc(alias_tok.len + 1); @@ -3637,7 +3638,8 @@ ASTNode *parse_import(ParserContext *ctx, Lexer *l) if (from_tok.type != TOK_IDENT || from_tok.len != 4 || strncmp(from_tok.start, "from", 4) != 0) { - zpanic("Expected 'from' after selective import list, got type=%d", from_tok.type); + zpanic_at(from_tok, "Expected 'from' after selective import list, got type=%d", + from_tok.type); } } @@ -3645,9 +3647,10 @@ ASTNode *parse_import(ParserContext *ctx, Lexer *l) Token t = lexer_next(l); if (t.type != TOK_STRING) { - zpanic("Expected string (filename) after 'from' in selective import, got " - "type %d", - t.type); + zpanic_at(t, + "Expected string (filename) after 'from' in selective import, got " + "type %d", + t.type); } int ln = t.len - 2; // Remove quotes char *fn = xmalloc(ln + 1); @@ -3737,7 +3740,7 @@ ASTNode *parse_import(ParserContext *ctx, Lexer *l) Token alias_tok = lexer_next(l); if (alias_tok.type != TOK_IDENT) { - zpanic("Expected identifier after 'as'"); + zpanic_at(alias_tok, "Expected identifier after 'as'"); } alias = xmalloc(alias_tok.len + 1); @@ -3767,19 +3770,6 @@ ASTNode *parse_import(ParserContext *ctx, Lexer *l) // C Header: Emit include and return (don't parse) if (strlen(fn) > 2 && strcmp(fn + strlen(fn) - 2, ".h") == 0) { - // We can iterate over registered modules to check if we missed setting - // is_c_header? But we handled 'as' above. If no 'as', we need to check if - // we should register it? Usually 'import "foo.h" as f' is required for - // namespacing. - - // Emit #include - // TODO: Where to emit? parser doesn't emit code usually. - // Actually, we can just return a NODE_INCLUDE AST! - // But wait, the user wants 'import as alias'. - - // If we return NULL, nothing happens. - // Use NODE_INCLUDE to ensure it gets emitted. - ASTNode *n = ast_create(NODE_INCLUDE); n->include.path = xstrdup(fn); // Store exact path n->include.is_system = 0; // Double quotes @@ -3790,7 +3780,7 @@ ASTNode *parse_import(ParserContext *ctx, Lexer *l) char *src = load_file(fn); if (!src) { - zpanic("Not found: %s", fn); + zpanic_at(t, "Not found: %s", fn); } Lexer i; @@ -3869,7 +3859,7 @@ char *run_comptime_block(ParserContext *ctx, Lexer *l) Token t = lexer_next(l); if (t.type == TOK_EOF) { - zpanic("Unexpected EOF in comptime block"); + zpanic_at(t, "Unexpected EOF in comptime block"); } if (t.type == TOK_LBRACE) { @@ -3909,7 +3899,7 @@ char *run_comptime_block(ParserContext *ctx, Lexer *l) FILE *f = fopen(filename, "w"); if (!f) { - zpanic("Could not create temp file %s", filename); + zpanic_at(lexer_peek(l), "Could not create temp file %s", filename); } emit_preamble(ctx, f); @@ -3992,7 +3982,7 @@ char *run_comptime_block(ParserContext *ctx, Lexer *l) int res = system(cmd); if (res != 0) { - zpanic("Comptime compilation failed for:\n%s", code); + zpanic_at(lexer_peek(l), "Comptime compilation failed for:\n%s", code); } char out_file[1024]; @@ -4000,7 +3990,7 @@ char *run_comptime_block(ParserContext *ctx, Lexer *l) sprintf(cmd, "./%s > %s", bin, out_file); if (system(cmd) != 0) { - zpanic("Comptime execution failed"); + zpanic_at(lexer_peek(l), "Comptime execution failed"); } char *output_src = load_file(out_file); @@ -4037,7 +4027,7 @@ ASTNode *parse_plugin(ParserContext *ctx, Lexer *l) Token tk = lexer_next(l); if (tk.type != TOK_IDENT) { - zpanic("Expected plugin name after 'plugin' keyword"); + zpanic_at(tk, "Expected plugin name after 'plugin' keyword"); } // Extract plugin name @@ -4055,7 +4045,7 @@ ASTNode *parse_plugin(ParserContext *ctx, Lexer *l) Token t = lexer_peek(l); if (t.type == TOK_EOF) { - zpanic("Unexpected EOF in plugin block, expected 'end'"); + zpanic_at(t, "Unexpected EOF in plugin block, expected 'end'"); } // Check for 'end' diff --git a/src/parser/parser_type.c b/src/parser/parser_type.c index cc33d99..d39e498 100644 --- a/src/parser/parser_type.c +++ b/src/parser/parser_type.c @@ -399,7 +399,7 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l) } char *arg_str = type_to_string(arg); - instantiate_generic(ctx, name, arg_str); + instantiate_generic(ctx, name, arg_str, t); char *clean_arg = sanitize_mangled_name(arg_str); char mangled[256]; @@ -455,7 +455,7 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l) } if (lexer_next(l).type != TOK_RBRACKET) { - zpanic("Expected ] after array size"); + zpanic_at(lexer_peek(l), "Expected ] after array size"); } Type *arr = type_new(TYPE_ARRAY); @@ -467,7 +467,7 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l) // Otherwise it's a slice [T] if (lexer_next(l).type != TOK_RBRACKET) { - zpanic("Expected ] in type"); + zpanic_at(lexer_peek(l), "Expected ] in type"); } // Register Slice @@ -505,7 +505,7 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l) } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ) in tuple"); + zpanic_at(lexer_peek(l), "Expected ) in tuple"); } register_tuple(ctx, sig); @@ -773,7 +773,7 @@ char *parse_embed(ParserContext *ctx, Lexer *l) Token t = lexer_next(l); if (t.type != TOK_STRING) { - zpanic("String required"); + zpanic_at(t, "String required"); } char fn[256]; strncpy(fn, t.start + 1, t.len - 2); @@ -782,7 +782,7 @@ char *parse_embed(ParserContext *ctx, Lexer *l) FILE *f = fopen(fn, "rb"); if (!f) { - zpanic("404: %s", fn); + zpanic_at(t, "404: %s", fn); } fseek(f, 0, SEEK_END); long len = ftell(f); diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index ba506a0..7af8d62 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -1761,7 +1761,7 @@ ASTNode *copy_fields_replacing(ParserContext *ctx, ASTNode *fields, const char * if (found) { - instantiate_generic(ctx, template_name, concrete_arg); + instantiate_generic(ctx, template_name, concrete_arg, fields->token); } } free(type_copy); @@ -1819,7 +1819,7 @@ void instantiate_methods(ParserContext *ctx, GenericImplTemplate *it, if (strcmp(gt->name, template_name) == 0) { // Found matching template, instantiate it - instantiate_generic(ctx, template_name, arg); + instantiate_generic(ctx, template_name, arg, meth->token); break; } gt = gt->next; @@ -1833,7 +1833,7 @@ void instantiate_methods(ParserContext *ctx, GenericImplTemplate *it, add_instantiated_func(ctx, new_impl); } -void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg) +void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg, Token token) { // Ignore generic placeholders if (strlen(arg) == 1 && isupper(arg[0])) @@ -1871,7 +1871,7 @@ void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg) } if (!t) { - zpanic("Unknown generic: %s", tpl); + zpanic_at(token, "Unknown generic: %s", tpl); } Instantiation *ni = xmalloc(sizeof(Instantiation)); @@ -1981,7 +1981,7 @@ char *parse_condition_raw(ParserContext *ctx, Lexer *l) t = lexer_next(l); if (t.type == TOK_EOF) { - zpanic("Unterminated condition"); + zpanic_at(t, "Unterminated condition"); } if (t.type == TOK_LPAREN) { @@ -2014,7 +2014,7 @@ char *parse_condition_raw(ParserContext *ctx, Lexer *l) int len = (l->src + l->pos) - start; if (len == 0) { - zpanic("Empty condition or missing body"); + zpanic_at(lexer_peek(l), "Empty condition or missing body"); } char *c = xmalloc(len + 1); strncpy(c, start, len); @@ -2340,9 +2340,10 @@ char *consume_and_rewrite(ParserContext *ctx, Lexer *l) char *parse_and_convert_args(ParserContext *ctx, Lexer *l, char ***defaults_out, int *count_out, Type ***types_out, char ***names_out, int *is_varargs_out) { - if (lexer_next(l).type != TOK_LPAREN) + Token t = lexer_next(l); + if (t.type != TOK_LPAREN) { - zpanic("Expected '(' in function args"); + zpanic_at(t, "Expected '(' in function args"); } char *buf = xmalloc(1024); @@ -2421,13 +2422,13 @@ char *parse_and_convert_args(ParserContext *ctx, Lexer *l, char ***defaults_out, { if (t.type != TOK_IDENT) { - zpanic("Expected arg name"); + zpanic_at(lexer_peek(l), "Expected arg name"); } char *name = token_strdup(t); names[count] = name; // Store name if (lexer_next(l).type != TOK_COLON) { - zpanic("Expected ':'"); + zpanic_at(lexer_peek(l), "Expected ':'"); } Type *arg_type = parse_type_formal(ctx, l); @@ -2500,7 +2501,7 @@ char *parse_and_convert_args(ParserContext *ctx, Lexer *l, char ***defaults_out, } if (lexer_next(l).type != TOK_RPAREN) { - zpanic("Expected ')' after args"); + zpanic_at(lexer_peek(l), "Expected ')' after args"); } *defaults_out = defaults; |
