types.rs 14.5 KB
Newer Older
qinsoon's avatar
qinsoon committed
1 2 3
use ptr::P;
use ir::*;

qinsoon's avatar
qinsoon committed
4
use utils::POINTER_SIZE;
qinsoon's avatar
qinsoon committed
5
use utils::vec_utils;
6 7

use std::fmt;
qinsoon's avatar
qinsoon committed
8 9
use std::collections::HashMap;
use std::sync::RwLock;
qinsoon's avatar
qinsoon committed
10

qinsoon's avatar
qinsoon committed
11 12 13 14
lazy_static! {
    pub static ref ADDRESS_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::int(POINTER_SIZE * 8))
    );
15 16 17 18 19 20 21 22

    pub static ref UINT8_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::int(8))
    );

    pub static ref UINT16_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::int(16))
    );
qinsoon's avatar
qinsoon committed
23 24 25 26 27 28 29 30 31 32 33 34
    
    pub static ref UINT32_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::int(32))
    );
    
    pub static ref UINT64_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::int(64))
    );
    
    pub static ref DOUBLE_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::double())
    );
35 36 37 38

    pub static ref VOID_TYPE : P<MuType> = P(
        MuType::new(new_internal_id(), MuType_::void())
    );
qinsoon's avatar
qinsoon committed
39 40 41
    
    pub static ref INTERNAL_TYPES : Vec<P<MuType>> = vec![
        ADDRESS_TYPE.clone(),
qinsoon's avatar
qinsoon committed
42 43
        UINT8_TYPE.clone(),
        UINT16_TYPE.clone(),
qinsoon's avatar
qinsoon committed
44 45 46 47 48 49
        UINT32_TYPE.clone(),
        UINT64_TYPE.clone(),
        DOUBLE_TYPE.clone()
    ];    
}

qinsoon's avatar
qinsoon committed
50
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
51
pub struct MuType {
52
    pub hdr: MuEntityHeader,
qinsoon's avatar
qinsoon committed
53 54 55 56 57 58
    pub v: MuType_
}

impl MuType {
    pub fn new(id: MuID, v: MuType_) -> MuType {
        MuType {
59
            hdr: MuEntityHeader::unnamed(id),
qinsoon's avatar
qinsoon committed
60 61 62
            v: v
        }
    }
qinsoon's avatar
qinsoon committed
63 64 65 66 67 68 69 70 71 72 73

    pub fn get_referenced_ty(&self) -> Option<P<MuType>> {
        use types::MuType_::*;
        match self.v {
            Ref(ref ty)
            | IRef(ref ty)
            | WeakRef(ref ty)
            | UPtr(ref ty) => Some(ty.clone()),
            _ => None
        }
    }
qinsoon's avatar
qinsoon committed
74
}
qinsoon's avatar
qinsoon committed
75

76 77
pub type StructTag = MuName;
pub type HybridTag = MuName;
qinsoon's avatar
qinsoon committed
78
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
79
pub enum MuType_ {
qinsoon's avatar
qinsoon committed
80
    /// int <length>
qinsoon's avatar
qinsoon committed
81
    Int          (usize),
qinsoon's avatar
qinsoon committed
82
    /// float
qinsoon's avatar
qinsoon committed
83
    Float,
qinsoon's avatar
qinsoon committed
84
    /// double
qinsoon's avatar
qinsoon committed
85
    Double,
86

qinsoon's avatar
qinsoon committed
87
    /// ref<T>
qinsoon's avatar
qinsoon committed
88
    Ref          (P<MuType>),    // Box is needed for non-recursive enum
qinsoon's avatar
qinsoon committed
89
    /// iref<T>: internal reference
qinsoon's avatar
qinsoon committed
90
    IRef         (P<MuType>),
qinsoon's avatar
qinsoon committed
91
    /// weakref<T>
qinsoon's avatar
qinsoon committed
92
    WeakRef      (P<MuType>),
93

qinsoon's avatar
qinsoon committed
94
    /// uptr<T>: unsafe pointer
qinsoon's avatar
qinsoon committed
95
    UPtr         (P<MuType>),
96

qinsoon's avatar
qinsoon committed
97
    /// struct<T1 T2 ...>
98
    Struct       (StructTag),
99

qinsoon's avatar
qinsoon committed
100
    /// array<T length>
qinsoon's avatar
qinsoon committed
101
    Array        (P<MuType>, usize),
102

qinsoon's avatar
qinsoon committed
103
    /// hybrid<F1 F2 ... V>: a hybrid of fixed length parts and a variable length part
104
    Hybrid       (HybridTag),
105

qinsoon's avatar
qinsoon committed
106
    /// void
qinsoon's avatar
qinsoon committed
107
    Void,
108

qinsoon's avatar
qinsoon committed
109
    /// threadref
qinsoon's avatar
qinsoon committed
110
    ThreadRef,
qinsoon's avatar
qinsoon committed
111
    /// stackref
qinsoon's avatar
qinsoon committed
112
    StackRef,
113

qinsoon's avatar
qinsoon committed
114
    /// tagref64: hold a double or an int or an ref<void>
qinsoon's avatar
qinsoon committed
115
    Tagref64,
116

qinsoon's avatar
qinsoon committed
117
    /// vector<T length>
qinsoon's avatar
qinsoon committed
118
    Vector       (P<MuType>, usize),
119

qinsoon's avatar
qinsoon committed
120
    /// funcref<@sig>
121
    FuncRef      (P<MuFuncSig>),
122

qinsoon's avatar
qinsoon committed
123
    /// ufuncptr<@sig>
124
    UFuncPtr     (P<MuFuncSig>),
qinsoon's avatar
qinsoon committed
125 126
}

