GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

types.rs 9.1 KB
Newer Older
qinsoon's avatar
qinsoon committed
1
use ast::ptr::P;
qinsoon's avatar
qinsoon committed
2
use ast::ir::*;
3 4 5
use common::vector_as_str;

use std::fmt;
qinsoon's avatar
qinsoon committed
6 7
use std::collections::HashMap;
use std::sync::RwLock;
qinsoon's avatar
qinsoon committed
8

qinsoon's avatar
qinsoon committed
9 10
pub type MuType = MuType_;

11
#[derive(Clone, PartialEq, Eq, Debug)]
qinsoon's avatar
qinsoon committed
12
pub enum MuType_ {
qinsoon's avatar
qinsoon committed
13
    /// int <length>
qinsoon's avatar
qinsoon committed
14
    Int          (usize),
qinsoon's avatar
qinsoon committed
15
    /// float
qinsoon's avatar
qinsoon committed
16
    Float,
qinsoon's avatar
qinsoon committed
17
    /// double
qinsoon's avatar
qinsoon committed
18
    Double,
qinsoon's avatar
qinsoon committed
19 20
    
    /// ref<T>
qinsoon's avatar
qinsoon committed
21
    Ref          (P<MuType>),    // Box is needed for non-recursive enum
qinsoon's avatar
qinsoon committed
22
    /// iref<T>: internal reference
qinsoon's avatar
qinsoon committed
23
    IRef         (P<MuType>),
qinsoon's avatar
qinsoon committed
24
    /// weakref<T>
qinsoon's avatar
qinsoon committed
25
    WeakRef      (P<MuType>),
qinsoon's avatar
qinsoon committed
26 27
    
    /// uptr<T>: unsafe pointer
qinsoon's avatar
qinsoon committed
28
    UPtr         (P<MuType>),
qinsoon's avatar
qinsoon committed
29 30
    
    /// struct<T1 T2 ...>
qinsoon's avatar
qinsoon committed
31
    Struct       (MuTag),
qinsoon's avatar
qinsoon committed
32 33
    
    /// array<T length>
qinsoon's avatar
qinsoon committed
34
    Array        (P<MuType>, usize),
qinsoon's avatar
qinsoon committed
35 36
    
    /// hybrid<F1 F2 ... V>: a hybrid of fixed length parts and a variable length part
qinsoon's avatar
qinsoon committed
37
    Hybrid       (Vec<P<MuType>>, P<MuType>),
qinsoon's avatar
qinsoon committed
38 39
    
    /// void
qinsoon's avatar
qinsoon committed
40
    Void,
qinsoon's avatar
qinsoon committed
41 42
    
    /// threadref
qinsoon's avatar
qinsoon committed
43
    ThreadRef,
qinsoon's avatar
qinsoon committed
44
    /// stackref
qinsoon's avatar
qinsoon committed
45
    StackRef,
qinsoon's avatar
qinsoon committed
46 47
    
    /// tagref64: hold a double or an int or an ref<void>
qinsoon's avatar
qinsoon committed
48
    Tagref64,
qinsoon's avatar
qinsoon committed
49 50
    
    /// vector<T length>
qinsoon's avatar
qinsoon committed
51
    Vector       (P<MuType>, usize),
qinsoon's avatar
qinsoon committed
52 53
    
    /// funcref<@sig>
54
    FuncRef      (P<MuFuncSig>),
qinsoon's avatar
qinsoon committed
55 56
    
    /// ufuncptr<@sig>
57
    UFuncPtr     (P<MuFuncSig>),
qinsoon's avatar
qinsoon committed
58 59
}

