summaryrefslogtreecommitdiff
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/parser.h9
-rw-r--r--src/parser/parser_core.c10
-rw-r--r--src/parser/parser_decl.c21
-rw-r--r--src/parser/parser_expr.c60
-rw-r--r--src/parser/parser_stmt.c7
5 files changed, 75 insertions, 32 deletions
diff --git a/src/parser/parser.h b/src/parser/parser.h
index 6ac55bf..8857641 100644
--- a/src/parser/parser.h
+++ b/src/parser/parser.h
@@ -41,6 +41,7 @@ typedef struct Symbol
int is_autofree;
Token decl_token;
int is_const_value;
+ int is_def;
int const_int_val;
int is_moved;
struct Symbol *next;
@@ -56,14 +57,14 @@ typedef struct Scope
typedef struct FuncSig
{
char *name;
- Token decl_token; // For LSP
+ Token decl_token;
int total_args;
char **defaults;
Type **arg_types;
Type *ret_type;
int is_varargs;
- int is_async; // Async function flag
- int must_use; // Attribute: warn if return value discarded
+ int is_async;
+ int must_use;
struct FuncSig *next;
} FuncSig;
@@ -438,7 +439,7 @@ ASTNode *parse_defer(ParserContext *ctx, Lexer *l);
ASTNode *parse_asm(ParserContext *ctx, Lexer *l);
ASTNode *parse_plugin(ParserContext *ctx, Lexer *l);
ASTNode *parse_var_decl(ParserContext *ctx, Lexer *l);
-ASTNode *parse_const(ParserContext *ctx, Lexer *l);
+ASTNode *parse_def(ParserContext *ctx, Lexer *l);
ASTNode *parse_type_alias(ParserContext *ctx, Lexer *l);
ASTNode *parse_function(ParserContext *ctx, Lexer *l, int is_async);
diff --git a/src/parser/parser_core.c b/src/parser/parser_core.c
index 464c905..8410203 100644
--- a/src/parser/parser_core.c
+++ b/src/parser/parser_core.c
@@ -267,6 +267,10 @@ ASTNode *parse_program_nodes(ParserContext *ctx, Lexer *l)
s = ast_create(NODE_RAW_STMT);
s->raw_stmt.content = content;
}
+ else if (t.type == TOK_DEF)
+ {
+ s = parse_def(ctx, l);
+ }
else if (t.type == TOK_IDENT)
{
// Inline function: inline fn name(...) { }
@@ -337,9 +341,13 @@ ASTNode *parse_program_nodes(ParserContext *ctx, Lexer *l)
{
s = parse_var_decl(ctx, l);
}
+ else if (t.len == 3 && strncmp(t.start, "def", 3) == 0)
+ {
+ s = parse_def(ctx, l);
+ }
else if (t.len == 5 && strncmp(t.start, "const", 5) == 0)
{
- s = parse_const(ctx, l);
+ zpanic_at(t, "'const' for declarations is deprecated. Use 'def' for constants or 'var x: const T' for read-only variables.");
}
else if (t.len == 6 && strncmp(t.start, "extern", 6) == 0)
{
diff --git a/src/parser/parser_decl.c b/src/parser/parser_decl.c
index 5cac0b4..87b15ad 100644
--- a/src/parser/parser_decl.c
+++ b/src/parser/parser_decl.c
@@ -701,9 +701,9 @@ ASTNode *parse_var_decl(ParserContext *ctx, Lexer *l)
return n;
}
-ASTNode *parse_const(ParserContext *ctx, Lexer *l)
+ASTNode *parse_def(ParserContext *ctx, Lexer *l)
{
- lexer_next(l); // eat const
+ lexer_next(l); // eat def
Token n = lexer_next(l);
char *type_str = NULL;
@@ -723,7 +723,14 @@ ASTNode *parse_const(ParserContext *ctx, Lexer *l)
type_obj = type_new(TYPE_UNKNOWN); // Ensure we have an object
}
type_obj->is_const = 1;
+
+ // Use is_def flag for manifest constants
add_symbol(ctx, ns, type_str ? type_str : "unknown", type_obj);
+ Symbol *sym_entry = find_symbol_entry(ctx, ns);
+ if (sym_entry) {
+ sym_entry->is_def = 1;
+ // is_const_value set only if literal
+ }
ASTNode *i = 0;
if (lexer_peek(l).type == TOK_OP && is_token(lexer_peek(l), "="))
@@ -741,6 +748,7 @@ ASTNode *parse_const(ParserContext *ctx, Lexer *l)
{
s->is_const_value = 1;
s->const_int_val = val;
+ s->is_def = 1; // Double ensure
if (!s->type_name || strcmp(s->type_name, "unknown") == 0)
{
@@ -754,6 +762,7 @@ ASTNode *parse_const(ParserContext *ctx, Lexer *l)
free(s->type_info);
}
s->type_info = type_new(TYPE_INT);
+ s->type_info->is_const = 1;
}
}
}
@@ -771,7 +780,7 @@ ASTNode *parse_const(ParserContext *ctx, Lexer *l)
}
else
{
- lexer_next(l);
+ zpanic_at(n, "'def' constants must be initialized");
}
if (lexer_peek(l).type == TOK_SEMICOLON)
@@ -783,6 +792,7 @@ ASTNode *parse_const(ParserContext *ctx, Lexer *l)
o->var_decl.name = ns;
o->var_decl.type_str = type_str;
o->var_decl.init_expr = i;
+ // Store extra metadata if needed, but NODE_CONST usually suffices
if (!ctx->current_scope || !ctx->current_scope->parent)
{
@@ -805,10 +815,7 @@ ASTNode *parse_type_alias(ParserContext *ctx, Lexer *l)
char *o = parse_type(ctx, l);
- lexer_next(l); // consume ';' (parse_type doesn't consume it? parse_type calls parse_type_formal
- // which doesn't consume ;?)
- // Note: parse_type_stmt usually expects ; but parse_type just parses type expression.
- // Check previous implementation: it had lexer_next(l) at end. This assumes ;.
+ lexer_next(l);
ASTNode *node = ast_create(NODE_TYPE_ALIAS);
node->type_alias.alias = xmalloc(n.len + 1);
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c
index 9251f98..9d21e77 100644
--- a/src/parser/parser_expr.c
+++ b/src/parser/parser_expr.c
@@ -2327,35 +2327,48 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
}
else
{
- node = ast_create(NODE_EXPR_VAR);
- node->token = t; // Set source token
- node->var_ref.name = acc;
- node->type_info = find_symbol_type_info(ctx, acc);
-
Symbol *sym = find_symbol_entry(ctx, acc);
- if (sym)
- {
- sym->is_used = 1;
- node->definition_token = sym->decl_token;
- }
-
- char *type_str = find_symbol_type(ctx, acc);
-
- if (type_str)
+ if (sym && sym->is_def && sym->is_const_value)
{
- node->resolved_type = type_str;
- node->var_ref.suggestion = NULL;
+ // 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.int_val = sym->const_int_val;
+ node->type_info = type_new(TYPE_INT);
+ // No need for resolution
}
else
{
- node->resolved_type = xstrdup("unknown");
- if (should_suppress_undef_warning(ctx, acc))
+ node = ast_create(NODE_EXPR_VAR);
+ node->token = t; // Set source token
+ node->var_ref.name = acc;
+ node->type_info = find_symbol_type_info(ctx, acc);
+
+ if (sym)
+ {
+ sym->is_used = 1;
+ node->definition_token = sym->decl_token;
+ }
+
+ char *type_str = find_symbol_type(ctx, acc);
+
+ if (type_str)
{
+ node->resolved_type = type_str;
node->var_ref.suggestion = NULL;
}
else
{
- node->var_ref.suggestion = find_similar_symbol(ctx, acc);
+ node->resolved_type = xstrdup("unknown");
+ if (should_suppress_undef_warning(ctx, acc))
+ {
+ node->var_ref.suggestion = NULL;
+ }
+ else
+ {
+ node->var_ref.suggestion = find_similar_symbol(ctx, acc);
+ }
}
}
}
@@ -3405,6 +3418,15 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec)
lexer_next(l); // consume op
ASTNode *operand = parse_expr_prec(ctx, l, PREC_UNARY);
+ if (is_token(t, "&") && operand->type == NODE_EXPR_VAR)
+ {
+ Symbol *s = find_symbol_entry(ctx, operand->var_ref.name);
+ if (s && s->is_def)
+ {
+ zpanic_at(t, "Cannot take address of manifest constant '%s' (use 'var' if you need an address)", operand->var_ref.name);
+ }
+ }
+
char *method = NULL;
if (is_token(t, "-"))
{
diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c
index dfc99db..bc1849d 100644
--- a/src/parser/parser_stmt.c
+++ b/src/parser/parser_stmt.c
@@ -1869,6 +1869,10 @@ ASTNode *parse_statement(ParserContext *ctx, Lexer *l)
{
return parse_asm(ctx, l);
}
+ if (tk.type == TOK_DEF)
+ {
+ return parse_def(ctx, l);
+ }
// Identifiers (Keywords or Expressions)
if (tk.type == TOK_IDENT)
@@ -1956,9 +1960,10 @@ ASTNode *parse_statement(ParserContext *ctx, Lexer *l)
}
zpanic_at(next, "Expected 'var' after 'static'");
}
+
if (strncmp(tk.start, "const", 5) == 0 && tk.len == 5)
{
- return parse_const(ctx, l);
+ zpanic_at(tk, "'const' for declarations is deprecated. Use 'def' for constants or 'var x: const T' for read-only variables.");
}
if (strncmp(tk.start, "return", 6) == 0 && tk.len == 6)
{