qinsoon's avatar
qinsoon committed
127 128 129 130 131 132
impl fmt::Display for MuType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.v)        
    }
}

133
impl fmt::Display for MuType_ {
134 135
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
qinsoon's avatar
qinsoon committed
136 137 138
            &MuType_::Int(n)                          => write!(f, "int<{}>", n),
            &MuType_::Float                           => write!(f, "float"),
            &MuType_::Double                          => write!(f, "double"),
139 140 141 142 143
            &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
144 145 146 147
            &MuType_::Void                            => write!(f, "void"),
            &MuType_::ThreadRef                       => write!(f, "threadref"),
            &MuType_::StackRef                        => write!(f, "stackref"),
            &MuType_::Tagref64                        => write!(f, "tagref64"),
148 149 150
            &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),
151 152
            &MuType_::Struct(ref tag)                 => write!(f, "{}(struct)", tag),
            &MuType_::Hybrid(ref tag)                 => write!(f, "{}(hybrid)", tag)
153 154 155 156
        }
    }
}

qinsoon's avatar
qinsoon committed
157
lazy_static! {
qinsoon's avatar
qinsoon committed
158
    /// storing a map from MuName to StructType_
159 160 161
    pub static ref STRUCT_TAG_MAP : RwLock<HashMap<StructTag, StructType_>> = RwLock::new(HashMap::new());
    /// storing a map from MuName to HybridType_
    pub static ref HYBRID_TAG_MAP : RwLock<HashMap<HybridTag, HybridType_>> = RwLock::new(HashMap::new());
qinsoon's avatar
qinsoon committed
162 163
}

qinsoon's avatar
qinsoon committed
164
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
165
pub struct StructType_ {
qinsoon's avatar
qinsoon committed
166
    tys: Vec<P<MuType>>
qinsoon's avatar
qinsoon committed
167 168
}

169
impl fmt::Display for StructType_ {
170
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
qinsoon's avatar
qinsoon committed
171 172 173
        write!(f, "struct<").unwrap();
        for i in 0..self.tys.len() {
            let ty = &self.tys[i];
174
            write!(f, "{}", ty).unwrap();
qinsoon's avatar
qinsoon committed
175 176 177
            if i != self.tys.len() - 1 {
                write!(f, " ").unwrap();
            }
178
        }
qinsoon's avatar
qinsoon committed
179
        write!(f, ">")
180
    }
181 182
}

qinsoon's avatar
qinsoon committed
183
impl StructType_ {
184 185 186 187
    // The IR builder needs to create StructType objects, too.
    pub fn new(tys: Vec<P<MuType>>) -> StructType_ {
        StructType_ { tys: tys }
    }
qinsoon's avatar
qinsoon committed
188
    pub fn set_tys(&mut self, mut list: Vec<P<MuType>>) {
qinsoon's avatar
qinsoon committed
189
        self.tys.clear();
qinsoon's avatar
qinsoon committed
190
        self.tys.append(&mut list);
qinsoon's avatar
qinsoon committed
191
    }
qinsoon's avatar
qinsoon committed
192
    
qinsoon's avatar
qinsoon committed
193
    pub fn get_tys(&self) -> &Vec<P<MuType>> {
qinsoon's avatar
qinsoon committed
194 195
        &self.tys
    }
qinsoon's avatar
qinsoon committed
196 197
}

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
pub struct HybridType_ {
    fix_tys: Vec<P<MuType>>,
    var_ty : P<MuType>
}

