Skip to content

Commit 9bbab68

Browse files
committed
WIP: flow_control: Support match expressions.
commit-id:df88d67e
1 parent 3c9e307 commit 9bbab68

File tree

4 files changed

+150
-7
lines changed

4 files changed

+150
-7
lines changed

crates/cairo-lang-lowering/src/lower/flow_control/create_graph.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use cairo_lang_semantic::{self as semantic, Condition};
1+
use cairo_lang_semantic::{self as semantic, Condition, PatternId};
22
use cairo_lang_syntax::node::TypedStablePtr;
33
use itertools::Itertools;
44
use patterns::create_node_for_patterns;
55

66
use super::graph::{
7-
ArmExpr, BooleanIf, EvaluateExpr, FlowControlGraph, FlowControlGraphBuilder, FlowControlNode,
7+
ArmExpr, BooleanIf, EvaluateExpr, FlowControlGraph, FlowControlGraphBuilder, FlowControlNode, NodeId,
88
};
99
use crate::lower::context::LoweringContext;
1010

@@ -86,3 +86,54 @@ pub fn create_graph_expr_if<'db>(
8686

8787
graph.finalize(current_node)
8888
}
89+
90+
/// Creates a graph node for [semantic::ExprMatch].
91+
#[allow(dead_code)]
92+
pub fn create_graph_expr_match<'db>(
93+
ctx: &LoweringContext<'db, '_>,
94+
expr: &semantic::ExprMatch<'db>,
95+
) -> FlowControlGraph<'db> {
96+
let mut graph = FlowControlGraphBuilder::default();
97+
98+
let matched_expr = &ctx.function_body.arenas.exprs[expr.matched_expr];
99+
let matched_expr_location = ctx.get_location(matched_expr.stable_ptr().untyped());
100+
let matched_var = graph.new_var(matched_expr.ty(), matched_expr_location);
101+
102+
// Create a list of patterns and nodes.
103+
let pattern_and_nodes: Vec<(PatternId, NodeId)> = expr
104+
.arms
105+
.iter()
106+
.flat_map(|match_arm| {
107+
// For each arm, create a node for the arm expression.
108+
let arm_node =
109+
graph.add_node(FlowControlNode::ArmExpr(ArmExpr { expr: match_arm.expression }));
110+
// Then map the patterns to that node.
111+
match_arm.patterns.iter().map(move |pattern| (*pattern, arm_node))
112+
})
113+
.collect();
114+
115+
// TODO(lior): add diagnostics if there is an unreachable arm.
116+
let match_node_id = create_node_for_patterns(
117+
ctx,
118+
&mut graph,
119+
matched_var,
120+
&pattern_and_nodes
121+
.iter()
122+
.map(|(pattern, _)| &ctx.function_body.arenas.patterns[*pattern])
123+
.collect_vec(),
124+
&|_graph, pattern_indices| {
125+
// TODO(lior): add diagnostics if pattern_indices is empty (instead of `unwrap`).
126+
let index = pattern_indices.first().unwrap();
127+
pattern_and_nodes[index].1
128+
},
129+
matched_expr_location,
130+
);
131+
132+
let root = graph.add_node(FlowControlNode::EvaluateExpr(EvaluateExpr {
133+
expr: expr.matched_expr,
134+
var_id: matched_var,
135+
next: match_node_id,
136+
}));
137+
138+
graph.finalize(root)
139+
}

crates/cairo-lang-lowering/src/lower/flow_control/graph_test.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use cairo_lang_utils::extract_matches;
1010
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
1111
use itertools::Itertools;
1212