60
impl fmt::Display for MuType_ {
61 62
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
qinsoon's avatar
qinsoon committed
63 64 65
            &MuType_::Int(n)                          => write!(f, "int<{}>", n),
            &MuType_::Float                           => write!(f, "float"),
            &MuType_::Double                          => write!(f, "double"),
66 67 68 69 70
            &MuType_::Ref(ref ty)                     => write!(f, "ref<{}>", ty),
            &MuType_::IRef(ref ty)                    => write!(f, "iref<{}>", ty),
            &MuType_::WeakRef(ref ty)                 => write!(f, "weakref<{}>", ty),
            &MuType_::UPtr(ref ty)                    => write!(f, "uptr<{}>", ty),
            &MuType_::Array(ref ty, size)             => write!(f, "array<{} {}>", ty, size),
71
            &MuType_::Hybrid(ref fix_tys, ref var_ty) => write!(f, "hybrid<[{}] {}>", vector_as_str(fix_tys), var_ty), 
qinsoon's avatar
qinsoon committed
72 73 74 75
            &MuType_::Void                            => write!(f, "void"),
            &MuType_::ThreadRef                       => write!(f, "threadref"),
            &MuType_::StackRef                        => write!(f, "stackref"),
            &MuType_::Tagref64                        => write!(f, "tagref64"),
76 77 78
            &MuType_::Vector(ref ty, size)            => write!(f, "vector<{} {}>", ty, size),
            &MuType_::FuncRef(ref sig)                => write!(f, "funcref<{}>", sig),
            &MuType_::UFuncPtr(ref sig)               => write!(f, "ufuncref<{}>", sig),
qinsoon's avatar
qinsoon committed
79
            &MuType_::Struct(tag)                     => write!(f, "{}(struct)", tag)
80 81 82 83
        }
    }
}

qinsoon's avatar
qinsoon committed
84 85
lazy_static! {
    /// storing a map from MuTag to StructType_
86
    pub static ref STRUCT_TAG_MAP : RwLock<HashMap<MuTag, StructType_>> = RwLock::new(HashMap::new());
qinsoon's avatar
qinsoon committed
87 88
}

89
#[derive(Clone, PartialEq, Eq, Debug)]
qinsoon's avatar
qinsoon committed
90
pub struct StructType_ {
91
    tys: Vec<P<MuType_>>
qinsoon's avatar
qinsoon committed
92 93
}

94
impl fmt::Display for StructType_ {
95
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
qinsoon's avatar
qinsoon committed
96 97 98
        write!(f, "struct<").unwrap();
        for i in 0..self.tys.len() {
            let ty = &self.tys[i];
99
            write!(f, "{}", ty).unwrap();
qinsoon's avatar
qinsoon committed
100 101 102
            if i != self.tys.len() - 1 {
                write!(f, " ").unwrap();
            }
103
        }
qinsoon's avatar
qinsoon committed
104
        write!(f, ">")
105 106 107
    }    
}

qinsoon's avatar
qinsoon committed
108
impl StructType_ {
qinsoon's avatar
qinsoon committed
109
    pub fn set_tys(&mut self, mut list: Vec<P<MuType>>) {
qinsoon's avatar
qinsoon committed
110
        self.tys.clear();
qinsoon's avatar
qinsoon committed
111
        self.tys.append(&mut list);
qinsoon's avatar
qinsoon committed
112 113 114
    }
}

