Skip to content

Commit

Permalink
Add std.randseed and use global RNG
Browse files Browse the repository at this point in the history
  • Loading branch information
caioraposo committed Sep 13, 2023
1 parent 01b4303 commit 0174d4b
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 5 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ serde_json = "1.0"
base64 = "0.13"
hex = "0.4"
rand = "0.8.5"
rand_chacha = "0.3.1"

[dev-dependencies]
assert_matches = "1.5"
Expand Down
39 changes: 34 additions & 5 deletions src/runtime/lib/rand.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
//! This module uses the `ChaCha8Rng` pseudo-random generator from the rand
//! crate. It is suitable for tasks such as simulation, but should not be used
//! for applications like criptography or gambling games.
//! see: <https://rust-random.github.io/rand/rand_chacha/struct.ChaCha8Rng.html>
use std::cell::RefCell;

use gc::{Finalize, Trace};
use rand::{Rng, SeedableRng, thread_rng};
use rand_chacha::ChaCha8Rng;

use super::{
Float,
Expand All @@ -8,25 +17,29 @@ use super::{
Value,
CallContext,
};
use rand::{Rng, thread_rng};

inventory::submit! { RustFun::from(Rand) }
inventory::submit! { RustFun::from(RandInt) }
inventory::submit! { RustFun::from(RandSeed) }

thread_local!(static RNG: RefCell<ChaCha8Rng> = RefCell::new(ChaCha8Rng::from_rng(thread_rng()).unwrap()));

#[derive(Trace, Finalize)]
struct Rand;

#[derive(Trace, Finalize)]
struct RandInt;

#[derive(Trace, Finalize)]
struct RandSeed;

impl NativeFun for Rand {
fn name(&self) -> &'static str { "std.rand" }

fn call(&self, context: CallContext) -> Result<Value, Panic> {
let mut rng = thread_rng();
let args = context.args();
if args.is_empty() {
Ok(Value::Float(Float(rng.gen::<f64>())))
Ok(Value::Float(Float(RNG.with(|rng| rng.borrow_mut().gen::<f64>()))))
} else {
Err(Panic::invalid_args(args.len() as u32, 0, context.pos))
}
Expand All @@ -37,11 +50,27 @@ impl NativeFun for RandInt {
fn name(&self) -> &'static str { "std.randint" }

fn call(&self, context: CallContext) -> Result<Value, Panic> {
let mut rng = thread_rng();
match context.args() {
[ Value::Int(m), Value::Int(n) ] => Ok(Value::Int(rng.gen_range(*m..=*n))),
[ Value::Int(m), Value::Int(n) ] => Ok(Value::Int(
RNG.with(|rng| rng.borrow_mut().gen_range(*m..=*n))
)),
[ other, _ ] => Err(Panic::type_error(other.copy(), "int", context.pos)),
args => Err(Panic::invalid_args(args.len() as u32, 2, context.pos))
}
}
}

impl NativeFun for RandSeed {
fn name(&self) -> &'static str { "std.randseed" }

fn call(&self, context: CallContext) -> Result<Value, Panic> {
match context.args() {
[ Value::Int(n) ] => {
RNG.with(|rng| *rng.borrow_mut() = ChaCha8Rng::seed_from_u64(*n as u64));
Ok(Value::default())
},
[ other ] => Err(Panic::type_error(other.copy(), "int", context.pos)),
args => Err(Panic::invalid_args(args.len() as u32, 1, context.pos))
}
}
}

0 comments on commit 0174d4b

Please sign in to comment.