Skip to content

Commit

Permalink
feat(vm): Add a basic wrapper around the rand crate
Browse files Browse the repository at this point in the history
I need at least basic randomness for an example so figured I should add
this.
  • Loading branch information
Marwes committed Dec 11, 2017
1 parent 464176e commit 7210d8d
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ serde_derive_state = { version = "0.4.0", optional = true }

# Binding crates
regex = { version = "0.2.1", optional = true }
rand = { version = "0.3", optional = true }

# Crates used in testing Testing
compiletest_rs = { version = "0.3", optional = true }
Expand All @@ -66,7 +67,7 @@ bincode = "0.8.0"
gluon_completion = { path = "completion", version = "0.6.2" } # GLUON

[features]
default = ["regex"]
default = ["regex", "rand"]
serialization = ["serde", "serde_state", "serde_derive_state", "gluon_vm/serialization"]

test = ["serialization", "gluon_vm/test", "gluon_check/test", "gluon_parser/test"]
Expand Down
5 changes: 5 additions & 0 deletions format/tests/pretty_print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ fn parser() {
test_format("std/parser.glu");
}

#[test]
fn random() {
test_format("std/random.glu");
}

#[test]
fn repl() {
test_format("repl/src/repl.glu");
Expand Down
10 changes: 10 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub mod import;
pub mod io;
#[cfg(feature = "regex")]
pub mod regex_bind;
#[cfg(feature = "rand")]
pub mod rand_bind;

pub use vm::thread::{RootedThread, Thread};

Expand Down Expand Up @@ -587,6 +589,7 @@ pub fn new_vm() -> RootedThread {
add_extern_module(&vm, "std.io.prim", ::io::load);

load_regex(&vm);
load_random(&vm);

vm
}
Expand All @@ -598,6 +601,13 @@ fn load_regex(vm: &Thread) {
#[cfg(not(feature = "regex"))]
fn load_regex(_: &Thread) {}

#[cfg(feature = "rand")]
fn load_random(vm: &Thread) {
add_extern_module(&vm, "std.random.prim", ::rand_bind::load);
}
#[cfg(not(feature = "rand"))]
fn load_random(_: &Thread) {}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
87 changes: 87 additions & 0 deletions src/rand_bind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//! Module containing bindings to the `rand` library.

extern crate rand;

use self::rand::{Rng, SeedableRng};

use vm::{self, ExternModule};
use vm::api::{RuntimeResult, Userdata, VmType, IO};
use vm::gc::{Gc, Traverseable};
use vm::thread::Thread;
use vm::types::VmInt;

#[derive(Debug, Clone)]
struct XorShiftRng(self::rand::XorShiftRng);

impl Userdata for XorShiftRng {}

impl VmType for XorShiftRng {
type Type = XorShiftRng;
}

impl Traverseable for XorShiftRng {
fn traverse(&self, _: &mut Gc) {}
}

field_decl! { value, gen }

fn next_int(_: ()) -> IO<VmInt> {
IO::Value(rand::thread_rng().gen())
}

fn next_float(_: ()) -> IO<f64> {
IO::Value(rand::thread_rng().gen())
}

fn gen_int_range(low: VmInt, high: VmInt) -> IO<VmInt> {
IO::Value(rand::thread_rng().gen_range(low, high))
}

type RngNext<G> = record_type!{
value => VmInt,
gen => G
};

fn xor_shift_new(seed: &[VmInt]) -> RuntimeResult<XorShiftRng, String> {
if seed.len() == 4 {
RuntimeResult::Return(XorShiftRng(self::rand::XorShiftRng::from_seed([
seed[0] as u32,
seed[1] as u32,
seed[2] as u32,
seed[3] as u32,
])))
} else {
RuntimeResult::Panic("Expected xorshift seed to have 4 elements".to_string())
}
}

fn xor_shift_next(gen: &XorShiftRng) -> RngNext<XorShiftRng> {
let mut gen = gen.clone();
record_no_decl!{
value => gen.0.gen(),
gen => gen
}
}

mod std {
pub mod random {
pub use rand_bind as prim;
}
}

pub fn load(vm: &Thread) -> vm::Result<ExternModule> {
use self::std;

vm.register_type::<XorShiftRng>("XorShiftRng", &[])?;

ExternModule::new(
vm,
record!{
next_int => primitive!(1 std::random::prim::next_int),
next_float => primitive!(1 std::random::prim::next_float),
gen_int_range => primitive!(2 std::random::prim::gen_int_range),
xor_shift_new => primitive!(1 std::random::prim::xor_shift_new),
xor_shift_next => primitive!(1 std::random::prim::xor_shift_next)
},
)
}
25 changes: 25 additions & 0 deletions std/random.glu
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
let prim = import! std.random.prim

type RandomGen g = { next : g -> { value : Int, gen : g } }

let xor_shift_rng =
let random_gen : RandomGen XorShiftRng = {
next = prim.xor_shift_next
}

{
new = prim.xor_shift_new,
random_gen,
}

{
RandomGen,

xor_shift_rng,

thread_rng = {
next_int = prim.next_int,
next_float = prim.next_float,
gen_int_range = prim.gen_int_range,
},
}

0 comments on commit 7210d8d

Please sign in to comment.