Compare commits

..
2 Commits
31 changed files with 819 additions and 702 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",
] ]
+3 -3
View File
@@ -2,7 +2,7 @@ use std::fmt::Write;
use colored::Colorize as _; use colored::Colorize as _;
use crate::{InstructionPtr, Op, OperandType, PrimOpPhase}; 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;
@@ -294,8 +294,8 @@ impl<'a, Ctx: DisassemblerContext> Disassembler<'a, Ctx> {
self.read_operand_data(); self.read_operand_data();
("Call", "arg=?".into()) ("Call", "arg=?".into())
} }
Op::DispatchPrimOp => { Op::DispatchCont => {
let phase = PrimOpPhase::try_from(self.read_u8()).expect("invalid primop phase"); let phase = Continuation::try_from(self.read_u8()).expect("invalid primop phase");
("DispatchPrimOp", format!("phase={phase:?}")) ("DispatchPrimOp", format!("phase={phase:?}"))
} }
+233 -232
View File
@@ -31,7 +31,7 @@ pub enum Op {
MakePatternClosure, MakePatternClosure,
Call, Call,
DispatchPrimOp, DispatchCont,
MakeAttrs, MakeAttrs,
MakeEmptyAttrs, MakeEmptyAttrs,
@@ -133,128 +133,140 @@ pub enum OperandData {
#[repr(u8)] #[repr(u8)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum PrimOpPhase { pub enum Continuation {
Abort, // primops
Add, PAbort,
AddErrorContext, PAdd,
PAddErrorContext,
All, PAll,
AllCallPred, PAllCallPred,
AllCheck, PAllCheck,
Any, PAny,
AnyCallPred, PAnyCallPred,
AnyCheck, PAnyCheck,
AppendContext, PAppendContext,
AttrNames, PAppendContextLoop,
AttrValues, PAppendContextEntryForced,
BaseNameOf, PAppendContextOutputsForced,
BitAnd, PAppendContextOutputElementLoop,
BitOr, PAppendContextOutputElementForced,
BitXor,
Break,
CatAttrs,
Ceil,
CompareVersions,
ConcatLists,
ConcatMap,
ConcatStringsSep,
ConvertHash,
DeepSeq, PAttrNames,
DeepSeqPush, PAttrValues,
DeepSeqLoop, PBaseNameOf,
PBitAnd,
PBitOr,
PBitXor,
PBreak,
PCatAttrs,
PCeil,
PCompareVersions,
PConcatLists,
PConcatMap,
PConcatStringsSep,
PConvertHash,
Derivation, PDeepSeq,
DerivationStrict, PDeepSeqPush,
DirOf, PDeepSeqLoop,
Div,
Elem,
ElemAt,
FetchGit,
FetchMercurial,
FetchTarball,
FetchTree,
FetchUrl,
FilterForceList, PDerivation,
FilterCallPred, PDerivationStrict,
FilterCheck, PDirOf,
PDiv,
PElem,
PElemAt,
PFetchGit,
PFetchMercurial,
PFetchTarball,
PFetchTree,
PFetchUrl,
FilterSource, PFilterForceList,
FindFile, PFilterCallPred,
Floor, PFilterCheck,
FoldlStrict,
FoldlStrictEmpty, PFilterSource,
FoldlStrictCall1, PFindFile,
FoldlStrictCall2, PFloor,
FoldlStrictUpdate, PFoldlStrict,
FromJSON, PFoldlStrictEmpty,
FromTOML, PFoldlStrictCall1,
FunctionArgs, PFoldlStrictCall2,
GenList, PFoldlStrictUpdate,
GenericClosure, PFromJSON,
GetAttr, PFromTOML,
GetContext, PFunctionArgs,
GetEnv, PGenList,
GroupBy, PGenericClosure,
HasAttr, PGetAttr,
HasContext, PGetContext,
HashFile, PGetEnv,
HashString, PGroupBy,
Head, PHasAttr,
Import, PHasContext,
IntersectAttrs, PHashFile,
IsAttrs, PHashString,
IsBool, PHead,
IsFloat,
IsFunction, PImport,
IsInt, PImportFinalize,
IsList, PScopedImport,
IsNull, PScopedImportFinalize,
IsPath,
IsString, PIntersectAttrs,
Length, PIsAttrs,
LessThan, PIsBool,
ListToAttrs, PIsFloat,
Map, PIsFunction,
MapAttrs, PIsInt,
Match, PIsList,
Mul, PIsNull,
ParseDrvName, PIsPath,
Partition, PIsString,
Path, PLength,
PathExists, PLessThan,
Placeholder, PListToAttrs,
ReadDir, PMap,
ReadFile, PMapAttrs,
ReadFileType, PMatch,
RemoveAttrs, PMul,
ReplaceStrings, PParseDrvName,
ScopedImport, PPartition,
Seq, PPath,
Sort, PPathExists,
Split, PPlaceholder,
SplitVersion, PReadDir,
StorePath, PReadFile,
StringLength, PReadFileType,
Sub, PRemoveAttrs,
Substring, PReplaceStrings,
Tail, PSeq,
Throw, PSort,
ToFile, PSplit,
ToJSON, PSplitVersion,
ToPath, PStorePath,
ToString, PStringLength,
ToXML, PSub,
Trace, PSubstring,
TryEval, PTail,
TypeOf, PThrow,
UnsafeDiscardStringContext, PToFile,
UnsafeGetAttrPos, PToJSON,
Warn, PToPath,
ZipAttrsWith, PToString,
PToXML,
PTrace,
PTryEval,
PTypeOf,
PUnsafeDiscardStringContext,
PUnsafeGetAttrPos,
PWarn,
PZipAttrsWith,
PUnsafeDiscardOutputDependency,
ForceResultShallow, ForceResultShallow,
ForceResultShallowPush, ForceResultShallowPush,
@@ -268,21 +280,10 @@ pub enum PrimOpPhase {
CallFunctor1, CallFunctor1,
CallFunctor2, CallFunctor2,
ImportFinalize,
ScopedImportFinalize,
AppendContextLoop,
AppendContextEntryForced,
AppendContextOutputsForced,
AppendContextOutputElementLoop,
AppendContextOutputElementForced,
UnsafeDiscardOutputDependency,
Illegal, Illegal,
} }
impl TryFrom<u8> for PrimOpPhase { impl TryFrom<u8> for Continuation {
type Error = u8; type Error = u8;
fn try_from(value: u8) -> Result<Self, Self::Error> { fn try_from(value: u8) -> Result<Self, Self::Error> {
@@ -294,113 +295,113 @@ impl TryFrom<u8> for PrimOpPhase {
} }
} }
impl PrimOpPhase { impl Continuation {
pub fn entry_for_builtin(id: BuiltinId) -> Self { pub fn entry_for_builtin(id: BuiltinId) -> Self {
use BuiltinId::*; use BuiltinId::*;
match id { match id {
Abort => Self::Abort, Abort => Self::PAbort,
Add => Self::Add, Add => Self::PAdd,
AddErrorContext => Self::AddErrorContext, AddErrorContext => Self::PAddErrorContext,
All => Self::All, All => Self::PAll,
Any => Self::Any, Any => Self::PAny,
AppendContext => Self::AppendContext, AppendContext => Self::PAppendContext,
AttrNames => Self::AttrNames, AttrNames => Self::PAttrNames,
AttrValues => Self::AttrValues, AttrValues => Self::PAttrValues,
BaseNameOf => Self::BaseNameOf, BaseNameOf => Self::PBaseNameOf,
BitAnd => Self::BitAnd, BitAnd => Self::PBitAnd,
BitOr => Self::BitOr, BitOr => Self::PBitOr,
BitXor => Self::BitXor, BitXor => Self::PBitXor,
Break => Self::Break, Break => Self::PBreak,
CatAttrs => Self::CatAttrs, CatAttrs => Self::PCatAttrs,
Ceil => Self::Ceil, Ceil => Self::PCeil,
CompareVersions => Self::CompareVersions, CompareVersions => Self::PCompareVersions,
ConcatLists => Self::ConcatLists, ConcatLists => Self::PConcatLists,
ConcatMap => Self::ConcatMap, ConcatMap => Self::PConcatMap,
ConcatStringsSep => Self::ConcatStringsSep, ConcatStringsSep => Self::PConcatStringsSep,
ConvertHash => Self::ConvertHash, ConvertHash => Self::PConvertHash,
DeepSeq => Self::DeepSeq, DeepSeq => Self::PDeepSeq,
Derivation => Self::Derivation, Derivation => Self::PDerivation,
DerivationStrict => Self::DerivationStrict, DerivationStrict => Self::PDerivationStrict,
DirOf => Self::DirOf, DirOf => Self::PDirOf,
Div => Self::Div, Div => Self::PDiv,
Elem => Self::Elem, Elem => Self::PElem,
ElemAt => Self::ElemAt, ElemAt => Self::PElemAt,
FetchGit => Self::FetchGit, FetchGit => Self::PFetchGit,
FetchMercurial => Self::FetchMercurial, FetchMercurial => Self::PFetchMercurial,
FetchTarball => Self::FetchTarball, FetchTarball => Self::PFetchTarball,
FetchTree => Self::FetchTree, FetchTree => Self::PFetchTree,
FetchUrl => Self::FetchUrl, FetchUrl => Self::PFetchUrl,
Filter => Self::FilterForceList, Filter => Self::PFilterForceList,
FilterSource => Self::FilterSource, FilterSource => Self::PFilterSource,
FindFile => Self::FindFile, FindFile => Self::PFindFile,
Floor => Self::Floor, Floor => Self::PFloor,
FoldlStrict => Self::FoldlStrict, FoldlStrict => Self::PFoldlStrict,
FromJSON => Self::FromJSON, FromJSON => Self::PFromJSON,
FromTOML => Self::FromTOML, FromTOML => Self::PFromTOML,
FunctionArgs => Self::FunctionArgs, FunctionArgs => Self::PFunctionArgs,
GenList => Self::GenList, GenList => Self::PGenList,
GenericClosure => Self::GenericClosure, GenericClosure => Self::PGenericClosure,
GetAttr => Self::GetAttr, GetAttr => Self::PGetAttr,
GetContext => Self::GetContext, GetContext => Self::PGetContext,
GetEnv => Self::GetEnv, GetEnv => Self::PGetEnv,
GroupBy => Self::GroupBy, GroupBy => Self::PGroupBy,
HasAttr => Self::HasAttr, HasAttr => Self::PHasAttr,
HasContext => Self::HasContext, HasContext => Self::PHasContext,
HashFile => Self::HashFile, HashFile => Self::PHashFile,
HashString => Self::HashString, HashString => Self::PHashString,
Head => Self::Head, Head => Self::PHead,
Import => Self::Import, Import => Self::PImport,
IntersectAttrs => Self::IntersectAttrs, IntersectAttrs => Self::PIntersectAttrs,
IsAttrs => Self::IsAttrs, IsAttrs => Self::PIsAttrs,
IsBool => Self::IsBool, IsBool => Self::PIsBool,
IsFloat => Self::IsFloat, IsFloat => Self::PIsFloat,
IsFunction => Self::IsFunction, IsFunction => Self::PIsFunction,
IsInt => Self::IsInt, IsInt => Self::PIsInt,
IsList => Self::IsList, IsList => Self::PIsList,
IsNull => Self::IsNull, IsNull => Self::PIsNull,
IsPath => Self::IsPath, IsPath => Self::PIsPath,
IsString => Self::IsString, IsString => Self::PIsString,
Length => Self::Length, Length => Self::PLength,
LessThan => Self::LessThan, LessThan => Self::PLessThan,
ListToAttrs => Self::ListToAttrs, ListToAttrs => Self::PListToAttrs,
Map => Self::Map, Map => Self::PMap,
MapAttrs => Self::MapAttrs, MapAttrs => Self::PMapAttrs,
Match => Self::Match, Match => Self::PMatch,
Mul => Self::Mul, Mul => Self::PMul,
ParseDrvName => Self::ParseDrvName, ParseDrvName => Self::PParseDrvName,
Partition => Self::Partition, Partition => Self::PPartition,
Path => Self::Path, Path => Self::PPath,
PathExists => Self::PathExists, PathExists => Self::PPathExists,
Placeholder => Self::Placeholder, Placeholder => Self::PPlaceholder,
ReadDir => Self::ReadDir, ReadDir => Self::PReadDir,
ReadFile => Self::ReadFile, ReadFile => Self::PReadFile,
ReadFileType => Self::ReadFileType, ReadFileType => Self::PReadFileType,
RemoveAttrs => Self::RemoveAttrs, RemoveAttrs => Self::PRemoveAttrs,
ReplaceStrings => Self::ReplaceStrings, ReplaceStrings => Self::PReplaceStrings,
ScopedImport => Self::ScopedImport, ScopedImport => Self::PScopedImport,
Seq => Self::Seq, Seq => Self::PSeq,
Sort => Self::Sort, Sort => Self::PSort,
Split => Self::Split, Split => Self::PSplit,
SplitVersion => Self::SplitVersion, SplitVersion => Self::PSplitVersion,
StorePath => Self::StorePath, StorePath => Self::PStorePath,
StringLength => Self::StringLength, StringLength => Self::PStringLength,
Sub => Self::Sub, Sub => Self::PSub,
Substring => Self::Substring, Substring => Self::PSubstring,
Tail => Self::Tail, Tail => Self::PTail,
Throw => Self::Throw, Throw => Self::PThrow,
ToFile => Self::ToFile, ToFile => Self::PToFile,
ToJSON => Self::ToJSON, ToJSON => Self::PToJSON,
ToPath => Self::ToPath, ToPath => Self::PToPath,
ToString => Self::ToString, ToString => Self::PToString,
ToXML => Self::ToXML, ToXML => Self::PToXML,
Trace => Self::Trace, Trace => Self::PTrace,
TryEval => Self::TryEval, TryEval => Self::PTryEval,
TypeOf => Self::TypeOf, TypeOf => Self::PTypeOf,
UnsafeDiscardStringContext => Self::UnsafeDiscardStringContext, UnsafeDiscardStringContext => Self::PUnsafeDiscardStringContext,
UnsafeDiscardOutputDependency => Self::UnsafeDiscardOutputDependency, UnsafeDiscardOutputDependency => Self::PUnsafeDiscardOutputDependency,
UnsafeGetAttrPos => Self::UnsafeGetAttrPos, UnsafeGetAttrPos => Self::PUnsafeGetAttrPos,
Warn => Self::Warn, Warn => Self::PWarn,
ZipAttrsWith => Self::ZipAttrsWith, ZipAttrsWith => Self::PZipAttrsWith,
} }
} }
+8 -8
View File
@@ -1,5 +1,5 @@
use bumpalo::Bump; use bumpalo::Bump;
use fix_bytecode::{Const, InstructionPtr, Op, PrimOpPhase}; 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};
@@ -25,9 +25,9 @@ pub struct CodeState {
impl CodeState { impl CodeState {
pub fn new(strings: &mut DefaultStringInterner) -> Self { pub fn new(strings: &mut DefaultStringInterner) -> Self {
let global_env = crate::ir::new_global_env(strings); let global_env = crate::ir::new_global_env(strings);
let mut bytecode = Vec::with_capacity(PrimOpPhase::Illegal as usize * 2); let mut bytecode = Vec::with_capacity(Continuation::Illegal as usize * 2);
for phase in 0..=PrimOpPhase::Illegal as u8 { for phase in 0..=Continuation::Illegal as u8 {
bytecode.push(Op::DispatchPrimOp as u8); bytecode.push(Op::DispatchCont as u8);
bytecode.push(phase); bytecode.push(phase);
} }
Self { Self {
@@ -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,
+2 -2
View File
@@ -1,4 +1,4 @@
use fix_bytecode::{Const, InstructionPtr, Op, OperandType, PrimOpPhase}; 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;
@@ -80,7 +80,7 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
InlineOperand::Const(Const::PrimOp { InlineOperand::Const(Const::PrimOp {
id, id,
arity, arity,
dispatch_ip: PrimOpPhase::entry_for_builtin(id).ip(), dispatch_ip: Continuation::entry_for_builtin(id).ip(),
}) })
} }
BuiltinConst(id) => InlineOperand::BuiltinConst(id), BuiltinConst(id) => InlineOperand::BuiltinConst(id),
+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
///
/// [`Self::is_value`] must hold for `value`.
unsafe fn from_raw<'gc>(value: &Value<'gc>) -> Self::Ty<'gc>;
}
/// # Safety /// # Safety
/// ///
/// [`Self::TAG`] must be unique among all implementors. /// Each implementor must round-trip through [`Self::to_raw_box`] /
unsafe trait Storable: private::Cealed { /// [`Self::from_raw_box`] and must be the sole owner of its NaN-boxed
const TAG: RawTag; /// 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()
+2 -2
View File
@@ -144,7 +144,7 @@ tail_fn!(op_make_closure, (reader, mc));
tail_fn!(op_make_pattern_closure, (reader, mc)); tail_fn!(op_make_pattern_closure, (reader, mc));
tail_fn!(op_call, (ctx, reader, mc)); tail_fn!(op_call, (ctx, reader, mc));
tail_fn!(op_dispatch_primop, (ctx, reader, mc)); tail_fn!(op_dispatch_cont, (ctx, reader, mc));
tail_fn!(op_return, (ctx, reader, mc)); tail_fn!(op_return, (ctx, reader, mc));
tail_fn!(op_make_attrs, (ctx, reader, mc)); tail_fn!(op_make_attrs, (ctx, reader, mc));
@@ -235,7 +235,7 @@ table! {
MakePatternClosure => op_make_pattern_closure, MakePatternClosure => op_make_pattern_closure,
Call => op_call, Call => op_call,
DispatchPrimOp => op_dispatch_primop, DispatchCont => op_dispatch_cont,
Return => op_return, Return => op_return,
MakeAttrs => op_make_attrs, MakeAttrs => op_make_attrs,
+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)
} }
} }
+14 -14
View File
@@ -1,4 +1,4 @@
use fix_bytecode::PrimOpPhase; use fix_bytecode::Continuation;
use fix_error::Error; use fix_error::Error;
use fix_runtime::{resolve_operand, *}; use fix_runtime::{resolve_operand, *};
use gc_arena::{Gc, Mutation, RefLock}; use gc_arena::{Gc, Mutation, RefLock};
@@ -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());
@@ -31,7 +31,7 @@ pub(crate) fn call<'gc, M: Machine<'gc>>(
thunk: None, thunk: None,
env: m.env(), env: m.env(),
}); });
reader.set_pc(PrimOpPhase::CallPattern.ip() as usize); reader.set_pc(Continuation::CallPattern.ip() as usize);
return Step::Continue(()); return Step::Continue(());
} }
@@ -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
@@ -101,7 +101,7 @@ pub(crate) fn call<'gc, M: Machine<'gc>>(
m.push(arg); m.push(arg);
m.push(func.relax()); m.push(func.relax());
m.push(functor); m.push(functor);
reader.set_pc(PrimOpPhase::CallFunctor1.ip() as usize); reader.set_pc(Continuation::CallFunctor1.ip() as usize);
return Step::Continue(()); return Step::Continue(());
} else { } else {
return m.finish_err(Error::eval_error(format!( return m.finish_err(Error::eval_error(format!(
@@ -142,19 +142,19 @@ pub(crate) fn op_return<'gc, M: Machine<'gc>>(
ForceMode::AsIs => return m.finish_ok(ctx.convert_value(val.relax())), ForceMode::AsIs => return m.finish_ok(ctx.convert_value(val.relax())),
ForceMode::Shallow => { ForceMode::Shallow => {
m.push(val.relax()); m.push(val.relax());
reader.set_pc(PrimOpPhase::ForceResultShallow.ip() as usize); reader.set_pc(Continuation::ForceResultShallow.ip() as usize);
return Step::Continue(()); return Step::Continue(());
} }
ForceMode::Deep => { ForceMode::Deep => {
m.push(val.relax()); m.push(val.relax());
m.push(val.relax()); m.push(val.relax());
m.push_call_frame(CallFrame { m.push_call_frame(CallFrame {
pc: PrimOpPhase::ForceResultDeepFinish.ip() as usize, pc: Continuation::ForceResultDeepFinish.ip() as usize,
thunk: None, thunk: None,
env: m.env(), env: m.env(),
}); });
m.inc_call_depth(); m.inc_call_depth();
reader.set_pc(PrimOpPhase::DeepSeq.ip() as usize); reader.set_pc(Continuation::PDeepSeq.ip() as usize);
return Step::Continue(()); return Step::Continue(());
} }
} }
@@ -171,11 +171,11 @@ pub(crate) fn op_return<'gc, M: Machine<'gc>>(
} }
#[inline(always)] #[inline(always)]
pub(crate) fn op_dispatch_primop<'gc, M: Machine<'gc>>( pub(crate) fn op_dispatch_cont<'gc, M: Machine<'gc>>(
m: &mut M, m: &mut M,
ctx: &mut impl VmRuntimeCtx, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
crate::primops::dispatch_primop(m, ctx, reader, mc) crate::primops::dispatch_cont(m, ctx, reader, mc)
} }
+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(())
} }
+11 -11
View File
@@ -1,6 +1,6 @@
use std::path::PathBuf; use std::path::PathBuf;
use fix_bytecode::PrimOpPhase; use fix_bytecode::Continuation;
use fix_error::Error; use fix_error::Error;
use fix_lang::{BUILTINS, BuiltinId, StringId}; use fix_lang::{BUILTINS, BuiltinId, StringId};
use fix_runtime::{ use fix_runtime::{
@@ -22,10 +22,10 @@ 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: PrimOpPhase::entry_for_builtin(id).ip(), dispatch_ip: Continuation::entry_for_builtin(id).ip(),
})); }));
Step::Continue(()) Step::Continue(())
} }
@@ -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);
} }
+19 -23
View File
@@ -7,7 +7,7 @@
use std::path::PathBuf; use std::path::PathBuf;
use fix_bytecode::{InstructionPtr, PrimOpPhase}; 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;
@@ -60,10 +60,10 @@ fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmRuntimeCtx) -> Value<
let id = BuiltinId::try_from(idx as u8).expect("infallible"); let id = BuiltinId::try_from(idx as u8).expect("infallible");
let name = name.strip_prefix("__").unwrap_or(name); let name = name.strip_prefix("__").unwrap_or(name);
let name = ctx.intern_string(name); let name = ctx.intern_string(name);
let dispatch_ip = PrimOpPhase::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);
@@ -476,6 +470,8 @@ impl<'gc> Vm<'gc> {
let mut fuel = Self::DEFAULT_FUEL_AMOUNT; let mut fuel = Self::DEFAULT_FUEL_AMOUNT;
loop { loop {
use crate::instructions::op_dispatch_cont;
if fuel == 0 { if fuel == 0 {
return Action::Continue { pc: reader.pc() }; return Action::Continue { pc: reader.pc() };
} }
@@ -502,7 +498,7 @@ impl<'gc> Vm<'gc> {
MakePatternClosure => op_make_pattern_closure(self, &mut reader, mc), MakePatternClosure => op_make_pattern_closure(self, &mut reader, mc),
Call => op_call(self, ctx, &mut reader, mc), Call => op_call(self, ctx, &mut reader, mc),
DispatchPrimOp => op_dispatch_primop(self, ctx, &mut reader, mc), DispatchCont => op_dispatch_cont(self, ctx, &mut reader, mc),
Return => op_return(self, ctx, &mut reader, mc), Return => op_return(self, ctx, &mut reader, mc),
MakeAttrs => op_make_attrs(self, ctx, &mut reader, mc), MakeAttrs => op_make_attrs(self, ctx, &mut reader, mc),
+62 -62
View File
@@ -5,7 +5,7 @@
//! See `fix-runtime/src/string_context.rs` for the //! See `fix-runtime/src/string_context.rs` for the
//! `StringContextElem` type. //! `StringContextElem` type.
use fix_bytecode::PrimOpPhase; use fix_bytecode::Continuation;
use fix_error::Error; use fix_error::Error;
use fix_lang::StringId; use fix_lang::StringId;
use fix_runtime::{ use fix_runtime::{
@@ -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,11 +192,11 @@ 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(PrimOpPhase::AppendContextLoop.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);
@@ -221,9 +221,9 @@ pub fn append_context_loop<'gc, M: Machine<'gc>>(
0, 0,
reader, reader,
mc, mc,
PrimOpPhase::AppendContextEntryForced.ip() as usize, Continuation::PAppendContextEntryForced.ip() as usize,
)?; )?;
reader.set_pc(PrimOpPhase::AppendContextEntryForced.ip() as usize); reader.set_pc(Continuation::PAppendContextEntryForced.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -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);
@@ -296,17 +296,17 @@ pub fn append_context_entry_forced<'gc, M: Machine<'gc>>(
0, 0,
reader, reader,
mc, mc,
PrimOpPhase::AppendContextOutputsForced.ip() as usize, Continuation::PAppendContextOutputsForced.ip() as usize,
)?; )?;
reader.set_pc(PrimOpPhase::AppendContextOutputsForced.ip() as usize); reader.set_pc(Continuation::PAppendContextOutputsForced.ip() as usize);
return Step::Continue(()); return Step::Continue(());
} }
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(PrimOpPhase::AppendContextLoop.ip() as usize); reader.set_pc(Continuation::PAppendContextLoop.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -318,21 +318,21 @@ 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(PrimOpPhase::AppendContextLoop.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(PrimOpPhase::AppendContextOutputElementLoop.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,9 +353,9 @@ 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(PrimOpPhase::AppendContextLoop.ip() as usize); reader.set_pc(Continuation::PAppendContextLoop.ip() as usize);
return Step::Continue(()); return Step::Continue(());
} }
@@ -365,9 +365,9 @@ pub fn append_context_output_element_loop<'gc, M: Machine<'gc>>(
0, 0,
reader, reader,
mc, mc,
PrimOpPhase::AppendContextOutputElementForced.ip() as usize, Continuation::PAppendContextOutputElementForced.ip() as usize,
)?; )?;
reader.set_pc(PrimOpPhase::AppendContextOutputElementForced.ip() as usize); reader.set_pc(Continuation::PAppendContextOutputElementForced.ip() as usize);
Step::Continue(()) 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,22 +397,22 @@ 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(PrimOpPhase::AppendContextOutputElementLoop.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)
} }
+38 -38
View File
@@ -1,4 +1,4 @@
use fix_bytecode::PrimOpPhase; use fix_bytecode::Continuation;
use fix_error::Error; use fix_error::Error;
use fix_runtime::{ use fix_runtime::{
AttrSet, BytecodeReader, Closure, Env, List, Machine, MachineExt, Step, StrictValue, Value, AttrSet, BytecodeReader, Closure, Env, List, Machine, MachineExt, Step, StrictValue, Value,
@@ -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,16 +69,16 @@ 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(PrimOpPhase::DeepSeqPush.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,15 +99,15 @@ 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
m.force_slot_to_pc(0, reader, mc, PrimOpPhase::DeepSeqLoop.ip() as usize)?; m.force_slot_to_pc(0, reader, mc, Continuation::PDeepSeqLoop.ip() as usize)?;
reader.set_pc(PrimOpPhase::DeepSeqLoop.ip() as usize); reader.set_pc(Continuation::PDeepSeqLoop.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -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,8 +156,8 @@ 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(PrimOpPhase::DeepSeqPush.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,9 +185,9 @@ 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(PrimOpPhase::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,24 +210,24 @@ 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,
reader, reader,
mc, mc,
PrimOpPhase::ForceResultShallowLoop.ip() as usize, Continuation::ForceResultShallowLoop.ip() as usize,
)?; )?;
reader.set_pc(PrimOpPhase::ForceResultShallowLoop.ip() as usize); reader.set_pc(Continuation::ForceResultShallowLoop.ip() as usize);
} }
Step::Continue(()) Step::Continue(())
} }
@@ -238,7 +238,7 @@ pub fn force_result_shallow_loop<'gc, M: Machine<'gc>>(
_mc: &Mutation<'gc>, _mc: &Mutation<'gc>,
) -> Step { ) -> Step {
let _ = m.pop(); // forced child let _ = m.pop(); // forced child
reader.set_pc(PrimOpPhase::ForceResultShallowPush.ip() as usize); reader.set_pc(Continuation::ForceResultShallowPush.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -288,7 +288,7 @@ pub fn call_functor_1<'gc, M: Machine<'gc>>(
reader, reader,
mc, mc,
self_val, self_val,
PrimOpPhase::CallFunctor2.ip() as usize, Continuation::CallFunctor2.ip() as usize,
) )
} }
@@ -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)
} }
+26 -23
View File
@@ -1,4 +1,4 @@
use fix_bytecode::PrimOpPhase; use fix_bytecode::Continuation;
use fix_runtime::{ use fix_runtime::{
AttrSet, BytecodeReader, CallFrame, List, Machine, MachineExt, NixNum, Null, Path, Step, AttrSet, BytecodeReader, CallFrame, List, Machine, MachineExt, NixNum, Null, Path, Step,
StrictValue, Value, VmRuntimeCtx, VmRuntimeCtxExt, StrictValue, Value, VmRuntimeCtx, VmRuntimeCtxExt,
@@ -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() {
@@ -71,7 +71,7 @@ pub fn eq_step<'gc, M: Machine<'gc>>(
.expect("non-empty rhs queue"); .expect("non-empty rhs queue");
m.push(lhs); m.push(lhs);
m.push(rhs); m.push(rhs);
reader.set_pc(PrimOpPhase::EqForce.ip() as usize); reader.set_pc(Continuation::EqForce.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -83,7 +83,7 @@ pub fn eq_force<'gc, M: Machine<'gc>>(
) -> Step { ) -> Step {
let (lhs, rhs) = m.force_and_retry::<(StrictValue, StrictValue)>(reader, mc)?; let (lhs, rhs) = m.force_and_retry::<(StrictValue, StrictValue)>(reader, mc)?;
apply_pair(m, ctx, mc, lhs, rhs); apply_pair(m, ctx, mc, lhs, rhs);
reader.set_pc(PrimOpPhase::EqStep.ip() as usize); reader.set_pc(Continuation::EqStep.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -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,11 +169,11 @@ 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(PrimOpPhase::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() {
+8 -8
View File
@@ -1,6 +1,6 @@
use std::path::PathBuf; use std::path::PathBuf;
use fix_bytecode::PrimOpPhase; use fix_bytecode::Continuation;
use fix_error::Error; use fix_error::Error;
use fix_lang::StringId; use fix_lang::StringId;
use fix_runtime::{ use fix_runtime::{
@@ -40,10 +40,10 @@ 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: PrimOpPhase::ImportFinalize.ip() as usize, pc: Continuation::PImportFinalize.ip() as usize,
thunk: None, thunk: None,
env, env,
}); });
@@ -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,11 +107,11 @@ 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 {
pc: PrimOpPhase::ScopedImportFinalize.ip() as usize, pc: Continuation::PScopedImportFinalize.ip() as usize,
thunk: None, thunk: None,
env, env,
}); });
@@ -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
+54 -49
View File
@@ -1,4 +1,4 @@
use fix_bytecode::PrimOpPhase; use fix_bytecode::Continuation;
use fix_runtime::{BytecodeReader, List, Machine, MachineExt, NixType, Step, StrictValue, Value}; use fix_runtime::{BytecodeReader, List, Machine, MachineExt, NixType, Step, StrictValue, Value};
use gc_arena::Mutation; use gc_arena::Mutation;
@@ -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,9 +18,9 @@ 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(PrimOpPhase::FilterCallPred.ip() as usize); reader.set_pc(Continuation::PFilterCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -32,11 +32,11 @@ 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, PrimOpPhase::FilterCheck.ip() as usize) m.call(reader, mc, elem, Continuation::PFilterCheck.ip() as usize)
} }
pub fn filter_check<'gc, M: Machine<'gc>>( pub fn filter_check<'gc, M: Machine<'gc>>(
@@ -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,8 +63,8 @@ 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(PrimOpPhase::FilterCallPred.ip() as usize); reader.set_pc(Continuation::PFilterCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -83,20 +83,20 @@ 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() {
let _ = m.pop(); // list let _ = m.pop(); // list
reader.set_pc(PrimOpPhase::FoldlStrictEmpty.ip() as usize); reader.set_pc(Continuation::PFoldlStrictEmpty.ip() as usize);
return Step::Continue(()); return Step::Continue(());
} }
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(PrimOpPhase::FoldlStrictCall1.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, PrimOpPhase::FoldlStrictCall2.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,15 +133,15 @@ 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,
mc, mc,
elem, elem,
PrimOpPhase::FoldlStrictUpdate.ip() as usize, Continuation::PFoldlStrictUpdate.ip() as usize,
) )
} }
@@ -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,8 +164,8 @@ 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(PrimOpPhase::FoldlStrictCall1.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,11 +184,11 @@ 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(PrimOpPhase::AllCallPred.ip() as usize); reader.set_pc(Continuation::PAllCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -194,11 +199,11 @@ 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, PrimOpPhase::AllCheck.ip() as usize) m.call(reader, mc, elem, Continuation::PAllCheck.ip() as usize)
} }
pub fn all_check<'gc, M: Machine<'gc>>( pub fn all_check<'gc, M: Machine<'gc>>(
@@ -208,18 +213,18 @@ 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(PrimOpPhase::AllCallPred.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,11 +243,11 @@ 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(PrimOpPhase::AnyCallPred.ip() as usize); reader.set_pc(Continuation::PAnyCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
@@ -253,11 +258,11 @@ 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, PrimOpPhase::AnyCheck.ip() as usize) m.call(reader, mc, elem, Continuation::PAnyCheck.ip() as usize)
} }
pub fn any_check<'gc, M: Machine<'gc>>( pub fn any_check<'gc, M: Machine<'gc>>(
@@ -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(PrimOpPhase::AnyCallPred.ip() as usize); reader.set_pc(Continuation::PAnyCallPred.ip() as usize);
Step::Continue(()) Step::Continue(())
} }
+45 -44
View File
@@ -10,7 +10,7 @@ pub use context::*;
pub use control::*; pub use control::*;
pub use conv::*; pub use conv::*;
pub use eq::*; pub use eq::*;
use fix_bytecode::PrimOpPhase; use fix_bytecode::Continuation;
use fix_error::Error; use fix_error::Error;
use fix_runtime::{BytecodeReader, Machine, Step, VmRuntimeCtx}; use fix_runtime::{BytecodeReader, Machine, Step, VmRuntimeCtx};
use gc_arena::Mutation; use gc_arena::Mutation;
@@ -19,42 +19,42 @@ pub use list::*;
pub use path::*; pub use path::*;
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
pub fn dispatch_primop<'gc, M: Machine<'gc>>( pub fn dispatch_cont<'gc, M: Machine<'gc>>(
m: &mut M, m: &mut M,
ctx: &mut impl VmRuntimeCtx, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
use PrimOpPhase::*; use Continuation::*;
let phase_disc = reader.read_u8(); let cont = reader.read_u8();
let Ok(phase) = PrimOpPhase::try_from(phase_disc) else { let Ok(cont) = Continuation::try_from(cont) else {
return m.finish_err(Error::eval_error("invalid primop phase")); return m.finish_err(Error::eval_error("invalid primop phase"));
}; };
match phase { match cont {
Abort => abort(m, ctx, reader, mc), PAbort => abort(m, ctx, reader, mc),
All => all_entry(m, reader, mc), PAll => all_entry(m, reader, mc),
AllCallPred => all_call_pred(m, reader, mc), PAllCallPred => all_call_pred(m, reader, mc),
AllCheck => all_check(m, reader, mc), PAllCheck => all_check(m, reader, mc),
Any => any_entry(m, reader, mc), PAny => any_entry(m, reader, mc),
AnyCallPred => any_call_pred(m, reader, mc), PAnyCallPred => any_call_pred(m, reader, mc),
AnyCheck => any_check(m, reader, mc), PAnyCheck => any_check(m, reader, mc),
DeepSeq => deep_seq_force_top(m, reader, mc), PDeepSeq => deep_seq_force_top(m, reader, mc),
DeepSeqPush => deep_seq_push(m, reader, mc), PDeepSeqPush => deep_seq_push(m, reader, mc),
DeepSeqLoop => deep_seq_loop(m, reader, mc), PDeepSeqLoop => deep_seq_loop(m, reader, mc),
Seq => seq(m, reader, mc), PSeq => seq(m, reader, mc),
FilterForceList => filter_force_list(m, reader, mc), PFilterForceList => filter_force_list(m, reader, mc),
FilterCallPred => filter_call_pred(m, reader, mc), PFilterCallPred => filter_call_pred(m, reader, mc),
FilterCheck => filter_check(m, reader, mc), PFilterCheck => filter_check(m, reader, mc),
FoldlStrict => foldl_strict_entry(m, reader, mc), PFoldlStrict => foldl_strict_entry(m, reader, mc),
FoldlStrictEmpty => foldl_strict_empty(m, reader, mc), PFoldlStrictEmpty => foldl_strict_empty(m, reader, mc),
FoldlStrictCall1 => foldl_strict_call1(m, reader, mc), PFoldlStrictCall1 => foldl_strict_call1(m, reader, mc),
FoldlStrictCall2 => foldl_strict_call2(m, reader, mc), PFoldlStrictCall2 => foldl_strict_call2(m, reader, mc),
FoldlStrictUpdate => foldl_strict_update(m, reader, mc), PFoldlStrictUpdate => foldl_strict_update(m, reader, mc),
ForceResultShallow => force_result_shallow(m, ctx, reader, mc), ForceResultShallow => force_result_shallow(m, ctx, reader, mc),
ForceResultShallowPush => force_result_shallow_push(m, ctx, reader, mc), ForceResultShallowPush => force_result_shallow_push(m, ctx, reader, mc),
@@ -68,29 +68,30 @@ pub fn dispatch_primop<'gc, M: Machine<'gc>>(
CallFunctor1 => call_functor_1(m, reader, mc), CallFunctor1 => call_functor_1(m, reader, mc),
CallFunctor2 => call_functor_2(m, reader, mc), CallFunctor2 => call_functor_2(m, reader, mc),
Import => import(m, ctx, reader, mc), PImport => import(m, ctx, reader, mc),
ImportFinalize => import_finalize(m, ctx, reader), PImportFinalize => import_finalize(m, ctx, reader),
ScopedImport => scoped_import(m, ctx, reader, mc), PScopedImport => scoped_import(m, ctx, reader, mc),
ScopedImportFinalize => scoped_import_finalize(m, ctx, reader, mc), PScopedImportFinalize => scoped_import_finalize(m, ctx, reader, mc),
PathExists => path_exists(m, ctx, reader, mc), PPathExists => path_exists(m, ctx, reader, mc),
ToPath => to_path(m, ctx, reader, mc), PToPath => to_path(m, ctx, reader, mc),
IsPath => is_path(m, reader, mc), PIsPath => is_path(m, reader, mc),
ToString => to_string(m, ctx, reader, mc), PToString => to_string(m, ctx, reader, mc),
TypeOf => type_of(m, ctx, reader, mc), PTypeOf => type_of(m, ctx, reader, mc),
HasContext => has_context(m, ctx, reader, mc), PHasContext => has_context(m, ctx, reader, mc),
GetContext => get_context(m, ctx, reader, mc), PGetContext => get_context(m, ctx, reader, mc),
AppendContext => append_context(m, ctx, reader, mc), PAppendContext => append_context(m, ctx, reader, mc),
AppendContextLoop => append_context_loop(m, ctx, reader, mc), PAppendContextLoop => append_context_loop(m, ctx, reader, mc),
AppendContextEntryForced => append_context_entry_forced(m, ctx, reader, mc), PAppendContextEntryForced => append_context_entry_forced(m, ctx, reader, mc),
AppendContextOutputsForced => append_context_outputs_forced(m, ctx, reader, mc), PAppendContextOutputsForced => append_context_outputs_forced(m, ctx, reader, mc),
AppendContextOutputElementLoop => append_context_output_element_loop(m, ctx, reader, mc), PAppendContextOutputElementLoop => append_context_output_element_loop(m, ctx, reader, mc),
AppendContextOutputElementForced => { PAppendContextOutputElementForced => {
append_context_output_element_forced(m, ctx, reader, mc) append_context_output_element_forced(m, ctx, reader, mc)
} }
UnsafeDiscardStringContext => unsafe_discard_string_context(m, ctx, reader, mc),
UnsafeDiscardOutputDependency => unsafe_discard_output_dependency(m, ctx, reader, mc), PUnsafeDiscardStringContext => unsafe_discard_string_context(m, ctx, reader, mc),
PUnsafeDiscardOutputDependency => unsafe_discard_output_dependency(m, ctx, reader, mc),
phase => todo!("primop phase {phase:?}"), phase => todo!("primop phase {phase:?}"),
} }
+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)
} }