1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
extern crate rand;
extern crate rand_xorshift;
use self::rand::{Rng, SeedableRng};
use crate::vm::api::{RuntimeResult, IO};
use crate::vm::thread::Thread;
use crate::vm::types::VmInt;
use crate::vm::{self, ExternModule};
#[derive(Clone, Debug, Userdata)]
#[gluon(crate_name = "::vm")]
struct XorShiftRng(self::rand_xorshift::XorShiftRng);
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: &[u8]) -> RuntimeResult<XorShiftRng, String> {
if seed.len() == 16 {
let seed = unsafe { *(seed.as_ptr() as *const [u8; 16]) };
RuntimeResult::Return(XorShiftRng(self::rand_xorshift::XorShiftRng::from_seed(
seed,
)))
} 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 crate::rand_bind as prim;
}
}
pub fn load(vm: &Thread) -> vm::Result<ExternModule> {
use self::std;
vm.register_type::<XorShiftRng>("std.random.XorShiftRng", &[])?;
ExternModule::new(
vm,
record! {
type XorShiftRng => XorShiftRng,
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)
},
)
}