qinsoon's avatar
qinsoon committed
115 116 117
impl MuType_ {
    pub fn int(len: usize) -> MuType_ {
        MuType_::Int(len)
qinsoon's avatar
qinsoon committed
118
    }
qinsoon's avatar
qinsoon committed
119 120
    pub fn float() -> MuType_ {
        MuType_::Float
qinsoon's avatar
qinsoon committed
121
    }
qinsoon's avatar
qinsoon committed
122 123
    pub fn double() -> MuType_ {
        MuType_::Double
qinsoon's avatar
qinsoon committed
124
    }
125
    pub fn muref(referent: P<MuType_>) -> MuType_ {
qinsoon's avatar
qinsoon committed
126
        MuType_::Ref(referent)
qinsoon's avatar
qinsoon committed
127
    }
qinsoon's avatar
qinsoon committed
128
    pub fn muref_void() -> MuType_ {
129
        MuType_::Ref(P(MuType_::void()))
qinsoon's avatar
qinsoon committed
130
    }
131
    pub fn iref(referent: P<MuType_>) -> MuType_ {
qinsoon's avatar
qinsoon committed
132
        MuType_::IRef(referent)
qinsoon's avatar
qinsoon committed
133
    }
134
    pub fn weakref(referent: P<MuType_>) -> MuType_ {
qinsoon's avatar
qinsoon committed
135
        MuType_::WeakRef(referent)
qinsoon's avatar
qinsoon committed
136
    }
137
    pub fn uptr(referent: P<MuType_>) -> MuType_ {
qinsoon's avatar
qinsoon committed
138
        MuType_::UPtr(referent)
qinsoon's avatar
qinsoon committed
139
    }
qinsoon's avatar
qinsoon committed
140
    pub fn mustruct_empty(tag: MuTag) -> MuType_ {
qinsoon's avatar
qinsoon committed
141 142 143
        let struct_ty_ = StructType_{tys: vec![]};
        STRUCT_TAG_MAP.write().unwrap().insert(tag, struct_ty_);

qinsoon's avatar
qinsoon committed
144
        MuType_::Struct(tag)
qinsoon's avatar
qinsoon committed
145
    }
146
    pub fn mustruct(tag: MuTag, list: Vec<P<MuType_>>) -> MuType_ {
qinsoon's avatar
qinsoon committed
147
        let struct_ty_ = StructType_{tys: list};
qinsoon's avatar
qinsoon committed
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163

        // if there is an attempt to use a same tag for different struct,
        // we panic
        match STRUCT_TAG_MAP.read().unwrap().get(tag) {
            Some(old_struct_ty_) => {
                if struct_ty_ != *old_struct_ty_ {
                    panic!(format!(
                            "trying to insert {:?} as {}, while the old struct is defined as {:?}",
                            struct_ty_, tag, old_struct_ty_))
                }
            },
            None => {}
        }
        // otherwise, store the tag
        STRUCT_TAG_MAP.write().unwrap().insert(tag, struct_ty_);

qinsoon's avatar
qinsoon committed
164
        MuType_::Struct(tag)
qinsoon's avatar
qinsoon committed
165
    }
166
    pub fn array(ty: P<MuType_>, len: usize) -> MuType_ {
qinsoon's avatar
qinsoon committed
167
        MuType_::Array(ty, len)
qinsoon's avatar
qinsoon committed
168
    }
169
    pub fn hybrid(fix_tys: Vec<P<MuType_>>, var_ty: P<MuType_>) -> MuType_ {
qinsoon's avatar
qinsoon committed
170
        MuType_::Hybrid(fix_tys, var_ty)
qinsoon's avatar
qinsoon committed
171
    }
qinsoon's avatar
qinsoon committed
172 173
    pub fn void() -> MuType_ {
        MuType_::Void
qinsoon's avatar
qinsoon committed
174
    }
qinsoon's avatar
qinsoon committed
175 176
    pub fn threadref() -> MuType_ {
        MuType_::ThreadRef
qinsoon's avatar
qinsoon committed
177
    }
qinsoon's avatar
qinsoon committed
178 179
    pub fn stackref() -> MuType_ {
        MuType_::StackRef
qinsoon's avatar
qinsoon committed
180
    }
qinsoon's avatar
qinsoon committed
181 182
    pub fn tagref64() -> MuType_ {
        MuType_::Tagref64
qinsoon's avatar
qinsoon committed
183
    }
184
    pub fn vector(ty: P<MuType_>, len: usize) -> MuType_ {
qinsoon's avatar
qinsoon committed
185
        MuType_::Vector(ty, len)
qinsoon's avatar
qinsoon committed
186
    }
187
    pub fn funcref(sig: P<MuFuncSig>) -> MuType_ {
qinsoon's avatar
qinsoon committed
188
        MuType_::FuncRef(sig)
qinsoon's avatar
qinsoon committed
189
    }
190
    pub fn ufuncptr(sig: P<MuFuncSig>) -> MuType_ {
qinsoon's avatar
qinsoon committed
191
        MuType_::UFuncPtr(sig)
qinsoon's avatar
qinsoon committed
192 193 194 195
    }
}

/// is a type floating-point type?
qinsoon's avatar
qinsoon committed
196
pub fn is_fp(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
197
    match *ty {
qinsoon's avatar
qinsoon committed
198
        MuType_::Float | MuType_::Double => true,
qinsoon's avatar
qinsoon committed
199 200 201 202 203
        _ => false
    }
}

/// is a type raw pointer?
qinsoon's avatar
qinsoon committed
204
pub fn is_ptr(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
205
    match *ty {
qinsoon's avatar
qinsoon committed
206
        MuType_::UPtr(_) | MuType_::UFuncPtr(_) => true,
qinsoon's avatar
qinsoon committed
207 208 209 210 211
        _ => false
    }
}

