summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.h1
-rw-r--r--src/codegen/codegen.c84
-rw-r--r--src/parser/parser_core.c4
-rw-r--r--src/parser/parser_stmt.c20
4 files changed, 92 insertions, 17 deletions
diff --git a/src/ast/ast.h b/src/ast/ast.h
index 2233b09..508a247 100644
--- a/src/ast/ast.h
+++ b/src/ast/ast.h
@@ -303,6 +303,7 @@ struct ASTNode
char *pattern;
char *binding_name;
int is_destructuring;
+ int is_ref; // New: Supports 'ref' binding (Some(ref x))
ASTNode *guard;
ASTNode *body;
int is_default;
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c
index b25c79c..32fbdcf 100644
--- a/src/codegen/codegen.c
+++ b/src/codegen/codegen.c
@@ -246,38 +246,89 @@ static void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out,
{
if (strstr(g_config.cc, "tcc"))
{
- fprintf(out, "__typeof__(_m_%d.val) %s = _m_%d.val; ", id,
- c->match_case.binding_name, id);
+ if (c->match_case.is_ref)
+ {
+ fprintf(out, "__typeof__(&_m_%d.val) %s = &_m_%d.val; ", id,
+ c->match_case.binding_name, id);
+ }
+ else
+ {
+ fprintf(out, "__typeof__(_m_%d.val) %s = _m_%d.val; ", id,
+ c->match_case.binding_name, id);
+ }
}
else
{
- fprintf(out, "ZC_AUTO %s = _m_%d.val; ", c->match_case.binding_name, id);
+ if (c->match_case.is_ref)
+ {
+ fprintf(out, "ZC_AUTO %s = &_m_%d.val; ", c->match_case.binding_name, id);
+ }
+ else
+ {
+ fprintf(out, "ZC_AUTO %s = _m_%d.val; ", c->match_case.binding_name, id);
+ }
}
}
- if (is_result)
+ else if (is_result) // FIX: Changed 'if' to 'else if' to match original logic structure
+ // if needed, but original code had implicit fallthrough checks? No,
+ // checks match pattern.
{
if (strcmp(c->match_case.pattern, "Ok") == 0)
{
if (strstr(g_config.cc, "tcc"))
{
- fprintf(out, "__typeof__(_m_%d.val) %s = _m_%d.val; ", id,
- c->match_case.binding_name, id);
+ if (c->match_case.is_ref)
+ {
+ fprintf(out, "__typeof__(&_m_%d.val) %s = &_m_%d.val; ", id,
+ c->match_case.binding_name, id);
+ }
+ else
+ {
+ fprintf(out, "__typeof__(_m_%d.val) %s = _m_%d.val; ", id,
+ c->match_case.binding_name, id);
+ }
}
else
{
- fprintf(out, "ZC_AUTO %s = _m_%d.val; ", c->match_case.binding_name, id);
+ if (c->match_case.is_ref)
+ {
+ fprintf(out, "ZC_AUTO %s = &_m_%d.val; ", c->match_case.binding_name,
+ id);
+ }
+ else
+ {
+ fprintf(out, "ZC_AUTO %s = _m_%d.val; ", c->match_case.binding_name,
+ id);
+ }
}
}
else
{
if (strstr(g_config.cc, "tcc"))
{
- fprintf(out, "__typeof__(_m_%d.err) %s = _m_%d.err; ", id,
- c->match_case.binding_name, id);
+ if (c->match_case.is_ref)
+ {
+ fprintf(out, "__typeof__(&_m_%d.err) %s = &_m_%d.err; ", id,
+ c->match_case.binding_name, id);
+ }
+ else
+ {
+ fprintf(out, "__typeof__(_m_%d.err) %s = _m_%d.err; ", id,
+ c->match_case.binding_name, id);
+ }
}
else
{
- fprintf(out, "ZC_AUTO %s = _m_%d.err; ", c->match_case.binding_name, id);
+ if (c->match_case.is_ref)
+ {
+ fprintf(out, "ZC_AUTO %s = &_m_%d.err; ", c->match_case.binding_name,
+ id);
+ }
+ else
+ {
+ fprintf(out, "ZC_AUTO %s = _m_%d.err; ", c->match_case.binding_name,
+ id);
+ }
}
}
}
@@ -292,7 +343,18 @@ static void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out,
{
f = c->match_case.pattern;
}
- fprintf(out, "ZC_AUTO %s = _m_%d.data.%s; ", c->match_case.binding_name, id, f);
+ // Generic struct destructuring (e.g. MyStruct_Variant)
+ // Assuming data union or accessible field.
+ // Original: _m_%d.data.%s
+ if (c->match_case.is_ref)
+ {
+ fprintf(out, "ZC_AUTO %s = &_m_%d.data.%s; ", c->match_case.binding_name, id,
+ f);
+ }
+ else
+ {
+ fprintf(out, "ZC_AUTO %s = _m_%d.data.%s; ", c->match_case.binding_name, id, f);
+ }
}
}
diff --git a/src/parser/parser_core.c b/src/parser/parser_core.c
index acab268..3c2805c 100644
--- a/src/parser/parser_core.c
+++ b/src/parser/parser_core.c
@@ -591,8 +591,8 @@ static ASTNode *generate_derive_impls(ParserContext *ctx, ASTNode *strct, char *
else if (fdef && fdef->type == NODE_STRUCT)
{
// Struct field: use _eq function, pass addresses
- // self.field is L-value, other.field is L-value (auto-deref from pointer)
- // We need addresses of them: &self.field, &other.field
+ // self.field is L-value, other.field is L-value (auto-deref from
+ // pointer) We need addresses of them: &self.field, &other.field
sprintf(cmp, "%s__eq(&self.%s, &other.%s)", ft, fn, fn);
}
else
diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c
index fc34a21..7433525 100644
--- a/src/parser/parser_stmt.c
+++ b/src/parser/parser_stmt.c
@@ -217,11 +217,11 @@ ASTNode *parse_match(ParserContext *ctx, Lexer *l)
break;
}
- // --- 1. Parse Patterns (with OR and range support) ---
+ // Parse Patterns (with OR and range support)
// Patterns can be:
// - Single value: 1
- // - OR patterns: 1 || 2 or 1 or 2
- // - Range patterns: 1..5 or 1..=5
+ // - OR patterns: 1 || 2 or 1 or 2 or 1, 2
+ // - Range patterns: 1..5 or 1..=5 or 1..<5
char patterns_buf[1024];
patterns_buf[0] = 0;
int pattern_count = 0;
@@ -292,11 +292,22 @@ ASTNode *parse_match(ParserContext *ctx, Lexer *l)
char *binding = NULL;
int is_destructure = 0;
- // --- 2. Handle Destructuring: Ok(v) ---
+ int is_ref = 0;
+
+ // Handle Destructuring: Ok(v)
// (Only allowed if we matched a single pattern, e.g. "Result::Ok(val)")
if (!is_default && pattern_count == 1 && lexer_peek(l).type == TOK_LPAREN)
{
lexer_next(l); // eat (
+
+ // Check for 'ref' keyword
+ if (lexer_peek(l).type == TOK_IDENT && lexer_peek(l).len == 3 &&
+ strncmp(lexer_peek(l).start, "ref", 3) == 0)
+ {
+ lexer_next(l); // eat 'ref'
+ is_ref = 1;
+ }
+
Token b = lexer_next(l);
if (b.type != TOK_IDENT)
{
@@ -348,6 +359,7 @@ ASTNode *parse_match(ParserContext *ctx, Lexer *l)
c->match_case.pattern = pattern;
c->match_case.binding_name = binding;
c->match_case.is_destructuring = is_destructure;
+ c->match_case.is_ref = is_ref; // Store is_ref flag
c->match_case.guard = guard;
c->match_case.body = body;
c->match_case.is_default = is_default;