Skip to content

Commit 41f03e3

Browse files
author
Jesus Lapastora Núñez
committed
separate adding graph edges from recursive visit
1 parent 219a452 commit 41f03e3

File tree

7 files changed

+58
-42
lines changed

7 files changed

+58
-42
lines changed

engine/baml-lib/ast/src/ast/baml_vis/graph.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,41 @@ impl<'index, 'pre> GraphBuilder<'index, 'pre> {
224224
self.build_scope_sequence(scope, None);
225225
}
226226

227+
self.add_scope_edges();
228+
227229
if self.cfg.show_call_nodes {
228230
self.add_header_calls();
229231
}
230232

231233
(self.graph, self.span_map)
232234
}
233235

236+
/// Links the items in each scope in source order, showing execution order.
237+
fn add_scope_edges(&mut self) {
238+
for scope in self.index.scopes() {
239+
// TODO: I think we can remove collect()?
240+
let items: Vec<Hid> = self
241+
.index
242+
.headers_in_scope_iter(scope)
243+
.filter(|h| !self.has_md_parent.contains(&h.hid))
244+
.map(|h| h.hid)
245+
.collect();
246+
247+
for (hid, prev_hid) in items[1..].iter().zip(&items) {
248+
let entry = self.header_entry[hid];
249+
let prev_exits = &self.header_exits[prev_hid];
250+
// NOTE: `extend` on a loop. TL;DR: each exits vec is pretty small.
251+
// More thorough explanation at the end of `build_header`.
252+
self.graph.edges.extend(
253+
prev_exits
254+
.iter()
255+
.copied()
256+
.map(|e| Edge { from: e, to: entry }),
257+
);
258+
}
259+
}
260+
}
261+
234262
fn build_scope_sequence(&mut self, scope: ScopeId, parent_cluster: Option<ClusterId>) {
235263
let items: Vec<Hid> = self
236264
.index
@@ -243,20 +271,6 @@ impl<'index, 'pre> GraphBuilder<'index, 'pre> {
243271
for &hid in &items {
244272
self.build_header(hid, parent_cluster);
245273
}
246-
247-
// unordered: add edges from scope <- header_entry, header_exits
248-
for (hid, prev_hid) in items[1..].iter().zip(&items) {
249-
let entry = self.header_entry[hid];
250-
let prev_exits = &self.header_exits[prev_hid];
251-
// NOTE: `extend` on a loop. TL;DR: each exits vec is pretty small.
252-
// More thorough explanation at the end of `build_header`.
253-
self.graph.edges.extend(
254-
prev_exits
255-
.iter()
256-
.copied()
257-
.map(|e| Edge { from: e, to: entry }),
258-
);
259-
}
260274
}
261275

262276
fn build_header(&mut self, hid: Hid, parent_cluster: Option<ClusterId>) {

engine/baml-lib/ast/src/ast/header_collector.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
1515
use std::{collections::HashMap, sync::Arc};
1616

17+
use baml_types::BamlMap;
1718
use internal_baml_diagnostics::Span;
1819

1920
use super::{Ast, Expression, ExpressionBlock, Field, Header, Stmt, Top, WithName, WithSpan};
@@ -70,8 +71,10 @@ pub struct RenderableHeader {
7071
pub struct HeaderIndex {
7172
/// All headers in source order per scope, flattened
7273
pub headers: Vec<RenderableHeader>,
73-
// header indexes in source order per scope
74-
by_scope: HashMap<ScopeId, Vec<usize>>,
74+
75+
/// Header indexes in source order per scope.
76+
/// Since it uses `BamlMap` it will maintain source order in snapshot testing.
77+
by_scope: BamlMap<ScopeId, Vec<usize>>,
7578
/// Mapping of internal Hid -> names of functions called by the labeled expression
7679
pub header_calls: HashMap<Hid, Vec<String>>, // hid -> [callee_name]
7780
hid_to_idx: Vec<usize>,
@@ -91,6 +94,12 @@ impl HeaderIndex {
9194
.flat_map(|idxs| idxs.iter().map(|i| &self.headers[*i]))
9295
}
9396

97+
/// Iterates all scopes. Under snapshot testing, order is guaranteed to be
98+
/// consistent with source order.
99+
pub fn scopes<'iter>(&'iter self) -> impl Iterator<Item = ScopeId> + 'iter {
100+
self.by_scope.keys().copied()
101+
}
102+
94103
/// O(1) access to a header by its Hid via internal index
95104
pub fn get_by_hid(&self, hid: Hid) -> Option<&RenderableHeader> {
96105
let idx = *self.hid_to_idx.get(hid.0 as usize)?;
@@ -107,12 +116,13 @@ impl HeaderIndex {
107116
}
108117

109118
/// Internal collector to walk AST and build a HeaderIndex
110-
#[derive(Debug)]
119+
#[derive(Debug, Default)]
111120
pub struct HeaderCollector {
112121
scope_counter: u32,
113122
scope_stack: Vec<ScopeId>,
114-
// Raw headers by scope before normalization and in-scope parenting
115-
raw_by_scope: HashMap<ScopeId, Vec<RawHeader>>, // source order
123+
/// Raw headers by scope before normalization and in-scope parenting.
124+
/// Will maintain source order under snapshot testing.
125+
raw_by_scope: BamlMap<ScopeId, Vec<RawHeader>>, // source order
116126
// Accumulated nested edges (Hid -> Hid)
117127
nested_edges_hid: Vec<(Hid, Hid)>,
118128
// Mapping during collection: header (by Hid) -> function names called by the labeled expression
@@ -134,15 +144,7 @@ struct RawHeader {
134144

135145
impl HeaderCollector {
136146
pub fn collect(ast: &Ast) -> HeaderIndex {
137-
let mut c = Self {
138-
scope_counter: 0,
139-
scope_stack: Vec::new(),
140-
raw_by_scope: HashMap::new(),
141-
nested_edges_hid: Vec::new(),
142-
header_fn_calls: HashMap::new(),
143-
next_hid: 0,
144-
last_hdr_stack: Vec::new(),
145-
};
147+
let mut c = Self::default();
146148
c.visit_ast(ast);
147149
c.build_index()
148150
}
@@ -464,7 +466,7 @@ impl HeaderCollector {
464466
fn build_index(self) -> HeaderIndex {
465467
let mut index = HeaderIndex {
466468
headers: Vec::new(),
467-
by_scope: HashMap::new(),
469+
by_scope: BamlMap::new(),
468470
header_calls: HashMap::new(),
469471
hid_to_idx: Vec::new(),
470472
nested_edges_hid: Vec::new(),

engine/baml-lib/baml/tests/validation_files/headers/ai_content_pipeline.mmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,8 @@ flowchart TD
3737
end
3838
n0 --> n1
3939
n3 --> n4
40-
n4 --> n5
4140
n2 --> n3
4241
n2 --> n6
43-
n7 --> n8
4442
n4 --> n7
4543
n6 --> n7
4644
n9 --> n10
@@ -49,6 +47,8 @@ flowchart TD
4947
n8 --> n9
5048
n10 --> n12
5149
n11 --> n12
50+
n4 --> n5
51+
n7 --> n8
5252
%%__BAML_SPANMAP__={"n0":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":4,"start":4,"end_line":5,"end":0},"n1":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":8,"start":4,"end_line":9,"end":0},"n2":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":15,"start":4,"end_line":16,"end":0},"n3":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":19,"start":8,"end_line":20,"end":0},"n4":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":22,"start":8,"end_line":23,"end":0},"n5":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":25,"start":8,"end_line":26,"end":0},"n6":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":30,"start":8,"end_line":31,"end":0},"n7":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":38,"start":8,"end_line":39,"end":0},"n8":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":42,"start":8,"end_line":43,"end":0},"n9":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":48,"start":4,"end_line":49,"end":0},"n10":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":50,"start":8,"end_line":51,"end":0},"n11":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":54,"start":8,"end_line":55,"end":0},"n12":{"file_path":"tests/validation_files/headers/ai_content_pipeline.baml","start_line":58,"start":4,"end_line":59,"end":0}}
5353
click n0 call bamlMermaidNodeClick() "Go to source"
5454
click n1 call bamlMermaidNodeClick() "Go to source"

engine/baml-lib/baml/tests/validation_files/headers/complex_headers_test.mmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ flowchart TD
4444
n0 --> n1
4545
n7 --> n8
4646
n8 --> n9
47-
n10 --> n11
4847
n11 --> n12
48+
n10 --> n11
4949
%%__BAML_SPANMAP__={"n0":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":3,"start":4,"end_line":4,"end":0},"n1":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":13,"start":8,"end_line":14,"end":0},"n2":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":16,"start":8,"end_line":17,"end":0},"n3":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":22,"start":12,"end_line":23,"end":0},"n4":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":25,"start":12,"end_line":26,"end":0},"n5":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":28,"start":12,"end_line":29,"end":0},"n6":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":32,"start":8,"end_line":33,"end":0},"n7":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":35,"start":8,"end_line":36,"end":0},"n8":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":39,"start":4,"end_line":40,"end":0},"n9":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":42,"start":4,"end_line":43,"end":0},"n10":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":53,"start":8,"end_line":54,"end":0},"n11":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":56,"start":8,"end_line":57,"end":0},"n12":{"file_path":"tests/validation_files/headers/complex_headers_test.baml","start_line":62,"start":4,"end_line":63,"end":0}}
5050
click n0 call bamlMermaidNodeClick() "Go to source"
5151
click n1 call bamlMermaidNodeClick() "Go to source"

