WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

types.rs 9.69 KB
Newer Older
qinsoon's avatar
qinsoon committed
1
use ast::ptr::P;
qinsoon's avatar
qinsoon committed
2
use ast::ir::*;
qinsoon's avatar
qinsoon committed
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,
qinsoon's avatar
qinsoon committed
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>),
qinsoon's avatar
qinsoon committed
41

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

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

qinsoon's avatar
qinsoon committed
48
    /// array<T length>
qinsoon's avatar
qinsoon committed
49
    Array        (P<MuType>, usize),
qinsoon's avatar
qinsoon committed
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>),
qinsoon's avatar
qinsoon committed
53

qinsoon's avatar
qinsoon committed
54
    /// void
qinsoon's avatar
qinsoon committed
55
    Void,
qinsoon's avatar
qinsoon committed
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,
qinsoon's avatar
qinsoon committed
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,
qinsoon's avatar
qinsoon committed
64

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

qinsoon's avatar
qinsoon committed
68
    /// funcref<@sig>
69
    FuncRef      (P<MuFuncSig>),
qinsoon's avatar
qinsoon committed
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),
qinsoon's avatar
qinsoon committed
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, ">")
qinsoon's avatar
qinsoon committed
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?
qinsoon's avatar
qinsoon committed
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))
qinsoon's avatar
qinsoon committed
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;
qinsoon's avatar
qinsoon committed
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) => {
qinsoon's avatar
qinsoon committed
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;
qinsoon's avatar
qinsoon committed
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 ret_tys : Vec<P<MuType>>,
    pub arg_tys: Vec<P<MuType>>
332
333
}

334
impl fmt::Display for MuFuncSig {
335
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
336
        write!(f, "[{}] -> [{}]", vector_as_str(&self.ret_tys), vector_as_str(&self.arg_tys))
qinsoon's avatar
qinsoon committed
337
338
    }
}