summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-13 13:44:31 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-13 13:44:31 +0000
commit6b0a0e7d7c017f78e7cca4a423fac686c0282575 (patch)
tree42c80517b30fc1f7651f1aa69c36ae5a06c18707
parent8d7e628878aac07d0380463196f823502d1816ce (diff)
Fix for #29
-rw-r--r--src/ast/ast.h2
-rw-r--r--src/parser/parser.h6
-rw-r--r--src/parser/parser_expr.c4
-rw-r--r--src/parser/parser_stmt.c47
-rw-r--r--src/parser/parser_utils.c32
5 files changed, 77 insertions, 14 deletions
diff --git a/src/ast/ast.h b/src/ast/ast.h
index 8c5bff4..1e14369 100644
--- a/src/ast/ast.h
+++ b/src/ast/ast.h
@@ -416,6 +416,8 @@ struct ASTNode
struct
{
char *content;
+ char **used_symbols;
+ int used_symbol_count;
} raw_stmt;
struct
diff --git a/src/parser/parser.h b/src/parser/parser.h
index e3a5e6b..9cdd0d2 100644
--- a/src/parser/parser.h
+++ b/src/parser/parser.h
@@ -377,7 +377,7 @@ void init_builtins();
// Expression rewriting
char *rewrite_expr_methods(ParserContext *ctx, char *raw);
-char *process_fstring(ParserContext *ctx, const char *content);
+char *process_fstring(ParserContext *ctx, const char *content, char ***used_syms, int *count);
char *instantiate_function_template(ParserContext *ctx, const char *name,
const char *concrete_type);
FuncSig *find_func(ParserContext *ctx, const char *name);
@@ -409,8 +409,8 @@ ASTNode *parse_guard(ParserContext *ctx, Lexer *l);
ASTNode *parse_match(ParserContext *ctx, Lexer *l);
ASTNode *parse_return(ParserContext *ctx, Lexer *l);
-char *process_printf_sugar(ParserContext *ctx, const char *content, int newline,
- const char *target);
+char *process_printf_sugar(ParserContext *ctx, const char *content, int newline, const char *target,
+ char ***used_syms, int *count);
ASTNode *parse_assert(ParserContext *ctx, Lexer *l);
ASTNode *parse_defer(ParserContext *ctx, Lexer *l);
ASTNode *parse_asm(ParserContext *ctx, Lexer *l);
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c
index f7af80f..9861de6 100644
--- a/src/parser/parser_expr.c
+++ b/src/parser/parser_expr.c
@@ -2240,7 +2240,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
}
// Reuse printf sugar to generate the prompt print
- char *print_code = process_printf_sugar(ctx, inner, 0, "stdout");
+ char *print_code = process_printf_sugar(ctx, inner, 0, "stdout", NULL, NULL);
free(inner);
// Checks for (args...) suffix for SCAN mode
@@ -2405,7 +2405,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
newline = 0;
}
- char *code = process_printf_sugar(ctx, inner, newline, "stderr");
+ char *code = process_printf_sugar(ctx, inner, newline, "stderr", NULL, NULL);
free(inner);
ASTNode *n = ast_create(NODE_RAW_STMT);
diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c
index 4478d22..484d742 100644
--- a/src/parser/parser_stmt.c
+++ b/src/parser/parser_stmt.c
@@ -1673,7 +1673,8 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l)
return n;
}
-char *process_printf_sugar(ParserContext *ctx, const char *content, int newline, const char *target)
+char *process_printf_sugar(ParserContext *ctx, const char *content, int newline, const char *target,
+ char ***used_syms, int *count)
{
char *gen = xmalloc(8192);
strcpy(gen, "({ ");
@@ -1765,12 +1766,34 @@ char *process_printf_sugar(ParserContext *ctx, const char *content, int newline,
clean_expr++; // Skip leading spaces
}
- // Mark the variable as used (fixes "Unused variable" warnings for f-string
- // interpolation)
- Symbol *sym = find_symbol_entry(ctx, clean_expr);
- if (sym)
+ // Analyze usage
{
- sym->is_used = 1;
+ Lexer lex;
+ lexer_init(&lex, clean_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;
+ }
+
+ if (used_syms && count)
+ {
+ *used_syms = xrealloc(*used_syms, sizeof(char *) * (*count + 1));
+ (*used_syms)[*count] = name;
+ (*count)++;
+ }
+ else
+ {
+ free(name);
+ }
+ }
+ }
}
char *type = find_symbol_type(ctx, clean_expr);
@@ -2097,7 +2120,9 @@ ASTNode *parse_statement(ParserContext *ctx, Lexer *l)
// ; means println (end of line), .. means print (continuation)
int is_ln = (next_type == TOK_SEMICOLON);
- char *code = process_printf_sugar(ctx, inner, is_ln, "stdout");
+ char **used_syms = NULL;
+ int used_count = 0;
+ char *code = process_printf_sugar(ctx, inner, is_ln, "stdout", &used_syms, &used_count);
if (next_type == TOK_SEMICOLON)
{
@@ -2114,6 +2139,8 @@ ASTNode *parse_statement(ParserContext *ctx, Lexer *l)
ASTNode *n = ast_create(NODE_RAW_STMT);
n->raw_stmt.content = code;
+ n->raw_stmt.used_symbols = used_syms;
+ n->raw_stmt.used_symbol_count = used_count;
free(inner);
return n;
}
@@ -2506,7 +2533,9 @@ ASTNode *parse_statement(ParserContext *ctx, Lexer *l)
inner[t.len - 2] = 0;
}
- char *code = process_printf_sugar(ctx, inner, is_ln, target);
+ char **used_syms = NULL;
+ int used_count = 0;
+ char *code = process_printf_sugar(ctx, inner, is_ln, target, &used_syms, &used_count);
free(inner);
if (lexer_peek(l).type == TOK_SEMICOLON)
@@ -2516,6 +2545,8 @@ ASTNode *parse_statement(ParserContext *ctx, Lexer *l)
ASTNode *n = ast_create(NODE_RAW_STMT);
n->raw_stmt.content = code;
+ n->raw_stmt.used_symbols = used_syms;
+ n->raw_stmt.used_symbol_count = used_count;
return n;
}
}
diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c
index 7733ef7..ba506a0 100644
--- a/src/parser/parser_utils.c
+++ b/src/parser/parser_utils.c
@@ -1554,7 +1554,7 @@ char *instantiate_function_template(ParserContext *ctx, const char *name, const
return mangled;
}
-char *process_fstring(ParserContext *ctx, const char *content)
+char *process_fstring(ParserContext *ctx, const char *content, char ***used_syms, int *count)
{
(void)ctx; // suppress unused parameter warning
char *gen = xmalloc(4096);
@@ -1621,6 +1621,36 @@ char *process_fstring(ParserContext *ctx, const char *content)
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;
+ }
+
+ if (used_syms && count)
+ {
+ *used_syms = xrealloc(*used_syms, sizeof(char *) * (*count + 1));
+ (*used_syms)[*count] = name;
+ (*count)++;
+ }
+ else
+ {
+ free(name);
+ }
+ }
+ }
+ }
+
if (fmt)
{
strcat(gen, "sprintf(_t, \"%");