feat: implement Random and Time built-in effects

Add Random and Time effects for random number generation and
time-based operations. These effects can be used in any
effectful code block.

Random effect operations:
- Random.int(min, max) - random integer in range [min, max]
- Random.float() - random float in range [0.0, 1.0)
- Random.bool() - random boolean

Time effect operations:
- Time.now() - current Unix timestamp in milliseconds
- Time.sleep(ms) - sleep for specified milliseconds

Changes:
- Add rand crate dependency
- Add Random and Time effect definitions to types.rs
- Add effects to built-in effects list in typechecker
- Implement effect handlers in interpreter
- Add 4 new tests for Random and Time effects
- Add examples/random.lux demonstrating usage

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 09:49:09 -05:00
parent c0ef71beb7
commit 52ad5f8781
7 changed files with 258 additions and 3 deletions

View File

@@ -4,6 +4,7 @@
use crate::ast::*;
use crate::diagnostics::{Diagnostic, Severity};
use rand::Rng;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
@@ -2177,6 +2178,47 @@ impl Interpreter {
("Reader", "ask") => {
Ok(self.builtin_reader.borrow().clone())
}
("Random", "int") => {
let min = match request.args.first() {
Some(Value::Int(n)) => *n,
_ => 0,
};
let max = match request.args.get(1) {
Some(Value::Int(n)) => *n,
_ => i64::MAX,
};
let mut rng = rand::thread_rng();
let value = rng.gen_range(min..=max);
Ok(Value::Int(value))
}
("Random", "float") => {
let mut rng = rand::thread_rng();
let value: f64 = rng.gen();
Ok(Value::Float(value))
}
("Random", "bool") => {
let mut rng = rand::thread_rng();
let value: bool = rng.gen();
Ok(Value::Bool(value))
}
("Time", "now") => {
use std::time::{SystemTime, UNIX_EPOCH};
let duration = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default();
let millis = duration.as_millis() as i64;
Ok(Value::Int(millis))
}
("Time", "sleep") => {
use std::thread;
use std::time::Duration;
let ms = match request.args.first() {
Some(Value::Int(n)) => *n as u64,
_ => 0,
};
thread::sleep(Duration::from_millis(ms));
Ok(Value::Unit)
}
_ => Err(RuntimeError {
message: format!(
"Unhandled effect operation: {}.{}",