simplicity/jet/
type_name.rs1use crate::types::{self, Final, Type};
8use crate::Tmr;
9use std::cmp;
10use std::sync::Arc;
11
12#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
32pub struct TypeName(pub &'static [u8]);
33
34impl PartialEq<Final> for TypeName {
35 fn eq(&self, other: &Final) -> bool {
36 self.tmr() == other.tmr()
37 }
38}
39
40impl PartialEq<TypeName> for Final {
41 fn eq(&self, other: &TypeName) -> bool {
42 self.tmr() == other.tmr()
43 }
44}
45
46impl TypeName {
47 pub fn to_type<'brand>(&self, ctx: &types::Context<'brand>) -> Type<'brand> {
49 Type::complete(ctx, self.to_final())
50 }
51
52 pub fn to_final(&self) -> Arc<Final> {
54 let mut stack = Vec::with_capacity(16);
55
56 for c in self.0.iter().rev() {
57 match c {
58 b'1' => stack.push(Final::unit()),
59 b'2' => stack.push(Final::two_two_n_fixed::<0>()),
60 b'c' => stack.push(Final::two_two_n_fixed::<3>()),
61 b's' => stack.push(Final::two_two_n_fixed::<4>()),
62 b'i' => stack.push(Final::two_two_n_fixed::<5>()),
63 b'l' => stack.push(Final::two_two_n_fixed::<6>()),
64 b'h' => stack.push(Final::two_two_n_fixed::<8>()),
65 b'+' | b'*' => {
66 let left = stack.pop().expect("Illegal type name syntax!");
67 let right = stack.pop().expect("Illegal type name syntax!");
68
69 match c {
70 b'+' => stack.push(Final::sum(left, right)),
71 b'*' => stack.push(Final::product(left, right)),
72 _ => unreachable!(),
73 }
74 }
75 _ => panic!("Illegal type name syntax!"),
76 }
77 }
78
79 if stack.len() == 1 {
80 stack.pop().unwrap()
81 } else {
82 panic!("Illegal type name syntax!")
83 }
84 }
85
86 pub fn tmr(&self) -> Tmr {
88 let mut stack = Vec::with_capacity(16);
89
90 for c in self.0.iter().rev() {
91 match c {
92 b'1' => stack.push(Tmr::unit()),
93 b'2' => stack.push(Tmr::TWO_TWO_N[0]),
94 b'c' => stack.push(Tmr::TWO_TWO_N[3]),
95 b's' => stack.push(Tmr::TWO_TWO_N[4]),
96 b'i' => stack.push(Tmr::TWO_TWO_N[5]),
97 b'l' => stack.push(Tmr::TWO_TWO_N[6]),
98 b'h' => stack.push(Tmr::TWO_TWO_N[8]),
99 b'+' | b'*' => {
100 let left = stack.pop().expect("Illegal type name syntax!");
101 let right = stack.pop().expect("Illegal type name syntax!");
102
103 match c {
104 b'+' => stack.push(Tmr::sum(left, right)),
105 b'*' => stack.push(Tmr::product(left, right)),
106 _ => unreachable!(),
107 }
108 }
109 _ => panic!("Illegal type name syntax!"),
110 }
111 }
112
113 if stack.len() == 1 {
114 stack.pop().unwrap()
115 } else {
116 panic!("Illegal type name syntax!")
117 }
118 }
119
120 pub fn to_bit_width(&self) -> usize {
124 let mut stack = Vec::with_capacity(16);
125
126 for c in self.0.iter().rev() {
127 match c {
128 b'1' => stack.push(0),
129 b'2' => stack.push(1),
130 b'c' => stack.push(8),
131 b's' => stack.push(16),
132 b'i' => stack.push(32),
133 b'l' => stack.push(64),
134 b'h' => stack.push(256),
135 b'+' | b'*' => {
136 let left = stack.pop().expect("Illegal type name syntax!");
137 let right = stack.pop().expect("Illegal type name syntax!");
138
139 match c {
140 b'+' => stack.push(1 + cmp::max(left, right)),
141 b'*' => stack.push(left + right),
142 _ => unreachable!(),
143 }
144 }
145 _ => panic!("Illegal type name syntax!"),
146 }
147 }
148
149 if stack.len() == 1 {
150 stack.pop().unwrap()
151 } else {
152 panic!("Illegal type name syntax!")
153 }
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use crate::jet::{Core, Jet};
160
161 #[test]
162 fn all_jet_tmrs() {
163 for jet in &Core::ALL {
164 let source_final = jet.source_ty().to_final();
165 let target_final = jet.target_ty().to_final();
166
167 assert_eq!(*source_final, jet.source_ty());
168 assert_eq!(jet.source_ty(), *source_final);
169 assert_eq!(source_final.tmr(), jet.source_ty().tmr());
170 assert_eq!(source_final.bit_width(), jet.source_ty().to_bit_width());
171
172 assert_eq!(*target_final, jet.target_ty());
173 assert_eq!(jet.target_ty(), *target_final);
174 assert_eq!(target_final.tmr(), jet.target_ty().tmr());
175 assert_eq!(target_final.bit_width(), jet.target_ty().to_bit_width());
176 }
177 }
178}