engine/baml-lib/baml/tests/validation_files/headers/edge_cases.mmd

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,39 +86,39 @@ flowchart TD
8686
n13 --> n14
8787
n12 --> n13
8888
n15 --> n16
89-
n14 --> n15
9089
n18 --> n19
9190
n17 --> n18
9291
n21 --> n22
93-
n22 --> n23
9492
n20 --> n21
9593
n20 --> n24
96-
n22 --> n25
97-
n24 --> n25
98-
n25 --> n26
9994
n31 --> n32
10095
n30 --> n31
10196
n29 --> n30
10297
n28 --> n29
10398
n27 --> n28
10499
n35 --> n36
105100
n36 --> n37
106-
n33 --> n34
107-
n34 --> n35
108101
n38 --> n39
109102
n38 --> n40
110103
n39 --> n41
111104
n40 --> n41
112105
n42 --> n43
113106
n41 --> n42
114107
n43 --> n44
115-
n44 --> n45
116108
n46 --> n47
117109
n52 --> n53
118110
n51 --> n52
119111
n50 --> n51
120112
n49 --> n50
121113
n48 --> n49
114+
n14 --> n15
115+
n25 --> n26
116+
n22 --> n25
117+
n24 --> n25
118+
n22 --> n23
119+
n33 --> n34
120+
n34 --> n35
121+
n44 --> n45
122122
%%__BAML_SPANMAP__={"n0":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":3,"start":4,"end_line":4,"end":0},"n1":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":6,"start":4,"end_line":7,"end":0},"n2":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":9,"start":4,"end_line":10,"end":0},"n3":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":15,"start":4,"end_line":16,"end":0},"n4":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":16,"start":4,"end_line":17,"end":0},"n5":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":17,"start":4,"end_line":18,"end":0},"n6":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":18,"start":4,"end_line":19,"end":0},"n7":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":19,"start":4,"end_line":20,"end":0},"n8":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":20,"start":4,"end_line":21,"end":0},"n9":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":21,"start":4,"end_line":22,"end":0},"n10":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":22,"start":4,"end_line":23,"end":0},"n11":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":23,"start":4,"end_line":24,"end":0},"n12":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":29,"start":4,"end_line":30,"end":0},"n13":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":30,"start":4,"end_line":31,"end":0},"n14":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":31,"start":4,"end_line":32,"end":0},"n15":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":35,"start":4,"end_line":36,"end":0},"n16":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":36,"start":4,"end_line":37,"end":0},"n17":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":42,"start":4,"end_line":43,"end":0},"n18":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":48,"start":4,"end_line":49,"end":0},"n19":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":51,"start":4,"end_line":52,"end":0},"n20":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":60,"start":8,"end_line":61,"end":0},"n21":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":63,"start":12,"end_line":64,"end":0},"n22":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":66,"start":16,"end_line":67,"end":0},"n23":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":70,"start":12,"end_line":71,"end":0},"n24":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":73,"start":12,"end_line":74,"end":0},"n25":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":77,"start":8,"end_line":78,"end":0},"n26":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":81,"start":4,"end_line":82,"end":0},"n27":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":86,"start":4,"end_line":87,"end":0},"n28":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":87,"start":4,"end_line":88,"end":0},"n29":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":88,"start":4,"end_line":89,"end":0},"n30":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":89,"start":4,"end_line":90,"end":0},"n31":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":90,"start":4,"end_line":91,"end":0},"n32":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":91,"start":4,"end_line":92,"end":0},"n33":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":97,"start":4,"end_line":98,"end":0},"n34":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":98,"start":4,"end_line":99,"end":0},"n35":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":101,"start":4,"end_line":102,"end":0},"n36":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":102,"start":4,"end_line":103,"end":0},"n37":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":103,"start":4,"end_line":104,"end":0},"n38":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":113,"start":4,"end_line":114,"end":0},"n39":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":115,"start":8,"end_line":116,"end":0},"n40":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":118,"start":8,"end_line":119,"end":0},"n41":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":121,"start":4,"end_line":122,"end":0},"n42":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":123,"start":4,"end_line":124,"end":0},"n43":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":125,"start":8,"end_line":126,"end":0},"n44":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":128,"start":4,"end_line":129,"end":0},"n45":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":130,"start":4,"end_line":131,"end":0},"n46":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":135,"start":4,"end_line":136,"end":0},"n47":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":137,"start":4,"end_line":138,"end":0},"n48":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":143,"start":4,"end_line":144,"end":0},"n49":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":144,"start":4,"end_line":145,"end":0},"n50":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":145,"start":4,"end_line":146,"end":0},"n51":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":146,"start":4,"end_line":147,"end":0},"n52":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":147,"start":4,"end_line":148,"end":0},"n53":{"file_path":"tests/validation_files/headers/edge_cases.baml","start_line":148,"start":4,"end_line":149,"end":0}}
123123
click n0 call bamlMermaidNodeClick() "Go to source"
124124
click n1 call bamlMermaidNodeClick() "Go to source"

