rl_lang/interpreter/stdlib/random/
random_general.rs1use crate::{
2 ast::statements::TypeAnnotation,
3 interpreter::{evaluator::Evaluator, values::Value},
4 utils::{errors::Error, span::Span},
5};
6
7pub fn dice(eval: &mut Evaluator, sides: i64, span: Span) -> Result<Value, Error> {
8 if sides <= 0 {
9 return Err(eval.err("sides should be 1 or higher", span));
10 }
11 Ok(Value::Integer(eval.rng.generate_random_int_range(1, sides)))
12}
13
14pub fn dices(eval: &mut Evaluator, count: i64, sides: i64, span: Span) -> Result<Value, Error> {
15 if count <= 0 {
16 return Err(eval.err("count should be 1 or higher", span));
17 }
18 if sides <= 0 {
19 return Err(eval.err("sides should be 1 or higher", span));
20 }
21
22 let result: Vec<Value> = (0..count)
23 .map(|_| Value::Integer(eval.rng.generate_random_int_range(1, sides)))
24 .collect();
25
26 Ok(Value::Values {
27 items_type: TypeAnnotation::Int,
28 items: result,
29 })
30}
31
32pub fn range(eval: &mut Evaluator, stop: i64, span: Span) -> Result<Value, Error> {
33 if 0 == stop {
34 return Err(eval.err("rand_range() stop shouldn't be zero", span));
35 }
36 if 0 > stop {
37 return Err(eval.err("rand_range() stop shouldn't be less than zero", span));
38 }
39
40 Ok(Value::Integer(eval.rng.generate_random_int_range(0, stop)))
41}
42
43pub fn range_step(
44 eval: &mut Evaluator,
45 start: i64,
46 end: i64,
47 step: i64,
48 span: Span,
49) -> Result<Value, Error> {
50 if 0 == step {
51 return Err(eval.err("rand_range_step() stop shouldn't be zero", span));
52 }
53 if start >= end {
54 return Err(eval.err(
55 format!(
56 "rand_range_step() end shouldn't be less than or equal to {}",
57 start
58 ),
59 span,
60 ));
61 }
62
63 let count = ((end - start) / step) + 1;
64 let i = eval.rng.generate_random_int_range(0, count - 1);
65 Ok(Value::Integer(start + i * step))
66}
67
68pub fn choice(eval: &mut Evaluator, array: Value, span: Span) -> Result<Value, Error> {
69 match array {
70 Value::Values { items, .. } => {
71 if items.is_empty() {
72 return Err(eval.err("array is empty", span));
73 }
74 Ok(items[eval
75 .rng
76 .generate_random_int_range(0, items.len() as i64 - 1)
77 as usize]
78 .clone())
79 }
80
81 other => Err(eval.err(
82 format!("rand_choice() expected array found {}", other),
83 span,
84 )),
85 }
86}
87
88pub fn choices(eval: &mut Evaluator, array: Value, count: i64, span: Span) -> Result<Value, Error> {
89 if count <= 0 {
90 return Err(eval.err("count should be 1 or higher", span));
91 }
92
93 match array.clone() {
94 Value::Values { items_type, items } => {
95 let result = (0..count)
96 .map(|_| {
97 items[eval
98 .rng
99 .generate_random_int_range(0, items.len() as i64 - 1)
100 as usize]
101 .clone()
102 })
103 .collect();
104 Ok(Value::Values {
105 items_type,
106 items: result,
107 })
108 }
109
110 other => Err(eval.err(
111 format!("rand_choices() expected array found {}", other),
112 span,
113 )),
114 }
115}
116
117pub fn sample(eval: &mut Evaluator, array: Value, count: i64, span: Span) -> Result<Value, Error> {
118 if count <= 0 {
119 return Err(eval.err("count should be 1 or higher", span));
120 }
121
122 match array.clone() {
123 Value::Values { items_type, items } => {
124 if count as usize > items.len() {
125 return Err(eval.err("count larger than array", span));
126 }
127 let mut indices: Vec<usize> = (0..items.len()).collect();
128 for i in (1..items.len()).rev() {
129 let j = eval.rng.generate_random_int_range(0, i as i64) as usize;
130 indices.swap(i, j);
131 }
132
133 let result = indices[..count as usize]
134 .iter()
135 .map(|&i| items[i].clone())
136 .collect();
137
138 Ok(Value::Values {
139 items_type,
140 items: result,
141 })
142 }
143
144 other => Err(eval.err(
145 format!("rand_sample() expected array found {}", other),
146 span,
147 )),
148 }
149}
150
151pub fn char(eval: &mut Evaluator) -> char {
152 eval.rng.generate_random_int_range(32, 126) as u8 as char
153}
154
155pub fn byte(eval: &mut Evaluator) -> i64 {
156 eval.rng.generate_random_int_range(0, 255)
157}
158
159pub fn string(eval: &mut Evaluator, count: i64, span: Span) -> Result<Value, Error> {
160 if count as usize <= 0 {
161 return Err(eval.err("count cannot be less than zero", span));
162 }
163
164 let result: String = (0..count).map(|_| char(eval)).collect();
165
166 Ok(Value::String(result))
167}
168
169pub fn bytes(eval: &mut Evaluator, count: i64, span: Span) -> Result<Value, Error> {
170 if count as usize <= 0 {
171 return Err(eval.err("count cannot be less than zero", span));
172 }
173
174 let result: Vec<Value> = (0..count).map(|_| Value::Integer(byte(eval))).collect();
175
176 Ok(Value::Values {
177 items_type: TypeAnnotation::Int,
178 items: result,
179 })
180}
181
182pub fn shuffle(eval: &mut Evaluator, array: Value, span: Span) -> Result<Value, Error> {
183 match array {
184 Value::Values { items, items_type } => {
185 if items.is_empty() {
186 return Err(eval.err("array is empty", span));
187 }
188
189 let mut items = items;
190 for i in (1..items.len()).rev() {
191 let j = eval.rng.generate_random_int_range(0, i as i64) as usize;
192 items.swap(i, j);
193 }
194
195 Ok(Value::Values { items_type, items })
196 }
197
198 other => Err(eval.err(
199 format!("rand_shuffle() expected array found {}", other),
200 span,
201 )),
202 }
203}