calyx_opt/passes_experimental/
metadata_table_gen.rs

1use crate::traversal::{Action, ConstructVisitor, Named, VisResult, Visitor};
2
3//use calyx_frontend::SetAttr::Pos;
4use calyx_ir::GetAttributes;
5use calyx_ir::source_info::{FileId, LineNum, SourceInfoTable};
6use calyx_utils::WithPos;
7use std::collections::HashMap;
8use std::path::PathBuf;
9
10/// Metadata creates and stores the source info table for the currently running program
11pub struct Metadata {
12    src_table: SourceInfoTable,
13    file_ids: HashMap<String, FileId>,
14}
15
16impl Metadata {
17    /// Create an empty metadata table
18    #[allow(clippy::new_without_default)]
19    pub fn new() -> Self {
20        Self {
21            src_table: SourceInfoTable::new_empty(),
22            file_ids: HashMap::new(),
23        }
24    }
25
26    pub fn add_control_node<A: GetAttributes>(&mut self, node: &mut A) {
27        let attr = node.get_mut_attributes();
28        let node_pos = attr.copy_span();
29        let (f, (line, endline)) = node_pos.get_line_num();
30        let fnum = self.file_ids.get(f).unwrap();
31        let pos = self.src_table.push_position(
32            *fnum,
33            LineNum::new(line as u32),
34            Some(LineNum::new(endline as u32)),
35        );
36        attr.insert_set(calyx_frontend::SetAttr::Pos, pos.value());
37    }
38}
39
40impl Named for Metadata {
41    fn name() -> &'static str {
42        "metadata-table-generation"
43    }
44    fn description() -> &'static str {
45        "generates metadata table for a file not containing one"
46    }
47}
48
49impl ConstructVisitor for Metadata {
50    fn from(_ctx: &calyx_ir::Context) -> calyx_utils::CalyxResult<Self>
51    where
52        Self: Sized,
53    {
54        Ok(Self::new())
55    }
56
57    fn clear_data(&mut self) {
58        // preserve across components
59        // hacky oops
60    }
61}
62impl Visitor for Metadata {
63    fn start_context(&mut self, ctx: &mut calyx_ir::Context) -> VisResult {
64        if let Some(x) = std::mem::take(&mut ctx.source_info_table) {
65            self.src_table = x;
66        }
67        Ok(Action::Continue)
68    }
69
70    // this visits each component
71    fn start(
72        &mut self,
73        comp: &mut calyx_ir::Component,
74        _sigs: &calyx_ir::LibrarySignatures,
75        _comps: &[calyx_ir::Component],
76    ) -> VisResult {
77        // implement visiting each component and adding the positions
78        // how this works:
79        // components have attributes !!
80        // check if file exists for component definition
81        let binding = comp.attributes.copy_span();
82        let (file, (line, endline)) = binding.get_line_num();
83
84        // add file to source table (if not already in)
85        if !self.file_ids.contains_key(file) {
86            let id = self.src_table.push_file(PathBuf::from(file));
87            self.file_ids.insert(String::from(file), id);
88        }
89
90        // add source position of the component itself
91        let component_file_id = self.file_ids.get(file).unwrap();
92        let component_pos = self.src_table.push_position(
93            *component_file_id,
94            LineNum::new(line as u32),
95            Some(LineNum::new(endline as u32)),
96        );
97        comp.attributes
98            .insert_set(calyx_frontend::SetAttr::Pos, component_pos.value());
99
100        // visit all groups in component
101        for rrcgrp in comp.groups.iter() {
102            let mut grp = rrcgrp.borrow_mut();
103            let attr = &mut grp.attributes;
104            let pos_data = attr.copy_span();
105            let (f, (line_start, line_end)) = pos_data.get_line_num();
106            let fid = self.file_ids.get(f).unwrap(); // this def should be in file_ids
107            let pos = self.src_table.push_position(
108                *fid,
109                LineNum::new(line_start as u32),
110                Some(LineNum::new(line_end as u32)),
111            );
112            // add tag to group attributes
113            attr.insert_set(calyx_frontend::SetAttr::Pos, pos.value());
114        }
115
116        // visit all comb groups in context
117        for rrc_comb_group in comp.comb_groups.iter() {
118            let mut grp = rrc_comb_group.borrow_mut();
119            let attr = &mut grp.attributes;
120            let pos_data = attr.copy_span();
121            let (f, (line_start, line_end)) = pos_data.get_line_num();
122            let fid = self.file_ids.get(f).unwrap(); // this def should be in file_ids
123            let pos = self.src_table.push_position(
124                *fid,
125                LineNum::new(line_start as u32),
126                Some(LineNum::new(line_end as u32)),
127            );
128            // add tag to group attributes
129            attr.insert_set(calyx_frontend::SetAttr::Pos, pos.value());
130        }
131
132        // visit all static groups in context
133        for rrc_static_group in comp.static_groups.iter() {
134            let mut grp = rrc_static_group.borrow_mut();
135            let attr = &mut grp.attributes;
136            let pos_data = attr.copy_span();
137            let (f, (line_start, line_end)) = pos_data.get_line_num();
138            let fid = self.file_ids.get(f).unwrap(); // this def should be in file_ids
139            let pos = self.src_table.push_position(
140                *fid,
141                LineNum::new(line_start as u32),
142                Some(LineNum::new(line_end as u32)),
143            );
144            // add tag to group attributes
145            attr.insert_set(calyx_frontend::SetAttr::Pos, pos.value());
146        }
147        Ok(Action::Continue)
148    }
149
150    fn finish_context(&mut self, ctx: &mut calyx_ir::Context) -> VisResult {
151        ctx.source_info_table = Some(std::mem::take(&mut self.src_table));
152        Ok(Action::Continue)
153    }
154
155    fn enable(
156        &mut self,
157        s: &mut calyx_ir::Enable,
158        _comp: &mut calyx_ir::Component,
159        _sigs: &calyx_ir::LibrarySignatures,
160        _comps: &[calyx_ir::Component],
161    ) -> VisResult {
162        self.add_control_node(s);
163        Ok(Action::Continue)
164    }
165
166    // control nodes
167    fn start_seq(
168        &mut self,
169        s: &mut calyx_ir::Seq,
170        _comp: &mut calyx_ir::Component,
171        _sigs: &calyx_ir::LibrarySignatures,
172        _comps: &[calyx_ir::Component],
173    ) -> VisResult {
174        self.add_control_node(s);
175        Ok(Action::Continue)
176    }
177
178    fn start_par(
179        &mut self,
180        s: &mut calyx_ir::Par,
181        _comp: &mut calyx_ir::Component,
182        _sigs: &calyx_ir::LibrarySignatures,
183        _comps: &[calyx_ir::Component],
184    ) -> VisResult {
185        self.add_control_node(s);
186        Ok(Action::Continue)
187    }
188
189    fn start_if(
190        &mut self,
191        s: &mut calyx_ir::If,
192        _comp: &mut calyx_ir::Component,
193        _sigs: &calyx_ir::LibrarySignatures,
194        _comps: &[calyx_ir::Component],
195    ) -> VisResult {
196        self.add_control_node(s);
197        Ok(Action::Continue)
198    }
199
200    fn start_while(
201        &mut self,
202        s: &mut calyx_ir::While,
203        _comp: &mut calyx_ir::Component,
204        _sigs: &calyx_ir::LibrarySignatures,
205        _comps: &[calyx_ir::Component],
206    ) -> VisResult {
207        self.add_control_node(s);
208        Ok(Action::Continue)
209    }
210
211    fn start_repeat(
212        &mut self,
213        s: &mut calyx_ir::Repeat,
214        _comp: &mut calyx_ir::Component,
215        _sigs: &calyx_ir::LibrarySignatures,
216        _comps: &[calyx_ir::Component],
217    ) -> VisResult {
218        self.add_control_node(s);
219        Ok(Action::Continue)
220    }
221}