Skip to main content

rl_lang/interpreter/stdlib/
common.rs

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