diff --git a/.forgejo/workflows/webrepl.yaml b/.forgejo/workflows/webrepl.yaml index d97ef54..2f19712 100644 --- a/.forgejo/workflows/webrepl.yaml +++ b/.forgejo/workflows/webrepl.yaml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v4 - name: Build talc-web - run: wasm-pack build --release --no-typescript --no-pack --target web + run: RUSTFLAGS='--cfg getrandom_backend="wasm_js"' wasm-pack build --release --no-typescript --no-pack --target web working-directory: talc-web - name: Save artifacts diff --git a/Cargo.lock b/Cargo.lock index 6b01cc2..b87b5d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,15 +145,16 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" dependencies = [ "cfg-if", "js-sys", "libc", "wasi", "wasm-bindgen", + "windows-targets", ] [[package]] @@ -254,7 +255,6 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", - "rand", ] [[package]] @@ -318,7 +318,7 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -351,20 +351,20 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ - "libc", "rand_chacha", "rand_core", + "zerocopy 0.8.16", ] [[package]] name = "rand_chacha" -version = "0.3.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", "rand_core", @@ -372,11 +372,12 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" dependencies = [ "getrandom", + "zerocopy 0.8.16", ] [[package]] @@ -468,7 +469,7 @@ dependencies = [ [[package]] name = "talc-bin" -version = "0.2.2" +version = "0.2.3" dependencies = [ "clap", "ctrlc", @@ -480,7 +481,7 @@ dependencies = [ [[package]] name = "talc-lang" -version = "0.2.2" +version = "0.2.3" dependencies = [ "lazy_static", "num", @@ -497,10 +498,9 @@ dependencies = [ [[package]] name = "talc-std" -version = "0.2.2" +version = "0.2.3" dependencies = [ "lazy_static", - "num-bigint", "rand", "regex", "talc-lang", @@ -509,7 +509,7 @@ dependencies = [ [[package]] name = "talc-web" -version = "0.1.0" +version = "0.2.3" dependencies = [ "getrandom", "talc-lang", @@ -543,9 +543,12 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.13.3+wasi-0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] [[package]] name = "wasm-bindgen" @@ -687,6 +690,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -694,7 +706,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b8c07a70861ce02bad1607b5753ecb2501f67847b9f9ada7c160fff0ec6300c" +dependencies = [ + "zerocopy-derive 0.8.16", ] [[package]] @@ -707,3 +728,14 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zerocopy-derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5226bc9a9a9836e7428936cde76bb6b22feea1a8bfdbc0d241136e4d13417e25" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/talc-bin/Cargo.toml b/talc-bin/Cargo.toml index d488f24..1fb603e 100644 --- a/talc-bin/Cargo.toml +++ b/talc-bin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "talc-bin" -version = "0.2.2" +version = "0.2.3" edition = "2021" rust-version = "1.81.0" diff --git a/talc-lang/Cargo.toml b/talc-lang/Cargo.toml index 5ca1dc0..e537e01 100644 --- a/talc-lang/Cargo.toml +++ b/talc-lang/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "talc-lang" -version = "0.2.2" +version = "0.2.3" edition = "2021" rust-version = "1.81.0" diff --git a/talc-lang/src/lib.rs b/talc-lang/src/lib.rs index 0eef978..2b848bf 100644 --- a/talc-lang/src/lib.rs +++ b/talc-lang/src/lib.rs @@ -18,3 +18,5 @@ pub mod prelude { ConstOne, ConstZero, Euclid, FromPrimitive, Num, One, Signed, ToPrimitive, Zero, }; } + +pub use num; diff --git a/talc-std/Cargo.toml b/talc-std/Cargo.toml index 21ba721..a22aa5e 100644 --- a/talc-std/Cargo.toml +++ b/talc-std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "talc-std" -version = "0.2.2" +version = "0.2.3" edition = "2021" rust-version = "1.81.0" @@ -11,12 +11,11 @@ workspace = true talc-lang = { path = "../talc-lang" } talc-macros = { path = "../talc-macros" } lazy_static = "1" -num-bigint = { version = "0.4", features = ["rand"], optional = true } regex = { version = "1", optional = true } -rand = { version = "0.8", optional = true } +rand = { version = "0.9", optional = true } [features] default = ["rand", "regex", "file"] -rand = ["dep:rand", "dep:num-bigint"] +rand = ["dep:rand"] regex = ["dep:regex"] file = [] diff --git a/talc-std/src/random.rs b/talc-std/src/random.rs index 2afc04a..2c0f378 100644 --- a/talc-std/src/random.rs +++ b/talc-std/src/random.rs @@ -1,8 +1,12 @@ -use num_bigint::RandBigInt; -use rand::{seq::SliceRandom, Rng}; +use rand::{ + seq::{IndexedRandom, SliceRandom}, + Rng, +}; use talc_lang::{ exception::Result, + num::bigint::{BigInt, BigUint, Sign}, number::Int, + prelude::*, symbol::{SYM_TYPE_ERROR, SYM_VALUE_ERROR}, throw, value::Value, @@ -21,7 +25,39 @@ pub fn load(vm: &mut Vm) { #[native_func(0)] pub fn rand(_: &mut Vm, _: Vec) -> Result { - Ok(Value::Float(rand::thread_rng().gen())) + Ok(Value::Float(rand::rng().random())) +} + +pub fn rand_int(mut rng: R, low: &BigInt, high: &BigInt) -> Int { + let (sign, range) = (high - low).into_parts(); + assert!(sign == Sign::Plus); + if let (Some(low), Some(high)) = (low.to_i64(), high.to_i64()) { + return Int::from(rng.random_range(low..high)) + } + let bits = range.bits(); + let (digits, rem) = bits.div_rem(&32); + let digits = usize::try_from(digits).expect("more digits than usize?"); + let len = digits + if rem == 0 { 0 } else { 1 }; + let mut data = vec![0u32; len]; + let v = loop { + rng.fill(&mut data[..]); + if rem > 0 { + data[len - 1] >>= 32 - rem; + } + let v = BigUint::new(data); + if v < range { + break v + } + data = v.to_u32_digits(); + }; + + let sign = if v == BigUint::ZERO { + Sign::NoSign + } else { + Sign::Plus + }; + let v = BigInt::from_biguint(sign, v); + Int::from(v + low) } #[native_func(1)] @@ -30,7 +66,7 @@ pub fn rand_in(vm: &mut Vm, args: Vec) -> Result { match col { Value::List(l) => { let l = l.borrow(); - let Some(v) = l.choose(&mut rand::thread_rng()) else { + let Some(v) = l.choose(&mut rand::rng()) else { throw!(*SYM_VALUE_ERROR, "rand_in: empty list") }; Ok(v.clone()) @@ -40,7 +76,7 @@ pub fn rand_in(vm: &mut Vm, args: Vec) -> Result { if t.is_empty() { throw!(*SYM_VALUE_ERROR, "rand_in: empty table") }; - let i = rand::thread_rng().gen_range(0..t.len()); + let i = rand::rng().random_range(0..t.len()); let key = t.keys().nth(i).unwrap(); Ok(key.clone().into_inner()) } @@ -52,9 +88,9 @@ pub fn rand_in(vm: &mut Vm, args: Vec) -> Result { throw!(*SYM_VALUE_ERROR, "rand_in: infinite range") }; if r.inclusive { - Ok(Int::from(rand::thread_rng().gen_bigint_range(s, &(e + 1))).into()) + Ok(rand_int(rand::rng(), s, &(e + 1)).into()) } else { - Ok(Int::from(rand::thread_rng().gen_bigint_range(s, e)).into()) + Ok(rand_int(rand::rng(), s, e).into()) } } col => { @@ -66,7 +102,7 @@ pub fn rand_in(vm: &mut Vm, args: Vec) -> Result { if values.is_empty() { throw!(*SYM_VALUE_ERROR, "rand_in: empty iterator") } - let i = rand::thread_rng().gen_range(0..values.len()); + let i = rand::rng().random_range(0..values.len()); let v = values.swap_remove(i); Ok(v) } @@ -79,6 +115,6 @@ pub fn shuf(_: &mut Vm, args: Vec) -> Result { let Value::List(list) = list else { throw!(*SYM_TYPE_ERROR, "shuf expected list, got {list:#}") }; - list.borrow_mut().shuffle(&mut rand::thread_rng()); + list.borrow_mut().shuffle(&mut rand::rng()); Ok(Value::List(list)) } diff --git a/talc-web/Cargo.toml b/talc-web/Cargo.toml index 8f52a5c..721171c 100644 --- a/talc-web/Cargo.toml +++ b/talc-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "talc-web" -version = "0.1.0" +version = "0.2.3" edition = "2021" rust-version = "1.81.0" @@ -13,5 +13,5 @@ workspace = true [dependencies] talc-lang = { path = "../talc-lang" } talc-std = { path = "../talc-std", default-features = false, features = ["rand", "regex"] } -getrandom = { version = "0.2", features = ["js"] } +getrandom = { version = "0.3", features = ["wasm_js"] } wasm-bindgen = "0.2" diff --git a/talc-web/README.md b/talc-web/README.md index 47bd9dc..2da9511 100644 --- a/talc-web/README.md +++ b/talc-web/README.md @@ -9,7 +9,7 @@ creates an alternative to the command-line REPL. In the `talc-web` directory, run: ```bash -wasm-pack build --release --no-typescript --no-pack --target web +RUSTFLAGS='--cfg getrandom_backend="wasm_js"' wasm-pack build --release --no-typescript --no-pack --target web ``` See (the main README.md)[../README.md] for more information about building