use crate::{
args::ArgValues,
bytecode::VM,
exception_private::RunResult,
heap::{HeapData, HeapId},
intern::StaticStrings,
modules::ModuleFunctions,
resource::{ResourceError, ResourceTracker},
types::Module,
value::Value,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::Display, serde::Serialize, serde::Deserialize)]
#[strum(serialize_all = "lowercase")]
pub(crate) enum GcFunctions {
Collect,
Disable,
Enable,
}
pub fn create_module(vm: &mut VM<'_, impl ResourceTracker>) -> Result<HeapId, ResourceError> {
let mut module = Module::new(StaticStrings::Gc);
for (name, function) in [
(StaticStrings::Collect, GcFunctions::Collect),
(StaticStrings::Disable, GcFunctions::Disable),
(StaticStrings::Enable, GcFunctions::Enable),
] {
module.set_attr(name, Value::ModuleFunction(ModuleFunctions::Gc(function)), vm);
}
vm.heap.allocate(HeapData::Module(module))
}
pub(super) fn call(vm: &mut VM<'_, impl ResourceTracker>, function: GcFunctions, args: ArgValues) -> RunResult<Value> {
match function {
GcFunctions::Collect => collect(vm, args),
GcFunctions::Disable => disable(vm, args),
GcFunctions::Enable => enable(vm, args),
}
}
fn collect(vm: &mut VM<'_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
args.check_zero_args("gc.collect", vm.heap)?;
let freed = vm.__force_gc_for_tests();
Ok(Value::Int(i64::try_from(freed).unwrap_or(i64::MAX)))
}
fn disable(vm: &mut VM<'_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
args.check_zero_args("gc.disable", vm.heap)?;
vm.heap.disable_gc();
Ok(Value::None)
}
fn enable(vm: &mut VM<'_, impl ResourceTracker>, args: ArgValues) -> RunResult<Value> {
args.check_zero_args("gc.enable", vm.heap)?;
vm.heap.enable_gc();
Ok(Value::None)
}