engine/baml-lib/baml/tests/validation_files/headers/for_loop_mermaid.mmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ flowchart TD
88
n1["Accumulation"]
99
end
1010
end
11-
n0 --> n1
1211
n1 --> n2
12+
n0 --> n1
1313
%%__BAML_SPANMAP__={"n0":{"file_path":"tests/validation_files/headers/for_loop_mermaid.baml","start_line":7,"start":8,"end_line":8,"end":0},"n1":{"file_path":"tests/validation_files/headers/for_loop_mermaid.baml","start_line":10,"start":8,"end_line":11,"end":0},"n2":{"file_path":"tests/validation_files/headers/for_loop_mermaid.baml","start_line":16,"start":4,"end_line":17,"end":0}}
1414
click n0 call bamlMermaidNodeClick() "Go to source"
1515
click n1 call bamlMermaidNodeClick() "Go to source"

engine/baml-lib/baml/tests/validation_files/headers/mixed_children_not_flattened.mmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ flowchart TD
55
n1["Loop Child"]
66
n2["And stuff"]
77
end
8-
n1 --> n2
98
n0 --> n1
9+
n1 --> n2
1010
%%__BAML_SPANMAP__={"n0":{"file_path":"tests/validation_files/headers/mixed_children_not_flattened.baml","start_line":0,"start":0,"end_line":1,"end":0},"n1":{"file_path":"tests/validation_files/headers/mixed_children_not_flattened.baml","start_line":5,"start":8,"end_line":6,"end":0},"n2":{"file_path":"tests/validation_files/headers/mixed_children_not_flattened.baml","start_line":6,"start":8,"end_line":7,"end":0}}
1111
click n0 call bamlMermaidNodeClick() "Go to source"
1212
click n1 call bamlMermaidNodeClick() "Go to source"

0 commit comments

Comments
 (0)