clean up
This commit is contained in:
511 files changed
+234
-12772
No files matched your search
@@ -16,9 +16,6 @@ vim.lsp.config("rust_analyzer", {
|
||||
settings = {
|
||||
["rust-analyzer"] = {
|
||||
cargo = {
|
||||
features = {
|
||||
"inspector"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+111
-967
File diff suppressed because it is too large.
Load diff
+1
-2
@@ -1,8 +1,7 @@
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = [
|
||||
"nix-js",
|
||||
"nix-js-macros"
|
||||
"fix"
|
||||
]
|
||||
|
||||
[profile.profiling]
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
[package]
|
||||
name = "nix-js"
|
||||
name = "fix"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
mimalloc = "0.1"
|
||||
@@ -35,9 +34,6 @@ itertools = "0.14"
|
||||
|
||||
regex = "1.11"
|
||||
|
||||
deno_core = "0.385"
|
||||
deno_error = "0.7"
|
||||
|
||||
nix-nar = "0.3"
|
||||
sha2 = "0.10"
|
||||
sha1 = "0.10"
|
||||
@@ -54,7 +50,7 @@ bzip2 = "0.6"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
# spec 1.0.0
|
||||
toml = "0.9.9"
|
||||
toml = "=0.9.9"
|
||||
dirs = "6.0"
|
||||
tempfile = "3.24"
|
||||
rusqlite = { version = "0.38", features = ["bundled"] }
|
||||
@@ -62,24 +58,15 @@ rusqlite = { version = "0.38", features = ["bundled"] }
|
||||
rnix = "0.14"
|
||||
rowan = "0.16"
|
||||
|
||||
nix-js-macros = { path = "../nix-js-macros" }
|
||||
ere = "0.2.4"
|
||||
num_enum = "0.7.5"
|
||||
tap = "1.0.1"
|
||||
|
||||
# Inspector (optional)
|
||||
fastwebsockets = { version = "0.10", features = ["upgrade"], optional = true }
|
||||
hyper = { version = "1", features = ["http1", "server"], optional = true }
|
||||
hyper-util = { version = "0.1", features = ["tokio"], optional = true }
|
||||
http-body-util = { version = "0.1", optional = true }
|
||||
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 = []
|
||||
ghost-cell = "0.2"
|
||||
colored = "3.1"
|
||||
boxing = "0.1"
|
||||
gc-arena = { version = "0.5.3", features = ["allocator-api2"] }
|
||||
allocator-api2 = "0.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.8", features = ["html_reports"] }
|
||||
@@ -96,7 +83,3 @@ harness = false
|
||||
[[bench]]
|
||||
name = "thunk_scope"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "compile_time"
|
||||
harness = false
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,8 +1,8 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use nix_js::context::Context;
|
||||
use nix_js::error::{Result, Source};
|
||||
use nix_js::value::Value;
|
||||
use fix::context::Context;
|
||||
use fix::error::{Result, Source};
|
||||
use fix::value::Value;
|
||||
|
||||
pub fn eval(expr: &str) -> Value {
|
||||
Context::new()
|
||||
@@ -16,10 +16,3 @@ pub fn eval_result(expr: &str) -> Result<Value> {
|
||||
.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)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub enum Op {
|
||||
PushConst = 0x01,
|
||||
PushString = 0x02,
|
||||
PushNull = 0x03,
|
||||
PushTrue = 0x04,
|
||||
PushFalse = 0x05,
|
||||
PushConst,
|
||||
PushString,
|
||||
PushNull,
|
||||
PushTrue,
|
||||
PushFalse,
|
||||
|
||||
LoadLocal = 0x06,
|
||||
LoadOuter = 0x07,
|
||||
StoreLocal = 0x08,
|
||||
AllocLocals = 0x09,
|
||||
LoadLocal,
|
||||
LoadOuter,
|
||||
StoreLocal,
|
||||
AllocLocals,
|
||||
|
||||
MakeThunk = 0x0A,
|
||||
MakeClosure = 0x0B,
|
||||
MakePatternClosure = 0x0C,
|
||||
MakeThunk,
|
||||
MakeClosure,
|
||||
MakePatternClosure,
|
||||
|
||||
Call = 0x0D,
|
||||
CallNoSpan = 0x0E,
|
||||
Call,
|
||||
CallNoSpan,
|
||||
|
||||
MakeAttrs = 0x0F,
|
||||
MakeAttrsDyn = 0x10,
|
||||
MakeEmptyAttrs = 0x11,
|
||||
Select = 0x12,
|
||||
SelectDefault = 0x13,
|
||||
HasAttr = 0x14,
|
||||
MakeAttrs,
|
||||
MakeAttrsDyn,
|
||||
MakeEmptyAttrs,
|
||||
Select,
|
||||
SelectDefault,
|
||||
HasAttr,
|
||||
|
||||
MakeList = 0x15,
|
||||
MakeList,
|
||||
|
||||
OpAdd = 0x16,
|
||||
OpSub = 0x17,
|
||||
OpMul = 0x18,
|
||||
OpDiv = 0x19,
|
||||
OpEq = 0x20,
|
||||
OpNeq = 0x21,
|
||||
OpLt = 0x22,
|
||||
OpGt = 0x23,
|
||||
OpLeq = 0x24,
|
||||
OpGeq = 0x25,
|
||||
OpConcat = 0x26,
|
||||
OpUpdate = 0x27,
|
||||
OpAdd,
|
||||
OpSub,
|
||||
OpMul,
|
||||
OpDiv,
|
||||
OpEq,
|
||||
OpNeq,
|
||||
OpLt,
|
||||
OpGt,
|
||||
OpLeq,
|
||||
OpGeq,
|
||||
OpConcat,
|
||||
OpUpdate,
|
||||
|
||||
OpNeg = 0x28,
|
||||
OpNot = 0x29,
|
||||
OpNeg,
|
||||
OpNot,
|
||||
|
||||
ForceBool = 0x30,
|
||||
JumpIfFalse = 0x31,
|
||||
JumpIfTrue = 0x32,
|
||||
Jump = 0x33,
|
||||
ForceBool,
|
||||
JumpIfFalse,
|
||||
JumpIfTrue,
|
||||
Jump,
|
||||
|
||||
ConcatStrings = 0x34,
|
||||
ResolvePath = 0x35,
|
||||
ConcatStrings,
|
||||
ResolvePath,
|
||||
|
||||
Assert = 0x36,
|
||||
Assert,
|
||||
|
||||
PushWith = 0x37,
|
||||
PopWith = 0x38,
|
||||
WithLookup = 0x39,
|
||||
PushWith,
|
||||
PopWith,
|
||||
WithLookup,
|
||||
|
||||
LoadBuiltins = 0x40,
|
||||
LoadBuiltin = 0x41,
|
||||
LoadBuiltins,
|
||||
LoadBuiltin,
|
||||
|
||||
MkPos = 0x43,
|
||||
MkPos,
|
||||
|
||||
LoadReplBinding = 0x44,
|
||||
LoadScopedBinding = 0x45,
|
||||
LoadReplBinding,
|
||||
LoadScopedBinding,
|
||||
|
||||
Return = 0x46,
|
||||
Return,
|
||||
}
|
||||
|
||||
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> {
|
||||
fn new(ctx: &'a mut Ctx) -> 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<'_>)]) {
|
||||
for &(id, inner) in thunks {
|
||||
let label = format!("e{}", id.0);
|
||||
@@ -9,14 +9,10 @@ use rnix::TextRange;
|
||||
use string_interner::DefaultStringInterner;
|
||||
|
||||
use crate::bytecode::{self, Bytecode, BytecodeContext, Constant};
|
||||
use crate::codegen::{CodegenContext, compile};
|
||||
use crate::disassembler::{Disassembler, DisassemblerContext};
|
||||
use crate::downgrade::*;
|
||||
use crate::error::{Error, Result, Source};
|
||||
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::value::{Symbol, Value};
|
||||
|
||||
@@ -48,129 +44,27 @@ fn handle_parse_error<'a>(
|
||||
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 {
|
||||
pub fn new() -> Result<Self> {
|
||||
let ctx = Ctx::new()?;
|
||||
#[cfg(feature = "inspector")]
|
||||
let runtime = Runtime::new(Default::default())?;
|
||||
#[cfg(not(feature = "inspector"))]
|
||||
let runtime = Runtime::new()?;
|
||||
|
||||
let mut context = Self {
|
||||
ctx,
|
||||
runtime,
|
||||
#[cfg(feature = "inspector")]
|
||||
_inspector_server: None,
|
||||
};
|
||||
context.init()?;
|
||||
|
||||
Ok(context)
|
||||
pub fn eval(&mut self, _source: Source) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
pub fn eval_shallow(&mut self, _source: Source) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
pub fn eval_deep(&mut self, _source: Source) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[cfg(feature = "inspector")]
|
||||
pub fn new_with_inspector(addr: std::net::SocketAddr, wait_for_session: bool) -> Result<Self> {
|
||||
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 eval_repl<'a>(&'a mut self, _source: Source, _scope: &'a HashSet<SymId>) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
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 {
|
||||
Disassembler::new(bytecode, &self.ctx).disassemble_colored()
|
||||
}
|
||||
|
||||
pub fn get_store_dir(&self) -> &str {
|
||||
self.ctx.get_store_dir()
|
||||
Disassembler::new(bytecode, self).disassemble_colored()
|
||||
}
|
||||
|
||||
pub fn add_binding<'a>(
|
||||
@@ -179,22 +73,11 @@ impl Context {
|
||||
expr: &str,
|
||||
scope: &'a mut HashSet<SymId>,
|
||||
) -> Result<Value> {
|
||||
let source = Source::new_repl(expr.to_string())?;
|
||||
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)
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
struct Ctx {
|
||||
pub struct Context {
|
||||
symbols: DefaultStringInterner,
|
||||
global: HashMap<SymId, Ir<'static, RawIrRef<'static>>>,
|
||||
sources: Vec<Source>,
|
||||
@@ -226,8 +109,8 @@ impl OwnedIr {
|
||||
}
|
||||
}
|
||||
|
||||
impl Ctx {
|
||||
fn new() -> Result<Self> {
|
||||
impl Context {
|
||||
pub fn new() -> Result<Self> {
|
||||
let mut symbols = DefaultStringInterner::new();
|
||||
let mut global = HashMap::new();
|
||||
let builtins_sym = symbols.get_or_intern("builtins");
|
||||
@@ -349,33 +232,7 @@ impl Ctx {
|
||||
})
|
||||
}
|
||||
|
||||
fn compile<'ctx>(
|
||||
&'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> {
|
||||
pub fn compile_bytecode(&mut self, source: Source) -> Result<Bytecode> {
|
||||
let root = self.downgrade(source, None)?;
|
||||
tracing::debug!("Generating bytecode");
|
||||
let bytecode = bytecode::compile_bytecode(root.as_ref(), self);
|
||||
@@ -383,47 +240,12 @@ impl Ctx {
|
||||
Ok(bytecode)
|
||||
}
|
||||
|
||||
fn compile_bytecode_scoped(&mut self, source: Source, scope: Vec<String>) -> Result<Bytecode> {
|
||||
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 {
|
||||
pub fn get_store_dir(&self) -> &str {
|
||||
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 {
|
||||
if let Some(&idx) = self.global_string_map.get(s) {
|
||||
return idx;
|
||||
@@ -445,7 +267,16 @@ impl BytecodeContext for Ctx {
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -453,51 +284,11 @@ impl BytecodeContext for Ctx {
|
||||
}
|
||||
|
||||
fn get_current_dir(&self) -> &Path {
|
||||
Ctx::get_current_dir(self)
|
||||
Context::get_current_dir(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl RuntimeContext for Ctx {
|
||||
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 {
|
||||
impl DisassemblerContext for Context {
|
||||
fn lookup_string(&self, id: u32) -> &str {
|
||||
self.global_strings
|
||||
.get(id as usize)
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,14 +1,9 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use deno_core::error::JsError;
|
||||
use deno_error::JsErrorClass as _;
|
||||
use itertools::Itertools as _;
|
||||
use miette::{Diagnostic, NamedSource, SourceSpan};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::runtime::RuntimeContext;
|
||||
|
||||
pub type Result<T> = core::result::Result<T, Box<Error>>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -229,127 +224,3 @@ pub struct StackFrame {
|
||||
#[source_code]
|
||||
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 tracing::{debug, info, warn};
|
||||
|
||||
use crate::runtime::OpStateExt;
|
||||
use crate::runtime::RuntimeContext;
|
||||
use crate::store::Store as _;
|
||||
|
||||
mod archive;
|
||||
@@ -20,7 +18,6 @@ pub use download::Downloader;
|
||||
pub use metadata_cache::MetadataCache;
|
||||
|
||||
use crate::nar;
|
||||
use crate::runtime::NixRuntimeError;
|
||||
|
||||
#[derive(ToV8)]
|
||||
pub struct FetchUrlResult {
|
||||
@@ -306,11 +303,3 @@ fn normalize_hash(hash: &str) -> 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>(),
|
||||
]
|
||||
}
|
||||
File renamed without changes.
@@ -10,7 +10,7 @@ impl FetcherCache {
|
||||
pub fn new() -> Result<Self, std::io::Error> {
|
||||
let base_dir = dirs::cache_dir()
|
||||
.unwrap_or_else(|| PathBuf::from("/tmp"))
|
||||
.join("nix-js")
|
||||
.join("fix")
|
||||
.join("fetchers");
|
||||
|
||||
fs::create_dir_all(&base_dir)?;
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -6,11 +6,10 @@ pub mod logging;
|
||||
pub mod value;
|
||||
|
||||
mod bytecode;
|
||||
mod codegen;
|
||||
mod derivation;
|
||||
mod disassembler;
|
||||
mod downgrade;
|
||||
mod fetcher;
|
||||
// mod fetcher;
|
||||
mod ir;
|
||||
mod nar;
|
||||
mod nix_utils;
|
||||
File renamed without changes.
@@ -4,22 +4,14 @@ use std::process::exit;
|
||||
use anyhow::Result;
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use hashbrown::HashSet;
|
||||
use nix_js::context::Context;
|
||||
use nix_js::error::Source;
|
||||
use fix::context::Context;
|
||||
use fix::error::Source;
|
||||
use rustyline::DefaultEditor;
|
||||
use rustyline::error::ReadlineError;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "nix-js", about = "Nix expression evaluator")]
|
||||
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: Command,
|
||||
}
|
||||
@@ -48,27 +40,6 @@ struct ExprSource {
|
||||
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<()> {
|
||||
let src = if let Some(expr) = src.expr {
|
||||
Source::new_eval(expr)?
|
||||
@@ -88,8 +59,6 @@ fn run_compile(context: &mut Context, src: ExprSource, silent: bool) -> Result<(
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
#[cfg(feature = "inspector")]
|
||||
context.wait_for_inspector_disconnect();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -110,8 +79,6 @@ fn run_eval(context: &mut Context, src: ExprSource) -> Result<()> {
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
#[cfg(feature = "inspector")]
|
||||
context.wait_for_inspector_disconnect();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -170,14 +137,11 @@ fn run_repl(context: &mut Context) -> Result<()> {
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
nix_js::logging::init_logging();
|
||||
fix::logging::init_logging();
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
let mut context = create_context(
|
||||
#[cfg(feature = "inspector")]
|
||||
&cli,
|
||||
)?;
|
||||
let mut context = Context::new()?;
|
||||
|
||||
match cli.command {
|
||||
Command::Compile { source, silent } => run_compile(&mut context, source, silent),
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,4 +1,4 @@
|
||||
use nix_js::value::Value;
|
||||
use fix::value::Value;
|
||||
|
||||
use crate::utils::{eval, eval_result};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use nix_js::value::{AttrSet, List, Value};
|
||||
use fix::value::{AttrSet, List, Value};
|
||||
|
||||
use crate::utils::eval;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use nix_js::value::Value;
|
||||
use fix::value::Value;
|
||||
|
||||
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};
|
||||
|
||||
File renamed without changes.
@@ -1,4 +1,4 @@
|
||||
use nix_js::value::{List, Value};
|
||||
use fix::value::{List, Value};
|
||||
|
||||
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};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use nix_js::context::Context;
|
||||
use nix_js::error::Source;
|
||||
use nix_js::value::Value;
|
||||
use fix::context::Context;
|
||||
use fix::error::Source;
|
||||
use fix::value::Value;
|
||||
|
||||
use crate::utils::{eval, eval_result};
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use nix_js::context::Context;
|
||||
use nix_js::error::Source;
|
||||
use nix_js::value::Value;
|
||||
use fix::context::Context;
|
||||
use fix::error::Source;
|
||||
use fix::value::Value;
|
||||
|
||||
fn get_lang_dir() -> PathBuf {
|
||||
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 source = Source {
|
||||
ty: nix_js::error::SourceType::File(nix_path.into()),
|
||||
ty: fix::error::SourceType::File(nix_path.into()),
|
||||
src: expr.into(),
|
||||
};
|
||||
ctx.eval_deep(source.clone())
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 511 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user