vxx2 / vlib / v3 / transform / match.v
75 lines · 71 sloc · 2.52 KB · ebf2f0131f8dd63a65cbb7b25ceba589e07bd33c
Raw
1module transform
2
3import v3.flat
4
5// match_has_sum_type_subject checks if a match_stmt's subject expression
6// resolves to a sum type. This determines whether the match needs to be
7// lowered with is_expr conditions (sum type dispatch) or plain equality
8// checks (value matching).
9fn (mut t Transformer) match_has_sum_type_subject(node flat.Node) bool {
10 if node.children_count == 0 {
11 return false
12 }
13 subject_id := t.a.child(&node, 0)
14 subject_type := t.resolve_expr_type(subject_id)
15 if subject_type.len == 0 {
16 return false
17 }
18 return subject_type in t.sum_types
19}
20
21// resolve_match_subject_type determines the type of a match subject expression.
22// Uses resolve_expr_type on child 0 (the match expression).
23fn (mut t Transformer) resolve_match_subject_type(node flat.Node) string {
24 if node.children_count == 0 {
25 return ''
26 }
27 subject_id := t.a.child(&node, 0)
28 return t.resolve_expr_type(subject_id)
29}
30
31// transform_match_branch_body transforms a match branch body with smartcast
32// awareness. When the branch matches a sum type variant, the subject variable
33// should be narrowed to that variant's type within the branch body.
34//
35// For now, this performs basic body transformation without smartcast injection.
36// When smartcast support is fully wired up, this will:
37// 1. Push a smartcast context for the subject variable narrowed to the variant
38// 2. Transform the body statements under that context
39// 3. Pop the smartcast context
40// 4. Rebuild the block with the transformed statements
41fn (mut t Transformer) transform_match_branch_body(branch_id flat.NodeId, subject_name string, variant_name string) flat.NodeId {
42 if int(branch_id) < 0 {
43 return branch_id
44 }
45 branch := t.a.nodes[int(branch_id)]
46 if branch.children_count == 0 {
47 return branch_id
48 }
49 // Collect the body statement ids from the branch
50 mut body_ids := []flat.NodeId{}
51 // Determine where the body starts (after the condition values)
52 n_conds := t.count_conds(branch)
53 for i in n_conds .. branch.children_count {
54 body_ids << t.a.child(&branch, i)
55 }
56 if body_ids.len == 0 {
57 return branch_id
58 }
59 // Push smartcast if we have a sum type variant match
60 mut has_sc := subject_name.len > 0 && variant_name.len > 0
61 if has_sc {
62 sum_type_name := t.find_sum_type_for_variant(variant_name)
63 if sum_type_name.len > 0 {
64 t.push_smartcast(subject_name, variant_name, sum_type_name)
65 } else {
66 has_sc = false
67 }
68 }
69 // Transform the body statements under smartcast context
70 new_body := t.transform_stmts(body_ids)
71 if has_sc {
72 t.pop_smartcast()
73 }
74 return t.make_block(new_body)
75}
76