13-
use super::create_graph::create_graph_expr_if;
13+
use super::create_graph::{create_graph_expr_if, create_graph_expr_match};
1414
use super::graph::FlowControlGraph;
1515
use super::lower_graph::lower_graph;
1616
use crate::Lowered;
@@ -27,6 +27,7 @@ cairo_lang_test_utils::test_file_test!(
2727
"src/lower/flow_control/test_data",
2828
{
2929
if_: "if",
30+
match_: "match",
3031
},
3132
test_create_graph
3233
);
@@ -67,6 +68,7 @@ fn test_create_graph(
6768

6869
let graph = match &expr {
6970
semantic::Expr::If(expr) => create_graph_expr_if(&ctx, expr),
71+
semantic::Expr::Match(expr) => create_graph_expr_match(&ctx, expr),
7072
_ => {
7173
panic!("Unsupported expression: {:?}", expr.debug(&expr_formatter));
7274
}

crates/cairo-lang-lowering/src/lower/flow_control/test_data/if

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ End:
180180
//! > Test if with panic in condition
181181

182182
//! > test_runner_name
183-
test_create_graph(expect_diagnostics: false, skip_lowering: false)
183+
test_create_graph(expect_diagnostics: false)
184184

185185
//! > function_code
186186
fn foo() -> felt252 {
@@ -221,7 +221,7 @@ End:
221221
//! > Test if with panic in body
222222

223223
//! > test_runner_name
224-
test_create_graph(expect_diagnostics: false, skip_lowering: false)
224+
test_create_graph(expect_diagnostics: false)
225225

226226
//! > function_code
227227
fn foo() -> felt252 {
@@ -283,7 +283,7 @@ End:
283283
//! > Test if with panic or return in both body and else
284284

285285
//! > test_runner_name
286-
test_create_graph(expect_diagnostics: false, skip_lowering: false)
286+
test_create_graph(expect_diagnostics: false)
287287

288288
//! > function_code
289289
fn foo() -> felt252 {
@@ -340,7 +340,7 @@ End:
340340
//! > Test if-let with nested enums.
341341

342342
//! > test_runner_name
343-
test_create_graph(expect_diagnostics: false, skip_lowering: false)
343+
test_create_graph(expect_diagnostics: false)
344344

345345
//! > function_code
346346
fn foo(x: Option<Option<felt252>>) -> felt252 {
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//! > Simple match
2+
3+
//! > test_runner_name
4+
test_create_graph(expect_diagnostics: false)
5+
6+
//! > function_code
7+
fn foo(color: Color) -> felt252 {
8+
match color {
9+
// TODO(lior): Remove some of the `(_)` once supported.
10+
Color::Red(_) | Color::Green(_) => 1,
11+
Color::Red(_) | Color::Blue(_) => 2,
12+
// TODO(lior): Change to `_` once supported.
13+
Color::Black(_) | Color::White(_) => 3,
14+
}
15+
}
16+
17+
//! > module_code
18+
enum Color {
19+
Red,
20+
Green,
21+
Blue,
22+
Black,
23+
White,
24+
}
25+
26+
//! > graph
27+
Root: 4
28+
0 ArmExpr { expr: ExprId(1) }
29+
1 ArmExpr { expr: ExprId(2) }
30+
2 ArmExpr { expr: ExprId(3) }
31+
3 EnumMatch { matched_var: FlowControlVar { idx: 0 }, variants: (NodeId(0), FlowControlVar { idx: 1 }), (NodeId(0), FlowControlVar { idx: 2 }), (NodeId(1), FlowControlVar { idx: 3 }), (NodeId(2), FlowControlVar { idx: 4 }), (NodeId(2), FlowControlVar { idx: 5 })}
32+
4 EvaluateExpr { expr: ExprId(0), var_id: FlowControlVar { idx: 0 }, next: NodeId(3) }
33+
34+
//! > semantic_diagnostics
35+
36+
//! > lowered
37+
Parameters: v0: test::Color
38+
blk0 (root):
39+
Statements:
40+
End:
41+
Match(match_enum(v0) {
42+
Color::Red(v1) => blk1,
43+
Color::Green(v2) => blk2,
44+
Color::Blue(v3) => blk3,
45+
Color::Black(v4) => blk4,
46+
Color::White(v5) => blk5,
47+
})
48+
49+
blk1:
50+
Statements:
51+
End:
52+
Goto(blk7, {})
53+
54+
blk2:
55+
Statements:
56+
End:
57+
Goto(blk7, {})
58+
59+
blk3:
60+
Statements:
61+
(v7: core::felt252) <- 2
62+
End:
63+
Goto(blk8, {v7 -> v9})
64+
65+
blk4:
66+
Statements:
67+
End:
68+
Goto(blk6, {})
69+
70+
blk5:
71+
Statements:
72+
End:
73+
Goto(blk6, {})
74+
75+
blk6:
76+
Statements:
77+
(v6: core::felt252) <- 3
78+
End:
79+
Goto(blk8, {v6 -> v9})
80+
81+
blk7:
82+
Statements:
83+
(v8: core::felt252) <- 1
84+
End:
85+
Goto(blk8, {v8 -> v9})
86+
87+
blk8:
88+
Statements:
89+
End:
90+
Return(v9)

0 commit comments

Comments
 (0)