conjure_cp_core/ast/
records.rs1use std::collections::VecDeque;
2
3use super::Name;
4use super::literals::AbstractLiteralValue;
5use serde::{Deserialize, Serialize};
6
7use polyquine::Quine;
8use uniplate::{Biplate, Uniplate};
9
10#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash, Quine)]
11#[path_prefix(conjure_cp::ast)]
12pub struct RecordValue<T: AbstractLiteralValue> {
13 pub name: Name,
14 pub value: T,
15}
16
17impl<T> Uniplate for RecordValue<T>
22where
23 T: AbstractLiteralValue,
24{
25 fn uniplate(
26 &self,
27 ) -> (
28 ::uniplate::Tree<RecordValue<T>>,
29 Box<dyn Fn(::uniplate::Tree<RecordValue<T>>) -> RecordValue<T>>,
30 ) {
31 let _name_copy = self.name.clone();
32 let (tree_value, ctx_value) = <T as Biplate<RecordValue<T>>>::biplate(&self.value);
33 let children = ::uniplate::Tree::Many(::std::collections::VecDeque::from([
34 tree_value,
35 ::uniplate::Tree::Zero,
36 ]));
37 let ctx = Box::new(move |x: ::uniplate::Tree<RecordValue<T>>| {
38 let ::uniplate::Tree::Many(xs) = x else {
39 panic!()
40 };
41 let tree_value = xs[0].clone();
42 let value = ctx_value(tree_value);
43 RecordValue {
44 name: _name_copy.clone(),
45 value,
46 }
47 });
48 (children, ctx)
49 }
50}
51
52impl<To, U> Biplate<To> for RecordValue<U>
55where
56 U: AbstractLiteralValue + Biplate<To>,
57 To: Uniplate,
58{
59 fn biplate(&self) -> (uniplate::Tree<To>, Box<dyn Fn(uniplate::Tree<To>) -> Self>) {
60 use uniplate::Tree;
61
62 if std::any::TypeId::of::<To>() == std::any::TypeId::of::<RecordValue<U>>() {
63 unsafe {
66 let self_to = std::mem::transmute::<&RecordValue<U>, &To>(self).clone();
68 let tree = Tree::One(self_to);
69 let ctx = Box::new(move |x| {
70 let Tree::One(x) = x else {
71 panic!();
72 };
73
74 std::mem::transmute::<&To, &RecordValue<U>>(&x).clone()
75 });
76
77 (tree, ctx)
78 }
79 } else if std::any::TypeId::of::<To>() == std::any::TypeId::of::<Name>() {
80 let self2: RecordValue<U> = self.clone();
82 let f_name: Name = self2.name;
83 let f_val: U = self2.value;
84
85 let (tree_val, ctx_val) = <U as Biplate<To>>::biplate(&f_val);
86
87 unsafe {
88 let f_name_to = std::mem::transmute::<&Name, &To>(&f_name).clone();
90 let tree_name = Tree::One(f_name_to);
91 let tree = Tree::Many(VecDeque::from([tree_name, tree_val]));
92
93 let ctx = Box::new(move |x| {
94 let Tree::Many(xs) = x else {
96 panic!();
97 };
98
99 let tree_name = xs[0].clone();
100 let tree_val = xs[1].clone();
101
102 let Tree::One(name) = tree_name else {
103 panic!();
104 };
105
106 let name = std::mem::transmute::<&To, &Name>(&name).clone();
108 let value = ctx_val(tree_val);
109
110 RecordValue { name, value }
112 });
113
114 (tree, ctx)
115 }
116 } else {
117 let self2: RecordValue<U> = self.clone();
120 let f_name: Name = self2.name;
121 let f_val: U = self2.value;
122
123 let (tree_val, ctx_val) = <U as Biplate<To>>::biplate(&f_val);
124
125 let tree = Tree::Many(VecDeque::from([tree_val]));
126
127 let ctx = Box::new(move |x| {
128 let Tree::Many(xs) = x else {
130 panic!();
131 };
132
133 let tree_val = xs[0].clone();
134
135 RecordValue {
137 name: f_name.clone(),
138 value: ctx_val(tree_val),
139 }
140 });
141
142 (tree, ctx)
143 }
144 }
145}