/// is a type scalar type?
qinsoon's avatar
qinsoon committed
212
pub fn is_scalar(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
213
    match *ty {
qinsoon's avatar
qinsoon committed
214 215 216 217 218 219 220 221 222 223 224 225
        MuType_::Int(_)
        | MuType_::Float
        | MuType_::Double
        | MuType_::Ref(_)
        | MuType_::IRef(_)
        | MuType_::WeakRef(_)
        | MuType_::FuncRef(_)
        | MuType_::UFuncPtr(_)
        | MuType_::ThreadRef
        | MuType_::StackRef
        | MuType_::Tagref64
        | MuType_::UPtr(_) => true,
qinsoon's avatar
qinsoon committed
226 227 228 229 230 231
        _ => false
    }
}

/// is a type traced by the garbage collector?
/// Note: An aggregated type is traced if any of its part is traced. 
qinsoon's avatar
qinsoon committed
232
pub fn is_traced(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
233
    match *ty {
qinsoon's avatar
qinsoon committed
234 235 236 237 238 239 240 241 242
        MuType_::Ref(_) => true,
        MuType_::IRef(_) => true,
        MuType_::WeakRef(_) => true,
        MuType_::Array(ref elem_ty, _)
        | MuType_::Vector(ref elem_ty, _) => is_traced(elem_ty),
        MuType_::ThreadRef
        | MuType_::StackRef
        | MuType_::Tagref64 => true,
        MuType_::Hybrid(ref fix_tys, ref var_ty) => {
qinsoon's avatar
qinsoon committed
243 244 245 246
            is_traced(var_ty) ||
            fix_tys.into_iter().map(|ty| is_traced(ty))
                .fold(false, |ret, this| ret || this) 
            },
qinsoon's avatar
qinsoon committed
247
        MuType_::Struct(tag) => {
qinsoon's avatar
qinsoon committed
248 249 250 251 252 253 254 255 256 257 258 259 260
            let map = STRUCT_TAG_MAP.read().unwrap();
            let struct_ty = map.get(tag).unwrap();
            let ref field_tys = struct_ty.tys;
            
            field_tys.into_iter().map(|ty| is_traced(&ty))
                .fold(false, |ret, this| ret || this)
        },
        _ => false
    }
}

/// is a type native safe?
/// Note: An aggregated type is native safe if all of its parts are native safe.
qinsoon's avatar
qinsoon committed
261
pub fn is_native_safe(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
262
    match *ty {
qinsoon's avatar
qinsoon committed
263 264 265 266 267 268 269 270 271
        MuType_::Int(_) => true,
        MuType_::Float => true,
        MuType_::Double => true,
        MuType_::Void => true,
        MuType_::Array(ref elem_ty, _)
        | MuType_::Vector(ref elem_ty, _) => is_native_safe(elem_ty),
        MuType_::UPtr(_) => true,
        MuType_::UFuncPtr(_) => true,
        MuType_::Hybrid(ref fix_tys, ref var_ty) => {
qinsoon's avatar
qinsoon committed
272 273 274 275
            is_native_safe(var_ty) && 
            fix_tys.into_iter().map(|ty| is_native_safe(&ty))
                .fold(true, |ret, this| ret && this)
        },
qinsoon's avatar
qinsoon committed
276
        MuType_::Struct(tag) => {
qinsoon's avatar
qinsoon committed
277 278 279 280 281 282 283 284
            let map = STRUCT_TAG_MAP.read().unwrap();
            let struct_ty = map.get(tag).unwrap();
            let ref field_tys = struct_ty.tys;
            
            field_tys.into_iter().map(|ty| is_native_safe(&ty))
                .fold(true, |ret, this| ret && this)
        },
        _ => false
qinsoon's avatar
qinsoon committed
285 286 287 288 289 290 291 292 293 294 295 296
    }
}

macro_rules! is_type (
    ($e:expr, $p:pat) => (
        match $e {
            $p => true,
            _ => false
        }
    )
);

297
#[derive(Clone, PartialEq, Eq, Debug)]
qinsoon's avatar
qinsoon committed
298
pub struct MuFuncSig {
qinsoon's avatar
qinsoon committed
299 300
    pub ret_tys : Vec<P<MuType>>,
    pub arg_tys: Vec<P<MuType>>
301 302
}

303
impl fmt::Display for MuFuncSig {
304
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
305
        write!(f, "[{}] -> [{}]", vector_as_str(&self.ret_tys), vector_as_str(&self.arg_tys))
306
    }    
qinsoon's avatar
qinsoon committed
307
}