feat: add experimental tailcall vm backend

This commit is contained in:
2026-04-19 22:13:54 +08:00
parent 800249cb1e
commit 98b07f00e4
16 changed files with 501 additions and 111 deletions
+19 -13
View File
@@ -2,8 +2,7 @@ use std::cmp::Ordering;
use gc_arena::{Gc, Mutation};
use crate::{BytecodeReader, NixNum, StepResult, StrictValue, VmError, Value};
use crate::VmContextExt;
use crate::{BytecodeReader, NixNum, StepResult, StrictValue, Value, VmContextExt, VmError};
impl<'gc> crate::Vm<'gc> {
#[inline(always)]
@@ -21,7 +20,10 @@ impl<'gc> crate::Vm<'gc> {
}
let rhs = self.pop_stack_forced();
let lhs = self.pop_stack_forced();
if let (Some(ls), Some(rs)) = (VmContextExt::get_string(ctx, lhs), VmContextExt::get_string(ctx, rhs)) {
if let (Some(ls), Some(rs)) = (
VmContextExt::get_string(ctx, lhs),
VmContextExt::get_string(ctx, rhs),
) {
let ns = Gc::new(mc, crate::NixString::new(format!("{ls}{rs}")));
self.push_stack(Value::new_gc(ns));
return StepResult::Continue;
@@ -300,7 +302,10 @@ impl<'gc> crate::Vm<'gc> {
if lhs.is::<crate::Null>() && rhs.is::<crate::Null>() {
return Ok(true);
}
if let (Some(a), Some(b)) = (VmContextExt::get_string(ctx, lhs), VmContextExt::get_string(ctx, rhs)) {
if let (Some(a), Some(b)) = (
VmContextExt::get_string(ctx, lhs),
VmContextExt::get_string(ctx, rhs),
) {
return Ok(a == b);
}
if let (Some(a), Some(b)) = (lhs.as_gc::<crate::List>(), rhs.as_gc::<crate::List>()) {
@@ -358,20 +363,21 @@ impl<'gc> crate::Vm<'gc> {
if let (Some(a), Some(b)) = (get_num(lhs), get_num(rhs)) {
let ord = match (a, b) {
(NixNum::Int(a), NixNum::Int(b)) => a.cmp(&b),
(NixNum::Float(a), NixNum::Float(b)) => {
a.partial_cmp(&b).unwrap_or(Ordering::Less)
(NixNum::Float(a), NixNum::Float(b)) => a.partial_cmp(&b).unwrap_or(Ordering::Less),
(NixNum::Int(a), NixNum::Float(b)) => {
(a as f64).partial_cmp(&b).unwrap_or(Ordering::Less)
}
(NixNum::Float(a), NixNum::Int(b)) => {
a.partial_cmp(&(b as f64)).unwrap_or(Ordering::Less)
}
(NixNum::Int(a), NixNum::Float(b)) => (a as f64)
.partial_cmp(&b)
.unwrap_or(Ordering::Less),
(NixNum::Float(a), NixNum::Int(b)) => a
.partial_cmp(&(b as f64))
.unwrap_or(Ordering::Less),
};
self.push_stack(Value::new_inline(pred(ord)));
return Ok(());
}
if let (Some(a), Some(b)) = (VmContextExt::get_string(ctx, lhs), VmContextExt::get_string(ctx, rhs)) {
if let (Some(a), Some(b)) = (
VmContextExt::get_string(ctx, lhs),
VmContextExt::get_string(ctx, rhs),
) {
self.push_stack(Value::new_inline(pred(a.cmp(b))));
return Ok(());
}