1
use super::Name;
2
use crate::ast::literals::AbstractLiteralValue;
3
use funcmap::{FuncMap, TryFuncMap};
4
use polyquine::Quine;
5
use serde::{Deserialize, Serialize};
6
use std::cmp::Ordering;
7
use std::collections::VecDeque;
8
use std::fmt::{Display, Formatter};
9
use uniplate::{Biplate, Uniplate};
10

            
11
/// A named field of a record or variant.
12
/// Used in [AbstractLiteral::Record] / [AbstractLiteral::Variant] and
13
/// in corresponding domains
14
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash, Quine, FuncMap, TryFuncMap)]
15
#[path_prefix(conjure_cp::ast)]
16
pub struct Field<T> {
17
    pub name: Name,
18
    pub value: T,
19
}
20

            
21
impl<T: Eq> PartialOrd<Self> for Field<T> {
22
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
23
        Some(self.cmp(other))
24
    }
25
}
26

            
27
impl<T: Eq> Ord for Field<T> {
28
    fn cmp(&self, other: &Self) -> Ordering {
29
        self.name.cmp(&other.name)
30
    }
31
}
32

            
33
// Uniplate instance copy and pasted from cargo expand
34

            
35
// derive macro doesn't work as this has a generic type (for the same reasons as AbstractLiteral) ~nd60
36

            
37
impl<T> Uniplate for Field<T>
38
where
39
    T: Biplate<Field<T>>,
40
{
41
    fn uniplate(
42
        &self,
43
    ) -> (
44
        ::uniplate::Tree<Field<T>>,
45
        Box<dyn Fn(::uniplate::Tree<Field<T>>) -> Field<T>>,
46
    ) {
47
        let _name_copy = self.name.clone();
48
        let (tree_value, ctx_value) = <T as Biplate<Field<T>>>::biplate(&self.value);
49
        let children = ::uniplate::Tree::Many(VecDeque::from([tree_value, ::uniplate::Tree::Zero]));
50
        let ctx = Box::new(move |x: ::uniplate::Tree<Field<T>>| {
51
            let ::uniplate::Tree::Many(xs) = x else {
52
                panic!()
53
            };
54
            let tree_value = xs[0].clone();
55
            let value = ctx_value(tree_value);
56
            Field {
57
                name: _name_copy.clone(),
58
                value,
59
            }
60
        });
61
        (children, ctx)
62
    }
63
}
64

            
65
// want to be able to go anywhere U can go
66
// (I'll follow U wherever U will go)
67
impl<To, U> Biplate<To> for Field<U>
68
where
69
    U: Biplate<Field<U>> + Biplate<To>,
70
    To: Uniplate,
71
{
72
44820
    fn biplate(&self) -> (uniplate::Tree<To>, Box<dyn Fn(uniplate::Tree<To>) -> Self>) {
73
        use uniplate::Tree;
74

            
75
44820
        if std::any::TypeId::of::<To>() == std::any::TypeId::of::<Field<U>>() {
76
            // To ==From => return One(self)
77

            
78
            unsafe {
79
                // SAFETY: asserted the type equality above
80
                let self_to = std::mem::transmute::<&Field<U>, &To>(self).clone();
81
                let tree = Tree::One(self_to);
82
                let ctx = Box::new(move |x| {
83
                    let Tree::One(x) = x else {
84
                        panic!();
85
                    };
86

            
87
                    std::mem::transmute::<&To, &Field<U>>(&x).clone()
88
                });
89

            
90
                (tree, ctx)
91
            }
92
44820
        } else if std::any::TypeId::of::<To>() == std::any::TypeId::of::<Name>() {
93
            // return name field, as well as any names inside the value
94
            let self2: Field<U> = self.clone();
95
            let f_name: Name = self2.name;
96
            let f_val: U = self2.value;
97

            
98
            let (tree_val, ctx_val) = <U as Biplate<To>>::biplate(&f_val);
99

            
100
            unsafe {
101
                // SAFETY: asserted previously that To == Name
102
                let f_name_to = std::mem::transmute::<&Name, &To>(&f_name).clone();
103
                let tree_name = Tree::One(f_name_to);
104
                let tree = Tree::Many(VecDeque::from([tree_name, tree_val]));
105

            
106
                let ctx = Box::new(move |x| {
107
                    // deconstruct tree into tree_name and tree_val
108
                    let Tree::Many(xs) = x else {
109
                        panic!();
110
                    };
111

            
112
                    let tree_name = xs[0].clone();
113
                    let tree_val = xs[1].clone();
114

            
115
                    let Tree::One(name) = tree_name else {
116
                        panic!();
117
                    };
118

            
119
                    // SAFETY: asserted previously that To == Name
120
                    let name = std::mem::transmute::<&To, &Name>(&name).clone();
121
                    let value = ctx_val(tree_val);
122

            
123
                    // reconstruct things
124
                    Field { name, value }
125
                });
126

            
127
                (tree, ctx)
128
            }
129
        } else {
130
            // walk into To ignoring name field, as Name can only biplate into Name
131

            
132
44820
            let self2: Field<U> = self.clone();
133
44820
            let f_name: Name = self2.name;
134
44820
            let f_val: U = self2.value;
135

            
136
44820
            let (tree_val, ctx_val) = <U as Biplate<To>>::biplate(&f_val);
137

            
138
44820
            let tree = Tree::Many(VecDeque::from([tree_val]));
139

            
140
44820
            let ctx = Box::new(move |x| {
141
                // deconstruct tree into tree_name and tree_val
142
3360
                let Tree::Many(xs) = x else {
143
                    panic!();
144
                };
145

            
146
3360
                let tree_val = xs[0].clone();
147

            
148
                // reconstruct things
149
3360
                Field {
150
3360
                    name: f_name.clone(),
151
3360
                    value: ctx_val(tree_val),
152
3360
                }
153
3360
            });
154

            
155
44820
            (tree, ctx)
156
        }
157
44820
    }
158
}
159

            
160
impl<T> Display for Field<T>
161
where
162
    T: AbstractLiteralValue,
163
{
164
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
165
        write!(f, "{} = {}", self.name, self.value)
166
    }
167
}