Refactor random number generation to factory

- Use a `make-random` factory to create isolated random number
  generators.
- Remove the global `prng` from the `Environment`.
- Ensure `make-random` can be called with or without a seed.
This commit is contained in:
Michael Schimmel
2026-03-02 14:01:36 +01:00
parent f3459baf43
commit a4af142719
4 changed files with 49 additions and 38 deletions
-2
View File
@@ -28,7 +28,6 @@ pub struct Environment {
pub global_types: Rc<RefCell<HashMap<GlobalIdx, StaticType>>>,
pub global_purity: Rc<RefCell<HashMap<GlobalIdx, Purity>>>,
pub global_values: Rc<RefCell<Vec<Value>>>,
pub prng: Rc<RefCell<fastrand::Rng>>,
pub function_registry: Rc<RefCell<HashMap<GlobalIdx, BoundNode>>>,
pub typed_function_registry: Rc<RefCell<HashMap<GlobalIdx, AnalyzedNode>>>,
pub monomorph_cache: Rc<RefCell<MonoCache>>,
@@ -102,7 +101,6 @@ impl Environment {
global_types: Rc::new(RefCell::new(HashMap::new())),
global_purity: Rc::new(RefCell::new(HashMap::new())),
global_values: Rc::new(RefCell::new(Vec::new())),
prng: Rc::new(RefCell::new(fastrand::Rng::new())),
function_registry: Rc::new(RefCell::new(HashMap::new())),
typed_function_registry: Rc::new(RefCell::new(HashMap::new())),
monomorph_cache: Rc::new(RefCell::new(HashMap::new())),
+31 -19
View File
@@ -135,27 +135,39 @@ pub fn register(env: &Environment) {
best
});
// Random
let random_ty = StaticType::Function(Box::new(Signature {
// Random generator factory (Closure-based)
let generator_sig = Signature {
params: StaticType::Tuple(vec![]),
ret: StaticType::Float,
}));
};
let make_random_ty = StaticType::FunctionOverloads(vec![
Signature {
params: StaticType::Tuple(vec![]),
ret: StaticType::Function(Box::new(generator_sig.clone())),
},
Signature {
params: StaticType::Tuple(vec![StaticType::Int]),
ret: StaticType::Function(Box::new(generator_sig)),
},
]);
let prng = env.prng.clone();
env.register_native_fn("random", random_ty, Purity::SideEffectFree, move |_| {
Value::Float(prng.borrow_mut().f64())
});
let seed_ty = StaticType::Function(Box::new(Signature {
params: StaticType::Tuple(vec![StaticType::Int]),
ret: StaticType::Void,
}));
let prng_seed = env.prng.clone();
env.register_native_fn("seed!", seed_ty, Purity::Impure, move |args| {
if let Value::Int(s) = args[0] {
prng_seed.borrow_mut().seed(s as u64);
}
Value::Void
env.register_native_fn("make-random", make_random_ty, Purity::SideEffectFree, |args| {
let rng = if args.is_empty() {
fastrand::Rng::new()
} else if let Value::Int(s) = args[0] {
fastrand::Rng::with_seed(s as u64)
} else {
fastrand::Rng::new()
};
let prng = std::rc::Rc::new(std::cell::RefCell::new(rng));
Value::Function(std::rc::Rc::new(crate::ast::types::NativeFunction {
func: std::rc::Rc::new(move |_| {
Value::Float(prng.borrow_mut().f64())
}),
purity: Purity::Impure,
}))
});
}