1#![macro_use]
2use super::channel::Channel;
3use super::ffi::Ffi;
4use super::gc::GcoVec;
5use super::instruction::{Instruction, OpIndex, Opcode, ValueType};
6use super::metadata::*;
7use super::stack::Stack;
8use super::value::{rcount_mark_and_queue, EmptyResult, GosValue, RCQueue, RCount};
9use goscript_parser::objects::{EntityKey, IdentKey};
10use slotmap::{new_key_type, DenseSlotMap};
11use std::cell::{Cell, Ref, RefCell, RefMut};
12use std::cmp::Ordering;
13use std::collections::HashMap;
14use std::convert::TryFrom;
15use std::convert::TryInto;
16use std::fmt::Write;
17use std::fmt::{self, Display};
18use std::hash::{Hash, Hasher};
19use std::iter::FromIterator;
20use std::rc::{Rc, Weak};
21
22const DEFAULT_CAPACITY: usize = 128;
23
24#[macro_export]
25macro_rules! null_key {
26 () => {
27 slotmap::Key::null()
28 };
29}
30
31new_key_type! { pub struct MetadataKey; }
32new_key_type! { pub struct FunctionKey; }
33new_key_type! { pub struct PackageKey; }
34
35pub type MetadataObjs = DenseSlotMap<MetadataKey, MetadataType>;
36pub type FunctionObjs = DenseSlotMap<FunctionKey, FunctionVal>;
37pub type PackageObjs = DenseSlotMap<PackageKey, PackageVal>;
38
39pub fn key_to_u64<K>(key: K) -> u64
40where
41 K: slotmap::Key,
42{
43 let data: slotmap::KeyData = key.into();
44 data.as_ffi()
45}
46
47pub fn u64_to_key<K>(u: u64) -> K
48where
49 K: slotmap::Key,
50{
51 let data = slotmap::KeyData::from_ffi(u);
52 data.into()
53}
54
55#[derive(Debug)]
56pub struct VMObjects {
57 pub metas: MetadataObjs,
58 pub functions: FunctionObjs,
59 pub packages: PackageObjs,
60 pub metadata: Metadata,
61}
62
63impl VMObjects {
64 pub fn new() -> VMObjects {
65 let mut metas = DenseSlotMap::with_capacity_and_key(DEFAULT_CAPACITY);
66 let md = Metadata::new(&mut metas);
67 VMObjects {
68 metas: metas,
69 functions: DenseSlotMap::with_capacity_and_key(DEFAULT_CAPACITY),
70 packages: DenseSlotMap::with_capacity_and_key(DEFAULT_CAPACITY),
71 metadata: md,
72 }
73 }
74}
75
76pub type StringIter<'a> = std::str::Chars<'a>;
80
81pub type StringEnumIter<'a> = std::iter::Enumerate<StringIter<'a>>;
82
83#[derive(Debug)]
84pub struct StringObj {
85 data: Rc<String>,
86 begin: usize,
87 end: usize,
88}
89
90impl StringObj {
91 #[inline]
92 pub fn with_str(s: String) -> StringObj {
93 let len = s.len();
94 StringObj {
95 data: Rc::new(s),
96 begin: 0,
97 end: len,
98 }
99 }
100
101 #[inline]
102 pub fn as_str(&self) -> &str {
103 &self.data.as_ref()[self.begin..self.end]
104 }
105
106 #[inline]
107 pub fn into_string(self) -> String {
108 Rc::try_unwrap(self.data).unwrap()
109 }
110
111 #[inline]
112 pub fn len(&self) -> usize {
113 self.end - self.begin
114 }
115
116 #[inline]
117 pub fn get_byte(&self, i: usize) -> Option<&u8> {
118 self.as_str().as_bytes().get(i)
119 }
120
121 pub fn slice(&self, begin: isize, end: isize) -> StringObj {
122 let self_end = self.len() as isize + 1;
123 let bi = begin as usize;
124 let ei = ((self_end + end) % self_end) as usize;
125 StringObj {
126 data: Rc::clone(&self.data),
127 begin: bi,
128 end: ei,
129 }
130 }
131
132 pub fn iter(&self) -> StringIter {
133 self.as_str().chars()
134 }
135}
136
137impl Clone for StringObj {
138 #[inline]
139 fn clone(&self) -> Self {
140 StringObj {
141 data: Rc::clone(&self.data),
142 begin: self.begin,
143 end: self.end,
144 }
145 }
146}
147
148impl PartialEq for StringObj {
149 #[inline]
150 fn eq(&self, other: &StringObj) -> bool {
151 self.as_str().eq(other.as_str())
152 }
153}
154
155impl Eq for StringObj {}
156
157impl PartialOrd for StringObj {
158 #[inline]
159 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
160 Some(self.cmp(other))
161 }
162}
163
164impl Ord for StringObj {
165 #[inline]
166 fn cmp(&self, other: &Self) -> Ordering {
167 self.as_str().cmp(other.as_str())
168 }
169}
170
171pub type GosHashMap = HashMap<GosValue, RefCell<GosValue>>;
175
176pub type GosHashMapIter<'a> = std::collections::hash_map::Iter<'a, GosValue, RefCell<GosValue>>;
177
178#[derive(Debug)]
179pub struct MapObj {
180 pub meta: GosMetadata,
181 default_val: RefCell<GosValue>,
182 pub map: Option<Rc<RefCell<GosHashMap>>>,
183}
184
185impl MapObj {
186 pub fn new(meta: GosMetadata, default_val: GosValue) -> MapObj {
187 MapObj {
188 meta: meta,
189 default_val: RefCell::new(default_val),
190 map: Some(Rc::new(RefCell::new(HashMap::new()))),
191 }
192 }
193
194 pub fn new_nil(meta: GosMetadata, default_val: GosValue) -> MapObj {
195 MapObj {
196 meta: meta,
197 default_val: RefCell::new(default_val),
198 map: None,
199 }
200 }
201
202 pub fn deep_clone(&self, gcos: &GcoVec) -> MapObj {
204 let m = self.map.as_ref().map(|x| {
205 Rc::new(RefCell::new(
206 x.borrow()
207 .iter()
208 .map(|(k, v)| {
209 (
210 k.deep_clone(gcos),
211 RefCell::new(v.borrow().deep_clone(gcos)),
212 )
213 })
214 .collect(),
215 ))
216 });
217 MapObj {
218 meta: self.meta,
219 default_val: self.default_val.clone(),
220 map: m,
221 }
222 }
223
224 #[inline]
225 pub fn insert(&self, key: GosValue, val: GosValue) -> Option<GosValue> {
226 self.borrow_data_mut()
227 .insert(key, RefCell::new(val))
228 .map(|x| x.into_inner())
229 }
230
231 #[inline]
232 pub fn is_nil(&self) -> bool {
233 self.map.is_none()
234 }
235
236 #[inline]
237 pub fn get(&self, key: &GosValue) -> GosValue {
238 let mref = self.borrow_data();
239 let cell = match mref.get(key) {
240 Some(v) => v,
241 None => &self.default_val,
242 };
243 cell.clone().into_inner()
244 }
245
246 #[inline]
247 pub fn try_get(&self, key: &GosValue) -> Option<GosValue> {
248 let mref = self.borrow_data();
249 mref.get(key).map(|x| x.clone().into_inner())
250 }
251
252 #[inline]
255 pub fn touch_key(&self, key: &GosValue) {
256 if self.borrow_data().get(&key).is_none() {
257 self.borrow_data_mut()
258 .insert(key.clone(), self.default_val.clone());
259 }
260 }
261
262 #[inline]
263 pub fn len(&self) -> usize {
264 self.borrow_data().len()
265 }
266
267 #[inline]
268 pub fn borrow_data_mut(&self) -> RefMut<GosHashMap> {
269 self.map.as_ref().unwrap().borrow_mut()
270 }
271
272 #[inline]
273 pub fn borrow_data(&self) -> Ref<GosHashMap> {
274 self.map.as_ref().unwrap().borrow()
275 }
276
277 #[inline]
278 pub fn clone_inner(&self) -> Rc<RefCell<GosHashMap>> {
279 self.map.as_ref().unwrap().clone()
280 }
281}
282
283impl Clone for MapObj {
284 fn clone(&self) -> Self {
285 MapObj {
286 meta: self.meta,
287 default_val: self.default_val.clone(),
288 map: self.map.clone(),
289 }
290 }
291}
292
293impl PartialEq for MapObj {
294 fn eq(&self, _other: &MapObj) -> bool {
295 unreachable!() }
297}
298
299impl Eq for MapObj {}
300
301impl Display for MapObj {
302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303 f.write_str("map[")?;
304 if let Some(m) = &self.map {
305 for (i, kv) in m.borrow().iter().enumerate() {
306 if i > 0 {
307 f.write_char(' ')?;
308 }
309 let v: &GosValue = &kv.1.borrow();
310 write!(f, "{}:{}", kv.0, v)?
311 }
312 }
313 f.write_char(']')
314 }
315}
316
317pub type GosVec = Vec<RefCell<GosValue>>;
321
322#[derive(Debug)]
323pub struct ArrayObj {
324 pub meta: GosMetadata,
325 pub vec: Rc<RefCell<GosVec>>,
326}
327
328impl ArrayObj {
329 pub fn with_size(size: usize, val: &GosValue, meta: GosMetadata, gcos: &GcoVec) -> ArrayObj {
330 let mut v = GosVec::with_capacity(size);
331 for _ in 0..size {
332 v.push(RefCell::new(val.copy_semantic(gcos)))
333 }
334 ArrayObj {
335 meta: meta,
336 vec: Rc::new(RefCell::new(v)),
337 }
338 }
339
340 pub fn with_data(val: Vec<GosValue>, meta: GosMetadata) -> ArrayObj {
341 ArrayObj {
342 meta: meta,
343 vec: Rc::new(RefCell::new(
344 val.into_iter().map(|x| RefCell::new(x)).collect(),
345 )),
346 }
347 }
348
349 pub fn deep_clone(&self, gcos: &GcoVec) -> ArrayObj {
350 ArrayObj {
351 meta: self.meta,
352 vec: Rc::new(RefCell::new(
353 self.borrow_data()
354 .iter()
355 .map(|x| RefCell::new(x.borrow().deep_clone(gcos)))
356 .collect(),
357 )),
358 }
359 }
360
361 #[inline]
362 pub fn len(&self) -> usize {
363 self.borrow_data().len()
364 }
365
366 #[inline]
367 pub fn borrow_data_mut(&self) -> std::cell::RefMut<GosVec> {
368 self.vec.borrow_mut()
369 }
370
371 #[inline]
372 pub fn borrow_data(&self) -> std::cell::Ref<GosVec> {
373 self.vec.borrow()
374 }
375
376 #[inline]
377 pub fn get(&self, i: usize) -> Option<GosValue> {
378 self.borrow_data().get(i).map(|x| x.clone().into_inner())
379 }
380
381 #[inline]
382 pub fn set_from(&self, other: &ArrayObj) {
383 *self.borrow_data_mut() = other.borrow_data().clone()
384 }
385}
386
387impl Display for ArrayObj {
388 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
389 f.write_char('[')?;
390 for (i, e) in self.vec.borrow().iter().enumerate() {
391 if i > 0 {
392 f.write_char(' ')?;
393 }
394 write!(f, "{}", e.borrow())?
395 }
396 f.write_char(']')
397 }
398}
399
400impl Hash for ArrayObj {
401 fn hash<H: Hasher>(&self, state: &mut H) {
402 for e in self.borrow_data().iter() {
403 e.borrow().hash(state);
404 }
405 }
406}
407
408impl Eq for ArrayObj {}
409
410impl PartialEq for ArrayObj {
411 fn eq(&self, b: &ArrayObj) -> bool {
412 if self.borrow_data().len() != b.borrow_data().len() {
413 return false;
414 }
415 for (i, e) in self.borrow_data().iter().enumerate() {
416 if e != b.borrow_data().get(i).unwrap() {
417 return false;
418 }
419 }
420 true
421 }
422}
423
424impl Clone for ArrayObj {
425 fn clone(&self) -> Self {
426 ArrayObj {
427 meta: self.meta,
428 vec: self.vec.clone(),
429 }
430 }
431}
432
433#[derive(Debug)]
437pub struct SliceObj {
438 pub meta: GosMetadata,
439 begin: Cell<usize>,
440 end: Cell<usize>,
441 soft_cap: Cell<usize>, pub vec: Option<Rc<RefCell<GosVec>>>,
443}
444
445impl<'a> SliceObj {
446 pub fn new(
447 len: usize,
448 cap: usize,
449 meta: GosMetadata,
450 default_val: Option<&GosValue>,
451 ) -> SliceObj {
452 assert!(cap >= len);
453 let mut val = SliceObj {
454 meta: meta,
455 begin: Cell::from(0),
456 end: Cell::from(0),
457 soft_cap: Cell::from(cap),
458 vec: Some(Rc::new(RefCell::new(Vec::with_capacity(cap)))),
459 };
460 for _ in 0..len {
461 val.push(default_val.unwrap().clone());
462 }
463 val
464 }
465
466 pub fn with_data(val: Vec<GosValue>, meta: GosMetadata) -> SliceObj {
467 SliceObj {
468 meta: meta,
469 begin: Cell::from(0),
470 end: Cell::from(val.len()),
471 soft_cap: Cell::from(val.len()),
472 vec: Some(Rc::new(RefCell::new(
473 val.into_iter().map(|x| RefCell::new(x)).collect(),
474 ))),
475 }
476 }
477
478 pub fn with_array(arr: &ArrayObj, begin: isize, end: isize) -> SliceObj {
479 let elem_meta = GosMetadata::new_slice_from_array(arr.meta);
480 let len = arr.len();
481 let self_end = len as isize + 1;
482 let bi = begin as usize;
483 let ei = ((self_end + end) % self_end) as usize;
484 SliceObj {
485 meta: elem_meta,
486 begin: Cell::from(bi),
487 end: Cell::from(ei),
488 soft_cap: Cell::from(len),
489 vec: Some(arr.vec.clone()),
490 }
491 }
492
493 pub fn new_nil(meta: GosMetadata) -> SliceObj {
494 SliceObj {
495 meta: meta,
496 begin: Cell::from(0),
497 end: Cell::from(0),
498 soft_cap: Cell::from(0),
499 vec: None,
500 }
501 }
502
503 pub fn set_from(&self, other: &SliceObj) {
504 self.begin.set(other.begin());
505 self.end.set(other.end());
506 self.soft_cap.set(other.soft_cap());
507 *self.borrow_data_mut() = other.borrow_data().clone()
508 }
509
510 pub fn deep_clone(&self, gcos: &GcoVec) -> SliceObj {
512 SliceObj {
513 meta: self.meta,
514 begin: Cell::from(0),
515 end: Cell::from(self.cap()),
516 soft_cap: Cell::from(self.cap()),
517 vec: self.vec.clone().map(|vec| {
518 Rc::new(RefCell::new(Vec::from_iter(
519 vec.borrow()[self.begin()..self.end()]
520 .iter()
521 .map(|x| RefCell::new(x.borrow().deep_clone(gcos))),
522 )))
523 }),
524 }
525 }
526
527 #[inline]
528 pub fn is_nil(&self) -> bool {
529 self.vec.is_none()
530 }
531
532 #[inline]
533 pub fn begin(&self) -> usize {
534 self.begin.get()
535 }
536
537 #[inline]
538 pub fn end(&self) -> usize {
539 self.end.get()
540 }
541
542 #[inline]
543 pub fn soft_cap(&self) -> usize {
544 self.soft_cap.get()
545 }
546
547 #[inline]
548 pub fn len(&self) -> usize {
549 self.end() - self.begin()
550 }
551
552 #[inline]
553 pub fn cap(&self) -> usize {
554 self.soft_cap() - self.begin()
555 }
556
557 #[inline]
558 pub fn borrow(&self) -> SliceRef {
559 SliceRef::new(self)
560 }
561
562 #[inline]
563 pub fn borrow_data_mut(&self) -> std::cell::RefMut<GosVec> {
564 match &self.vec {
565 Some(v) => v.borrow_mut(),
566 None => unreachable!(), }
568 }
569
570 #[inline]
571 pub fn borrow_data(&self) -> std::cell::Ref<GosVec> {
572 match &self.vec {
573 Some(v) => v.borrow(),
574 None => unreachable!(), }
576 }
577
578 #[inline]
579 pub fn push(&mut self, val: GosValue) {
580 self.try_grow_vec(self.len() + 1);
581 self.borrow_data_mut().push(RefCell::new(val));
582 *self.end.get_mut() += 1;
583 }
584
585 #[inline]
586 pub fn append(&mut self, vals: &mut GosVec) {
587 let new_len = self.len() + vals.len();
588 self.try_grow_vec(new_len);
589 self.borrow_data_mut().append(vals);
590 *self.end.get_mut() = self.begin() + new_len;
591 }
592
593 #[inline]
594 pub fn get(&self, i: usize) -> Option<GosValue> {
595 self.borrow_data()
596 .get(self.begin() + i)
597 .map(|x| x.clone().into_inner())
598 }
599
600 #[inline]
601 pub fn set(&self, i: usize, val: GosValue) {
602 self.borrow_data()[self.begin() + i].replace(val);
603 }
604
605 #[inline]
606 pub fn slice(&self, begin: isize, end: isize, max: isize) -> SliceObj {
607 let self_len = self.len() as isize + 1;
608 let self_cap = self.cap() as isize + 1;
609 let bi = begin as usize;
610 let ei = ((self_len + end) % self_len) as usize;
611 let mi = ((self_cap + max) % self_cap) as usize;
612 SliceObj {
613 meta: self.meta,
614 begin: Cell::from(self.begin() + bi),
615 end: Cell::from(self.begin() + ei),
616 soft_cap: Cell::from(self.begin() + mi),
617 vec: self.vec.clone(),
618 }
619 }
620
621 #[inline]
622 pub fn get_vec(&self) -> Vec<GosValue> {
623 self.borrow_data()
624 .iter()
625 .map(|x| x.borrow().clone())
626 .collect()
627 }
628
629 fn try_grow_vec(&mut self, len: usize) {
630 let mut cap = self.cap();
631 assert!(cap >= self.len());
632 if cap >= len {
633 return;
634 }
635 while cap < len {
636 if cap < 1024 {
637 cap *= 2
638 } else {
639 cap = (cap as f32 * 1.25) as usize
640 }
641 }
642 let data_len = self.len();
643 let mut vec = Vec::from_iter(self.borrow_data()[self.begin()..self.end()].iter().cloned());
644 vec.reserve_exact(cap - vec.len());
645 self.vec = Some(Rc::new(RefCell::new(vec)));
646 self.begin.set(0);
647 self.end.set(data_len);
648 self.soft_cap.set(cap);
649 }
650}
651
652impl Clone for SliceObj {
653 fn clone(&self) -> Self {
654 SliceObj {
655 meta: self.meta,
656 begin: self.begin.clone(),
657 end: self.end.clone(),
658 soft_cap: self.soft_cap.clone(),
659 vec: self.vec.clone(),
660 }
661 }
662}
663
664impl Display for SliceObj {
665 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
666 f.write_char('[')?;
667 for (i, e) in self.borrow().iter().enumerate() {
668 if i > 0 {
669 f.write_char(' ')?;
670 }
671 write!(f, "{}", e.borrow())?
672 }
673 f.write_char(']')
674 }
675}
676
677pub struct SliceRef<'a> {
678 vec_ref: Ref<'a, GosVec>,
679 begin: usize,
680 end: usize,
681}
682
683pub type SliceIter<'a> = std::slice::Iter<'a, RefCell<GosValue>>;
684
685pub type SliceEnumIter<'a> = std::iter::Enumerate<SliceIter<'a>>;
686
687impl<'a> SliceRef<'a> {
688 pub fn new(s: &SliceObj) -> SliceRef {
689 SliceRef {
690 vec_ref: s.borrow_data(),
691 begin: s.begin(),
692 end: s.end(),
693 }
694 }
695
696 pub fn iter(&self) -> SliceIter {
697 self.vec_ref[self.begin..self.end].iter()
698 }
699
700 #[inline]
701 pub fn get(&self, i: usize) -> Option<&RefCell<GosValue>> {
702 self.vec_ref.get(self.begin + i)
703 }
704}
705
706impl PartialEq for SliceObj {
707 fn eq(&self, _other: &SliceObj) -> bool {
708 unreachable!() }
710}
711
712impl Eq for SliceObj {}
713
714#[derive(Clone, Debug)]
718pub struct StructObj {
719 pub meta: GosMetadata,
720 pub fields: Vec<GosValue>,
721}
722
723impl StructObj {
724 pub fn deep_clone(&self, gcos: &GcoVec) -> StructObj {
725 StructObj {
726 meta: self.meta,
727 fields: Vec::from_iter(self.fields.iter().map(|x| x.deep_clone(gcos))),
728 }
729 }
730}
731
732impl Eq for StructObj {}
733
734impl PartialEq for StructObj {
735 #[inline]
736 fn eq(&self, other: &StructObj) -> bool {
737 for (i, f) in self.fields.iter().enumerate() {
738 if f != &other.fields[i] {
739 return false;
740 }
741 }
742 return true;
743 }
744}
745
746impl Hash for StructObj {
747 #[inline]
748 fn hash<H: Hasher>(&self, state: &mut H) {
749 for f in self.fields.iter() {
750 f.hash(state)
751 }
752 }
753}
754
755impl Display for StructObj {
756 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
757 f.write_char('{')?;
758 for (i, fld) in self.fields.iter().enumerate() {
759 if i > 0 {
760 f.write_char(' ')?;
761 }
762 write!(f, "{}", fld)?
763 }
764 f.write_char('}')
765 }
766}
767
768#[derive(Clone, Debug)]
772pub struct UnderlyingFfi {
773 pub ffi_obj: Rc<RefCell<dyn Ffi>>,
774 pub methods: Vec<(String, GosMetadata)>,
775}
776
777impl UnderlyingFfi {
778 pub fn new(obj: Rc<RefCell<dyn Ffi>>, methods: Vec<(String, GosMetadata)>) -> UnderlyingFfi {
779 UnderlyingFfi {
780 ffi_obj: obj,
781 methods: methods,
782 }
783 }
784}
785
786#[derive(Clone, Debug)]
787pub enum IfaceUnderlying {
788 None,
789 Gos(GosValue, Option<Rc<Vec<FunctionKey>>>),
790 Ffi(UnderlyingFfi),
791}
792
793impl Eq for IfaceUnderlying {}
794
795impl PartialEq for IfaceUnderlying {
796 #[inline]
797 fn eq(&self, other: &IfaceUnderlying) -> bool {
798 match (self, other) {
799 (Self::None, Self::None) => true,
800 (Self::Gos(x, _), Self::Gos(y, _)) => x == y,
801 (Self::Ffi(x), Self::Ffi(y)) => Rc::ptr_eq(&x.ffi_obj, &y.ffi_obj),
802 _ => false,
803 }
804 }
805}
806
807#[derive(Clone, Debug)]
808pub struct InterfaceObj {
809 pub meta: GosMetadata,
810 underlying: IfaceUnderlying,
813}
814
815impl InterfaceObj {
816 pub fn new(meta: GosMetadata, underlying: IfaceUnderlying) -> InterfaceObj {
817 InterfaceObj {
818 meta: meta,
819 underlying: underlying,
820 }
821 }
822
823 #[inline]
824 pub fn underlying(&self) -> &IfaceUnderlying {
825 &self.underlying
826 }
827
828 #[inline]
829 pub fn set_underlying(&mut self, v: IfaceUnderlying) {
830 self.underlying = v;
831 }
832
833 #[inline]
834 pub fn underlying_value(&self) -> Option<&GosValue> {
835 match self.underlying() {
836 IfaceUnderlying::Gos(v, _) => Some(v),
837 _ => None,
838 }
839 }
840
841 #[inline]
842 pub fn is_nil(&self) -> bool {
843 self.underlying() == &IfaceUnderlying::None
844 }
845
846 pub fn ref_sub_one(&self) {
848 match self.underlying() {
849 IfaceUnderlying::Gos(v, _) => v.ref_sub_one(),
850 _ => {}
851 };
852 }
853
854 pub fn mark_dirty(&self, queue: &mut RCQueue) {
856 match self.underlying() {
857 IfaceUnderlying::Gos(v, _) => v.mark_dirty(queue),
858 _ => {}
859 };
860 }
861}
862
863impl Eq for InterfaceObj {}
864
865impl PartialEq for InterfaceObj {
866 #[inline]
867 fn eq(&self, other: &InterfaceObj) -> bool {
868 self.underlying() == other.underlying()
869 }
870}
871
872impl Hash for InterfaceObj {
873 #[inline]
874 fn hash<H: Hasher>(&self, state: &mut H) {
875 match self.underlying() {
876 IfaceUnderlying::Gos(v, _) => v.hash(state),
877 IfaceUnderlying::Ffi(ffi) => Rc::as_ptr(&ffi.ffi_obj).hash(state),
878 IfaceUnderlying::None => 0.hash(state),
879 }
880 }
881}
882
883impl Display for InterfaceObj {
884 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
885 match self.underlying() {
886 IfaceUnderlying::Gos(v, _) => write!(f, "{}", v),
887 IfaceUnderlying::Ffi(ffi) => write!(f, "<ffi>{:?}", ffi.ffi_obj.borrow()),
888 IfaceUnderlying::None => f.write_str("<nil>"),
889 }
890 }
891}
892
893#[derive(Clone, Debug)]
897pub struct ChannelObj {
898 pub meta: GosMetadata,
899 pub chan: Channel,
900}
901
902impl ChannelObj {
903 pub fn new(meta: GosMetadata, cap: usize) -> ChannelObj {
904 ChannelObj {
905 meta: meta,
906 chan: Channel::new(cap),
907 }
908 }
909
910 #[inline]
911 pub fn len(&self) -> usize {
912 self.chan.len()
913 }
914
915 #[inline]
916 pub fn cap(&self) -> usize {
917 self.chan.cap()
918 }
919
920 #[inline]
921 pub fn close(&self) {
922 self.chan.close()
923 }
924
925 pub async fn send(&self, v: &GosValue) -> EmptyResult {
926 self.chan.send(v).await
927 }
928
929 pub async fn recv(&self) -> Option<GosValue> {
930 self.chan.recv().await
931 }
932}
933
934#[derive(Debug, Clone)]
947pub enum PointerObj {
948 Released,
949 UpVal(UpValue),
950 Struct(Rc<(RefCell<StructObj>, RCount)>, GosMetadata),
951 Array(Rc<(ArrayObj, RCount)>, GosMetadata),
952 Slice(Rc<(SliceObj, RCount)>, GosMetadata),
953 Map(Rc<(MapObj, RCount)>, GosMetadata),
954 SliceMember(Rc<(SliceObj, RCount)>, OpIndex),
955 StructField(Rc<(RefCell<StructObj>, RCount)>, OpIndex),
956 PkgMember(PackageKey, OpIndex),
957}
958
959impl PointerObj {
960 #[inline]
961 pub fn new_local(val: GosValue) -> PointerObj {
962 match val {
963 GosValue::Named(s) => match &s.0 {
964 GosValue::Struct(stru) => PointerObj::Struct(stru.clone(), s.1),
965 GosValue::Array(arr) => PointerObj::Array(arr.clone(), s.1),
966 GosValue::Slice(slice) => PointerObj::Slice(slice.clone(), s.1),
967 GosValue::Map(map) => PointerObj::Map(map.clone(), s.1),
968 _ => {
969 dbg!(s);
970 unreachable!()
971 }
972 },
973 GosValue::Struct(s) => PointerObj::Struct(s.clone(), GosMetadata::Untyped),
974 GosValue::Array(a) => PointerObj::Array(a.clone(), GosMetadata::Untyped),
975 GosValue::Slice(s) => PointerObj::Slice(s.clone(), GosMetadata::Untyped),
976 GosValue::Map(m) => PointerObj::Map(m.clone(), GosMetadata::Untyped),
977 _ => {
978 dbg!(val);
979 unreachable!()
980 }
981 }
982 }
983
984 #[inline]
985 pub fn set_local_ref_type(&self, val: GosValue) {
986 match self {
987 Self::Struct(v, _) => {
988 let mref: &mut StructObj = &mut v.0.borrow_mut();
989 *mref = val.try_get_struct().unwrap().0.borrow().clone();
990 }
991 _ => unreachable!(),
992 }
993 }
994
995 pub fn deep_clone(&self, gcos: &GcoVec) -> PointerObj {
996 match &self {
997 PointerObj::Released => PointerObj::Released,
998 PointerObj::Struct(s, m) => PointerObj::Struct(
999 Rc::new((RefCell::new(s.0.borrow().deep_clone(gcos)), Cell::new(0))),
1000 *m,
1001 ),
1002 PointerObj::Slice(s, m) => {
1003 PointerObj::Slice(Rc::new((s.0.deep_clone(gcos), Cell::new(0))), *m)
1004 }
1005 PointerObj::Map(map, m) => {
1006 PointerObj::Map(Rc::new((map.0.deep_clone(gcos), Cell::new(0))), *m)
1007 }
1008 _ => unreachable!(),
1009 }
1010 }
1011
1012 pub fn ref_sub_one(&self) {
1014 match &self {
1015 PointerObj::UpVal(uv) => uv.ref_sub_one(),
1016 PointerObj::Struct(s, _) => s.1.set(s.1.get() - 1),
1017 PointerObj::Slice(s, _) => s.1.set(s.1.get() - 1),
1018 PointerObj::Map(s, _) => s.1.set(s.1.get() - 1),
1019 PointerObj::SliceMember(s, _) => s.1.set(s.1.get() - 1),
1020 PointerObj::StructField(s, _) => s.1.set(s.1.get() - 1),
1021 _ => {}
1022 };
1023 }
1024
1025 pub fn mark_dirty(&self, queue: &mut RCQueue) {
1027 match &self {
1028 PointerObj::UpVal(uv) => uv.mark_dirty(queue),
1029 PointerObj::Struct(s, _) => rcount_mark_and_queue(&s.1, queue),
1030 PointerObj::Slice(s, _) => rcount_mark_and_queue(&s.1, queue),
1031 PointerObj::Map(s, _) => rcount_mark_and_queue(&s.1, queue),
1032 PointerObj::SliceMember(s, _) => rcount_mark_and_queue(&s.1, queue),
1033 PointerObj::StructField(s, _) => rcount_mark_and_queue(&s.1, queue),
1034 _ => {}
1035 };
1036 }
1037}
1038
1039impl Eq for PointerObj {}
1040
1041impl PartialEq for PointerObj {
1042 #[inline]
1043 fn eq(&self, other: &PointerObj) -> bool {
1044 match (self, other) {
1045 (Self::UpVal(x), Self::UpVal(y)) => x == y,
1046 (Self::Struct(x, _), Self::Struct(y, _)) => x == y,
1047 (Self::Array(x, _), Self::Array(y, _)) => x == y,
1048 (Self::Slice(x, _), Self::Slice(y, _)) => x == y,
1049 (Self::Map(x, _), Self::Map(y, _)) => x == y,
1050 (Self::SliceMember(x, ix), Self::SliceMember(y, iy)) => Rc::ptr_eq(x, y) && ix == iy,
1051 (Self::StructField(x, ix), Self::StructField(y, iy)) => Rc::ptr_eq(x, y) && ix == iy,
1052 (Self::PkgMember(ka, ix), Self::PkgMember(kb, iy)) => ka == kb && ix == iy,
1053 _ => false,
1054 }
1055 }
1056}
1057
1058impl Hash for PointerObj {
1059 fn hash<H: Hasher>(&self, state: &mut H) {
1060 match self {
1061 Self::UpVal(x) => x.hash(state),
1062 Self::Struct(s, _) => Rc::as_ptr(s).hash(state),
1063 Self::Array(s, _) => Rc::as_ptr(s).hash(state),
1064 Self::Slice(s, _) => Rc::as_ptr(s).hash(state),
1065 Self::Map(s, _) => Rc::as_ptr(s).hash(state),
1066 Self::SliceMember(s, index) => {
1067 Rc::as_ptr(s).hash(state);
1068 index.hash(state);
1069 }
1070 Self::StructField(s, index) => {
1071 Rc::as_ptr(s).hash(state);
1072 index.hash(state);
1073 }
1074 Self::PkgMember(p, index) => {
1075 p.hash(state);
1076 index.hash(state);
1077 }
1078 Self::Released => unreachable!(),
1079 }
1080 }
1081}
1082
1083impl Display for PointerObj {
1084 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1085 match self {
1086 Self::UpVal(uv) => f.write_fmt(format_args!("{:p}", Rc::as_ptr(&uv.inner))),
1087 Self::Struct(s, _) => f.write_fmt(format_args!("{:p}", Rc::as_ptr(&s))),
1088 Self::Array(s, _) => f.write_fmt(format_args!("{:p}", Rc::as_ptr(&s))),
1089 Self::Slice(s, _) => f.write_fmt(format_args!("{:p}", Rc::as_ptr(&s))),
1090 Self::Map(m, _) => f.write_fmt(format_args!("{:p}", Rc::as_ptr(&m))),
1091 Self::SliceMember(s, i) => f.write_fmt(format_args!("{:p}i{}", Rc::as_ptr(&s), i)),
1092 Self::StructField(s, i) => f.write_fmt(format_args!("{:p}i{}", Rc::as_ptr(&s), i)),
1093 Self::PkgMember(p, i) => f.write_fmt(format_args!("{:x}i{}", key_to_u64(*p), i)),
1094 Self::Released => f.write_str("released!!!"),
1095 }
1096 }
1097}
1098
1099#[derive(Clone, Debug)]
1103pub struct ValueDesc {
1104 pub func: FunctionKey,
1105 pub index: OpIndex,
1106 pub typ: ValueType,
1107 pub is_up_value: bool,
1108 pub stack: Weak<RefCell<Stack>>,
1109 pub stack_base: OpIndex,
1110}
1111
1112impl Eq for ValueDesc {}
1113
1114impl PartialEq for ValueDesc {
1115 #[inline]
1116 fn eq(&self, other: &ValueDesc) -> bool {
1117 self.index == other.index
1118 }
1119}
1120
1121impl ValueDesc {
1122 pub fn new(func: FunctionKey, index: OpIndex, typ: ValueType, is_up_value: bool) -> ValueDesc {
1123 ValueDesc {
1124 func: func,
1125 index: index,
1126 typ: typ,
1127 is_up_value: is_up_value,
1128 stack: Weak::new(),
1129 stack_base: 0,
1130 }
1131 }
1132
1133 pub fn clone_with_stack(&self, stack: Weak<RefCell<Stack>>, stack_base: OpIndex) -> ValueDesc {
1134 ValueDesc {
1135 func: self.func,
1136 index: self.index,
1137 typ: self.typ,
1138 is_up_value: self.is_up_value,
1139 stack: stack,
1140 stack_base: stack_base,
1141 }
1142 }
1143}
1144
1145#[derive(Clone, Debug, PartialEq, Eq)]
1146pub enum UpValueState {
1147 Open(ValueDesc), Closed(GosValue),
1151}
1152
1153#[derive(Clone, Debug, PartialEq)]
1154pub struct UpValue {
1155 pub inner: Rc<RefCell<UpValueState>>,
1156}
1157
1158impl UpValue {
1159 pub fn new(d: ValueDesc) -> UpValue {
1160 UpValue {
1161 inner: Rc::new(RefCell::new(UpValueState::Open(d))),
1162 }
1163 }
1164
1165 pub fn new_closed(v: GosValue) -> UpValue {
1166 UpValue {
1167 inner: Rc::new(RefCell::new(UpValueState::Closed(v))),
1168 }
1169 }
1170
1171 pub fn downgrade(&self) -> WeakUpValue {
1172 WeakUpValue {
1173 inner: Rc::downgrade(&self.inner),
1174 }
1175 }
1176
1177 pub fn desc(&self) -> ValueDesc {
1178 let r: &UpValueState = &self.inner.borrow();
1179 match r {
1180 UpValueState::Open(d) => d.clone(),
1181 _ => unreachable!(),
1182 }
1183 }
1184
1185 pub fn close(&self, val: GosValue) {
1186 *self.inner.borrow_mut() = UpValueState::Closed(val);
1187 }
1188
1189 pub fn ref_sub_one(&self) {
1191 let state: &UpValueState = &self.inner.borrow();
1192 if let UpValueState::Closed(uvs) = state {
1193 uvs.ref_sub_one()
1194 }
1195 }
1196
1197 pub fn mark_dirty(&self, queue: &mut RCQueue) {
1199 let state: &UpValueState = &self.inner.borrow();
1200 if let UpValueState::Closed(uvs) = state {
1201 uvs.mark_dirty(queue)
1202 }
1203 }
1204}
1205
1206impl Hash for UpValue {
1207 #[inline]
1208 fn hash<H: Hasher>(&self, state: &mut H) {
1209 let b: &UpValueState = &self.inner.borrow();
1210 match b {
1211 UpValueState::Open(desc) => desc.index.hash(state),
1212 UpValueState::Closed(_) => Rc::as_ptr(&self.inner).hash(state),
1213 }
1214 }
1215}
1216
1217#[derive(Clone, Debug)]
1218pub struct WeakUpValue {
1219 pub inner: Weak<RefCell<UpValueState>>,
1220}
1221
1222impl WeakUpValue {
1223 pub fn upgrade(&self) -> Option<UpValue> {
1224 Weak::upgrade(&self.inner).map(|x| UpValue { inner: x })
1225 }
1226}
1227
1228#[derive(Clone, Debug)]
1229pub struct FfiClosureObj {
1230 pub ffi: Rc<RefCell<dyn Ffi>>,
1231 pub func_name: String,
1232 pub meta: GosMetadata,
1233}
1234
1235#[derive(Clone, Debug)]
1236pub struct ClosureObj {
1237 pub func: Option<FunctionKey>,
1238 pub uvs: Option<HashMap<usize, UpValue>>,
1239 pub recv: Option<GosValue>,
1240
1241 pub ffi: Option<Box<FfiClosureObj>>,
1242
1243 pub meta: GosMetadata,
1244}
1245
1246impl ClosureObj {
1247 pub fn new_gos(key: FunctionKey, fobjs: &FunctionObjs, recv: Option<GosValue>) -> ClosureObj {
1248 let func = &fobjs[key];
1249 let uvs: Option<HashMap<usize, UpValue>> = if func.up_ptrs.len() > 0 {
1250 Some(
1251 func.up_ptrs
1252 .iter()
1253 .enumerate()
1254 .filter(|(_, x)| x.is_up_value)
1255 .map(|(i, x)| (i, UpValue::new(x.clone())))
1256 .collect(),
1257 )
1258 } else {
1259 None
1260 };
1261 ClosureObj {
1262 func: Some(key),
1263 uvs: uvs,
1264 recv: recv,
1265 ffi: None,
1266 meta: func.meta,
1267 }
1268 }
1269
1270 #[inline]
1271 pub fn new_ffi(ffi: FfiClosureObj) -> ClosureObj {
1272 let m = ffi.meta;
1273 ClosureObj {
1274 func: None,
1275 uvs: None,
1276 recv: None,
1277 ffi: Some(Box::new(ffi)),
1278 meta: m,
1279 }
1280 }
1281
1282 pub fn ref_sub_one(&self) {
1284 if self.func.is_some() {
1285 if let Some(uvs) = &self.uvs {
1286 for (_, v) in uvs.iter() {
1287 v.ref_sub_one()
1288 }
1289 }
1290 if let Some(recv) = &self.recv {
1291 recv.ref_sub_one()
1292 }
1293 }
1294 }
1295
1296 pub fn mark_dirty(&self, queue: &mut RCQueue) {
1298 if self.func.is_some() {
1299 if let Some(uvs) = &self.uvs {
1300 for (_, v) in uvs.iter() {
1301 v.mark_dirty(queue)
1302 }
1303 }
1304 if let Some(recv) = &self.recv {
1305 recv.mark_dirty(queue)
1306 }
1307 }
1308 }
1309}
1310
1311#[derive(Clone, Debug)]
1317pub struct PackageVal {
1318 name: String,
1319 members: Vec<Rc<RefCell<GosValue>>>, member_indices: HashMap<String, OpIndex>,
1321 var_mapping: Option<HashMap<OpIndex, OpIndex>>,
1323}
1324
1325impl PackageVal {
1326 pub fn new(name: String) -> PackageVal {
1327 PackageVal {
1328 name: name,
1329 members: Vec::new(),
1330 member_indices: HashMap::new(),
1331 var_mapping: Some(HashMap::new()),
1332 }
1333 }
1334
1335 pub fn add_member(&mut self, name: String, val: GosValue) -> OpIndex {
1336 self.members.push(Rc::new(RefCell::new(val)));
1337 let index = (self.members.len() - 1) as OpIndex;
1338 self.member_indices.insert(name, index);
1339 index as OpIndex
1340 }
1341
1342 pub fn add_var_mapping(&mut self, name: String, fn_index: OpIndex) -> OpIndex {
1343 let index = *self.get_member_index(&name).unwrap();
1344 self.var_mapping
1345 .as_mut()
1346 .unwrap()
1347 .insert(fn_index.into(), index);
1348 index
1349 }
1350
1351 pub fn var_mut(&self, fn_member_index: OpIndex) -> RefMut<GosValue> {
1352 let index = self.var_mapping.as_ref().unwrap()[&fn_member_index];
1353 self.members[index as usize].borrow_mut()
1354 }
1355
1356 pub fn var_count(&self) -> usize {
1357 self.var_mapping.as_ref().unwrap().len()
1358 }
1359
1360 pub fn get_member_index(&self, name: &str) -> Option<&OpIndex> {
1361 self.member_indices.get(name)
1362 }
1363
1364 pub fn inited(&self) -> bool {
1365 self.var_mapping.is_none()
1366 }
1367
1368 pub fn set_inited(&mut self) {
1369 self.var_mapping = None
1370 }
1371
1372 #[inline]
1373 pub fn member(&self, i: OpIndex) -> Ref<GosValue> {
1374 self.members[i as usize].borrow()
1375 }
1376
1377 #[inline]
1378 pub fn member_mut(&self, i: OpIndex) -> RefMut<GosValue> {
1379 self.members[i as usize].borrow_mut()
1380 }
1381}
1382
1383#[derive(Clone, Copy, Debug, PartialEq)]
1388pub enum EntIndex {
1389 Const(OpIndex),
1390 LocalVar(OpIndex),
1391 UpValue(OpIndex),
1392 PackageMember(PackageKey, IdentKey),
1393 BuiltInVal(Opcode), BuiltInType(GosMetadata),
1395 Blank,
1396}
1397
1398impl From<EntIndex> for OpIndex {
1399 fn from(t: EntIndex) -> OpIndex {
1400 match t {
1401 EntIndex::Const(i) => i,
1402 EntIndex::LocalVar(i) => i,
1403 EntIndex::UpValue(i) => i,
1404 EntIndex::PackageMember(_, _) => unreachable!(),
1405 EntIndex::BuiltInVal(_) => unreachable!(),
1406 EntIndex::BuiltInType(_) => unreachable!(),
1407 EntIndex::Blank => unreachable!(),
1408 }
1409 }
1410}
1411
1412#[derive(Eq, PartialEq, Copy, Clone, Debug)]
1413pub enum FuncFlag {
1414 Default,
1415 PkgCtor,
1416 HasDefer,
1417}
1418
1419#[derive(Clone, Debug)]
1421pub struct FunctionVal {
1422 pub package: PackageKey,
1423 pub meta: GosMetadata,
1424 code: Vec<Instruction>,
1425 pos: Vec<Option<usize>>,
1426 pub consts: Vec<GosValue>,
1427 pub up_ptrs: Vec<ValueDesc>,
1428
1429 pub ret_zeros: Vec<GosValue>,
1430 pub local_zeros: Vec<GosValue>,
1431 pub flag: FuncFlag,
1432
1433 param_count: usize,
1434 entities: HashMap<EntityKey, EntIndex>,
1435 uv_entities: HashMap<EntityKey, EntIndex>,
1436 local_alloc: u16,
1437}
1438
1439impl FunctionVal {
1440 pub fn new(
1441 package: PackageKey,
1442 meta: GosMetadata,
1443 objs: &VMObjects,
1444 gcv: &GcoVec,
1445 flag: FuncFlag,
1446 ) -> FunctionVal {
1447 match &objs.metas[meta.as_non_ptr()] {
1448 MetadataType::Signature(s) => {
1449 let mut returns = vec![];
1450 for m in s.results.iter() {
1451 returns.push(zero_val!(m, objs, gcv));
1452 }
1453 let params = s.params.len() + s.recv.map_or(0, |_| 1);
1454 FunctionVal {
1455 package: package,
1456 meta: meta,
1457 code: Vec::new(),
1458 pos: Vec::new(),
1459 consts: Vec::new(),
1460 up_ptrs: Vec::new(),
1461 ret_zeros: returns,
1462 local_zeros: Vec::new(),
1463 flag: flag,
1464 param_count: params,
1465 entities: HashMap::new(),
1466 uv_entities: HashMap::new(),
1467 local_alloc: 0,
1468 }
1469 }
1470 _ => unreachable!(),
1471 }
1472 }
1473
1474 #[inline]
1475 pub fn code(&self) -> &Vec<Instruction> {
1476 &self.code
1477 }
1478
1479 #[inline]
1480 pub fn instruction_mut(&mut self, i: usize) -> &mut Instruction {
1481 self.code.get_mut(i).unwrap()
1482 }
1483
1484 #[inline]
1485 pub fn pos(&self) -> &Vec<Option<usize>> {
1486 &self.pos
1487 }
1488
1489 #[inline]
1490 pub fn param_count(&self) -> usize {
1491 self.param_count
1492 }
1493
1494 #[inline]
1495 pub fn ret_count(&self) -> usize {
1496 self.ret_zeros.len()
1497 }
1498
1499 #[inline]
1500 pub fn is_ctor(&self) -> bool {
1501 self.flag == FuncFlag::PkgCtor
1502 }
1503
1504 #[inline]
1505 pub fn local_count(&self) -> usize {
1506 self.local_alloc as usize - self.param_count() - self.ret_count()
1507 }
1508
1509 #[inline]
1510 pub fn entity_index(&self, entity: &EntityKey) -> Option<&EntIndex> {
1511 self.entities.get(entity)
1512 }
1513
1514 #[inline]
1515 pub fn const_val(&self, index: OpIndex) -> &GosValue {
1516 &self.consts[index as usize]
1517 }
1518
1519 #[inline]
1520 pub fn offset(&self, loc: usize) -> OpIndex {
1521 OpIndex::try_from((self.code.len() - loc) as isize).unwrap()
1523 }
1524
1525 #[inline]
1526 pub fn next_code_index(&self) -> usize {
1527 self.code.len()
1528 }
1529
1530 #[inline]
1531 pub fn push_inst_pos(&mut self, i: Instruction, pos: Option<usize>) {
1532 self.code.push(i);
1533 self.pos.push(pos);
1534 }
1535
1536 #[inline]
1537 pub fn emit_inst(
1538 &mut self,
1539 op: Opcode,
1540 types: [Option<ValueType>; 3],
1541 imm: Option<i32>,
1542 pos: Option<usize>,
1543 ) {
1544 let i = Instruction::new(op, types[0], types[1], types[2], imm);
1545 self.code.push(i);
1546 self.pos.push(pos);
1547 }
1548
1549 pub fn emit_raw_inst(&mut self, u: u64, pos: Option<usize>) {
1550 let i = Instruction::from_u64(u);
1551 self.code.push(i);
1552 self.pos.push(pos);
1553 }
1554
1555 pub fn emit_code_with_type(&mut self, code: Opcode, t: ValueType, pos: Option<usize>) {
1556 self.emit_inst(code, [Some(t), None, None], None, pos);
1557 }
1558
1559 pub fn emit_code_with_type2(
1560 &mut self,
1561 code: Opcode,
1562 t0: ValueType,
1563 t1: Option<ValueType>,
1564 pos: Option<usize>,
1565 ) {
1566 self.emit_inst(code, [Some(t0), t1, None], None, pos);
1567 }
1568
1569 pub fn emit_code_with_imm(&mut self, code: Opcode, imm: OpIndex, pos: Option<usize>) {
1570 self.emit_inst(code, [None, None, None], Some(imm), pos);
1571 }
1572
1573 pub fn emit_code_with_type_imm(
1574 &mut self,
1575 code: Opcode,
1576 t: ValueType,
1577 imm: OpIndex,
1578 pos: Option<usize>,
1579 ) {
1580 self.emit_inst(code, [Some(t), None, None], Some(imm), pos);
1581 }
1582
1583 pub fn emit_code_with_flag_imm(
1584 &mut self,
1585 code: Opcode,
1586 comma_ok: bool,
1587 imm: OpIndex,
1588 pos: Option<usize>,
1589 ) {
1590 let mut inst = Instruction::new(code, None, None, None, Some(imm));
1591 let flag = if comma_ok { 1 } else { 0 };
1592 inst.set_t2_with_index(flag);
1593 self.code.push(inst);
1594 self.pos.push(pos);
1595 }
1596
1597 pub fn emit_code(&mut self, code: Opcode, pos: Option<usize>) {
1598 self.emit_inst(code, [None, None, None], None, pos);
1599 }
1600
1601 pub fn get_const_index(&self, val: &GosValue) -> Option<EntIndex> {
1603 self.consts.iter().enumerate().find_map(|(i, x)| {
1604 if val.identical(x) {
1605 Some(EntIndex::Const(i as OpIndex))
1606 } else {
1607 None
1608 }
1609 })
1610 }
1611
1612 pub fn add_local(&mut self, entity: Option<EntityKey>) -> EntIndex {
1613 let result = self.local_alloc as OpIndex;
1614 if let Some(key) = entity {
1615 let old = self.entities.insert(key, EntIndex::LocalVar(result));
1616 assert_eq!(old, None);
1617 };
1618 self.local_alloc += 1;
1619 EntIndex::LocalVar(result)
1620 }
1621
1622 pub fn add_local_zero(&mut self, zero: GosValue) {
1623 self.local_zeros.push(zero)
1624 }
1625
1626 pub fn add_const(&mut self, entity: Option<EntityKey>, cst: GosValue) -> EntIndex {
1630 if let Some(index) = self.get_const_index(&cst) {
1631 index
1632 } else {
1633 self.consts.push(cst);
1634 let result = (self.consts.len() - 1).try_into().unwrap();
1635 if let Some(key) = entity {
1636 let old = self.entities.insert(key, EntIndex::Const(result));
1637 assert_eq!(old, None);
1638 }
1639 EntIndex::Const(result)
1640 }
1641 }
1642
1643 pub fn try_add_upvalue(&mut self, entity: &EntityKey, uv: ValueDesc) -> EntIndex {
1644 match self.uv_entities.get(entity) {
1645 Some(i) => *i,
1646 None => self.add_upvalue(entity, uv),
1647 }
1648 }
1649
1650 fn add_upvalue(&mut self, entity: &EntityKey, uv: ValueDesc) -> EntIndex {
1651 self.up_ptrs.push(uv);
1652 let i = (self.up_ptrs.len() - 1).try_into().unwrap();
1653 let et = EntIndex::UpValue(i);
1654 self.uv_entities.insert(*entity, et);
1655 et
1656 }
1657}