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 temp = attr.copy_span();
29        let (f, (line, _)) = temp.get_line_num();
30        let fnum = self.file_ids.get(f).unwrap();
31        let pos = self
32            .src_table
33            .push_position(*fnum, LineNum::new(line as u32));
34        attr.insert_set(calyx_frontend::SetAttr::Pos, pos.value());
35    }
36}
37
38impl Named for Metadata {
39    fn name() -> &'static str {
40        "metadata-table-generation"
41    }
42    fn description() -> &'static str {
43        "generates metadata table for a file not containing one"
44    }
45}
46
47impl ConstructVisitor for Metadata {
48    fn from(_ctx: &calyx_ir::Context) -> calyx_utils::CalyxResult<Self>
49    where
50        Self: Sized,
51    {
52        Ok(Self::new())
53    }
54
55    fn clear_data(&mut self) {
56        // preserve across components
57        // hacky oops
58    }
59}
60impl Visitor for Metadata {
61    fn start_context(&mut self, ctx: &mut calyx_ir::Context) -> VisResult {
62        if let Some(x) = std::mem::take(&mut ctx.source_info_table) {
63            self.src_table = x;
64        }
65        Ok(Action::Continue)
66    }
67
68    // this visits each component
69    fn start(
70        &mut self,
71        comp: &mut calyx_ir::Component,
72        _sigs: &calyx_ir::LibrarySignatures,
73        _comps: &[calyx_ir::Component],
74    ) -> VisResult {
75        // implement visiting each component and adding the positions
76        // how this works:
77        // components have attributes !!
78        // check if file exists for component definition
79        let binding = comp.attributes.copy_span();
80        let (file, (line, _)) = binding.get_line_num();
81
82        // add file to source table (if not already in)
83        if !self.file_ids.contains_key(file) {
84            let id = self.src_table.push_file(PathBuf::from(file));
85            self.file_ids.insert(String::from(file), id);
86        }
87
88        // add source position of the component itself
89        let component_file_id = self.file_ids.get(file).unwrap();
90        let component_pos = self
91            .src_table
92            .push_position(*component_file_id, LineNum::new(line as u32));
93        comp.attributes
94            .insert_set(calyx_frontend::SetAttr::Pos, component_pos.value());
95
96        // visit all groups in component
97        for rrcgrp in comp.groups.iter() {
98            let mut grp = rrcgrp.borrow_mut();
99            let attr = &mut grp.attributes;
100            let pos_data = attr.copy_span();
101            let (f, (line_start, _line_end)) = pos_data.get_line_num();
102            let fid = self.file_ids.get(f).unwrap(); // this def should be in file_ids
103            let pos = self
104                .src_table
105                .push_position(*fid, LineNum::new(line_start as u32));
106            // add tag to group attributes
107            attr.insert_set(calyx_frontend::SetAttr::Pos, pos.value());
108        }
109        Ok(Action::Continue)
110    }
111
112    fn finish_context(&mut self, ctx: &mut calyx_ir::Context) -> VisResult {
113        ctx.source_info_table = Some(std::mem::take(&mut self.src_table));
114        Ok(Action::Continue)
115    }
116
117    fn enable(
118        &mut self,
119        s: &mut calyx_ir::Enable,
120        _comp: &mut calyx_ir::Component,
121        _sigs: &calyx_ir::LibrarySignatures,
122        _comps: &[calyx_ir::Component],
123    ) -> VisResult {
124        self.add_control_node(s);
125        Ok(Action::Continue)
126    }
127
128    // control nodes
129    fn start_seq(
130        &mut self,
131        s: &mut calyx_ir::Seq,
132        _comp: &mut calyx_ir::Component,
133        _sigs: &calyx_ir::LibrarySignatures,
134        _comps: &[calyx_ir::Component],
135    ) -> VisResult {
136        self.add_control_node(s);
137        Ok(Action::Continue)
138    }
139
140    fn start_par(
141        &mut self,
142        s: &mut calyx_ir::Par,
143        _comp: &mut calyx_ir::Component,
144        _sigs: &calyx_ir::LibrarySignatures,
145        _comps: &[calyx_ir::Component],
146    ) -> VisResult {
147        self.add_control_node(s);
148        Ok(Action::Continue)
149    }
150
151    fn start_if(
152        &mut self,
153        s: &mut calyx_ir::If,
154        _comp: &mut calyx_ir::Component,
155        _sigs: &calyx_ir::LibrarySignatures,
156        _comps: &[calyx_ir::Component],
157    ) -> VisResult {
158        self.add_control_node(s);
159        Ok(Action::Continue)
160    }
161
162    fn start_while(
163        &mut self,
164        s: &mut calyx_ir::While,
165        _comp: &mut calyx_ir::Component,
166        _sigs: &calyx_ir::LibrarySignatures,
167        _comps: &[calyx_ir::Component],
168    ) -> VisResult {
169        self.add_control_node(s);
170        Ok(Action::Continue)
171    }
172
173    fn start_repeat(
174        &mut self,
175        s: &mut calyx_ir::Repeat,
176        _comp: &mut calyx_ir::Component,
177        _sigs: &calyx_ir::LibrarySignatures,
178        _comps: &[calyx_ir::Component],
179    ) -> VisResult {
180        self.add_control_node(s);
181        Ok(Action::Continue)
182    }
183}