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.35 KB
Newer Older
1
use std::fmt;
qinsoon's avatar
qinsoon committed
2

qinsoon's avatar
qinsoon committed
3
use ast::ptr::P;
qinsoon's avatar
qinsoon committed
4
use ast::ir::*;
qinsoon's avatar
qinsoon committed
5
6
use std::collections::HashMap;
use std::sync::RwLock;
qinsoon's avatar
qinsoon committed
7

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

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

59
impl fmt::Display for MuType_ {
60
61
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
qinsoon's avatar
qinsoon committed
62
63
64
            &MuType_::Int(n)                          => write!(f, "int<{}>", n),
            &MuType_::Float                           => write!(f, "float"),
            &MuType_::Double                          => write!(f, "double"),
65
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),
            &MuType_::Hybrid(ref fix_tys, ref var_ty) => write!(f, "hybrid<[{}] {}>", type_vector_str(fix_tys), var_ty), 
qinsoon's avatar
qinsoon committed
71
72
73
74
            &MuType_::Void                            => write!(f, "void"),
            &MuType_::ThreadRef                       => write!(f, "threadref"),
            &MuType_::StackRef                        => write!(f, "stackref"),
            &MuType_::Tagref64                        => write!(f, "tagref64"),
75
76
77
            &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
78
            &MuType_::Struct(tag)                     => write!(f, "{}(struct)", tag)
79
80
81
82
        }
    }
}

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

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

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

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

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

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

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

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

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

/// is a type scalar type?
qinsoon's avatar
qinsoon committed
211
pub fn is_scalar(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
212
    match *ty {
qinsoon's avatar
qinsoon committed
213
214
215
216
217
218
219
220
221
222
223
224
        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
225
226
227
228
229
230
        _ => 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
231
pub fn is_traced(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
232
    match *ty {
qinsoon's avatar
qinsoon committed
233
234
235
236
237
238
239
240
241
        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
242
243
244
245
            is_traced(var_ty) ||
            fix_tys.into_iter().map(|ty| is_traced(ty))
                .fold(false, |ret, this| ret || this) 
            },
qinsoon's avatar
qinsoon committed
246
        MuType_::Struct(tag) => {
qinsoon's avatar
qinsoon committed
247
248
249
250
251
252
253
254
255
256
257
258
259
            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
260
pub fn is_native_safe(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
261
    match *ty {
qinsoon's avatar
qinsoon committed
262
263
264
265
266
267
268
269
270
        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
271
272
273
274
            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
275
        MuType_::Struct(tag) => {
qinsoon's avatar
qinsoon committed
276
277
278
279
280
281
282
283
            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
284
285
286
287
288
289
290
291
292
293
294
295
    }
}

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

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

302
impl fmt::Display for MuFuncSig {
303
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
304
        write!(f, "[{}] -> [{}]", type_vector_str(&self.ret_tys), type_vector_str(&self.arg_tys))
305
    }    
306
307
308
309
310
311
312
313
314
315
316
}

fn type_vector_str(vec: &Vec<P<MuType>>) -> String {
    let mut ret = String::new();
    for i in 0..vec.len() {
        ret.push_str(fmt::format(format_args!("{}", vec[i])).as_str());
        if i != vec.len() - 1 {
            ret.push_str(", ");
        }
    }
    ret
qinsoon's avatar
qinsoon committed
317
}