types.rs 9.73 KB
Newer Older
qinsoon's avatar
qinsoon committed
1
use ast::ptr::P;
qinsoon's avatar
qinsoon committed
2
use ast::ir::*;
3
use utils::vec_utils::as_str as vector_as_str;
4 5

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 11 12 13 14 15 16 17 18 19 20 21 22 23 24
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct MuType {
    pub id: MuID,
    pub name: Option<MuName>,
    pub v: MuType_
}

impl MuType {
    pub fn new(id: MuID, v: MuType_) -> MuType {
        MuType {
            id: id,
            name: None,
            v: v
        }
    }
}
qinsoon's avatar
qinsoon committed
25

qinsoon's avatar
qinsoon committed
26
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
qinsoon's avatar
qinsoon committed
27
pub enum MuType_ {
qinsoon's avatar
qinsoon committed
28
    /// int <length>
qinsoon's avatar
qinsoon committed
29
    Int          (usize),
qinsoon's avatar
qinsoon committed
30
    /// float
qinsoon's avatar
qinsoon committed
31
    Float,
qinsoon's avatar
qinsoon committed
32
    /// double
qinsoon's avatar
qinsoon committed
33
    Double,
34

qinsoon's avatar
qinsoon committed
35
    /// ref<T>
qinsoon's avatar
qinsoon committed
36
    Ref          (P<MuType>),    // Box is needed for non-recursive enum
qinsoon's avatar
qinsoon committed
37
    /// iref<T>: internal reference
qinsoon's avatar
qinsoon committed
38
    IRef         (P<MuType>),
qinsoon's avatar
qinsoon committed
39
    /// weakref<T>
qinsoon's avatar
qinsoon committed
40
    WeakRef      (P<MuType>),
41

qinsoon's avatar
qinsoon committed
42
    /// uptr<T>: unsafe pointer
qinsoon's avatar
qinsoon committed
43
    UPtr         (P<MuType>),
44

qinsoon's avatar
qinsoon committed
45
    /// struct<T1 T2 ...>
qinsoon's avatar
qinsoon committed
46
    Struct       (MuName),
47

qinsoon's avatar
qinsoon committed
48
    /// array<T length>
qinsoon's avatar
qinsoon committed
49
    Array        (P<MuType>, usize),
50

qinsoon's avatar
qinsoon committed
51
    /// hybrid<F1 F2 ... V>: a hybrid of fixed length parts and a variable length part
qinsoon's avatar
qinsoon committed
52
    Hybrid       (Vec<P<MuType>>, P<MuType>),
53

qinsoon's avatar
qinsoon committed
54
    /// void
qinsoon's avatar
qinsoon committed
55
    Void,
56

qinsoon's avatar
qinsoon committed
57
    /// threadref
qinsoon's avatar
qinsoon committed
58
    ThreadRef,
qinsoon's avatar
qinsoon committed
59
    /// stackref
qinsoon's avatar
qinsoon committed
60
    StackRef,
61

qinsoon's avatar
qinsoon committed
62
    /// tagref64: hold a double or an int or an ref<void>
qinsoon's avatar
qinsoon committed
63
    Tagref64,
64

qinsoon's avatar
qinsoon committed
65
    /// vector<T length>
qinsoon's avatar
qinsoon committed
66
    Vector       (P<MuType>, usize),
67

qinsoon's avatar
qinsoon committed
68
    /// funcref<@sig>
69
    FuncRef      (P<MuFuncSig>),
70

qinsoon's avatar
qinsoon committed
71
    /// ufuncptr<@sig>
72
    UFuncPtr     (P<MuFuncSig>),
qinsoon's avatar
qinsoon committed
73 74
}

qinsoon's avatar
qinsoon committed
75 76 77 78 79 80
impl fmt::Display for MuType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.v)        
    }
}

81
impl fmt::Display for MuType_ {
82 83
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
qinsoon's avatar
qinsoon committed
84 85 86
            &MuType_::Int(n)                          => write!(f, "int<{}>", n),
            &MuType_::Float                           => write!(f, "float"),
            &MuType_::Double                          => write!(f, "double"),
87 88 89 90 91
            &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),
92
            &MuType_::Hybrid(ref fix_tys, ref var_ty) => write!(f, "hybrid<[{}] {}>", vector_as_str(fix_tys), var_ty),
qinsoon's avatar
qinsoon committed
93 94 95 96
            &MuType_::Void                            => write!(f, "void"),
            &MuType_::ThreadRef                       => write!(f, "threadref"),
            &MuType_::StackRef                        => write!(f, "stackref"),
            &MuType_::Tagref64                        => write!(f, "tagref64"),
97 98 99
            &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
100
            &MuType_::Struct(tag)                     => write!(f, "{}(struct)", tag)
101 102 103 104
        }
    }
}

qinsoon's avatar
qinsoon committed
105
lazy_static! {
qinsoon's avatar
qinsoon committed
106 107
    /// storing a map from MuName to StructType_
    pub static ref STRUCT_TAG_MAP : RwLock<HashMap<MuName, StructType_>> = RwLock::new(HashMap::new());
qinsoon's avatar
qinsoon committed
108 109
}

