From f3d2544b18fe8267edaba97474033782f7da3f40 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Sat, 24 Jan 2026 05:53:02 +0300 Subject: open_memstream -> tmpfile --- src/parser/parser_utils.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/parser/parser_utils.c') diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index 05ea74a..a090298 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -2108,10 +2108,15 @@ char *process_fstring(ParserContext *ctx, const char *content, char ***used_syms // Codegen expression to temporary buffer char *code_buffer = NULL; size_t code_len = 0; - FILE *mem_stream = open_memstream(&code_buffer, &code_len); + FILE *mem_stream = tmpfile(); if (mem_stream) { codegen_expression(ctx, expr_node, mem_stream); + code_len = ftell(mem_stream); + code_buffer = xmalloc(code_len + 1); + fseek(mem_stream, 0, SEEK_SET); + fread(code_buffer, 1, code_len, mem_stream); + code_buffer[code_len] = 0; fclose(mem_stream); } -- cgit v1.2.3 From 812fe9cbe124bf39a06f58a538c8c01f7402fb09 Mon Sep 17 00:00:00 2001 From: Zuhaitz Méndez Fernández de Aránguiz Date: Sat, 24 Jan 2026 12:14:48 +0000 Subject: Fix for #110 --- src/ast/ast.h | 11 ++++++++++- src/codegen/codegen.c | 11 ++++++----- src/codegen/codegen_stmt.c | 5 +++-- src/codegen/codegen_utils.c | 10 +++++----- src/parser/parser_decl.c | 8 ++++---- src/parser/parser_expr.c | 38 +++++++++++++++++++------------------- src/parser/parser_stmt.c | 8 ++++---- src/parser/parser_utils.c | 2 +- tests/features/test_tuples.zc | 5 +++++ 9 files changed, 57 insertions(+), 41 deletions(-) (limited to 'src/parser/parser_utils.c') diff --git a/src/ast/ast.h b/src/ast/ast.h index 6ef5d7a..5bcc4d5 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -11,6 +11,15 @@ typedef struct ASTNode ASTNode; // ** Formal Type System ** // Used for Generics, Type Inference, and robust pointer handling. + +typedef enum +{ + LITERAL_INT = 0, + LITERAL_FLOAT = 1, + LITERAL_STRING = 2, + LITERAL_CHAR = 3 +} LiteralKind; + typedef enum { TYPE_VOID, @@ -329,7 +338,7 @@ struct ASTNode struct { - int type_kind; + LiteralKind type_kind; unsigned long long int_val; double float_val; char *string_val; diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index 706d613..038f3cb 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -11,22 +11,23 @@ #include "ast.h" #include "zprep_plugin.h" +// Emit literal expression (int, float, string, char) // Emit literal expression (int, float, string, char) static void codegen_literal_expr(ASTNode *node, FILE *out) { - if (node->literal.type_kind == TOK_STRING) + if (node->literal.type_kind == LITERAL_STRING) { fprintf(out, "\"%s\"", node->literal.string_val); } - else if (node->literal.type_kind == TOK_CHAR) + else if (node->literal.type_kind == LITERAL_CHAR) { fprintf(out, "%s", node->literal.string_val); } - else if (node->literal.type_kind == 1) // float + else if (node->literal.type_kind == LITERAL_FLOAT) { fprintf(out, "%f", node->literal.float_val); } - else // int + else // LITERAL_INT { if (node->literal.int_val > 9223372036854775807ULL) { @@ -34,7 +35,7 @@ static void codegen_literal_expr(ASTNode *node, FILE *out) } else { - fprintf(out, "%llu", (unsigned long long)node->literal.int_val); + fprintf(out, "%lld", (long long)node->literal.int_val); } } } diff --git a/src/codegen/codegen_stmt.c b/src/codegen/codegen_stmt.c index 54c6a14..406a6e5 100644 --- a/src/codegen/codegen_stmt.c +++ b/src/codegen/codegen_stmt.c @@ -475,7 +475,8 @@ void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out, int us // Check if body is a string literal (should auto-print). ASTNode *body = c->match_case.body; - int is_string_literal = (body->type == NODE_EXPR_LITERAL && body->literal.type_kind == 2); + int is_string_literal = + (body->type == NODE_EXPR_LITERAL && body->literal.type_kind == LITERAL_STRING); if (is_expr) { @@ -1576,7 +1577,7 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) } case NODE_EXPR_LITERAL: // String literal statement should auto-print - if (node->literal.type_kind == 2 || node->literal.type_kind == TOK_STRING) + if (node->literal.type_kind == LITERAL_STRING) { fprintf(out, " printf(\"%%s\\n\", "); codegen_expression(ctx, node, out); diff --git a/src/codegen/codegen_utils.c b/src/codegen/codegen_utils.c index fe580bf..a7e4925 100644 --- a/src/codegen/codegen_utils.c +++ b/src/codegen/codegen_utils.c @@ -455,15 +455,15 @@ char *infer_type(ParserContext *ctx, ASTNode *node) if (node->type == NODE_EXPR_LITERAL) { - if (node->literal.type_kind == TOK_STRING) + if (node->literal.type_kind == LITERAL_STRING) { - return "string"; + return xstrdup("string"); } - if (node->literal.type_kind == TOK_CHAR) + if (node->literal.type_kind == LITERAL_CHAR) { - return "char"; + return xstrdup("char"); } - if (node->literal.type_kind == 1) + if (node->literal.type_kind == LITERAL_FLOAT) { return "double"; } diff --git a/src/parser/parser_decl.c b/src/parser/parser_decl.c index 7e0cc5b..bd56350 100644 --- a/src/parser/parser_decl.c +++ b/src/parser/parser_decl.c @@ -562,17 +562,17 @@ ASTNode *parse_var_decl(ParserContext *ctx, Lexer *l) // Fallbacks for literals else if (init->type == NODE_EXPR_LITERAL) { - if (init->literal.type_kind == 0) + if (init->literal.type_kind == LITERAL_INT) { type = xstrdup("int"); type_obj = type_new(TYPE_INT); } - else if (init->literal.type_kind == 1) + else if (init->literal.type_kind == LITERAL_FLOAT) { type = xstrdup("float"); type_obj = type_new(TYPE_FLOAT); } - else if (init->literal.type_kind == 2) + else if (init->literal.type_kind == LITERAL_STRING) { type = xstrdup("string"); type_obj = type_new(TYPE_STRING); @@ -596,7 +596,7 @@ ASTNode *parse_var_decl(ParserContext *ctx, Lexer *l) add_symbol_with_token(ctx, name, type, type_obj, name_tok); // NEW: Capture Const Integer Values - if (init && init->type == NODE_EXPR_LITERAL && init->literal.type_kind == 0) + if (init && init->type == NODE_EXPR_LITERAL && init->literal.type_kind == LITERAL_INT) { Symbol *s = find_symbol_entry(ctx, name); // Helper to find the struct if (s) diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c index 32a054e..e21c983 100644 --- a/src/parser/parser_expr.c +++ b/src/parser/parser_expr.c @@ -203,7 +203,7 @@ static void check_format_string(ASTNode *call, Token t) return; } - if (fmt_arg->type != NODE_EXPR_LITERAL || fmt_arg->literal.type_kind != TOK_STRING) + if (fmt_arg->type != NODE_EXPR_LITERAL || fmt_arg->literal.type_kind != 2) { return; } @@ -991,7 +991,7 @@ static ASTNode *create_fstring_block(ParserContext *ctx, const char *content) char *fmt_str = xmalloc(strlen(fmt) + 3); sprintf(fmt_str, "%%%s", fmt); arg_fmt = ast_create(NODE_EXPR_LITERAL); - arg_fmt->literal.type_kind = 2; + arg_fmt->literal.type_kind = LITERAL_STRING; arg_fmt->literal.string_val = fmt_str; arg_fmt->type_info = type_new(TYPE_STRING); } @@ -1045,7 +1045,7 @@ static ASTNode *create_fstring_block(ParserContext *ctx, const char *content) static ASTNode *parse_int_literal(Token t) { ASTNode *node = ast_create(NODE_EXPR_LITERAL); - node->literal.type_kind = 0; + node->literal.type_kind = LITERAL_INT; node->type_info = type_new(TYPE_INT); char *s = token_strdup(t); unsigned long long val; @@ -1066,7 +1066,7 @@ static ASTNode *parse_int_literal(Token t) static ASTNode *parse_float_literal(Token t) { ASTNode *node = ast_create(NODE_EXPR_LITERAL); - node->literal.type_kind = 1; + node->literal.type_kind = LITERAL_FLOAT; node->literal.float_val = atof(t.start); node->type_info = type_new(TYPE_F64); return node; @@ -1076,7 +1076,7 @@ static ASTNode *parse_float_literal(Token t) static ASTNode *parse_string_literal(Token t) { ASTNode *node = ast_create(NODE_EXPR_LITERAL); - node->literal.type_kind = TOK_STRING; + node->literal.type_kind = LITERAL_STRING; node->literal.string_val = xmalloc(t.len); strncpy(node->literal.string_val, t.start + 1, t.len - 2); node->literal.string_val[t.len - 2] = 0; @@ -1099,7 +1099,7 @@ static ASTNode *parse_fstring_literal(ParserContext *ctx, Token t) static ASTNode *parse_char_literal(Token t) { ASTNode *node = ast_create(NODE_EXPR_LITERAL); - node->literal.type_kind = TOK_CHAR; + node->literal.type_kind = LITERAL_CHAR; node->literal.string_val = token_strdup(t); node->type_info = type_new(TYPE_I8); return node; @@ -2046,7 +2046,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) node->type_info = type_new(TYPE_INT); // Returns count ASTNode *fmt_node = ast_create(NODE_EXPR_LITERAL); - fmt_node->literal.type_kind = 2; // string + fmt_node->literal.type_kind = LITERAL_STRING; // string fmt_node->literal.string_val = xstrdup(fmt); ASTNode *head = fmt_node, *tail = fmt_node; @@ -2540,7 +2540,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) // Constant Folding for 'def', emits literal node = ast_create(NODE_EXPR_LITERAL); node->token = t; - node->literal.type_kind = 0; // INT (assumed for now from const_int_val) + node->literal.type_kind = LITERAL_INT; // INT (assumed for now from const_int_val) node->literal.int_val = sym->const_int_val; node->type_info = type_new(TYPE_INT); // No need for resolution @@ -2740,15 +2740,15 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) if (elements[i]->type == NODE_EXPR_LITERAL) { char buf[256]; - if (elements[i]->literal.type_kind == 0) // int + if (elements[i]->literal.type_kind == LITERAL_INT) // int { sprintf(buf, "%lld", elements[i]->literal.int_val); } - else if (elements[i]->literal.type_kind == 1) // float + else if (elements[i]->literal.type_kind == LITERAL_FLOAT) // float { sprintf(buf, "%f", elements[i]->literal.float_val); } - else if (elements[i]->literal.type_kind == 2) // string + else if (elements[i]->literal.type_kind == LITERAL_STRING) // string { sprintf(buf, "\"%s\"", elements[i]->literal.string_val); } @@ -2969,7 +2969,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) if (node->type_info && node->type_info->kind == TYPE_ARRAY && node->type_info->array_size > 0) { - if (index->type == NODE_EXPR_LITERAL && index->literal.type_kind == 0) + if (index->type == NODE_EXPR_LITERAL && index->literal.type_kind == LITERAL_INT) { int idx = index->literal.int_val; if (idx < 0 || idx >= node->type_info->array_size) @@ -3498,7 +3498,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) call->type_info = type_new(TYPE_INT); ASTNode *fmt_node = ast_create(NODE_EXPR_LITERAL); - fmt_node->literal.type_kind = TOK_STRING; + fmt_node->literal.type_kind = LITERAL_STRING; fmt_node->literal.string_val = xstrdup(fmt); ASTNode *head = fmt_node, *tail = fmt_node; @@ -4441,7 +4441,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) if (lhs->type_info && lhs->type_info->kind == TYPE_ARRAY && lhs->type_info->array_size > 0) { - if (start->type == NODE_EXPR_LITERAL && start->literal.type_kind == 0) + if (start->type == NODE_EXPR_LITERAL && start->literal.type_kind == LITERAL_INT) { int idx = start->literal.int_val; if (idx < 0 || idx >= lhs->type_info->array_size) @@ -4564,7 +4564,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) if (find_func(ctx, trait_mangled)) { strcpy(mangled, trait_mangled); // Update mangled name - sig = find_func(ctx, mangled); + sig = find_func(ctx, trait_mangled); break; } } @@ -4819,7 +4819,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) if (strcmp(bin->binary.op, "/") == 0 || strcmp(bin->binary.op, "%") == 0) { - if (rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == 0 && + if (rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == LITERAL_INT && rhs->literal.int_val == 0) { warn_division_by_zero(op); @@ -4845,8 +4845,8 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) } } } - else if (lhs->type == NODE_EXPR_LITERAL && lhs->literal.type_kind == 0 && - rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == 0) + else if (lhs->type == NODE_EXPR_LITERAL && lhs->literal.type_kind == LITERAL_INT && + rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == LITERAL_INT) { // Check if literals make sense (e.g. 5 > 5) if (lhs->literal.int_val == rhs->literal.int_val) @@ -4865,7 +4865,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) if (lhs->type_info && type_is_unsigned(lhs->type_info)) { - if (rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == 0 && + if (rhs->type == NODE_EXPR_LITERAL && rhs->literal.type_kind == LITERAL_INT && rhs->literal.int_val == 0) { if (strcmp(bin->binary.op, ">=") == 0) diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c index 73ae249..325fa1c 100644 --- a/src/parser/parser_stmt.c +++ b/src/parser/parser_stmt.c @@ -917,8 +917,8 @@ ASTNode *parse_while(ParserContext *ctx, Lexer *l) check_assignment_condition(cond); // Zen: While(true) - if ((cond->type == NODE_EXPR_LITERAL && cond->literal.type_kind == TOK_INT && - strcmp(cond->literal.string_val, "1") == 0) || + if ((cond->type == NODE_EXPR_LITERAL && cond->literal.type_kind == LITERAL_INT && + cond->literal.int_val == 1) || (cond->type == NODE_EXPR_VAR && strcmp(cond->var_ref.name, "true") == 0)) { zen_trigger_at(TRIGGER_WHILE_TRUE, cond->token); @@ -1060,7 +1060,7 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l) // while(true) ASTNode *while_loop = ast_create(NODE_WHILE); ASTNode *true_lit = ast_create(NODE_EXPR_LITERAL); - true_lit->literal.type_kind = TOK_INT; // Treated as bool in conditions + true_lit->literal.type_kind = LITERAL_INT; // Treated as bool in conditions true_lit->literal.int_val = 1; true_lit->literal.string_val = xstrdup("1"); while_loop->while_stmt.condition = true_lit; @@ -1203,7 +1203,7 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l) { // Empty condition = true ASTNode *true_lit = ast_create(NODE_EXPR_LITERAL); - true_lit->literal.type_kind = 0; + true_lit->literal.type_kind = LITERAL_INT; true_lit->literal.int_val = 1; cond = true_lit; } diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index 05ea74a..96b0c17 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -1624,7 +1624,7 @@ ASTNode *copy_ast_replacing(ASTNode *n, const char *p, const char *c, const char new_node->field.type = replace_type_str(n->field.type, p, c, os, ns); break; case NODE_EXPR_LITERAL: - if (n->literal.type_kind == 2) + if (n->literal.type_kind == LITERAL_STRING) { new_node->literal.string_val = xstrdup(n->literal.string_val); } diff --git a/tests/features/test_tuples.zc b/tests/features/test_tuples.zc index f8ccb1f..bc8b8d8 100644 --- a/tests/features/test_tuples.zc +++ b/tests/features/test_tuples.zc @@ -21,6 +21,11 @@ fn main() { // Different types var mixed: (int, string) = (10, "Hello"); assert(mixed.0 == 10, "Mixed 0"); + assert(strcmp(mixed.1, "Hello") == 0, "Mixed 1 (String)"); + + // Regression for segfault (inferred tuple with string) + var p_str = (1, "World"); + assert(strcmp(p_str.1, "World") == 0, "Inferred tuple string"); // Tuple destructuring var (a, b) = get_pair(); -- cgit v1.2.3