slvm/vm/
exec_loop.rs

1use crate::opcodes::*;
2use crate::vm_hashmap::{VMHashMap, ValHash};
3use crate::{
4    CallFrame, Chunk, Continuation, Error, GVm, STACK_CAP, VMError, VMErrorObj, VMResult, Value,
5    from_i56,
6};
7use std::marker::PhantomData;
8use std::num::TryFromIntError;
9use std::sync::Arc;
10use unicode_segmentation::UnicodeSegmentation;
11
12impl<ENV> GVm<ENV> {
13    #[inline]
14    fn map_destructure(
15        &mut self,
16        //code: T,
17        decodes: (u16, u16, u16),
18        //wide: bool,
19    ) -> VMResult<()> {
20        let (dest, len, src) = decodes; //decode3!(code, wide);
21        if len > 0 {
22            let len = len as usize;
23            let dest = dest as usize;
24            let val = self.register(src as usize);
25            match val {
26                Value::Map(handle) => {
27                    let map = self.get_map(handle);
28                    for i in 0..len {
29                        let key = self.register(dest + i);
30                        if let Some(item) = map.get(self, key) {
31                            *self.register_mut(dest + i) = item;
32                        } else {
33                            *self.register_mut(dest + i) = Value::Undefined;
34                        }
35                    }
36                }
37                Value::Vector(handle) => {
38                    let vector = self.get_vector(handle);
39                    for i in 0..len {
40                        let key = self.register(dest + i);
41                        if key.is_int() {
42                            let key = key.get_int(self)?;
43                            if key >= 0 && key < vector.len() as i64 {
44                                *self.register_mut(dest + i) = vector[key as usize];
45                            } else {
46                                return Err(VMError::new_vm("seq key out of bounds"));
47                            }
48                        } else {
49                            let mut iter = vector.iter();
50                            *self.register_mut(dest + i) = Value::Undefined;
51                            while let Some(v) = iter.next() {
52                                if *v == key {
53                                    if let Some(value) = iter.next() {
54                                        *self.register_mut(dest + i) = *value;
55                                    }
56                                    break;
57                                }
58                            }
59                        }
60                    }
61                }
62                Value::List(handle, idx) => {
63                    let vector = &self.get_vector(handle)[idx as usize..];
64                    for i in 0..len {
65                        let key = self.register(dest + i);
66                        if key.is_int() {
67                            let key = key.get_int(self)?;
68                            if key >= 0 && key < vector.len() as i64 {
69                                *self.register_mut(dest + i) = vector[key as usize];
70                            } else {
71                                return Err(VMError::new_vm("seq key out of bounds"));
72                            }
73                        } else {
74                            let mut iter = vector.iter();
75                            *self.register_mut(dest + i) = Value::Undefined;
76                            while let Some(v) = iter.next() {
77                                if *v == key {
78                                    if let Some(value) = iter.next() {
79                                        *self.register_mut(dest + i) = *value;
80                                    }
81                                    break;
82                                }
83                            }
84                        }
85                    }
86                }
87                Value::Pair(_) => {
88                    for i in 0..len {
89                        let key = self.register(dest + i);
90                        if key.is_int() {
91                            let key = key.get_int(self)?;
92                            if key >= 0 {
93                                let mut iter = val.iter(self);
94                                if let Some(item) = iter.nth(key as usize) {
95                                    *self.register_mut(dest + i) = item;
96                                } else {
97                                    return Err(VMError::new_vm("seq key out of bounds"));
98                                }
99                            } else {
100                                return Err(VMError::new_vm("seq key out of bounds"));
101                            }
102                        } else {
103                            let mut iter = val.iter(self);
104                            *self.register_mut(dest + i) = Value::Undefined;
105                            while let Some(v) = iter.next() {
106                                if v == key {
107                                    if let Some(value) = iter.next() {
108                                        *self.register_mut(dest + i) = value;
109                                    }
110                                    break;
111                                }
112                            }
113                        }
114                    }
115                }
116                Value::Nil => {
117                    for i in 0..len {
118                        *self.register_mut(dest + i) = Value::Undefined;
119                    }
120                }
121                _ => return Err(VMError::new_vm("not a map")),
122            }
123        }
124        Ok(())
125    }
126
127    fn get_line(&self, wide: bool, chunk: &Chunk) -> Option<u32> {
128        if wide {
129            unsafe { chunk.offset_to_line(self.ip_ptr.offset_from(get_code!(chunk)) as usize - 4) }
130        } else {
131            unsafe { chunk.offset_to_line(self.ip_ptr.offset_from(get_code!(chunk)) as usize - 2) }
132        }
133    }
134
135    fn get_string_idx(&mut self, val: Value, i: u16) -> VMResult<Value> {
136        let s = match val {
137            Value::StringConst(it) => self.get_interned(it),
138            Value::String(h) => self.get_string(h),
139            _ => panic!("Invalid call to get_string_idx!"),
140        };
141        let idx = self.register_int(i as usize)?;
142        let mut iter = UnicodeSegmentation::graphemes(s, true);
143        let ch = if idx >= 0 {
144            iter.nth(idx as usize)
145        } else {
146            iter.rev().nth(((0 - idx) - 1) as usize)
147        };
148        let v = if let Some(ch) = ch {
149            // borrow checker won't let us use self.alloc_char(ch) here....
150            let len = ch.len();
151            if len <= 6 {
152                let mut b = [0_u8; 6];
153                b[0..len].copy_from_slice(ch.as_bytes());
154                Value::CharCluster(len as u8, b)
155            } else {
156                let h = self.alloc_string(ch.to_string());
157                Value::CharClusterLong(h.get_handle().expect("just allocated, missing handle!"))
158            }
159        } else {
160            self.make_err("vm-missing", idx.into())
161        };
162        Ok(v)
163    }
164
165    fn get(&mut self, wide: bool) -> VMResult<()> {
166        let (dest, data, i) = decode3!(self.ip_ptr, wide);
167        let data = self.register(data as usize);
168        let val = match data {
169            Value::Vector(h) => {
170                let v = self.get_vector(h);
171                let idx = self.register_int(i as usize)?;
172                let idx = if idx >= 0 { idx } else { v.len() as i64 + idx };
173                if idx < 0 {
174                    let iv = idx.into();
175                    self.make_err("vm-missing", iv)
176                } else if let Some(val) = v.get(idx as usize) {
177                    *val
178                } else {
179                    let iv = idx.into();
180                    self.make_err("vm-missing", iv)
181                }
182            }
183            Value::List(h, start) => {
184                let v = self.get_vector(h);
185                let idx = self.register_int(i as usize)?;
186                if idx < 0 {
187                    let iv = idx.into();
188                    self.make_err("vm-missing", iv)
189                } else if let Some(val) = v.get(start as usize + idx as usize) {
190                    *val
191                } else {
192                    let iv = idx.into();
193                    self.make_err("vm-missing", iv)
194                }
195            }
196            Value::Pair(_) => {
197                let idx = self.register_int(i as usize)?;
198                if idx >= 0 {
199                    let idx = idx as usize;
200                    if let Some((mut car_out, mut cdr)) = data.get_pair(self) {
201                        for _ in 0..idx {
202                            if let Some((car, cdr_in)) = cdr.get_pair(self) {
203                                car_out = car;
204                                cdr = cdr_in;
205                            } else {
206                                let iv = (idx as i64).into();
207                                car_out = self.make_err("vm-missing", iv);
208                            }
209                        }
210                        car_out
211                    } else {
212                        panic!("pair not a pair!")
213                    }
214                } else {
215                    return Err(VMError::new_vm(format!(
216                        "GET: list requires a positive index (pair), {}.",
217                        i,
218                    )));
219                }
220            }
221            Value::Map(h) => {
222                let map = self.get_map(h);
223                let key = self.register(i as usize);
224                if let Some(val) = map.get(self, key) {
225                    val
226                } else {
227                    self.make_err("vm-missing", key)
228                }
229            }
230            Value::StringConst(_) => self.get_string_idx(data, i)?,
231            Value::String(_) => self.get_string_idx(data, i)?,
232            Value::Error(_) => data, // Pass the error on (for stacked GETs).
233            _ => {
234                return Err(VMError::new_vm("GET: Not a compound data structure."));
235            }
236        };
237        set_register!(self, dest as usize, val);
238        Ok(())
239    }
240
241    fn set_data(&mut self, wide: bool) -> VMResult<()> {
242        let (src, data, i) = decode3!(self.ip_ptr, wide);
243        let data = self.register(data as usize);
244        let src = self.register(src as usize);
245        match data {
246            Value::Vector(h) => {
247                let idx = self.register_int(i as usize)?;
248                let v = self.get_vector_mut(h)?;
249                let idx = if idx >= 0 { idx } else { v.len() as i64 + idx };
250                if idx < 0 {
251                    return Err(VMError::new_vm(format!(
252                        "index out of bounds, {}/{}.",
253                        i,
254                        v.len()
255                    )));
256                }
257                if let Some(slot) = v.get_mut(idx as usize) {
258                    *slot = src;
259                } else {
260                    v.resize(idx as usize + 1, Value::Nil);
261                    if let Some(slot) = v.get_mut(idx as usize) {
262                        *slot = src;
263                    } else {
264                        return Err(VMError::new_vm(
265                            "Vector, index out of bounds (unable to grow vector).",
266                        ));
267                    }
268                }
269            }
270            Value::List(h, start) => {
271                let idx = self.register_int(i as usize)?;
272                let v = self.get_vector_mut(h)?;
273                if idx < 0 {
274                    return Err(VMError::new_vm(format!(
275                        "index out of bounds, {}/{}.",
276                        i,
277                        v.len() - start as usize,
278                    )));
279                }
280                if let Some(slot) = v.get_mut(start as usize + idx as usize) {
281                    *slot = src;
282                } else {
283                    return Err(VMError::new_vm("index out of bounds"));
284                }
285            }
286            Value::Pair(_) => {
287                let idx = self.register_int(i as usize)?;
288                if idx >= 0 {
289                    let idx = idx as usize;
290                    let mut last_cdr = data;
291                    for _ in 0..idx {
292                        if let Some((_car, cdr_in)) = last_cdr.get_pair(self) {
293                            last_cdr = cdr_in;
294                        } else {
295                            return Err(VMError::new_vm(format!(
296                                "index out of bounds (pair), {}.",
297                                i,
298                            )));
299                        }
300                    }
301                    match &last_cdr {
302                        Value::Pair(handle) => {
303                            let (car, _) = self.get_pair_mut(*handle)?;
304                            *car = src;
305                        }
306                        Value::List(_, _) => return Err(VMError::new_vm("pair is read only")),
307                        _ => return Err(VMError::new_vm("not a pair/conscell")),
308                    }
309                } else {
310                    return Err(VMError::new_vm(format!(
311                        "list requires a positive index (pair), {}.",
312                        i,
313                    )));
314                }
315            }
316            Value::Map(h) => {
317                let key = self.register(i as usize);
318                let id = ValHash::from_value(self, key);
319                let map = self.get_map_mut(h)?;
320                map.insert_id(id, src);
321            }
322            _ => {
323                return Err(VMError::new_vm(format!(
324                    "Not a compound data structure: {}.",
325                    data.display_type(self)
326                )));
327            }
328        }
329        Ok(())
330    }
331
332    /// If we are tail calling a builtin with no call frame then exit loop early.
333    /// Need to check this for some lambda -> builtin tail calls so SRET does not execute and
334    /// munge the return.
335    fn tail_builtin_exit(&self, lambda: Value) -> bool {
336        matches!(lambda, Value::Builtin(_)) && self.call_frame().is_none()
337    }
338
339    /** Implementation of the INC bytecode. */
340    fn inc_val(&mut self, wide: bool) -> VMResult<()> {
341        let (dest, i) = decode2!(self.ip_ptr, wide);
342        match self.register(dest as usize) {
343            Value::Byte(v) => {
344                let i: u8 = i
345                    .try_into()
346                    .map_err(|e: TryFromIntError| VMError::new_vm(e.to_string()))?;
347                *self.register_mut(dest as usize) = Value::Byte(v + i);
348                Ok(())
349            }
350            Value::Int(v) => {
351                let v = from_i56(&v);
352                *self.register_mut(dest as usize) = (v + i as i64).into();
353                Ok(())
354            }
355            // Handle closed over values...
356            Value::Value(h) => {
357                let val = self.get_value_mut(h);
358                match val {
359                    Value::Byte(v) => {
360                        let i: u8 = i
361                            .try_into()
362                            .map_err(|e: TryFromIntError| VMError::new_vm(e.to_string()))?;
363                        *val = Value::Byte(*v + i);
364                        Ok(())
365                    }
366                    Value::Int(v) => {
367                        let v = from_i56(v);
368                        *val = (v + i as i64).into();
369                        Ok(())
370                    }
371                    _ => Err(VMError::new_vm(format!(
372                        "INC: Can only INC an integer type, got {:?}.",
373                        val
374                    ))),
375                }
376            }
377            _ => Err(VMError::new_vm(format!(
378                "INC: Can only INC an integer type, got {:?}.",
379                self.register(dest as usize)
380            ))),
381        }
382    }
383
384    /** Implementation of the DEC bytecode. */
385    fn dec_val(&mut self, wide: bool) -> VMResult<()> {
386        let (dest, i) = decode2!(self.ip_ptr, wide);
387        match self.register(dest as usize) {
388            Value::Byte(v) => {
389                let i: u8 = i
390                    .try_into()
391                    .map_err(|e: TryFromIntError| VMError::new_vm(e.to_string()))?;
392                *self.register_mut(dest as usize) = Value::Byte(v - i);
393                Ok(())
394            }
395            Value::Int(v) => {
396                let v = from_i56(&v);
397                *self.register_mut(dest as usize) = (v - i as i64).into();
398                Ok(())
399            }
400            // Handle closed over values...
401            Value::Value(h) => {
402                let val = self.get_value_mut(h);
403                match val {
404                    Value::Byte(v) => {
405                        let i: u8 = i
406                            .try_into()
407                            .map_err(|e: TryFromIntError| VMError::new_vm(e.to_string()))?;
408                        *val = Value::Byte(*v - i);
409                        Ok(())
410                    }
411                    Value::Int(v) => {
412                        let v = from_i56(v);
413                        *val = (v - i as i64).into();
414                        Ok(())
415                    }
416                    _ => Err(VMError::new_vm(format!(
417                        "INC: Can only INC an integer type, got {:?}.",
418                        val
419                    ))),
420                }
421            }
422            _ => Err(VMError::new_vm(format!(
423                "DEC: Can only DEC an integer type, got {:?}.",
424                self.register(dest as usize)
425            ))),
426        }
427    }
428
429    // Some macro expansions trips this.
430    #[allow(clippy::redundant_closure_call)]
431    pub(super) fn exec_loop(
432        &mut self,
433        chunk: Arc<Chunk>,
434        skip_init: bool,
435    ) -> Result<(), (VMError, Arc<Chunk>)> {
436        let _env: PhantomData<ENV>;
437        self.make_registers();
438        let mut chunk = chunk;
439        let mut wide = false;
440        if !skip_init {
441            self.ip_ptr = get_code!(chunk);
442            // Clean up the working regs we are about to use.
443            if chunk.extra_regs > 0 {
444                let regs = unsafe {
445                    std::slice::from_raw_parts_mut(
446                        self.stack.add(self.stack_top),
447                        STACK_CAP - self.stack_top,
448                    )
449                };
450                for reg in regs
451                    .iter_mut()
452                    .skip(chunk.input_regs)
453                    .take(chunk.extra_regs + 1)
454                {
455                    *reg = Value::Undefined;
456                }
457            }
458        }
459        let mut opcode = NOP;
460        loop {
461            if wide && opcode != WIDE {
462                wide = false;
463            }
464            self.current_ip_ptr = self.ip_ptr;
465            opcode = decode_u8!(self.ip_ptr);
466            match opcode {
467                NOP => {}
468                HALT => {
469                    return Err((VMError::new_vm("HALT: VM halted and on fire!"), chunk));
470                }
471                RET => {
472                    if let Some(defer) = self.defers.pop() {
473                        let first_reg = (chunk.input_regs + chunk.extra_regs + 1) as u16;
474                        self.ip_ptr = self.current_ip_ptr;
475                        chunk = self.make_call(defer, chunk, first_reg, 0, false)?;
476                        self.make_registers();
477                    } else {
478                        // Clear used regs to make sure no closures or globals get overwritten later.
479                        for r in self.stack_top + 1..=self.stack_max {
480                            *self.stack_mut(r) = Value::Undefined;
481                        }
482                        if let Some(frame) = self.call_frame() {
483                            let stack_top = frame.stack_top;
484                            let ip_ptr = frame.ip;
485                            let current_ip = frame.current_ip;
486                            let this_fn = frame.this_fn;
487                            let on_error = frame.on_error;
488                            chunk = frame.chunk.clone();
489                            self.copy_frame_defers(); // Do this BEFORE we change stack_top...
490                            self.stack_top = stack_top;
491                            self.make_registers();
492                            self.stack_max = self.stack_top + chunk.input_regs + chunk.extra_regs;
493                            self.ip_ptr = ip_ptr;
494                            self.current_ip_ptr = current_ip;
495                            self.this_fn = this_fn;
496                            self.on_error = on_error;
497                        } else {
498                            return Ok(());
499                        }
500                    }
501                }
502                SRET => {
503                    if let Some(defer) = self.defers.pop() {
504                        let first_reg = (chunk.input_regs + chunk.extra_regs + 1) as u16;
505                        self.ip_ptr = self.current_ip_ptr;
506                        chunk = self.make_call(defer, chunk, first_reg, 0, false)?;
507                        self.make_registers();
508                    } else {
509                        let src = decode1!(self.ip_ptr, wide);
510                        let val = self.register(src as usize);
511                        let old_top = self.stack_top;
512                        // Clear used regs to make sure no closures or globals get overwritten later.
513                        for r in self.stack_top + 1..=self.stack_max {
514                            *self.stack_mut(r) = Value::Undefined;
515                        }
516                        if let Some(frame) = self.call_frame() {
517                            let stack_top = frame.stack_top;
518                            let ip_ptr = frame.ip;
519                            let current_ip = frame.current_ip;
520                            let this_fn = frame.this_fn;
521                            let on_error = frame.on_error;
522                            chunk = frame.chunk.clone();
523                            self.copy_frame_defers(); // Do this BEFORE we change stack_top...
524                            self.stack_top = stack_top;
525                            self.make_registers();
526                            self.stack_max = self.stack_top + chunk.input_regs + chunk.extra_regs;
527                            self.ip_ptr = ip_ptr;
528                            self.current_ip_ptr = current_ip;
529                            self.this_fn = this_fn;
530                            self.on_error = on_error;
531                        } else {
532                            *self.stack_mut(old_top) = val;
533                            return Ok(());
534                        }
535                        *self.stack_mut(old_top) = val;
536                    }
537                }
538                WIDE => wide = true,
539                MOV => {
540                    let (dest, src) = decode2!(self.ip_ptr, wide);
541                    // XXX TODO- figure out proper mov semantics...
542                    let val = self.register_unref(src as usize);
543                    //let val = self.register(src as usize);
544                    mov_register!(self, dest as usize, val);
545                }
546                MOVI => {
547                    let (dest, src) = decode2!(self.ip_ptr, wide);
548                    let val = self.register_unref(src as usize);
549                    let dest = self
550                        .register_int(dest as usize)
551                        .map_err(|e| (e, chunk.clone()))?;
552                    mov_register!(self, dest as usize, val);
553                }
554                MOVII => {
555                    let (dest, src) = decode2!(self.ip_ptr, wide);
556                    let src = self
557                        .register_int(src as usize)
558                        .map_err(|e| (e, chunk.clone()))?;
559                    let val = self.register_unref(src as usize);
560                    mov_register!(self, dest as usize, val);
561                }
562                GET => self.get(wide).map_err(|e| (e, chunk.clone()))?,
563                SETCOL => self.set_data(wide).map_err(|e| (e, chunk.clone()))?,
564                BMOV => {
565                    let (dest, src, len) = decode3!(self.ip_ptr, wide);
566                    for i in 0..len as usize {
567                        mov_register!(self, dest as usize + i, self.register(src as usize + i));
568                    }
569                }
570                LDSC => {
571                    let (dest, len, src) = decode3!(self.ip_ptr, wide);
572                    if len > 0 {
573                        let len = len as usize;
574                        let dest = dest as usize;
575                        let val = self.register(src as usize);
576                        match val {
577                            Value::Vector(_) | Value::Pair(_) | Value::List(_, _) | Value::Nil => {
578                                let mut iter = val.iter(self);
579                                for i in 0..len {
580                                    if let Some(item) = iter.next() {
581                                        *self.register_mut(dest + i) = item;
582                                    } else {
583                                        *self.register_mut(dest + i) = Value::Undefined;
584                                    }
585                                }
586                            }
587                            _ => return Err((VMError::new_vm("not a sequence"), chunk)),
588                        }
589                    }
590                }
591                LDSCR => {
592                    let (dest, len, src) = decode3!(self.ip_ptr, wide);
593                    if len > 0 {
594                        let len = len as usize;
595                        let dest = dest as usize;
596                        let val = self.register(src as usize);
597                        match val {
598                            Value::Vector(_) | Value::Pair(_) | Value::List(_, _) | Value::Nil => {
599                                let mut iter = val.iter(self);
600                                for i in 0..len - 1 {
601                                    if let Some(item) = iter.next() {
602                                        *self.register_mut(dest + i) = item;
603                                    } else {
604                                        *self.register_mut(dest + i) = Value::Undefined;
605                                    }
606                                }
607                                let rest: Vec<Value> = iter.collect();
608                                if rest.is_empty() {
609                                    *self.register_mut(dest + (len - 1)) = Value::Nil;
610                                } else {
611                                    *self.register_mut(dest + (len - 1)) = self.alloc_list_ro(rest);
612                                }
613                            }
614                            _ => return Err((VMError::new_vm("not a sequence"), chunk)),
615                        }
616                    }
617                }
618                MDSC => {
619                    let decodes = decode3!(self.ip_ptr, wide);
620                    self.map_destructure(decodes)
621                        .map_err(|e| (e, chunk.clone()))?;
622                }
623                COPY => {
624                    let (_dest, _src) = decode2!(self.ip_ptr, wide);
625                    // XXX Deep copy src to dest
626                }
627                FRZ => {
628                    let target = decode1!(self.ip_ptr, wide);
629                    let target = self.register(target as usize);
630                    self.heap_mut().immutable(target);
631                }
632                SET => {
633                    let (dest, src) = decode2!(self.ip_ptr, wide);
634                    let val = self.register_unref(src as usize);
635                    set_register!(self, dest as usize, val);
636                }
637                CONST => {
638                    let (dest, src) = decode2!(self.ip_ptr, wide);
639                    let val = chunk.constants[src as usize];
640                    set_register!(self, dest as usize, val);
641                }
642                DEF => {
643                    let src = decode1!(self.ip_ptr, wide);
644                    let idx = if wide {
645                        decode_u32!(self.ip_ptr)
646                    } else {
647                        decode_u16!(self.ip_ptr) as u32
648                    };
649                    let val = self.register(src as usize);
650                    self.set_global(idx, val);
651                }
652                DEFV => {
653                    let src = decode1!(self.ip_ptr, wide);
654                    let idx = if wide {
655                        decode_u32!(self.ip_ptr)
656                    } else {
657                        decode_u16!(self.ip_ptr) as u32
658                    };
659                    let val = self.register(src as usize);
660                    if let Value::Undefined = self.globals.get(idx) {
661                        self.set_global(idx, val);
662                    }
663                }
664                REFI => {
665                    let dest = decode1!(self.ip_ptr, wide);
666                    let idx = if wide {
667                        decode_u32!(self.ip_ptr)
668                    } else {
669                        decode_u16!(self.ip_ptr) as u32
670                    };
671                    mov_register!(self, dest as usize, self.globals.get(idx));
672                }
673                CLRREG => {
674                    let dest = decode1!(self.ip_ptr, wide);
675                    mov_register!(self, dest as usize, Value::Undefined);
676                }
677                REGT => {
678                    let dest = decode1!(self.ip_ptr, wide);
679                    set_register!(self, dest as usize, Value::True);
680                }
681                REGF => {
682                    let dest = decode1!(self.ip_ptr, wide);
683                    set_register!(self, dest as usize, Value::False);
684                }
685                REGN => {
686                    let dest = decode1!(self.ip_ptr, wide);
687                    set_register!(self, dest as usize, Value::Nil);
688                }
689                REGC => {
690                    let dest = decode1!(self.ip_ptr, wide);
691                    set_register!(self, dest as usize, Value::Undefined);
692                }
693                REGB => {
694                    let (dest, i) = decode2!(self.ip_ptr, wide);
695                    set_register!(self, dest as usize, Value::Byte(i as u8));
696                }
697                REGI => {
698                    let (dest, i) = decode2!(self.ip_ptr, wide);
699                    let i: Value = (i as i64).into();
700                    set_register!(self, dest as usize, i);
701                }
702                CLOSE => {
703                    let (dest, src) = decode2!(self.ip_ptr, wide);
704                    //let lambda = self.register(src as usize);
705                    let lambda = self.register_unref(src as usize);
706                    let (lambda, caps) = if let Value::Lambda(h) = lambda {
707                        let l = self.heap().get_lambda(h);
708                        let mut caps = Vec::new();
709                        if let Some(captures) = &l.captures {
710                            for c in captures {
711                                let r = self.register(*c as usize);
712                                if let Value::Value(b) = r {
713                                    caps.push(b);
714                                } else {
715                                    let val = self.new_upval(r);
716                                    mov_register!(self, *c as usize, val);
717                                    caps.push(val.get_handle().unwrap());
718                                }
719                            }
720                        }
721                        (l, caps)
722                    } else {
723                        return Err((
724                            VMError::new_vm(format!("CLOSE: requires a lambda, got {lambda:?}.")),
725                            chunk,
726                        ));
727                    };
728                    let new_closure = self.alloc_closure(lambda, caps);
729                    set_register!(self, dest as usize, new_closure);
730                }
731                CALL => {
732                    let (lambda, num_args, first_reg) = decode3!(self.ip_ptr, wide);
733                    let lambda = self.register(lambda as usize);
734                    chunk = self.make_call(lambda, chunk, first_reg, num_args, false)?;
735                    self.make_registers();
736                }
737                CALLG => {
738                    let idx = if wide {
739                        decode_u32!(self.ip_ptr)
740                    } else {
741                        decode_u16!(self.ip_ptr) as u32
742                    };
743                    let (num_args, first_reg) = decode2!(self.ip_ptr, wide);
744                    let lambda = self.get_global(idx);
745                    chunk = self.make_call(lambda, chunk, first_reg, num_args, false)?;
746                    self.make_registers();
747                }
748                TCALL => {
749                    let (lambda, num_args) = decode2!(self.ip_ptr, wide);
750                    let lambda = self.register(lambda as usize);
751                    let done = self.tail_builtin_exit(lambda);
752                    chunk = self.make_call(lambda, chunk, 0, num_args, true)?;
753                    if done {
754                        return Ok(());
755                    }
756                    self.make_registers(); // In case of a builtin call
757                }
758                TCALLG => {
759                    let idx = if wide {
760                        decode_u32!(self.ip_ptr)
761                    } else {
762                        decode_u16!(self.ip_ptr) as u32
763                    };
764                    let num_args = decode1!(self.ip_ptr, wide);
765                    let lambda = self.get_global(idx);
766                    let done = self.tail_builtin_exit(lambda);
767                    chunk = self.make_call(lambda, chunk, 0, num_args, true)?;
768                    if done {
769                        return Ok(());
770                    }
771                    self.make_registers(); // In case of a builtin call
772                }
773                CALLM => {
774                    let (num_args, first_reg) = decode2!(self.ip_ptr, wide);
775                    if let Some(this_fn) = self.this_fn {
776                        chunk = self.make_call(this_fn, chunk, first_reg, num_args, false)?;
777                        self.make_registers();
778                    } else {
779                        let line = self.get_line(wide, &chunk);
780                        return Err((
781                            VMError::new_vm(format!(
782                                "CALLM: Not in an existing lambda call, line {}.",
783                                line.unwrap_or(0)
784                            )),
785                            chunk,
786                        ));
787                    }
788                }
789                TCALLM => {
790                    let num_args = decode1!(self.ip_ptr, wide);
791                    if let Some(this_fn) = self.this_fn {
792                        chunk = self.make_call(this_fn, chunk, 0, num_args, true)?;
793                        self.make_registers(); // In case of a builtin call
794                    } else {
795                        let line = self.get_line(wide, &chunk);
796                        return Err((
797                            VMError::new_vm(format!(
798                                "TCALLM: Not in an existing lambda call, line {}.",
799                                line.unwrap_or(0)
800                            )),
801                            chunk,
802                        ));
803                    }
804                }
805                JMP => {
806                    let jmp = decode1!(self.ip_ptr, wide);
807                    self.ip_ptr = get_code_at!(chunk, chunk.jump_table[jmp as usize] as isize);
808                }
809                JMPT => {
810                    let (test, jmp) = decode2!(self.ip_ptr, wide);
811                    if self.register(test as usize).is_truthy() {
812                        self.ip_ptr = get_code_at!(chunk, chunk.jump_table[jmp as usize] as isize);
813                    }
814                }
815                JMPF => {
816                    let (test, jmp) = decode2!(self.ip_ptr, wide);
817                    if self.register(test as usize).is_falsey() {
818                        self.ip_ptr = get_code_at!(chunk, chunk.jump_table[jmp as usize] as isize);
819                    }
820                }
821                JMPEQ => {
822                    let (op1, op2, jmp) = decode3!(self.ip_ptr, wide);
823                    let op1 = self
824                        .register(op1 as usize)
825                        .get_int(self)
826                        .map_err(|e| (e, chunk.clone()))?;
827                    let op2 = self
828                        .register(op2 as usize)
829                        .get_int(self)
830                        .map_err(|e| (e, chunk.clone()))?;
831                    if op1 == op2 {
832                        self.ip_ptr = get_code_at!(chunk, chunk.jump_table[jmp as usize] as isize);
833                    }
834                }
835                JMPLT => {
836                    let (op1, op2, jmp) = decode3!(self.ip_ptr, wide);
837                    let op1 = self
838                        .register_int(op1 as usize)
839                        .map_err(|e| (e, chunk.clone()))?;
840                    let op2 = self
841                        .register_int(op2 as usize)
842                        .map_err(|e| (e, chunk.clone()))?;
843                    if op1 < op2 {
844                        self.ip_ptr = get_code_at!(chunk, chunk.jump_table[jmp as usize] as isize);
845                    }
846                }
847                JMPGT => {
848                    let (op1, op2, jmp) = decode3!(self.ip_ptr, wide);
849                    let op1 = self
850                        .register_int(op1 as usize)
851                        .map_err(|e| (e, chunk.clone()))?;
852                    let op2 = self
853                        .register_int(op2 as usize)
854                        .map_err(|e| (e, chunk.clone()))?;
855                    if op1 > op2 {
856                        self.ip_ptr = get_code_at!(chunk, chunk.jump_table[jmp as usize] as isize);
857                    }
858                }
859                JMPU => {
860                    let (test, jmp) = decode2!(self.ip_ptr, wide);
861                    if self.register(test as usize).is_undef() {
862                        self.ip_ptr = get_code_at!(chunk, chunk.jump_table[jmp as usize] as isize);
863                    }
864                }
865                JMPNU => {
866                    let (test, jmp) = decode2!(self.ip_ptr, wide);
867                    if !self.register(test as usize).is_undef() {
868                        self.ip_ptr = get_code_at!(chunk, chunk.jump_table[jmp as usize] as isize);
869                    }
870                }
871                JMPRU => {
872                    let (test, len, jmp) = decode3!(self.ip_ptr, wide);
873                    if len > 0 {
874                        let test = test as usize;
875                        let len = len as usize;
876                        for i in 0..len {
877                            if self.register(test + i).is_undef() {
878                                self.ip_ptr =
879                                    get_code_at!(chunk, chunk.jump_table[jmp as usize] as isize);
880                                break;
881                            }
882                        }
883                    }
884                }
885                JMPRNU => {
886                    let (test, len, jmp) = decode3!(self.ip_ptr, wide);
887                    if len > 0 {
888                        let len = len as usize;
889                        let test = test as usize;
890                        let mut jump = true;
891                        for i in 0..len {
892                            if self.register(test + i).is_undef() {
893                                jump = false;
894                                break;
895                            }
896                        }
897                        if jump {
898                            self.ip_ptr =
899                                get_code_at!(chunk, chunk.jump_table[jmp as usize] as isize);
900                        }
901                    }
902                }
903                EQ => {
904                    let (dest, reg1, reg2) = decode3!(self.ip_ptr, wide);
905                    let val = self
906                        .is_identical(reg1, reg2)
907                        .map_err(|e| (e, chunk.clone()))?;
908                    set_register!(self, dest as usize, val);
909                }
910                EQUAL => {
911                    let (dest, reg1, reg2) = decode3!(self.ip_ptr, wide);
912                    let val = self.is_equal(reg1, reg2).map_err(|e| (e, chunk.clone()))?;
913                    set_register!(self, dest as usize, val);
914                }
915                ISERR => {
916                    let (dest, testreg) = decode2!(self.ip_ptr, wide);
917                    let test = self.register_unref(testreg as usize);
918                    let val = if let Value::Error(_) = test {
919                        Value::True
920                    } else {
921                        Value::False
922                    };
923                    set_register!(self, dest as usize, val);
924                }
925                ISOK => {
926                    let (dest, testreg) = decode2!(self.ip_ptr, wide);
927                    let test = self.register_unref(testreg as usize);
928                    let val = if let Value::Error(_) = test {
929                        Value::False
930                    } else {
931                        Value::True
932                    };
933                    set_register!(self, dest as usize, val);
934                }
935                NOT => {
936                    let (dest, val) = decode2!(self.ip_ptr, wide);
937                    let val = self.register(val as usize);
938                    let res = if val.is_falsey() {
939                        Value::True
940                    } else {
941                        Value::False
942                    };
943                    set_register!(self, dest as usize, res);
944                }
945                ERR => {
946                    let (key, val) = decode2!(self.ip_ptr, wide);
947                    let key = self.register(key as usize);
948                    let val = self.register(val as usize);
949                    let key_str = if let Value::Keyword(i) = key {
950                        self.get_interned(i)
951                    } else {
952                        return Err((
953                            VMError::new_vm(format!("ERR: key must be a keyword, got {key:?}.")),
954                            chunk,
955                        ));
956                    };
957                    if let Value::StringConst(i) = val {
958                        return Err((
959                            VMError {
960                                key: key_str,
961                                obj: VMErrorObj::Message(self.get_interned(i).to_string()),
962                            },
963                            chunk,
964                        ));
965                    } else {
966                        return Err((
967                            VMError {
968                                key: key_str,
969                                obj: VMErrorObj::Object(val),
970                            },
971                            chunk,
972                        ));
973                    }
974                }
975                MKERR => {
976                    let (dest, key, data) = decode3!(self.ip_ptr, wide);
977                    let key = self.register(key as usize);
978                    let data = self.register(data as usize);
979                    let keyword = if let Value::Keyword(i) = key {
980                        i
981                    } else {
982                        return Err((
983                            VMError::new_vm(format!("MKERR: key must be a keyword, got {key:?}.")),
984                            chunk,
985                        ));
986                    };
987                    let err = Error { keyword, data };
988                    let err = self.alloc_error(err);
989                    set_register!(self, dest as usize, err);
990                }
991                CCC => {
992                    let (lambda, first_reg) = decode2!(self.ip_ptr, wide);
993                    let lambda = self.register(lambda as usize);
994                    let mut defers = vec![Value::Undefined; self.defers.len()];
995                    defers.copy_from_slice(&self.defers[..]);
996                    let frame = CallFrame {
997                        id: self.callframe_id, // This will duplicate the id for lambda ccc calls on purpose.
998                        chunk: chunk.clone(),
999                        ip: self.ip_ptr,
1000                        current_ip: self.current_ip_ptr,
1001                        stack_top: self.stack_top,
1002                        this_fn: self.this_fn,
1003                        defers,
1004                        on_error: self.on_error,
1005                        called: Value::Undefined,
1006                    };
1007                    let mut stack = Vec::with_capacity(self.stack_max);
1008                    stack.resize(self.stack_max, Value::Undefined);
1009                    stack[..].copy_from_slice(&self.stack_slice()[0..self.stack_max]);
1010                    let k = Continuation {
1011                        frame,
1012                        arg_reg: self.stack_top + first_reg as usize, //stack_len,
1013                        stack,
1014                    };
1015                    let k_obj = self.alloc_continuation(k);
1016                    mov_register!(self, (first_reg + 1) as usize, k_obj);
1017                    chunk = self.make_call(lambda, chunk, first_reg, 1, false)?;
1018                    self.make_registers();
1019                }
1020                DFR => {
1021                    let lambda = decode1!(self.ip_ptr, wide);
1022                    let lambda = self.register(lambda as usize);
1023                    self.defers.push(lambda);
1024                }
1025                DFRPOP => {
1026                    if let Some(defer) = self.defers.pop() {
1027                        let first_reg = (chunk.input_regs + chunk.extra_regs + 1) as u16;
1028                        chunk = self.make_call(defer, chunk, first_reg, 0, false)?;
1029                        self.make_registers();
1030                    }
1031                }
1032                ONERR => {
1033                    let on_error_reg = decode1!(self.ip_ptr, wide);
1034                    let on_error = self.register(on_error_reg as usize);
1035                    if let Some(oe) = self.on_error {
1036                        mov_register!(self, on_error_reg as usize, oe);
1037                    } else {
1038                        mov_register!(self, on_error_reg as usize, Value::Nil);
1039                    }
1040                    if let Value::Nil = on_error {
1041                        self.on_error = None;
1042                    } else {
1043                        self.on_error = Some(on_error);
1044                    }
1045                }
1046                ADD => binary_math!(self, chunk, self.ip_ptr, |a, b| a + b, wide),
1047                SUB => binary_math!(self, chunk, self.ip_ptr, |a, b| a - b, wide),
1048                MUL => binary_math!(self, chunk, self.ip_ptr, |a, b| a * b, wide),
1049                DIV => div_math!(self, chunk, self.ip_ptr, wide),
1050                NUMEQ => {
1051                    compare_numeric_eq!(self, chunk, self.ip_ptr, wide)
1052                }
1053                NUMLT => {
1054                    compare_numeric!(self, chunk, self.ip_ptr, |a, b| a < b, wide)
1055                }
1056                NUMLTE => {
1057                    compare_numeric!(self, chunk, self.ip_ptr, |a, b| a <= b, wide)
1058                }
1059                NUMGT => {
1060                    compare_numeric!(self, chunk, self.ip_ptr, |a, b| a > b, wide)
1061                }
1062                NUMGTE => {
1063                    compare_numeric!(self, chunk, self.ip_ptr, |a, b| a >= b, wide)
1064                }
1065                INC => self.inc_val(wide).map_err(|e| (e, chunk.clone()))?,
1066                DEC => self.dec_val(wide).map_err(|e| (e, chunk.clone()))?,
1067                CONS => {
1068                    let (dest, op2, op3) = decode3!(self.ip_ptr, wide);
1069                    let car = self.register(op2 as usize);
1070                    let cdr = self.register(op3 as usize);
1071                    let pair = self.alloc_pair(car, cdr);
1072                    set_register!(self, dest as usize, pair);
1073                }
1074                CAR => {
1075                    let (dest, op) = decode2!(self.ip_ptr, wide);
1076                    let op = self.register(op as usize);
1077                    match op {
1078                        Value::Pair(_) | Value::List(_, _) => {
1079                            let (car, _) = op.get_pair(self).expect("Pair not a pair?");
1080                            set_register!(self, dest as usize, car);
1081                        }
1082                        Value::Nil => set_register!(self, dest as usize, Value::Nil),
1083                        Value::Error(h) => {
1084                            let err = self.get_error(h);
1085                            set_register!(self, dest as usize, Value::Keyword(err.keyword));
1086                        }
1087                        _ => {
1088                            return Err((
1089                                VMError::new_vm(format!(
1090                                    "CAR: Not a pair/conscell. {}",
1091                                    op.display_value(self)
1092                                )),
1093                                chunk,
1094                            ));
1095                        }
1096                    }
1097                }
1098                CDR => {
1099                    let (dest, op) = decode2!(self.ip_ptr, wide);
1100                    let op = self.register(op as usize);
1101                    match op {
1102                        Value::Pair(_) | Value::List(_, _) => {
1103                            let (_, cdr) = op.get_pair(self).expect("Pair not a pair?");
1104                            set_register!(self, dest as usize, cdr);
1105                        }
1106                        Value::Nil => set_register!(self, dest as usize, Value::Nil),
1107                        Value::Error(h) => {
1108                            let err = self.get_error(h);
1109                            set_register!(self, dest as usize, err.data);
1110                        }
1111                        _ => return Err((VMError::new_vm("CDR: Not a pair/conscell."), chunk)),
1112                    }
1113                }
1114                LIST => {
1115                    self.pause_gc();
1116                    let r = self.list(wide).map_err(|e| (e, chunk.clone()));
1117                    self.unpause_gc();
1118                    r?
1119                }
1120                APND => {
1121                    self.pause_gc();
1122                    let r = self.append(wide).map_err(|e| (e, chunk.clone()));
1123                    self.unpause_gc();
1124                    r?;
1125                }
1126                XAR => self.xar(wide).map_err(|e| (e, chunk.clone()))?,
1127                XDR => self.xdr(wide).map_err(|e| (e, chunk.clone()))?,
1128                VEC => {
1129                    let (dest, start, end) = decode3!(self.ip_ptr, wide);
1130                    if end == start {
1131                        let vh = self.alloc_vector(Vec::new());
1132                        set_register!(self, dest as usize, vh);
1133                    } else {
1134                        let mut v = Vec::new();
1135                        for i in start..end {
1136                            v.push(self.register(i as usize));
1137                        }
1138                        let vh = self.alloc_vector(v);
1139                        set_register!(self, dest as usize, vh);
1140                    }
1141                }
1142                MAPMK => {
1143                    let (dest, start, end) = decode3!(self.ip_ptr, wide);
1144                    let map = if end == start {
1145                        VMHashMap::new()
1146                    } else if (end - start) % 2 != 0 {
1147                        return Err((
1148                            VMError::new_vm(
1149                                "make-hash: Invalid arguments (must be even, [key val]*)"
1150                                    .to_string(),
1151                            ),
1152                            chunk.clone(),
1153                        ));
1154                    } else {
1155                        let mut map = VMHashMap::new();
1156                        for i in (start..end).step_by(2) {
1157                            map.insert(
1158                                self,
1159                                self.register(i as usize),
1160                                self.register(i as usize + 1),
1161                            );
1162                        }
1163                        map
1164                    };
1165                    let mh = self.alloc_map(map);
1166                    set_register!(self, dest as usize, mh);
1167                }
1168                VECMK => {
1169                    let (dest, op) = decode2!(self.ip_ptr, wide);
1170                    let len = self
1171                        .register(op as usize)
1172                        .get_int(self)
1173                        .map_err(|e| (e, chunk.clone()))?;
1174                    let val = self.alloc_vector(Vec::with_capacity(len as usize));
1175                    set_register!(self, dest as usize, val);
1176                }
1177                VECELS => {
1178                    let (dest, op) = decode2!(self.ip_ptr, wide);
1179                    let len = self
1180                        .register(op as usize)
1181                        .get_int(self)
1182                        .map_err(|e| (e, chunk.clone()))?;
1183                    if let Value::Vector(h) = self.register(dest as usize) {
1184                        let v = self
1185                            .heap_mut()
1186                            .get_vector_mut(h)
1187                            .map_err(|e| (e, chunk.clone()))?;
1188                        v.resize(len as usize, Value::Undefined);
1189                    }
1190                }
1191                VECPSH => {
1192                    let (dest, op) = decode2!(self.ip_ptr, wide);
1193                    let val = self.register(op as usize);
1194                    if let Value::Vector(h) = self.register(dest as usize) {
1195                        let v = self
1196                            .heap_mut()
1197                            .get_vector_mut(h)
1198                            .map_err(|e| (e, chunk.clone()))?;
1199                        v.push(val);
1200                    }
1201                }
1202                VECPOP => {
1203                    let (vc, dest) = decode2!(self.ip_ptr, wide);
1204                    let val = if let Value::Vector(h) = self.register(vc as usize) {
1205                        let v = self
1206                            .heap_mut()
1207                            .get_vector_mut(h)
1208                            .map_err(|e| (e, chunk.clone()))?;
1209                        if let Some(val) = v.pop() {
1210                            val
1211                        } else {
1212                            return Err((VMError::new_vm("VECPOP: Vector is empty."), chunk));
1213                        }
1214                    } else {
1215                        return Err((VMError::new_vm("VECPOP: Not a vector."), chunk));
1216                    };
1217                    set_register!(self, dest as usize, val);
1218                }
1219                VECMKD => {
1220                    let (dest, len, dfn) = decode3!(self.ip_ptr, wide);
1221                    let len = self
1222                        .register(len as usize)
1223                        .get_int(self)
1224                        .map_err(|e| (e, chunk.clone()))?;
1225                    let dfn = self.register(dfn as usize);
1226                    let mut v = Vec::with_capacity(len as usize);
1227                    for _ in 0..len {
1228                        v.push(dfn);
1229                    }
1230                    let val = self.alloc_vector(v);
1231                    set_register!(self, dest as usize, val);
1232                }
1233                LEN => {
1234                    let (dest, v) = decode2!(self.ip_ptr, wide);
1235                    let len = match self.register(v as usize) {
1236                        Value::String(h) => {
1237                            let mut len: i64 = 0;
1238                            for _ in UnicodeSegmentation::graphemes(self.get_string(h), true) {
1239                                len += 1;
1240                            }
1241                            len
1242                        }
1243                        Value::StringConst(i) => {
1244                            let mut len: i64 = 0;
1245                            for _ in UnicodeSegmentation::graphemes(self.get_interned(i), true) {
1246                                len += 1;
1247                            }
1248                            len
1249                        }
1250                        Value::Vector(h) => self.get_vector(h).len() as i64,
1251                        Value::List(h, i) => self.get_vector(h).len() as i64 - i as i64,
1252                        Value::Pair(h) => {
1253                            let mut len: i64 = 1;
1254                            let (_, mut cdr) = self.get_pair(h);
1255                            while let Value::Pair(h) = cdr {
1256                                let (_, c) = self.get_pair(h);
1257                                cdr = c;
1258                                len += 1;
1259                            }
1260                            len
1261                        }
1262                        Value::Map(h) => self.get_map(h).len() as i64,
1263                        Value::Nil | Value::False => 0,
1264                        _ => 1, /*Err(VMError::new_vm(format!(
1265                                    "len: net valid for value of type {}",
1266                                    val.display_type(vm)
1267                                ))),
1268                                */
1269                    };
1270                    set_register!(self, dest as usize, len.into());
1271                }
1272                CLR => {
1273                    let v = decode1!(self.ip_ptr, wide);
1274                    let val = self.register(v as usize);
1275                    match val {
1276                        Value::Vector(h) => {
1277                            let v = self
1278                                .heap_mut()
1279                                .get_vector_mut(h)
1280                                .map_err(|e| (e, chunk.clone()))?;
1281                            v.clear();
1282                        }
1283                        Value::Map(h) => {
1284                            self.get_map_mut(h).map_err(|e| (e, chunk.clone()))?.clear();
1285                        }
1286                        Value::String(h) => {
1287                            self.get_string_mut(h)
1288                                .map_err(|e| (e, chunk.clone()))?
1289                                .clear();
1290                        }
1291                        Value::StringConst(_) => {
1292                            return Err((
1293                                VMError::new_vm("can not clear a string const".to_string()),
1294                                chunk.clone(),
1295                            ));
1296                        }
1297                        _ => {
1298                            return Err((
1299                                VMError::new_vm(format!(
1300                                    "clr: net valid for value of type {}",
1301                                    val.display_type(self)
1302                                )),
1303                                chunk.clone(),
1304                            ));
1305                        }
1306                    }
1307                }
1308                STR => {
1309                    let (dest, reg1, reg2) = decode3!(self.ip_ptr, wide);
1310                    let val = self.mk_str(reg1, reg2).map_err(|e| (e, chunk.clone()))?;
1311                    set_register!(self, dest as usize, val);
1312                }
1313                TYPE => {
1314                    let (dest, val) = decode2!(self.ip_ptr, wide);
1315                    let val = self.register(val as usize);
1316                    let t = Value::Keyword(self.intern_static(val.display_type(self)));
1317                    set_register!(self, dest as usize, t);
1318                }
1319                _ => {
1320                    return Err((VMError::new_vm(format!("Invalid opcode {opcode}")), chunk));
1321                }
1322            }
1323            // Don't do stuff after match, do it at the top of the loop to avoid extra JMPs.
1324        }
1325    }
1326}