Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abf7dc0855
|
||
|
|
7220b42024
|
Generated
+49
-4
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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"] }
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
@@ -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" }
|
||||||
|
|||||||
@@ -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
@@ -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 {
|
||||||
|
|||||||
@@ -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
@@ -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()
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(())
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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),
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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() {
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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:?}"),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user