From c79eb0951e3f44a171b27f1fb946059042c79644 Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Sat, 3 Jan 2026 12:19:43 +0800 Subject: [PATCH] fix(runtime::to_value): numbers are always NixFloat --- .envrc | 1 + nix-js/src/context.rs | 22 +++++++++------------- nix-js/src/runtime.rs | 16 ++++------------ 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/.envrc b/.envrc index 3550a30..3b11770 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,2 @@ use flake +dotenv diff --git a/nix-js/src/context.rs b/nix-js/src/context.rs index a516afb..44aa6bb 100644 --- a/nix-js/src/context.rs +++ b/nix-js/src/context.rs @@ -1,6 +1,7 @@ use std::ptr::NonNull; use hashbrown::HashMap; +use itertools::Itertools as _; use string_interner::DefaultStringInterner; use crate::codegen::{CodegenContext, Compile}; @@ -15,7 +16,7 @@ mod downgrade; pub struct Context { irs: Vec, symbols: DefaultStringInterner, - global: NonNull>, + global: NonNull>, } impl Drop for Context { @@ -99,14 +100,7 @@ impl Context { pub fn eval(&mut self, expr: &str) -> Result { let root = rnix::Root::parse(expr); if !root.errors().is_empty() { - return Err(Error::parse_error(root.errors().iter().fold( - String::new(), - |mut acc, err| { - acc.push_str(&err.to_string()); - acc.push_str("; "); - acc - }, - ))); + return Err(Error::parse_error(root.errors().iter().join("; "))); } let root = self .downgrade_ctx() @@ -331,11 +325,9 @@ mod test { #[test] fn test_builtin_function_map() { - // Test higher-order builtin: builtins.map (x: x * 2) [1 2 3] + // Test higher-order builtin: map (x: x * 2) [1 2 3] assert_eq!( - Context::new() - .eval("builtins.map (x: x * 2) [1 2 3]") - .unwrap(), + Context::new().eval("map (x: x * 2) [1 2 3]").unwrap(), Value::List(List::new(vec![ Value::Const(Const::Int(2)), Value::Const(Const::Int(4)), @@ -628,6 +620,10 @@ mod test { ctx.eval("builtins.typeOf 3.14").unwrap(), Value::String("float".to_string()) ); + + // literal tests + assert_eq!(ctx.eval("1").unwrap(), Value::Const(Const::Int(1))); + assert_eq!(ctx.eval("1.").unwrap(), Value::Const(Const::Float(1.))) } #[test] diff --git a/nix-js/src/runtime.rs b/nix-js/src/runtime.rs index a677eed..157ad88 100644 --- a/nix-js/src/runtime.rs +++ b/nix-js/src/runtime.rs @@ -146,16 +146,8 @@ fn to_value<'a, 'b>(val: v8::Local<'a, v8::Value>, ctx: &RuntimeContext<'a, 'b>) } _ if val.is_number() => { let val = val.to_number(scope).unwrap().value(); - // Heuristic: convert whole numbers to Int (for backward compatibility and JS interop) - if val.is_finite() - && val.fract() == 0.0 - && val >= i64::MIN as f64 - && val <= i64::MAX as f64 - { - Value::Const(Const::Int(val as i64)) - } else { - Value::Const(Const::Float(val)) - } + // number is always NixFloat + Value::Const(Const::Float(val)) } _ if val.is_true() => Value::Const(Const::Bool(true)), _ if val.is_false() => Value::Const(Const::Bool(false)), @@ -280,13 +272,13 @@ fn primop_app_name<'a, 'b>( fn to_value_working() { assert_eq!( run("({ - test: [1, 9223372036854775807n, true, false, 'hello world!'] + test: [1., 9223372036854775807n, true, false, 'hello world!'] })") .unwrap(), Value::AttrSet(AttrSet::new(std::collections::BTreeMap::from([( Symbol::from("test"), Value::List(List::new(vec![ - Value::Const(Const::Int(1)), + Value::Const(Const::Float(1.)), Value::Const(Const::Int(9223372036854775807)), Value::Const(Const::Bool(true)), Value::Const(Const::Bool(false)),