110
#[derive(Clone, PartialEq, Eq, Debug)]
qinsoon's avatar
qinsoon committed
111
pub struct StructType_ {
qinsoon's avatar
qinsoon committed
112
    tys: Vec<P<MuType>>
qinsoon's avatar
qinsoon committed
113 114
}

115
impl fmt::Display for StructType_ {
116
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
qinsoon's avatar
qinsoon committed
117 118 119
        write!(f, "struct<").unwrap();
        for i in 0..self.tys.len() {
            let ty = &self.tys[i];
120
            write!(f, "{}", ty).unwrap();
qinsoon's avatar
qinsoon committed
121 122 123
            if i != self.tys.len() - 1 {
                write!(f, " ").unwrap();
            }
124
        }
qinsoon's avatar
qinsoon committed
125
        write!(f, ">")
126
    }
127 128
}

qinsoon's avatar
qinsoon committed
129
impl StructType_ {
qinsoon's avatar
qinsoon committed
130
    pub fn set_tys(&mut self, mut list: Vec<P<MuType>>) {
qinsoon's avatar
qinsoon committed
131
        self.tys.clear();
qinsoon's avatar
qinsoon committed
132
        self.tys.append(&mut list);
qinsoon's avatar
qinsoon committed
133
    }
qinsoon's avatar
qinsoon committed
134
    
qinsoon's avatar
qinsoon committed
135
    pub fn get_tys(&self) -> &Vec<P<MuType>> {
qinsoon's avatar
qinsoon committed
136 137
        &self.tys
    }
qinsoon's avatar
qinsoon committed
138 139
}

qinsoon's avatar
qinsoon committed
140 141 142
impl MuType_ {
    pub fn int(len: usize) -> MuType_ {
        MuType_::Int(len)
qinsoon's avatar
qinsoon committed
143
    }
qinsoon's avatar
qinsoon committed
144 145
    pub fn float() -> MuType_ {
        MuType_::Float
qinsoon's avatar
qinsoon committed
146
    }
qinsoon's avatar
qinsoon committed
147 148
    pub fn double() -> MuType_ {
        MuType_::Double
qinsoon's avatar
qinsoon committed
149
    }
qinsoon's avatar
qinsoon committed
150
    pub fn muref(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
151
        MuType_::Ref(referent)
qinsoon's avatar
qinsoon committed
152
    }
qinsoon's avatar
qinsoon committed
153
    pub fn iref(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
154
        MuType_::IRef(referent)
qinsoon's avatar
qinsoon committed
155
    }
qinsoon's avatar
qinsoon committed
156
    pub fn weakref(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
157
        MuType_::WeakRef(referent)
qinsoon's avatar
qinsoon committed
158
    }
qinsoon's avatar
qinsoon committed
159
    pub fn uptr(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
160
        MuType_::UPtr(referent)
qinsoon's avatar
qinsoon committed
161
    }
qinsoon's avatar
qinsoon committed
162
    pub fn mustruct_empty(tag: MuName) -> MuType_ {
qinsoon's avatar
qinsoon committed
163 164 165
        let struct_ty_ = StructType_{tys: vec![]};
        STRUCT_TAG_MAP.write().unwrap().insert(tag, struct_ty_);

qinsoon's avatar
qinsoon committed
166
        MuType_::Struct(tag)
qinsoon's avatar
qinsoon committed
167
    }
qinsoon's avatar
qinsoon committed
168
    pub fn mustruct(tag: MuName, list: Vec<P<MuType>>) -> MuType_ {
qinsoon's avatar
qinsoon committed
169
        let struct_ty_ = StructType_{tys: list};
qinsoon's avatar
qinsoon committed
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185

        // 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
186
        MuType_::Struct(tag)
qinsoon's avatar
qinsoon committed
187
    }
qinsoon's avatar
qinsoon committed
188
    pub fn array(ty: P<MuType>, len: usize) -> MuType_ {
qinsoon's avatar
qinsoon committed
189
        MuType_::Array(ty, len)
qinsoon's avatar
qinsoon committed
190
    }
qinsoon's avatar
qinsoon committed
191
    pub fn hybrid(fix_tys: Vec<P<MuType>>, var_ty: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
192
        MuType_::Hybrid(fix_tys, var_ty)
qinsoon's avatar
qinsoon committed
193
    }
qinsoon's avatar
qinsoon committed
194 195
    pub fn void() -> MuType_ {
        MuType_::Void
qinsoon's avatar
qinsoon committed
196
    }
qinsoon's avatar
qinsoon committed
197 198
    pub fn threadref() -> MuType_ {
        MuType_::ThreadRef
qinsoon's avatar
qinsoon committed
199
    }
qinsoon's avatar
qinsoon committed
200 201
    pub fn stackref() -> MuType_ {
        MuType_::StackRef
qinsoon's avatar
qinsoon committed
202
    }
qinsoon's avatar
qinsoon committed
203 204
    pub fn tagref64() -> MuType_ {
        MuType_::Tagref64
qinsoon's avatar
qinsoon committed
205
    }
qinsoon's avatar
qinsoon committed
206
    pub fn vector(ty: P<MuType>, len: usize) -> MuType_ {
qinsoon's avatar
qinsoon committed
207
        MuType_::Vector(ty, len)
qinsoon's avatar
qinsoon committed
208
    }
209
    pub fn funcref(sig: P<MuFuncSig>) -> MuType_ {
qinsoon's avatar
qinsoon committed
210
        MuType_::FuncRef(sig)
qinsoon's avatar
qinsoon committed
211
    }
212
    pub fn ufuncptr(sig: P<MuFuncSig>) -> MuType_ {
qinsoon's avatar
qinsoon committed
213
        MuType_::UFuncPtr(sig)
qinsoon's avatar
qinsoon committed
214 215 216 217
    }
}