impl HybridType_ {
    pub fn new(fix_tys: Vec<P<MuType>>, var_ty: P<MuType>) -> HybridType_ {
        HybridType_ {fix_tys: fix_tys, var_ty: var_ty}
    }

    pub fn set_tys(&mut self, mut fix_tys: Vec<P<MuType>>, var_ty: P<MuType>) {
        self.fix_tys.clear();
        self.fix_tys.append(&mut fix_tys);

        self.var_ty = var_ty;
    }

    pub fn get_fix_tys(&self) -> &Vec<P<MuType>> {
        &self.fix_tys
    }

    pub fn get_var_ty(&self) -> &P<MuType> {
        &self.var_ty
    }
}

impl fmt::Display for HybridType_ {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "hybrid<").unwrap();
        for i in 0..self.fix_tys.len() {
            let ty = &self.fix_tys[i];
            write!(f, "{}", ty).unwrap();
            if i != self.fix_tys.len() - 1 {
                write!(f, " ").unwrap();
            }
        }
        write!(f, "|{}>", self.var_ty)
    }
}

qinsoon's avatar
qinsoon committed
239 240 241
impl MuType_ {
    pub fn int(len: usize) -> MuType_ {
        MuType_::Int(len)
qinsoon's avatar
qinsoon committed
242
    }
qinsoon's avatar
qinsoon committed
243 244
    pub fn float() -> MuType_ {
        MuType_::Float
qinsoon's avatar
qinsoon committed
245
    }
qinsoon's avatar
qinsoon committed
246 247
    pub fn double() -> MuType_ {
        MuType_::Double
qinsoon's avatar
qinsoon committed
248
    }
qinsoon's avatar
qinsoon committed
249
    pub fn muref(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
250
        MuType_::Ref(referent)
qinsoon's avatar
qinsoon committed
251
    }
qinsoon's avatar
qinsoon committed
252
    pub fn iref(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
253
        MuType_::IRef(referent)
qinsoon's avatar
qinsoon committed
254
    }
qinsoon's avatar
qinsoon committed
255
    pub fn weakref(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
256
        MuType_::WeakRef(referent)
qinsoon's avatar
qinsoon committed
257
    }
qinsoon's avatar
qinsoon committed
258
    pub fn uptr(referent: P<MuType>) -> MuType_ {
qinsoon's avatar
qinsoon committed
259
        MuType_::UPtr(referent)
qinsoon's avatar
qinsoon committed
260
    }
qinsoon's avatar
qinsoon committed
261
    pub fn mustruct_empty(tag: MuName) -> MuType_ {
qinsoon's avatar
qinsoon committed
262
        let struct_ty_ = StructType_{tys: vec![]};
263
        STRUCT_TAG_MAP.write().unwrap().insert(tag.clone(), struct_ty_);
qinsoon's avatar
qinsoon committed
264

qinsoon's avatar
qinsoon committed
265
        MuType_::Struct(tag)
qinsoon's avatar
qinsoon committed
266
    }
267 268 269 270 271 272 273 274 275 276 277 278
    pub fn mustruct_put(tag: MuName, mut list: Vec<P<MuType>>) {
        let mut map_guard = STRUCT_TAG_MAP.write().unwrap();

        match map_guard.get_mut(&tag) {
            Some(struct_ty_) => {
                struct_ty_.tys.clear();
                struct_ty_.tys.append(&mut list);
            },
            None => panic!("call mustruct_empty() to create an empty struct before mustruct_put()")
        }
    }
    pub fn mustruct(tag: StructTag, list: Vec<P<MuType>>) -> MuType_ {
qinsoon's avatar
qinsoon committed
279
        let struct_ty_ = StructType_{tys: list};
qinsoon's avatar
qinsoon committed
280 281 282

        // if there is an attempt to use a same tag for different struct,
        // we panic
283
        match STRUCT_TAG_MAP.read().unwrap().get(&tag) {
qinsoon's avatar
qinsoon committed
284 285
            Some(old_struct_ty_) => {
                if struct_ty_ != *old_struct_ty_ {
286 287
                    panic!("trying to insert {} as {}, while the old struct is defined as {}",
                            struct_ty_, tag, old_struct_ty_)
qinsoon's avatar
qinsoon committed
288 289 290 291 292
                }
            },
            None => {}
        }
        // otherwise, store the tag
293
        STRUCT_TAG_MAP.write().unwrap().insert(tag.clone(), struct_ty_);
qinsoon's avatar
qinsoon committed
294

qinsoon's avatar
qinsoon committed
295
        MuType_::Struct(tag)
qinsoon's avatar
qinsoon committed
296
    }
qinsoon's avatar
qinsoon committed
297
    pub fn array(ty: P<MuType>, len: usize) -> MuType_ {
qinsoon's avatar
qinsoon committed
298
        MuType_::Array(ty, len)
qinsoon's avatar
qinsoon committed
299
    }
300 301 302 303 304 305
    pub fn hybrid_empty(tag: HybridTag) -> MuType_ {
        let hybrid_ty_ = HybridType_{fix_tys: vec![], var_ty: VOID_TYPE.clone()};
        HYBRID_TAG_MAP.write().unwrap().insert(tag.clone(), hybrid_ty_);

        MuType_::Hybrid(tag)
    }
qinsoon's avatar
qinsoon committed
306 307 308 309 310 311 312 313 314 315 316 317 318
    pub fn hybrid_put(tag: HybridTag, mut fix_tys: Vec<P<MuType>>, var_ty: P<MuType>) {
        let mut map_guard = HYBRID_TAG_MAP.write().unwrap();

        match map_guard.get_mut(&tag) {
            Some(hybrid_ty_) => {
                hybrid_ty_.fix_tys.clear();
                hybrid_ty_.fix_tys.append(&mut fix_tys);

                hybrid_ty_.var_ty = var_ty;
            },
            None => panic!("call hybrid_empty() to create an empty struct before hybrid_put()")
        }
    }
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
    pub fn hybrid(tag: HybridTag, fix_tys: Vec<P<MuType>>, var_ty: P<MuType>) -> MuType_ {
        let hybrid_ty_ = HybridType_{fix_tys: fix_tys, var_ty: var_ty};


        match HYBRID_TAG_MAP.read().unwrap().get(&tag) {
            Some(old_hybrid_ty_) => {
                if hybrid_ty_ != *old_hybrid_ty_ {
                    panic!("trying to insert {} as {}, while the old hybrid is defined as {}",
                           hybrid_ty_, tag, old_hybrid_ty_);
                }
            },
            None => {}
        }

        HYBRID_TAG_MAP.write().unwrap().insert(tag.clone(), hybrid_ty_);

        MuType_::Hybrid(tag)
qinsoon's avatar
qinsoon committed
336
    }
qinsoon's avatar
qinsoon committed
337 338
    pub fn void() -> MuType_ {
        MuType_::Void
qinsoon's avatar
qinsoon committed
339
    }
qinsoon's avatar
qinsoon committed
340 341
    pub fn threadref() -> MuType_ {
        MuType_::ThreadRef
qinsoon's avatar
qinsoon committed
342
    }
qinsoon's avatar
qinsoon committed
343 344
    pub fn stackref() -> MuType_ {
        MuType_::StackRef
qinsoon's avatar
qinsoon committed
345
    }
qinsoon's avatar
qinsoon committed
346 347
    pub fn tagref64() -> MuType_ {
        MuType_::Tagref64
qinsoon's avatar
qinsoon committed
348
    }
qinsoon's avatar
qinsoon committed
349
    pub fn vector(ty: P<MuType>, len: usize) -> MuType_ {
qinsoon's avatar
qinsoon committed
350
        MuType_::Vector(ty, len)
qinsoon's avatar
qinsoon committed
351
    }
352
    pub fn funcref(sig: P<MuFuncSig>) -> MuType_ {
qinsoon's avatar
qinsoon committed
353
        MuType_::FuncRef(sig)
qinsoon's avatar
qinsoon committed
354
    }
355
    pub fn ufuncptr(sig: P<MuFuncSig>) -> MuType_ {
qinsoon's avatar
qinsoon committed
356
        MuType_::UFuncPtr(sig)
qinsoon's avatar
qinsoon committed
357 358 359 360
    }
}

