goscript_vm/
value.rs

1//#![allow(dead_code)]
2use super::gc::{GcWeak, GcoVec};
3use super::instruction::{Opcode, ValueType};
4use super::metadata::*;
5pub use super::objects::*;
6use super::stack::Stack;
7use ordered_float;
8use std::cell::{Cell, RefCell};
9use std::cmp::Ordering;
10use std::collections::VecDeque;
11use std::fmt::{self, Display};
12use std::hash::{Hash, Hasher};
13use std::num::Wrapping;
14use std::rc::Rc;
15use std::result;
16
17type F32 = ordered_float::OrderedFloat<f32>;
18type F64 = ordered_float::OrderedFloat<f64>;
19pub type IRC = i32;
20pub type RCount = Cell<IRC>;
21pub type RCQueue = VecDeque<IRC>;
22
23#[inline]
24pub fn rcount_mark_and_queue(rc: &RCount, queue: &mut RCQueue) {
25    let i = rc.get();
26    if i <= 0 {
27        queue.push_back(i);
28        rc.set(1);
29    }
30}
31
32macro_rules! unwrap_gos_val {
33    ($name:tt, $self_:ident) => {
34        if let GosValue::$name(k) = $self_ {
35            k
36        } else {
37            unreachable!();
38        }
39    };
40}
41
42macro_rules! union_op_wrap {
43    ($a:ident, $b:ident, $name:tt, $op:tt) => {
44        GosValue64{
45            data: V64Union {
46            $name: (Wrapping($a.data.$name) $op Wrapping($b.data.$name)).0,
47        }}
48    };
49}
50
51macro_rules! union_op {
52    ($a:ident, $b:ident, $name:tt, $op:tt) => {
53        GosValue64{
54            data: V64Union {
55            $name: $a.data.$name $op $b.data.$name,
56        }}
57    };
58}
59
60macro_rules! union_shift {
61    ($a:ident, $b:ident, $name:tt, $op:tt) => {
62        GosValue64 {
63            data: V64Union {
64                $name: $a.data.$name.$op($b).unwrap_or(0),
65            },
66        }
67    };
68}
69
70macro_rules! union_cmp {
71    ($a:ident, $b:ident, $name:tt, $op:tt) => {
72        $a.data.$name $op $b.data.$name
73    };
74}
75
76macro_rules! binary_op_int_float {
77    ($t:ident, $a:ident, $b:ident, $op:tt) => {
78        match $t {
79            ValueType::Int => union_op_wrap!($a, $b, int, $op),
80            ValueType::Int8 => union_op_wrap!($a, $b, int8, $op),
81            ValueType::Int16 => union_op_wrap!($a, $b, int16, $op),
82            ValueType::Int32 => union_op_wrap!($a, $b, int32, $op),
83            ValueType::Int64 => union_op_wrap!($a, $b, int64, $op),
84            ValueType::Uint => union_op_wrap!($a, $b, uint, $op),
85            ValueType::Uint8 => union_op_wrap!($a, $b, uint8, $op),
86            ValueType::Uint16 => union_op_wrap!($a, $b, uint16, $op),
87            ValueType::Uint32 => union_op_wrap!($a, $b, uint32, $op),
88            ValueType::Uint64 => union_op_wrap!($a, $b, uint64, $op),
89            ValueType::Float32 => union_op!($a, $b, float32, $op),
90            ValueType::Float64 => union_op!($a, $b, float64, $op),
91            _ => unreachable!(),
92        }
93    };
94}
95
96macro_rules! binary_op_int_no_wrap {
97    ($t:ident, $a:ident, $b:ident, $op:tt) => {
98        match $t {
99            ValueType::Int => union_op!($a, $b, int, $op),
100            ValueType::Int8 => union_op!($a, $b, int8, $op),
101            ValueType::Int16 => union_op!($a, $b, int16, $op),
102            ValueType::Int32 => union_op!($a, $b, int32, $op),
103            ValueType::Int64 => union_op!($a, $b, int64, $op),
104            ValueType::Uint => union_op!($a, $b, uint, $op),
105            ValueType::Uint8 => union_op!($a, $b, uint8, $op),
106            ValueType::Uint16 => union_op!($a, $b, uint16, $op),
107            ValueType::Uint32 => union_op!($a, $b, uint32, $op),
108            ValueType::Uint64 => union_op!($a, $b, uint64, $op),
109            _ => unreachable!(),
110        }
111    };
112}
113
114macro_rules! cmp_bool_int_float {
115    ($t:ident, $a:ident, $b:ident, $op:tt) => {
116        match $t {
117            ValueType::Bool => union_cmp!($a, $b, ubool, $op),
118            ValueType::Int => union_cmp!($a, $b, int, $op),
119            ValueType::Int8 => union_cmp!($a, $b, int8, $op),
120            ValueType::Int16 => union_cmp!($a, $b, int16, $op),
121            ValueType::Int32 => union_cmp!($a, $b, int32, $op),
122            ValueType::Int64 => union_cmp!($a, $b, int64, $op),
123            ValueType::Uint => union_cmp!($a, $b, uint, $op),
124            ValueType::Uint8 => union_cmp!($a, $b, uint8, $op),
125            ValueType::Uint16 => union_cmp!($a, $b, uint16, $op),
126            ValueType::Uint32 => union_cmp!($a, $b, uint32, $op),
127            ValueType::Uint64 => union_cmp!($a, $b, uint64, $op),
128            ValueType::Float32 => union_cmp!($a, $b, float32, $op),
129            ValueType::Float64 => union_cmp!($a, $b, float64, $op),
130            _ => unreachable!(),
131        }
132    };
133}
134
135macro_rules! cmp_int_float {
136    ($t:ident, $a:ident, $b:ident, $op:tt) => {
137        match $t {
138            ValueType::Int => union_cmp!($a, $b, int, $op),
139            ValueType::Int8 => union_cmp!($a, $b, int8, $op),
140            ValueType::Int16 => union_cmp!($a, $b, int16, $op),
141            ValueType::Int32 => union_cmp!($a, $b, int32, $op),
142            ValueType::Int64 => union_cmp!($a, $b, int64, $op),
143            ValueType::Uint => union_cmp!($a, $b, uint, $op),
144            ValueType::Uint8 => union_cmp!($a, $b, uint8, $op),
145            ValueType::Uint16 => union_cmp!($a, $b, uint16, $op),
146            ValueType::Uint32 => union_cmp!($a, $b, uint32, $op),
147            ValueType::Uint64 => union_cmp!($a, $b, uint64, $op),
148            ValueType::Float32 => union_cmp!($a, $b, float32, $op),
149            ValueType::Float64 => union_cmp!($a, $b, float64, $op),
150            _ => unreachable!(),
151        }
152    };
153}
154
155macro_rules! shift_int {
156    ($t:ident, $a:ident, $b:ident, $op:tt) => {
157        *$a = match $t {
158            ValueType::Int => union_shift!($a, $b, int, $op),
159            ValueType::Int8 => union_shift!($a, $b, int8, $op),
160            ValueType::Int16 => union_shift!($a, $b, int16, $op),
161            ValueType::Int32 => union_shift!($a, $b, int32, $op),
162            ValueType::Int64 => union_shift!($a, $b, int64, $op),
163            ValueType::Uint => union_shift!($a, $b, uint, $op),
164            ValueType::Uint8 => union_shift!($a, $b, uint8, $op),
165            ValueType::Uint16 => union_shift!($a, $b, uint16, $op),
166            ValueType::Uint32 => union_shift!($a, $b, uint32, $op),
167            ValueType::Uint64 => union_shift!($a, $b, uint64, $op),
168            _ => unreachable!(),
169        };
170    };
171}
172
173macro_rules! convert_to_int {
174    ($val:expr, $vt:expr, $d_type:tt, $typ:tt) => {{
175        unsafe {
176            match $vt {
177                ValueType::Uint => $val.data.$d_type = $val.data.uint as $typ,
178                ValueType::Uint8 => $val.data.$d_type = $val.data.uint8 as $typ,
179                ValueType::Uint16 => $val.data.$d_type = $val.data.uint16 as $typ,
180                ValueType::Uint32 => $val.data.$d_type = $val.data.uint32 as $typ,
181                ValueType::Uint64 => $val.data.$d_type = $val.data.uint64 as $typ,
182                ValueType::Int => $val.data.$d_type = $val.data.int as $typ,
183                ValueType::Int8 => $val.data.$d_type = $val.data.int8 as $typ,
184                ValueType::Int16 => $val.data.$d_type = $val.data.int16 as $typ,
185                ValueType::Int32 => $val.data.$d_type = $val.data.int32 as $typ,
186                ValueType::Int64 => $val.data.$d_type = $val.data.int64 as $typ,
187                ValueType::Float32 => $val.data.$d_type = f32::from($val.data.float32) as $typ,
188                ValueType::Float64 => $val.data.$d_type = f64::from($val.data.float64) as $typ,
189                _ => unreachable!(),
190            }
191        }
192    }};
193}
194
195macro_rules! convert_to_float {
196    ($val:expr, $vt:expr, $d_type:tt, $f_type:tt, $typ:tt) => {{
197        unsafe {
198            match $vt {
199                ValueType::Uint => $val.data.$d_type = $f_type::from($val.data.uint as $typ),
200                ValueType::Uint8 => $val.data.$d_type = $f_type::from($val.data.uint8 as $typ),
201                ValueType::Uint16 => $val.data.$d_type = $f_type::from($val.data.uint16 as $typ),
202                ValueType::Uint32 => $val.data.$d_type = $f_type::from($val.data.uint32 as $typ),
203                ValueType::Uint64 => $val.data.$d_type = $f_type::from($val.data.uint64 as $typ),
204                ValueType::Int => $val.data.$d_type = $f_type::from($val.data.int as $typ),
205                ValueType::Int8 => $val.data.$d_type = $f_type::from($val.data.int8 as $typ),
206                ValueType::Int16 => $val.data.$d_type = $f_type::from($val.data.int16 as $typ),
207                ValueType::Int32 => $val.data.$d_type = $f_type::from($val.data.int32 as $typ),
208                ValueType::Int64 => $val.data.$d_type = $f_type::from($val.data.int64 as $typ),
209                ValueType::Float32 => {
210                    $val.data.$d_type = $f_type::from(f32::from($val.data.float32) as $typ)
211                }
212                ValueType::Float64 => {
213                    $val.data.$d_type = $f_type::from(f64::from($val.data.float64) as $typ)
214                }
215                _ => unreachable!(),
216            }
217        }
218    }};
219}
220
221pub type RuntimeResult<T> = result::Result<T, String>;
222
223pub type EmptyResult = RuntimeResult<()>;
224
225pub type RtValueResult = RuntimeResult<GosValue>;
226
227// ----------------------------------------------------------------------------
228// GosValue
229#[derive(Debug, Clone)]
230pub enum GosValue {
231    Nil(GosMetadata),
232    Bool(bool),
233    Int(isize),
234    Int8(i8),
235    Int16(i16),
236    Int32(i32),
237    Int64(i64),
238    Uint(usize),
239    Uint8(u8),
240    Uint16(u16),
241    Uint32(u32),
242    Uint64(u64),
243    Float32(F32),
244    Float64(F64), // becasue in Go there is no "float", just float64
245    Complex64(F32, F32),
246    Complex128(Box<(F64, F64)>),
247
248    // the 3 below are not visible to users, they are "values" not "variables"
249    // they are static data, don't use Rc for better performance
250    Function(FunctionKey),
251    Package(PackageKey),
252    Metadata(GosMetadata),
253
254    Str(Rc<StringObj>), // "String" is taken
255    Array(Rc<(ArrayObj, RCount)>),
256    Pointer(Box<PointerObj>),
257    Closure(Rc<(RefCell<ClosureObj>, RCount)>),
258    Slice(Rc<(SliceObj, RCount)>),
259    Map(Rc<(MapObj, RCount)>),
260    Interface(Rc<RefCell<InterfaceObj>>),
261    Struct(Rc<(RefCell<StructObj>, RCount)>),
262    Channel(Rc<ChannelObj>),
263
264    Named(Box<(GosValue, GosMetadata)>),
265}
266
267impl GosValue {
268    #[inline]
269    pub fn new_nil() -> GosValue {
270        GosValue::Nil(GosMetadata::Untyped)
271    }
272
273    #[inline]
274    pub fn new_str(s: String) -> GosValue {
275        GosValue::Str(Rc::new(StringObj::with_str(s)))
276    }
277
278    #[inline]
279    pub fn new_pointer(v: PointerObj) -> GosValue {
280        GosValue::Pointer(Box::new(v))
281    }
282
283    #[inline]
284    pub fn array_with_size(
285        size: usize,
286        val: &GosValue,
287        meta: GosMetadata,
288        gcobjs: &GcoVec,
289    ) -> GosValue {
290        let arr = Rc::new((ArrayObj::with_size(size, val, meta, gcobjs), Cell::new(0)));
291        let v = GosValue::Array(arr);
292        gcobjs.add(&v);
293        v
294    }
295
296    #[inline]
297    pub fn array_with_val(val: Vec<GosValue>, meta: GosMetadata, gcobjs: &GcoVec) -> GosValue {
298        let arr = Rc::new((ArrayObj::with_data(val, meta), Cell::new(0)));
299        let v = GosValue::Array(arr);
300        gcobjs.add(&v);
301        v
302    }
303
304    #[inline]
305    pub fn new_slice(
306        len: usize,
307        cap: usize,
308        meta: GosMetadata,
309        dval: Option<&GosValue>,
310        gcobjs: &GcoVec,
311    ) -> GosValue {
312        let s = Rc::new((SliceObj::new(len, cap, meta, dval), Cell::new(0)));
313        let v = GosValue::Slice(s);
314        gcobjs.add(&v);
315        v
316    }
317
318    #[inline]
319    pub fn new_slice_nil(meta: GosMetadata, gcobjs: &GcoVec) -> GosValue {
320        let s = Rc::new((SliceObj::new_nil(meta), Cell::new(0)));
321        let v = GosValue::Slice(s);
322        gcobjs.add(&v);
323        v
324    }
325
326    #[inline]
327    pub fn slice_with_val(val: Vec<GosValue>, meta: GosMetadata, gcobjs: &GcoVec) -> GosValue {
328        let s = Rc::new((SliceObj::with_data(val, meta), Cell::new(0)));
329        let v = GosValue::Slice(s);
330        gcobjs.add(&v);
331        v
332    }
333
334    #[inline]
335    pub fn slice_with_array(arr: &GosValue, begin: isize, end: isize, gcobjs: &GcoVec) -> GosValue {
336        let s = Rc::new((
337            SliceObj::with_array(&arr.as_array().0, begin, end),
338            Cell::new(0),
339        ));
340        let v = GosValue::Slice(s);
341        gcobjs.add(&v);
342        v
343    }
344
345    #[inline]
346    pub fn new_map(meta: GosMetadata, default_val: GosValue, gcobjs: &GcoVec) -> GosValue {
347        let val = Rc::new((MapObj::new(meta, default_val), Cell::new(0)));
348        let v = GosValue::Map(val);
349        gcobjs.add(&v);
350        v
351    }
352
353    #[inline]
354    pub fn new_map_nil(meta: GosMetadata, default_val: GosValue, gcobjs: &GcoVec) -> GosValue {
355        let val = Rc::new((MapObj::new_nil(meta, default_val), Cell::new(0)));
356        let v = GosValue::Map(val);
357        gcobjs.add(&v);
358        v
359    }
360
361    #[inline]
362    pub fn new_struct(obj: StructObj, gcobjs: &GcoVec) -> GosValue {
363        let val = Rc::new((RefCell::new(obj), Cell::new(0)));
364        let v = GosValue::Struct(val);
365        gcobjs.add(&v);
366        v
367    }
368
369    #[inline]
370    pub fn new_function(
371        package: PackageKey,
372        meta: GosMetadata,
373        objs: &mut VMObjects,
374        gcv: &GcoVec,
375        flag: FuncFlag,
376    ) -> GosValue {
377        let val = FunctionVal::new(package, meta, objs, gcv, flag);
378        GosValue::Function(objs.functions.insert(val))
379    }
380
381    #[inline]
382    pub fn new_closure(
383        fkey: FunctionKey,
384        fobjs: &FunctionObjs, /*, gcobjs: &mut GcoVec todo! */
385    ) -> GosValue {
386        let val = ClosureObj::new_gos(fkey, fobjs, None);
387        GosValue::Closure(Rc::new((RefCell::new(val), Cell::new(0))))
388    }
389
390    #[inline]
391    pub fn new_runtime_closure(clsobj: ClosureObj, gcobjs: &GcoVec) -> GosValue {
392        let v = GosValue::Closure(Rc::new((RefCell::new(clsobj), Cell::new(0))));
393        gcobjs.add(&v);
394        v
395    }
396
397    #[inline]
398    pub fn new_iface(meta: GosMetadata, underlying: IfaceUnderlying) -> GosValue {
399        let val = Rc::new(RefCell::new(InterfaceObj::new(meta, underlying)));
400        GosValue::Interface(val)
401    }
402
403    #[inline]
404    pub fn new_empty_iface(mdata: &Metadata, underlying: GosValue) -> GosValue {
405        let val = Rc::new(RefCell::new(InterfaceObj::new(
406            mdata.empty_iface,
407            IfaceUnderlying::Gos(underlying, None),
408        )));
409        GosValue::Interface(val)
410    }
411
412    #[inline]
413    pub fn new_channel(meta: GosMetadata, cap: usize) -> GosValue {
414        GosValue::Channel(Rc::new(ChannelObj::new(meta, cap)))
415    }
416
417    #[inline]
418    pub fn new_meta(t: MetadataType, metas: &mut MetadataObjs) -> GosValue {
419        GosValue::Metadata(GosMetadata::NonPtr(metas.insert(t), MetaCategory::Default))
420    }
421
422    #[inline]
423    pub fn as_bool(&self) -> &bool {
424        unwrap_gos_val!(Bool, self)
425    }
426
427    #[inline]
428    pub fn as_int(&self) -> &isize {
429        unwrap_gos_val!(Int, self)
430    }
431
432    #[inline]
433    pub fn as_uint8(&self) -> &u8 {
434        unwrap_gos_val!(Uint8, self)
435    }
436
437    #[inline]
438    pub fn as_int32(&self) -> &i32 {
439        unwrap_gos_val!(Int32, self)
440    }
441
442    #[inline]
443    pub fn as_int_mut(&mut self) -> &mut isize {
444        unwrap_gos_val!(Int, self)
445    }
446
447    #[inline]
448    pub fn as_float(&self) -> &f64 {
449        unwrap_gos_val!(Float64, self)
450    }
451
452    #[inline]
453    pub fn as_str(&self) -> &Rc<StringObj> {
454        unwrap_gos_val!(Str, self)
455    }
456
457    #[inline]
458    pub fn as_array(&self) -> &Rc<(ArrayObj, RCount)> {
459        unwrap_gos_val!(Array, self)
460    }
461
462    #[inline]
463    pub fn as_slice(&self) -> &Rc<(SliceObj, RCount)> {
464        unwrap_gos_val!(Slice, self)
465    }
466
467    #[inline]
468    pub fn as_map(&self) -> &Rc<(MapObj, RCount)> {
469        unwrap_gos_val!(Map, self)
470    }
471
472    #[inline]
473    pub fn as_interface(&self) -> &Rc<RefCell<InterfaceObj>> {
474        unwrap_gos_val!(Interface, self)
475    }
476
477    #[inline]
478    pub fn as_channel(&self) -> &Rc<ChannelObj> {
479        unwrap_gos_val!(Channel, self)
480    }
481
482    #[inline]
483    pub fn as_function(&self) -> &FunctionKey {
484        unwrap_gos_val!(Function, self)
485    }
486
487    #[inline]
488    pub fn as_package(&self) -> &PackageKey {
489        unwrap_gos_val!(Package, self)
490    }
491
492    #[inline]
493    pub fn as_struct(&self) -> &Rc<(RefCell<StructObj>, RCount)> {
494        unwrap_gos_val!(Struct, self)
495    }
496
497    #[inline]
498    pub fn as_closure(&self) -> &Rc<(RefCell<ClosureObj>, RCount)> {
499        unwrap_gos_val!(Closure, self)
500    }
501
502    #[inline]
503    pub fn as_meta(&self) -> &GosMetadata {
504        unwrap_gos_val!(Metadata, self)
505    }
506
507    #[inline]
508    pub fn as_pointer(&self) -> &Box<PointerObj> {
509        unwrap_gos_val!(Pointer, self)
510    }
511
512    #[inline]
513    pub fn as_named(&self) -> &Box<(GosValue, GosMetadata)> {
514        unwrap_gos_val!(Named, self)
515    }
516
517    #[inline]
518    pub fn is_nil(&self) -> bool {
519        match &self {
520            GosValue::Nil(_) => true,
521            _ => false,
522        }
523    }
524
525    pub fn try_get_struct(&self) -> Option<&Rc<(RefCell<StructObj>, RCount)>> {
526        match &self {
527            GosValue::Struct(_) => Some(self.as_struct()),
528            GosValue::Named(n) => Some(n.0.as_struct()),
529            _ => None,
530        }
531    }
532
533    pub fn try_get_map(&self) -> Option<&Rc<(MapObj, RCount)>> {
534        match &self {
535            GosValue::Map(_) => Some(self.as_map()),
536            GosValue::Named(n) => Some(n.0.as_map()),
537            _ => None,
538        }
539    }
540
541    #[inline]
542    pub fn iface_underlying(&self) -> Option<GosValue> {
543        match &self {
544            GosValue::Named(n) => {
545                let b = n.0.as_interface().borrow();
546                b.underlying_value().map(|x| x.clone())
547            }
548            GosValue::Interface(v) => {
549                let b = v.borrow();
550                b.underlying_value().map(|x| x.clone())
551            }
552            _ => unreachable!(),
553        }
554    }
555
556    #[inline]
557    pub fn equals_nil(&self) -> bool {
558        match &self {
559            GosValue::Nil(_) => true,
560            GosValue::Named(n) => n.0.is_nil(),
561            GosValue::Slice(s) => s.0.is_nil(),
562            GosValue::Map(m) => m.0.is_nil(),
563            GosValue::Interface(iface) => iface.borrow().is_nil(),
564            _ => false,
565        }
566    }
567
568    #[inline]
569    pub fn get_type(&self) -> ValueType {
570        match self {
571            GosValue::Nil(_) => ValueType::Nil,
572            GosValue::Bool(_) => ValueType::Bool,
573            GosValue::Int(_) => ValueType::Int,
574            GosValue::Int8(_) => ValueType::Int8,
575            GosValue::Int16(_) => ValueType::Int16,
576            GosValue::Int32(_) => ValueType::Int32,
577            GosValue::Int64(_) => ValueType::Int64,
578            GosValue::Uint(_) => ValueType::Uint,
579            GosValue::Uint8(_) => ValueType::Uint8,
580            GosValue::Uint16(_) => ValueType::Uint16,
581            GosValue::Uint32(_) => ValueType::Uint32,
582            GosValue::Uint64(_) => ValueType::Uint64,
583            GosValue::Float32(_) => ValueType::Float32,
584            GosValue::Float64(_) => ValueType::Float64,
585            GosValue::Complex64(_, _) => ValueType::Complex64,
586            GosValue::Complex128(_) => ValueType::Complex128,
587            GosValue::Str(_) => ValueType::Str,
588            GosValue::Array(_) => ValueType::Array,
589            GosValue::Pointer(_) => ValueType::Pointer,
590            GosValue::Closure(_) => ValueType::Closure,
591            GosValue::Slice(_) => ValueType::Slice,
592            GosValue::Map(_) => ValueType::Map,
593            GosValue::Interface(_) => ValueType::Interface,
594            GosValue::Struct(_) => ValueType::Struct,
595            GosValue::Channel(_) => ValueType::Channel,
596            GosValue::Function(_) => ValueType::Function,
597            GosValue::Package(_) => ValueType::Package,
598            GosValue::Metadata(_) => ValueType::Metadata,
599            GosValue::Named(_) => ValueType::Named,
600        }
601    }
602
603    pub fn identical(&self, other: &GosValue) -> bool {
604        self.get_type() == other.get_type() && self == other
605    }
606
607    pub fn get_meta(&self, objs: &VMObjects, stack: &Stack) -> GosMetadata {
608        match self {
609            GosValue::Nil(m) => *m,
610            GosValue::Bool(_) => objs.metadata.mbool,
611            GosValue::Int(_) => objs.metadata.mint,
612            GosValue::Int8(_) => objs.metadata.mint8,
613            GosValue::Int16(_) => objs.metadata.mint16,
614            GosValue::Int32(_) => objs.metadata.mint32,
615            GosValue::Int64(_) => objs.metadata.mint64,
616            GosValue::Uint(_) => objs.metadata.muint,
617            GosValue::Uint8(_) => objs.metadata.muint8,
618            GosValue::Uint16(_) => objs.metadata.muint16,
619            GosValue::Uint32(_) => objs.metadata.muint32,
620            GosValue::Uint64(_) => objs.metadata.muint64,
621            GosValue::Float32(_) => objs.metadata.mfloat32,
622            GosValue::Float64(_) => objs.metadata.mfloat64,
623            GosValue::Complex64(_, _) => objs.metadata.mcomplex64,
624            GosValue::Complex128(_) => objs.metadata.mcomplex128,
625            GosValue::Str(_) => objs.metadata.mstr,
626            GosValue::Array(a) => a.0.meta,
627            GosValue::Pointer(b) => {
628                let bobj: &PointerObj = &*b;
629                let pointee = match bobj {
630                    //PointerObj::Nil => GosMetadata::Untyped,
631                    PointerObj::UpVal(uv) => {
632                        let state: &UpValueState = &uv.inner.borrow();
633                        match state {
634                            UpValueState::Open(d) => stack
635                                .get_with_type(d.index as usize, d.typ)
636                                .get_meta(objs, stack),
637                            UpValueState::Closed(v) => v.get_meta(objs, stack),
638                        }
639                    }
640                    PointerObj::Struct(s, named_md) => match named_md {
641                        GosMetadata::Untyped => s.0.borrow().meta,
642                        _ => *named_md,
643                    },
644                    PointerObj::Array(a, named_md) => match named_md {
645                        GosMetadata::Untyped => a.0.meta,
646                        _ => *named_md,
647                    },
648                    PointerObj::Slice(s, named_md) => match named_md {
649                        GosMetadata::Untyped => s.0.meta,
650                        _ => *named_md,
651                    },
652                    PointerObj::Map(m, named_md) => match named_md {
653                        GosMetadata::Untyped => m.0.meta,
654                        _ => *named_md,
655                    },
656                    PointerObj::StructField(sobj, index) => {
657                        sobj.0.borrow().fields[*index as usize].get_meta(objs, stack)
658                    }
659                    PointerObj::SliceMember(sobj, index) => sobj.0.borrow_data()[*index as usize]
660                        .borrow()
661                        .get_meta(objs, stack),
662                    PointerObj::PkgMember(pkey, index) => {
663                        objs.packages[*pkey].member(*index).get_meta(objs, stack)
664                    }
665                    PointerObj::Released => unreachable!(),
666                };
667                pointee.ptr_to()
668            }
669            GosValue::Closure(c) => c.0.borrow().meta,
670            GosValue::Slice(s) => s.0.meta,
671            GosValue::Map(m) => m.0.meta,
672            GosValue::Interface(i) => i.borrow().meta,
673            GosValue::Struct(s) => s.0.borrow().meta,
674            GosValue::Channel(_) => unimplemented!(),
675            GosValue::Function(_) => unimplemented!(),
676            GosValue::Package(_) => unimplemented!(),
677            GosValue::Metadata(_) => unimplemented!(),
678            GosValue::Named(v) => v.1,
679        }
680    }
681
682    #[inline]
683    pub fn copy_semantic(&self, gcos: &GcoVec) -> GosValue {
684        match self {
685            GosValue::Slice(s) => {
686                let rc = Rc::new((SliceObj::clone(&s.0), Cell::new(0)));
687                gcos.add_weak(GcWeak::Slice(Rc::downgrade(&rc)));
688                GosValue::Slice(rc)
689            }
690            GosValue::Map(m) => {
691                let rc = Rc::new((MapObj::clone(&m.0), Cell::new(0)));
692                gcos.add_weak(GcWeak::Map(Rc::downgrade(&rc)));
693                GosValue::Map(rc)
694            }
695            GosValue::Struct(s) => {
696                let rc = Rc::new((RefCell::clone(&s.0), Cell::new(0)));
697                gcos.add_weak(GcWeak::Struct(Rc::downgrade(&rc)));
698                GosValue::Struct(rc)
699            }
700            GosValue::Named(v) => GosValue::Named(Box::new((v.0.copy_semantic(gcos), v.1))),
701            _ => self.clone(),
702        }
703    }
704
705    #[inline]
706    pub fn deep_clone(&self, gcos: &GcoVec) -> GosValue {
707        match self {
708            GosValue::Slice(s) => {
709                let rc = Rc::new((s.0.deep_clone(gcos), Cell::new(0)));
710                gcos.add_weak(GcWeak::Slice(Rc::downgrade(&rc)));
711                GosValue::Slice(rc)
712            }
713            GosValue::Map(m) => {
714                let rc = Rc::new((m.0.deep_clone(gcos), Cell::new(0)));
715                gcos.add_weak(GcWeak::Map(Rc::downgrade(&rc)));
716                GosValue::Map(rc)
717            }
718            GosValue::Array(arr) => {
719                let rc = Rc::new((arr.0.deep_clone(gcos), Cell::new(0)));
720                gcos.add_weak(GcWeak::Array(Rc::downgrade(&rc)));
721                GosValue::Array(rc)
722            }
723            GosValue::Struct(s) => {
724                let rc = Rc::new((RefCell::new(s.0.borrow().deep_clone(gcos)), Cell::new(0)));
725                gcos.add_weak(GcWeak::Struct(Rc::downgrade(&rc)));
726                GosValue::Struct(rc)
727            }
728            GosValue::Pointer(p) => GosValue::Pointer(Box::new(p.deep_clone(gcos))),
729            GosValue::Named(v) => GosValue::Named(Box::new((v.0.deep_clone(gcos), v.1))),
730            _ => self.clone(),
731        }
732    }
733
734    #[inline]
735    pub fn add_str(a: &GosValue, b: &GosValue) -> GosValue {
736        let mut s = a.as_str().as_str().to_string();
737        s.push_str(b.as_str().as_str());
738        GosValue::new_str(s)
739    }
740
741    /// for gc
742    pub fn ref_sub_one(&self) {
743        match &self {
744            GosValue::Array(obj) => obj.1.set(obj.1.get() - 1),
745            GosValue::Pointer(obj) => obj.ref_sub_one(),
746            GosValue::Closure(obj) => obj.1.set(obj.1.get() - 1),
747            GosValue::Slice(obj) => obj.1.set(obj.1.get() - 1),
748            GosValue::Map(obj) => obj.1.set(obj.1.get() - 1),
749            GosValue::Interface(obj) => obj.borrow().ref_sub_one(),
750            GosValue::Struct(obj) => obj.1.set(obj.1.get() - 1),
751            GosValue::Named(obj) => obj.0.ref_sub_one(),
752            _ => {}
753        };
754    }
755
756    /// for gc
757    pub fn mark_dirty(&self, queue: &mut RCQueue) {
758        match &self {
759            GosValue::Array(obj) => rcount_mark_and_queue(&obj.1, queue),
760            GosValue::Pointer(obj) => obj.mark_dirty(queue),
761            GosValue::Closure(obj) => rcount_mark_and_queue(&obj.1, queue),
762            GosValue::Slice(obj) => rcount_mark_and_queue(&obj.1, queue),
763            GosValue::Map(obj) => rcount_mark_and_queue(&obj.1, queue),
764            GosValue::Interface(obj) => obj.borrow().mark_dirty(queue),
765            GosValue::Struct(obj) => rcount_mark_and_queue(&obj.1, queue),
766            GosValue::Named(obj) => obj.0.mark_dirty(queue),
767            _ => {}
768        };
769    }
770
771    pub fn rc(&self) -> IRC {
772        match &self {
773            GosValue::Array(obj) => obj.1.get(),
774            GosValue::Closure(obj) => obj.1.get(),
775            GosValue::Slice(obj) => obj.1.get(),
776            GosValue::Map(obj) => obj.1.get(),
777            GosValue::Struct(obj) => obj.1.get(),
778            _ => unreachable!(),
779        }
780    }
781
782    pub fn set_rc(&self, rc: IRC) {
783        match &self {
784            GosValue::Array(obj) => obj.1.set(rc),
785            GosValue::Closure(obj) => obj.1.set(rc),
786            GosValue::Slice(obj) => obj.1.set(rc),
787            GosValue::Map(obj) => obj.1.set(rc),
788            GosValue::Struct(obj) => obj.1.set(rc),
789            _ => unreachable!(),
790        }
791    }
792}
793
794impl Eq for GosValue {}
795
796impl PartialEq for GosValue {
797    fn eq(&self, b: &GosValue) -> bool {
798        match (self, b) {
799            (Self::Nil(_), Self::Nil(_)) => true,
800            (Self::Bool(x), Self::Bool(y)) => x == y,
801            (Self::Int(x), Self::Int(y)) => x == y,
802            (Self::Int8(x), Self::Int8(y)) => x == y,
803            (Self::Int16(x), Self::Int16(y)) => x == y,
804            (Self::Int32(x), Self::Int32(y)) => x == y,
805            (Self::Int64(x), Self::Int64(y)) => x == y,
806            (Self::Uint(x), Self::Uint(y)) => x == y,
807            (Self::Uint8(x), Self::Uint8(y)) => x == y,
808            (Self::Uint16(x), Self::Uint16(y)) => x == y,
809            (Self::Uint32(x), Self::Uint32(y)) => x == y,
810            (Self::Uint64(x), Self::Uint64(y)) => x == y,
811            (Self::Float32(x), Self::Float32(y)) => x == y,
812            (Self::Float64(x), Self::Float64(y)) => x == y,
813            (Self::Complex64(xr, xi), Self::Complex64(yr, yi)) => xr == yr && xi == yi,
814            (Self::Complex128(x), Self::Complex128(y)) => x.0 == y.0 && x.1 == y.1,
815            (Self::Function(x), Self::Function(y)) => x == y,
816            (Self::Package(x), Self::Package(y)) => x == y,
817            (Self::Metadata(x), Self::Metadata(y)) => x == y,
818            (Self::Str(x), Self::Str(y)) => *x == *y,
819            (Self::Array(x), Self::Array(y)) => x.0 == y.0,
820            (Self::Pointer(x), Self::Pointer(y)) => x == y,
821            (Self::Closure(x), Self::Closure(y)) => Rc::ptr_eq(x, y),
822            (Self::Slice(x), Self::Slice(y)) => Rc::ptr_eq(x, y),
823            (Self::Map(x), Self::Map(y)) => Rc::ptr_eq(x, y),
824            (Self::Interface(x), Self::Interface(y)) => InterfaceObj::eq(&x.borrow(), &y.borrow()),
825            (Self::Struct(x), Self::Struct(y)) => StructObj::eq(&x.0.borrow(), &y.0.borrow()),
826            (Self::Channel(x), Self::Channel(y)) => Rc::ptr_eq(x, y),
827            (Self::Named(x), Self::Named(y)) => x.0 == y.0,
828            (Self::Nil(_), nil) | (nil, Self::Nil(_)) => nil.equals_nil(),
829            (Self::Interface(iface), val) | (val, Self::Interface(iface)) => {
830                match iface.borrow().underlying_value() {
831                    Some(v) => v == val,
832                    None => false,
833                }
834            }
835            _ => false,
836        }
837    }
838}
839
840impl PartialOrd for GosValue {
841    #[inline]
842    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
843        Some(self.cmp(other))
844    }
845}
846
847impl Hash for GosValue {
848    fn hash<H: Hasher>(&self, state: &mut H) {
849        match &self {
850            GosValue::Bool(b) => b.hash(state),
851            GosValue::Int(i) => i.hash(state),
852            GosValue::Int8(i) => i.hash(state),
853            GosValue::Int16(i) => i.hash(state),
854            GosValue::Int32(i) => i.hash(state),
855            GosValue::Int64(i) => i.hash(state),
856            GosValue::Uint(i) => i.hash(state),
857            GosValue::Uint8(i) => i.hash(state),
858            GosValue::Uint16(i) => i.hash(state),
859            GosValue::Uint32(i) => i.hash(state),
860            GosValue::Uint64(i) => i.hash(state),
861            GosValue::Float32(f) => f.to_bits().hash(state),
862            GosValue::Float64(f) => f.to_bits().hash(state),
863            GosValue::Str(s) => s.as_str().hash(state),
864            GosValue::Array(a) => a.0.hash(state),
865            GosValue::Complex64(i, r) => {
866                i.hash(state);
867                r.hash(state);
868            }
869            GosValue::Complex128(c) => {
870                c.0.hash(state);
871                c.1.hash(state);
872            }
873            GosValue::Struct(s) => {
874                s.0.borrow().hash(state);
875            }
876            GosValue::Interface(i) => {
877                i.borrow().hash(state);
878            }
879            GosValue::Pointer(p) => {
880                PointerObj::hash(&p, state);
881            }
882            GosValue::Named(n) => n.0.hash(state),
883            _ => unreachable!(),
884        }
885    }
886}
887
888impl Ord for GosValue {
889    fn cmp(&self, b: &Self) -> Ordering {
890        match (self, b) {
891            (Self::Bool(x), Self::Bool(y)) => x.cmp(y),
892            (Self::Int(x), Self::Int(y)) => x.cmp(y),
893            (Self::Int8(x), Self::Int8(y)) => x.cmp(y),
894            (Self::Int16(x), Self::Int16(y)) => x.cmp(y),
895            (Self::Int32(x), Self::Int32(y)) => x.cmp(y),
896            (Self::Int64(x), Self::Int64(y)) => x.cmp(y),
897            (Self::Uint(x), Self::Uint(y)) => x.cmp(y),
898            (Self::Uint8(x), Self::Uint8(y)) => x.cmp(y),
899            (Self::Uint16(x), Self::Uint16(y)) => x.cmp(y),
900            (Self::Uint32(x), Self::Uint32(y)) => x.cmp(y),
901            (Self::Uint64(x), Self::Uint64(y)) => x.cmp(y),
902            (Self::Float32(x), Self::Float32(y)) => x.cmp(y),
903            (Self::Float64(x), Self::Float64(y)) => x.cmp(y),
904            (Self::Str(x), Self::Str(y)) => x.cmp(y),
905            _ => {
906                dbg!(self, b);
907                unreachable!()
908            }
909        }
910    }
911}
912
913impl Display for GosValue {
914    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
915        match self {
916            GosValue::Nil(_) => f.write_str("<nil>"),
917            GosValue::Bool(true) => f.write_str("true"),
918            GosValue::Bool(false) => f.write_str("false"),
919            GosValue::Int(i) => write!(f, "{}", i),
920            GosValue::Int8(i) => write!(f, "{}", i),
921            GosValue::Int16(i) => write!(f, "{}", i),
922            GosValue::Int32(i) => write!(f, "{}", i),
923            GosValue::Int64(i) => write!(f, "{}", i),
924            GosValue::Uint(i) => write!(f, "{}", i),
925            GosValue::Uint8(i) => write!(f, "{}", i),
926            GosValue::Uint16(i) => write!(f, "{}", i),
927            GosValue::Uint32(i) => write!(f, "{}", i),
928            GosValue::Uint64(i) => write!(f, "{}", i),
929            GosValue::Float32(fl) => write!(f, "{}", fl),
930            GosValue::Float64(fl) => write!(f, "{}", fl),
931            GosValue::Complex64(r, i) => write!(f, "({}, {})", r, i),
932            GosValue::Complex128(b) => write!(f, "({}, {})", b.0, b.1),
933            GosValue::Str(s) => f.write_str(s.as_ref().as_str()),
934            GosValue::Array(a) => write!(f, "{}", a.0),
935            GosValue::Pointer(p) => p.fmt(f),
936            GosValue::Closure(_) => f.write_str("<closure>"),
937            GosValue::Slice(s) => write!(f, "{}", s.0),
938            GosValue::Map(m) => write!(f, "{}", m.0),
939            GosValue::Interface(i) => write!(f, "{}", i.borrow()),
940            GosValue::Struct(s) => write!(f, "{}", s.0.borrow()),
941            GosValue::Channel(_) => f.write_str("<channel>"),
942            GosValue::Function(_) => f.write_str("<function>"),
943            GosValue::Package(_) => f.write_str("<package>"),
944            GosValue::Metadata(_) => f.write_str("<metadata>"),
945            GosValue::Named(v) => write!(f, "{}", v.0),
946        }
947    }
948}
949
950// ----------------------------------------------------------------------------
951// GosValue64
952// nil is only allowed on the stack as a rhs value
953// never as a lhs var, because when it's assigned to
954// we wouldn't know we should release it or not
955#[derive(Copy, Clone)]
956pub union V64Union {
957    nil: (),
958    ubool: bool,
959    int: isize,
960    int8: i8,
961    int16: i16,
962    int32: i32,
963    int64: i64,
964    uint: usize,
965    uint8: u8,
966    uint16: u16,
967    uint32: u32,
968    uint64: u64,
969    float32: F32,
970    float64: F64,
971    complex64: (F32, F32),
972    function: FunctionKey,
973    package: PackageKey,
974}
975
976impl fmt::Debug for V64Union {
977    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
978        f.write_fmt(format_args!("{:x}", unsafe { self.uint64 }))
979    }
980}
981
982/// GosValue64 is a 64bit struct for VM stack to get better performance, when converting
983/// to GosValue64, the type info is lost, Opcode is responsible for providing type info
984/// when converting back to GosValue
985#[derive(Copy, Clone, Debug)]
986pub struct GosValue64 {
987    data: V64Union,
988    //pub debug_type: ValueType, // to be removed in release build
989}
990
991impl GosValue64 {
992    #[inline]
993    pub fn from_v128(v: &GosValue) -> (GosValue64, ValueType) {
994        match v {
995            GosValue::Bool(b) => (
996                GosValue64 {
997                    data: V64Union { ubool: *b },
998                },
999                ValueType::Bool,
1000            ),
1001            GosValue::Int(i) => (
1002                GosValue64 {
1003                    data: V64Union { int: *i },
1004                },
1005                ValueType::Int,
1006            ),
1007            GosValue::Int8(i) => (
1008                GosValue64 {
1009                    data: V64Union { int8: *i },
1010                },
1011                ValueType::Int8,
1012            ),
1013            GosValue::Int16(i) => (
1014                GosValue64 {
1015                    data: V64Union { int16: *i },
1016                },
1017                ValueType::Int16,
1018            ),
1019            GosValue::Int32(i) => (
1020                GosValue64 {
1021                    data: V64Union { int32: *i },
1022                },
1023                ValueType::Int32,
1024            ),
1025            GosValue::Int64(i) => (
1026                GosValue64 {
1027                    data: V64Union { int64: *i },
1028                },
1029                ValueType::Int64,
1030            ),
1031            GosValue::Uint(i) => (
1032                GosValue64 {
1033                    data: V64Union { uint: *i },
1034                },
1035                ValueType::Uint,
1036            ),
1037            GosValue::Uint8(i) => (
1038                GosValue64 {
1039                    data: V64Union { uint8: *i },
1040                },
1041                ValueType::Uint8,
1042            ),
1043            GosValue::Uint16(i) => (
1044                GosValue64 {
1045                    data: V64Union { uint16: *i },
1046                },
1047                ValueType::Uint16,
1048            ),
1049            GosValue::Uint32(i) => (
1050                GosValue64 {
1051                    data: V64Union { uint32: *i },
1052                },
1053                ValueType::Uint32,
1054            ),
1055            GosValue::Uint64(i) => (
1056                GosValue64 {
1057                    data: V64Union { uint64: *i },
1058                },
1059                ValueType::Uint64,
1060            ),
1061            GosValue::Float32(f) => (
1062                GosValue64 {
1063                    data: V64Union { float32: *f },
1064                },
1065                ValueType::Float32,
1066            ),
1067            GosValue::Float64(f) => (
1068                GosValue64 {
1069                    data: V64Union { float64: *f },
1070                },
1071                ValueType::Float64,
1072            ),
1073            GosValue::Complex64(f1, f2) => (
1074                GosValue64 {
1075                    data: V64Union {
1076                        complex64: (*f1, *f2),
1077                    },
1078                },
1079                ValueType::Complex64,
1080            ),
1081            GosValue::Function(k) => (
1082                GosValue64 {
1083                    data: V64Union { function: *k },
1084                },
1085                ValueType::Function,
1086            ),
1087            GosValue::Package(k) => (
1088                GosValue64 {
1089                    data: V64Union { package: *k },
1090                },
1091                ValueType::Package,
1092            ),
1093            _ => unreachable!(),
1094        }
1095    }
1096
1097    #[inline]
1098    pub fn nil() -> GosValue64 {
1099        GosValue64 {
1100            data: V64Union { nil: () },
1101            //debug_type: ValueType::Nil,
1102        }
1103    }
1104
1105    #[inline]
1106    pub fn from_bool(b: bool) -> GosValue64 {
1107        GosValue64 {
1108            data: V64Union { ubool: b },
1109            //debug_type: ValueType::Bool,
1110        }
1111    }
1112
1113    #[inline]
1114    pub fn from_int(i: isize) -> GosValue64 {
1115        GosValue64 {
1116            data: V64Union { int: i },
1117            //debug_type: ValueType::Int,
1118        }
1119    }
1120
1121    #[inline]
1122    pub fn from_int32_as(i: i32, t: ValueType) -> GosValue64 {
1123        let u = match t {
1124            ValueType::Int => V64Union { int: i as isize },
1125            ValueType::Int8 => V64Union { int8: i as i8 },
1126            ValueType::Int16 => V64Union { int16: i as i16 },
1127            ValueType::Int32 => V64Union { int32: i as i32 },
1128            ValueType::Int64 => V64Union { int64: i as i64 },
1129            ValueType::Uint => V64Union { uint: i as usize },
1130            ValueType::Uint8 => V64Union { uint8: i as u8 },
1131            ValueType::Uint16 => V64Union { uint16: i as u16 },
1132            ValueType::Uint32 => V64Union { uint32: i as u32 },
1133            ValueType::Uint64 => V64Union { uint64: i as u64 },
1134            _ => unreachable!(),
1135        };
1136        GosValue64 { data: u }
1137    }
1138
1139    #[inline]
1140    pub fn from_float64(f: F64) -> GosValue64 {
1141        GosValue64 {
1142            data: V64Union { float64: f },
1143            //debug_type: ValueType::Float64,
1144        }
1145    }
1146
1147    #[inline]
1148    pub fn from_complex64(r: F32, i: F32) -> GosValue64 {
1149        GosValue64 {
1150            data: V64Union { complex64: (r, i) },
1151            //debug_type: ValueType::Complex64,
1152        }
1153    }
1154
1155    /// returns GosValue and increases RC
1156    #[inline]
1157    pub fn get_v128(&self, t: ValueType) -> GosValue {
1158        //debug_assert!(t == self.debug_type);
1159        unsafe {
1160            match t {
1161                ValueType::Bool => GosValue::Bool(self.data.ubool),
1162                ValueType::Int => GosValue::Int(self.data.int),
1163                ValueType::Int8 => GosValue::Int8(self.data.int8),
1164                ValueType::Int16 => GosValue::Int16(self.data.int16),
1165                ValueType::Int32 => GosValue::Int32(self.data.int32),
1166                ValueType::Int64 => GosValue::Int64(self.data.int64),
1167                ValueType::Uint => GosValue::Uint(self.data.uint),
1168                ValueType::Uint8 => GosValue::Uint8(self.data.uint8),
1169                ValueType::Uint16 => GosValue::Uint16(self.data.uint16),
1170                ValueType::Uint32 => GosValue::Uint32(self.data.uint32),
1171                ValueType::Uint64 => GosValue::Uint64(self.data.uint64),
1172                ValueType::Float32 => GosValue::Float32(self.data.float32),
1173                ValueType::Float64 => GosValue::Float64(self.data.float64),
1174                ValueType::Complex64 => {
1175                    GosValue::Complex64(self.data.complex64.0, self.data.complex64.1)
1176                }
1177                ValueType::Function => GosValue::Function(self.data.function),
1178                ValueType::Package => GosValue::Package(self.data.package),
1179                _ => unreachable!(),
1180            }
1181        }
1182    }
1183
1184    #[inline]
1185    pub fn get_bool(&self) -> bool {
1186        //debug_assert_eq!(self.debug_type, ValueType::Bool);
1187        unsafe { self.data.ubool }
1188    }
1189
1190    #[inline]
1191    pub fn get_int(&self) -> isize {
1192        //debug_assert_eq!(self.debug_type, ValueType::Int);
1193        unsafe { self.data.int }
1194    }
1195
1196    #[inline]
1197    pub fn get_int32(&self) -> i32 {
1198        unsafe { self.data.int32 }
1199    }
1200
1201    #[inline]
1202    pub fn get_uint(&self) -> usize {
1203        unsafe { self.data.uint }
1204    }
1205
1206    #[inline]
1207    pub fn get_uint32(&self) -> u32 {
1208        unsafe { self.data.uint32 }
1209    }
1210
1211    #[inline]
1212    pub fn get_float64(&self) -> F64 {
1213        //debug_assert_eq!(self.debug_type, ValueType::Float64);
1214        unsafe { self.data.float64 }
1215    }
1216
1217    #[inline]
1218    pub fn get_complex64(&self) -> (F32, F32) {
1219        //debug_assert_eq!(self.debug_type, ValueType::Complex64);
1220        unsafe { self.data.complex64 }
1221    }
1222
1223    #[inline]
1224    pub fn to_uint(&mut self, t: ValueType) {
1225        convert_to_int!(self, t, uint, usize);
1226    }
1227
1228    #[inline]
1229    pub fn to_uint8(&mut self, t: ValueType) {
1230        convert_to_int!(self, t, uint8, u8);
1231    }
1232
1233    #[inline]
1234    pub fn to_uint16(&mut self, t: ValueType) {
1235        convert_to_int!(self, t, uint16, u16);
1236    }
1237
1238    #[inline]
1239    pub fn to_uint32(&mut self, t: ValueType) {
1240        convert_to_int!(self, t, uint32, u32);
1241    }
1242
1243    #[inline]
1244    pub fn to_uint64(&mut self, t: ValueType) {
1245        convert_to_int!(self, t, uint64, u64);
1246    }
1247
1248    #[inline]
1249    pub fn to_int(&mut self, t: ValueType) {
1250        convert_to_int!(self, t, int, isize);
1251    }
1252
1253    #[inline]
1254    pub fn to_int8(&mut self, t: ValueType) {
1255        convert_to_int!(self, t, int8, i8);
1256    }
1257
1258    #[inline]
1259    pub fn to_int16(&mut self, t: ValueType) {
1260        convert_to_int!(self, t, int16, i16);
1261    }
1262
1263    #[inline]
1264    pub fn to_int32(&mut self, t: ValueType) {
1265        convert_to_int!(self, t, int32, i32);
1266    }
1267
1268    #[inline]
1269    pub fn to_int64(&mut self, t: ValueType) {
1270        convert_to_int!(self, t, int64, i64);
1271    }
1272
1273    #[inline]
1274    pub fn to_float32(&mut self, t: ValueType) {
1275        convert_to_float!(self, t, float32, F32, f32);
1276    }
1277
1278    #[inline]
1279    pub fn to_float64(&mut self, t: ValueType) {
1280        convert_to_float!(self, t, float64, F64, f64);
1281    }
1282
1283    #[inline]
1284    pub fn unary_negate(&mut self, t: ValueType) {
1285        match t {
1286            ValueType::Int => self.data.int = -unsafe { self.data.int },
1287            ValueType::Int8 => self.data.int8 = -unsafe { self.data.int8 },
1288            ValueType::Int16 => self.data.int16 = -unsafe { self.data.int16 },
1289            ValueType::Int32 => self.data.int32 = -unsafe { self.data.int32 },
1290            ValueType::Int64 => self.data.int64 = -unsafe { self.data.int64 },
1291            ValueType::Float32 => self.data.float32 = -unsafe { self.data.float32 },
1292            ValueType::Float64 => self.data.float64 = -unsafe { self.data.float64 },
1293            ValueType::Uint => self.data.uint = unsafe { (!0) ^ self.data.uint } + 1,
1294            ValueType::Uint8 => self.data.uint8 = unsafe { (!0) ^ self.data.uint8 } + 1,
1295            ValueType::Uint16 => self.data.uint16 = unsafe { (!0) ^ self.data.uint16 } + 1,
1296            ValueType::Uint32 => self.data.uint32 = unsafe { (!0) ^ self.data.uint32 } + 1,
1297            ValueType::Uint64 => self.data.uint64 = unsafe { (!0) ^ self.data.uint64 } + 1,
1298            _ => unreachable!(),
1299        }
1300    }
1301
1302    #[inline]
1303    pub fn unary_xor(&mut self, t: ValueType) {
1304        match t {
1305            ValueType::Uint => self.data.uint = unsafe { (!0) ^ self.data.uint },
1306            ValueType::Uint8 => self.data.uint8 = unsafe { (!0) ^ self.data.uint8 },
1307            ValueType::Uint16 => self.data.uint16 = unsafe { (!0) ^ self.data.uint16 },
1308            ValueType::Uint32 => self.data.uint32 = unsafe { (!0) ^ self.data.uint32 },
1309            ValueType::Uint64 => self.data.uint64 = unsafe { (!0) ^ self.data.uint64 },
1310            ValueType::Int => self.data.int = unsafe { -1 ^ self.data.int },
1311            ValueType::Int8 => self.data.int8 = unsafe { -1 ^ self.data.int8 },
1312            ValueType::Int16 => self.data.int16 = unsafe { -1 ^ self.data.int16 },
1313            ValueType::Int32 => self.data.int32 = unsafe { -1 ^ self.data.int32 },
1314            ValueType::Int64 => self.data.int64 = unsafe { -1 ^ self.data.int64 },
1315            _ => unreachable!(),
1316        }
1317    }
1318
1319    #[inline]
1320    pub fn unary_not(&mut self, t: ValueType) {
1321        debug_assert!(t == ValueType::Bool);
1322        self.data.ubool = unsafe { !self.data.ubool };
1323    }
1324
1325    #[inline]
1326    pub fn binary_op_add(a: &GosValue64, b: &GosValue64, t: ValueType) -> GosValue64 {
1327        unsafe { binary_op_int_float!(t, a, b, +) }
1328    }
1329
1330    #[inline]
1331    pub fn binary_op_sub(a: &GosValue64, b: &GosValue64, t: ValueType) -> GosValue64 {
1332        unsafe { binary_op_int_float!(t, a, b, -) }
1333    }
1334
1335    #[inline]
1336    pub fn binary_op_mul(a: &GosValue64, b: &GosValue64, t: ValueType) -> GosValue64 {
1337        unsafe { binary_op_int_float!(t, a, b, *) }
1338    }
1339
1340    #[inline]
1341    pub fn binary_op_quo(a: &GosValue64, b: &GosValue64, t: ValueType) -> GosValue64 {
1342        unsafe { binary_op_int_float!(t, a, b, /) }
1343    }
1344
1345    #[inline]
1346    pub fn binary_op_rem(a: &GosValue64, b: &GosValue64, t: ValueType) -> GosValue64 {
1347        unsafe { binary_op_int_no_wrap!(t, a, b, %) }
1348    }
1349
1350    #[inline]
1351    pub fn binary_op_and(a: &GosValue64, b: &GosValue64, t: ValueType) -> GosValue64 {
1352        unsafe { binary_op_int_no_wrap!(t, a, b, &) }
1353    }
1354
1355    #[inline]
1356    pub fn binary_op_or(a: &GosValue64, b: &GosValue64, t: ValueType) -> GosValue64 {
1357        unsafe { binary_op_int_no_wrap!(t, a, b, |) }
1358    }
1359
1360    #[inline]
1361    pub fn binary_op_xor(a: &GosValue64, b: &GosValue64, t: ValueType) -> GosValue64 {
1362        unsafe { binary_op_int_no_wrap!(t, a, b, ^) }
1363    }
1364
1365    #[inline]
1366    pub fn binary_op_shl(&mut self, b: u32, t: ValueType) {
1367        unsafe { shift_int!(t, self, b, checked_shl) }
1368    }
1369
1370    #[inline]
1371    pub fn binary_op_shr(&mut self, b: u32, t: ValueType) {
1372        unsafe { shift_int!(t, self, b, checked_shr) }
1373    }
1374
1375    #[inline]
1376    pub fn binary_op_and_not(a: &GosValue64, b: &GosValue64, t: ValueType) -> GosValue64 {
1377        GosValue64 {
1378            //debug_type: t,
1379            data: unsafe {
1380                match t {
1381                    ValueType::Int => V64Union {
1382                        int: a.data.int & !b.data.int,
1383                    },
1384                    ValueType::Int8 => V64Union {
1385                        int8: a.data.int8 & !b.data.int8,
1386                    },
1387                    ValueType::Int16 => V64Union {
1388                        int16: a.data.int16 & !b.data.int16,
1389                    },
1390                    ValueType::Int32 => V64Union {
1391                        int32: a.data.int32 & !b.data.int32,
1392                    },
1393                    ValueType::Int64 => V64Union {
1394                        int64: a.data.int64 & !b.data.int64,
1395                    },
1396                    ValueType::Uint => V64Union {
1397                        uint: a.data.uint & !b.data.uint,
1398                    },
1399                    ValueType::Uint8 => V64Union {
1400                        uint8: a.data.uint8 & !b.data.uint8,
1401                    },
1402                    ValueType::Uint16 => V64Union {
1403                        uint16: a.data.uint16 & !b.data.uint16,
1404                    },
1405                    ValueType::Uint32 => V64Union {
1406                        uint32: a.data.uint32 & !b.data.uint32,
1407                    },
1408                    ValueType::Uint64 => V64Union {
1409                        uint64: a.data.uint64 & !b.data.uint64,
1410                    },
1411                    _ => unreachable!(),
1412                }
1413            },
1414        }
1415    }
1416
1417    #[inline]
1418    pub fn binary_op(a: &GosValue64, b: &GosValue64, t: ValueType, op: Opcode) -> GosValue64 {
1419        match op {
1420            Opcode::ADD => GosValue64::binary_op_add(a, b, t),
1421            Opcode::SUB => GosValue64::binary_op_sub(a, b, t),
1422            Opcode::MUL => GosValue64::binary_op_mul(a, b, t),
1423            Opcode::QUO => GosValue64::binary_op_quo(a, b, t),
1424            Opcode::REM => GosValue64::binary_op_rem(a, b, t),
1425            Opcode::AND => GosValue64::binary_op_and(a, b, t),
1426            Opcode::OR => GosValue64::binary_op_or(a, b, t),
1427            Opcode::XOR => GosValue64::binary_op_xor(a, b, t),
1428            Opcode::AND_NOT => GosValue64::binary_op_and_not(a, b, t),
1429            Opcode::SHL => {
1430                let mut v = a.clone();
1431                v.binary_op_shl(b.get_uint32(), t);
1432                v
1433            }
1434            Opcode::SHR => {
1435                let mut v = a.clone();
1436                v.binary_op_shr(b.get_uint32(), t);
1437                v
1438            }
1439            _ => {
1440                dbg!(t, op);
1441                unreachable!()
1442            }
1443        }
1444    }
1445
1446    #[inline]
1447    pub fn compare_eql(a: &GosValue64, b: &GosValue64, t: ValueType) -> bool {
1448        unsafe { cmp_bool_int_float!(t, a, b, ==) }
1449    }
1450
1451    #[inline]
1452    pub fn compare_neq(a: &GosValue64, b: &GosValue64, t: ValueType) -> bool {
1453        unsafe { cmp_bool_int_float!(t, a, b, !=) }
1454    }
1455
1456    #[inline]
1457    pub fn compare_lss(a: &GosValue64, b: &GosValue64, t: ValueType) -> bool {
1458        unsafe { cmp_int_float!(t, a, b, <) }
1459    }
1460
1461    #[inline]
1462    pub fn compare_gtr(a: &GosValue64, b: &GosValue64, t: ValueType) -> bool {
1463        unsafe { cmp_int_float!(t, a, b, >) }
1464    }
1465
1466    #[inline]
1467    pub fn compare_leq(a: &GosValue64, b: &GosValue64, t: ValueType) -> bool {
1468        unsafe { cmp_int_float!(t, a, b, <=) }
1469    }
1470
1471    #[inline]
1472    pub fn compare_geq(a: &GosValue64, b: &GosValue64, t: ValueType) -> bool {
1473        unsafe { cmp_int_float!(t, a, b, >=) }
1474    }
1475}
1476
1477#[cfg(test)]
1478mod test {
1479    use super::super::value::*;
1480    use std::collections::HashMap;
1481    use std::mem;
1482
1483    #[test]
1484    fn test_types() {
1485        let _t1: Vec<GosValue> = vec![
1486            GosValue::new_str("Norway".to_string()),
1487            GosValue::Int(100),
1488            GosValue::new_str("Denmark".to_string()),
1489            GosValue::Int(10),
1490        ];
1491
1492        let _t2: Vec<GosValue> = vec![
1493            GosValue::new_str("Norway".to_string()),
1494            GosValue::Int(100),
1495            GosValue::new_str("Denmark".to_string()),
1496            GosValue::Int(10),
1497        ];
1498    }
1499
1500    #[test]
1501    fn test_size() {
1502        dbg!(mem::size_of::<HashMap<GosValue, GosValue>>());
1503        dbg!(mem::size_of::<String>());
1504        dbg!(mem::size_of::<Rc<String>>());
1505        dbg!(mem::size_of::<SliceObj>());
1506        dbg!(mem::size_of::<RefCell<GosValue>>());
1507        dbg!(mem::size_of::<GosValue>());
1508        dbg!(mem::size_of::<GosValue64>());
1509
1510        let mut h: HashMap<isize, isize> = HashMap::new();
1511        h.insert(0, 1);
1512        let mut h2 = h.clone();
1513        h2.insert(0, 3);
1514        dbg!(h[&0]);
1515        dbg!(h2[&0]);
1516    }
1517}