rl_lang/interpreter/stdlib/
common.rs1use crate::{
2 interpreter::values::Value,
3 utils::{
4 errors::{Error, Reason},
5 span::Span,
6 },
7};
8
9pub fn check_arity(args: &[Value], expected: usize, name: &str, span: Span) -> Result<(), Error> {
10 if args.len() != expected {
11 let message = if expected == 0 {
12 format!("{}: function takes no arguments, got {}", name, args.len())
13 } else {
14 format!("{}: expected {} arg(s), got {}", name, expected, args.len())
15 };
16
17 return Err(Error::at(Reason::Runtime, message, span));
18 }
19 Ok(())
20}
21
22pub fn check_arity_range(
23 args: &[Value],
24 expected_from: usize,
25 expected_to: usize,
26 name: &str,
27 span: Span,
28) -> Result<(), Error> {
29 let len = args.len();
30 if !(expected_from..expected_to).contains(&len) {
31 let message = format!(
32 "{}: expected from {} to {} arg(s), got {}",
33 name,
34 expected_from,
35 expected_to,
36 args.len()
37 );
38
39 return Err(Error::at(Reason::Runtime, message, span));
40 }
41 Ok(())
42}
43
44pub fn check_type(value: &Value, expected: &str, name: &str) -> Result<(), String> {
45 match (value, expected) {
46 (Value::Bool(_), "bool")
47 | (Value::String(_), "string")
48 | (Value::Integer(_), "int")
49 | (Value::Byte(_), "byte")
50 | (Value::Char(_), "char")
51 | (Value::Error(_), "error")
52 | (Value::Float(_), "float")
53 | (Value::Function { .. }, "fn")
54 | (Value::Null, "none" | "null")
55 | (Value::Ok(_), "ok")
56 | (Value::Tuple(_), "tuple" | "()")
57 | (Value::Values { .. }, "arr") => Ok(()),
58
59 (other_val, other_exp) => Err(format!(
60 "{}: expected {} type, got {}",
61 name,
62 other_exp,
63 other_val.type_name()
64 )),
65 }
66}
67
68pub fn extract_string(value: Value, name: &str) -> Result<String, String> {
69 check_type(&value, "string", name)?;
70 let Value::String(v) = value else {
71 unreachable!()
72 };
73 Ok(v)
74}
75
76pub fn extract_int(value: Value, name: &str) -> Result<i64, String> {
77 check_type(&value, "int", name)?;
78 let Value::Integer(v) = value else {
79 unreachable!()
80 };
81 Ok(v)
82}
83
84pub fn extract_number(value: Value, name: &str) -> Result<u64, String> {
85 if check_type(&value, "int", name).is_err() && check_type(&value, "byte", name).is_err() {
86 return Err(format!(
87 "{}: expected int or byte type, got {}",
88 name,
89 value.type_name()
90 ));
91 }
92
93 match value {
94 Value::Integer(i) => Ok(i as u64),
95 Value::Byte(b) => Ok(b as u64),
96 _ => {
97 unreachable!()
98 }
99 }
100}
101
102macro_rules! vok {
103 ($e:expr) => {
104 Value::Ok(Box::new($e))
105 };
106}
107pub(crate) use vok;
108
109macro_rules! verr {
110 ($e:expr) => {
111 Value::Err(Box::new($e))
112 };
113}
114pub(crate) use verr;
115
116macro_rules! vb {
117 ($e:expr) => {
118 Value::Bool($e)
119 };
120}
121pub(crate) use vb;
122
123macro_rules! vi {
124 ($e:expr) => {
125 Value::Integer($e)
126 };
127}
128pub(crate) use vi;
129
130macro_rules! vf {
131 ($e:expr) => {
132 Value::Float($e)
133 };
134}
135pub(crate) use vf;
136
137macro_rules! vs {
138 ($e:expr) => {
139 Value::String($e)
140 };
141}
142pub(crate) use vs;
143
144macro_rules! vc {
145 ($e:expr) => {
146 Value::Char($e)
147 };
148}
149pub(crate) use vc;
150
151macro_rules! vby {
152 ($e:expr) => {
153 Value::Byte($e)
154 };
155}
156pub(crate) use vby;
157
158macro_rules! vnl {
159 () => {
160 Value::Null
161 };
162}
163pub(crate) use vnl;
164
165macro_rules! try_fn {
166 ($s:expr, $e:expr) => {
167 if let Err(e) = $e {
168 return verr!(vs!(format!("{}: {}", $s, e)));
169 }
170 };
171}
172pub(crate) use try_fn;