1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use Data;
use Function;
use Generics;
use Signature;

#[derive(Debug, Clone)]
#[repr(C)]
pub struct Type(pub(crate) TypeNode);

#[derive(Debug, Clone)]
pub(crate) enum TypeNode {
    Infer,
    Unit,
    PrimitiveStr,
    Reference(Box<TypeNode>),
    ReferenceMut(Box<TypeNode>),
    Dereference(Box<TypeNode>),
    DataStructure {
        name: String,
        data: Data<TypeNode>,
    },
    Path {
        global: bool,
        path: Vec<String>,
        name: String,
        generics: Generics,
    },
}

impl Type {
    pub fn unit() -> Self {
        Type(TypeNode::Unit)
    }

    pub fn primitive_str() -> Self {
        Type(TypeNode::PrimitiveStr)
    }

    pub fn reference(&self) -> Self {
        Type(TypeNode::Reference(Box::new(self.0.clone())))
    }

    pub fn reference_mut(&self) -> Self {
        Type(TypeNode::ReferenceMut(Box::new(self.0.clone())))
    }

    pub fn dereference(&self) -> Self {
        match self.0 {
            TypeNode::Reference(ref inner) => Type((**inner).clone()),
            TypeNode::ReferenceMut(ref inner) => Type((**inner).clone()),
            ref other => Type(TypeNode::Dereference(Box::new(other.clone()))),
        }
    }

    pub fn get_function(&self, name: &str, sig: Signature) -> Function {
        Function {
            parent: Some(self.clone()),
            name: name.to_owned(),
            sig,
        }
    }

    pub fn data(&self) -> Data<Type> {
        match self.0 {
            TypeNode::DataStructure { ref data, .. } => {
                data.clone().map(|field| Type(field.element))
            }
            TypeNode::Reference(ref inner) => Type((**inner).clone())
                .data()
                .map(|field| field.element.reference()),
            TypeNode::ReferenceMut(ref inner) => Type((**inner).clone())
                .data()
                .map(|field| field.element.reference_mut()),
            _ => panic!("Type::data"),
        }
    }
}

impl TypeNode {
    pub(crate) fn get_name(&self) -> String {
        match *self {
            TypeNode::DataStructure { ref name, .. } => name.clone(),
            TypeNode::Reference(ref inner) => (&**inner).get_name(),
            TypeNode::ReferenceMut(ref inner) => (&**inner).get_name(),
            _ => panic!("Type::get_name"),
        }
    }
}