fetish_lib/type_id.rs
1use std::collections::HashMap;
2use crate::context::*;
3use crate::params::*;
4use crate::displayable_with_context::*;
5use std::fmt;
6use rand::prelude::*;
7
8///A directory of [`Type`]s associating them to [`TypeId`]s, used as
9///part of the specification of a [`Context`]. There can be multiple
10///`Type::VecType`s with different [`TypeId`]s, but given argument
11///and return [`TypeId`]s, this directory may only contain at most one
12///[`TypeId`] with the corresponding `Type::FuncType`.
13pub struct TypeInfoDirectory {
14 info_vec : Vec::<Type>,
15 func_ind_map : HashMap<(TypeId, TypeId), TypeId>,
16 ret_map : HashMap::<TypeId, Vec::<(TypeId, TypeId)>>
17}
18
19impl TypeInfoDirectory {
20 ///Creates an empty [`TypeInfoDirectory`].
21 pub fn new() -> Self {
22 TypeInfoDirectory {
23 info_vec : Vec::new(),
24 func_ind_map : HashMap::new(),
25 ret_map : HashMap::new()
26 }
27 }
28 ///Adds the given [`Type`] to this [`TypeInfoDirectory`], and
29 ///returns the [`TypeId`] that it was assigned.
30 pub fn add(&mut self, info : Type) -> TypeId {
31 let added_type_id : usize = self.info_vec.len();
32
33 self.ret_map.insert(added_type_id, Vec::new());
34
35 if let Type::FuncType(arg_type, ret_type) = info {
36 let pair = (arg_type, ret_type);
37 if (self.func_ind_map.contains_key(&pair)) {
38 return *self.func_ind_map.get(&pair).unwrap();
39 } else {
40 self.func_ind_map.insert(pair, added_type_id);
41 }
42
43 let ret_row = self.ret_map.get_mut(&ret_type).unwrap();
44 ret_row.push((added_type_id, arg_type));
45 }
46
47 self.info_vec.push(info);
48 added_type_id
49 }
50 ///Gets the total number of types stored in this [`TypeInfoDirectory`].
51 ///Since [`TypeId`]s are allocated consecutively, it's correct to use
52 ///this as an iteration bound if you want to iterate over all [`TypeId`]s stored here.
53 pub fn get_total_num_types(&self) -> usize {
54 self.info_vec.len()
55 }
56 ///Returns true iff this [`TypeInfoDirectory`] has a registered [`TypeId`] for
57 ///`Type::FuncType(arg_type_id, ret_type_id)`.
58 pub fn has_func_type(&self, arg_type_id : TypeId, ret_type_id : TypeId) -> bool {
59 let pair = (arg_type_id, ret_type_id);
60 self.func_ind_map.contains_key(&pair)
61 }
62 ///Assuming that there is a [`TypeId`] for a function from the given argument [`TypeId`]
63 ///to the given return [`TypeId`], yields the [`TypeId`] of the function type.
64 pub fn get_func_type_id(&self, arg_type_id : TypeId, ret_type_id : TypeId) -> TypeId {
65 let pair = (arg_type_id, ret_type_id);
66 *self.func_ind_map.get(&pair).unwrap()
67 }
68 ///Gets the [`Type`] information stored for the given [`TypeId`].
69 pub fn get_type(&self, id : TypeId) -> Type {
70 self.info_vec[id]
71 }
72 ///Gets all `(func_type_id, arg_type_id)` pairs which may be applied to yield the
73 ///given [`TypeId`].
74 pub fn get_application_type_ids(&self, id : TypeId) -> Vec::<(TypeId, TypeId)> {
75 self.ret_map.get(&id).unwrap().clone()
76 }
77 ///Given the [`TypeId`] of a function type, yields the [`TypeId`] of the return type.
78 pub fn get_ret_type_id(&self, func_type_id : TypeId) -> TypeId {
79 let func_type = self.get_type(func_type_id);
80 if let Type::FuncType(_, ret_type_id) = func_type {
81 ret_type_id
82 } else {
83 panic!();
84 }
85 }
86 ///Returns true iff the given [`TypeId`] points to a `Type::VecType`.
87 pub fn is_vector_type(&self, id : TypeId) -> bool {
88 let kind = self.get_type(id);
89 match (kind) {
90 Type::FuncType(_, _) => false,
91 Type::VecType(_) => true
92 }
93 }
94 ///Given the [`TypeId`] of a function type, yields the [`TypeId`] of the argument type.
95 pub fn get_arg_type_id(&self, func_type_id : TypeId) -> TypeId {
96 let func_type = self.get_type(func_type_id);
97 if let Type::FuncType(arg_type_id, _) = func_type {
98 arg_type_id
99 } else {
100 panic!();
101 }
102 }
103 ///Assuming that the given [`TypeId`] points to a `Type::VecType`, yields the
104 ///declared number of dimensions for that type's base space.
105 pub fn get_dimension(&self, vec_type_id : TypeId) -> usize {
106 let vec_type = self.get_type(vec_type_id);
107 if let Type::VecType(dim) = vec_type {
108 dim
109 } else {
110 panic!();
111 }
112 }
113}
114
115///Type alias for a `usize` index into a [`TypeInfoDirectory`]'s storage of
116///[`Type`]s. These are assumed to uniquely identify a type, whereas there may
117///be multiple [`TypeId`]s for the same [`Type`]. This is done so that
118///different vector types of the same dimension can potentially have different
119///canonical feature mappings, for instance, if one represents 2d images, and
120///the other represents 1d signals.
121pub type TypeId = usize;
122
123///Fundamental information about a type, generally indexed by a [`TypeId`] and
124///stored in a [`TypeInfoDirectory`].
125#[derive(Copy, Eq, PartialEq, Hash, Debug, Clone)]
126pub enum Type {
127 ///A type for vectors with the given declared number of dimensions for their base space
128 VecType(usize),
129 ///A type for functions which map elements of the former [`TypeId`] to the latter [`TypeId`],
130 ///which is consequently only truly meaningful in the context of a [`TypeInfoDirectory`].
131 FuncType(TypeId, TypeId)
132}
133
134impl DisplayableWithContext for Type {
135 fn display(&self, ctxt : &Context) -> String {
136 match (self) {
137 Type::VecType(n) => format!("{}", n),
138 Type::FuncType(arg, ret) => format!("({} -> {})",
139 ctxt.get_type(*arg).display(ctxt),
140 ctxt.get_type(*ret).display(ctxt))
141 }
142 }
143}