litex/runtime/
runtime_parsing_free_param_collection.rs1use crate::prelude::*;
2use std::collections::HashMap;
3
4#[derive(Clone)]
5pub struct FreeParamCollection {
6 pub params: HashMap<String, Vec<FreeParamTypeAndLineFile>>,
7}
8
9#[derive(Clone, Debug)]
10pub struct FreeParamTypeAndLineFile {
11 pub kind: ParamObjType,
12 pub line_file: LineFile,
13}
14
15impl FreeParamCollection {
16 pub fn new() -> Self {
17 FreeParamCollection {
18 params: HashMap::new(),
19 }
20 }
21
22 pub fn clear(&mut self) {
23 self.params.clear();
24 }
25
26 fn push_param(
27 &mut self,
28 name: String,
29 kind: ParamObjType,
30 line_file: LineFile,
31 ) -> Result<(), RuntimeError> {
32 let stack = self.params.entry(name.clone()).or_default();
33 if stack.iter().any(|b| b.kind == kind) {
34 return Err(RuntimeError::from(ParseRuntimeError(
35 RuntimeErrorStruct::new_with_msg_and_line_file(
36 format!(
37 "free parameter `{}` is already bound as {:?} in an active scope",
38 name, kind
39 ),
40 line_file,
41 ),
42 )));
43 }
44 stack.push(FreeParamTypeAndLineFile { kind, line_file });
45 Ok(())
46 }
47
48 pub fn begin_scope(
49 &mut self,
50 kind: ParamObjType,
51 names: &[String],
52 line_file: LineFile,
53 ) -> Result<(), RuntimeError> {
54 for n in names {
55 self.push_param(n.clone(), kind, line_file.clone())?;
56 }
57 Ok(())
58 }
59
60 pub fn end_scope(&mut self, kind: ParamObjType, names: &[String]) {
61 for n in names {
62 let Some(stack) = self.params.get_mut(n) else {
63 panic!("free param stack missing for `{}` on end_scope", n);
64 };
65 let Some(top) = stack.pop() else {
66 panic!("free param stack for `{}` empty on end_scope", n);
67 };
68 debug_assert_eq!(top.kind, kind);
69 if stack.is_empty() {
70 self.params.remove(n);
71 }
72 }
73 }
74
75 pub fn name_is_in_any_free_param_map(&self, name: &str) -> bool {
76 self.params
77 .get(name)
78 .map_or(false, |stack| !stack.is_empty())
79 }
80
81 pub fn resolve_identifier_to_free_param_obj(&self, name: &str) -> Obj {
82 if !self.name_is_in_any_free_param_map(name) {
83 return Identifier::new(name.to_string()).into();
84 }
85 let Some(stack) = self.params.get(name) else {
86 return Identifier::new(name.to_string()).into();
87 };
88 let Some(top) = stack.last() else {
89 return Identifier::new(name.to_string()).into();
90 };
91 match top.kind {
92 ParamObjType::Forall => ForallFreeParamObj::new(name.to_string()).into(),
93 ParamObjType::DefHeader => DefHeaderFreeParamObj::new(name.to_string()).into(),
94 ParamObjType::Exist => ExistFreeParamObj::new(name.to_string()).into(),
95 ParamObjType::SetBuilder => SetBuilderFreeParamObj::new(name.to_string()).into(),
96 ParamObjType::FnSet => FnSetFreeParamObj::new(name.to_string()).into(),
97 ParamObjType::Induc => ByInducFreeParamObj::new(name.to_string()).into(),
98 ParamObjType::DefAlgo => DefAlgoFreeParamObj::new(name.to_string()).into(),
99 ParamObjType::Identifier => Identifier::new(name.to_string()).into(),
100 }
101 }
102}