Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions fjs/nanvm/module.f.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -344,9 +344,6 @@ const mulCases = [
{ name: 'numberByBigint', args: [1, 1n], expected: throws },
]

const hexadecimalBigint =
'nanvm-lib prints bigints in hexadecimal; see nanvm-lib/todo/bigint-decimal-string-coercion.md'

/**
* `String(x)`.
*
Expand All @@ -369,8 +366,8 @@ const stringCoercionCases = [
{ name: 'null', args: [null], expected: 'null' },
{ name: 'undefined', args: [undefined], expected: 'undefined' },
{ name: 'string', args: ['already'], expected: 'already' },
{ name: 'bigint', args: [123n], expected: '123', rust: hexadecimalBigint },
{ name: 'negativeBigint', args: [-456n], expected: '-456', rust: hexadecimalBigint },
{ name: 'bigint', args: [123n], expected: '123' },
{ name: 'negativeBigint', args: [-456n], expected: '-456' },
Comment on lines +369 to +370

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove the obsolete known-divergence documentation

With bigint coercion now enabled, fjs/nanvm/README.md lines 84–91 still claims that NaNVM returns hexadecimal text and that these cases carry a rust exclusion; it also links to the todo file deleted by this commit. A repo-wide search finds no replacement target, so readers now see both incorrect behavior documentation and a broken link; remove or update that section in this change.

Useful? React with 👍 / 👎.

{ name: 'emptyArray', args: [[]], expected: '' },
{ name: 'singletonArray', args: [[1]], expected: '1' },
{ name: 'array', args: [[1, 2, 3]], expected: '1,2,3' },
Expand Down
41 changes: 41 additions & 0 deletions nanvm-lib/src/vm/bigint/display.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::{
common::sized_index::SizedIndex,
sign::Sign,
vm::{BigInt, IContainer, IVm},
};
use core::fmt::{Display, Formatter, Result, Write};

const DECIMAL_BASE: u64 = 10_000_000_000_000_000_000;

impl<A: IVm> Display for BigInt<A> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
if self.is_zero() {
return f.write_char('0');
}
if *self.0.header() == Sign::Negative {
f.write_char('-')?;
}

let items = self.0.items();
let mut words: Vec<u64> = (0..items.length()).map(|i| items[i]).collect();
let mut groups = Vec::new();
while !words.is_empty() {
let mut remainder = 0u128;
for word in words.iter_mut().rev() {
let dividend = (remainder << 64) | *word as u128;
*word = (dividend / DECIMAL_BASE as u128) as u64;
remainder = dividend % DECIMAL_BASE as u128;
}
groups.push(remainder as u64);
while words.last() == Some(&0) {
words.pop();
}
}

write!(f, "{}", groups.pop().unwrap())?;
for group in groups.iter().rev() {
write!(f, "{group:019}")?;
}
Ok(())
}
}
1 change: 1 addition & 0 deletions nanvm-lib/src/vm/bigint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod add;
mod cmp;
mod debug;
mod default;
mod display;
mod from;
mod index;
mod mul;
Expand Down
3 changes: 1 addition & 2 deletions nanvm-lib/src/vm/string_coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ impl<A: IVm> Dispatch<A> for StringCoercion {
}

fn bigint(self, v: BigInt<A>) -> Self::Result {
// TODO: we should use different algorithm for large numbers.
to_result(&format!("{v:?}"))
to_result(&v.to_string())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the required unreleased changelog entry

This changes the user-visible behavior of bigint string coercion, but the commit adds no changelog/unreleased/<PR>.md, so the fix will be absent from the next published changelog. Add a short entry for the behavior change once the PR number is available.

AGENTS.md reference: AGENTS.md:L89-L93

Useful? React with 👍 / 👎.

}

fn object(self, v: Object<A>) -> Self::Result {
Expand Down
6 changes: 2 additions & 4 deletions nanvm-lib/tests/test/generated.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions nanvm-lib/tests/test/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,24 @@ fn bigint_debug_format<A: IVm>() {
}
}

/// Decimal display across limb and decimal-group boundaries.
fn bigint_display_format<A: IVm>() {
let zero: BigInt<A> = 0u64.into();
assert_eq!(zero.to_string(), "0");

let two_to_64 = BigInt::<A>::normalize_new(Sign::Positive, [0, 1]);
assert_eq!(two_to_64.to_string(), "18446744073709551616");

let max_u128 = BigInt::<A>::normalize_new(Sign::Positive, [u64::MAX, u64::MAX]);
assert_eq!(
max_u128.to_string(),
"340282366920938463463374607431768211455"
);

let negative = BigInt::<A>::normalize_new(Sign::Negative, [0, 1]);
assert_eq!(negative.to_string(), "-18446744073709551616");
}

fn format_fn<A: IVm>() {
let f = Function::<A>(A::InternalFunction::new_ok(
("myfunc".into(), 2),
Expand Down Expand Up @@ -185,6 +203,7 @@ fn gen_test<A: IVm>() {
conversions::<A>();
debug_format::<A>();
bigint_debug_format::<A>();
bigint_display_format::<A>();
unary_plus_bigint_message::<A>();
bigint_add::<A>();
bigint_mul::<A>();
Expand Down
54 changes: 0 additions & 54 deletions nanvm-lib/todo/bigint-decimal-string-coercion.md

This file was deleted.