machine_check_common/iir/
description.rs1use std::fmt::Debug;
2
3use mck::refin::{Boolean, RArray, RBitvector, RefinementDomain, RefinementValue};
4
5use indexmap::IndexMap;
6use serde::{Deserialize, Serialize};
7
8use crate::iir::{
9    context::IContext,
10    func::{IFn, IFnDeclaration},
11    path::IIdent,
12    ty::IElementaryType,
13};
14
15#[derive(Clone, Debug, Serialize, Deserialize)]
16pub struct IMachine {
17    pub machine: IStructId,
18    pub init: IFnId,
19    pub next: IFnId,
20
21    pub input: IStructId,
22    pub param: IStructId,
23    pub state: IStructId,
24
25    pub description: IDescription,
26}
27
28#[derive(Clone, Debug, Serialize, Deserialize)]
29pub struct IDescription {
30    pub structs: IndexMap<IIdent, IStruct>,
31}
32
33#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
34pub struct IStructId(pub usize);
35
36#[derive(Clone, Debug, Serialize, Deserialize)]
37pub struct IStructDeclaration {
38    pub fields: IndexMap<IIdent, IElementaryType>,
39    pub fns: IndexMap<(ITrait, IIdent), IFnDeclaration>,
40}
41
42#[derive(Clone, Debug, Serialize, Deserialize)]
43pub struct IStruct {
44    pub fields: IndexMap<IIdent, IElementaryType>,
45    pub fns: IndexMap<(ITrait, IIdent), IFn>,
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
49pub enum ITrait {
50    Inherent,
51    Machine,
52}
53
54#[derive(Clone, Debug, Serialize, Deserialize, Default)]
55pub struct IImpl {
56    fns: IndexMap<IIdent, IFn>,
57}
58
59impl IMachine {
60    pub fn machine(&self) -> &IStruct {
61        self.description.struct_with_id(self.machine)
62    }
63
64    pub fn input(&self) -> &IStruct {
65        self.description.struct_with_id(self.input)
66    }
67
68    pub fn param(&self) -> &IStruct {
69        self.description.struct_with_id(self.param)
70    }
71
72    pub fn state(&self) -> &IStruct {
73        self.description.struct_with_id(self.state)
74    }
75
76    pub fn init(&self) -> &IFn {
77        self.description.fn_with_id(self.init)
78    }
79    pub fn next(&self) -> &IFn {
80        self.description.fn_with_id(self.next)
81    }
82}
83
84impl IDescription {
85    pub fn context(&self) -> IContext {
86        IContext {
87            structs: Some(&self.structs),
88        }
89    }
90
91    pub fn struct_with_id(&self, id: IStructId) -> &IStruct {
92        self.structs
93            .get_index(id.0)
94            .expect("Struct with given id should exist")
95            .1
96    }
97
98    pub fn fn_with_id(&self, id: IFnId) -> &IFn {
99        self.struct_with_id(id.struct_id)
100            .fns
101            .get_index(id.fn_index)
102            .expect("Call with given id should exist")
103            .1
104    }
105}
106
107impl IStruct {
108    pub fn clean_refin(&self, description: &IDescription) -> RefinementValue {
109        let mut result = Vec::new();
110        for field_ty in self.fields.values() {
111            let field_result = match field_ty {
112                IElementaryType::Bitvector(width) => {
113                    RefinementValue::Bitvector(RBitvector::new_unmarked(*width))
114                }
115                IElementaryType::Array(array) => RefinementValue::Array(RArray::new_unmarked(
116                    array.index_width,
117                    array.element_width,
118                )),
119                IElementaryType::Boolean => RefinementValue::Boolean(Boolean::new_unmarked()),
120                IElementaryType::Struct(struct_id) => {
121                    let iir_struct = description.struct_with_id(*struct_id);
122                    iir_struct.clean_refin(description)
123                }
124            };
125            result.push(field_result)
126        }
127
128        RefinementValue::Struct(result)
129    }
130
131    pub fn dirty_refin(&self, description: &IDescription) -> RefinementValue {
132        let mut result = Vec::new();
133        for field_ty in self.fields.values() {
134            let field_result = match field_ty {
135                IElementaryType::Bitvector(width) => {
136                    RefinementValue::Bitvector(RBitvector::new_marked_unimportant(*width))
137                }
138                IElementaryType::Array(array) => RefinementValue::Array(
139                    RArray::new_marked_unimportant(array.index_width, array.element_width),
140                ),
141                IElementaryType::Boolean => {
142                    RefinementValue::Boolean(Boolean::new_marked_unimportant())
143                }
144                IElementaryType::Struct(struct_id) => {
145                    let iir_struct = description.struct_with_id(*struct_id);
146                    iir_struct.dirty_refin(description)
147                }
148            };
149            result.push(field_result)
150        }
151
152        RefinementValue::Struct(result)
153    }
154
155    pub fn into_declaration(self) -> IStructDeclaration {
156        let fns = self
157            .fns
158            .into_iter()
159            .map(|func| (func.0, func.1.into_declaration()))
160            .collect();
161
162        IStructDeclaration {
163            fields: self.fields,
164            fns,
165        }
166    }
167}
168
169impl Debug for IStructId {
170    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171        write!(f, "${}", self.0)
172    }
173}
174
175#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
176pub struct IFnId {
177    pub struct_id: IStructId,
178    pub fn_index: usize,
179}
180
181impl Debug for IFnId {
182    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183        write!(f, "{:?}::{}", self.struct_id, self.fn_index)
184    }
185}