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