summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-24 12:14:48 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-24 12:14:48 +0000
commit812fe9cbe124bf39a06f58a538c8c01f7402fb09 (patch)
tree8ea1f8258714e7dd8916eb221006e45082a129bb
parent22035400ed7b7fcda088a1a5b1ca6505b23bf63f (diff)
Fix for #110
-rw-r--r--src/ast/ast.h11
-rw-r--r--src/codegen/codegen.c11
-rw-r--r--src/codegen/codegen_stmt.c5
-rw-r--r--src/codegen/codegen_utils.c10
-rw-r--r--src/parser/parser_decl.c8
-rw-r--r--src/parser/parser_expr.c38
-rw-r--r--src/parser/parser_stmt.c8
-rw-r--r--src/parser/parser_utils.c2
-rw-r--r--tests/features/test_tuples.zc5
9 files changed, 57 insertions, 41 deletions
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
@@ -12,21 +12,22 @@
#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();