/// is a type floating-point type?
qinsoon's avatar
qinsoon committed
361
pub fn is_fp(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
362
    match ty.v {
qinsoon's avatar
qinsoon committed
363
        MuType_::Float | MuType_::Double => true,
qinsoon's avatar
qinsoon committed
364 365 366 367 368
        _ => false
    }
}

/// is a type raw pointer?
qinsoon's avatar
qinsoon committed
369
pub fn is_ptr(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
370
    match ty.v {
qinsoon's avatar
qinsoon committed
371
        MuType_::UPtr(_) | MuType_::UFuncPtr(_) => true,
qinsoon's avatar
qinsoon committed
372 373 374 375 376
        _ => false
    }
}

/// is a type scalar type?
qinsoon's avatar
qinsoon committed
377
pub fn is_scalar(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
378
    match ty.v {
qinsoon's avatar
qinsoon committed
379 380 381 382 383 384 385 386 387 388 389 390
        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
391 392 393 394 395
        _ => false
    }
}

/// is a type traced by the garbage collector?
396
/// Note: An aggregated type is traced if any of its part is traced.
qinsoon's avatar
qinsoon committed
397
pub fn is_traced(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
398
    match ty.v {
qinsoon's avatar
qinsoon committed
399 400 401 402 403 404 405 406
        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,
407 408 409 410 411 412 413
        MuType_::Hybrid(ref tag) => {
            let map = HYBRID_TAG_MAP.read().unwrap();
            let hybrid_ty = map.get(tag).unwrap();

            let ref fix_tys = hybrid_ty.fix_tys;
            let ref var_ty  = hybrid_ty.var_ty;

qinsoon's avatar
qinsoon committed
414 415
            is_traced(var_ty) ||
            fix_tys.into_iter().map(|ty| is_traced(ty))
416
                .fold(false, |ret, this| ret || this)
qinsoon's avatar
qinsoon committed
417
            },
418
        MuType_::Struct(ref tag) => {
qinsoon's avatar
qinsoon committed
419 420 421
            let map = STRUCT_TAG_MAP.read().unwrap();
            let struct_ty = map.get(tag).unwrap();
            let ref field_tys = struct_ty.tys;
422

qinsoon's avatar
qinsoon committed
423 424 425 426 427 428 429 430 431
            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
432
pub fn is_native_safe(ty: &MuType) -> bool {
qinsoon's avatar
qinsoon committed
433
    match ty.v {
qinsoon's avatar
qinsoon committed
434 435 436 437 438 439 440 441
        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,
442 443 444 445 446 447 448
        MuType_::Hybrid(ref tag) => {
            let map = HYBRID_TAG_MAP.read().unwrap();
            let hybrid_ty = map.get(tag).unwrap();

            let ref fix_tys = hybrid_ty.fix_tys;
            let ref var_ty  = hybrid_ty.var_ty;

449
            is_native_safe(var_ty) &&
qinsoon's avatar
qinsoon committed
450 451 452
            fix_tys.into_iter().map(|ty| is_native_safe(&ty))
                .fold(true, |ret, this| ret && this)
        },
453
        MuType_::Struct(ref tag) => {
qinsoon's avatar
qinsoon committed
454 455 456
            let map = STRUCT_TAG_MAP.read().unwrap();
            let struct_ty = map.get(tag).unwrap();
            let ref field_tys = struct_ty.tys;
457

qinsoon's avatar
qinsoon committed
458 459 460 461
            field_tys.into_iter().map(|ty| is_native_safe(&ty))
                .fold(true, |ret, this| ret && this)
        },
        _ => false
qinsoon's avatar
qinsoon committed
462 463 464
    }
}

465
pub fn get_referent_ty(ty: &MuType) -> Option<P<MuType>> {
qinsoon's avatar
qinsoon committed
466 467 468 469
    match ty.v {
        MuType_::Ref(ref referent)
        | MuType_::IRef(ref referent)
        | MuType_::WeakRef(ref referent) => Some(referent.clone()),
470 471 472 473
        _ => None
    }
}

qinsoon's avatar
qinsoon committed
474 475 476 477 478 479 480 481 482
macro_rules! is_type (
    ($e:expr, $p:pat) => (
        match $e {
            $p => true,
            _ => false
        }
    )
);

483 484
pub type CFuncSig = MuFuncSig;

qinsoon's avatar
qinsoon committed
485
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
qinsoon's avatar
qinsoon committed
486
pub struct MuFuncSig {
487
    pub hdr: MuEntityHeader,
qinsoon's avatar
qinsoon committed
488 489
    pub ret_tys : Vec<P<MuType>>,
    pub arg_tys: Vec<P<MuType>>
490 491
}

492
impl fmt::Display for MuFuncSig {
493
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
qinsoon's avatar
qinsoon committed
494
        write!(f, "[{}] -> [{}]", vec_utils::as_str(&self.ret_tys), vec_utils::as_str(&self.arg_tys))
495 496
    }
}