Skip to content

Commit 8b89ebd

Browse files
committed
no mistakes
1 parent 0a1beb8 commit 8b89ebd

File tree

1 file changed

+42
-28
lines changed

1 file changed

+42
-28
lines changed

src/to_c.rs

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,7 +1452,11 @@ fn stmt_to_c(
14521452
w!(p, "{} {} = ", c_ty(rhs_ty), rhs_temp);
14531453
expr_to_c(&rhs.node, &rhs.loc, locals, cg, p);
14541454
wln!(p, "; // {}", loc_display(&rhs.loc));
1455-
wln!(p, "{};", pat_to_cond(&lhs.node, &rhs_temp, locals, cg));
1455+
wln!(
1456+
p,
1457+
"{};",
1458+
pat_to_cond(&lhs.node, &rhs_temp, None, locals, cg)
1459+
);
14561460
if let Some(result_var) = result_var {
14571461
wln!(
14581462
p,
@@ -1795,7 +1799,7 @@ fn expr_to_c(expr: &Expr, loc: &Loc, locals: &[LocalInfo], cg: &mut Cg, p: &mut
17951799
w!(p, " else ");
17961800
}
17971801
// Generate pattern match condition
1798-
let cond = pat_to_cond(&alt.pat.node, &scrut_temp, locals, cg);
1802+
let cond = pat_to_cond(&alt.pat.node, &scrut_temp, None, locals, cg);
17991803
w!(p, "if ({}", cond);
18001804

18011805
// Add guard if present
@@ -1974,7 +1978,7 @@ fn expr_to_c(expr: &Expr, loc: &Loc, locals: &[LocalInfo], cg: &mut Cg, p: &mut
19741978
w!(
19751979
p,
19761980
"if ({}) {{",
1977-
pat_to_cond(&pat.node, &expr_temp, locals, cg)
1981+
pat_to_cond(&pat.node, &expr_temp, None, locals, cg)
19781982
);
19791983
p.indent();
19801984
p.nl();
@@ -2189,13 +2193,24 @@ fn gen_variant_conversion(
21892193
}
21902194

21912195
/// Generate a C condition expression for pattern matching.
2192-
fn pat_to_cond(pat: &Pat, scrutinee: &str, locals: &[LocalInfo], cg: &mut Cg) -> String {
2196+
///
2197+
/// - `scrutinee` is the expression being matched against.
2198+
///
2199+
/// - `tag_expr` is an optional override for how to get the tag. When `Some`, use that expression
2200+
/// directly (e.g., for variant patterns where we check the variant's `_tag` field). When `None`,
2201+
/// derive the tag from the scrutinee using `get_tag(scrutinee)`.
2202+
fn pat_to_cond(
2203+
pat: &Pat,
2204+
scrutinee: &str,
2205+
tag_expr: Option<&str>,
2206+
locals: &[LocalInfo],
2207+
cg: &mut Cg,
2208+
) -> String {
21932209
match pat {
21942210
Pat::Ignore => "1".to_string(),
21952211

21962212
Pat::Var(VarPat { idx, original_ty }) => {
21972213
let refined_ty = &locals[idx.as_usize()].ty;
2198-
21992214
if needs_variant_conversion(original_ty, refined_ty) {
22002215
let conversion = gen_variant_conversion(scrutinee, original_ty, refined_ty, cg);
22012216
format!("({{ _{} = {}; 1; }})", idx.as_usize(), conversion)
@@ -2207,12 +2222,15 @@ fn pat_to_cond(pat: &Pat, scrutinee: &str, locals: &[LocalInfo], cg: &mut Cg) ->
22072222
Pat::Con(ConPat { con, fields }) => {
22082223
let struct_name = heap_obj_struct_name(cg.pgm, *con);
22092224
let tag_name = heap_obj_tag_name(cg.pgm, *con);
2210-
// let get_tag_expr = gen_get_tag(&cg.pgm, scrutinee, ty); TODO
2211-
let mut cond = format!("(get_tag({}) == {})", scrutinee, tag_name);
2225+
let tag_check = match tag_expr {
2226+
Some(expr) => format!("({expr} == {tag_name})"),
2227+
None => format!("(get_tag({scrutinee}) == {tag_name})"),
2228+
};
2229+
let mut cond = tag_check;
22122230
for (i, field_pat) in fields.iter().enumerate() {
22132231
let field_expr = format!("(({struct_name}*){scrutinee})->_{i}");
2214-
let field_cond = pat_to_cond(&field_pat.node, &field_expr, locals, cg);
2215-
cond = format!("({} && {})", cond, field_cond);
2232+
let field_cond = pat_to_cond(&field_pat.node, &field_expr, None, locals, cg);
2233+
cond = format!("({cond} && {field_cond})");
22162234
}
22172235
cond
22182236
}
@@ -2221,36 +2239,34 @@ fn pat_to_cond(pat: &Pat, scrutinee: &str, locals: &[LocalInfo], cg: &mut Cg) ->
22212239
let mut escaped = String::new();
22222240
for byte in s.bytes() {
22232241
if byte == b'"' || byte == b'\\' || !(32..=126).contains(&byte) {
2224-
// Same as `Expr::Str`, use octal escape here instead of hex.
22252242
escaped.push_str(&format!("\\{:03o}", byte));
22262243
} else {
22272244
escaped.push(byte as char);
22282245
}
22292246
}
2230-
// Note: the type cast below is to handle strings in variants. Variants are currently
2231-
// `Variant*` so they need to be cast.
2247+
let tag_check = match tag_expr {
2248+
Some(expr) => format!("({expr} == {})", cg.pgm.str_con_idx.0),
2249+
None => format!("(get_tag({scrutinee}) == {})", cg.pgm.str_con_idx.0),
2250+
};
22322251
format!(
2233-
"(get_tag({}) == {} && str_eq((Str*){}, \"{}\", {}))",
2234-
scrutinee,
2235-
cg.pgm.str_con_idx.0,
2236-
scrutinee,
2237-
escaped,
2252+
"({tag_check} && str_eq((Str*){scrutinee}, \"{escaped}\", {}))",
22382253
s.len()
22392254
)
22402255
}
22412256

22422257
Pat::Char(c) => {
22432258
let tag_name = heap_obj_tag_name(cg.pgm, cg.pgm.char_con_idx);
2244-
format!(
2245-
"(get_tag({}) == {} && ((Char*){})->_0 == {})",
2246-
scrutinee, tag_name, scrutinee, *c as u32
2247-
)
2259+
let tag_check = match tag_expr {
2260+
Some(expr) => format!("({expr} == {tag_name})"),
2261+
None => format!("(get_tag({scrutinee}) == {tag_name})"),
2262+
};
2263+
format!("({tag_check} && ((Char*){scrutinee})->_0 == {})", *c as u32)
22482264
}
22492265

22502266
Pat::Or(p1, p2) => {
2251-
let c1 = pat_to_cond(&p1.node, scrutinee, locals, cg);
2252-
let c2 = pat_to_cond(&p2.node, scrutinee, locals, cg);
2253-
format!("({} || {})", c1, c2)
2267+
let c1 = pat_to_cond(&p1.node, scrutinee, tag_expr, locals, cg);
2268+
let c2 = pat_to_cond(&p2.node, scrutinee, tag_expr, locals, cg);
2269+
format!("({c1} || {c2})")
22542270
}
22552271

22562272
Pat::Variant {
@@ -2260,10 +2276,8 @@ fn pat_to_cond(pat: &Pat, scrutinee: &str, locals: &[LocalInfo], cg: &mut Cg) ->
22602276
} => {
22612277
let alt_idx = find_variant_alt_index(pat_ty, variant_ty);
22622278
let inner_expr = format!("({scrutinee})._alt._{alt_idx}");
2263-
let expected_tag = gen_get_tag(cg.pgm, &inner_expr, pat_ty);
2264-
let tag_check = format!("(({scrutinee})._tag == {expected_tag})");
2265-
let inner_cond = pat_to_cond(&pat.node, &inner_expr, locals, cg);
2266-
format!("({tag_check} && {inner_cond})")
2279+
let variant_tag_expr = format!("({scrutinee})._tag");
2280+
pat_to_cond(&pat.node, &inner_expr, Some(&variant_tag_expr), locals, cg)
22672281
}
22682282
}
22692283
}

0 commit comments

Comments
 (0)