tl_scheme/
tokens.rs

1use crc::{Crc, CRC_32_ISO_HDLC};
2use rustc_hash::FxHashMap;
3
4/// Parsed scheme with all types and functions.
5#[derive(Debug, Clone, Default)]
6pub struct Scheme<'a> {
7    pub builtins: FxHashMap<&'a str, BuiltinConstructor<'a>>,
8    pub types: FxHashMap<&'a str, Constructor<'a>>,
9    pub boxed_types: FxHashMap<&'a str, Vec<&'a str>>,
10    pub functions: FxHashMap<&'a str, Constructor<'a>>,
11}
12
13impl<'a> Scheme<'a> {
14    /// Computes all TL ids in the scheme
15    pub fn compute_all_ids(&self) -> FxHashMap<u32, (ConstructorKind, &Constructor<'a>)> {
16        let mut ids = FxHashMap::with_capacity_and_hasher(
17            self.types.len() + self.functions.len(),
18            Default::default(),
19        );
20
21        for ty in self.types.values() {
22            ids.insert(ty.compute_tl_id(), (ConstructorKind::Type, ty));
23        }
24
25        for func in self.functions.values() {
26            ids.insert(func.compute_tl_id(), (ConstructorKind::Function, func));
27        }
28
29        ids
30    }
31
32    /// Resolves all types in the scheme
33    pub fn validate(&self) -> Result<(), ValidationError> {
34        for ty in self.types.values() {
35            self.check_constructor(ty)?;
36        }
37        for func in self.functions.values() {
38            self.check_constructor(func)?;
39        }
40        Ok(())
41    }
42
43    /// Finds a type variant or function with the given name
44    pub fn find_constructor(&self, name: &str) -> Option<(ConstructorKind, &Constructor<'a>)> {
45        if let Some(constructor) = self.get_type_variant(name) {
46            Some((ConstructorKind::Type, constructor))
47        } else {
48            self.get_function(name)
49                .map(|constructor| (ConstructorKind::Function, constructor))
50        }
51    }
52
53    /// Finds type variant with the given name
54    pub fn get_type_variant(&self, name: &str) -> Option<&Constructor<'a>> {
55        self.types.get(name)
56    }
57
58    /// Finds function with the given name
59    pub fn get_function(&self, name: &str) -> Option<&Constructor<'a>> {
60        self.functions.get(name)
61    }
62
63    fn check_constructor(&self, decl: &Constructor<'a>) -> Result<(), ValidationError> {
64        for (i, field) in decl.fields.iter().enumerate() {
65            let prev_fields = &decl.fields[..i];
66            self.check_type(&field.ty, &decl.type_parameters, prev_fields)?;
67        }
68
69        if !self.boxed_types.contains_key(decl.output.ty)
70            && !decl
71                .type_parameters
72                .iter()
73                .any(|field| field.name == Some(decl.output.ty))
74        {
75            return Err(ValidationError::UnknownType(decl.output.to_string()));
76        }
77
78        if let Some(ty_param) = &decl.output.ty_param {
79            self.check_type(ty_param, &decl.type_parameters, &[])?;
80        }
81
82        Ok(())
83    }
84
85    fn check_type(
86        &self,
87        ty: &Type<'a>,
88        type_parameters: &[Field<'a>],
89        prev_fields: &[Field<'a>],
90    ) -> Result<(), ValidationError> {
91        match ty {
92            Type::Int => {}
93            Type::Named { ty } => {
94                if !self.is_declared(ty)
95                    && !type_parameters.iter().any(|field| field.name == Some(ty))
96                {
97                    return Err(ValidationError::UnknownType(ty.to_string()));
98                }
99            }
100            Type::Generic { ty, ty_param } => {
101                if !self.is_declared(ty)
102                    && !type_parameters.iter().any(|field| field.name == Some(ty))
103                {
104                    return Err(ValidationError::UnknownType(ty.to_string()));
105                }
106                self.check_type(ty_param, type_parameters, &[])?;
107            }
108            Type::Flagged {
109                flags_field, ty, ..
110            } => {
111                prev_fields
112                    .iter()
113                    .find(|field| field.name == Some(flags_field))
114                    .ok_or_else(|| ValidationError::UnknownField(flags_field.to_string()))?;
115                self.check_type(ty, type_parameters, prev_fields)?;
116            }
117            Type::Repeated { ty, .. } => {
118                for field in ty {
119                    self.check_type(&field.ty, type_parameters, prev_fields)?;
120                }
121            }
122        }
123
124        Ok(())
125    }
126
127    fn is_declared(&self, ty: &str) -> bool {
128        self.types.contains_key(ty)
129            || self.boxed_types.contains_key(ty)
130            || self.builtins.contains_key(ty)
131    }
132}
133
134/// Predefined constructor
135#[derive(Debug, Copy, Clone, Eq, PartialEq)]
136pub struct BuiltinConstructor<'a> {
137    pub variant: &'a str,
138    pub tl_id: Option<u32>,
139    pub output: &'a str,
140}
141
142#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
143pub enum ConstructorKind {
144    Type,
145    Function,
146}
147
148impl std::fmt::Display for ConstructorKind {
149    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150        match self {
151            ConstructorKind::Type => write!(f, "type"),
152            ConstructorKind::Function => write!(f, "function"),
153        }
154    }
155}
156
157/// Type or function declaration
158#[derive(Debug, Clone, Eq, PartialEq)]
159pub struct Constructor<'a> {
160    pub variant: &'a str,
161    pub tl_id: Option<u32>,
162    pub type_parameters: Vec<Field<'a>>,
163    pub fields: Vec<Field<'a>>,
164    pub output: OutputType<'a>,
165}
166
167impl Constructor<'_> {
168    pub fn as_normalized(&self) -> String {
169        NormalizedConstructor(self).to_string()
170    }
171
172    pub fn compute_tl_id(&self) -> u32 {
173        use std::fmt::Write;
174
175        if let Some(id) = self.tl_id {
176            return id;
177        }
178
179        struct Checksum<'a>(crc::Digest<'a, u32>);
180
181        impl Write for Checksum<'_> {
182            #[inline(always)]
183            fn write_str(&mut self, s: &str) -> std::fmt::Result {
184                self.0.update(s.as_bytes());
185                Ok(())
186            }
187        }
188
189        let mut checksum = Checksum(CRC.digest());
190        write!(&mut checksum, "{}", NormalizedConstructor(self)).unwrap();
191
192        checksum.0.finalize()
193    }
194}
195
196struct NormalizedConstructor<'c, 'a>(&'c Constructor<'a>);
197
198impl std::fmt::Display for NormalizedConstructor<'_, '_> {
199    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200        self.0.variant.fmt(f)?;
201
202        for ty in &self.0.type_parameters {
203            f.write_fmt(format_args!(" {{{ty}}}"))?;
204        }
205
206        for field in &self.0.fields {
207            f.write_fmt(format_args!(" {field}"))?
208        }
209
210        f.write_fmt(format_args!(" = {}", self.0.output))
211    }
212}
213
214#[derive(Debug, Clone, Eq, PartialEq)]
215pub struct Field<'a> {
216    pub name: Option<&'a str>,
217    pub ty: Type<'a>,
218}
219
220impl std::fmt::Display for Field<'_> {
221    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
222        if let Some(name) = self.name {
223            f.write_fmt(format_args!("{name}:{}", self.ty))
224        } else {
225            self.ty.fmt(f)
226        }
227    }
228}
229
230#[derive(Debug, Clone, Eq, PartialEq)]
231pub struct OutputType<'a> {
232    pub ty: &'a str,
233    pub ty_param: Option<Box<Type<'a>>>,
234}
235
236impl std::fmt::Display for OutputType<'_> {
237    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238        match &self.ty_param {
239            None => f.write_str(self.ty),
240            Some(ty_param) => f.write_fmt(format_args!("{} {ty_param}", self.ty)),
241        }
242    }
243}
244
245#[derive(Debug, Clone, Eq, PartialEq)]
246pub enum Type<'a> {
247    /// Simple `#` (equivalent to `u32`)
248    Int,
249    /// Full path to identifier
250    Named { ty: &'a str },
251    /// Full path to identifier with type param
252    Generic {
253        ty: &'a str,
254        ty_param: Box<Type<'a>>,
255    },
256    /// Conditional type
257    Flagged {
258        flags_field: &'a str,
259        bit: u8,
260        ty: Box<Type<'a>>,
261    },
262    /// Tuple type which can be multiplied
263    Repeated {
264        multiplicity: Option<u32>,
265        ty: Vec<Field<'a>>,
266    },
267}
268
269impl std::fmt::Display for Type<'_> {
270    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271        match self {
272            Self::Int => f.write_str("#"),
273
274            Self::Named { ty } => f.write_str(ty),
275
276            Self::Generic { ty, ty_param } => f.write_fmt(format_args!("{ty} {ty_param}")),
277
278            Self::Flagged {
279                flags_field,
280                bit,
281                ty,
282            } => f.write_fmt(format_args!("{flags_field}.{bit}?{ty}")),
283
284            Self::Repeated { multiplicity, ty } => {
285                if let Some(multiplicity) = multiplicity {
286                    f.write_fmt(format_args!("{multiplicity} * [ "))?
287                } else {
288                    f.write_str("[ ")?
289                }
290
291                for ty in ty {
292                    f.write_fmt(format_args!("{ty} "))?
293                }
294
295                f.write_str("]")
296            }
297        }
298    }
299}
300
301#[derive(thiserror::Error, Debug)]
302pub enum ValidationError {
303    #[error("unknown field: {0}")]
304    UnknownField(String),
305    #[error("unknown type: {0}")]
306    UnknownType(String),
307}
308
309static CRC: Crc<u32> = Crc::<u32>::new(&CRC_32_ISO_HDLC);