Skip to main content

rl_lang/interpreter/stdlib/random/
random_general.rs

1use 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}