clean up
This commit is contained in:
@@ -16,9 +16,6 @@ vim.lsp.config("rust_analyzer", {
|
|||||||
settings = {
|
settings = {
|
||||||
["rust-analyzer"] = {
|
["rust-analyzer"] = {
|
||||||
cargo = {
|
cargo = {
|
||||||
features = {
|
|
||||||
"inspector"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1078
Cargo.lock
generated
1078
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,7 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = [
|
members = [
|
||||||
"nix-js",
|
"fix"
|
||||||
"nix-js-macros"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[profile.profiling]
|
[profile.profiling]
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "nix-js"
|
name = "fix"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
mimalloc = "0.1"
|
mimalloc = "0.1"
|
||||||
@@ -35,9 +34,6 @@ itertools = "0.14"
|
|||||||
|
|
||||||
regex = "1.11"
|
regex = "1.11"
|
||||||
|
|
||||||
deno_core = "0.385"
|
|
||||||
deno_error = "0.7"
|
|
||||||
|
|
||||||
nix-nar = "0.3"
|
nix-nar = "0.3"
|
||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
sha1 = "0.10"
|
sha1 = "0.10"
|
||||||
@@ -54,7 +50,7 @@ bzip2 = "0.6"
|
|||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
# spec 1.0.0
|
# spec 1.0.0
|
||||||
toml = "0.9.9"
|
toml = "=0.9.9"
|
||||||
dirs = "6.0"
|
dirs = "6.0"
|
||||||
tempfile = "3.24"
|
tempfile = "3.24"
|
||||||
rusqlite = { version = "0.38", features = ["bundled"] }
|
rusqlite = { version = "0.38", features = ["bundled"] }
|
||||||
@@ -62,24 +58,15 @@ rusqlite = { version = "0.38", features = ["bundled"] }
|
|||||||
rnix = "0.14"
|
rnix = "0.14"
|
||||||
rowan = "0.16"
|
rowan = "0.16"
|
||||||
|
|
||||||
nix-js-macros = { path = "../nix-js-macros" }
|
|
||||||
ere = "0.2.4"
|
ere = "0.2.4"
|
||||||
num_enum = "0.7.5"
|
num_enum = "0.7.5"
|
||||||
tap = "1.0.1"
|
tap = "1.0.1"
|
||||||
|
|
||||||
# Inspector (optional)
|
ghost-cell = "0.2"
|
||||||
fastwebsockets = { version = "0.10", features = ["upgrade"], optional = true }
|
colored = "3.1"
|
||||||
hyper = { version = "1", features = ["http1", "server"], optional = true }
|
boxing = "0.1"
|
||||||
hyper-util = { version = "0.1", features = ["tokio"], optional = true }
|
gc-arena = { version = "0.5.3", features = ["allocator-api2"] }
|
||||||
http-body-util = { version = "0.1", optional = true }
|
allocator-api2 = "0.4.0"
|
||||||
http = { version = "1", optional = true }
|
|
||||||
uuid = { version = "1", features = ["v4"], optional = true }
|
|
||||||
ghost-cell = "0.2.6"
|
|
||||||
colored = "3.1.1"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
inspector = ["dep:fastwebsockets", "dep:hyper", "dep:hyper-util", "dep:http-body-util", "dep:http", "dep:uuid"]
|
|
||||||
prof = []
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = { version = "0.8", features = ["html_reports"] }
|
criterion = { version = "0.8", features = ["html_reports"] }
|
||||||
@@ -96,7 +83,3 @@ harness = false
|
|||||||
[[bench]]
|
[[bench]]
|
||||||
name = "thunk_scope"
|
name = "thunk_scope"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[[bench]]
|
|
||||||
name = "compile_time"
|
|
||||||
harness = false
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use nix_js::context::Context;
|
use fix::context::Context;
|
||||||
use nix_js::error::{Result, Source};
|
use fix::error::{Result, Source};
|
||||||
use nix_js::value::Value;
|
use fix::value::Value;
|
||||||
|
|
||||||
pub fn eval(expr: &str) -> Value {
|
pub fn eval(expr: &str) -> Value {
|
||||||
Context::new()
|
Context::new()
|
||||||
@@ -16,10 +16,3 @@ pub fn eval_result(expr: &str) -> Result<Value> {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.eval(Source::new_eval(expr.into()).unwrap())
|
.eval(Source::new_eval(expr.into()).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(expr: &str) -> String {
|
|
||||||
Context::new()
|
|
||||||
.unwrap()
|
|
||||||
.compile(Source::new_eval(expr.into()).unwrap())
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
@@ -30,72 +30,72 @@ pub(crate) trait BytecodeContext {
|
|||||||
#[derive(Clone, Copy, TryFromPrimitive)]
|
#[derive(Clone, Copy, TryFromPrimitive)]
|
||||||
#[allow(clippy::enum_variant_names)]
|
#[allow(clippy::enum_variant_names)]
|
||||||
pub enum Op {
|
pub enum Op {
|
||||||
PushConst = 0x01,
|
PushConst,
|
||||||
PushString = 0x02,
|
PushString,
|
||||||
PushNull = 0x03,
|
PushNull,
|
||||||
PushTrue = 0x04,
|
PushTrue,
|
||||||
PushFalse = 0x05,
|
PushFalse,
|
||||||
|
|
||||||
LoadLocal = 0x06,
|
LoadLocal,
|
||||||
LoadOuter = 0x07,
|
LoadOuter,
|
||||||
StoreLocal = 0x08,
|
StoreLocal,
|
||||||
AllocLocals = 0x09,
|
AllocLocals,
|
||||||
|
|
||||||
MakeThunk = 0x0A,
|
MakeThunk,
|
||||||
MakeClosure = 0x0B,
|
MakeClosure,
|
||||||
MakePatternClosure = 0x0C,
|
MakePatternClosure,
|
||||||
|
|
||||||
Call = 0x0D,
|
Call,
|
||||||
CallNoSpan = 0x0E,
|
CallNoSpan,
|
||||||
|
|
||||||
MakeAttrs = 0x0F,
|
MakeAttrs,
|
||||||
MakeAttrsDyn = 0x10,
|
MakeAttrsDyn,
|
||||||
MakeEmptyAttrs = 0x11,
|
MakeEmptyAttrs,
|
||||||
Select = 0x12,
|
Select,
|
||||||
SelectDefault = 0x13,
|
SelectDefault,
|
||||||
HasAttr = 0x14,
|
HasAttr,
|
||||||
|
|
||||||
MakeList = 0x15,
|
MakeList,
|
||||||
|
|
||||||
OpAdd = 0x16,
|
OpAdd,
|
||||||
OpSub = 0x17,
|
OpSub,
|
||||||
OpMul = 0x18,
|
OpMul,
|
||||||
OpDiv = 0x19,
|
OpDiv,
|
||||||
OpEq = 0x20,
|
OpEq,
|
||||||
OpNeq = 0x21,
|
OpNeq,
|
||||||
OpLt = 0x22,
|
OpLt,
|
||||||
OpGt = 0x23,
|
OpGt,
|
||||||
OpLeq = 0x24,
|
OpLeq,
|
||||||
OpGeq = 0x25,
|
OpGeq,
|
||||||
OpConcat = 0x26,
|
OpConcat,
|
||||||
OpUpdate = 0x27,
|
OpUpdate,
|
||||||
|
|
||||||
OpNeg = 0x28,
|
OpNeg,
|
||||||
OpNot = 0x29,
|
OpNot,
|
||||||
|
|
||||||
ForceBool = 0x30,
|
ForceBool,
|
||||||
JumpIfFalse = 0x31,
|
JumpIfFalse,
|
||||||
JumpIfTrue = 0x32,
|
JumpIfTrue,
|
||||||
Jump = 0x33,
|
Jump,
|
||||||
|
|
||||||
ConcatStrings = 0x34,
|
ConcatStrings,
|
||||||
ResolvePath = 0x35,
|
ResolvePath,
|
||||||
|
|
||||||
Assert = 0x36,
|
Assert,
|
||||||
|
|
||||||
PushWith = 0x37,
|
PushWith,
|
||||||
PopWith = 0x38,
|
PopWith,
|
||||||
WithLookup = 0x39,
|
WithLookup,
|
||||||
|
|
||||||
LoadBuiltins = 0x40,
|
LoadBuiltins,
|
||||||
LoadBuiltin = 0x41,
|
LoadBuiltin,
|
||||||
|
|
||||||
MkPos = 0x43,
|
MkPos,
|
||||||
|
|
||||||
LoadReplBinding = 0x44,
|
LoadReplBinding,
|
||||||
LoadScopedBinding = 0x45,
|
LoadScopedBinding,
|
||||||
|
|
||||||
Return = 0x46,
|
Return,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScopeInfo {
|
struct ScopeInfo {
|
||||||
@@ -120,19 +120,6 @@ pub(crate) fn compile_bytecode(ir: RawIrRef<'_>, ctx: &mut impl BytecodeContext)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compile_bytecode_scoped(
|
|
||||||
ir: RawIrRef<'_>,
|
|
||||||
ctx: &mut impl BytecodeContext,
|
|
||||||
) -> Bytecode {
|
|
||||||
let current_dir = ctx.get_current_dir().to_string_lossy().to_string();
|
|
||||||
let mut emitter = BytecodeEmitter::new(ctx);
|
|
||||||
emitter.emit_toplevel_scoped(ir);
|
|
||||||
Bytecode {
|
|
||||||
code: emitter.code.into_boxed_slice(),
|
|
||||||
current_dir,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
||||||
fn new(ctx: &'a mut Ctx) -> Self {
|
fn new(ctx: &'a mut Ctx) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -397,37 +384,6 @@ impl<'a, Ctx: BytecodeContext> BytecodeEmitter<'a, Ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_toplevel_scoped(&mut self, ir: RawIrRef<'_>) {
|
|
||||||
match ir.deref() {
|
|
||||||
Ir::TopLevel { body, thunks } => {
|
|
||||||
let with_thunk_count = self.count_with_thunks(*body);
|
|
||||||
let total_slots = thunks.len() + with_thunk_count;
|
|
||||||
|
|
||||||
let all_thunks = self.collect_all_thunks(thunks, *body);
|
|
||||||
let thunk_ids: Vec<ThunkId> = all_thunks.iter().map(|&(id, _)| id).collect();
|
|
||||||
|
|
||||||
self.push_scope(false, None, &thunk_ids);
|
|
||||||
|
|
||||||
if total_slots > 0 {
|
|
||||||
self.emit_op(Op::AllocLocals);
|
|
||||||
self.emit_u32(total_slots as u32);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.emit_scope_thunks(thunks);
|
|
||||||
self.emit_expr(*body);
|
|
||||||
self.emit_op(Op::Return);
|
|
||||||
|
|
||||||
self.pop_scope();
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.push_scope(false, None, &[]);
|
|
||||||
self.emit_expr(ir);
|
|
||||||
self.emit_op(Op::Return);
|
|
||||||
self.pop_scope();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_scope_thunks(&mut self, thunks: &[(ThunkId, RawIrRef<'_>)]) {
|
fn emit_scope_thunks(&mut self, thunks: &[(ThunkId, RawIrRef<'_>)]) {
|
||||||
for &(id, inner) in thunks {
|
for &(id, inner) in thunks {
|
||||||
let label = format!("e{}", id.0);
|
let label = format!("e{}", id.0);
|
||||||
@@ -9,14 +9,10 @@ use rnix::TextRange;
|
|||||||
use string_interner::DefaultStringInterner;
|
use string_interner::DefaultStringInterner;
|
||||||
|
|
||||||
use crate::bytecode::{self, Bytecode, BytecodeContext, Constant};
|
use crate::bytecode::{self, Bytecode, BytecodeContext, Constant};
|
||||||
use crate::codegen::{CodegenContext, compile};
|
|
||||||
use crate::disassembler::{Disassembler, DisassemblerContext};
|
use crate::disassembler::{Disassembler, DisassemblerContext};
|
||||||
use crate::downgrade::*;
|
use crate::downgrade::*;
|
||||||
use crate::error::{Error, Result, Source};
|
use crate::error::{Error, Result, Source};
|
||||||
use crate::ir::{ArgId, Ir, IrKey, IrRef, RawIrRef, SymId, ThunkId, ir_content_eq};
|
use crate::ir::{ArgId, Ir, IrKey, IrRef, RawIrRef, SymId, ThunkId, ir_content_eq};
|
||||||
#[cfg(feature = "inspector")]
|
|
||||||
use crate::runtime::inspector::InspectorServer;
|
|
||||||
use crate::runtime::{ForceMode, Runtime, RuntimeContext};
|
|
||||||
use crate::store::{DaemonStore, Store, StoreConfig};
|
use crate::store::{DaemonStore, Store, StoreConfig};
|
||||||
use crate::value::{Symbol, Value};
|
use crate::value::{Symbol, Value};
|
||||||
|
|
||||||
@@ -48,129 +44,27 @@ fn handle_parse_error<'a>(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Context {
|
|
||||||
ctx: Ctx,
|
|
||||||
runtime: Runtime<Ctx>,
|
|
||||||
#[cfg(feature = "inspector")]
|
|
||||||
_inspector_server: Option<InspectorServer>,
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! eval_bc {
|
|
||||||
($name:ident, $mode:expr) => {
|
|
||||||
pub fn $name(&mut self, source: Source) -> Result<Value> {
|
|
||||||
tracing::info!("Starting evaluation");
|
|
||||||
|
|
||||||
tracing::debug!("Compiling bytecode");
|
|
||||||
let bytecode = self.ctx.compile_bytecode(source)?;
|
|
||||||
|
|
||||||
tracing::debug!("Executing bytecode");
|
|
||||||
self.runtime.eval_bytecode(bytecode, &mut self.ctx, $mode)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn eval(&mut self, _source: Source) -> Result<Value> {
|
||||||
let ctx = Ctx::new()?;
|
todo!()
|
||||||
#[cfg(feature = "inspector")]
|
}
|
||||||
let runtime = Runtime::new(Default::default())?;
|
pub fn eval_shallow(&mut self, _source: Source) -> Result<Value> {
|
||||||
#[cfg(not(feature = "inspector"))]
|
todo!()
|
||||||
let runtime = Runtime::new()?;
|
}
|
||||||
|
pub fn eval_deep(&mut self, _source: Source) -> Result<Value> {
|
||||||
let mut context = Self {
|
todo!()
|
||||||
ctx,
|
|
||||||
runtime,
|
|
||||||
#[cfg(feature = "inspector")]
|
|
||||||
_inspector_server: None,
|
|
||||||
};
|
|
||||||
context.init()?;
|
|
||||||
|
|
||||||
Ok(context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "inspector")]
|
pub fn eval_repl<'a>(&'a mut self, _source: Source, _scope: &'a HashSet<SymId>) -> Result<Value> {
|
||||||
pub fn new_with_inspector(addr: std::net::SocketAddr, wait_for_session: bool) -> Result<Self> {
|
todo!()
|
||||||
use crate::runtime::InspectorOptions;
|
|
||||||
|
|
||||||
let ctx = Ctx::new()?;
|
|
||||||
let runtime = Runtime::new(InspectorOptions {
|
|
||||||
enable: true,
|
|
||||||
wait: wait_for_session,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let server = crate::runtime::inspector::InspectorServer::new(addr, "nix-js")
|
|
||||||
.map_err(|e| Error::internal(e.to_string()))?;
|
|
||||||
server.register_inspector("nix-js".to_string(), runtime.inspector(), wait_for_session);
|
|
||||||
|
|
||||||
let mut context = Self {
|
|
||||||
ctx,
|
|
||||||
runtime,
|
|
||||||
_inspector_server: Some(server),
|
|
||||||
};
|
|
||||||
context.init()?;
|
|
||||||
Ok(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "inspector")]
|
|
||||||
pub fn wait_for_inspector_disconnect(&mut self) {
|
|
||||||
self.runtime.wait_for_inspector_disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init(&mut self) -> Result<()> {
|
|
||||||
const DERIVATION_NIX: &str = include_str!("runtime/corepkgs/derivation.nix");
|
|
||||||
let source = Source::new_virtual(
|
|
||||||
"<nix/derivation-internal.nix>".into(),
|
|
||||||
DERIVATION_NIX.to_string(),
|
|
||||||
);
|
|
||||||
let code = self.ctx.compile(source, None)?;
|
|
||||||
self.runtime.eval(
|
|
||||||
format!(
|
|
||||||
"Nix.builtins.set('derivation',({}));Nix.builtins.set('storeDir','{}');{}0n",
|
|
||||||
code,
|
|
||||||
self.get_store_dir(),
|
|
||||||
if std::env::var("NIX_JS_DEBUG_THUNKS").is_ok() {
|
|
||||||
"Nix.DEBUG_THUNKS.enabled=true;"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
),
|
|
||||||
&mut self.ctx,
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
eval_bc!(eval, ForceMode::Force);
|
|
||||||
eval_bc!(eval_shallow, ForceMode::ForceShallow);
|
|
||||||
eval_bc!(eval_deep, ForceMode::ForceDeep);
|
|
||||||
pub fn eval_repl<'a>(&'a mut self, source: Source, scope: &'a HashSet<SymId>) -> Result<Value> {
|
|
||||||
tracing::info!("Starting evaluation");
|
|
||||||
|
|
||||||
tracing::debug!("Compiling code");
|
|
||||||
let code = self.ctx.compile(source, Some(Scope::Repl(scope)))?;
|
|
||||||
|
|
||||||
tracing::debug!("Executing JavaScript");
|
|
||||||
self.runtime
|
|
||||||
.eval(format!("Nix.forceShallow({})", code), &mut self.ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compile(&mut self, source: Source) -> Result<String> {
|
|
||||||
self.ctx.compile(source, None)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compile_bytecode(&mut self, source: Source) -> Result<Bytecode> {
|
|
||||||
self.ctx.compile_bytecode(source)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disassemble(&self, bytecode: &Bytecode) -> String {
|
pub fn disassemble(&self, bytecode: &Bytecode) -> String {
|
||||||
Disassembler::new(bytecode, &self.ctx).disassemble()
|
Disassembler::new(bytecode, self).disassemble()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disassemble_colored(&self, bytecode: &Bytecode) -> String {
|
pub fn disassemble_colored(&self, bytecode: &Bytecode) -> String {
|
||||||
Disassembler::new(bytecode, &self.ctx).disassemble_colored()
|
Disassembler::new(bytecode, self).disassemble_colored()
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_store_dir(&self) -> &str {
|
|
||||||
self.ctx.get_store_dir()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_binding<'a>(
|
pub fn add_binding<'a>(
|
||||||
@@ -179,22 +73,11 @@ impl Context {
|
|||||||
expr: &str,
|
expr: &str,
|
||||||
scope: &'a mut HashSet<SymId>,
|
scope: &'a mut HashSet<SymId>,
|
||||||
) -> Result<Value> {
|
) -> Result<Value> {
|
||||||
let source = Source::new_repl(expr.to_string())?;
|
todo!()
|
||||||
let code = self.ctx.compile(source, Some(Scope::Repl(scope)))?;
|
|
||||||
|
|
||||||
let sym = self.ctx.symbols.get_or_intern(name);
|
|
||||||
|
|
||||||
let eval_and_store = format!(
|
|
||||||
"(()=>{{const __v=Nix.forceShallow({});Nix.setReplBinding(\"{}\",__v);return __v}})()",
|
|
||||||
code, name
|
|
||||||
);
|
|
||||||
|
|
||||||
scope.insert(sym);
|
|
||||||
self.runtime.eval(eval_and_store, &mut self.ctx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Ctx {
|
pub struct Context {
|
||||||
symbols: DefaultStringInterner,
|
symbols: DefaultStringInterner,
|
||||||
global: HashMap<SymId, Ir<'static, RawIrRef<'static>>>,
|
global: HashMap<SymId, Ir<'static, RawIrRef<'static>>>,
|
||||||
sources: Vec<Source>,
|
sources: Vec<Source>,
|
||||||
@@ -226,8 +109,8 @@ impl OwnedIr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ctx {
|
impl Context {
|
||||||
fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let mut symbols = DefaultStringInterner::new();
|
let mut symbols = DefaultStringInterner::new();
|
||||||
let mut global = HashMap::new();
|
let mut global = HashMap::new();
|
||||||
let builtins_sym = symbols.get_or_intern("builtins");
|
let builtins_sym = symbols.get_or_intern("builtins");
|
||||||
@@ -349,33 +232,7 @@ impl Ctx {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile<'ctx>(
|
pub fn compile_bytecode(&mut self, source: Source) -> Result<Bytecode> {
|
||||||
&'ctx mut self,
|
|
||||||
source: Source,
|
|
||||||
extra_scope: Option<Scope<'ctx>>,
|
|
||||||
) -> Result<String> {
|
|
||||||
let root = self.downgrade(source, extra_scope)?;
|
|
||||||
tracing::debug!("Generating JavaScript code");
|
|
||||||
let code = compile::<false>(root.as_ref(), self);
|
|
||||||
tracing::debug!("Generated code: {}", &code);
|
|
||||||
Ok(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compile_scoped(&mut self, source: Source, scope: Vec<String>) -> Result<String> {
|
|
||||||
let scope = Scope::ScopedImport(
|
|
||||||
scope
|
|
||||||
.into_iter()
|
|
||||||
.map(|k| self.symbols.get_or_intern(k))
|
|
||||||
.collect(),
|
|
||||||
);
|
|
||||||
let root = self.downgrade(source, Some(scope))?;
|
|
||||||
tracing::debug!("Generating JavaScript code for scoped import");
|
|
||||||
let code = compile::<true>(root.as_ref(), self);
|
|
||||||
tracing::debug!("Generated scoped code: {}", &code);
|
|
||||||
Ok(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compile_bytecode(&mut self, source: Source) -> Result<Bytecode> {
|
|
||||||
let root = self.downgrade(source, None)?;
|
let root = self.downgrade(source, None)?;
|
||||||
tracing::debug!("Generating bytecode");
|
tracing::debug!("Generating bytecode");
|
||||||
let bytecode = bytecode::compile_bytecode(root.as_ref(), self);
|
let bytecode = bytecode::compile_bytecode(root.as_ref(), self);
|
||||||
@@ -383,47 +240,12 @@ impl Ctx {
|
|||||||
Ok(bytecode)
|
Ok(bytecode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_bytecode_scoped(&mut self, source: Source, scope: Vec<String>) -> Result<Bytecode> {
|
pub fn get_store_dir(&self) -> &str {
|
||||||
let scope = Scope::ScopedImport(
|
|
||||||
scope
|
|
||||||
.into_iter()
|
|
||||||
.map(|k| self.symbols.get_or_intern(k))
|
|
||||||
.collect(),
|
|
||||||
);
|
|
||||||
let root = self.downgrade(source, Some(scope))?;
|
|
||||||
tracing::debug!("Generating bytecode for scoped import");
|
|
||||||
Ok(bytecode::compile_bytecode_scoped(root.as_ref(), self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CodegenContext for Ctx {
|
|
||||||
fn get_sym(&self, id: SymId) -> Symbol<'_> {
|
|
||||||
self.symbols
|
|
||||||
.resolve(id)
|
|
||||||
.expect("SymId out of bounds")
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
fn get_current_dir(&self) -> &std::path::Path {
|
|
||||||
self.get_current_dir()
|
|
||||||
}
|
|
||||||
fn get_current_source_id(&self) -> usize {
|
|
||||||
self.sources
|
|
||||||
.len()
|
|
||||||
.checked_sub(1)
|
|
||||||
.expect("current_source not set")
|
|
||||||
}
|
|
||||||
fn get_store_dir(&self) -> &str {
|
|
||||||
self.store.get_store_dir()
|
self.store.get_store_dir()
|
||||||
}
|
}
|
||||||
fn register_span(&self, range: rnix::TextRange) -> usize {
|
|
||||||
let spans = unsafe { &mut *self.spans.get() };
|
|
||||||
let id = spans.len();
|
|
||||||
spans.push((self.get_current_source_id(), range));
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BytecodeContext for Ctx {
|
impl BytecodeContext for Context {
|
||||||
fn intern_string(&mut self, s: &str) -> u32 {
|
fn intern_string(&mut self, s: &str) -> u32 {
|
||||||
if let Some(&idx) = self.global_string_map.get(s) {
|
if let Some(&idx) = self.global_string_map.get(s) {
|
||||||
return idx;
|
return idx;
|
||||||
@@ -445,7 +267,16 @@ impl BytecodeContext for Ctx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn register_span(&self, range: TextRange) -> u32 {
|
fn register_span(&self, range: TextRange) -> u32 {
|
||||||
CodegenContext::register_span(self, range) as u32
|
// FIXME: SAFETY
|
||||||
|
let spans = unsafe { &mut *self.spans.get() };
|
||||||
|
let id = spans.len();
|
||||||
|
let source_id = self
|
||||||
|
.sources
|
||||||
|
.len()
|
||||||
|
.checked_sub(1)
|
||||||
|
.expect("current_source not set");
|
||||||
|
spans.push((source_id, range));
|
||||||
|
id as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_sym(&self, id: SymId) -> &str {
|
fn get_sym(&self, id: SymId) -> &str {
|
||||||
@@ -453,51 +284,11 @@ impl BytecodeContext for Ctx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_dir(&self) -> &Path {
|
fn get_current_dir(&self) -> &Path {
|
||||||
Ctx::get_current_dir(self)
|
Context::get_current_dir(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RuntimeContext for Ctx {
|
impl DisassemblerContext for Context {
|
||||||
fn get_current_dir(&self) -> &Path {
|
|
||||||
self.get_current_dir()
|
|
||||||
}
|
|
||||||
fn add_source(&mut self, source: Source) {
|
|
||||||
self.sources.push(source);
|
|
||||||
}
|
|
||||||
fn compile(&mut self, source: Source) -> Result<String> {
|
|
||||||
self.compile(source, None)
|
|
||||||
}
|
|
||||||
fn compile_scoped(&mut self, source: Source, scope: Vec<String>) -> Result<String> {
|
|
||||||
self.compile_scoped(source, scope)
|
|
||||||
}
|
|
||||||
fn compile_bytecode(&mut self, source: Source) -> Result<Bytecode> {
|
|
||||||
self.compile_bytecode(source)
|
|
||||||
}
|
|
||||||
fn compile_bytecode_scoped(&mut self, source: Source, scope: Vec<String>) -> Result<Bytecode> {
|
|
||||||
self.compile_bytecode_scoped(source, scope)
|
|
||||||
}
|
|
||||||
fn get_source(&self, id: usize) -> Source {
|
|
||||||
self.sources.get(id).expect("source not found").clone()
|
|
||||||
}
|
|
||||||
fn get_store(&self) -> &DaemonStore {
|
|
||||||
&self.store
|
|
||||||
}
|
|
||||||
fn get_span(&self, id: usize) -> (usize, TextRange) {
|
|
||||||
let spans = unsafe { &*self.spans.get() };
|
|
||||||
spans[id]
|
|
||||||
}
|
|
||||||
fn get_unsynced(&mut self) -> (&[String], &[Constant], usize, usize) {
|
|
||||||
let strings_base = self.synced_strings;
|
|
||||||
let constants_base = self.synced_constants;
|
|
||||||
let new_strings = &self.global_strings[strings_base..];
|
|
||||||
let new_constants = &self.global_constants[constants_base..];
|
|
||||||
self.synced_strings = self.global_strings.len();
|
|
||||||
self.synced_constants = self.global_constants.len();
|
|
||||||
(new_strings, new_constants, strings_base, constants_base)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DisassemblerContext for Ctx {
|
|
||||||
fn lookup_string(&self, id: u32) -> &str {
|
fn lookup_string(&self, id: u32) -> &str {
|
||||||
self.global_strings
|
self.global_strings
|
||||||
.get(id as usize)
|
.get(id as usize)
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_core::error::JsError;
|
|
||||||
use deno_error::JsErrorClass as _;
|
|
||||||
use itertools::Itertools as _;
|
|
||||||
use miette::{Diagnostic, NamedSource, SourceSpan};
|
use miette::{Diagnostic, NamedSource, SourceSpan};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::runtime::RuntimeContext;
|
|
||||||
|
|
||||||
pub type Result<T> = core::result::Result<T, Box<Error>>;
|
pub type Result<T> = core::result::Result<T, Box<Error>>;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -229,127 +224,3 @@ pub struct StackFrame {
|
|||||||
#[source_code]
|
#[source_code]
|
||||||
pub src: NamedSource<Arc<str>>,
|
pub src: NamedSource<Arc<str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_STACK_FRAMES: usize = 20;
|
|
||||||
const FRAMES_AT_START: usize = 15;
|
|
||||||
const FRAMES_AT_END: usize = 5;
|
|
||||||
|
|
||||||
pub(crate) fn parse_js_error(error: Box<JsError>, ctx: &impl RuntimeContext) -> Error {
|
|
||||||
let (span, src, frames) = if let Some(stack) = &error.stack {
|
|
||||||
let mut frames = parse_frames(stack, ctx);
|
|
||||||
|
|
||||||
if let Some(last_frame) = frames.pop() {
|
|
||||||
(
|
|
||||||
Some(text_range_to_source_span(last_frame.span)),
|
|
||||||
Some(last_frame.src.into()),
|
|
||||||
frames,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(None, None, frames)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(None, None, Vec::new())
|
|
||||||
};
|
|
||||||
let stack_trace = if std::env::var("NIX_JS_STACK_TRACE").is_ok() {
|
|
||||||
truncate_stack_trace(frames)
|
|
||||||
} else {
|
|
||||||
Vec::new()
|
|
||||||
};
|
|
||||||
let message = error.get_message().to_string();
|
|
||||||
let js_backtrace = error.stack.map(|stack| {
|
|
||||||
stack
|
|
||||||
.lines()
|
|
||||||
.filter(|line| !line.starts_with("NIX_STACK_FRAME:"))
|
|
||||||
.join("\n")
|
|
||||||
});
|
|
||||||
|
|
||||||
Error::EvalError {
|
|
||||||
src,
|
|
||||||
span,
|
|
||||||
message,
|
|
||||||
js_backtrace,
|
|
||||||
stack_trace,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NixStackFrame {
|
|
||||||
span: rnix::TextRange,
|
|
||||||
message: String,
|
|
||||||
src: Source,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<NixStackFrame> for StackFrame {
|
|
||||||
fn from(NixStackFrame { span, message, src }: NixStackFrame) -> Self {
|
|
||||||
StackFrame {
|
|
||||||
span: text_range_to_source_span(span),
|
|
||||||
message,
|
|
||||||
src: src.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_frames(stack: &str, ctx: &impl RuntimeContext) -> Vec<NixStackFrame> {
|
|
||||||
let mut frames = Vec::new();
|
|
||||||
|
|
||||||
for line in stack.lines() {
|
|
||||||
// Format: NIX_STACK_FRAME:span_id:message
|
|
||||||
let Some(rest) = line.strip_prefix("NIX_STACK_FRAME:") else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let parts: Vec<&str> = rest.splitn(2, ':').collect();
|
|
||||||
|
|
||||||
if parts.is_empty() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let span_id: usize = match parts[0].parse() {
|
|
||||||
Ok(id) => id,
|
|
||||||
Err(_) => continue,
|
|
||||||
};
|
|
||||||
let (source_id, span) = ctx.get_span(span_id);
|
|
||||||
let src = ctx.get_source(source_id);
|
|
||||||
|
|
||||||
let message = if parts.len() == 2 {
|
|
||||||
parts[1].to_string()
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
frames.push(NixStackFrame { span, message, src });
|
|
||||||
}
|
|
||||||
|
|
||||||
frames.dedup_by(|a, b| a.span == b.span && a.message == b.message);
|
|
||||||
|
|
||||||
frames
|
|
||||||
}
|
|
||||||
|
|
||||||
fn truncate_stack_trace(frames: Vec<NixStackFrame>) -> Vec<StackFrame> {
|
|
||||||
let reversed: Vec<_> = frames.into_iter().rev().collect();
|
|
||||||
let total = reversed.len();
|
|
||||||
|
|
||||||
if total <= MAX_STACK_FRAMES {
|
|
||||||
return reversed.into_iter().map(Into::into).collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
let omitted_count = total - FRAMES_AT_START - FRAMES_AT_END;
|
|
||||||
|
|
||||||
reversed
|
|
||||||
.into_iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter_map(|(i, frame)| {
|
|
||||||
if i < FRAMES_AT_START {
|
|
||||||
Some(frame.into())
|
|
||||||
} else if i == FRAMES_AT_START {
|
|
||||||
Some(StackFrame {
|
|
||||||
span: text_range_to_source_span(frame.span),
|
|
||||||
message: format!("... ({} more frames omitted)", omitted_count),
|
|
||||||
src: frame.src.into(),
|
|
||||||
})
|
|
||||||
} else if i >= total - FRAMES_AT_END {
|
|
||||||
Some(frame.into())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
@@ -5,8 +5,6 @@ use nix_compat::nixhash::HashAlgo;
|
|||||||
use nix_compat::nixhash::NixHash;
|
use nix_compat::nixhash::NixHash;
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use crate::runtime::OpStateExt;
|
|
||||||
use crate::runtime::RuntimeContext;
|
|
||||||
use crate::store::Store as _;
|
use crate::store::Store as _;
|
||||||
|
|
||||||
mod archive;
|
mod archive;
|
||||||
@@ -20,7 +18,6 @@ pub use download::Downloader;
|
|||||||
pub use metadata_cache::MetadataCache;
|
pub use metadata_cache::MetadataCache;
|
||||||
|
|
||||||
use crate::nar;
|
use crate::nar;
|
||||||
use crate::runtime::NixRuntimeError;
|
|
||||||
|
|
||||||
#[derive(ToV8)]
|
#[derive(ToV8)]
|
||||||
pub struct FetchUrlResult {
|
pub struct FetchUrlResult {
|
||||||
@@ -306,11 +303,3 @@ fn normalize_hash(hash: &str) -> String {
|
|||||||
}
|
}
|
||||||
hash.to_string()
|
hash.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_ops<Ctx: RuntimeContext>() -> Vec<deno_core::OpDecl> {
|
|
||||||
vec![
|
|
||||||
op_fetch_url::<Ctx>(),
|
|
||||||
op_fetch_tarball::<Ctx>(),
|
|
||||||
op_fetch_git::<Ctx>(),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,7 @@ impl FetcherCache {
|
|||||||
pub fn new() -> Result<Self, std::io::Error> {
|
pub fn new() -> Result<Self, std::io::Error> {
|
||||||
let base_dir = dirs::cache_dir()
|
let base_dir = dirs::cache_dir()
|
||||||
.unwrap_or_else(|| PathBuf::from("/tmp"))
|
.unwrap_or_else(|| PathBuf::from("/tmp"))
|
||||||
.join("nix-js")
|
.join("fix")
|
||||||
.join("fetchers");
|
.join("fetchers");
|
||||||
|
|
||||||
fs::create_dir_all(&base_dir)?;
|
fs::create_dir_all(&base_dir)?;
|
||||||
@@ -6,11 +6,10 @@ pub mod logging;
|
|||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
mod bytecode;
|
mod bytecode;
|
||||||
mod codegen;
|
|
||||||
mod derivation;
|
mod derivation;
|
||||||
mod disassembler;
|
mod disassembler;
|
||||||
mod downgrade;
|
mod downgrade;
|
||||||
mod fetcher;
|
// mod fetcher;
|
||||||
mod ir;
|
mod ir;
|
||||||
mod nar;
|
mod nar;
|
||||||
mod nix_utils;
|
mod nix_utils;
|
||||||
@@ -4,22 +4,14 @@ use std::process::exit;
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{Args, Parser, Subcommand};
|
use clap::{Args, Parser, Subcommand};
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use nix_js::context::Context;
|
use fix::context::Context;
|
||||||
use nix_js::error::Source;
|
use fix::error::Source;
|
||||||
use rustyline::DefaultEditor;
|
use rustyline::DefaultEditor;
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[command(name = "nix-js", about = "Nix expression evaluator")]
|
#[command(name = "nix-js", about = "Nix expression evaluator")]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
#[cfg(feature = "inspector")]
|
|
||||||
#[arg(long, value_name = "HOST:PORT", num_args = 0..=1, default_missing_value = "127.0.0.1:9229")]
|
|
||||||
inspect: Option<String>,
|
|
||||||
|
|
||||||
#[cfg(feature = "inspector")]
|
|
||||||
#[arg(long, value_name = "HOST:PORT", num_args = 0..=1, default_missing_value = "127.0.0.1:9229")]
|
|
||||||
inspect_brk: Option<String>,
|
|
||||||
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: Command,
|
command: Command,
|
||||||
}
|
}
|
||||||
@@ -48,27 +40,6 @@ struct ExprSource {
|
|||||||
file: Option<PathBuf>,
|
file: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_context(#[cfg(feature = "inspector")] cli: &Cli) -> Result<Context> {
|
|
||||||
#[cfg(feature = "inspector")]
|
|
||||||
{
|
|
||||||
let (addr_str, wait) = if let Some(ref addr) = cli.inspect_brk {
|
|
||||||
(Some(addr.as_str()), true)
|
|
||||||
} else if let Some(ref addr) = cli.inspect {
|
|
||||||
(Some(addr.as_str()), false)
|
|
||||||
} else {
|
|
||||||
(None, false)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(addr_str) = addr_str {
|
|
||||||
let addr: std::net::SocketAddr = addr_str
|
|
||||||
.parse()
|
|
||||||
.map_err(|e| anyhow::anyhow!("invalid inspector address '{}': {}", addr_str, e))?;
|
|
||||||
return Ok(Context::new_with_inspector(addr, wait)?);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Context::new()?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_compile(context: &mut Context, src: ExprSource, silent: bool) -> Result<()> {
|
fn run_compile(context: &mut Context, src: ExprSource, silent: bool) -> Result<()> {
|
||||||
let src = if let Some(expr) = src.expr {
|
let src = if let Some(expr) = src.expr {
|
||||||
Source::new_eval(expr)?
|
Source::new_eval(expr)?
|
||||||
@@ -88,8 +59,6 @@ fn run_compile(context: &mut Context, src: ExprSource, silent: bool) -> Result<(
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#[cfg(feature = "inspector")]
|
|
||||||
context.wait_for_inspector_disconnect();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,8 +79,6 @@ fn run_eval(context: &mut Context, src: ExprSource) -> Result<()> {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#[cfg(feature = "inspector")]
|
|
||||||
context.wait_for_inspector_disconnect();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,14 +137,11 @@ fn run_repl(context: &mut Context) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
nix_js::logging::init_logging();
|
fix::logging::init_logging();
|
||||||
|
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
||||||
let mut context = create_context(
|
let mut context = Context::new()?;
|
||||||
#[cfg(feature = "inspector")]
|
|
||||||
&cli,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
match cli.command {
|
match cli.command {
|
||||||
Command::Compile { source, silent } => run_compile(&mut context, source, silent),
|
Command::Compile { source, silent } => run_compile(&mut context, source, silent),
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use nix_js::value::Value;
|
use fix::value::Value;
|
||||||
|
|
||||||
use crate::utils::{eval, eval_result};
|
use crate::utils::{eval, eval_result};
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use nix_js::value::{AttrSet, List, Value};
|
use fix::value::{AttrSet, List, Value};
|
||||||
|
|
||||||
use crate::utils::eval;
|
use crate::utils::eval;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use nix_js::value::Value;
|
use fix::value::Value;
|
||||||
|
|
||||||
use crate::utils::eval_result;
|
use crate::utils::eval_result;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use nix_js::value::Value;
|
use fix::value::Value;
|
||||||
|
|
||||||
use crate::utils::{eval_deep, eval_deep_result};
|
use crate::utils::{eval_deep, eval_deep_result};
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use nix_js::value::{List, Value};
|
use fix::value::{List, Value};
|
||||||
|
|
||||||
use crate::utils::{eval, eval_result};
|
use crate::utils::{eval, eval_result};
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use nix_js::value::Value;
|
use fix::value::Value;
|
||||||
|
|
||||||
use crate::utils::{eval, eval_result};
|
use crate::utils::{eval, eval_result};
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use nix_js::context::Context;
|
use fix::context::Context;
|
||||||
use nix_js::error::Source;
|
use fix::error::Source;
|
||||||
use nix_js::value::Value;
|
use fix::value::Value;
|
||||||
|
|
||||||
use crate::utils::{eval, eval_result};
|
use crate::utils::{eval, eval_result};
|
||||||
|
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use nix_js::context::Context;
|
use fix::context::Context;
|
||||||
use nix_js::error::Source;
|
use fix::error::Source;
|
||||||
use nix_js::value::Value;
|
use fix::value::Value;
|
||||||
|
|
||||||
fn get_lang_dir() -> PathBuf {
|
fn get_lang_dir() -> PathBuf {
|
||||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/tests/lang")
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/tests/lang")
|
||||||
@@ -18,7 +18,7 @@ fn eval_file(name: &str) -> Result<(Value, Source), String> {
|
|||||||
|
|
||||||
let mut ctx = Context::new().map_err(|e| e.to_string())?;
|
let mut ctx = Context::new().map_err(|e| e.to_string())?;
|
||||||
let source = Source {
|
let source = Source {
|
||||||
ty: nix_js::error::SourceType::File(nix_path.into()),
|
ty: fix::error::SourceType::File(nix_path.into()),
|
||||||
src: expr.into(),
|
src: expr.into(),
|
||||||
};
|
};
|
||||||
ctx.eval_deep(source.clone())
|
ctx.eval_deep(source.clone())
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user