diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-23 14:54:12 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-23 14:54:12 +0000 |
| commit | 8d0ea93a7220730ccce754429549fd63e4eeaa7c (patch) | |
| tree | 8af868229559a54829991a20b7641d6c608a108d /src/parser | |
| parent | f73df8d5de30a7f3f320fccf5f57c13094940a6a (diff) | |
Default arguments
Diffstat (limited to 'src/parser')
| -rw-r--r-- | src/parser/parser_expr.c | 6 | ||||
| -rw-r--r-- | src/parser/parser_stmt.c | 102 | ||||
| -rw-r--r-- | src/parser/parser_utils.c | 115 |
3 files changed, 139 insertions, 84 deletions
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c index be97707..bfbdb28 100644 --- a/src/parser/parser_expr.c +++ b/src/parser/parser_expr.c @@ -2093,8 +2093,10 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) { if (sig->defaults[i]) { - ASTNode *def = ast_create(NODE_RAW_STMT); - def->raw_stmt.content = xstrdup(sig->defaults[i]); + Lexer def_l; + lexer_init(&def_l, sig->defaults[i]); + ASTNode *def = parse_expression(ctx, &def_l); + if (!head) { head = def; diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c index 5eefb81..dfc99db 100644 --- a/src/parser/parser_stmt.c +++ b/src/parser/parser_stmt.c @@ -1376,19 +1376,20 @@ char *process_printf_sugar(ParserContext *ctx, const char *content, int newline, } expr = final_expr; - char *allocated_expr = NULL; clean_expr = final_expr; - int skip_rewrite = 0; + // Parse expression fully + Lexer lex; + lexer_init(&lex, clean_expr); + ASTNode *expr_node = parse_expression(ctx, &lex); - // Check if struct and has to_string (Robust Logic) - { - Lexer lex; - lexer_init(&lex, clean_expr); - // Parse using temporary lexer to check type - ASTNode *expr_node = parse_expression(ctx, &lex); + char *rw_expr = NULL; + int used_codegen = 0; - if (expr_node && expr_node->type_info) + if (expr_node) + { + // Check for to_string conversion on struct types + if (expr_node->type_info) { Type *t = expr_node->type_info; char *struct_name = NULL; @@ -1410,47 +1411,52 @@ char *process_printf_sugar(ParserContext *ctx, const char *content, int newline, sprintf(mangled, "%s__to_string", struct_name); if (find_func(ctx, mangled)) { - char *inner_wrapped = xmalloc(strlen(clean_expr) + 5); - sprintf(inner_wrapped, "#{%s}", clean_expr); - char *inner_c = rewrite_expr_methods(ctx, inner_wrapped); - free(inner_wrapped); - - // Now wrap in to_string call using C99 compound literal for safety - char *new_expr = xmalloc(strlen(inner_c) + strlen(mangled) + 64); - if (is_ptr) - { - sprintf(new_expr, "%s(%s)", mangled, inner_c); - } - else + char *inner_c = NULL; + size_t len = 0; + FILE *ms = open_memstream(&inner_c, &len); + if (ms) { - sprintf(new_expr, "%s(({ %s _z_tmp = (%s); &_z_tmp; }))", mangled, - struct_name, inner_c); + codegen_expression(ctx, expr_node, ms); + fclose(ms); } - if (expr != s) + if (inner_c) { - free(expr); // Free if explicitly allocated + char *new_expr = xmalloc(strlen(inner_c) + strlen(mangled) + 64); + if (is_ptr) + { + sprintf(new_expr, "%s(%s)", mangled, inner_c); + } + else + { + sprintf(new_expr, "%s(({ %s _z_tmp = (%s); &_z_tmp; }))", mangled, + struct_name, inner_c); + } + rw_expr = new_expr; + free(inner_c); } - expr = new_expr; - skip_rewrite = 1; // Don't rewrite again on the C99 syntax } } } - } - // Rewrite the expression to handle pointer access (header_ptr.magic -> - // header_ptr->magic) - char *rw_expr; - if (skip_rewrite) - { - rw_expr = xstrdup(expr); + if (!rw_expr) + { + char *buf = NULL; + size_t len = 0; + FILE *ms = open_memstream(&buf, &len); + if (ms) + { + codegen_expression(ctx, expr_node, ms); + fclose(ms); + rw_expr = buf; + used_codegen = 1; + } + } } - else + + if (!rw_expr) { - char *wrapped_expr = xmalloc(strlen(expr) + 5); - sprintf(wrapped_expr, "#{%s}", expr); - rw_expr = rewrite_expr_methods(ctx, wrapped_expr); - free(wrapped_expr); + rw_expr = xstrdup(expr); // Fallback } if (fmt) @@ -1466,11 +1472,10 @@ char *process_printf_sugar(ParserContext *ctx, const char *content, int newline, } else { - // Auto-detect format based on type if possible const char *format_spec = NULL; - char *inferred_type = find_symbol_type(ctx, clean_expr); // Simple variable lookup + Type *t = expr_node ? expr_node->type_info : NULL; + char *inferred_type = t ? type_to_string(t) : find_symbol_type(ctx, clean_expr); - // Basic Type Mappings if (inferred_type) { if (strcmp(inferred_type, "int") == 0 || strcmp(inferred_type, "i32") == 0 || @@ -1507,6 +1512,10 @@ char *process_printf_sugar(ParserContext *ctx, const char *content, int newline, { format_spec = "%p"; // Pointer } + if (t) + { + free(inferred_type); + } } // Check for Literals if variable lookup failed @@ -1549,10 +1558,13 @@ char *process_printf_sugar(ParserContext *ctx, const char *content, int newline, } } - free(rw_expr); // Don't forget to free! - if (allocated_expr) + if (rw_expr && used_codegen) + { + free(rw_expr); + } + else if (rw_expr && !used_codegen) { - free(allocated_expr); // Don't forget to free the auto-generated call! + free(rw_expr); } cur = p + 1; diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index 918e8e1..97e6e78 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -1991,10 +1991,9 @@ char *instantiate_function_template(ParserContext *ctx, const char *name, const char *process_fstring(ParserContext *ctx, const char *content, char ***used_syms, int *count) { - (void)ctx; // suppress unused parameter warning - char *gen = xmalloc(4096); + char *gen = xmalloc(8192); // Increased buffer size - strcpy(gen, "({ static char _b[1024]; _b[0]=0; char _t[128]; "); + strcpy(gen, "({ static char _b[4096]; _b[0]=0; char _t[1024]; "); char *s = xstrdup(content); char *cur = s; @@ -2048,7 +2047,7 @@ char *process_fstring(ParserContext *ctx, const char *content, char ***used_syms } *p = 0; - char *expr = brace + 1; + char *expr_str = brace + 1; char *fmt = NULL; if (colon) { @@ -2056,34 +2055,19 @@ char *process_fstring(ParserContext *ctx, const char *content, char ***used_syms fmt = colon + 1; } - // Analyze usage in expression - { - Lexer lex; - lexer_init(&lex, expr); - Token t; - while ((t = lexer_next(&lex)).type != TOK_EOF) - { - if (t.type == TOK_IDENT) - { - char *name = token_strdup(t); - Symbol *sym = find_symbol_entry(ctx, name); - if (sym) - { - sym->is_used = 1; - } + // Parse expression fully to handle default arguments etc. + Lexer expr_lex; + lexer_init(&expr_lex, expr_str); + ASTNode *expr_node = parse_expression(ctx, &expr_lex); - if (used_syms && count) - { - *used_syms = xrealloc(*used_syms, sizeof(char *) * (*count + 1)); - (*used_syms)[*count] = name; - (*count)++; - } - else - { - free(name); - } - } - } + // Codegen expression to temporary buffer + char *code_buffer = NULL; + size_t code_len = 0; + FILE *mem_stream = open_memstream(&code_buffer, &code_len); + if (mem_stream) + { + codegen_expression(ctx, expr_node, mem_stream); + fclose(mem_stream); } if (fmt) @@ -2091,18 +2075,44 @@ char *process_fstring(ParserContext *ctx, const char *content, char ***used_syms strcat(gen, "sprintf(_t, \"%"); strcat(gen, fmt); strcat(gen, "\", "); - strcat(gen, expr); + if (code_buffer) + { + strcat(gen, code_buffer); + } + else + { + strcat(gen, expr_str); // Fallback + } strcat(gen, "); strcat(_b, _t); "); } else { strcat(gen, "sprintf(_t, _z_str("); - strcat(gen, expr); + if (code_buffer) + { + strcat(gen, code_buffer); + } + else + { + strcat(gen, expr_str); + } strcat(gen, "), "); - strcat(gen, expr); + if (code_buffer) + { + strcat(gen, code_buffer); + } + else + { + strcat(gen, expr_str); + } strcat(gen, "); strcat(_b, _t); "); } + if (code_buffer) + { + free(code_buffer); + } + cur = p + 1; } @@ -3261,9 +3271,40 @@ char *parse_and_convert_args(ParserContext *ctx, Lexer *l, char ***defaults_out, if (lexer_peek(l).type == TOK_OP && is_token(lexer_peek(l), "=")) { - lexer_next(l); - Token val = lexer_next(l); - defaults[count - 1] = token_strdup(val); + lexer_next(l); // consume = + + const char *start_ptr = lexer_peek(l).start; + int nesting = 0; + while (1) + { + Token t = lexer_peek(l); + if (t.type == TOK_EOF) + { + zpanic_at(t, "Unexpected EOF in default arg"); + } + + if (nesting == 0 && (t.type == TOK_COMMA || t.type == TOK_RPAREN)) + { + break; + } + + if (t.type == TOK_LPAREN || t.type == TOK_LBRACE || t.type == TOK_LBRACKET) + { + nesting++; + } + if (t.type == TOK_RPAREN || t.type == TOK_RBRACE || t.type == TOK_RBRACKET) + { + nesting--; + } + + lexer_next(l); + } + const char *end_ptr = lexer_peek(l).start; + size_t len = end_ptr - start_ptr; + char *def_val = xmalloc(len + 1); + strncpy(def_val, start_ptr, len); + def_val[len] = 0; + defaults[count - 1] = def_val; } } if (lexer_peek(l).type == TOK_COMMA) |
