1use enum_downcast::EnumDowncast;
2
3use crate::prelude::*;
4
5pub mod values;
6
7#[derive(Clone, Debug, PartialEq)]
9pub struct Value {
10 pub value: ValueEnum,
12 pub span: Span,
14}
15
16impl Value {
17 pub fn new_value(value: ValueEnum, span: Span) -> Value {
18 Self { value, span }
19 }
20
21 pub fn new_ok_value(value: ValueEnum, span: Span) -> ValueResult {
22 ValueResult::Ok(Self { value, span })
23 }
24
25 pub fn new_err_value(value: ValueEnum, span: Span) -> ValueResult {
26 ValueResult::Err(Self { value, span })
27 }
28
29 pub fn expect_integer(&self) -> Result<i64> {
30 let number = self.expect::<values::Number>()?;
31
32 if number.value.fract() != 0.0 {
33 return Err(Error::new(
34 ErrorType::UnexpectedValue {
35 expected: vec!["Integer".to_string()],
36 actual: "Float".to_string(),
37 },
38 self.span.clone(),
39 ));
40 }
41
42 Ok(number.value as i64)
43 }
44
45 pub fn expect<T>(&self) -> Result<T>
46 where
47 ValueEnum: enum_downcast::AsVariant<T>,
48 T: Clone,
49 {
50 match self.value.enum_downcast_ref::<T>() {
51 Some(token) => Ok(token.clone()),
52 None => Err(Error::new(
53 {
54 let expected = std::any::type_name::<T>().split("::").last().unwrap();
55 let actual = self.value.name();
56
57 ErrorType::UnexpectedValue {
58 expected: vec![expected.to_string()],
59 actual,
60 }
61 },
62 self.span.clone(),
63 )),
64 }
65 }
66}
67
68#[derive(Clone, Debug)]
69pub enum ValueResult {
70 Ok(Value),
71 Err(Value),
72}
73
74impl ValueResult {
75 pub fn ignore_error(&self) -> &Value {
76 match self {
77 ValueResult::Ok(value) | ValueResult::Err(value) => value,
78 }
79 }
80
81 pub fn expect_non_error(self) -> Result<Value> {
82 match self {
83 ValueResult::Ok(value) => Ok(value),
84 ValueResult::Err(Value { span, .. }) => {
85 Err(Error::new(ErrorType::ExpectedNonErrorValue, span))
86 }
87 }
88 }
89
90 pub fn inner_mut(&mut self) -> &mut Value {
91 match self {
92 ValueResult::Ok(value) | ValueResult::Err(value) => value,
93 }
94 }
95}
96
97impl std::fmt::Display for ValueResult {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 match self {
100 ValueResult::Ok(value) => write!(f, "{}", value),
101 ValueResult::Err(value) => write!(f, "~{}", value),
102 }
103 }
104}
105
106pub trait ExpectValue {
107 fn expect_value(self, expected: &[&str], span: &Span) -> Result<Value>;
108}
109
110impl ExpectValue for Option<&Value> {
111 fn expect_value(self, expected: &[&str], span: &Span) -> Result<Value> {
112 match self {
113 Some(value) => Ok(value.clone()),
114 None => Err(Error::new(
115 ErrorType::UnexpectedValue {
116 expected: expected.iter().map(|v| v.to_string()).collect(),
117 actual: "EOF".to_string(),
118 },
119 span.clone(),
120 )),
121 }
122 }
123}
124
125pub trait ExpectArity {
126 fn expect_exact<const N: usize>(&self, span: &Span) -> Result<&[ValueResult; N], Error>;
127 fn expect_min<const N: usize>(
128 &self,
129 span: &Span,
130 ) -> Result<([ValueResult; N], Vec<ValueResult>), Error>;
131}
132
133impl ExpectArity for Vec<ValueResult> {
134 fn expect_exact<const N: usize>(&self, span: &Span) -> Result<&[ValueResult; N], Error> {
135 if self.len() == N {
136 Ok(TryInto::<&[ValueResult; N]>::try_into(self.as_slice()).unwrap())
137 } else {
138 Err(Error::new(
139 ErrorType::UnexpectedAmountOfArguments {
140 expected: N,
141 actual: self.len(),
142 },
143 span.clone(),
144 ))
145 }
146 }
147
148 fn expect_min<const N: usize>(
149 &self,
150 span: &Span,
151 ) -> Result<([ValueResult; N], Vec<ValueResult>), Error> {
152 if self.len() >= N {
153 let mut has_minimum = false;
154
155 let mut min = vec![];
156 let mut rest = vec![];
157
158 for argument in self {
159 if !has_minimum {
160 min.push(argument.clone());
161
162 if min.len() == N {
163 has_minimum = true;
164 }
165 } else {
166 rest.push(argument.clone());
167 }
168 }
169
170 let min = TryInto::<&[ValueResult; N]>::try_into(min.as_slice()).unwrap();
171
172 Ok((min.clone(), rest))
173 } else {
174 Err(Error::new(
175 ErrorType::NotEnoughArguments {
176 expected: N,
177 actual: self.len(),
178 },
179 span.clone(),
180 ))
181 }
182 }
183}
184
185impl std::fmt::Display for Value {
186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187 write!(f, "{}", self.value)
188 }
189}
190
191#[derive(Clone, Debug, EnumDowncast, PartialEq)]
193pub enum ValueEnum {
194 Number(values::Number),
195 Bool(values::Bool),
196 Nil(values::Nil),
197 Str(values::Str),
198 Range(values::Range),
199 Map(values::Map),
200 Callable(values::Callable),
201}
202
203impl ValueEnum {
204 pub fn name(&self) -> String {
206 use ValueEnum::*;
207
208 match self {
209 Number(_) => "Number",
210 Bool(_) => "Bool",
211 Nil(_) => "Nil",
212 Str(_) => "Str",
213 Range(_) => "Range",
214 Map(_) => "Map",
215 Callable(_) => "Callable",
216 }
217 .to_string()
218 }
219
220 pub fn get_iterator(&self, span: &Span) -> Result<Vec<Value>> {
221 match self {
222 ValueEnum::Range(values::Range::Closed { lhs, rhs }) => {
223 let mut out = vec![];
224
225 for i in { *lhs }..*rhs {
226 out.push(Value::new_value(
227 values::Number { value: i as f64 }.into(),
228 span.clone(),
229 ));
230 }
231
232 Ok(out)
233 }
234 ValueEnum::Number(values::Number { value }) => {
235 let upper_bound = if value.fract() == 0.0 {
236 *value as i64
237 } else {
238 return Err(Error::new(
239 ErrorType::UnexpectedValue {
240 expected: vec!["Integer".to_string()],
241 actual: "Float".to_string(),
242 },
243 span.clone(),
244 ));
245 };
246
247 let mut out = vec![];
248
249 for i in 0..upper_bound {
250 out.push(Value::new_value(
251 values::Number { value: i as f64 }.into(),
252 span.clone(),
253 ));
254 }
255
256 Ok(out)
257 }
258 ValueEnum::Str(values::Str { value }) => {
259 let mut out = vec![];
260
261 for ch in value.chars() {
262 out.push(Value::new_value(
263 values::Str {
264 value: ch.to_string(),
265 }
266 .into(),
267 span.clone(),
268 ));
269 }
270
271 Ok(out)
272 }
273 ValueEnum::Map(values::Map { values }) => {
274 let mut out = vec![];
275
276 for (key, value) in values {
277 out.push(Value::new_value(
278 values::Map {
279 values: vec![
280 (
281 values::Str {
282 value: "key".to_string(),
283 }
284 .into(),
285 key.clone(),
286 ),
287 (
288 values::Str {
289 value: "value".to_string(),
290 }
291 .into(),
292 value.clone(),
293 ),
294 ],
295 }
296 .into(),
297 span.clone(),
298 ));
299 }
300
301 Ok(out)
302 }
303 value => Err(Error::new(
304 ErrorType::CannotLoopOver(value.name()),
305 span.clone(),
306 )),
307 }
308 }
309}
310
311impl std::fmt::Display for ValueEnum {
312 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
313 use ValueEnum::*;
314
315 match self {
316 Number(number) => write!(f, "{}", number.value),
317 Bool(values::Bool { value: true }) => write!(f, "true"),
318 Bool(values::Bool { value: false }) => write!(f, "false"),
319 Nil(_) => write!(f, "nil"),
320 Str(string) => write!(f, "{}", string.value),
321 Range(range) => match range {
322 values::Range::Closed { rhs, lhs } => write!(f, "{}..{}", lhs, rhs),
323 values::Range::From { lhs } => write!(f, "{}..", lhs),
324 values::Range::To { rhs } => write!(f, "{}..", rhs),
325 },
326 Map(map) => {
327 if map.values.is_empty() {
328 write!(f, "||")
329 } else {
330 let mut out = "| ".to_string();
331
332 for (key, value) in &map.values {
333 out.push_str(&format!("[{}] = {}, ", key, value));
334 }
335
336 out.pop();
337 out.pop();
338
339 write!(f, "{} |", out)
340 }
341 }
342 Callable(callable) => match callable {
343 values::Callable::User {
344 parameters,
345 body: _,
346 } => {
347 let mut out = "fn(".to_string();
348
349 for parameter in parameters {
350 out.push_str(&format!("{}, ", parameter.name()));
351 }
352
353 if !parameters.is_empty() {
354 out.pop();
355 out.pop();
356 };
357
358 out.push(')');
359
360 write!(f, "{}", out)
361 }
362 &values::Callable::Lib {
363 function: _,
364 can_be_error,
365 } => write!(
366 f,
367 "<builtin_callable>{}",
368 if can_be_error { "?" } else { "" }
369 ),
370 },
371 }
372 }
373}