Compare commits

...
1 Commits
28 changed files with 475 additions and 362 deletions
Generated
+49 -4
View File
@@ -513,6 +513,16 @@ dependencies = [
"string-interner", "string-interner",
] ]
[[package]]
name = "fix-macros"
version = "0.1.0"
dependencies = [
"manyhow",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "fix-runtime" name = "fix-runtime"
version = "0.1.0" version = "0.1.0"
@@ -520,6 +530,7 @@ dependencies = [
"fix-bytecode", "fix-bytecode",
"fix-error", "fix-error",
"fix-lang", "fix-lang",
"fix-macros",
"gc-arena", "gc-arena",
"hashbrown 0.16.1", "hashbrown 0.16.1",
"smallvec", "smallvec",
@@ -747,6 +758,29 @@ version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "manyhow"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587"
dependencies = [
"manyhow-macros",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "manyhow-macros"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495"
dependencies = [
"proc-macro-utils",
"proc-macro2",
"quote",
]
[[package]] [[package]]
name = "matchers" name = "matchers"
version = "0.2.0" version = "0.2.0"
@@ -995,6 +1029,17 @@ dependencies = [
"toml_edit", "toml_edit",
] ]
[[package]]
name = "proc-macro-utils"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071"
dependencies = [
"proc-macro2",
"quote",
"smallvec",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.106" version = "1.0.106"
@@ -1006,9 +1051,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.45" version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -1275,9 +1320,9 @@ checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.117" version = "2.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
+1
View File
@@ -6,6 +6,7 @@ members = [
"fix-compiler", "fix-compiler",
"fix-error", "fix-error",
"fix-lang", "fix-lang",
"fix-macros",
"fix-runtime", "fix-runtime",
"fix-vm", "fix-vm",
] ]
+1 -1
View File
@@ -2,7 +2,7 @@ use std::fmt::Write;
use colored::Colorize as _; use colored::Colorize as _;
use crate::{InstructionPtr, Op, OperandType, Continuation}; use crate::{Continuation, InstructionPtr, Op, OperandType};
pub trait DisassemblerContext { pub trait DisassemblerContext {
fn resolve_string(&self, id: u32) -> &str; fn resolve_string(&self, id: u32) -> &str;
+5 -5
View File
@@ -1,5 +1,5 @@
use bumpalo::Bump; use bumpalo::Bump;
use fix_bytecode::{Const, InstructionPtr, Op, Continuation}; use fix_bytecode::{Const, Continuation, InstructionPtr, Op};
use fix_error::{Error, Result, Source}; use fix_error::{Error, Result, Source};
use fix_lang::{StringId, Symbol}; use fix_lang::{StringId, Symbol};
use fix_runtime::{StaticValue, VmCode, VmRuntimeCtx}; use fix_runtime::{StaticValue, VmCode, VmRuntimeCtx};
@@ -148,11 +148,11 @@ impl<'a, R: VmRuntimeCtx> BytecodeContext for CompilerCtx<'a, R> {
fn add_constant(&mut self, val: Const) -> u32 { fn add_constant(&mut self, val: Const) -> u32 {
use Const::*; use Const::*;
let val = match val { let val = match val {
Smi(x) => StaticValue::new_inline(x), Smi(x) => StaticValue::new(x),
Float(x) => StaticValue::new_float(x), Float(x) => StaticValue::new_float(x),
Bool(x) => StaticValue::new_inline(x), Bool(x) => StaticValue::new(x),
String(x) => StaticValue::new_inline(x), String(x) => StaticValue::new(x),
Path(x) => StaticValue::new_inline(fix_runtime::Path(x)), Path(x) => StaticValue::new(fix_runtime::Path(x)),
PrimOp { PrimOp {
id, id,
arity, arity,
+1 -1
View File
@@ -1,4 +1,4 @@
use fix_bytecode::{Const, InstructionPtr, Op, OperandType, Continuation}; use fix_bytecode::{Const, Continuation, InstructionPtr, Op, OperandType};
use fix_lang::{BUILTINS, StringId}; use fix_lang::{BUILTINS, StringId};
use hashbrown::HashMap; use hashbrown::HashMap;
use rnix::TextRange; use rnix::TextRange;
+13
View File
@@ -0,0 +1,13 @@
[package]
name = "fix-macros"
version = "0.1.0"
edition = "2024"
[lib]
proc-macro = true
[dependencies]
manyhow = "0.11"
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "2.0", features = ["full", "visit"] }
+36
View File
@@ -0,0 +1,36 @@
extern crate proc_macro;
#[proc_macro]
pub fn unelide_lifetimes(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
use quote::ToTokens;
use syn::parse::{Parse, ParseStream};
use syn::visit_mut::VisitMut;
struct Input {
lt: syn::Lifetime,
ty: syn::Type,
}
impl Parse for Input {
fn parse(input: ParseStream) -> syn::Result<Self> {
let lt: syn::Lifetime = input.parse()?;
let _: syn::Token!(;) = input.parse()?;
let ty: syn::Type = input.parse()?;
Ok(Self { lt, ty })
}
}
struct UnelideLifetimes(syn::Lifetime);
impl VisitMut for UnelideLifetimes {
fn visit_lifetime_mut(&mut self, i: &mut syn::Lifetime) {
if i.ident == "_" {
*i = self.0.clone();
}
}
}
let mut input = syn::parse_macro_input!(input as Input);
UnelideLifetimes(input.lt).visit_type_mut(&mut input.ty);
input.ty.to_token_stream().into()
}
+1
View File
@@ -13,3 +13,4 @@ string-interner = { workspace = true }
fix-bytecode = { path = "../fix-bytecode" } fix-bytecode = { path = "../fix-bytecode" }
fix-error = { path = "../fix-error" } fix-error = { path = "../fix-error" }
fix-lang = { path = "../fix-lang" } fix-lang = { path = "../fix-lang" }
fix-macros = { path = "../fix-macros" }
+6 -6
View File
@@ -63,7 +63,7 @@ macro_rules! impl_forced_inline {
) -> Step { ) -> Step {
m.force_slot_to_pc(base_depth, reader, mc, resume_pc)?; m.force_slot_to_pc(base_depth, reader, mc, resume_pc)?;
let v = m.peek_forced(base_depth); let v = m.peek_forced(base_depth);
if v.as_inline::<$ty>().is_none() { if v.downcast::<$ty>().is_none() {
let _: Step = m.finish_type_err($nix_ty, v.ty()); let _: Step = m.finish_type_err($nix_ty, v.ty());
return Step::Break(Break::Done); return Step::Break(Break::Done);
} }
@@ -73,7 +73,7 @@ macro_rules! impl_forced_inline {
#[inline(always)] #[inline(always)]
fn pop_converted<M: Machine<'gc>>(m: &mut M) -> Self { fn pop_converted<M: Machine<'gc>>(m: &mut M) -> Self {
m.pop_forced() m.pop_forced()
.as_inline::<$ty>() .downcast::<$ty>()
.expect("type checked in force_and_check") .expect("type checked in force_and_check")
} }
} }
@@ -97,7 +97,7 @@ macro_rules! impl_forced_gc {
) -> Step { ) -> Step {
m.force_slot_to_pc(base_depth, reader, mc, resume_pc)?; m.force_slot_to_pc(base_depth, reader, mc, resume_pc)?;
let v = m.peek_forced(base_depth); let v = m.peek_forced(base_depth);
if v.as_gc::<$ty>().is_none() { if v.downcast::<$ty>().is_none() {
let _: Step = m.finish_type_err($nix_ty, v.ty()); let _: Step = m.finish_type_err($nix_ty, v.ty());
return Step::Break(Break::Done); return Step::Break(Break::Done);
} }
@@ -107,7 +107,7 @@ macro_rules! impl_forced_gc {
#[inline(always)] #[inline(always)]
fn pop_converted<M: Machine<'gc>>(m: &mut M) -> Self { fn pop_converted<M: Machine<'gc>>(m: &mut M) -> Self {
m.pop_forced() m.pop_forced()
.as_gc::<$ty>() .downcast::<$ty>()
.expect("type checked in force_and_check") .expect("type checked in force_and_check")
} }
} }
@@ -173,7 +173,7 @@ impl<'gc> Forced<'gc> for f64 {
) -> Step { ) -> Step {
m.force_slot_to_pc(base_depth, reader, mc, resume_pc)?; m.force_slot_to_pc(base_depth, reader, mc, resume_pc)?;
let v = m.peek_forced(base_depth); let v = m.peek_forced(base_depth);
if v.as_float().is_none() { if v.downcast_float().is_none() {
let _: Step = m.finish_type_err(NixType::Float, v.ty()); let _: Step = m.finish_type_err(NixType::Float, v.ty());
return Step::Break(Break::Done); return Step::Break(Break::Done);
} }
@@ -183,7 +183,7 @@ impl<'gc> Forced<'gc> for f64 {
#[inline(always)] #[inline(always)]
fn pop_converted<M: Machine<'gc>>(m: &mut M) -> Self { fn pop_converted<M: Machine<'gc>>(m: &mut M) -> Self {
m.pop_forced() m.pop_forced()
.as_float() .downcast_float()
.expect("type checked in force_and_check") .expect("type checked in force_and_check")
} }
} }
+18 -18
View File
@@ -44,10 +44,10 @@ pub trait VmRuntimeCtxExt: VmRuntimeCtx {
impl<T: VmRuntimeCtx> VmRuntimeCtxExt for T { impl<T: VmRuntimeCtx> VmRuntimeCtxExt for T {
fn get_string<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str> { fn get_string<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str> {
if let Some(sid) = val.as_inline::<StringId>() { if let Some(sid) = val.downcast::<StringId>() {
Some(self.resolve_string(sid)) Some(self.resolve_string(sid))
} else { } else {
val.as_gc::<NixString>().map(|ns| ns.as_ref().as_str()) val.downcast::<NixString>().map(|ns| ns.as_ref().as_str())
} }
} }
@@ -56,7 +56,7 @@ impl<T: VmRuntimeCtx> VmRuntimeCtxExt for T {
/// would coerce a path to a string (string interpolation, file IO /// would coerce a path to a string (string interpolation, file IO
/// builtins, etc.). /// builtins, etc.).
fn get_string_or_path<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str> { fn get_string_or_path<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str> {
if let Some(p) = val.as_inline::<Path>() { if let Some(p) = val.downcast::<Path>() {
Some(self.resolve_string(p.0)) Some(self.resolve_string(p.0))
} else { } else {
self.get_string(val) self.get_string(val)
@@ -67,9 +67,9 @@ impl<T: VmRuntimeCtx> VmRuntimeCtxExt for T {
&'a mut self, &'a mut self,
val: StrictValue<'gc>, val: StrictValue<'gc>,
) -> std::result::Result<StringId, NixType> { ) -> std::result::Result<StringId, NixType> {
if let Some(sid) = val.as_inline::<StringId>() { if let Some(sid) = val.downcast::<StringId>() {
Ok(sid) Ok(sid)
} else if let Some(s) = val.as_gc::<NixString>().map(|ns| ns.as_ref().as_str()) { } else if let Some(s) = val.downcast::<NixString>().map(|ns| ns.as_ref().as_str()) {
Ok(self.intern_string(s)) Ok(self.intern_string(s))
} else { } else {
Err(val.ty()) Err(val.ty())
@@ -77,7 +77,7 @@ impl<T: VmRuntimeCtx> VmRuntimeCtxExt for T {
} }
fn get_string_context<'gc>(&self, val: StrictValue<'gc>) -> &'gc StringContext { fn get_string_context<'gc>(&self, val: StrictValue<'gc>) -> &'gc StringContext {
if let Some(ns) = val.as_gc::<NixString>() { if let Some(ns) = val.downcast::<NixString>() {
ns.as_ref().context() ns.as_ref().context()
} else { } else {
StringContext::empty() StringContext::empty()
@@ -96,24 +96,24 @@ pub(crate) trait ConvertValueWithSeen: VmRuntimeCtx {
impl<T: VmRuntimeCtx> ConvertValueWithSeen for T { impl<T: VmRuntimeCtx> ConvertValueWithSeen for T {
fn convert_value_with_seen(&self, val: Value, seen: &mut HashSet<u64>) -> fix_lang::Value { fn convert_value_with_seen(&self, val: Value, seen: &mut HashSet<u64>) -> fix_lang::Value {
use fix_lang::Value; use fix_lang::Value;
if let Some(i) = val.as_inline::<i32>() { if let Some(i) = val.downcast::<i32>() {
Value::Int(i as i64) Value::Int(i as i64)
} else if let Some(gc_i) = val.as_gc::<i64>() { } else if let Some(gc_i) = val.downcast::<i64>() {
Value::Int(*gc_i) Value::Int(*gc_i)
} else if let Some(f) = val.as_float() { } else if let Some(f) = val.downcast_float() {
Value::Float(f) Value::Float(f)
} else if let Some(b) = val.as_inline::<bool>() { } else if let Some(b) = val.downcast::<bool>() {
Value::Bool(b) Value::Bool(b)
} else if val.is::<Null>() { } else if val.is::<Null>() {
Value::Null Value::Null
} else if let Some(sid) = val.as_inline::<StringId>() { } else if let Some(sid) = val.downcast::<StringId>() {
let s = self.resolve_string(sid).to_owned(); let s = self.resolve_string(sid).to_owned();
Value::String(s) Value::String(s)
} else if let Some(ns) = val.as_gc::<NixString>() { } else if let Some(ns) = val.downcast::<NixString>() {
Value::String(ns.as_str().to_owned()) Value::String(ns.as_str().to_owned())
} else if let Some(p) = val.as_inline::<Path>() { } else if let Some(p) = val.downcast::<Path>() {
Value::Path(self.resolve_string(p.0).to_owned()) Value::Path(self.resolve_string(p.0).to_owned())
} else if let Some(attrs) = val.as_gc::<AttrSet>() { } else if let Some(attrs) = val.downcast::<AttrSet>() {
let bits = val.to_bits(); let bits = val.to_bits();
if attrs.entries.is_empty() { if attrs.entries.is_empty() {
return Value::AttrSet(Default::default()); return Value::AttrSet(Default::default());
@@ -128,7 +128,7 @@ impl<T: VmRuntimeCtx> ConvertValueWithSeen for T {
map.insert(fix_lang::Symbol::from(key), converted); map.insert(fix_lang::Symbol::from(key), converted);
} }
Value::AttrSet(fix_lang::AttrSet::new(map)) Value::AttrSet(fix_lang::AttrSet::new(map))
} else if let Some(list) = val.as_gc::<List>() { } else if let Some(list) = val.downcast::<List>() {
let bits = val.to_bits(); let bits = val.to_bits();
if list.inner.borrow().is_empty() { if list.inner.borrow().is_empty() {
return Value::List(Default::default()); return Value::List(Default::default());
@@ -146,16 +146,16 @@ impl<T: VmRuntimeCtx> ConvertValueWithSeen for T {
Value::List(fix_lang::List::new(items)) Value::List(fix_lang::List::new(items))
} else if val.is::<Closure>() { } else if val.is::<Closure>() {
Value::Func Value::Func
} else if let Some(thunk) = val.as_gc::<Thunk>() { } else if let Some(thunk) = val.downcast::<Thunk>() {
if let ThunkState::Evaluated(v) = *thunk.borrow() { if let ThunkState::Evaluated(v) = *thunk.borrow() {
self.convert_value_with_seen(v.relax(), seen) self.convert_value_with_seen(v.relax(), seen)
} else { } else {
Value::Thunk Value::Thunk
} }
} else if let Some(primop) = val.as_inline::<PrimOp>() { } else if let Some(primop) = val.downcast::<PrimOp>() {
let name = BUILTINS[primop.id as usize].0; let name = BUILTINS[primop.id as usize].0;
Value::PrimOp(name.strip_prefix("__").unwrap_or(name)) Value::PrimOp(name.strip_prefix("__").unwrap_or(name))
} else if let Some(app) = val.as_gc::<PrimOpApp>() { } else if let Some(app) = val.downcast::<PrimOpApp>() {
let name = BUILTINS[app.primop.id as usize].0; let name = BUILTINS[app.primop.id as usize].0;
Value::PrimOpApp(name.strip_prefix("__").unwrap_or(name)) Value::PrimOpApp(name.strip_prefix("__").unwrap_or(name))
} else { } else {
+8 -3
View File
@@ -18,16 +18,21 @@ pub fn resolve_operand<'gc, M: Machine<'gc>>(
use OperandData::*; use OperandData::*;
match *op { match *op {
Const(id) => ctx.get_const(id).into(), Const(id) => ctx.get_const(id).into(),
BigInt(val) => Value::new_gc(Gc::new(mc, val)), BigInt(val) => Value::new(Gc::new(mc, val)),
Local { layer, idx } => m.local(layer, idx), Local { layer, idx } => m.local(layer, idx),
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
BuiltinConst(id) => m.builtins().as_gc::<AttrSet>().unwrap().lookup(id).unwrap(), BuiltinConst(id) => m
.builtins()
.downcast::<AttrSet>()
.unwrap()
.lookup(id)
.unwrap(),
Builtins => m.builtins(), Builtins => m.builtins(),
ReplBinding(_id) => todo!(), ReplBinding(_id) => todo!(),
ScopedImportBinding { slot_id, name } => { ScopedImportBinding { slot_id, name } => {
let scope = m.scope_slot(slot_id); let scope = m.scope_slot(slot_id);
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let attrs = scope.as_gc::<AttrSet>().expect("scope must be attrset"); let attrs = scope.downcast::<AttrSet>().expect("scope must be attrset");
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
attrs.lookup(name).expect("scoped binding not found") attrs.lookup(name).expect("scoped binding not found")
} }
+119 -109
View File
@@ -19,33 +19,81 @@ mod private {
pub trait Cealed {} pub trait Cealed {}
} }
pub trait ValueVariant: private::Cealed {
type Ty<'gc>: 'gc;
fn is_value(value: &Value<'_>) -> bool;
/// # Safety /// # Safety
/// ///
/// [`Self::TAG`] must be unique among all implementors. /// [`Self::is_value`] must hold for `value`.
unsafe trait Storable: private::Cealed { unsafe fn from_raw<'gc>(value: &Value<'gc>) -> Self::Ty<'gc>;
const TAG: RawTag; }
/// # Safety
///
/// Each implementor must round-trip through [`Self::to_raw_box`] /
/// [`Self::from_raw_box`] and must be the sole owner of its NaN-boxed
/// representation (tagged payload or float).
pub(crate) unsafe trait Storable: private::Cealed {
fn to_raw_box(self) -> RawBox;
/// # Safety
///
/// `raw` must represent a valid `Self`.
unsafe fn from_raw_box(raw: &RawBox) -> Self;
} }
trait InlineStorable: Storable + RawStore {}
trait GcStorable: Storable {}
macro_rules! define_value_types { macro_rules! define_value_types {
( (
inline { $($itype:ty => $itag:expr, $iname:literal;)* } inline { $($itype:ty => $itag:path, $iname:literal;)* }
gc { $($gtype:ty => $gtag:expr, $gname:literal;)* } gc { $($gtype:ty => $gtag:path, $gname:literal;)* }
) => { ) => {
$( $(
unsafe impl Storable for $itype { unsafe impl Storable for $itype {
const TAG: RawTag = $itag; fn to_raw_box(self) -> RawBox {
RawBox::from_value(RawValue::store($itag, self))
}
unsafe fn from_raw_box(raw: &RawBox) -> Self {
unsafe { <Self as RawStore>::from_val(raw.value().unwrap_unchecked()) }
}
} }
impl InlineStorable for $itype {}
impl private::Cealed for $itype {} impl private::Cealed for $itype {}
impl ValueVariant for $itype {
type Ty<'gc> = $itype;
#[inline(always)]
fn is_value(value: &Value<'_>) -> bool {
value.raw.tag() == Some($itag)
}
#[inline(always)]
unsafe fn from_raw<'gc>(value: &Value<'gc>) -> Self::Ty<'gc> {
unsafe { <$itype as Storable>::from_raw_box(&value.raw) }
}
}
)* )*
$( $(
unsafe impl Storable for $gtype { unsafe impl Storable for Gc<'_, $gtype> {
const TAG: RawTag = $gtag; fn to_raw_box(self) -> RawBox {
RawBox::from_value(RawValue::store($gtag, Gc::as_ptr(self)))
} }
impl GcStorable for $gtype {} unsafe fn from_raw_box(raw: &RawBox) -> Self {
unsafe { Gc::from_ptr(<*mut $gtype as RawStore>::from_val(raw.value().unwrap_unchecked())) }
}
}
impl private::Cealed for Gc<'_, $gtype> {}
impl private::Cealed for $gtype {} impl private::Cealed for $gtype {}
impl ValueVariant for $gtype {
type Ty<'gc> = Gc<'gc, fix_macros::unelide_lifetimes!('gc; $gtype)>;
#[inline(always)]
fn is_value(value: &Value<'_>) -> bool {
value.raw.tag() == Some($gtag)
}
#[inline(always)]
unsafe fn from_raw<'gc>(value: &Value<'gc>) -> Self::Ty<'gc> {
unsafe {
<Gc<'gc, fix_macros::unelide_lifetimes!('gc; $gtype)> as Storable>::from_raw_box(
&value.raw,
)
}
}
}
)* )*
const _: () = assert!(size_of::<Value<'static>>() == 8); const _: () = assert!(size_of::<Value<'static>>() == 8);
@@ -75,10 +123,10 @@ macro_rules! define_value_types {
fn trace<T: Trace<'gc>>(&self, cc: &mut T) { fn trace<T: Trace<'gc>>(&self, cc: &mut T) {
let Some(tag) = self.raw.tag() else { return }; let Some(tag) = self.raw.tag() else { return };
match tag { match tag {
$(<$gtype as Storable>::TAG => unsafe { $($gtag => unsafe {
self.load_gc::<$gtype>().trace(cc) self.downcast::<$gtype>().unwrap_unchecked().trace(cc)
},)* },)*
$(<$itype as Storable>::TAG => (),)* $($itag => (),)*
_ => unreachable!("invalid value tag"), _ => unreachable!("invalid value tag"),
} }
} }
@@ -90,10 +138,10 @@ macro_rules! define_value_types {
None => write!(f, "Float({:?})", unsafe { None => write!(f, "Float({:?})", unsafe {
self.raw.float().unwrap_unchecked() self.raw.float().unwrap_unchecked()
}), }),
$(Some(<$itype as Storable>::TAG) => write!(f, "{}({:?})", $iname, unsafe { $(Some($itag) => write!(f, "{}({:?})", $iname, unsafe {
self.as_inline::<$itype>().unwrap_unchecked() self.downcast::<$itype>().unwrap_unchecked()
}),)* }),)*
$(Some(<$gtype as Storable>::TAG) => $(Some($gtag) =>
write!(f, "{}(..)", $gname),)* write!(f, "{}(..)", $gname),)*
_ => unreachable!("invalid value tag"), _ => unreachable!("invalid value tag"),
} }
@@ -122,6 +170,29 @@ define_value_types! {
} }
} }
impl private::Cealed for f64 {}
unsafe impl Storable for f64 {
fn to_raw_box(self) -> RawBox {
RawBox::from_float(self)
}
unsafe fn from_raw_box(raw: &RawBox) -> Self {
unsafe { raw.float().copied().unwrap_unchecked() }
}
}
impl ValueVariant for f64 {
type Ty<'gc> = f64;
#[inline(always)]
fn is_value(value: &Value<'_>) -> bool {
value.raw.is_float()
}
#[inline(always)]
unsafe fn from_raw<'gc>(value: &Value<'gc>) -> Self::Ty<'gc> {
unsafe { <f64 as Storable>::from_raw_box(&value.raw) }
}
}
/// # Nix runtime value representation /// # Nix runtime value representation
/// ///
/// NaN-boxed value fitting in 8 bytes. /// NaN-boxed value fitting in 8 bytes.
@@ -135,33 +206,11 @@ pub struct Value<'gc> {
impl Default for Value<'_> { impl Default for Value<'_> {
#[inline(always)] #[inline(always)]
fn default() -> Self { fn default() -> Self {
Self::new_inline(Null) Self::new(Null)
} }
} }
impl<'gc> Value<'gc> { impl<'gc> Value<'gc> {
#[inline(always)]
fn from_raw_value(rv: RawValue) -> Self {
Self {
raw: RawBox::from_value(rv),
_marker: PhantomData,
}
}
/// Load a GC pointer from a value with a negative tag.
///
/// # Safety
///
/// The value must actually store a `Gc<'gc, T>` with the matching type.
#[inline(always)]
unsafe fn load_gc<T: GcStorable>(self) -> Gc<'gc, T> {
unsafe {
let rv = self.raw.value().unwrap_unchecked();
let ptr: *const T = <*const T as RawStore>::from_val(rv);
Gc::from_ptr(ptr)
}
}
#[inline(always)] #[inline(always)]
const fn tag(self) -> Option<RawTag> { const fn tag(self) -> Option<RawTag> {
self.raw.tag() self.raw.tag()
@@ -179,23 +228,19 @@ impl<'gc> Value<'gc> {
#[inline] #[inline]
#[allow(private_bounds)] #[allow(private_bounds)]
pub fn new_inline<T: InlineStorable>(val: T) -> Self { pub fn new<T: Storable>(val: T) -> Self {
Self::from_raw_value(RawValue::store(T::TAG, val)) Self {
raw: val.to_raw_box(),
_marker: PhantomData,
} }
#[inline]
#[allow(private_bounds)]
pub fn new_gc<T: GcStorable>(gc: Gc<'gc, T>) -> Self {
let ptr = Gc::as_ptr(gc);
Self::from_raw_value(RawValue::store(T::TAG, ptr))
} }
#[inline] #[inline]
pub fn make_int(val: i64, mc: &Mutation<'gc>) -> Self { pub fn make_int(val: i64, mc: &Mutation<'gc>) -> Self {
if val >= i32::MIN as i64 && val <= i32::MAX as i64 { if val >= i32::MIN as i64 && val <= i32::MAX as i64 {
Value::new_inline(val as i32) Value::new(val as i32)
} else { } else {
Value::new_gc(Gc::new(mc, val)) Value::new(Gc::new(mc, val))
} }
} }
} }
@@ -207,43 +252,20 @@ impl<'gc> Value<'gc> {
} }
#[inline] #[inline]
#[allow(private_bounds)] pub fn is<T: ValueVariant>(self) -> bool {
pub fn is<T: Storable>(self) -> bool { T::is_value(&self)
self.tag() == Some(T::TAG)
} }
} }
impl<'gc> Value<'gc> { impl<'gc> Value<'gc> {
#[inline] #[inline]
pub fn as_float(self) -> Option<f64> { pub fn downcast_float(self) -> Option<f64> {
self.raw.float().copied() self.raw.float().copied()
} }
#[inline] #[inline]
#[allow(private_bounds)] pub fn downcast<T: ValueVariant>(self) -> Option<T::Ty<'gc>> {
pub fn as_inline<T: InlineStorable>(self) -> Option<T> { self.is::<T>().then(|| unsafe { T::from_raw(&self) })
if self.is::<T>() {
Some(unsafe {
let rv = self.raw.value().unwrap_unchecked();
T::from_val(rv)
})
} else {
None
}
}
#[inline]
#[allow(private_bounds)]
pub fn as_gc<T: GcStorable>(self) -> Option<Gc<'gc, T>> {
if self.is::<T>() {
Some(unsafe {
let rv = self.raw.value().unwrap_unchecked();
let ptr: *const T = <*const T as RawStore>::from_val(rv);
Gc::from_ptr(ptr)
})
} else {
None
}
} }
#[inline] #[inline]
@@ -253,18 +275,18 @@ impl<'gc> Value<'gc> {
#[inline] #[inline]
pub fn as_num(self) -> Option<NixNum> { pub fn as_num(self) -> Option<NixNum> {
if let Some(i) = self.as_inline::<i32>() { if let Some(i) = self.downcast::<i32>() {
Some(NixNum::Int(i as i64)) Some(NixNum::Int(i as i64))
} else if let Some(gc_i) = self.as_gc::<i64>() { } else if let Some(gc_i) = self.downcast::<i64>() {
Some(NixNum::Int(*gc_i)) Some(NixNum::Int(*gc_i))
} else { } else {
self.as_float().map(NixNum::Float) self.downcast_float().map(NixNum::Float)
} }
} }
#[inline] #[inline]
pub fn restrict(self) -> Result<StrictValue<'gc>, Gc<'gc, Thunk<'gc>>> { pub fn restrict(self) -> Result<StrictValue<'gc>, Gc<'gc, Thunk<'gc>>> {
if let Some(thunk) = self.as_gc::<Thunk<'gc>>() { if let Some(thunk) = self.downcast::<Thunk>() {
Err(thunk) Err(thunk)
} else { } else {
Ok(StrictValue(self)) Ok(StrictValue(self))
@@ -305,15 +327,8 @@ impl<'gc> Value<'gc> {
} }
#[inline] #[inline]
#[allow(private_bounds)] pub fn expect<T: ValueVariant>(self) -> Result<T::Ty<'gc>, NixType> {
pub fn expect_inline<T: InlineStorable>(self) -> Result<T, NixType> { self.downcast::<T>().ok_or_else(|| self.ty())
self.as_inline::<T>().ok_or_else(|| self.ty())
}
#[inline]
#[allow(private_bounds)]
pub fn expect_gc<T: GcStorable>(self) -> Result<Gc<'gc, T>, NixType> {
self.as_gc::<T>().ok_or_else(|| self.ty())
} }
#[inline] #[inline]
@@ -321,14 +336,9 @@ impl<'gc> Value<'gc> {
self.as_num().ok_or_else(|| self.ty()) self.as_num().ok_or_else(|| self.ty())
} }
#[inline]
pub fn expect_bool(self) -> Result<bool, NixType> {
self.as_inline::<bool>().ok_or_else(|| self.ty())
}
#[inline] #[inline]
pub fn expect_float(self) -> Result<f64, NixType> { pub fn expect_float(self) -> Result<f64, NixType> {
self.as_float().ok_or_else(|| self.ty()) self.downcast_float().ok_or_else(|| self.ty())
} }
} }
@@ -351,35 +361,35 @@ impl StaticValue {
} }
#[inline] #[inline]
#[allow(private_bounds)] #[allow(private_bounds)]
pub fn new_inline<T: InlineStorable>(val: T) -> Self { pub fn new<T: Storable + 'static>(val: T) -> Self {
Self(Value::new_inline(val)) Self(Value::new(val))
} }
#[inline] #[inline]
pub fn new_primop(id: BuiltinId, arity: u8, dispatch_ip: u32) -> Self { pub fn new_primop(id: BuiltinId, arity: u8, dispatch_ip: u32) -> Self {
Self(Value::new_inline(PrimOp { Self::new(PrimOp {
id, id,
arity, arity,
dispatch_ip, dispatch_ip,
})) })
} }
#[inline] #[inline]
pub fn is_float(self) -> bool { pub fn is_float(self) -> bool {
self.0.is_float() self.0.is_float()
} }
#[inline] #[inline]
#[allow(private_bounds)] pub fn is<T: ValueVariant>(self) -> bool {
pub fn is<T: InlineStorable>(self) -> bool {
self.0.is::<T>() self.0.is::<T>()
} }
#[inline] #[inline]
pub fn as_float(self) -> Option<f64> { pub fn downcast<T: ValueVariant>(self) -> Option<T::Ty<'static>> {
self.0.as_float() self.0.downcast::<T>()
} }
#[inline] #[inline]
#[allow(private_bounds)] pub fn downcast_float(self) -> Option<f64> {
pub fn as_inline<T: InlineStorable>(self) -> Option<T> { self.0.downcast_float()
self.0.as_inline::<T>()
} }
#[inline] #[inline]
pub fn to_bits(self) -> u64 { pub fn to_bits(self) -> u64 {
self.0.raw.to_bits() self.0.raw.to_bits()
+12 -12
View File
@@ -28,7 +28,7 @@ pub(crate) fn op_add<'gc, M: Machine<'gc>>(
let combined = format!("{ls}{rs}"); let combined = format!("{ls}{rs}");
let canon = canon_path_str(&combined); let canon = canon_path_str(&combined);
let sid = ctx.intern_string(canon); let sid = ctx.intern_string(canon);
m.push(Value::new_inline(fix_runtime::Path(sid))); m.push(Value::new(fix_runtime::Path(sid)));
return Step::Continue(()); return Step::Continue(());
} }
if let (Some(ls), Some(rs)) = (ctx.get_string(lhs), ctx.get_string_or_path(rhs)) { if let (Some(ls), Some(rs)) = (ctx.get_string(lhs), ctx.get_string_or_path(rhs)) {
@@ -39,7 +39,7 @@ pub(crate) fn op_add<'gc, M: Machine<'gc>>(
mc, mc,
crate::NixString::with_context(format!("{ls}{rs}"), merged), crate::NixString::with_context(format!("{ls}{rs}"), merged),
); );
m.push(Value::new_gc(ns)); m.push(Value::new(ns));
return Step::Continue(()); return Step::Continue(());
} }
let res = numeric_binop(lhs, rhs, mc, i64::wrapping_add, |a, b| a + b); let res = numeric_binop(lhs, rhs, mc, i64::wrapping_add, |a, b| a + b);
@@ -200,7 +200,7 @@ pub(crate) fn op_concat<'gc, M: Machine<'gc>>(
let mut items = smallvec::SmallVec::new(); let mut items = smallvec::SmallVec::new();
items.extend_from_slice(&l.inner.borrow()); items.extend_from_slice(&l.inner.borrow());
items.extend_from_slice(&r.inner.borrow()); items.extend_from_slice(&r.inner.borrow());
m.push(Value::new_gc(Gc::new( m.push(Value::new(Gc::new(
mc, mc,
crate::List { crate::List {
inner: RefLock::new(items), inner: RefLock::new(items),
@@ -216,7 +216,7 @@ pub(crate) fn op_update<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
let (l, r) = m.force_and_retry::<(Gc<AttrSet>, Gc<AttrSet>)>(reader, mc)?; let (l, r) = m.force_and_retry::<(Gc<AttrSet>, Gc<AttrSet>)>(reader, mc)?;
m.push(Value::new_gc(l.merge(&r, mc))); m.push(Value::new(l.merge(&r, mc)));
Step::Continue(()) Step::Continue(())
} }
@@ -241,7 +241,7 @@ pub(crate) fn op_not<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
let rhs = m.force_and_retry::<bool>(reader, mc)?; let rhs = m.force_and_retry::<bool>(reader, mc)?;
m.push(Value::new_inline(!rhs)); m.push(Value::new(!rhs));
Step::Continue(()) Step::Continue(())
} }
@@ -263,17 +263,17 @@ fn compare_values_inner<'gc, M: Machine<'gc>>(
a.partial_cmp(&(b as f64)).unwrap_or(Ordering::Less) a.partial_cmp(&(b as f64)).unwrap_or(Ordering::Less)
} }
}; };
m.push(Value::new_inline(pred(ord))); m.push(Value::new(pred(ord)));
return Ok(()); return Ok(());
} }
if let (Some(a), Some(b)) = (ctx.get_string(lhs), ctx.get_string(rhs)) { if let (Some(a), Some(b)) = (ctx.get_string(lhs), ctx.get_string(rhs)) {
m.push(Value::new_inline(pred(a.cmp(b)))); m.push(Value::new(pred(a.cmp(b))));
return Ok(()); return Ok(());
} }
if let (Some(a), Some(b)) = (lhs.as_inline::<Path>(), rhs.as_inline::<Path>()) { if let (Some(a), Some(b)) = (lhs.downcast::<Path>(), rhs.downcast::<Path>()) {
let a = ctx.resolve_string(a.0); let a = ctx.resolve_string(a.0);
let b = ctx.resolve_string(b.0); let b = ctx.resolve_string(b.0);
m.push(Value::new_inline(pred(a.cmp(b)))); m.push(Value::new(pred(a.cmp(b))));
return Ok(()); return Ok(());
} }
// TODO: compare other types // TODO: compare other types
@@ -285,12 +285,12 @@ fn compare_values_inner<'gc, M: Machine<'gc>>(
} }
pub(crate) fn get_num(val: StrictValue<'_>) -> Option<NixNum> { pub(crate) fn get_num(val: StrictValue<'_>) -> Option<NixNum> {
if let Some(i) = val.as_inline::<i32>() { if let Some(i) = val.downcast::<i32>() {
Some(NixNum::Int(i64::from(i))) Some(NixNum::Int(i64::from(i)))
} else if let Some(gc_i) = val.as_gc::<i64>() { } else if let Some(gc_i) = val.downcast::<i64>() {
Some(NixNum::Int(*gc_i)) Some(NixNum::Int(*gc_i))
} else { } else {
val.as_float().map(NixNum::Float) val.downcast_float().map(NixNum::Float)
} }
} }
+6 -6
View File
@@ -21,7 +21,7 @@ pub(crate) fn call<'gc, M: Machine<'gc>>(
return m.finish_err(Error::eval_error("stack overflow; max-call-depth exceeded")); return m.finish_err(Error::eval_error("stack overflow; max-call-depth exceeded"));
} }
m.inc_call_depth(); m.inc_call_depth();
if let Some(closure) = func.as_gc::<Closure>() { if let Some(closure) = func.downcast::<Closure>() {
if closure.pattern.is_some() { if closure.pattern.is_some() {
// FIXME: better DX... // FIXME: better DX...
m.push(func.relax()); m.push(func.relax());
@@ -46,7 +46,7 @@ pub(crate) fn call<'gc, M: Machine<'gc>>(
}); });
reader.set_pc(ip as usize); reader.set_pc(ip as usize);
m.set_env(new_env); m.set_env(new_env);
} else if let Some(primop) = func.as_inline::<PrimOp>() { } else if let Some(primop) = func.downcast::<PrimOp>() {
if primop.arity == 1 { if primop.arity == 1 {
m.push(arg); m.push(arg);
m.push_call_frame(CallFrame { m.push_call_frame(CallFrame {
@@ -61,9 +61,9 @@ pub(crate) fn call<'gc, M: Machine<'gc>>(
arity: primop.arity - 1, arity: primop.arity - 1,
args: [arg, Value::default(), Value::default()], args: [arg, Value::default(), Value::default()],
}; };
m.push(Value::new_gc(Gc::new(mc, app))); m.push(Value::new(Gc::new(mc, app)));
} }
} else if let Some(app) = func.as_gc::<PrimOpApp>() { } else if let Some(app) = func.downcast::<PrimOpApp>() {
if app.arity == 1 { if app.arity == 1 {
for i in 0..app.primop.arity - 1 { for i in 0..app.primop.arity - 1 {
m.push(app.args[i as usize]); m.push(app.args[i as usize]);
@@ -82,9 +82,9 @@ pub(crate) fn call<'gc, M: Machine<'gc>>(
..*app ..*app
}; };
new_app.args[position] = arg; new_app.args[position] = arg;
m.push(Value::new_gc(Gc::new(mc, new_app))) m.push(Value::new(Gc::new(mc, new_app)))
} }
} else if let Some(attrs) = func.as_gc::<AttrSet>() } else if let Some(attrs) = func.downcast::<AttrSet>()
&& let Some(functor) = attrs.lookup(m.functor_sym()) && let Some(functor) = attrs.lookup(m.functor_sym())
{ {
// f arg => (f.__functor f) arg // f arg => (f.__functor f) arg
+3 -3
View File
@@ -17,7 +17,7 @@ pub(crate) fn op_make_thunk<'gc, M: Machine<'gc>>(
env: m.env(), env: m.env(),
}), }),
); );
m.push(Value::new_gc(thunk)); m.push(Value::new(thunk));
Step::Continue(()) Step::Continue(())
} }
@@ -38,7 +38,7 @@ pub(crate) fn op_make_closure<'gc, M: Machine<'gc>>(
pattern: None, pattern: None,
}, },
); );
m.push(Value::new_gc(closure)); m.push(Value::new(closure));
Step::Continue(()) Step::Continue(())
} }
@@ -88,6 +88,6 @@ pub(crate) fn op_make_pattern_closure<'gc, M: Machine<'gc>>(
pattern: Some(pattern), pattern: Some(pattern),
}, },
); );
m.push(Value::new_gc(closure)); m.push(Value::new(closure));
Step::Continue(()) Step::Continue(())
} }
+9 -9
View File
@@ -57,7 +57,7 @@ pub(crate) fn op_make_attrs<'gc, M: Machine<'gc>>(
kv.sort_by_key(|(k, _)| *k); kv.sort_by_key(|(k, _)| *k);
let attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(kv)); let attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(kv));
m.push(Value::new_gc(attrs)); m.push(Value::new(attrs));
Step::Continue(()) Step::Continue(())
} }
@@ -195,7 +195,7 @@ pub(crate) fn op_has_attr_path_static<'gc, M: Machine<'gc>>(
let current = m.force_and_retry::<StrictValue>(reader, mc)?; let current = m.force_and_retry::<StrictValue>(reader, mc)?;
match current match current
.as_gc::<AttrSet>() .downcast::<AttrSet>()
.and_then(|attrs| attrs.lookup(key)) .and_then(|attrs| attrs.lookup(key))
{ {
Some(v) => { Some(v) => {
@@ -223,7 +223,7 @@ pub(crate) fn op_has_attr_path_dynamic<'gc, M: Machine<'gc>>(
}; };
match current match current
.as_gc::<AttrSet>() .downcast::<AttrSet>()
.and_then(|attrs| attrs.lookup(key_sid)) .and_then(|attrs| attrs.lookup(key_sid))
{ {
Some(v) => { Some(v) => {
@@ -263,9 +263,9 @@ pub(crate) fn op_has_attr_static<'gc, M: Machine<'gc>>(
let key = reader.read_string_id(); let key = reader.read_string_id();
let current = m.force_and_retry::<StrictValue>(reader, mc)?; let current = m.force_and_retry::<StrictValue>(reader, mc)?;
m.push(Value::new_inline( m.push(Value::new(
current current
.as_gc::<AttrSet>() .downcast::<AttrSet>()
.and_then(|attrs| attrs.lookup(key)) .and_then(|attrs| attrs.lookup(key))
.is_some(), .is_some(),
)); ));
@@ -289,9 +289,9 @@ pub(crate) fn op_has_attr_dynamic<'gc, M: MachineExt<'gc>>(
Err(got) => return m.finish_type_err(NixType::String, got), Err(got) => return m.finish_type_err(NixType::String, got),
}; };
m.push(Value::new_inline( m.push(Value::new(
current current
.as_gc::<AttrSet>() .downcast::<AttrSet>()
.and_then(|attrs| attrs.lookup(key_sid)) .and_then(|attrs| attrs.lookup(key_sid))
.is_some(), .is_some(),
)); ));
@@ -304,7 +304,7 @@ pub(crate) fn op_has_attr_dynamic<'gc, M: MachineExt<'gc>>(
#[inline(always)] #[inline(always)]
pub(crate) fn op_has_attr_resolve<'gc, M: Machine<'gc>>(m: &mut M) -> Step { pub(crate) fn op_has_attr_resolve<'gc, M: Machine<'gc>>(m: &mut M) -> Step {
// If we reach here, has_attr check has failed, push false (AttrSet is already popped) // If we reach here, has_attr check has failed, push false (AttrSet is already popped)
m.push(Value::new_inline(false)); m.push(Value::new(false));
Step::Continue(()) Step::Continue(())
} }
@@ -326,7 +326,7 @@ pub(crate) fn op_make_list<'gc, M: Machine<'gc>>(
inner: RefLock::new(items), inner: RefLock::new(items),
}, },
); );
m.push(Value::new_gc(list)); m.push(Value::new(list));
Step::Continue(()) Step::Continue(())
} }
+2 -2
View File
@@ -12,7 +12,7 @@ pub(crate) fn op_jump_if_false<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let offset = reader.read_i32(); let offset = reader.read_i32();
let cond = m.force_and_retry::<StrictValue>(reader, mc)?; let cond = m.force_and_retry::<StrictValue>(reader, mc)?;
if cond.as_inline::<bool>() == Some(false) { if cond.downcast::<bool>() == Some(false) {
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize); reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
} }
Step::Continue(()) Step::Continue(())
@@ -26,7 +26,7 @@ pub(crate) fn op_jump_if_true<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let offset = reader.read_i32(); let offset = reader.read_i32();
let cond = m.force_and_retry::<StrictValue>(reader, mc)?; let cond = m.force_and_retry::<StrictValue>(reader, mc)?;
if cond.as_inline::<bool>() == Some(true) { if cond.downcast::<bool>() == Some(true) {
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize); reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
} }
Step::Continue(()) Step::Continue(())
+6 -6
View File
@@ -9,7 +9,7 @@ pub(crate) fn op_push_smi<'gc, M: Machine<'gc>>(
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
) -> Step { ) -> Step {
let val = reader.read_i32(); let val = reader.read_i32();
m.push(Value::new_inline(val)); m.push(Value::new(val));
Step::Continue(()) Step::Continue(())
} }
@@ -20,7 +20,7 @@ pub(crate) fn op_push_bigint<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
let val = reader.read_i64(); let val = reader.read_i64();
m.push(Value::new_gc(Gc::new(mc, val))); m.push(Value::new(Gc::new(mc, val)));
Step::Continue(()) Step::Continue(())
} }
@@ -40,24 +40,24 @@ pub(crate) fn op_push_string<'gc, M: Machine<'gc>>(
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
) -> Step { ) -> Step {
let sid = reader.read_string_id(); let sid = reader.read_string_id();
m.push(Value::new_inline(sid)); m.push(Value::new(sid));
Step::Continue(()) Step::Continue(())
} }
#[inline(always)] #[inline(always)]
pub(crate) fn op_push_null<'gc, M: Machine<'gc>>(m: &mut M) -> Step { pub(crate) fn op_push_null<'gc, M: Machine<'gc>>(m: &mut M) -> Step {
m.push(Value::new_inline(crate::Null)); m.push(Value::new(crate::Null));
Step::Continue(()) Step::Continue(())
} }
#[inline(always)] #[inline(always)]
pub(crate) fn op_push_true<'gc, M: Machine<'gc>>(m: &mut M) -> Step { pub(crate) fn op_push_true<'gc, M: Machine<'gc>>(m: &mut M) -> Step {
m.push(Value::new_inline(true)); m.push(Value::new(true));
Step::Continue(()) Step::Continue(())
} }
#[inline(always)] #[inline(always)]
pub(crate) fn op_push_false<'gc, M: Machine<'gc>>(m: &mut M) -> Step { pub(crate) fn op_push_false<'gc, M: Machine<'gc>>(m: &mut M) -> Step {
m.push(Value::new_inline(false)); m.push(Value::new(false));
Step::Continue(()) Step::Continue(())
} }
+9 -9
View File
@@ -22,7 +22,7 @@ pub(crate) fn op_load_builtin<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let Ok(id) = BuiltinId::try_from(reader.read_u8()) let Ok(id) = BuiltinId::try_from(reader.read_u8())
.map_err(|err| panic!("unknown builtin id: {}", err.number)); .map_err(|err| panic!("unknown builtin id: {}", err.number));
m.push(Value::new_inline(PrimOp { m.push(Value::new(PrimOp {
id, id,
arity: BUILTINS[id as usize].1, arity: BUILTINS[id as usize].1,
dispatch_ip: Continuation::entry_for_builtin(id).ip(), dispatch_ip: Continuation::entry_for_builtin(id).ip(),
@@ -49,7 +49,7 @@ pub(crate) fn op_load_scoped_binding<'gc, M: Machine<'gc>>(
let slot_id = reader.read_u32(); let slot_id = reader.read_u32();
let name = reader.read_string_id(); let name = reader.read_string_id();
let scope = m.scope_slot(slot_id); let scope = m.scope_slot(slot_id);
let Some(attrs) = scope.as_gc::<AttrSet>() else { let Some(attrs) = scope.downcast::<AttrSet>() else {
return m.finish_err(Error::eval_error("internal: scope slot is not an attrset")); return m.finish_err(Error::eval_error("internal: scope slot is not an attrset"));
}; };
match attrs.lookup(name) { match attrs.lookup(name) {
@@ -73,10 +73,10 @@ pub(crate) fn op_coerce_to_string<'gc, M: Machine<'gc>>(
let val = m.force_and_retry::<StrictValue>(reader, mc)?; let val = m.force_and_retry::<StrictValue>(reader, mc)?;
if val.is::<StringId>() || val.is::<NixString>() { if val.is::<StringId>() || val.is::<NixString>() {
m.push(val.relax()); m.push(val.relax());
} else if let Some(p) = val.as_inline::<Path>() { } else if let Some(p) = val.downcast::<Path>() {
// Coercing a path to a string yields the canonical path text. // Coercing a path to a string yields the canonical path text.
// FIXME: copy to store // FIXME: copy to store
m.push(Value::new_inline(p.0)); m.push(Value::new(p.0));
} else { } else {
todo!("coerce other types to string: {:?}", val.ty()); todo!("coerce other types to string: {:?}", val.ty());
} }
@@ -122,10 +122,10 @@ pub(crate) fn op_concat_strings<'gc, M: Machine<'gc>>(
if merged.is_empty() { if merged.is_empty() {
let sid = ctx.intern_string(result); let sid = ctx.intern_string(result);
m.push(Value::new_inline(sid)); m.push(Value::new(sid));
} else { } else {
let ns = gc_arena::Gc::new(mc, NixString::with_context(result, merged)); let ns = gc_arena::Gc::new(mc, NixString::with_context(result, merged));
m.push(Value::new_gc(ns)); m.push(Value::new(ns));
} }
Step::Continue(()) Step::Continue(())
} }
@@ -140,8 +140,8 @@ pub(crate) fn op_resolve_path<'gc, M: MachineExt<'gc>>(
let path_val = m.force_and_retry::<StrictValue>(reader, mc)?; let path_val = m.force_and_retry::<StrictValue>(reader, mc)?;
let dir_id = reader.read_string_id(); let dir_id = reader.read_string_id();
// Already a path: keep as-is. ResolvePath is idempotent on paths. // Already a path: keep as-is. ResolvePath is idempotent on paths.
if let Some(p) = path_val.as_inline::<Path>() { if let Some(p) = path_val.downcast::<Path>() {
m.push(Value::new_inline(p)); m.push(Value::new(p));
return Step::Continue(()); return Step::Continue(());
} }
let path = match ctx.get_string(path_val) { let path = match ctx.get_string(path_val) {
@@ -158,7 +158,7 @@ pub(crate) fn op_resolve_path<'gc, M: MachineExt<'gc>>(
Err(e) => return m.finish_err(e), Err(e) => return m.finish_err(e),
}; };
let sid = ctx.intern_string(resolved); let sid = ctx.intern_string(resolved);
m.push(Value::new_inline(Path(sid))); m.push(Value::new(Path(sid)));
Step::Continue(()) Step::Continue(())
} }
+3 -3
View File
@@ -13,7 +13,7 @@ pub(crate) fn op_lookup_with<'gc, M: Machine<'gc>>(
mc: &gc_arena::Mutation<'gc>, mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let counter = m.peek_forced(0).as_inline::<i32>().unwrap(); let counter = m.peek_forced(0).downcast::<i32>().unwrap();
let name = reader.read_string_id(); let name = reader.read_string_id();
let n = reader.read_u8(); let n = reader.read_u8();
@@ -57,7 +57,7 @@ pub(crate) fn op_lookup_with<'gc, M: Machine<'gc>>(
}; };
if let Some(val) = namespace if let Some(val) = namespace
.as_gc::<AttrSet>() .downcast::<AttrSet>()
.and_then(|attrs| attrs.lookup(name)) .and_then(|attrs| attrs.lookup(name))
{ {
m.replace(0, val); m.replace(0, val);
@@ -67,7 +67,7 @@ pub(crate) fn op_lookup_with<'gc, M: Machine<'gc>>(
Symbol::from(ctx.resolve_string(name)) Symbol::from(ctx.resolve_string(name))
))); )));
} else { } else {
m.replace(0, Value::new_inline(counter + 1)); m.replace(0, Value::new(counter + 1));
reader.set_pc(resume_pc); reader.set_pc(resume_pc);
} }
+15 -21
View File
@@ -7,7 +7,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use fix_bytecode::{InstructionPtr, Continuation}; use fix_bytecode::{Continuation, InstructionPtr};
use fix_error::{Error, Result, Source}; use fix_error::{Error, Result, Source};
use fix_lang::{BUILTINS, BuiltinId, StringId}; use fix_lang::{BUILTINS, BuiltinId, StringId};
use gc_arena::metrics::Pacing; use gc_arena::metrics::Pacing;
@@ -63,7 +63,7 @@ fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmRuntimeCtx) -> Value<
let dispatch_ip = Continuation::entry_for_builtin(id).ip(); let dispatch_ip = Continuation::entry_for_builtin(id).ip();
entries.push(( entries.push((
name, name,
Value::new_inline(PrimOp { Value::new(PrimOp {
id, id,
arity, arity,
dispatch_ip, dispatch_ip,
@@ -74,21 +74,15 @@ fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmRuntimeCtx) -> Value<
let consts = [ let consts = [
( (
"__currentSystem", "__currentSystem",
Value::new_inline(ctx.intern_string("x86_64-linux")), Value::new(ctx.intern_string("x86_64-linux")),
), ),
("__langVersion", Value::new_inline(6i32)), ("__langVersion", Value::new(6i32)),
( ("__nixVersion", Value::new(ctx.intern_string("2.24.0"))),
"__nixVersion", ("__storeDir", Value::new(ctx.intern_string("/nix/store"))),
Value::new_inline(ctx.intern_string("2.24.0")), ("__nixPath", Value::new(Gc::new(mc, List::default()))),
), ("null", Value::new(Null)),
( ("true", Value::new(true)),
"__storeDir", ("false", Value::new(false)),
Value::new_inline(ctx.intern_string("/nix/store")),
),
("__nixPath", Value::new_gc(Gc::new(mc, List::default()))),
("null", Value::new_inline(Null)),
("true", Value::new_inline(true)),
("false", Value::new_inline(false)),
]; ];
for (name, val) in consts { for (name, val) in consts {
@@ -99,12 +93,12 @@ fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmRuntimeCtx) -> Value<
let self_ref_thunk = Gc::new(mc, RefLock::new(ThunkState::Blackhole)); let self_ref_thunk = Gc::new(mc, RefLock::new(ThunkState::Blackhole));
let sym = ctx.intern_string("builtins"); let sym = ctx.intern_string("builtins");
entries.push((sym, Value::new_gc(self_ref_thunk))); entries.push((sym, Value::new(self_ref_thunk)));
entries.sort_by_key(|(k, _)| *k); entries.sort_by_key(|(k, _)| *k);
let builtins_set = Gc::new(mc, AttrSet::from_sorted_unchecked(entries)); let builtins_set = Gc::new(mc, AttrSet::from_sorted_unchecked(entries));
let builtins_value = Value::new_gc(builtins_set); let builtins_value = Value::new(builtins_set);
*self_ref_thunk.borrow_mut(mc) = *self_ref_thunk.borrow_mut(mc) =
ThunkState::Evaluated(builtins_value.restrict().expect("builtins is not a thunk")); ThunkState::Evaluated(builtins_value.restrict().expect("builtins is not a thunk"));
builtins_value builtins_value
@@ -125,8 +119,8 @@ impl<'gc> Vm<'gc> {
scope_slots: Vec::new(), scope_slots: Vec::new(),
builtins, builtins,
empty_list: Value::new_gc(Gc::new(mc, List::default())), empty_list: Value::new(Gc::new(mc, List::default())),
empty_attrs: Value::new_gc(Gc::new(mc, AttrSet::default())), empty_attrs: Value::new(Gc::new(mc, AttrSet::default())),
force_mode, force_mode,
@@ -202,7 +196,7 @@ impl<'gc> Machine<'gc> for Vm<'gc> {
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
resume_pc: usize, resume_pc: usize,
) -> Step { ) -> Step {
let Some(thunk) = self.peek(depth).as_gc::<Thunk>() else { let Some(thunk) = self.peek(depth).downcast::<Thunk>() else {
return Step::Continue(()); return Step::Continue(());
}; };
let mut state = thunk.borrow_mut(mc); let mut state = thunk.borrow_mut(mc);
+49 -49
View File
@@ -22,11 +22,11 @@ pub fn has_context<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
let val = m.force_and_retry::<StrictValue>(reader, mc)?; let val = m.force_and_retry::<StrictValue>(reader, mc)?;
if !val.is::<StringId>() && val.as_gc::<NixString>().is_none() { if !val.is::<StringId>() && val.downcast::<NixString>().is_none() {
return m.finish_type_err(NixType::String, val.ty()); return m.finish_type_err(NixType::String, val.ty());
} }
let has_ctx = !ctx.get_string_context(val).is_empty(); let has_ctx = !ctx.get_string_context(val).is_empty();
m.return_from_primop(Value::new_inline(has_ctx), reader) m.return_from_primop(Value::new(has_ctx), reader)
} }
pub fn unsafe_discard_string_context<'gc, M: Machine<'gc>>( pub fn unsafe_discard_string_context<'gc, M: Machine<'gc>>(
@@ -36,14 +36,14 @@ pub fn unsafe_discard_string_context<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
let val = m.force_and_retry::<StrictValue>(reader, mc)?; let val = m.force_and_retry::<StrictValue>(reader, mc)?;
if let Some(sid) = val.as_inline::<StringId>() { if let Some(sid) = val.downcast::<StringId>() {
return m.return_from_primop(Value::new_inline(sid), reader); return m.return_from_primop(Value::new(sid), reader);
} }
let Some(ns) = val.as_gc::<NixString>() else { let Some(ns) = val.downcast::<NixString>() else {
return m.finish_type_err(NixType::String, val.ty()); return m.finish_type_err(NixType::String, val.ty());
}; };
let sid = ctx.intern_string(ns.as_str()); let sid = ctx.intern_string(ns.as_str());
m.return_from_primop(Value::new_inline(sid), reader) m.return_from_primop(Value::new(sid), reader)
} }
pub fn unsafe_discard_output_dependency<'gc, M: Machine<'gc>>( pub fn unsafe_discard_output_dependency<'gc, M: Machine<'gc>>(
@@ -53,15 +53,15 @@ pub fn unsafe_discard_output_dependency<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
let val = m.force_and_retry::<StrictValue>(reader, mc)?; let val = m.force_and_retry::<StrictValue>(reader, mc)?;
if let Some(sid) = val.as_inline::<StringId>() { if let Some(sid) = val.downcast::<StringId>() {
return m.return_from_primop(Value::new_inline(sid), reader); return m.return_from_primop(Value::new(sid), reader);
} }
let Some(ns) = val.as_gc::<NixString>() else { let Some(ns) = val.downcast::<NixString>() else {
return m.finish_type_err(NixType::String, val.ty()); return m.finish_type_err(NixType::String, val.ty());
}; };
if ns.context().is_empty() { if ns.context().is_empty() {
let sid = ctx.intern_string(ns.as_str()); let sid = ctx.intern_string(ns.as_str());
return m.return_from_primop(Value::new_inline(sid), reader); return m.return_from_primop(Value::new(sid), reader);
} }
let mut new_ctx = StringContext::new(); let mut new_ctx = StringContext::new();
@@ -77,7 +77,7 @@ pub fn unsafe_discard_output_dependency<'gc, M: Machine<'gc>>(
let s: Box<str> = ns.as_str().into(); let s: Box<str> = ns.as_str().into();
let new_ns = Gc::new(mc, NixString::with_context(s, new_ctx)); let new_ns = Gc::new(mc, NixString::with_context(s, new_ctx));
m.return_from_primop(Value::new_gc(new_ns), reader) m.return_from_primop(Value::new(new_ns), reader)
} }
pub fn get_context<'gc, M: Machine<'gc>>( pub fn get_context<'gc, M: Machine<'gc>>(
@@ -87,7 +87,7 @@ pub fn get_context<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
let val = m.force_and_retry::<StrictValue>(reader, mc)?; let val = m.force_and_retry::<StrictValue>(reader, mc)?;
if !val.is::<StringId>() && val.as_gc::<NixString>().is_none() { if !val.is::<StringId>() && val.downcast::<NixString>().is_none() {
return m.finish_type_err(NixType::String, val.ty()); return m.finish_type_err(NixType::String, val.ty());
} }
let elems = ctx.get_string_context(val); let elems = ctx.get_string_context(val);
@@ -135,29 +135,29 @@ pub fn get_context<'gc, M: Machine<'gc>>(
let mut sub: SmallVec<[(StringId, Value<'gc>); 4]> = SmallVec::new(); let mut sub: SmallVec<[(StringId, Value<'gc>); 4]> = SmallVec::new();
if info.all_outputs { if info.all_outputs {
sub.push((ctx.intern_string("allOutputs"), Value::new_inline(true))); sub.push((ctx.intern_string("allOutputs"), Value::new(true)));
} }
if !info.outputs.is_empty() { if !info.outputs.is_empty() {
let items: smallvec::SmallVec<[Value<'gc>; 4]> = info let items: smallvec::SmallVec<[Value<'gc>; 4]> = info
.outputs .outputs
.iter() .iter()
.map(|o| Value::new_inline(ctx.intern_string(o))) .map(|o| Value::new(ctx.intern_string(o)))
.collect(); .collect();
let list = VmList::new(mc, items); let list = VmList::new(mc, items);
sub.push((ctx.intern_string("outputs"), Value::new_gc(list))); sub.push((ctx.intern_string("outputs"), Value::new(list)));
} }
if info.path { if info.path {
sub.push((ctx.intern_string("path"), Value::new_inline(true))); sub.push((ctx.intern_string("path"), Value::new(true)));
} }
sub.sort_by_key(|(k, _)| *k); sub.sort_by_key(|(k, _)| *k);
let sub_attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(sub)); let sub_attrs = Gc::new(mc, AttrSet::from_sorted_unchecked(sub));
outer_entries.push((ctx.intern_string(&path), Value::new_gc(sub_attrs))); outer_entries.push((ctx.intern_string(&path), Value::new(sub_attrs)));
} }
outer_entries.sort_by_key(|(k, _)| *k); outer_entries.sort_by_key(|(k, _)| *k);
let outer = Gc::new(mc, AttrSet::from_sorted_unchecked(outer_entries)); let outer = Gc::new(mc, AttrSet::from_sorted_unchecked(outer_entries));
m.return_from_primop(Value::new_gc(outer), reader) m.return_from_primop(Value::new(outer), reader)
} }
/// appendContext :: String -> AttrSet -> String /// appendContext :: String -> AttrSet -> String
@@ -192,9 +192,9 @@ pub fn append_context<'gc, M: Machine<'gc>>(
let acc = Gc::new(mc, NixString::with_context("", initial_ctx)); let acc = Gc::new(mc, NixString::with_context("", initial_ctx));
m.push(str_val.relax()); m.push(str_val.relax());
m.push(Value::new_gc(attrs)); m.push(Value::new(attrs));
m.push(Value::new_inline(0i32)); m.push(Value::new(0i32));
m.push(Value::new_gc(acc)); m.push(Value::new(acc));
reader.set_pc(Continuation::PAppendContextLoop.ip() as usize); reader.set_pc(Continuation::PAppendContextLoop.ip() as usize);
Step::Continue(()) Step::Continue(())
@@ -207,9 +207,9 @@ pub fn append_context_loop<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(1).as_inline::<i32>().unwrap(); let idx = m.peek(1).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let attrs = m.peek_forced(2).as_gc::<AttrSet>().unwrap(); let attrs = m.peek_forced(2).downcast::<AttrSet>().unwrap();
if idx as usize >= attrs.entries.len() { if idx as usize >= attrs.entries.len() {
return append_context_finalize(m, ctx, reader, mc); return append_context_finalize(m, ctx, reader, mc);
@@ -238,14 +238,14 @@ pub fn append_context_entry_forced<'gc, M: Machine<'gc>>(
// Evaluated value into the slot. // Evaluated value into the slot.
m.force_slot(0, reader, mc)?; m.force_slot(0, reader, mc)?;
let entry_val = m.peek_forced(0); let entry_val = m.peek_forced(0);
let Some(entry_attrs) = entry_val.as_gc::<AttrSet>() else { let Some(entry_attrs) = entry_val.downcast::<AttrSet>() else {
return m.finish_type_err(NixType::AttrSet, entry_val.ty()); return m.finish_type_err(NixType::AttrSet, entry_val.ty());
}; };
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(2).as_inline::<i32>().unwrap(); let idx = m.peek(2).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let outer = m.peek_forced(3).as_gc::<AttrSet>().unwrap(); let outer = m.peek_forced(3).downcast::<AttrSet>().unwrap();
let path_key = outer.entries[idx as usize].0; let path_key = outer.entries[idx as usize].0;
let path_str_owned: Box<str> = ctx.resolve_string(path_key).into(); let path_str_owned: Box<str> = ctx.resolve_string(path_key).into();
if !path_str_owned.starts_with("/nix/store/") { if !path_str_owned.starts_with("/nix/store/") {
@@ -263,11 +263,11 @@ pub fn append_context_entry_forced<'gc, M: Machine<'gc>>(
let outputs_id = ctx.intern_string("outputs"); let outputs_id = ctx.intern_string("outputs");
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let acc_gc = m.peek(1).as_gc::<NixString>().unwrap(); let acc_gc = m.peek(1).downcast::<NixString>().unwrap();
let mut new_acc: StringContext = acc_gc.context().iter().cloned().collect(); let mut new_acc: StringContext = acc_gc.context().iter().cloned().collect();
if let Some(v) = entry_attrs.lookup(path_id) if let Some(v) = entry_attrs.lookup(path_id)
&& v.as_inline::<bool>() == Some(true) && v.downcast::<bool>() == Some(true)
{ {
new_acc.insert(StringContextElem::Opaque { new_acc.insert(StringContextElem::Opaque {
path: path_str_owned.clone(), path: path_str_owned.clone(),
@@ -275,7 +275,7 @@ pub fn append_context_entry_forced<'gc, M: Machine<'gc>>(
} }
if let Some(v) = entry_attrs.lookup(all_outputs_id) if let Some(v) = entry_attrs.lookup(all_outputs_id)
&& v.as_inline::<bool>() == Some(true) && v.downcast::<bool>() == Some(true)
{ {
if !path_str_owned.ends_with(".drv") { if !path_str_owned.ends_with(".drv") {
return m.finish_err(Error::eval_error(format!( return m.finish_err(Error::eval_error(format!(
@@ -288,7 +288,7 @@ pub fn append_context_entry_forced<'gc, M: Machine<'gc>>(
} }
let new_acc_gc = Gc::new(mc, NixString::with_context("", new_acc)); let new_acc_gc = Gc::new(mc, NixString::with_context("", new_acc));
m.replace(1, Value::new_gc(new_acc_gc)); m.replace(1, Value::new(new_acc_gc));
if let Some(outputs_val) = entry_attrs.lookup(outputs_id) { if let Some(outputs_val) = entry_attrs.lookup(outputs_id) {
m.replace(0, outputs_val); m.replace(0, outputs_val);
@@ -304,8 +304,8 @@ pub fn append_context_entry_forced<'gc, M: Machine<'gc>>(
let _ = m.pop(); let _ = m.pop();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx_back = m.peek(1).as_inline::<i32>().unwrap(); let idx_back = m.peek(1).downcast::<i32>().unwrap();
m.replace(1, Value::new_inline(idx_back + 1)); m.replace(1, Value::new(idx_back + 1));
reader.set_pc(Continuation::PAppendContextLoop.ip() as usize); reader.set_pc(Continuation::PAppendContextLoop.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -318,20 +318,20 @@ pub fn append_context_outputs_forced<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
m.force_slot(0, reader, mc)?; m.force_slot(0, reader, mc)?;
let list_val = m.peek_forced(0); let list_val = m.peek_forced(0);
let Some(list) = list_val.as_gc::<VmList>() else { let Some(list) = list_val.downcast::<VmList>() else {
return m.finish_type_err(NixType::List, list_val.ty()); return m.finish_type_err(NixType::List, list_val.ty());
}; };
if list.inner.borrow().is_empty() { if list.inner.borrow().is_empty() {
// Stack: [strVal, attrs, idx, acc, list] -> drop list, bump idx. // Stack: [strVal, attrs, idx, acc, list] -> drop list, bump idx.
let _ = m.pop(); let _ = m.pop();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx_back = m.peek(1).as_inline::<i32>().unwrap(); let idx_back = m.peek(1).downcast::<i32>().unwrap();
m.replace(1, Value::new_inline(idx_back + 1)); m.replace(1, Value::new(idx_back + 1));
reader.set_pc(Continuation::PAppendContextLoop.ip() as usize); reader.set_pc(Continuation::PAppendContextLoop.ip() as usize);
return Step::Continue(()); return Step::Continue(());
} }
m.push(Value::new_inline(0i32)); m.push(Value::new(0i32));
reader.set_pc(Continuation::PAppendContextOutputElementLoop.ip() as usize); reader.set_pc(Continuation::PAppendContextOutputElementLoop.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -343,9 +343,9 @@ pub fn append_context_output_element_loop<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let oidx = m.peek(0).as_inline::<i32>().unwrap(); let oidx = m.peek(0).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let list = m.peek_forced(1).as_gc::<VmList>().unwrap(); let list = m.peek_forced(1).downcast::<VmList>().unwrap();
let len = list.inner.borrow().len(); let len = list.inner.borrow().len();
if oidx as usize >= len { if oidx as usize >= len {
// Stack: [strVal, attrs, idx, acc, list, oidx] -> drop oidx & list, // Stack: [strVal, attrs, idx, acc, list, oidx] -> drop oidx & list,
@@ -353,8 +353,8 @@ pub fn append_context_output_element_loop<'gc, M: Machine<'gc>>(
let _ = m.pop(); let _ = m.pop();
let _ = m.pop(); let _ = m.pop();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx_back = m.peek(1).as_inline::<i32>().unwrap(); let idx_back = m.peek(1).downcast::<i32>().unwrap();
m.replace(1, Value::new_inline(idx_back + 1)); m.replace(1, Value::new(idx_back + 1));
reader.set_pc(Continuation::PAppendContextLoop.ip() as usize); reader.set_pc(Continuation::PAppendContextLoop.ip() as usize);
return Step::Continue(()); return Step::Continue(());
} }
@@ -385,9 +385,9 @@ pub fn append_context_output_element_forced<'gc, M: Machine<'gc>>(
let output_name: Box<str> = output_name.into(); let output_name: Box<str> = output_name.into();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(4).as_inline::<i32>().unwrap(); let idx = m.peek(4).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let outer = m.peek_forced(5).as_gc::<AttrSet>().unwrap(); let outer = m.peek_forced(5).downcast::<AttrSet>().unwrap();
let path_key = outer.entries[idx as usize].0; let path_key = outer.entries[idx as usize].0;
let path_str: Box<str> = ctx.resolve_string(path_key).into(); let path_str: Box<str> = ctx.resolve_string(path_key).into();
if !path_str.ends_with(".drv") { if !path_str.ends_with(".drv") {
@@ -397,21 +397,21 @@ pub fn append_context_output_element_forced<'gc, M: Machine<'gc>>(
} }
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let acc_gc = m.peek(3).as_gc::<NixString>().unwrap(); let acc_gc = m.peek(3).downcast::<NixString>().unwrap();
let mut new_acc: StringContext = acc_gc.context().iter().cloned().collect(); let mut new_acc: StringContext = acc_gc.context().iter().cloned().collect();
new_acc.insert(StringContextElem::Built { new_acc.insert(StringContextElem::Built {
drv_path: path_str, drv_path: path_str,
output: output_name, output: output_name,
}); });
let new_acc_gc = Gc::new(mc, NixString::with_context("", new_acc)); let new_acc_gc = Gc::new(mc, NixString::with_context("", new_acc));
m.replace(3, Value::new_gc(new_acc_gc)); m.replace(3, Value::new(new_acc_gc));
// Stack: [strVal, attrs, idx, acc, list, oidx, outElem] -> drop outElem, // Stack: [strVal, attrs, idx, acc, list, oidx, outElem] -> drop outElem,
// bump oidx in place. // bump oidx in place.
let _ = m.pop(); let _ = m.pop();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let oidx = m.peek(0).as_inline::<i32>().unwrap(); let oidx = m.peek(0).downcast::<i32>().unwrap();
m.replace(0, Value::new_inline(oidx + 1)); m.replace(0, Value::new(oidx + 1));
reader.set_pc(Continuation::PAppendContextOutputElementLoop.ip() as usize); reader.set_pc(Continuation::PAppendContextOutputElementLoop.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -424,7 +424,7 @@ fn append_context_finalize<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
// Stack: [strVal, attrs, idx, acc] // Stack: [strVal, attrs, idx, acc]
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let acc_gc = m.pop().as_gc::<NixString>().unwrap(); let acc_gc = m.pop().downcast::<NixString>().unwrap();
let _ = m.pop(); // idx let _ = m.pop(); // idx
let _ = m.pop(); // attrs let _ = m.pop(); // attrs
let str_val_raw = m.pop(); let str_val_raw = m.pop();
@@ -438,10 +438,10 @@ fn append_context_finalize<'gc, M: Machine<'gc>>(
let context: StringContext = acc_gc.context().iter().cloned().collect(); let context: StringContext = acc_gc.context().iter().cloned().collect();
let result = if context.is_empty() { let result = if context.is_empty() {
let sid = ctx.intern_string(s_str); let sid = ctx.intern_string(s_str);
Value::new_inline(sid) Value::new(sid)
} else { } else {
let ns = Gc::new(mc, NixString::with_context(s_str, context)); let ns = Gc::new(mc, NixString::with_context(s_str, context));
Value::new_gc(ns) Value::new(ns)
}; };
m.return_from_primop(result, reader) m.return_from_primop(result, reader)
} }
+28 -28
View File
@@ -44,14 +44,14 @@ pub fn deep_seq_force_top<'gc, M: Machine<'gc>>(
let e1 = m.peek_forced(1); let e1 = m.peek_forced(1);
let children: SmallVec<_> = if let Some(attrs) = e1.as_gc::<AttrSet>() { let children: SmallVec<_> = if let Some(attrs) = e1.downcast::<AttrSet>() {
let attrs = &attrs.entries; let attrs = &attrs.entries;
if attrs.is_empty() { if attrs.is_empty() {
SmallVec::new() SmallVec::new()
} else { } else {
attrs.iter().map(|&(_, v)| v).collect() attrs.iter().map(|&(_, v)| v).collect()
} }
} else if let Some(list) = e1.as_gc::<List<'gc>>() { } else if let Some(list) = e1.downcast::<List>() {
let inner = list.inner.borrow(); let inner = list.inner.borrow();
if inner.is_empty() { if inner.is_empty() {
SmallVec::new() SmallVec::new()
@@ -69,15 +69,15 @@ pub fn deep_seq_force_top<'gc, M: Machine<'gc>>(
} }
let count = children.len() as i32; let count = children.len() as i32;
let seen: Gc<'gc, List<'gc>> = Gc::new(mc, List::default()); let seen = Gc::new(mc, List::default());
let worklist: Gc<'gc, List<'gc>> = List::new(mc, children); let worklist = List::new(mc, children);
let e2 = m.pop(); let e2 = m.pop();
let _ = m.pop(); let _ = m.pop();
m.push(e2); m.push(e2);
m.push(Value::new_gc(seen)); m.push(Value::new(seen));
m.push(Value::new_gc(worklist)); m.push(Value::new(worklist));
m.push(Value::new_inline(count)); m.push(Value::new(count));
reader.set_pc(Continuation::PDeepSeqPush.ip() as usize); reader.set_pc(Continuation::PDeepSeqPush.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -89,7 +89,7 @@ pub fn deep_seq_push<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
// stack: [e2, seen, worklist, counter] // stack: [e2, seen, worklist, counter]
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let counter = m.peek(0).as_inline::<i32>().unwrap(); let counter = m.peek(0).downcast::<i32>().unwrap();
if counter == 0 { if counter == 0 {
let _ = m.pop(); // counter let _ = m.pop(); // counter
let _ = m.pop(); // worklist let _ = m.pop(); // worklist
@@ -99,10 +99,10 @@ pub fn deep_seq_push<'gc, M: Machine<'gc>>(
} }
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let worklist = m.peek_forced(1).as_gc::<List<'gc>>().unwrap(); let worklist = m.peek_forced(1).downcast::<List>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let item = worklist.unlock(mc).borrow_mut().pop().unwrap(); let item = worklist.unlock(mc).borrow_mut().pop().unwrap();
m.replace(0, Value::new_inline(counter - 1)); m.replace(0, Value::new(counter - 1));
m.push(item); m.push(item);
// force item at TOS, resume at DeepSeqLoop after force // force item at TOS, resume at DeepSeqLoop after force
@@ -119,17 +119,17 @@ pub fn deep_seq_loop<'gc, M: Machine<'gc>>(
// stack after pop: [e2, seen, worklist, counter] // stack after pop: [e2, seen, worklist, counter]
let item = m.pop(); let item = m.pop();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let counter = m.peek(0).as_inline::<i32>().unwrap(); let counter = m.peek(0).downcast::<i32>().unwrap();
let mut added: usize = 0; let mut added: usize = 0;
if let Some(attrs) = item.as_gc::<AttrSet>() { if let Some(attrs) = item.downcast::<AttrSet>() {
let attrs = &attrs.entries; let attrs = &attrs.entries;
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let seen = m.peek_forced(2).as_gc::<List<'gc>>().unwrap(); let seen = m.peek_forced(2).downcast::<List>().unwrap();
if !is_value_in_seen(seen, item) { if !is_value_in_seen(seen, item) {
add_value_to_seen(seen, mc, item); add_value_to_seen(seen, mc, item);
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let worklist = m.peek_forced(1).as_gc::<List<'gc>>().unwrap(); let worklist = m.peek_forced(1).downcast::<List>().unwrap();
{ {
let mut wl = worklist.unlock(mc).borrow_mut(); let mut wl = worklist.unlock(mc).borrow_mut();
for &(_, v) in attrs.iter() { for &(_, v) in attrs.iter() {
@@ -138,13 +138,13 @@ pub fn deep_seq_loop<'gc, M: Machine<'gc>>(
added = attrs.len(); added = attrs.len();
} }
} }
} else if let Some(list) = item.as_gc::<List<'gc>>() { } else if let Some(list) = item.downcast::<List>() {
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let seen = m.peek_forced(2).as_gc::<List<'gc>>().unwrap(); let seen = m.peek_forced(2).downcast::<List>().unwrap();
if !is_value_in_seen(seen, item) { if !is_value_in_seen(seen, item) {
add_value_to_seen(seen, mc, item); add_value_to_seen(seen, mc, item);
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let worklist = m.peek_forced(1).as_gc::<List<'gc>>().unwrap(); let worklist = m.peek_forced(1).downcast::<List>().unwrap();
{ {
let inner = list.inner.borrow(); let inner = list.inner.borrow();
let mut wl = worklist.unlock(mc).borrow_mut(); let mut wl = worklist.unlock(mc).borrow_mut();
@@ -156,7 +156,7 @@ pub fn deep_seq_loop<'gc, M: Machine<'gc>>(
} }
} }
m.replace(0, Value::new_inline(counter + added as i32)); m.replace(0, Value::new(counter + added as i32));
reader.set_pc(Continuation::PDeepSeqPush.ip() as usize); reader.set_pc(Continuation::PDeepSeqPush.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -170,10 +170,10 @@ pub fn force_result_shallow<'gc, M: Machine<'gc>>(
m.force_slot(0, reader, mc)?; m.force_slot(0, reader, mc)?;
let val = m.peek_forced(0); let val = m.peek_forced(0);
let (count, has_children) = if let Some(attrs) = val.as_gc::<AttrSet>() { let (count, has_children) = if let Some(attrs) = val.downcast::<AttrSet>() {
let len = attrs.entries.len(); let len = attrs.entries.len();
(len, len > 0) (len, len > 0)
} else if let Some(list) = val.as_gc::<List<'gc>>() { } else if let Some(list) = val.downcast::<List>() {
let len = list.inner.borrow().len(); let len = list.inner.borrow().len();
(len, len > 0) (len, len > 0)
} else { } else {
@@ -185,8 +185,8 @@ pub fn force_result_shallow<'gc, M: Machine<'gc>>(
return m.finish_ok(ctx.convert_value(val)); return m.finish_ok(ctx.convert_value(val));
} }
m.push(Value::new_inline(0i32)); m.push(Value::new(0i32));
m.push(Value::new_inline(count as i32)); m.push(Value::new(count as i32));
reader.set_pc(Continuation::ForceResultShallowPush.ip() as usize); reader.set_pc(Continuation::ForceResultShallowPush.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -198,9 +198,9 @@ pub fn force_result_shallow_push<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(1).as_inline::<i32>().unwrap(); let idx = m.peek(1).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let len = m.peek(0).as_inline::<i32>().unwrap(); let len = m.peek(0).downcast::<i32>().unwrap();
if idx == len { if idx == len {
let _ = m.pop(); // len let _ = m.pop(); // len
@@ -210,16 +210,16 @@ pub fn force_result_shallow_push<'gc, M: Machine<'gc>>(
} }
let val = m.peek_forced(2); let val = m.peek_forced(2);
let child = if let Some(attrs) = val.as_gc::<AttrSet>() { let child = if let Some(attrs) = val.downcast::<AttrSet>() {
attrs.entries.get(idx as usize).map(|&(_, v)| v) attrs.entries.get(idx as usize).map(|&(_, v)| v)
} else if let Some(list) = val.as_gc::<List<'gc>>() { } else if let Some(list) = val.downcast::<List>() {
list.inner.borrow().get(idx as usize).copied() list.inner.borrow().get(idx as usize).copied()
} else { } else {
None None
}; };
if let Some(child) = child { if let Some(child) = child {
m.replace(1, Value::new_inline(idx + 1)); m.replace(1, Value::new(idx + 1));
m.push(child); m.push(child);
m.force_slot_to_pc( m.force_slot_to_pc(
0, 0,
@@ -349,7 +349,7 @@ pub fn call_pattern<'gc, M: Machine<'gc>>(
let new_env = Gc::new( let new_env = Gc::new(
mc, mc,
RefLock::new(Env::with_arg(Value::new_gc(attrset), n_locals, env)), RefLock::new(Env::with_arg(Value::new(attrset), n_locals, env)),
); );
reader.set_pc(ip as usize); reader.set_pc(ip as usize);
m.set_env(new_env); m.set_env(new_env);
+3 -3
View File
@@ -16,8 +16,8 @@ pub fn to_string<'gc, M: Machine<'gc>>(
if val.is::<StringId>() || val.is::<NixString>() { if val.is::<StringId>() || val.is::<NixString>() {
return m.return_from_primop(val.relax(), reader); return m.return_from_primop(val.relax(), reader);
} }
if let Some(p) = val.as_inline::<Path>() { if let Some(p) = val.downcast::<Path>() {
return m.return_from_primop(Value::new_inline(p.0), reader); return m.return_from_primop(Value::new(p.0), reader);
} }
// TODO: derivations / `__toString` / `outPath`, // TODO: derivations / `__toString` / `outPath`,
// numbers, lists. // numbers, lists.
@@ -47,5 +47,5 @@ pub fn type_of<'gc, M: Machine<'gc>>(
NixType::Thunk => unreachable!("forced"), NixType::Thunk => unreachable!("forced"),
}; };
let sid = ctx.intern_string(name); let sid = ctx.intern_string(name);
m.return_from_primop(Value::new_inline(sid), reader) m.return_from_primop(Value::new(sid), reader)
} }
+22 -19
View File
@@ -17,11 +17,11 @@ pub fn start_eq<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
match shallow_eq(ctx, lhs, rhs) { match shallow_eq(ctx, lhs, rhs) {
ShallowEq::True => { ShallowEq::True => {
m.push(Value::new_inline(!negate)); m.push(Value::new(!negate));
Step::Continue(()) Step::Continue(())
} }
ShallowEq::False => { ShallowEq::False => {
m.push(Value::new_inline(negate)); m.push(Value::new(negate));
Step::Continue(()) Step::Continue(())
} }
ShallowEq::RecurseList(la, lb) => { ShallowEq::RecurseList(la, lb) => {
@@ -44,15 +44,15 @@ pub fn eq_step<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let rhs_q = m let rhs_q = m
.peek(0) .peek(0)
.as_gc::<List<'gc>>() .downcast::<List>()
.expect("eq state corrupted: rhs_queue"); .expect("eq state corrupted: rhs_queue");
let lhs_q = m let lhs_q = m
.peek(1) .peek(1)
.as_gc::<List<'gc>>() .downcast::<List>()
.expect("eq state corrupted: lhs_queue"); .expect("eq state corrupted: lhs_queue");
let result = m let result = m
.peek(2) .peek(2)
.as_inline::<bool>() .downcast::<bool>()
.expect("eq state corrupted: result"); .expect("eq state corrupted: result");
if !result || lhs_q.inner.borrow().is_empty() { if !result || lhs_q.inner.borrow().is_empty() {
@@ -92,13 +92,13 @@ fn finalize<'gc, M: Machine<'gc>>(m: &mut M, reader: &mut BytecodeReader<'_>) ->
let _ = m.pop(); let _ = m.pop();
let result = m let result = m
.pop() .pop()
.as_inline::<bool>() .downcast::<bool>()
.expect("eq state corrupted: result"); .expect("eq state corrupted: result");
let negate = m let negate = m
.pop() .pop()
.as_inline::<bool>() .downcast::<bool>()
.expect("eq state corrupted: negate"); .expect("eq state corrupted: negate");
m.return_from_primop(Value::new_inline(result ^ negate), reader) m.return_from_primop(Value::new(result ^ negate), reader)
} }
fn apply_pair<'gc, M: Machine<'gc>>( fn apply_pair<'gc, M: Machine<'gc>>(
@@ -111,7 +111,7 @@ fn apply_pair<'gc, M: Machine<'gc>>(
match shallow_eq(ctx, lhs, rhs) { match shallow_eq(ctx, lhs, rhs) {
ShallowEq::True => {} ShallowEq::True => {}
ShallowEq::False => { ShallowEq::False => {
m.replace(2, Value::new_inline(false)); m.replace(2, Value::new(false));
} }
ShallowEq::RecurseList(la, lb) => { ShallowEq::RecurseList(la, lb) => {
extend_queues( extend_queues(
@@ -140,11 +140,11 @@ where
{ {
let rhs_q = m let rhs_q = m
.peek(0) .peek(0)
.as_gc::<List<'gc>>() .downcast::<List>()
.expect("eq state corrupted: rhs_queue"); .expect("eq state corrupted: rhs_queue");
let lhs_q = m let lhs_q = m
.peek(1) .peek(1)
.as_gc::<List<'gc>>() .downcast::<List>()
.expect("eq state corrupted: lhs_queue"); .expect("eq state corrupted: lhs_queue");
let mut lq = lhs_q.unlock(mc).borrow_mut(); let mut lq = lhs_q.unlock(mc).borrow_mut();
let mut rq = rhs_q.unlock(mc).borrow_mut(); let mut rq = rhs_q.unlock(mc).borrow_mut();
@@ -169,10 +169,10 @@ fn enter_eq_machine<'gc, M: Machine<'gc>>(
env: m.env(), env: m.env(),
}); });
m.inc_call_depth(); m.inc_call_depth();
m.push(Value::new_inline(negate)); m.push(Value::new(negate));
m.push(Value::new_inline(true)); m.push(Value::new(true));
m.push(Value::new_gc(List::new(mc, lhs_init))); m.push(Value::new(List::new(mc, lhs_init)));
m.push(Value::new_gc(List::new(mc, rhs_init))); m.push(Value::new(List::new(mc, rhs_init)));
reader.set_pc(Continuation::EqStep.ip() as usize); reader.set_pc(Continuation::EqStep.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -198,25 +198,28 @@ fn shallow_eq<'gc>(
}; };
return bool_outcome(eq); return bool_outcome(eq);
} }
if let (Some(a), Some(b)) = (lhs.as_inline::<bool>(), rhs.as_inline::<bool>()) { if let (Some(a), Some(b)) = (lhs.downcast::<bool>(), rhs.downcast::<bool>()) {
return bool_outcome(a == b); return bool_outcome(a == b);
} }
if lhs.is::<Null>() && rhs.is::<Null>() { if lhs.is::<Null>() && rhs.is::<Null>() {
return ShallowEq::True; return ShallowEq::True;
} }
if let (Some(a), Some(b)) = (lhs.as_inline::<Path>(), rhs.as_inline::<Path>()) { if let (Some(a), Some(b)) = (lhs.downcast::<Path>(), rhs.downcast::<Path>()) {
return bool_outcome(a.0 == b.0); return bool_outcome(a.0 == b.0);
} }
if let (Some(a), Some(b)) = (ctx.get_string(lhs), ctx.get_string(rhs)) { if let (Some(a), Some(b)) = (ctx.get_string(lhs), ctx.get_string(rhs)) {
return bool_outcome(a == b); return bool_outcome(a == b);
} }
if let (Some(a), Some(b)) = (lhs.as_gc::<List<'gc>>(), rhs.as_gc::<List<'gc>>()) { if let (Some(a), Some(b)) = (lhs.downcast::<List>(), rhs.downcast::<List>()) {
if a.inner.borrow().len() != b.inner.borrow().len() { if a.inner.borrow().len() != b.inner.borrow().len() {
return ShallowEq::False; return ShallowEq::False;
} }
return ShallowEq::RecurseList(a, b); return ShallowEq::RecurseList(a, b);
} }
if let (Some(a), Some(b)) = (lhs.as_gc::<AttrSet<'gc>>(), rhs.as_gc::<AttrSet<'gc>>()) { if let (Some(a), Some(b)) = (
lhs.downcast::<AttrSet<'gc>>(),
rhs.downcast::<AttrSet<'gc>>(),
) {
let ae = &a.entries; let ae = &a.entries;
let be = &b.entries; let be = &b.entries;
if ae.len() != be.len() { if ae.len() != be.len() {
+5 -5
View File
@@ -40,7 +40,7 @@ pub fn import<'gc, M: Machine<'gc>>(
// finalizer can use it as the cache key. The slot we pop here was // finalizer can use it as the cache key. The slot we pop here was
// freed by `force_and_retry`, so we simply push. // freed by `force_and_retry`, so we simply push.
let path_sid = ctx.intern_string(abs.to_string_lossy()); let path_sid = ctx.intern_string(abs.to_string_lossy());
m.push(Value::new_inline(path_sid)); m.push(Value::new(path_sid));
let env = m.env(); let env = m.env();
m.push_call_frame(CallFrame { m.push_call_frame(CallFrame {
pc: Continuation::PImportFinalize.ip() as usize, pc: Continuation::PImportFinalize.ip() as usize,
@@ -63,7 +63,7 @@ pub fn import_finalize<'gc, M: Machine<'gc>>(
// stack: [path_sid, return_value] // stack: [path_sid, return_value]
let val = m.pop(); let val = m.pop();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let path_sid = m.pop().as_inline::<StringId>().unwrap(); let path_sid = m.pop().downcast::<StringId>().unwrap();
// The cache key is keyed by the absolute path string we interned in // The cache key is keyed by the absolute path string we interned in
// `import`. Resolve it back to the host PathBuf. // `import`. Resolve it back to the host PathBuf.
let path_str = ctx.resolve_string(path_sid).to_owned(); let path_str = ctx.resolve_string(path_sid).to_owned();
@@ -107,7 +107,7 @@ pub fn scoped_import<'gc, M: Machine<'gc>>(
}; };
let keys: HashSet<StringId> = scope_attrs.entries.iter().map(|&(k, _)| k).collect(); let keys: HashSet<StringId> = scope_attrs.entries.iter().map(|&(k, _)| k).collect();
let slot_id = m.scope_slots_push(Value::new_gc(scope_attrs)); let slot_id = m.scope_slots_push(Value::new(scope_attrs));
let env = m.env(); let env = m.env();
m.push_call_frame(CallFrame { m.push_call_frame(CallFrame {
@@ -146,7 +146,7 @@ pub fn path_exists<'gc, M: Machine<'gc>>(
let path_val = m.force_and_retry::<StrictValue>(reader, mc)?; let path_val = m.force_and_retry::<StrictValue>(reader, mc)?;
// pathExists requires an absolute path. A `Path` value is // pathExists requires an absolute path. A `Path` value is
// always absolute; a string is accepted only if it starts with `/`. // always absolute; a string is accepted only if it starts with `/`.
let (path, is_path_value) = if let Some(p) = path_val.as_inline::<Path>() { let (path, is_path_value) = if let Some(p) = path_val.downcast::<Path>() {
(ctx.resolve_string(p.0).to_owned(), true) (ctx.resolve_string(p.0).to_owned(), true)
} else if let Some(s) = ctx.get_string(path_val) { } else if let Some(s) = ctx.get_string(path_val) {
(s.to_owned(), false) (s.to_owned(), false)
@@ -171,7 +171,7 @@ pub fn path_exists<'gc, M: Machine<'gc>>(
} else { } else {
std::fs::symlink_metadata(p).is_ok() std::fs::symlink_metadata(p).is_ok()
}; };
m.return_from_primop(Value::new_inline(exists), reader) m.return_from_primop(Value::new(exists), reader)
} }
/// Convert the user-supplied path string into an absolute, dotted-segment /// Convert the user-supplied path string into an absolute, dotted-segment
+40 -35
View File
@@ -8,7 +8,7 @@ pub fn filter_force_list<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
m.force_slot(0, reader, mc)?; m.force_slot(0, reader, mc)?;
let list = match m.peek_forced(0).expect_gc::<List>() { let list = match m.peek_forced(0).expect::<List>() {
Ok(list) => list, Ok(list) => list,
Err(got) => return m.finish_type_err(NixType::List, got), Err(got) => return m.finish_type_err(NixType::List, got),
}; };
@@ -18,8 +18,8 @@ pub fn filter_force_list<'gc, M: Machine<'gc>>(
return m.return_from_primop(val, reader); return m.return_from_primop(val, reader);
} }
// prepare stack layout: [ pred list idx acc ] // prepare stack layout: [ pred list idx acc ]
m.push(Value::new_inline(0)); m.push(Value::new(0));
m.push(Value::new_gc(List::new_gc(mc))); m.push(Value::new(List::new_gc(mc)));
reader.set_pc(Continuation::PFilterCallPred.ip() as usize); reader.set_pc(Continuation::PFilterCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -32,9 +32,9 @@ pub fn filter_call_pred<'gc, M: Machine<'gc>>(
m.force_slot(3, reader, mc)?; m.force_slot(3, reader, mc)?;
let pred = m.peek_forced(3); let pred = m.peek_forced(3);
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(1).as_inline::<i32>().unwrap(); let idx = m.peek(1).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let elem = m.peek_forced(2).as_gc::<List>().unwrap().inner.borrow()[idx as usize]; let elem = m.peek_forced(2).downcast::<List>().unwrap().inner.borrow()[idx as usize];
m.push(pred.relax()); m.push(pred.relax());
m.call(reader, mc, elem, Continuation::PFilterCheck.ip() as usize) m.call(reader, mc, elem, Continuation::PFilterCheck.ip() as usize)
} }
@@ -46,12 +46,12 @@ pub fn filter_check<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let ret = m.force_and_retry::<bool>(reader, mc)?; let ret = m.force_and_retry::<bool>(reader, mc)?;
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(1).as_inline::<i32>().unwrap(); let idx = m.peek(1).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let list = m.peek_forced(2).as_gc::<List>().unwrap(); let list = m.peek_forced(2).downcast::<List>().unwrap();
let list = list.inner.borrow(); let list = list.inner.borrow();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let acc = m.peek_forced(0).as_gc::<List>().unwrap(); let acc = m.peek_forced(0).downcast::<List>().unwrap();
if ret { if ret {
let mut acc = acc.unlock(mc).borrow_mut(); let mut acc = acc.unlock(mc).borrow_mut();
acc.push(list[idx as usize]); acc.push(list[idx as usize]);
@@ -63,7 +63,7 @@ pub fn filter_check<'gc, M: Machine<'gc>>(
let _ = m.pop(); // pred let _ = m.pop(); // pred
return m.return_from_primop(acc, reader); return m.return_from_primop(acc, reader);
} }
m.replace(1, Value::new_inline(idx + 1)); m.replace(1, Value::new(idx + 1));
reader.set_pc(Continuation::PFilterCallPred.ip() as usize); reader.set_pc(Continuation::PFilterCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -83,7 +83,7 @@ pub fn foldl_strict_entry<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
m.force_slot(0, reader, mc)?; m.force_slot(0, reader, mc)?;
let list_val = m.peek_forced(0); let list_val = m.peek_forced(0);
let Some(list) = list_val.as_gc::<List>() else { let Some(list) = list_val.downcast::<List>() else {
return m.finish_type_err(NixType::List, list_val.ty()); return m.finish_type_err(NixType::List, list_val.ty());
}; };
if list.inner.borrow().is_empty() { if list.inner.borrow().is_empty() {
@@ -94,7 +94,7 @@ pub fn foldl_strict_entry<'gc, M: Machine<'gc>>(
let list_val = m.pop(); let list_val = m.pop();
let nul_val = m.pop(); let nul_val = m.pop();
m.push(list_val); m.push(list_val);
m.push(Value::new_inline(0i32)); m.push(Value::new(0i32));
m.push(nul_val); m.push(nul_val);
reader.set_pc(Continuation::PFoldlStrictCall1.ip() as usize); reader.set_pc(Continuation::PFoldlStrictCall1.ip() as usize);
Step::Continue(()) Step::Continue(())
@@ -119,7 +119,12 @@ pub fn foldl_strict_call1<'gc, M: Machine<'gc>>(
let op = m.peek_forced(3); let op = m.peek_forced(3);
let acc = m.peek(0); let acc = m.peek(0);
m.push(op.relax()); m.push(op.relax());
m.call(reader, mc, acc, Continuation::PFoldlStrictCall2.ip() as usize) m.call(
reader,
mc,
acc,
Continuation::PFoldlStrictCall2.ip() as usize,
)
} }
pub fn foldl_strict_call2<'gc, M: Machine<'gc>>( pub fn foldl_strict_call2<'gc, M: Machine<'gc>>(
@@ -128,9 +133,9 @@ pub fn foldl_strict_call2<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(2).as_inline::<i32>().unwrap(); let idx = m.peek(2).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let list = m.peek_forced(3).as_gc::<List>().unwrap(); let list = m.peek_forced(3).downcast::<List>().unwrap();
let elem = list.inner.borrow()[idx as usize]; let elem = list.inner.borrow()[idx as usize];
m.call( m.call(
reader, reader,
@@ -148,9 +153,9 @@ pub fn foldl_strict_update<'gc, M: Machine<'gc>>(
let result = m.pop(); let result = m.pop();
m.replace(0, result); m.replace(0, result);
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(1).as_inline::<i32>().unwrap(); let idx = m.peek(1).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let list = m.peek_forced(2).as_gc::<List>().unwrap(); let list = m.peek_forced(2).downcast::<List>().unwrap();
let len = list.inner.borrow().len(); let len = list.inner.borrow().len();
if (idx as usize) + 1 == len { if (idx as usize) + 1 == len {
let acc = m.pop(); let acc = m.pop();
@@ -159,7 +164,7 @@ pub fn foldl_strict_update<'gc, M: Machine<'gc>>(
let _ = m.pop(); // op let _ = m.pop(); // op
return m.return_from_primop(acc, reader); return m.return_from_primop(acc, reader);
} }
m.replace(1, Value::new_inline(idx + 1)); m.replace(1, Value::new(idx + 1));
reader.set_pc(Continuation::PFoldlStrictCall1.ip() as usize); reader.set_pc(Continuation::PFoldlStrictCall1.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -170,7 +175,7 @@ pub fn all_entry<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
m.force_slot(0, reader, mc)?; m.force_slot(0, reader, mc)?;
let list = match m.peek_forced(0).expect_gc::<List>() { let list = match m.peek_forced(0).expect::<List>() {
Ok(list) => list, Ok(list) => list,
Err(got) => return m.finish_type_err(NixType::List, got), Err(got) => return m.finish_type_err(NixType::List, got),
}; };
@@ -179,10 +184,10 @@ pub fn all_entry<'gc, M: Machine<'gc>>(
if list.inner.borrow().is_empty() { if list.inner.borrow().is_empty() {
let _list = m.pop(); let _list = m.pop();
let _pred = m.pop(); let _pred = m.pop();
return m.return_from_primop(Value::new_inline(true), reader); return m.return_from_primop(Value::new(true), reader);
} }
// prepare stack layout: [ pred list idx ] // prepare stack layout: [ pred list idx ]
m.push(Value::new_inline(0)); m.push(Value::new(0));
reader.set_pc(Continuation::PAllCallPred.ip() as usize); reader.set_pc(Continuation::PAllCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -194,9 +199,9 @@ pub fn all_call_pred<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let pred = m.peek_forced(2); let pred = m.peek_forced(2);
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(0).as_inline::<i32>().unwrap(); let idx = m.peek(0).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let elem = m.peek_forced(1).as_gc::<List>().unwrap().inner.borrow()[idx as usize]; let elem = m.peek_forced(1).downcast::<List>().unwrap().inner.borrow()[idx as usize];
m.push(pred.relax()); m.push(pred.relax());
m.call(reader, mc, elem, Continuation::PAllCheck.ip() as usize) m.call(reader, mc, elem, Continuation::PAllCheck.ip() as usize)
} }
@@ -208,17 +213,17 @@ pub fn all_check<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let ret = m.force_and_retry::<bool>(reader, mc)?; let ret = m.force_and_retry::<bool>(reader, mc)?;
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(0).as_inline::<i32>().unwrap(); let idx = m.peek(0).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let list = m.peek_forced(1).as_gc::<List>().unwrap(); let list = m.peek_forced(1).downcast::<List>().unwrap();
let list = list.inner.borrow(); let list = list.inner.borrow();
if idx as usize == list.len() - 1 || !ret { if idx as usize == list.len() - 1 || !ret {
let _ = m.pop(); // idx let _ = m.pop(); // idx
let _ = m.pop(); // list let _ = m.pop(); // list
let _ = m.pop(); // pred let _ = m.pop(); // pred
return m.return_from_primop(Value::new_inline(ret), reader); return m.return_from_primop(Value::new(ret), reader);
} }
m.replace(0, Value::new_inline(idx + 1)); m.replace(0, Value::new(idx + 1));
reader.set_pc(Continuation::PAllCallPred.ip() as usize); reader.set_pc(Continuation::PAllCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -229,7 +234,7 @@ pub fn any_entry<'gc, M: Machine<'gc>>(
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
m.force_slot(0, reader, mc)?; m.force_slot(0, reader, mc)?;
let list = match m.peek_forced(0).expect_gc::<List>() { let list = match m.peek_forced(0).expect::<List>() {
Ok(list) => list, Ok(list) => list,
Err(got) => return m.finish_type_err(NixType::List, got), Err(got) => return m.finish_type_err(NixType::List, got),
}; };
@@ -238,10 +243,10 @@ pub fn any_entry<'gc, M: Machine<'gc>>(
if list.inner.borrow().is_empty() { if list.inner.borrow().is_empty() {
let _list = m.pop(); let _list = m.pop();
let _pred = m.pop(); let _pred = m.pop();
return m.return_from_primop(Value::new_inline(false), reader); return m.return_from_primop(Value::new(false), reader);
} }
// prepare stack layout: [ pred list idx ] // prepare stack layout: [ pred list idx ]
m.push(Value::new_inline(0)); m.push(Value::new(0));
reader.set_pc(Continuation::PAnyCallPred.ip() as usize); reader.set_pc(Continuation::PAnyCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -253,9 +258,9 @@ pub fn any_call_pred<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let pred = m.peek_forced(2); let pred = m.peek_forced(2);
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(0).as_inline::<i32>().unwrap(); let idx = m.peek(0).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let elem = m.peek_forced(1).as_gc::<List>().unwrap().inner.borrow()[idx as usize]; let elem = m.peek_forced(1).downcast::<List>().unwrap().inner.borrow()[idx as usize];
m.push(pred.relax()); m.push(pred.relax());
m.call(reader, mc, elem, Continuation::PAnyCheck.ip() as usize) m.call(reader, mc, elem, Continuation::PAnyCheck.ip() as usize)
} }
@@ -267,17 +272,17 @@ pub fn any_check<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let ret = m.force_and_retry::<bool>(reader, mc)?; let ret = m.force_and_retry::<bool>(reader, mc)?;
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let idx = m.peek(0).as_inline::<i32>().unwrap(); let idx = m.peek(0).downcast::<i32>().unwrap();
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
let list = m.peek_forced(1).as_gc::<List>().unwrap(); let list = m.peek_forced(1).downcast::<List>().unwrap();
let list = list.inner.borrow(); let list = list.inner.borrow();
if idx as usize == list.len() - 1 || ret { if idx as usize == list.len() - 1 || ret {
let _ = m.pop(); // idx let _ = m.pop(); // idx
let _ = m.pop(); // list let _ = m.pop(); // list
let _ = m.pop(); // pred let _ = m.pop(); // pred
return m.return_from_primop(Value::new_inline(ret), reader); return m.return_from_primop(Value::new(ret), reader);
} }
m.replace(0, Value::new_inline(idx + 1)); m.replace(0, Value::new(idx + 1));
reader.set_pc(Continuation::PAnyCallPred.ip() as usize); reader.set_pc(Continuation::PAnyCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
+4 -4
View File
@@ -13,8 +13,8 @@ pub fn to_path<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
// coerce to path THEN TO STRING // coerce to path THEN TO STRING
let val = m.force_and_retry::<StrictValue>(reader, mc)?; let val = m.force_and_retry::<StrictValue>(reader, mc)?;
if let Some(Path(s)) = val.as_inline::<Path>() { if let Some(Path(s)) = val.downcast::<Path>() {
return m.return_from_primop(Value::new_inline(s), reader); return m.return_from_primop(Value::new(s), reader);
} }
let Some(s) = ctx.get_string(val) else { let Some(s) = ctx.get_string(val) else {
return m.finish_err(Error::eval_error(format!( return m.finish_err(Error::eval_error(format!(
@@ -29,7 +29,7 @@ pub fn to_path<'gc, M: Machine<'gc>>(
} }
let canon = canon_path_str(s); let canon = canon_path_str(s);
let sid = ctx.intern_string(canon); let sid = ctx.intern_string(canon);
m.return_from_primop(Value::new_inline(sid), reader) m.return_from_primop(Value::new(sid), reader)
} }
pub fn is_path<'gc, M: Machine<'gc>>( pub fn is_path<'gc, M: Machine<'gc>>(
@@ -39,5 +39,5 @@ pub fn is_path<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let val = m.force_and_retry::<StrictValue>(reader, mc)?; let val = m.force_and_retry::<StrictValue>(reader, mc)?;
let is_path = val.is::<Path>(); let is_path = val.is::<Path>();
m.return_from_primop(Value::new_inline(is_path), reader) m.return_from_primop(Value::new(is_path), reader)
} }