/// is a type floating-point type?
qinsoon's avatar
qinsoon committed
218
pub fn is_fp(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
219
    match ty.v {
qinsoon's avatar
qinsoon committed
220
        MuType_::Float | MuType_::Double => true,
qinsoon's avatar
qinsoon committed
221 222 223 224 225
        _ => false
    }
}

/// is a type raw pointer?
qinsoon's avatar
qinsoon committed
226
pub fn is_ptr(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
227
    match ty.v {
qinsoon's avatar
qinsoon committed
228
        MuType_::UPtr(_) | MuType_::UFuncPtr(_) => true,
qinsoon's avatar
qinsoon committed
229 230 231 232 233
        _ => false
    }
}

/// is a type scalar type?
qinsoon's avatar
qinsoon committed
234
pub fn is_scalar(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
235
    match ty.v {
qinsoon's avatar
qinsoon committed
236 237 238 239 240 241 242 243 244 245 246 247
        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
248 249 250 251 252
        _ => false
    }
}

/// is a type traced by the garbage collector?
253
/// Note: An aggregated type is traced if any of its part is traced.
qinsoon's avatar
qinsoon committed
254
pub fn is_traced(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
255
    match ty.v {
qinsoon's avatar
qinsoon committed
256 257 258 259 260 261 262 263 264
        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
265 266
            is_traced(var_ty) ||
            fix_tys.into_iter().map(|ty| is_traced(ty))
267
                .fold(false, |ret, this| ret || this)
qinsoon's avatar
qinsoon committed
268
            },
qinsoon's avatar
qinsoon committed
269
        MuType_::Struct(tag) => {
qinsoon's avatar
qinsoon committed
270 271 272
            let map = STRUCT_TAG_MAP.read().unwrap();
            let struct_ty = map.get(tag).unwrap();
            let ref field_tys = struct_ty.tys;
273

qinsoon's avatar
qinsoon committed
274 275 276 277 278 279 280 281 282
            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
283
pub fn is_native_safe(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
284
    match ty.v {
qinsoon's avatar
qinsoon committed
285 286 287 288 289 290 291 292 293
        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) => {
294
            is_native_safe(var_ty) &&
qinsoon's avatar
qinsoon committed
295 296 297
            fix_tys.into_iter().map(|ty| is_native_safe(&ty))
                .fold(true, |ret, this| ret && this)
        },
qinsoon's avatar
qinsoon committed
298
        MuType_::Struct(tag) => {
qinsoon's avatar
qinsoon committed
299 300 301
            let map = STRUCT_TAG_MAP.read().unwrap();
            let struct_ty = map.get(tag).unwrap();
            let ref field_tys = struct_ty.tys;
302

qinsoon's avatar
qinsoon committed
303 304 305 306
            field_tys.into_iter().map(|ty| is_native_safe(&ty))
                .fold(true, |ret, this| ret && this)
        },
        _ => false
qinsoon's avatar
qinsoon committed
307 308 309
    }
}

310
pub fn get_referent_ty(ty: &MuType) -> Option<P<MuType>> {
qinsoon's avatar
qinsoon committed
311 312 313 314
    match ty.v {
        MuType_::Ref(ref referent)
        | MuType_::IRef(ref referent)
        | MuType_::WeakRef(ref referent) => Some(referent.clone()),
315 316 317 318
        _ => None
    }
}

qinsoon's avatar
qinsoon committed
319 320 321 322 323 324 325 326 327
macro_rules! is_type (
    ($e:expr, $p:pat) => (
        match $e {
            $p => true,
            _ => false
        }
    )
);

qinsoon's avatar
qinsoon committed
328
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
qinsoon's avatar
qinsoon committed
329
pub struct MuFuncSig {
qinsoon's avatar
qinsoon committed
330 331
    pub id: MuID,
    pub name: Option<MuName>,
qinsoon's avatar
qinsoon committed
332 333
    pub ret_tys : Vec<P<MuType>>,
    pub arg_tys: Vec<P<MuType>>
334 335
}

336
impl fmt::Display for MuFuncSig {
337
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338
        write!(f, "[{}] -> [{}]", vector_as_str(&self.ret_tys), vector_as_str(&self.arg_tys))
339 340
    }
}