Skip to main content

qanglang_core/backend/
vm.rs

1use std::collections::VecDeque;
2
3use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
4
5#[cfg(debug_assertions)]
6use crate::debug::disassemble_instruction;
7use crate::{
8    BoundIntrinsicObject, BoundMethodObject, ClassHandle, ClosureHandle, HashMapHandle,
9    HeapAllocator, NativeFn, NativeFunctionError, NativeFunctionHandle, NativeFunctionObject,
10    QangProgram, QangRuntimeError, StringHandle, Value, ValueKind,
11    backend::{
12        assembler::{FRAME_MAX, STACK_MAX},
13        chunk::{OpCode, SourceLocation},
14        external_context::ExternalContext,
15        module_resolver::ModuleResolver,
16        object::{ClosureObject, FunctionObject, IntrinsicKind, IntrinsicMethod, UpvalueSlot},
17        qang_std::{
18            qang_array_create, qang_assert, qang_assert_eq, qang_assert_throws, qang_env_cwd,
19            qang_hash, qang_object_assign, qang_object_get, qang_object_set,
20            qang_object_to_entries, qang_print, qang_println, qang_system_time, qang_to_string,
21            qang_typeof,
22        },
23        value::{
24            ARRAY_TYPE_STRING, BOOLEAN_TYPE_STRING, CLASS_TYPE_STRING, FUNCTION_TYPE_STRING,
25            MODULE_TYPE_STRING, NIL_TYPE_STRING, NUMBER_TYPE_STRING, OBJECT_TYPE_STRING,
26            STRING_TYPE_STRING,
27        },
28    },
29    debug_log,
30};
31
32#[derive(Debug, Clone)]
33pub struct BinaryOperationError(pub String);
34
35impl BinaryOperationError {
36    pub fn new(message: &str) -> Self {
37        Self(message.to_string())
38    }
39
40    fn into_qang_error(self, loc: SourceLocation) -> QangRuntimeError {
41        QangRuntimeError::new(self.0, loc)
42    }
43}
44
45impl From<&'_ str> for BinaryOperationError {
46    fn from(value: &'_ str) -> Self {
47        BinaryOperationError::new(value)
48    }
49}
50
51pub type RuntimeResult<T> = Result<T, QangRuntimeError>;
52
53type StackSlot = usize;
54type UpvalueIndex = usize;
55use crate::memory::OpenUpvalueTracker;
56type OpenUpvalueEntry = (StackSlot, OpenUpvalueTracker);
57
58#[derive(Debug, Clone, Copy)]
59pub struct PropertyCache {
60    pub object_type: CachedObjectType,
61    pub property_name: StringHandle,
62    pub table_handle: HashMapHandle,
63    pub generation: u32,
64}
65
66#[derive(Debug, Clone, Copy, PartialEq)]
67pub enum CachedObjectType {
68    Instance(ClassHandle),
69    ObjectLiteral,
70    Module,
71}
72
73impl Default for PropertyCache {
74    fn default() -> Self {
75        Self {
76            object_type: CachedObjectType::ObjectLiteral,
77            property_name: StringHandle::default(),
78            table_handle: HashMapHandle::default(),
79            generation: 0,
80        }
81    }
82}
83
84#[derive(Debug, Clone, Copy)]
85pub struct MethodCache {
86    pub object_type: CachedObjectType,
87    pub method_name: StringHandle,
88    pub table_handle: HashMapHandle,
89    pub cached_method: Value,
90    pub generation: u32,
91}
92
93impl Default for MethodCache {
94    fn default() -> Self {
95        Self {
96            object_type: CachedObjectType::ObjectLiteral,
97            method_name: StringHandle::default(),
98            table_handle: HashMapHandle::default(),
99            cached_method: Value::nil(),
100            generation: 0,
101        }
102    }
103}
104
105#[macro_export]
106macro_rules! push_value {
107    ($vm:expr, $value:expr) => {
108        if $vm.state.stack_top >= STACK_MAX {
109            Err($crate::QangRuntimeError::new(
110                format!(
111                    "Stack overflow: maximum stack size of {} exceeded",
112                    STACK_MAX
113                ),
114                $vm.state.get_current_loc(),
115            ))
116        } else {
117            $vm.state.stack[$vm.state.stack_top] = $value;
118            $vm.state.stack_top += 1;
119            Ok(())
120        }
121    };
122}
123
124#[macro_export]
125macro_rules! pop_value {
126    ($vm:expr) => {{
127        debug_assert!(
128            $vm.state.stack_top > 0,
129            "Stack underflow: unexpected empty stack."
130        );
131        $vm.state.stack_top -= 1;
132        $vm.state.stack[$vm.state.stack_top]
133    }};
134}
135
136#[macro_export]
137macro_rules! peek_value {
138    ($vm:expr, $distance:expr) => {
139        if $vm.state.stack_top > $distance {
140            $vm.state
141                .stack
142                .get($vm.state.stack_top - 1 - $distance)
143                .copied()
144                .unwrap_or(Value::nil())
145        } else {
146            Value::nil()
147        }
148    };
149}
150
151#[macro_export]
152macro_rules! read_string {
153    ($vm:expr) => {
154        match $vm.state.read_constant().as_string() {
155            Some(handle) => handle,
156            _ => panic!("Expected string constant"),
157        }
158    };
159}
160
161#[macro_export]
162macro_rules! read_string_16 {
163    ($vm:expr) => {
164        match $vm.state.read_constant_16().as_string() {
165            Some(handle) => handle,
166            _ => panic!("Expected string constant"),
167        }
168    };
169}
170
171#[derive(Debug, Clone, Default)]
172pub(crate) struct CallFrame {
173    pub closure: ClosureHandle,
174    pub ip: usize,
175    pub value_slot: usize,
176    pub module_export_target: Option<HashMapHandle>,
177}
178
179#[derive(Debug, Clone)]
180pub(crate) struct VmState {
181    pub stack_top: usize,
182    pub frame_count: usize,
183    pub stack: Vec<Value>,
184    pub frames: [CallFrame; FRAME_MAX],
185    globals: FxHashMap<StringHandle, Value>,
186    intrinsics: FxHashMap<IntrinsicKind, IntrinsicMethod>,
187    open_upvalues: Vec<OpenUpvalueEntry>,
188    current_function_ptr: *const FunctionObject,
189    pub modules: ModuleResolver,
190    function_module_context: Option<HashMapHandle>,
191    property_cache: [PropertyCache; Self::PROPERTY_CACHE_SIZE],
192    method_cache: [MethodCache; Self::METHOD_CACHE_SIZE],
193    cache_generation: u32,
194    pub(crate) arg_buffer: [Value; 256],
195    additional_roots: FxHashSet<Value>,
196}
197
198impl VmState {
199    const PROPERTY_CACHE_SIZE: usize = 256;
200    const METHOD_CACHE_SIZE: usize = 256;
201
202    fn new(
203        globals: FxHashMap<StringHandle, Value>,
204        intrinsics: FxHashMap<IntrinsicKind, IntrinsicMethod>,
205    ) -> Self {
206        Self {
207            frame_count: 0,
208            stack_top: 0,
209            stack: vec![Value::default(); STACK_MAX],
210            frames: std::array::from_fn(|_| CallFrame::default()),
211            globals,
212            intrinsics,
213            open_upvalues: Vec::with_capacity(8),
214            current_function_ptr: std::ptr::null(),
215            modules: ModuleResolver::default(),
216            function_module_context: None,
217            property_cache: [PropertyCache::default(); Self::PROPERTY_CACHE_SIZE],
218            method_cache: [MethodCache::default(); Self::METHOD_CACHE_SIZE],
219            cache_generation: 0,
220            arg_buffer: [Value::default(); 256],
221            additional_roots: FxHashSet::with_capacity_and_hasher(64, FxBuildHasher),
222        }
223    }
224
225    fn invalidate_caches(&mut self) {
226        self.cache_generation = self.cache_generation.wrapping_add(1);
227    }
228
229    fn get_property_cache_index(&self) -> usize {
230        let ip = self.frames[self.frame_count - 1].ip;
231        let closure_handle = self.frames[self.frame_count - 1].closure;
232
233        let cache_key = (ip as u64) ^ closure_handle.as_raw();
234        cache_key as usize % Self::PROPERTY_CACHE_SIZE
235    }
236
237    fn get_method_cache_index(&self) -> usize {
238        let ip = self.frames[self.frame_count - 1].ip;
239        let closure_handle = self.frames[self.frame_count - 1].closure;
240
241        let cache_key = (ip as u64) ^ closure_handle.as_raw();
242        cache_key as usize % Self::METHOD_CACHE_SIZE
243    }
244
245    fn get_current_function(&self) -> &FunctionObject {
246        debug_assert!(
247            !self.current_function_ptr.is_null(),
248            "Function pointer is null"
249        );
250        unsafe { &*self.current_function_ptr }
251    }
252
253    pub fn get_current_loc(&self) -> SourceLocation {
254        self.get_loc_at(self.frames[self.frame_count - 1].ip)
255    }
256
257    pub fn get_previous_loc(&self) -> SourceLocation {
258        if self.frames[self.frame_count - 1].ip > 0 {
259            self.get_loc_at(self.frames[self.frame_count - 1].ip - 1)
260        } else {
261            SourceLocation::default()
262        }
263    }
264
265    pub fn get_loc_at(&self, index: usize) -> SourceLocation {
266        self.get_current_function()
267            .chunk
268            .locs
269            .get(index)
270            .copied()
271            .unwrap_or_default()
272    }
273
274    fn read_byte(&mut self) -> u8 {
275        let frame = unsafe { self.frames.get_unchecked_mut(self.frame_count - 1) };
276        debug_assert!(
277            !self.current_function_ptr.is_null(),
278            "Function pointer is null"
279        );
280
281        let code = unsafe { &(*self.current_function_ptr).chunk.code };
282        debug_assert!(frame.ip < code.len(), "IP out of bounds");
283        let byte = unsafe { *code.get_unchecked(frame.ip) };
284        frame.ip += 1;
285        byte
286    }
287
288    fn read_constant(&mut self) -> Value {
289        let index = self.read_byte() as usize;
290        debug_assert!(
291            !self.current_function_ptr.is_null(),
292            "Function pointer is null"
293        );
294        let constants = unsafe { &(*self.current_function_ptr).chunk.constants };
295        debug_assert!(index < constants.len(), "Constant index out of bounds");
296        constants[index]
297    }
298
299    fn read_constant_16(&mut self) -> Value {
300        let index = self.read_short();
301        debug_assert!(
302            !self.current_function_ptr.is_null(),
303            "Function pointer is null"
304        );
305        let constants = unsafe { &(*self.current_function_ptr).chunk.constants };
306        debug_assert!(index < constants.len(), "Constant index out of bounds");
307        constants[index]
308    }
309
310    fn read_short(&mut self) -> usize {
311        let high_byte = self.read_byte() as usize;
312        let low_byte = self.read_byte() as usize;
313        (high_byte << 8) | low_byte
314    }
315}
316
317#[derive(Debug)]
318pub struct Vm {
319    pub is_debug: bool,
320    pub is_gc_enabled: bool,
321    pub(crate) state: VmState,
322    pub alloc: HeapAllocator,
323    pub external_context: ExternalContext,
324}
325
326impl Vm {
327    pub(crate) fn with_gc_check<T>(&mut self, op: impl FnOnce(&mut HeapAllocator) -> T) -> T {
328        if self.is_gc_enabled && self.alloc.should_collect_garbage() {
329            self.collect_garbage();
330        }
331        op(&mut self.alloc)
332    }
333
334    pub fn new(mut alloc: HeapAllocator) -> Self {
335        let mut globals = FxHashMap::with_capacity_and_hasher(64, FxBuildHasher);
336
337        let nil_type_value_handle = alloc.strings.intern(NIL_TYPE_STRING);
338        globals.insert(
339            alloc.strings.intern("NIL"),
340            Value::string(nil_type_value_handle),
341        );
342        let boolean_type_value_handle = alloc.strings.intern(BOOLEAN_TYPE_STRING);
343        globals.insert(
344            alloc.strings.intern("BOOLEAN"),
345            Value::string(boolean_type_value_handle),
346        );
347        let number_type_value_handle = alloc.strings.intern(NUMBER_TYPE_STRING);
348        globals.insert(
349            alloc.strings.intern("NUMBER"),
350            Value::string(number_type_value_handle),
351        );
352        let string_type_value_handle = alloc.strings.intern(STRING_TYPE_STRING);
353        globals.insert(
354            alloc.strings.intern("STRING"),
355            Value::string(string_type_value_handle),
356        );
357        let function_type_value_handle = alloc.strings.intern(FUNCTION_TYPE_STRING);
358        globals.insert(
359            alloc.strings.intern("FUNCTION"),
360            Value::string(function_type_value_handle),
361        );
362        let class_type_value_handle = alloc.strings.intern(CLASS_TYPE_STRING);
363        globals.insert(
364            alloc.strings.intern("CLASS"),
365            Value::string(class_type_value_handle),
366        );
367        let object_type_value_handle = alloc.strings.intern(OBJECT_TYPE_STRING);
368        globals.insert(
369            alloc.strings.intern("OBJECT"),
370            Value::string(object_type_value_handle),
371        );
372        let array_type_value_handle = alloc.strings.intern(ARRAY_TYPE_STRING);
373        globals.insert(
374            alloc.strings.intern("ARRAY"),
375            Value::string(array_type_value_handle),
376        );
377        let module_type_value_handle = alloc.strings.intern(MODULE_TYPE_STRING);
378        globals.insert(
379            alloc.strings.intern("MODULE"),
380            Value::string(module_type_value_handle),
381        );
382        let mut vm = Self {
383            is_debug: false,
384            is_gc_enabled: true,
385            state: VmState::new(globals, Self::load_intrinsics(&mut alloc)),
386            alloc,
387            external_context: ExternalContext::new(),
388        };
389
390        vm.add_native_function("assert", 2, qang_assert)
391            .add_native_function("assert_eq", 3, qang_assert_eq)
392            .add_native_function("assert_throws", 2, qang_assert_throws)
393            .add_native_function("print", 1, qang_print)
394            .add_native_function("println", 1, qang_println)
395            .add_native_function("system_time", 0, qang_system_time)
396            .add_native_function("typeof", 1, qang_typeof)
397            .add_native_function("to_string", 1, qang_to_string)
398            .add_native_function("hash", 1, qang_hash)
399            .add_native_function("array_of_length", 1, qang_array_create)
400            .add_native_function("env_cwd", 0, qang_env_cwd)
401            .add_native_function("object_to_entries", 1, qang_object_to_entries)
402            .add_native_function("object_get", 2, qang_object_get)
403            .add_native_function("object_set", 3, qang_object_set)
404            .add_native_function("object_assign", 2, qang_object_assign)
405            .with_stdlib()
406            .with_native_filesystem();
407
408        vm
409    }
410
411    pub fn set_debug(mut self, is_debug: bool) -> Self {
412        self.is_debug = is_debug;
413        self
414    }
415
416    pub fn set_gc_status(mut self, is_enabled: bool) -> Self {
417        self.is_gc_enabled = is_enabled;
418        self
419    }
420
421    pub fn add_native_function(
422        &mut self,
423        name: &str,
424        arity: usize,
425        function: NativeFn,
426    ) -> &mut Self {
427        let identifier_handle = self.alloc.strings.intern(name);
428        let native_function = NativeFunctionObject {
429            name_handle: identifier_handle,
430            arity,
431            function,
432        };
433        let handle = self.alloc.allocate_native_function(native_function);
434
435        self.state
436            .globals
437            .insert(identifier_handle, Value::native_function(handle));
438
439        self
440    }
441
442    pub fn add_external_root(&mut self, value: Value) {
443        self.state.additional_roots.insert(value);
444    }
445
446    pub fn remove_external_root(&mut self, value: Value) {
447        self.state.additional_roots.remove(&value);
448    }
449
450    pub fn interpret(&mut self, program: QangProgram) -> RuntimeResult<()> {
451        let function_handle = program.get_handle();
452        self.state.modules = program.into_modules();
453        let upvalue_count = self.alloc.get_function(function_handle).upvalue_count;
454
455        let handle = self.alloc.closures.allocate_closure(ClosureObject::new(
456            function_handle,
457            upvalue_count,
458            None,
459        ));
460        push_value!(self, Value::closure(handle))?;
461        self.call(handle, 0)?;
462
463        #[cfg(feature = "profiler")]
464        coz::scope!("vm_interpret");
465
466        let _ = self
467            .run()
468            .map_err(|e| e.with_stack_trace(self.get_stack_trace()))?;
469
470        #[cfg(feature = "profiler")]
471        coz::progress!("execution_complete");
472
473        Ok(())
474    }
475
476    fn run(&mut self) -> RuntimeResult<Value> {
477        loop {
478            #[cfg(feature = "profiler")]
479            coz::progress!("vm_instructions");
480
481            #[cfg(debug_assertions)]
482            {
483                if self.is_debug {
484                    self.debug_print();
485                }
486            }
487
488            let opcode: OpCode = self.state.read_byte().into();
489
490            match opcode {
491                OpCode::Constant => {
492                    let constant = self.state.read_constant();
493                    push_value!(self, constant)?;
494                }
495                OpCode::Constant16 => {
496                    let constant = self.state.read_constant_16();
497                    push_value!(self, constant)?;
498                }
499                OpCode::Negate => {
500                    if let Some(number) = peek_value!(self, 0).as_number() {
501                        if let Some(stack_value) =
502                            self.state.stack.get_mut(self.state.stack_top - 1)
503                        {
504                            *stack_value = Value::number(-number);
505                        }
506                    } else {
507                        return Err(QangRuntimeError::new(
508                            "Operand must be a number.".to_string(),
509                            self.state.get_previous_loc(),
510                        ));
511                    }
512                }
513                OpCode::Not => {
514                    let value = peek_value!(self, 0);
515                    if let Some(stack_value) = self.state.stack.get_mut(self.state.stack_top - 1) {
516                        *stack_value = (!value.is_truthy()).into();
517                    }
518                }
519                OpCode::True => {
520                    push_value!(self, Value::boolean(true))?;
521                }
522                OpCode::False => {
523                    push_value!(self, Value::boolean(false))?;
524                }
525                OpCode::Nil => {
526                    push_value!(self, Value::nil())?;
527                }
528                OpCode::Add => {
529                    self.binary_operation(|a, b, alloc| match (a.kind(), b.kind()) {
530                        (ValueKind::Number(num1), ValueKind::Number(num2)) => {
531                            Ok(Value::number(num1 + num2))
532                        }
533                        (ValueKind::String(handle1), ValueKind::String(handle2)) => {
534                            #[cfg(feature = "profiler")]
535                            coz::scope!("string_concatenation");
536                            Ok(Value::string(alloc.strings.concat(handle1, handle2)))
537                        }
538                        (ValueKind::Array(handle1), ValueKind::Array(handle2)) => {
539                            Ok(Value::array(alloc.arrays.concat(handle1, handle2)))
540                        }
541                        (ValueKind::Number(_), _) => {
542                            Err(format!("Cannot add number to {}.", b.to_type_string())
543                                .as_str()
544                                .into())
545                        }
546                        (ValueKind::String(_), _) => {
547                            Err(format!("Cannot add string to {}.", b.to_type_string())
548                                .as_str()
549                                .into())
550                        }
551                        (ValueKind::Array(_), _) => {
552                            Err(format!("Cannot add an array to {}.", b.to_type_string())
553                                .as_str()
554                                .into())
555                        }
556                        (_, ValueKind::Number(_)) => {
557                            Err(format!("Cannot add {} to number.", a.to_type_string())
558                                .as_str()
559                                .into())
560                        }
561                        (_, ValueKind::String(_)) => {
562                            Err(format!("Cannot add {} to string.", a.to_type_string())
563                                .as_str()
564                                .into())
565                        }
566                        (_, ValueKind::Array(_)) => {
567                            Err(format!("Cannot add {} to an array.", a.to_type_string())
568                                .as_str()
569                                .into())
570                        }
571                        _ => Err("Both operands must be a numbers, strings or arrays.".into()),
572                    })?;
573                }
574                OpCode::Subtract => self.binary_operation(|a, b, _allocator| {
575                    match (a.as_number(), b.as_number()) {
576                        (Some(num1), Some(num2)) => Ok((num1 - num2).into()),
577                        _ => Err(BinaryOperationError::new("Both operands must be a number.")),
578                    }
579                })?,
580                OpCode::Multiply => self.binary_operation(|a, b, _allocator| {
581                    match (a.as_number(), b.as_number()) {
582                        (Some(num1), Some(num2)) => Ok((num1 * num2).into()),
583                        _ => Err(BinaryOperationError::new("Both operands must be a number.")),
584                    }
585                })?,
586                OpCode::Divide => self.binary_operation(|a, b, _allocator| {
587                    match (a.as_number(), b.as_number()) {
588                        (Some(num1), Some(num2)) => {
589                            if num2 == 0.0 {
590                                Err(BinaryOperationError::new("Cannot divide by zero."))
591                            } else {
592                                Ok((num1 / num2).into())
593                            }
594                        }
595                        _ => Err(BinaryOperationError::new("Both operands must be a number.")),
596                    }
597                })?,
598                OpCode::Modulo => self.binary_operation(|a, b, _allocator| {
599                    match (a.as_number(), b.as_number()) {
600                        (Some(num1), Some(num2)) => Ok((num1 % num2).into()),
601                        _ => Err(BinaryOperationError::new("Both operands must be a number.")),
602                    }
603                })?,
604                OpCode::Equal => self.binary_operation(|a, b, _allocator| Ok((a == b).into()))?,
605                OpCode::Greater => self.binary_operation(|a, b, _allocator| {
606                    match (a.as_number(), b.as_number()) {
607                        (Some(num1), Some(num2)) => Ok((num1 > num2).into()),
608                        _ => Err(BinaryOperationError::new("Both operands must be a number.")),
609                    }
610                })?,
611                OpCode::GreaterEqual => self.binary_operation(|a, b, _allocator| {
612                    match (a.as_number(), b.as_number()) {
613                        (Some(num1), Some(num2)) => Ok((num1 >= num2).into()),
614                        _ => Err(BinaryOperationError::new("Both operands must be a number.")),
615                    }
616                })?,
617                OpCode::Less => self.binary_operation(|a, b, _allocator| {
618                    match (a.as_number(), b.as_number()) {
619                        (Some(num1), Some(num2)) => Ok((num1 < num2).into()),
620                        _ => Err(BinaryOperationError::new("Both operands must be a number.")),
621                    }
622                })?,
623                OpCode::LessEqual => self.binary_operation(|a, b, _allocator| {
624                    match (a.as_number(), b.as_number()) {
625                        (Some(num1), Some(num2)) => Ok((num1 <= num2).into()),
626                        _ => Err(BinaryOperationError::new("Both operands must be a number.")),
627                    }
628                })?,
629                OpCode::Is => {
630                    let b = pop_value!(self);
631                    let a = pop_value!(self);
632
633                    let result = match (a.kind(), b.kind()) {
634                        (ValueKind::Array(_), ValueKind::String(string_handle)) => {
635                            let array_handle = self.alloc.strings.intern("array");
636                            array_handle == string_handle
637                        }
638                        (ValueKind::Number(_), ValueKind::String(string_handle)) => {
639                            let number_handle = self.alloc.strings.intern("number");
640                            number_handle == string_handle
641                        }
642                        (ValueKind::String(_), ValueKind::String(string_handle)) => {
643                            let other_string_handle = self.alloc.strings.intern("string");
644                            other_string_handle == string_handle
645                        }
646                        (ValueKind::Nil, ValueKind::String(string_handle)) => {
647                            let nil_handle = self.alloc.strings.intern("nil");
648                            nil_handle == string_handle
649                        }
650                        (ValueKind::True | ValueKind::False, ValueKind::String(string_handle)) => {
651                            let boolean_handle = self.alloc.strings.intern("boolean");
652                            boolean_handle == string_handle
653                        }
654                        (ValueKind::Class(_), ValueKind::String(string_handle)) => {
655                            let class_handle = self.alloc.strings.intern("class");
656                            class_handle == string_handle
657                        }
658                        (
659                            ValueKind::ObjectLiteral(_) | ValueKind::Instance(_),
660                            ValueKind::String(string_handle),
661                        ) => {
662                            let object_handle = self.alloc.strings.intern("object");
663                            object_handle == string_handle
664                        }
665                        (
666                            ValueKind::FunctionDecl(_)
667                            | ValueKind::NativeFunction(_)
668                            | ValueKind::Closure(_)
669                            | ValueKind::BoundMethod(_)
670                            | ValueKind::BoundIntrinsic(_),
671                            ValueKind::String(string_handle),
672                        ) => {
673                            let function_handle = self.alloc.strings.intern("function");
674                            function_handle == string_handle
675                        }
676                        (ValueKind::Instance(instance_handle), ValueKind::Class(clazz_handle)) => {
677                            let instance_of_handle = self.alloc.get_instance(instance_handle).clazz;
678
679                            if instance_of_handle == clazz_handle {
680                                true
681                            } else {
682                                let mut current_handle = instance_of_handle;
683                                loop {
684                                    let current_class = self.alloc.get_class(current_handle);
685                                    if let Some(super_handle) = current_class.super_clazz {
686                                        if super_handle == clazz_handle {
687                                            break true;
688                                        }
689                                        current_handle = super_handle;
690                                    } else {
691                                        break false;
692                                    }
693                                }
694                            }
695                        }
696                        _ => false,
697                    };
698
699                    push_value!(self, result.into())?;
700                }
701                OpCode::Pop => {
702                    pop_value!(self);
703                }
704                OpCode::DefineGlobal => {
705                    let identifier_handle = read_string!(self);
706                    let value = pop_value!(self);
707
708                    if let Some(module_target) =
709                        self.state.frames[self.state.frame_count - 1].module_export_target
710                    {
711                        self.alloc.tables.insert(
712                            module_target,
713                            Value::string(identifier_handle),
714                            value,
715                        );
716                    } else {
717                        self.state.globals.insert(identifier_handle, value);
718                    }
719                }
720
721                OpCode::DefineGlobal16 => {
722                    let identifier_handle = read_string_16!(self);
723                    let value = pop_value!(self);
724
725                    if let Some(module_target) =
726                        self.state.frames[self.state.frame_count - 1].module_export_target
727                    {
728                        self.alloc.tables.insert(
729                            module_target,
730                            Value::string(identifier_handle),
731                            value,
732                        );
733                    } else {
734                        self.state.globals.insert(identifier_handle, value);
735                    }
736                }
737                OpCode::SetGlobal => {
738                    let identifier_handle = read_string!(self);
739                    self.set_global(identifier_handle)?;
740                }
741
742                OpCode::SetGlobal16 => {
743                    let identifier_handle = read_string_16!(self);
744                    self.set_global(identifier_handle)?;
745                }
746                OpCode::GetGlobal => {
747                    let identifier_handle = read_string!(self);
748                    let value = self.get_global(identifier_handle)?;
749                    push_value!(self, value)?;
750                }
751
752                OpCode::GetGlobal16 => {
753                    let identifier_handle = read_string_16!(self);
754                    let value = self.get_global(identifier_handle)?;
755                    push_value!(self, value)?;
756                }
757                OpCode::GetLocal => {
758                    let slot = self.state.read_byte();
759                    let absolute_slot =
760                        self.state.frames[self.state.frame_count - 1].value_slot + slot as usize;
761                    debug_assert!(
762                        absolute_slot < STACK_MAX,
763                        "Local slot {} out of bounds",
764                        absolute_slot
765                    );
766
767                    let value = self.state.stack[absolute_slot];
768                    push_value!(self, value)?;
769                }
770                OpCode::SetLocal => {
771                    let slot = self.state.read_byte();
772                    let value = peek_value!(self, 0);
773                    let absolute_slot =
774                        self.state.frames[self.state.frame_count - 1].value_slot + slot as usize;
775
776                    self.state.stack[absolute_slot] = value;
777                }
778                OpCode::JumpIfFalse => {
779                    let offset = self.state.read_short();
780                    if !peek_value!(self, 0).is_truthy() {
781                        self.state.frames[self.state.frame_count - 1].ip += offset;
782                    }
783                }
784                OpCode::JumpIfNil => {
785                    let offset = self.state.read_short();
786                    if peek_value!(self, 0).is_nil() {
787                        self.state.frames[self.state.frame_count - 1].ip += offset;
788                    }
789                }
790                OpCode::Jump => {
791                    let offset = self.state.read_short();
792                    self.state.frames[self.state.frame_count - 1].ip += offset;
793                }
794                OpCode::Loop => {
795                    let offset = self.state.read_short();
796                    self.state.frames[self.state.frame_count - 1].ip -= offset;
797                }
798                OpCode::Call => {
799                    let arg_count = self.state.read_byte() as usize;
800                    let function_value = peek_value!(self, arg_count);
801                    self.call_value(function_value, arg_count)?;
802                }
803                OpCode::TailCall => {
804                    let arg_count = self.state.read_byte() as usize;
805                    let function_value = peek_value!(self, arg_count);
806                    self.tail_call_value(function_value, arg_count)?;
807                }
808                OpCode::Closure => {
809                    let constant = self.state.read_constant();
810                    self.create_closure(constant)?;
811                }
812                OpCode::Closure16 => {
813                    let constant = self.state.read_constant_16();
814                    self.create_closure(constant)?;
815                }
816                OpCode::GetUpvalue => {
817                    let slot = self.state.read_byte() as usize;
818                    let current_closure_handle =
819                        self.state.frames[self.state.frame_count - 1].closure;
820                    let upvalue = self
821                        .alloc
822                        .closures
823                        .get_upvalue(current_closure_handle, slot)
824                        .unwrap_or(UpvalueSlot::Open(0));
825
826                    match upvalue {
827                        UpvalueSlot::Open(stack_slot) => {
828                            let value = self.state.stack[stack_slot];
829                            push_value!(self, value)?;
830                        }
831                        UpvalueSlot::Closed(value_handle) => {
832                            let value = *self.alloc.get_upvalue(value_handle);
833                            push_value!(self, value)?;
834                        }
835                    }
836                }
837                OpCode::SetUpvalue => {
838                    let slot = self.state.read_byte() as usize;
839                    let value = peek_value!(self, 0);
840                    let current_closure_handle =
841                        self.state.frames[self.state.frame_count - 1].closure;
842
843                    let upvalue = self
844                        .alloc
845                        .closures
846                        .get_upvalue(current_closure_handle, slot)
847                        .unwrap_or(UpvalueSlot::Open(0));
848                    match upvalue {
849                        UpvalueSlot::Open(stack_slot) => {
850                            self.state.stack[stack_slot] = value;
851                        }
852                        UpvalueSlot::Closed(value_handle) => {
853                            *self.alloc.get_upvalue_mut(value_handle) = value;
854                        }
855                    }
856                }
857                OpCode::CloseUpvalue => {
858                    self.close_upvalue(self.state.stack_top - 1);
859                    pop_value!(self);
860                }
861                OpCode::Class => {
862                    let identifier_handle = read_string!(self);
863                    let class_handle: crate::arena::Index =
864                        self.with_gc_check(|alloc| alloc.allocate_class(identifier_handle));
865                    push_value!(self, Value::class(class_handle))?
866                }
867                OpCode::Class16 => {
868                    let identifier_handle = read_string_16!(self);
869                    let class_handle: crate::arena::Index =
870                        self.with_gc_check(|alloc| alloc.allocate_class(identifier_handle));
871                    push_value!(self, Value::class(class_handle))?
872                }
873                OpCode::GetProperty => {
874                    let object = peek_value!(self, 0);
875                    let identifier = read_string!(self);
876                    self.get_property_value(object, false, identifier)?;
877                }
878                OpCode::GetProperty16 => {
879                    let object = peek_value!(self, 0);
880                    let identifier = read_string_16!(self);
881                    self.get_property_value(object, false, identifier)?;
882                }
883                OpCode::SetProperty => {
884                    let identifier = read_string!(self);
885                    self.set_property(identifier)?
886                }
887                OpCode::SetProperty16 => {
888                    let identifier = read_string_16!(self);
889                    self.set_property(identifier)?
890                }
891                OpCode::GetOptionalProperty => {
892                    let object = peek_value!(self, 0);
893                    let identifier = read_string!(self);
894                    self.get_property_value(object, true, identifier)?;
895                }
896                OpCode::GetOptionalProperty16 => {
897                    let object = peek_value!(self, 0);
898                    let identifier = read_string_16!(self);
899                    self.get_property_value(object, true, identifier)?;
900                }
901                OpCode::Method => {
902                    let identifier_handle = read_string!(self);
903                    self.define_method(identifier_handle)?;
904                }
905                OpCode::Method16 => {
906                    let identifier_handle = read_string_16!(self);
907                    self.define_method(identifier_handle)?;
908                }
909                OpCode::InitField => {
910                    let identifier_handle = read_string!(self);
911                    let value = pop_value!(self);
912                    self.init_field(identifier_handle, value)?;
913                }
914                OpCode::InitField16 => {
915                    let identifier_handle = read_string_16!(self);
916                    let value = pop_value!(self);
917                    self.init_field(identifier_handle, value)?;
918                }
919                OpCode::Invoke => {
920                    let method_handle = read_string!(self);
921                    let arg_count = self.state.read_byte();
922                    self.invoke(method_handle, arg_count as usize)?;
923                }
924                OpCode::Invoke16 => {
925                    let method_handle = read_string_16!(self);
926                    let arg_count = self.state.read_byte();
927                    self.invoke(method_handle, arg_count as usize)?;
928                }
929                OpCode::GetSuper => {
930                    let property_handle = read_string!(self);
931                    self.get_super(property_handle)?;
932                }
933                OpCode::GetSuper16 => {
934                    let property_handle = read_string_16!(self);
935                    self.get_super(property_handle)?;
936                }
937                OpCode::SuperInvoke => {
938                    let method_handle = read_string!(self);
939                    self.invoke_super(method_handle)?;
940                }
941                OpCode::SuperInvoke16 => {
942                    let method_handle = read_string_16!(self);
943                    self.invoke_super(method_handle)?;
944                }
945                OpCode::Inherit => {
946                    let superclass = peek_value!(self, 0);
947                    let subclass = peek_value!(self, 1);
948
949                    match (superclass.as_class(), subclass.as_class()) {
950                        (Some(superclass_handle), Some(subclass_handle)) => {
951                            let subclass = self.alloc.get_class_mut(subclass_handle);
952                            subclass.super_clazz = Some(superclass_handle);
953                            let subclass = self.alloc.get_class(subclass_handle);
954                            let superclass = self.alloc.get_class(superclass_handle);
955                            let subclass_value_table = subclass.value_table;
956                            let superclass_value_table = superclass.value_table;
957                            let superclass_method_table = superclass.method_table;
958                            let subclass_method_table = subclass.method_table;
959                            self.alloc
960                                .tables
961                                .copy_into(superclass_method_table, subclass_method_table);
962                            self.alloc
963                                .tables
964                                .copy_into(superclass_value_table, subclass_value_table);
965                            pop_value!(self);
966                            Ok(())
967                        }
968                        (Some(_), _) => Err(QangRuntimeError::new(
969                            "Invalid subclass.".to_string(),
970                            self.state.get_previous_loc(),
971                        )),
972                        (_, Some(_)) => Err(QangRuntimeError::new(
973                            "Super class must be a class.".to_string(),
974                            self.state.get_previous_loc(),
975                        )),
976                        _ => Err(QangRuntimeError::new(
977                            "Invalid class declaration.".to_string(),
978                            self.state.get_previous_loc(),
979                        )),
980                    }?
981                }
982                OpCode::ArrayLiteral => {
983                    let length = self.state.read_byte() as usize;
984                    let array = self.with_gc_check(|alloc| alloc.arrays.create_array(length));
985                    for i in 0..length {
986                        let value = pop_value!(self);
987                        self.alloc.arrays.insert(array, i, value);
988                    }
989                    push_value!(self, Value::array(array))?;
990                }
991                OpCode::GetArrayIndex => {
992                    let index = pop_value!(self);
993                    match (index.as_number(), peek_value!(self, 0).as_array()) {
994                        (Some(index), Some(handle)) => {
995                            let value = self.alloc.arrays.get(handle, index.trunc() as isize);
996                            pop_value!(self);
997                            push_value!(self, value)?;
998                        }
999                        (_, Some(_)) => {
1000                            return Err(QangRuntimeError::new(
1001                                "An array can only be indexed by a number.".to_string(),
1002                                self.state.get_previous_loc(),
1003                            ));
1004                        }
1005                        (Some(_), _) => {
1006                            return Err(QangRuntimeError::new(
1007                                "Only arrays can be indexed.".to_string(),
1008                                self.state.get_previous_loc(),
1009                            ));
1010                        }
1011                        _ => {
1012                            return Err(QangRuntimeError::new(
1013                                "Invalid operation.".to_string(),
1014                                self.state.get_previous_loc(),
1015                            ));
1016                        }
1017                    }
1018                }
1019                OpCode::SetArrayIndex => {
1020                    let value = pop_value!(self);
1021                    let index = pop_value!(self);
1022                    match (index.as_number(), peek_value!(self, 0).as_array()) {
1023                        (Some(index), Some(handle)) => {
1024                            let is_within_bounds =
1025                                self.alloc
1026                                    .arrays
1027                                    .insert(handle, index.trunc() as usize, value);
1028
1029                            if !is_within_bounds {
1030                                return Err(QangRuntimeError::new(
1031                                    "Index out of bounds.".to_string(),
1032                                    self.state.get_previous_loc(),
1033                                ));
1034                            }
1035                            pop_value!(self);
1036                            push_value!(self, value)?;
1037                        }
1038                        (_, Some(_)) => {
1039                            return Err(QangRuntimeError::new(
1040                                "An array can only be indexed by a number.".to_string(),
1041                                self.state.get_previous_loc(),
1042                            ));
1043                        }
1044                        (Some(_), _) => {
1045                            return Err(QangRuntimeError::new(
1046                                "Only arrays can be indexed.".to_string(),
1047                                self.state.get_previous_loc(),
1048                            ));
1049                        }
1050                        _ => {
1051                            return Err(QangRuntimeError::new(
1052                                "Invalid operation.".to_string(),
1053                                self.state.get_previous_loc(),
1054                            ));
1055                        }
1056                    }
1057                }
1058                OpCode::ObjectLiteral => {
1059                    let handle = self.alloc.tables.new_hashmap();
1060                    let length = self.state.read_byte() as usize;
1061                    for _ in 0..length {
1062                        let value = pop_value!(self);
1063                        let key = pop_value!(self);
1064                        self.alloc.tables.insert(handle, key, value);
1065                    }
1066                    push_value!(self, Value::object_literal(handle))?;
1067                }
1068                OpCode::Module => {
1069                    let module_path = read_string!(self);
1070                    self.load_module(module_path)?;
1071                }
1072                OpCode::Module16 => {
1073                    let module_path = read_string_16!(self);
1074                    self.load_module(module_path)?;
1075                }
1076                OpCode::Return => {
1077                    let result = pop_value!(self);
1078                    let value_slot = self.state.frames[self.state.frame_count - 1].value_slot;
1079
1080                    self.close_upvalue(value_slot);
1081                    self.state.frame_count -= 1;
1082
1083                    #[cfg(feature = "profiler")]
1084                    coz::progress!("function_returns");
1085
1086                    if self.state.frame_count > 0 {
1087                        let prev_closure = self
1088                            .alloc
1089                            .closures
1090                            .get_closure(self.state.frames[self.state.frame_count - 1].closure);
1091                        self.state.function_module_context = prev_closure.module_context;
1092                    } else {
1093                        self.state.function_module_context = None;
1094                    }
1095
1096                    if self.state.frame_count == 0 {
1097                        return Ok(result);
1098                    }
1099
1100                    let previous_frame = &self.state.frames[self.state.frame_count - 1];
1101                    let previous_closure = self.alloc.closures.get_closure(previous_frame.closure);
1102                    let previous_function = self.alloc.get_function(previous_closure.function);
1103                    self.state.current_function_ptr = previous_function as *const FunctionObject;
1104
1105                    self.state.stack_top = value_slot + 1;
1106                    self.state.stack[value_slot] = result;
1107                }
1108                OpCode::ModuleReturn => {
1109                    let result = pop_value!(self);
1110                    let value_slot = self.state.frames[self.state.frame_count - 1].value_slot;
1111
1112                    let module_instance =
1113                        self.state.frames[self.state.frame_count - 1].module_export_target;
1114
1115                    self.close_upvalue(value_slot);
1116                    self.state.frame_count -= 1;
1117
1118                    #[cfg(feature = "profiler")]
1119                    coz::progress!("function_returns");
1120
1121                    if let Some(module_instance) = module_instance {
1122                        self.state.stack[self.state.stack_top - 1] = Value::module(module_instance);
1123                    } else if self.state.frame_count == 0 {
1124                        return Ok(result);
1125                    }
1126
1127                    if self.state.frame_count == 0 {
1128                        return Ok(result);
1129                    }
1130
1131                    let previous_frame = &self.state.frames[self.state.frame_count - 1];
1132                    let previous_closure = self.alloc.closures.get_closure(previous_frame.closure);
1133                    let previous_function = self.alloc.get_function(previous_closure.function);
1134                    self.state.current_function_ptr = previous_function as *const FunctionObject;
1135                }
1136            };
1137        }
1138    }
1139
1140    fn load_module(&mut self, module_path: StringHandle) -> RuntimeResult<()> {
1141        if let Some(instance_handle) = self.state.modules.get_instance_handle(module_path) {
1142            push_value!(self, Value::module(instance_handle))?;
1143            return Ok(());
1144        }
1145
1146        let module_function = self
1147            .state
1148            .modules
1149            .get_module_handle(module_path, self.state.get_previous_loc())?;
1150
1151        let module_instance = self.with_gc_check(|alloc| alloc.tables.new_hashmap());
1152
1153        self.state
1154            .modules
1155            .add_instance(module_path, module_instance);
1156
1157        let module_closure = self.with_gc_check(|alloc| {
1158            alloc
1159                .closures
1160                .allocate_closure(ClosureObject::new(module_function, 0, None))
1161        });
1162
1163        push_value!(self, Value::closure(module_closure))?;
1164        self.call(module_closure, 0)?;
1165
1166        self.state.frames[self.state.frame_count - 1].module_export_target = Some(module_instance);
1167
1168        Ok(())
1169    }
1170
1171    fn create_closure(&mut self, constant: Value) -> RuntimeResult<()> {
1172        let handle = match constant.as_function() {
1173            Some(handle) => handle,
1174            _ => {
1175                return Err(QangRuntimeError::new(
1176                    "Expected function.".to_string(),
1177                    self.state.get_previous_loc(),
1178                ));
1179            }
1180        };
1181        let upvalue_count = self.alloc.get_function(handle).upvalue_count;
1182        let module_context = if self.state.frame_count > 0 {
1183            self.state.frames[self.state.frame_count - 1].module_export_target
1184        } else {
1185            None
1186        };
1187        let closure_handle = self.with_gc_check(|alloc| {
1188            alloc.closures.allocate_closure(ClosureObject::new(
1189                handle,
1190                upvalue_count,
1191                module_context,
1192            ))
1193        });
1194
1195        push_value!(self, Value::closure(closure_handle))?;
1196
1197        for i in 0..self
1198            .alloc
1199            .closures
1200            .get_closure(closure_handle)
1201            .upvalue_count
1202        {
1203            let is_local = self.state.read_byte() != 0;
1204            let index = self.state.read_byte() as usize;
1205
1206            if is_local {
1207                let stack_slot = self.state.frames[self.state.frame_count - 1].value_slot + index;
1208                self.capture_upvalue(stack_slot, closure_handle, i);
1209            } else {
1210                let current_closure_handle = self.state.frames[self.state.frame_count - 1].closure;
1211                if let Some(current_upvalue) = self
1212                    .alloc
1213                    .closures
1214                    .get_upvalue(current_closure_handle, index)
1215                {
1216                    self.alloc
1217                        .closures
1218                        .set_upvalue(closure_handle, i, current_upvalue);
1219                }
1220            }
1221        }
1222
1223        Ok(())
1224    }
1225
1226    fn define_method(&mut self, name: StringHandle) -> RuntimeResult<()> {
1227        if let Some(method) = peek_value!(self, 0).as_closure()
1228            && let Some(clazz_handle) = peek_value!(self, 1).as_class()
1229        {
1230            let clazz = self.alloc.get_class(clazz_handle);
1231            self.alloc.set_class_method(
1232                clazz.method_table,
1233                Value::string(name),
1234                Value::closure(method),
1235            );
1236            pop_value!(self);
1237        }
1238
1239        Ok(())
1240    }
1241
1242    fn init_field(&mut self, field_name: StringHandle, value: Value) -> RuntimeResult<()> {
1243        if let Some(clazz_handle) = peek_value!(self, 0).as_class() {
1244            let clazz = self.alloc.get_class(clazz_handle);
1245            self.alloc
1246                .set_class_method(clazz.value_table, Value::string(field_name), value);
1247        }
1248
1249        Ok(())
1250    }
1251
1252    fn bind_method(&mut self, clazz_handle: ClassHandle, method_name: Value) -> RuntimeResult<()> {
1253        if let Some(method_handle) = method_name.as_string() {
1254            let init_handle = self.alloc.strings.intern("init");
1255            if method_handle == init_handle {
1256                pop_value!(self);
1257                push_value!(self, Value::nil())?;
1258                return Ok(());
1259            }
1260        }
1261
1262        let clazz = self.alloc.get_class(clazz_handle);
1263        if let Some(closure) = self
1264            .alloc
1265            .get_class_method(clazz.method_table, method_name)
1266            .and_then(|v| v.as_closure())
1267        {
1268            let receiver = peek_value!(self, 0);
1269            let bound = BoundMethodObject::new(receiver, closure);
1270            let handle = self.with_gc_check(|alloc| alloc.allocate_bound_method(bound));
1271            pop_value!(self);
1272            push_value!(self, Value::bound_method(handle))?;
1273        } else {
1274            pop_value!(self);
1275            push_value!(self, Value::nil())?;
1276        }
1277        Ok(())
1278    }
1279
1280    fn bind_intrinsic_method(
1281        &mut self,
1282        method_name: StringHandle,
1283        kind: IntrinsicKind,
1284        receiver: Value,
1285    ) -> RuntimeResult<()> {
1286        let intrinsic = *self.state.intrinsics.get(&kind).ok_or_else(|| {
1287            QangRuntimeError::new(
1288                "invalid method call.".to_string(),
1289                self.state.get_previous_loc(),
1290            )
1291        })?;
1292
1293        let final_intrinsic = if receiver.is_nil() {
1294            match intrinsic {
1295                IntrinsicMethod::Call => IntrinsicMethod::NilSafeCall,
1296                IntrinsicMethod::Apply => IntrinsicMethod::NilSafeApply,
1297                other => other,
1298            }
1299        } else {
1300            intrinsic
1301        };
1302
1303        let bound = BoundIntrinsicObject::new(receiver, final_intrinsic, method_name);
1304        let handle = self.with_gc_check(|alloc| alloc.allocate_bound_intrinsic(bound));
1305        pop_value!(self);
1306        push_value!(self, Value::bound_intrinsic(handle))?;
1307        Ok(())
1308    }
1309
1310    fn bind_super_method(
1311        &mut self,
1312        method_table_handle: HashMapHandle,
1313        method_name: StringHandle,
1314    ) -> RuntimeResult<bool> {
1315        if let Some(closure) = self
1316            .alloc
1317            .get_class_method(method_table_handle, Value::string(method_name))
1318            .and_then(|v| v.as_closure())
1319        {
1320            let receiver = peek_value!(self, 0);
1321            let bound = BoundMethodObject::new(receiver, closure);
1322            let handle = self.with_gc_check(|alloc| alloc.allocate_bound_method(bound));
1323            pop_value!(self); // Pop 'this'
1324            push_value!(self, Value::bound_method(handle))?;
1325            Ok(true)
1326        } else {
1327            Ok(false)
1328        }
1329    }
1330
1331    fn close_upvalue(&mut self, last_slot: StackSlot) {
1332        let mut i = self.state.open_upvalues.len();
1333        while i > 0 {
1334            i -= 1;
1335            let (stack_slot, upvalue_ref) = &self.state.open_upvalues[i];
1336
1337            if *stack_slot >= last_slot {
1338                let value = self.state.stack[*stack_slot];
1339
1340                let value_handle = self.alloc.allocate_upvalue(value);
1341
1342                for (closure_handle, upvalue_index) in
1343                    upvalue_ref.iter_all_entries(&self.alloc.upvalue_overflow)
1344                {
1345                    self.alloc.closures.set_upvalue(
1346                        closure_handle,
1347                        upvalue_index,
1348                        UpvalueSlot::Closed(value_handle),
1349                    );
1350                }
1351
1352                self.state.open_upvalues.remove(i);
1353            }
1354        }
1355    }
1356
1357    fn capture_upvalue(
1358        &mut self,
1359        stack_slot: StackSlot,
1360        closure_handle: ClosureHandle,
1361        upvalue_index: UpvalueIndex,
1362    ) {
1363        for (open_slot, upvalue_ref) in self.state.open_upvalues.iter_mut() {
1364            if *open_slot == stack_slot {
1365                upvalue_ref.add_closure(
1366                    closure_handle,
1367                    upvalue_index,
1368                    &mut self.alloc.upvalue_overflow,
1369                );
1370
1371                self.alloc.closures.set_upvalue(
1372                    closure_handle,
1373                    upvalue_index,
1374                    UpvalueSlot::Open(stack_slot),
1375                );
1376                return;
1377            }
1378        }
1379
1380        let mut upvalue_ref = OpenUpvalueTracker::new();
1381        upvalue_ref.add_closure(
1382            closure_handle,
1383            upvalue_index,
1384            &mut self.alloc.upvalue_overflow,
1385        );
1386
1387        self.alloc.closures.set_upvalue(
1388            closure_handle,
1389            upvalue_index,
1390            UpvalueSlot::Open(stack_slot),
1391        );
1392
1393        self.state.open_upvalues.push((stack_slot, upvalue_ref));
1394    }
1395
1396    fn binary_operation<F>(&mut self, op: F) -> RuntimeResult<()>
1397    where
1398        F: FnOnce(Value, Value, &mut HeapAllocator) -> Result<Value, BinaryOperationError>,
1399    {
1400        #[cfg(feature = "profiler")]
1401        coz::scope!("binary_operation");
1402
1403        let b = pop_value!(self);
1404        let a = pop_value!(self);
1405
1406        let value = op(a, b, &mut self.alloc)
1407            .map_err(|e: BinaryOperationError| e.into_qang_error(self.state.get_previous_loc()))?;
1408
1409        push_value!(self, value)?;
1410        Ok(())
1411    }
1412
1413    pub(crate) fn call_value(&mut self, value: Value, arg_count: usize) -> RuntimeResult<()> {
1414        match value.kind() {
1415            ValueKind::Closure(handle) => self.call(handle, arg_count),
1416            ValueKind::NativeFunction(function) => self.call_native_function(function, arg_count),
1417            ValueKind::Class(handle) => {
1418                let clazz = self.alloc.get_class(handle);
1419                let clazz_method_table = clazz.method_table;
1420                let clazz_value_table = clazz.value_table;
1421                let instance_handle = self.with_gc_check(|alloc| alloc.allocate_instance(handle));
1422                self.state.stack[self.state.stack_top - arg_count - 1] =
1423                    Value::instance(instance_handle);
1424                let instance_table = self.alloc.get_instance(instance_handle).table;
1425
1426                self.alloc
1427                    .tables
1428                    .copy_into(clazz_value_table, instance_table);
1429
1430                let constructor_handle = self.alloc.strings.intern("init");
1431                if let Some(constructor) = self
1432                    .alloc
1433                    .get_class_method(clazz_method_table, Value::string(constructor_handle))
1434                    .and_then(|v| v.as_closure())
1435                {
1436                    self.call(constructor, arg_count)?;
1437                } else {
1438                    // No constructor found, pop the arguments from the stack
1439                    for _ in 0..arg_count {
1440                        pop_value!(self);
1441                    }
1442                }
1443                Ok(())
1444            }
1445            ValueKind::BoundMethod(handle) => {
1446                let bound_method = self.alloc.get_bound_method(handle);
1447
1448                self.state.stack[self.state.stack_top - arg_count - 1] = bound_method.receiver;
1449                self.call(bound_method.closure, arg_count)
1450            }
1451            ValueKind::BoundIntrinsic(handle) => {
1452                let bound_intrinsic = self.alloc.get_bound_intrinsic(handle);
1453                self.call_intrinsic_method(
1454                    bound_intrinsic.receiver,
1455                    bound_intrinsic.method,
1456                    arg_count,
1457                )
1458            }
1459            _ => {
1460                let value_str = value.to_display_string(&self.alloc);
1461                Err(QangRuntimeError::new(
1462                    format!("Identifier '{}' not callable.", value_str).to_string(),
1463                    self.state.get_previous_loc(),
1464                ))
1465            }
1466        }
1467    }
1468
1469    fn invoke(&mut self, method_handle: StringHandle, arg_count: usize) -> RuntimeResult<()> {
1470        let receiver = peek_value!(self, arg_count);
1471
1472        match receiver.kind() {
1473            ValueKind::Instance(instance_handle) => {
1474                let clazz = {
1475                    let instance = self.alloc.get_instance(instance_handle);
1476
1477                    if let Some(value) = self
1478                        .alloc
1479                        .get_instance_field(instance.table, Value::string(method_handle))
1480                    {
1481                        self.state.stack[self.state.stack_top - arg_count - 1] = value;
1482                        return self.call_value(value, arg_count);
1483                    }
1484
1485                    instance.clazz
1486                };
1487
1488                let init_handle = self.alloc.strings.intern("init");
1489                if method_handle == init_handle {
1490                    return Err(QangRuntimeError::new(
1491                        "Cannot call constructor 'init' on an instance.".to_string(),
1492                        self.state.get_previous_loc(),
1493                    ));
1494                }
1495
1496                self.invoke_from_class_cached(clazz, method_handle, arg_count)
1497            }
1498
1499            ValueKind::ObjectLiteral(handle) => {
1500                let object_type = CachedObjectType::ObjectLiteral;
1501
1502                if let Some(method_value) =
1503                    self.get_method_cached(object_type, handle, method_handle)
1504                {
1505                    self.state.stack[self.state.stack_top - arg_count - 1] = method_value;
1506                    self.call_value(method_value, arg_count)
1507                } else {
1508                    Err(QangRuntimeError::new(
1509                        format!(
1510                            "Property '{}' does not exist on object.",
1511                            self.alloc.strings.get(method_handle)
1512                        ),
1513                        self.state.get_previous_loc(),
1514                    ))
1515                }
1516            }
1517
1518            ValueKind::Module(handle) => {
1519                let object_type = CachedObjectType::Module;
1520
1521                if let Some(method_value) =
1522                    self.get_method_cached(object_type, handle, method_handle)
1523                {
1524                    self.state.stack[self.state.stack_top - arg_count - 1] = method_value;
1525                    self.call_value(method_value, arg_count)
1526                } else {
1527                    Err(QangRuntimeError::new(
1528                        format!(
1529                            "Property '{}' does not exist on module.",
1530                            self.alloc.strings.get(method_handle)
1531                        ),
1532                        self.state.get_previous_loc(),
1533                    ))
1534                }
1535            }
1536
1537            ValueKind::String(_) => {
1538                let intrinsic = *self
1539                    .state
1540                    .intrinsics
1541                    .get(&IntrinsicKind::String(method_handle))
1542                    .ok_or_else(|| {
1543                        QangRuntimeError::new(
1544                            "invalid method call.".to_string(),
1545                            self.state.get_previous_loc(),
1546                        )
1547                    })?;
1548                self.call_intrinsic_method(receiver, intrinsic, arg_count)
1549            }
1550
1551            ValueKind::Array(_) => {
1552                let intrinsic = *self
1553                    .state
1554                    .intrinsics
1555                    .get(&IntrinsicKind::Array(method_handle))
1556                    .ok_or_else(|| {
1557                        QangRuntimeError::new(
1558                            "invalid method call.".to_string(),
1559                            self.state.get_previous_loc(),
1560                        )
1561                    })?;
1562                self.call_intrinsic_method(receiver, intrinsic, arg_count)
1563            }
1564
1565            ValueKind::Number(_) => {
1566                let intrinsic = *self
1567                    .state
1568                    .intrinsics
1569                    .get(&IntrinsicKind::Number(method_handle))
1570                    .ok_or_else(|| {
1571                        QangRuntimeError::new(
1572                            "invalid method call.".to_string(),
1573                            self.state.get_previous_loc(),
1574                        )
1575                    })?;
1576                self.call_intrinsic_method(receiver, intrinsic, arg_count)
1577            }
1578
1579            ValueKind::Closure(_)
1580            | ValueKind::NativeFunction(_)
1581            | ValueKind::BoundIntrinsic(_)
1582            | ValueKind::BoundMethod(_) => {
1583                let intrinsic = *self
1584                    .state
1585                    .intrinsics
1586                    .get(&IntrinsicKind::Function(method_handle))
1587                    .ok_or_else(|| {
1588                        QangRuntimeError::new(
1589                            "invalid method call.".to_string(),
1590                            self.state.get_previous_loc(),
1591                        )
1592                    })?;
1593                self.call_intrinsic_method(receiver, intrinsic, arg_count)
1594            }
1595
1596            _ => Err(QangRuntimeError::new(
1597                format!(
1598                    "Cannot invoke {}, no methods exist.",
1599                    receiver.to_type_string()
1600                ),
1601                self.state.get_previous_loc(),
1602            )),
1603        }
1604    }
1605
1606    fn call(&mut self, closure_handle: ClosureHandle, arg_count: usize) -> RuntimeResult<()> {
1607        #[cfg(feature = "profiler")]
1608        coz::scope!("call_function");
1609
1610        #[cfg(feature = "profiler")]
1611        coz::progress!("before_call");
1612
1613        let closure = self.alloc.closures.get_closure(closure_handle);
1614        let function = self.alloc.get_function(closure.function);
1615
1616        let final_arg_count = {
1617            if arg_count < function.arity {
1618                let arity = function.arity;
1619                for _ in arg_count..arity {
1620                    push_value!(self, Value::nil())?;
1621                }
1622                arity
1623            } else {
1624                arg_count
1625            }
1626        };
1627
1628        if self.state.frame_count >= FRAME_MAX {
1629            let loc = if self.state.frame_count > 0 {
1630                self.state.get_previous_loc()
1631            } else {
1632                SourceLocation::default()
1633            };
1634            return Err(QangRuntimeError::new(
1635                "Maximum call depth exceeded.".to_string(),
1636                loc,
1637            ));
1638        }
1639
1640        self.state.frame_count += 1;
1641
1642        let value_slot = self.state.stack_top - final_arg_count - 1;
1643        let call_frame = &mut self.state.frames[self.state.frame_count - 1];
1644
1645        call_frame.value_slot = value_slot;
1646        call_frame.closure = closure_handle;
1647        call_frame.ip = 0;
1648        call_frame.module_export_target = None;
1649        self.state.current_function_ptr = function as *const FunctionObject;
1650
1651        if let Some(module_context) = closure.module_context {
1652            self.state.function_module_context = Some(module_context);
1653        }
1654
1655        #[cfg(feature = "profiler")]
1656        coz::progress!("after_call");
1657
1658        Ok(())
1659    }
1660
1661    fn tail_call_value(&mut self, callee: Value, arg_count: usize) -> RuntimeResult<()> {
1662        match callee.kind() {
1663            ValueKind::Closure(closure_handle) => self.tail_call(closure_handle, arg_count),
1664            ValueKind::NativeFunction(handle) => self.call_native_function(handle, arg_count),
1665            ValueKind::Class(_handle) => {
1666                panic!("Cannot tail call optimize class instancing.")
1667            }
1668            ValueKind::BoundMethod(handle) => {
1669                let bound_method = self.alloc.get_bound_method(handle);
1670                self.state.stack[self.state.stack_top - arg_count - 1] = bound_method.receiver;
1671                self.tail_call(bound_method.closure, arg_count)
1672            }
1673            ValueKind::BoundIntrinsic(handle) => {
1674                let bound_intrinsic = self.alloc.get_bound_intrinsic(handle);
1675                self.call_intrinsic_method(
1676                    bound_intrinsic.receiver,
1677                    bound_intrinsic.method,
1678                    arg_count,
1679                )
1680            }
1681            _ => {
1682                let value_str = callee.to_display_string(&self.alloc);
1683                Err(QangRuntimeError::new(
1684                    format!("Identifier '{}' not callable.", value_str).to_string(),
1685                    self.state.get_previous_loc(),
1686                ))
1687            }
1688        }
1689    }
1690
1691    fn tail_call(&mut self, closure_handle: ClosureHandle, arg_count: usize) -> RuntimeResult<()> {
1692        let closure = self.alloc.closures.get_closure(closure_handle);
1693        let function_handle = closure.function;
1694        let function_arity = self.alloc.get_function(function_handle).arity;
1695
1696        // Pad arguments if needed
1697        let final_arg_count = if arg_count < function_arity {
1698            for _ in arg_count..function_arity {
1699                push_value!(self, Value::nil())?;
1700            }
1701            function_arity
1702        } else {
1703            arg_count
1704        };
1705
1706        // Get current frame info
1707        let current_frame = &self.state.frames[self.state.frame_count - 1];
1708        let current_value_slot = current_frame.value_slot;
1709
1710        // Close upvalues that might be affected by the tail call
1711        // This ensures that any upvalues pointing to the current frame's locals
1712        // are properly closed before we reuse the frame
1713        self.close_upvalue(current_value_slot + 1);
1714
1715        // New function and args are at top of stack
1716        // [... current frame locals] [new_func] [new_arg1] [new_arg2] <- stack_top
1717        let new_func_pos = self.state.stack_top - final_arg_count - 1;
1718
1719        // Move new function + args to current frame's position
1720        for i in 0..=final_arg_count {
1721            // Include function itself
1722            self.state.stack[current_value_slot + i] = self.state.stack[new_func_pos + i];
1723        }
1724
1725        // Reset stack_top to just after the new arguments
1726        self.state.stack_top = current_value_slot + final_arg_count + 1;
1727
1728        // Update current frame (don't increment frame_count!)
1729        let current_frame = &mut self.state.frames[self.state.frame_count - 1];
1730        current_frame.closure = closure_handle;
1731        current_frame.ip = 0;
1732
1733        // Get function pointer after all mutations are done
1734        let function = self.alloc.get_function(function_handle);
1735        self.state.current_function_ptr = function as *const FunctionObject;
1736
1737        Ok(())
1738    }
1739
1740    pub fn call_function(&mut self, handle: ClosureHandle, args: &[Value]) -> RuntimeResult<Value> {
1741        let saved_stack_top = self.state.stack_top;
1742        let saved_frame_count = self.state.frame_count;
1743        let saved_function_ptr = self.state.current_function_ptr;
1744
1745        push_value!(self, Value::closure(handle))?;
1746
1747        for value in args {
1748            push_value!(self, *value)?;
1749        }
1750
1751        self.call(handle, args.len())?;
1752
1753        let result = self.run();
1754
1755        self.state.stack_top = saved_stack_top;
1756        self.state.frame_count = saved_frame_count;
1757        self.state.current_function_ptr = saved_function_ptr;
1758
1759        result
1760    }
1761
1762    pub fn get_function_args(&self, arg_count: usize) -> &[Value] {
1763        &self.state.arg_buffer[..arg_count]
1764    }
1765
1766    fn call_native_function(
1767        &mut self,
1768        handle: NativeFunctionHandle,
1769        arg_count: usize,
1770    ) -> RuntimeResult<()> {
1771        let function = self.alloc.get_native_function(handle);
1772
1773        for i in (0..arg_count).rev() {
1774            if i < function.arity {
1775                self.state.arg_buffer[i] = pop_value!(self);
1776            } else {
1777                pop_value!(self); // discard values that are passed in but not needed by the function.
1778            }
1779        }
1780
1781        pop_value!(self); // pop function off the stack now that it has been called.
1782
1783        let value = (function.function)(arg_count, self)
1784            .map_err(|e: NativeFunctionError| {
1785                let loc = self.state.get_previous_loc();
1786                e.into_qang_error(loc)
1787            })?
1788            .unwrap_or_default();
1789
1790        push_value!(self, value)?;
1791        self.state.arg_buffer.fill(Value::default());
1792
1793        Ok(())
1794    }
1795
1796    fn call_intrinsic_method(
1797        &mut self,
1798        receiver: Value,
1799        method: IntrinsicMethod,
1800        arg_count: usize,
1801    ) -> RuntimeResult<()> {
1802        match method {
1803            IntrinsicMethod::Native { function, arity } => {
1804                for i in (0..arg_count).rev() {
1805                    if i < arity {
1806                        self.state.arg_buffer[i] = pop_value!(self);
1807                    } else {
1808                        pop_value!(self); // discard values that are passed in but not needed by the function.
1809                    }
1810                }
1811
1812                pop_value!(self); // pop function off the stack now that it has been called.
1813
1814                // Add receiver to external roots to prevent it from being GC'd during native function execution
1815                self.state.additional_roots.insert(receiver);
1816
1817                let value = function(receiver, arg_count, self)
1818                    .map_err(|e: NativeFunctionError| {
1819                        let loc = self.state.get_previous_loc();
1820                        e.into_qang_error(loc)
1821                    })?
1822                    .unwrap_or_default();
1823
1824                // Remove receiver from external roots after function execution
1825                self.state.additional_roots.remove(&receiver);
1826
1827                push_value!(self, value)?;
1828                self.state.arg_buffer.fill(Value::default());
1829
1830                Ok(())
1831            }
1832            IntrinsicMethod::Apply => self.handle_function_intrinsic_apply(receiver, arg_count),
1833            IntrinsicMethod::Call => self.handle_function_intrinsic_call(receiver, arg_count),
1834            IntrinsicMethod::Iter => self.handle_array_intrinsic_iter(receiver, arg_count),
1835            IntrinsicMethod::ToNumber => {
1836                self.handle_string_intrinsic_to_number(receiver, arg_count)
1837            }
1838            IntrinsicMethod::NilSafeCall | IntrinsicMethod::NilSafeApply => {
1839                // For nil-safe call, consume arguments and return nil
1840                for _ in 0..arg_count {
1841                    pop_value!(self);
1842                }
1843                pop_value!(self); // pop the bound method
1844                push_value!(self, Value::nil())?;
1845                Ok(())
1846            }
1847        }
1848    }
1849
1850    fn invoke_from_class(
1851        &mut self,
1852        clazz_handle: ClassHandle,
1853        method_handle: StringHandle,
1854        arg_count: usize,
1855    ) -> RuntimeResult<()> {
1856        let clazz = self.alloc.get_class(clazz_handle);
1857        if let Some(method) = self
1858            .alloc
1859            .get_class_method(clazz.method_table, Value::string(method_handle))
1860            .and_then(|v| v.as_closure())
1861        {
1862            self.call(method, arg_count)
1863        } else {
1864            // If method is `init` and it does not exist, do nothing (return nil)
1865            let init_handle = self.alloc.strings.intern("init");
1866            if method_handle == init_handle {
1867                // Pop arguments but leave receiver on stack
1868                for _ in 0..arg_count {
1869                    pop_value!(self);
1870                }
1871                // Push nil as return value
1872                push_value!(self, Value::nil())?;
1873                Ok(())
1874            } else {
1875                Err(QangRuntimeError::new(
1876                    format!(
1877                        "{} does not exist on class {}.",
1878                        Value::string(method_handle).to_display_string(&self.alloc),
1879                        Value::class(clazz_handle).to_display_string(&self.alloc),
1880                    ),
1881                    self.state.get_previous_loc(),
1882                ))
1883            }
1884        }
1885    }
1886
1887    fn invoke_from_class_cached(
1888        &mut self,
1889        clazz_handle: ClassHandle,
1890        method_handle: StringHandle,
1891        arg_count: usize,
1892    ) -> RuntimeResult<()> {
1893        let clazz = self.alloc.get_class(clazz_handle);
1894        let object_type = CachedObjectType::Instance(clazz_handle);
1895
1896        if let Some(method_value) =
1897            self.get_method_cached(object_type, clazz.method_table, method_handle)
1898        {
1899            if let Some(method) = method_value.as_closure() {
1900                self.call(method, arg_count)
1901            } else {
1902                Err(QangRuntimeError::new(
1903                    format!(
1904                        "{} is not a method on class {}.",
1905                        Value::string(method_handle).to_display_string(&self.alloc),
1906                        Value::class(clazz_handle).to_display_string(&self.alloc),
1907                    ),
1908                    self.state.get_previous_loc(),
1909                ))
1910            }
1911        } else {
1912            let init_handle = self.alloc.strings.intern("init");
1913            if method_handle == init_handle {
1914                for _ in 0..arg_count {
1915                    pop_value!(self);
1916                }
1917                // Push nil as return value
1918                push_value!(self, Value::nil())?;
1919                Ok(())
1920            } else {
1921                Err(QangRuntimeError::new(
1922                    format!(
1923                        "{} does not exist on class {}.",
1924                        Value::string(method_handle).to_display_string(&self.alloc),
1925                        Value::class(clazz_handle).to_display_string(&self.alloc),
1926                    ),
1927                    self.state.get_previous_loc(),
1928                ))
1929            }
1930        }
1931    }
1932
1933    fn get_property_cached(
1934        &mut self,
1935        object_type: CachedObjectType,
1936        table_handle: HashMapHandle,
1937        property_name: StringHandle,
1938    ) -> Option<Value> {
1939        let cache_index = self.state.get_property_cache_index();
1940
1941        if let Some(cached) = self.state.property_cache.get(cache_index)
1942            && cached.object_type == object_type
1943            && cached.property_name == property_name
1944            && cached.table_handle == table_handle
1945            && cached.generation == self.state.cache_generation
1946        {
1947            let key = Value::string(property_name);
1948            return self.alloc.tables.get(cached.table_handle, &key);
1949        }
1950
1951        let key = Value::string(property_name);
1952        let value = self.alloc.tables.get(table_handle, &key);
1953
1954        if let Some(cache_entry) = self.state.property_cache.get_mut(cache_index) {
1955            *cache_entry = PropertyCache {
1956                object_type,
1957                property_name,
1958                table_handle,
1959                generation: self.state.cache_generation,
1960            };
1961        }
1962
1963        value
1964    }
1965
1966    fn get_method_cached(
1967        &mut self,
1968        object_type: CachedObjectType,
1969        table_handle: HashMapHandle,
1970        method_name: StringHandle,
1971    ) -> Option<Value> {
1972        let cache_index = self.state.get_method_cache_index();
1973
1974        if let Some(cached) = self.state.method_cache.get(cache_index)
1975            && cached.object_type == object_type
1976            && cached.method_name == method_name
1977            && cached.table_handle == table_handle
1978            && cached.generation == self.state.cache_generation
1979        {
1980            return Some(cached.cached_method);
1981        }
1982
1983        let key = Value::string(method_name);
1984        if let Some(method_value) = self.alloc.tables.get(table_handle, &key) {
1985            if let Some(cache_entry) = self.state.method_cache.get_mut(cache_index) {
1986                *cache_entry = MethodCache {
1987                    object_type,
1988                    method_name,
1989                    table_handle,
1990                    cached_method: method_value,
1991                    generation: self.state.cache_generation,
1992                };
1993            }
1994            Some(method_value)
1995        } else {
1996            None
1997        }
1998    }
1999
2000    fn get_property_value(
2001        &mut self,
2002        object: Value,
2003        optional: bool,
2004        identifier: StringHandle,
2005    ) -> RuntimeResult<()> {
2006        match object.kind() {
2007            ValueKind::Instance(instance_handle) => {
2008                let instance = self.alloc.get_instance(instance_handle);
2009                let clazz = instance.clazz;
2010                let object_type = CachedObjectType::Instance(clazz);
2011                let instance_table = instance.table;
2012
2013                if let Some(value) =
2014                    self.get_property_cached(object_type, instance_table, identifier)
2015                {
2016                    pop_value!(self);
2017                    push_value!(self, value)?;
2018                } else {
2019                    let key = Value::string(identifier);
2020                    self.bind_method(clazz, key)?;
2021                }
2022            }
2023
2024            ValueKind::ObjectLiteral(handle) => {
2025                let object_type = CachedObjectType::ObjectLiteral;
2026
2027                let value = self
2028                    .get_property_cached(object_type, handle, identifier)
2029                    .unwrap_or_default();
2030                pop_value!(self);
2031                push_value!(self, value)?;
2032            }
2033
2034            ValueKind::Module(handle) => {
2035                let object_type = CachedObjectType::Module;
2036
2037                let value = self.get_property_cached(object_type, handle, identifier);
2038
2039                pop_value!(self);
2040                match value {
2041                    Some(val) => push_value!(self, val)?,
2042                    None => {
2043                        if optional {
2044                            push_value!(self, Value::nil())?;
2045                        } else {
2046                            return Err(QangRuntimeError::new(
2047                                format!(
2048                                    "Property '{}' does not exist on module.",
2049                                    self.alloc.strings.get(identifier)
2050                                ),
2051                                self.state.get_previous_loc(),
2052                            ));
2053                        }
2054                    }
2055                }
2056            }
2057
2058            ValueKind::Nil => {
2059                let call_handle = self.alloc.strings.intern("call");
2060                let apply_handle = self.alloc.strings.intern("apply");
2061
2062                if identifier == call_handle || identifier == apply_handle {
2063                    let method = if identifier == call_handle {
2064                        IntrinsicMethod::NilSafeCall
2065                    } else {
2066                        IntrinsicMethod::NilSafeApply
2067                    };
2068                    let bound = BoundIntrinsicObject::new(object, method, identifier);
2069                    let handle = self.with_gc_check(|alloc| alloc.allocate_bound_intrinsic(bound));
2070                    pop_value!(self);
2071                    push_value!(self, Value::bound_intrinsic(handle))?;
2072                } else if optional {
2073                    pop_value!(self);
2074                    push_value!(self, Value::nil())?;
2075                } else {
2076                    return Err(QangRuntimeError::new(
2077                        format!("Cannot access property on {}.", object.to_type_string()),
2078                        self.state.get_previous_loc(),
2079                    ));
2080                }
2081            }
2082
2083            ValueKind::String(_) => {
2084                self.bind_intrinsic_method(identifier, IntrinsicKind::String(identifier), object)?;
2085            }
2086
2087            ValueKind::Array(_) => {
2088                self.bind_intrinsic_method(identifier, IntrinsicKind::Array(identifier), object)?;
2089            }
2090
2091            ValueKind::Number(_) => {
2092                self.bind_intrinsic_method(identifier, IntrinsicKind::Number(identifier), object)?;
2093            }
2094
2095            ValueKind::Closure(_) | ValueKind::BoundMethod(_) => {
2096                self.bind_intrinsic_method(
2097                    identifier,
2098                    IntrinsicKind::Function(identifier),
2099                    object,
2100                )?;
2101            }
2102
2103            _ => {
2104                if optional {
2105                    pop_value!(self);
2106                    push_value!(self, Value::nil())?;
2107                } else {
2108                    return Err(QangRuntimeError::new(
2109                        format!("Cannot access property on {}", object.to_type_string()),
2110                        self.state.get_previous_loc(),
2111                    ));
2112                }
2113            }
2114        }
2115        Ok(())
2116    }
2117
2118    fn set_property(&mut self, identifier: StringHandle) -> RuntimeResult<()> {
2119        let instance = peek_value!(self, 1);
2120        match instance.kind() {
2121            ValueKind::Instance(instance_handle) => {
2122                let instance_obj = self.alloc.get_instance(instance_handle);
2123                let table_handle = instance_obj.table;
2124                let constant = Value::string(identifier);
2125                let value = peek_value!(self, 0);
2126
2127                self.with_gc_check(|alloc| alloc.set_instance_field(table_handle, constant, value));
2128
2129                let value = pop_value!(self);
2130                pop_value!(self);
2131                push_value!(self, value)?;
2132            }
2133
2134            ValueKind::ObjectLiteral(obj_handle) => {
2135                let constant = Value::string(identifier);
2136                let value = peek_value!(self, 0);
2137
2138                self.with_gc_check(|alloc| alloc.tables.insert(obj_handle, constant, value));
2139
2140                let value = pop_value!(self);
2141                pop_value!(self);
2142                push_value!(self, value)?;
2143            }
2144
2145            _ => {
2146                return Err(QangRuntimeError::new(
2147                    format!("Cannot set property on {}.", instance.to_type_string()),
2148                    self.state.get_previous_loc(),
2149                ));
2150            }
2151        }
2152        Ok(())
2153    }
2154
2155    fn get_global(&self, identifier_handle: StringHandle) -> RuntimeResult<Value> {
2156        let key = Value::string(identifier_handle);
2157
2158        if let Some(function_context) = self.state.function_module_context
2159            && let Some(value) = self.try_get_from_table(function_context, &key)
2160        {
2161            return Ok(value);
2162        }
2163
2164        if self.state.frame_count > 0
2165            && let Some(module_target) =
2166                self.state.frames[self.state.frame_count - 1].module_export_target
2167            && let Some(value) = self.try_get_from_table(module_target, &key)
2168        {
2169            return Ok(value);
2170        }
2171
2172        if self.has_module_context() {
2173            Ok(self.get_from_globals_or_nil(identifier_handle))
2174        } else {
2175            self.try_get_from_globals_strict(identifier_handle)
2176        }
2177    }
2178
2179    fn try_get_from_table(&self, table_handle: HashMapHandle, key: &Value) -> Option<Value> {
2180        self.alloc.tables.get(table_handle, key)
2181    }
2182
2183    fn has_module_context(&self) -> bool {
2184        let has_frame_module_context = if self.state.frame_count > 0 {
2185            self.state.frames[self.state.frame_count - 1]
2186                .module_export_target
2187                .is_some()
2188        } else {
2189            false
2190        };
2191        self.state.function_module_context.is_some() || has_frame_module_context
2192    }
2193
2194    fn get_from_globals_or_nil(&self, identifier_handle: StringHandle) -> Value {
2195        self.state
2196            .globals
2197            .get(&identifier_handle)
2198            .copied()
2199            .unwrap_or(Value::nil())
2200    }
2201
2202    fn try_get_from_globals_strict(&self, identifier_handle: StringHandle) -> RuntimeResult<Value> {
2203        self.state
2204            .globals
2205            .get(&identifier_handle)
2206            .copied()
2207            .ok_or_else(|| {
2208                let loc = self.state.get_previous_loc();
2209                let identifier_name = self.alloc.strings.get(identifier_handle);
2210                QangRuntimeError::new(format!("Undefined variable: {}.", identifier_name), loc)
2211            })
2212    }
2213
2214    fn set_global(&mut self, identifier_handle: StringHandle) -> RuntimeResult<()> {
2215        let value = peek_value!(self, 0);
2216        let key = Value::string(identifier_handle);
2217
2218        if let Some(function_context) = self.state.function_module_context
2219            && self.try_set_in_table(function_context, &key, value)
2220        {
2221            return Ok(());
2222        }
2223
2224        if self.state.frame_count > 0
2225            && let Some(module_target) =
2226                self.state.frames[self.state.frame_count - 1].module_export_target
2227            && self.try_set_in_table(module_target, &key, value)
2228        {
2229            return Ok(());
2230        }
2231
2232        if self.try_set_in_globals(identifier_handle, value) {
2233            return Ok(());
2234        }
2235
2236        self.undefined_variable_error(identifier_handle)
2237    }
2238
2239    fn try_set_in_table(&mut self, table_handle: HashMapHandle, key: &Value, value: Value) -> bool {
2240        if self.alloc.tables.get(table_handle, key).is_some() {
2241            self.alloc.tables.insert(table_handle, *key, value);
2242            true
2243        } else {
2244            false
2245        }
2246    }
2247
2248    fn try_set_in_globals(&mut self, identifier_handle: StringHandle, value: Value) -> bool {
2249        if let std::collections::hash_map::Entry::Occupied(mut e) =
2250            self.state.globals.entry(identifier_handle)
2251        {
2252            e.insert(value);
2253            true
2254        } else {
2255            false
2256        }
2257    }
2258
2259    fn undefined_variable_error(&self, identifier_handle: StringHandle) -> RuntimeResult<()> {
2260        let identifier_name = self.alloc.strings.get(identifier_handle);
2261        let loc = self.state.get_previous_loc();
2262        Err(QangRuntimeError::new(
2263            format!("Undefined variable: {}.", identifier_name),
2264            loc,
2265        ))
2266    }
2267
2268    fn invoke_super(&mut self, method_handle: StringHandle) -> RuntimeResult<()> {
2269        let arg_count = self.state.read_byte() as usize;
2270        let superclass = pop_value!(self);
2271
2272        if let Some(superclass_handle) = superclass.as_class() {
2273            self.invoke_from_class(superclass_handle, method_handle, arg_count)
2274        } else {
2275            Err(QangRuntimeError::new(
2276                "Super class must be a class.".to_string(),
2277                self.state.get_previous_loc(),
2278            ))
2279        }
2280    }
2281
2282    fn get_super(&mut self, property_handle: StringHandle) -> RuntimeResult<()> {
2283        let superclass = pop_value!(self);
2284
2285        if let Some(superclass_handle) = superclass.as_class() {
2286            let superclass_obj = self.alloc.get_class(superclass_handle);
2287
2288            if let Some(field_value) = self
2289                .alloc
2290                .get_class_method(superclass_obj.value_table, Value::string(property_handle))
2291            {
2292                self.state.stack[self.state.stack_top - 1] = field_value; // replace 'this' with the value of the field.
2293            } else if !self.bind_super_method(superclass_obj.method_table, property_handle)? {
2294                pop_value!(self); // Pop 'this'
2295                push_value!(self, Value::nil())?;
2296            }
2297
2298            Ok(())
2299        } else {
2300            Err(QangRuntimeError::new(
2301                "Super class must be a class.".to_string(),
2302                self.state.get_previous_loc(),
2303            ))
2304        }
2305    }
2306
2307    pub fn gather_roots(&mut self) -> VecDeque<Value> {
2308        let capacity = self.state.stack_top
2309            + self.globals().len()
2310            + self.state.frame_count
2311            + self.state.open_upvalues.len()
2312            + self.state.modules.count()
2313            + self.state.arg_buffer.len()
2314            + self.state.additional_roots.len();
2315        let mut roots = VecDeque::with_capacity(capacity);
2316        roots.extend(&self.state.stack[..self.state.stack_top]);
2317        roots.extend(self.globals().values());
2318
2319        for frame in &self.state.frames[..self.state.frame_count] {
2320            roots.push_back(Value::closure(frame.closure));
2321        }
2322
2323        for (_, upvalue_ref) in &self.state.open_upvalues {
2324            for (closure_handle, _) in upvalue_ref.iter() {
2325                roots.push_back(Value::closure(closure_handle));
2326            }
2327        }
2328        roots.extend(&self.state.arg_buffer);
2329
2330        self.state.modules.gather_roots(&mut roots);
2331
2332        roots.extend(self.state.additional_roots.iter());
2333
2334        roots
2335    }
2336
2337    pub fn collect_garbage(&mut self) {
2338        debug_log!(self.is_debug, "--gc begin");
2339
2340        self.state.invalidate_caches();
2341
2342        for (_, upvalue_ref) in &self.state.open_upvalues {
2343            upvalue_ref.mark_overflow_chunks(&mut self.alloc.upvalue_overflow);
2344        }
2345
2346        let roots = self.gather_roots();
2347        self.alloc.collect_garbage(roots);
2348        debug_log!(self.is_debug, "--gc end");
2349    }
2350
2351    pub fn globals(&self) -> &FxHashMap<StringHandle, Value> {
2352        &self.state.globals
2353    }
2354
2355    #[cfg(debug_assertions)]
2356    fn debug_print(&self) {
2357        print!("          ");
2358        for i in 0..self.state.stack_top {
2359            if let Some(value) = self.state.stack.get(i) {
2360                value.print(&self.alloc);
2361                print!(" ");
2362            }
2363        }
2364        println!();
2365
2366        disassemble_instruction(
2367            &self.state.get_current_function().chunk,
2368            &self.alloc,
2369            self.state.frames[self.state.frame_count - 1].ip,
2370        );
2371    }
2372}