1use crate::{
2 entries,
3 module::StoredStruct,
4 value::methods::{
5 char::{
6 __char_escape_default, __char_escape_unicode, __char_from_digit, __char_is_alphabetic,
7 __char_is_alphanumeric, __char_is_ascii, __char_is_ascii_alphabetic,
8 __char_is_ascii_alphanumeric, __char_is_ascii_control, __char_is_ascii_digit,
9 __char_is_ascii_graphic, __char_is_ascii_lowercase, __char_is_ascii_punctuation,
10 __char_is_ascii_uppercase, __char_is_ascii_whitespace, __char_is_control,
11 __char_is_digit, __char_is_digit_in_base, __char_is_lowercase, __char_is_numeric,
12 __char_is_uppercase, __char_is_whitespace, __char_len_utf8, __char_to_ascii_lowercase,
13 __char_to_ascii_uppercase, __char_to_int, __char_to_lowercase, __char_to_string,
14 __char_to_uppercase,
15 },
16 string::{
17 __string_char_at, __string_char_code_at, __string_chars, __string_contains,
18 __string_ends_with, __string_index_of, __string_last_index_of, __string_len,
19 __string_replace, __string_reverse, __string_slice, __string_split,
20 __string_starts_with, __string_to_lowercase, __string_to_uppercase, __string_trim,
21 __string_trim_end, __string_trim_start,
22 },
23 vec::{__vec_len, __vec_next},
24 },
25 vm::native_fn::NativeFunction,
26};
27use anyhow::Result;
28use indexmap::IndexMap;
29use roan_ast::{Literal, LiteralType};
30use roan_error::{error::RoanError::TypeMismatch, TextSpan};
31use std::{
32 collections::HashMap,
33 fmt::{Debug, Display},
34 ops,
35};
36
37pub mod methods {
38 pub mod char;
39 pub mod string;
40 pub mod vec;
41}
42
43#[derive(Clone)]
44pub enum Value {
45 Int(i64),
46 Float(f64),
47 Bool(bool),
48 Char(char),
49 String(String),
50 Vec(Vec<Value>),
51 Struct(StoredStruct, HashMap<String, Value>),
52 Object(IndexMap<String, Value>),
53 Null,
54 Void,
55}
56
57impl Value {
58 pub fn builtin_methods(&self) -> HashMap<String, NativeFunction> {
59 match self {
60 Value::Vec(_) => {
61 entries!(
62 "len" => __vec_len(),
63 "next" => __vec_next()
64 )
65 }
66 Value::String(_) => {
67 entries!(
68 "len" => __string_len(),
69 "split" => __string_split(),
70 "chars" => __string_chars(),
71 "contains" => __string_contains(),
72 "starts_with" => __string_starts_with(),
73 "ends_with" => __string_ends_with(),
74 "replace" => __string_replace(),
75 "trim" => __string_trim(),
76 "trim_start" => __string_trim_start(),
77 "trim_end" => __string_trim_end(),
78 "to_uppercase" => __string_to_uppercase(),
79 "to_lowercase" => __string_to_lowercase(),
80 "reverse" => __string_reverse(),
81 "char_at" => __string_char_at(),
82 "char_code_at" => __string_char_code_at(),
83 "slice" => __string_slice(),
84 "index_of" => __string_index_of(),
85 "last_index_of" => __string_last_index_of()
86 )
87 }
88 Value::Char(_) => {
89 entries!(
90 "is_alphabetic" => __char_is_alphabetic(),
91 "is_alphanumeric" => __char_is_alphanumeric(),
92 "is_ascii" => __char_is_ascii(),
93 "is_ascii_alphabetic" => __char_is_ascii_alphabetic(),
94 "is_ascii_alphanumeric" => __char_is_ascii_alphanumeric(),
95 "is_ascii_control" => __char_is_ascii_control(),
96 "is_ascii_digit" => __char_is_ascii_digit(),
97 "is_ascii_graphic" => __char_is_ascii_graphic(),
98 "is_ascii_lowercase" => __char_is_ascii_lowercase(),
99 "is_ascii_punctuation" => __char_is_ascii_punctuation(),
100 "is_ascii_uppercase" => __char_is_ascii_uppercase(),
101 "is_ascii_whitespace" => __char_is_ascii_whitespace(),
102 "is_control" => __char_is_control(),
103 "is_digit" => __char_is_digit(),
104 "is_lowercase" => __char_is_lowercase(),
105 "is_numeric" => __char_is_numeric(),
106 "is_uppercase" => __char_is_uppercase(),
107 "is_whitespace" => __char_is_whitespace(),
108 "to_ascii_lowercase" => __char_to_ascii_lowercase(),
109 "to_ascii_uppercase" => __char_to_ascii_uppercase(),
110 "to_lowercase" => __char_to_lowercase(),
111 "to_uppercase" => __char_to_uppercase(),
112 "is_digit_in_base" => __char_is_digit_in_base(),
113 "escape_default" => __char_escape_default(),
114 "escape_unicode" => __char_escape_unicode(),
115 "from_digit" => __char_from_digit(),
116 "len_utf8" => __char_len_utf8(),
117 "to_string" => __char_to_string(),
118 "to_int" => __char_to_int()
119 )
120 }
121 _ => HashMap::new(),
122 }
123 }
124}
125
126impl Value {
127 pub fn from_literal(literal: Literal) -> Self {
128 match literal.value {
129 LiteralType::Int(i) => Value::Int(i),
130 LiteralType::Float(f) => Value::Float(f),
131 LiteralType::Bool(b) => Value::Bool(b),
132 LiteralType::String(s) => Value::String(s.clone()),
133 LiteralType::Null => Value::Null,
134 LiteralType::Char(c) => Value::Char(c),
135 }
136 }
137}
138
139impl ops::Add for Value {
140 type Output = Self;
141
142 fn add(self, other: Self) -> Self {
143 match (self.clone(), other.clone()) {
144 (Value::Int(a), Value::Int(b)) => Value::Int(a + b),
145 (Value::Float(a), Value::Float(b)) => Value::Float(a + b),
146 (Value::Int(a), Value::Float(b)) => Value::Float(a as f64 + b),
147 (Value::Float(a), Value::Int(b)) => Value::Float(a + b as f64),
148 (Value::String(a), Value::String(b)) => Value::String(a + &b),
149 (Value::Char(a), Value::Char(b)) => Value::String(format!("{}{}", a, b)),
150 (Value::Char(a), Value::String(b)) => Value::String(format!("{}{}", a, b)),
151 (Value::String(a), Value::Char(b)) => Value::String(format!("{}{}", a, b)),
152 _ => panic!(
153 "Cannot add values of different types: {:?} and {:?}",
154 self, other
155 ),
156 }
157 }
158}
159
160impl Debug for Value {
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 match self {
163 Value::Int(i) => write!(f, "Int({})", i),
164 Value::Float(fl) => write!(f, "Float({})", fl),
165 Value::Bool(b) => write!(f, "Bool({})", b),
166 Value::String(s) => write!(f, "String({})", s),
167 Value::Vec(v) => write!(f, "Vec({:?})", v),
168 Value::Null => write!(f, "Null"),
169 Value::Void => write!(f, "Void"),
170 Value::Struct(struct_def, fields) => {
171 write!(f, "Struct({} with fields: ", struct_def.name.literal())?;
172 for (name, val) in fields {
173 write!(f, "{}: {:?}, ", name, val)?;
174 }
175 write!(f, ")")
176 }
177 Value::Char(c) => write!(f, "Char({})", c),
178 Value::Object(fields) => {
179 write!(f, "{:#?}", fields)
180 }
181 }
182 }
183}
184
185impl Display for Value {
186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187 match self {
188 Value::Int(i) => write!(f, "{}", i),
189 Value::Float(fl) => write!(f, "{}", fl),
190 Value::Bool(b) => write!(f, "{}", b),
191 Value::String(s) => write!(f, "{}", s),
192 Value::Vec(v) => {
193 write!(f, "[")?;
194 for (i, val) in v.iter().enumerate() {
195 write!(f, "{}", val)?;
196 if i < v.len() - 1 {
197 write!(f, ", ")?;
198 }
199 }
200 write!(f, "]")
201 }
202 Value::Null => write!(f, "null"),
203 Value::Void => write!(f, "void"),
204 Value::Struct(st, fields) => {
205 let def = st.clone();
206
207 write!(f, "{} {{", def.name.literal())?;
208 for (i, (name, val)) in fields.iter().enumerate() {
209 write!(f, "{}: {}", name, val)?;
210 if i < fields.len() - 1 {
211 write!(f, ", ")?;
212 }
213 }
214 write!(f, "}}")
215 }
216 Value::Char(c) => write!(f, "{}", c),
217 Value::Object(fields) => {
218 write!(f, "{{")?;
219 for (i, (name, val)) in fields.iter().enumerate() {
220 write!(f, "{}: {}", name, val)?;
221 if i < fields.len() - 1 {
222 write!(f, ", ")?;
223 }
224 }
225 write!(f, "}}")
226 }
227 }
228 }
229}
230
231impl ops::Sub for Value {
232 type Output = Self;
233
234 fn sub(self, other: Self) -> Self {
235 match (self, other) {
236 (Value::Int(a), Value::Int(b)) => Value::Int(a - b),
237 (Value::Float(a), Value::Float(b)) => Value::Float(a - b),
238 (Value::Int(a), Value::Float(b)) => Value::Float(a as f64 - b),
239 (Value::Float(a), Value::Int(b)) => Value::Float(a - b as f64),
240 _ => panic!("Cannot subtract values of different types"),
241 }
242 }
243}
244
245impl ops::Mul for Value {
246 type Output = Self;
247
248 fn mul(self, other: Self) -> Self {
249 match (self, other) {
250 (Value::Int(a), Value::Int(b)) => Value::Int(a * b),
251 (Value::Float(a), Value::Float(b)) => Value::Float(a * b),
252 (Value::Int(a), Value::Float(b)) => Value::Float(a as f64 * b),
253 (Value::Float(a), Value::Int(b)) => Value::Float(a * b as f64),
254 _ => panic!("Cannot multiply values of different types"),
255 }
256 }
257}
258
259impl ops::Div for Value {
260 type Output = Self;
261
262 fn div(self, other: Self) -> Self {
263 match (self, other) {
264 (Value::Int(a), Value::Int(b)) => Value::Int(a / b),
265 (Value::Float(a), Value::Float(b)) => Value::Float(a / b),
266 (Value::Int(a), Value::Float(b)) => Value::Float(a as f64 / b),
267 (Value::Float(a), Value::Int(b)) => Value::Float(a / b as f64),
268 _ => panic!("Cannot divide values of different types"),
269 }
270 }
271}
272
273impl ops::Rem for Value {
274 type Output = Self;
275
276 fn rem(self, other: Self) -> Self {
277 match (self, other) {
278 (Value::Int(a), Value::Int(b)) => Value::Int(a % b),
279 (Value::Float(a), Value::Float(b)) => Value::Float(a % b),
280 (Value::Int(a), Value::Float(b)) => Value::Float(a as f64 % b),
281 (Value::Float(a), Value::Int(b)) => Value::Float(a % b as f64),
282 _ => panic!("Cannot modulo values of different types"),
283 }
284 }
285}
286
287impl PartialEq for Value {
288 fn eq(&self, other: &Self) -> bool {
289 match (self, other) {
290 (Value::Int(a), Value::Int(b)) => a == b,
291 (Value::Float(a), Value::Float(b)) => a == b,
292 (Value::Bool(a), Value::Bool(b)) => a == b,
293 (Value::String(a), Value::String(b)) => a == b,
294 (Value::Vec(a), Value::Vec(b)) => {
295 if a.len() != b.len() {
296 return false;
297 }
298 for (a, b) in a.iter().zip(b.iter()) {
299 if a != b {
300 return false;
301 }
302 }
303 true
304 }
305 (Value::Null, Value::Null) => true,
306 (Value::Void, Value::Void) => true,
307 (Value::Char(a), Value::Char(b)) => a == b,
308 (Value::Char(a), Value::String(b)) => a.to_string() == *b,
309 (Value::String(a), Value::Char(b)) => a == &b.to_string(),
310 _ => false,
311 }
312 }
313}
314
315impl Eq for Value {}
316
317impl PartialOrd for Value {
318 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
319 match (self, other) {
320 (Value::Int(a), Value::Int(b)) => a.partial_cmp(b),
321 (Value::Float(a), Value::Float(b)) => a.partial_cmp(b),
322 (Value::Int(a), Value::Float(b)) => (*a as f64).partial_cmp(b),
323 (Value::Float(a), Value::Int(b)) => a.partial_cmp(&(*b as f64)),
324 _ => None,
325 }
326 }
327}
328
329impl Value {
330 pub fn pow(self, other: Self) -> Self {
331 match (self, other) {
332 (Value::Int(a), Value::Int(b)) => Value::Int(a.pow(b as u32)),
333 (Value::Float(a), Value::Float(b)) => Value::Float(a.powf(b)),
334 (Value::Int(a), Value::Float(b)) => Value::Float((a as f64).powf(b)),
335 (Value::Float(a), Value::Int(b)) => Value::Float(a.powf(b as f64)),
336 _ => panic!("Cannot apply power operator on values of different or unsupported types"),
337 }
338 }
339}
340
341impl Value {
342 pub fn access_index(&self, index: Self) -> Self {
343 match self {
344 Value::Vec(v) => match index {
345 Value::Int(i) => v.get(i as usize).cloned().unwrap_or(Value::Null),
346 _ => Value::Null,
347 },
348 Value::String(s) => match index {
349 Value::Int(i) => {
350 if i < 0 {
351 Value::Null
352 } else {
353 s.chars()
354 .nth(i as usize)
355 .map(Value::Char)
356 .unwrap_or(Value::Null)
357 }
358 }
359 _ => Value::Null,
360 },
361 Value::Object(fields) => match index {
362 Value::String(key) => fields.get(&key).cloned().unwrap_or(Value::Null),
363 _ => Value::Null,
364 },
365 _ => panic!("Cannot access index of non-indexable value"),
367 }
368 }
369}
370
371impl Value {
372 pub fn is_array(&self) -> bool {
373 matches!(self, Value::Vec(_))
374 }
375
376 pub fn is_bool(&self) -> bool {
377 matches!(self, Value::Bool(_))
378 }
379
380 pub fn is_float(&self) -> bool {
381 matches!(self, Value::Float(_))
382 }
383
384 pub fn is_int(&self) -> bool {
385 matches!(self, Value::Int(_))
386 }
387
388 pub fn is_null(&self) -> bool {
389 matches!(self, Value::Null)
390 }
391
392 pub fn is_string(&self) -> bool {
393 matches!(self, Value::String(_))
394 }
395
396 pub fn is_struct(&self) -> bool {
397 matches!(self, Value::Struct(_, _))
398 }
399
400 pub fn is_void(&self) -> bool {
401 matches!(self, Value::Void)
402 }
403}
404
405impl Value {
406 pub fn check_type(&self, expected_type: &str, span: TextSpan) -> Result<()> {
407 if self.is_type(expected_type) {
408 Ok(())
409 } else {
410 Err(TypeMismatch(
411 format!(
412 "Expected type {} but got {}",
413 expected_type,
414 self.type_name()
415 ),
416 span,
417 )
418 .into())
419 }
420 }
421
422 pub fn is_type(&self, type_name: &str) -> bool {
423 match type_name {
424 "int" => self.is_int(),
425 "float" => self.is_float(),
426 "bool" => self.is_bool(),
427 "string" => self.is_string(),
428 "null" => self.is_null(),
429 "void" => self.is_void(),
430 _ => false,
431 }
432 }
433
434 pub fn type_name(&self) -> String {
435 match self {
436 Value::Int(_) => "int".to_string(),
437 Value::Float(_) => "float".to_string(),
438 Value::Bool(_) => "bool".to_string(),
439 Value::String(_) => "string".to_string(),
440 Value::Vec(vals) => {
442 if vals.is_empty() {
443 "void[]".to_string()
444 } else {
445 format!("{}[]", vals[0].type_name())
446 }
447 }
448 Value::Struct(struct_def, _) => struct_def.name.literal(),
449 Value::Null => "null".to_string(),
450 Value::Void => "void".to_string(),
451 Value::Char(_) => "char".to_string(),
452 Value::Object(_) => "object".to_string(),
453 }
454 }
455}
456
457impl Value {
458 pub fn is_truthy(&self) -> bool {
459 match self {
460 Value::Int(i) => *i != 0,
461 Value::Float(f) => *f != 0.0,
462 Value::Bool(b) => *b,
463 Value::String(s) => !s.is_empty(),
464 Value::Vec(v) => !v.is_empty(),
465 Value::Null => false,
466 Value::Void => false,
467 Value::Struct(_, _) => true,
468 Value::Char(_) => true,
469 Value::Object(_) => true,
470 }
471 }
472}
473
474#[cfg(test)]
475mod tests {
476 use super::*;
477
478 #[test]
479 fn test_value_add() {
480 assert_eq!(Value::Int(1) + Value::Int(2), Value::Int(3));
481 assert_eq!(Value::Float(1.0) + Value::Float(2.0), Value::Float(3.0));
482 assert_eq!(Value::Int(1) + Value::Float(2.0), Value::Float(3.0));
483 assert_eq!(Value::Float(1.0) + Value::Int(2), Value::Float(3.0));
484 assert_eq!(
485 Value::String("Hello".to_string()) + Value::String("World".to_string()),
486 Value::String("HelloWorld".to_string())
487 );
488 }
489
490 #[test]
491 fn test_value_sub() {
492 assert_eq!(Value::Int(1) - Value::Int(2), Value::Int(-1));
493 assert_eq!(Value::Float(1.0) - Value::Float(2.0), Value::Float(-1.0));
494 assert_eq!(Value::Int(1) - Value::Float(2.0), Value::Float(-1.0));
495 assert_eq!(Value::Float(1.0) - Value::Int(2), Value::Float(-1.0));
496 }
497
498 #[test]
499 fn test_value_mul() {
500 assert_eq!(Value::Int(1) * Value::Int(2), Value::Int(2));
501 assert_eq!(Value::Float(1.0) * Value::Float(2.0), Value::Float(2.0));
502 assert_eq!(Value::Int(1) * Value::Float(2.0), Value::Float(2.0));
503 assert_eq!(Value::Float(1.0) * Value::Int(2), Value::Float(2.0));
504 }
505
506 #[test]
507 fn test_value_div() {
508 assert_eq!(Value::Int(1) / Value::Int(2), Value::Int(0));
509 assert_eq!(Value::Float(1.0) / Value::Float(2.0), Value::Float(0.5));
510 assert_eq!(Value::Int(1) / Value::Float(2.0), Value::Float(0.5));
511 assert_eq!(Value::Float(5.5) / Value::Int(2), Value::Float(2.75));
512 }
513
514 #[test]
515 fn test_value_rem() {
516 assert_eq!(Value::Int(1) % Value::Int(2), Value::Int(1));
517 assert_eq!(Value::Float(1.0) % Value::Float(2.0), Value::Float(1.0));
518 assert_eq!(Value::Int(1) % Value::Float(2.0), Value::Float(1.0));
519 assert_eq!(Value::Float(5.5) % Value::Int(2), Value::Float(1.5));
520 }
521
522 #[test]
523 fn test_value_pow() {
524 assert_eq!(Value::Int(2).pow(Value::Int(3)), Value::Int(8));
525 assert_eq!(Value::Float(2.0).pow(Value::Float(3.0)), Value::Float(8.0));
526 assert_eq!(Value::Int(2).pow(Value::Float(3.0)), Value::Float(8.0));
527 assert_eq!(Value::Float(2.0).pow(Value::Int(3)), Value::Float(8.0));
528 }
529
530 #[test]
531 fn test_value_access_index() {
532 assert_eq!(
533 Value::Vec(vec![Value::Int(1), Value::Int(2), Value::Int(3)])
534 .access_index(Value::Int(1)),
535 Value::Int(2)
536 );
537 assert_eq!(
538 Value::Vec(vec![Value::Int(1), Value::Int(2), Value::Int(3)])
539 .access_index(Value::Int(3)),
540 Value::Null
541 );
542 assert_eq!(
543 Value::Vec(vec![Value::Int(1), Value::Int(2), Value::Int(3)])
544 .access_index(Value::Float(1.0)),
545 Value::Null
546 );
547 }
548
549 #[test]
550 fn test_value_eq() {
551 assert_eq!(Value::Int(1), Value::Int(1));
552 assert_eq!(Value::Float(1.0), Value::Float(1.0));
553 assert_eq!(Value::Bool(true), Value::Bool(true));
554 assert_eq!(
555 Value::String("Hello".to_string()),
556 Value::String("Hello".to_string())
557 );
558 assert_eq!(
559 Value::Vec(vec![Value::Int(1), Value::Int(2), Value::Int(3)]),
560 Value::Vec(vec![Value::Int(1), Value::Int(2), Value::Int(3)])
561 );
562 assert_eq!(Value::Null, Value::Null);
563 assert_eq!(Value::Void, Value::Void);
564 }
565
566 #[test]
567 fn test_value_partial_cmp() {
568 assert_eq!(
569 Value::Int(1).partial_cmp(&Value::Int(2)),
570 Some(std::cmp::Ordering::Less)
571 );
572 assert_eq!(
573 Value::Float(1.0).partial_cmp(&Value::Float(2.0)),
574 Some(std::cmp::Ordering::Less)
575 );
576 assert_eq!(
577 Value::Int(1).partial_cmp(&Value::Float(2.0)),
578 Some(std::cmp::Ordering::Less)
579 );
580 assert_eq!(
581 Value::Float(1.0).partial_cmp(&Value::Int(2)),
582 Some(std::cmp::Ordering::Less)
583 );
584 }
585
586 #[test]
587 fn test_value_display() {
588 assert_eq!(format!("{}", Value::Int(1)), "1");
589 assert_eq!(format!("{}", Value::Float(1.0)), "1");
590 assert_eq!(format!("{}", Value::Bool(true)), "true");
591 assert_eq!(format!("{}", Value::String("Hello".to_string())), "Hello");
592 assert_eq!(
593 format!(
594 "{}",
595 Value::Vec(vec![Value::Int(1), Value::Int(2), Value::Int(3)])
596 ),
597 "[1, 2, 3]"
598 );
599 assert_eq!(format!("{}", Value::Null), "null");
600 assert_eq!(format!("{}", Value::Void), "void");
601 }
602
603 #[test]
604 fn test_value_type_name() {
605 assert_eq!(Value::Int(1).type_name(), "int");
606 assert_eq!(Value::Float(1.0).type_name(), "float");
607 assert_eq!(Value::Bool(true).type_name(), "bool");
608 assert_eq!(Value::String("Hello".to_string()).type_name(), "string");
609 assert_eq!(
610 Value::Vec(vec![Value::Int(1), Value::Int(2), Value::Int(3)]).type_name(),
611 "int[]"
612 );
613 assert_eq!(Value::Null.type_name(), "null");
614 assert_eq!(Value::Void.type_name(), "void");
615 }
616
617 #[test]
618 fn test_value_is_type() {
619 assert!(Value::Int(1).is_type("int"));
620 assert!(Value::Float(1.0).is_type("float"));
621 assert!(Value::Bool(true).is_type("bool"));
622 assert!(Value::String("Hello".to_string()).is_type("string"));
623 assert!(Value::Null.is_type("null"));
628 assert!(Value::Void.is_type("void"));
629 }
630
631 #[test]
632 fn test_value_is_array() {
633 assert!(Value::Vec(vec![Value::Int(1), Value::Int(2), Value::Int(3)]).is_array());
634 assert!(!Value::Int(1).is_array());
635 }
636
637 #[test]
638 fn test_value_is_bool() {
639 assert!(Value::Bool(true).is_bool());
640 assert!(!Value::Int(1).is_bool());
641 }
642
643 #[test]
644 fn test_value_is_float() {
645 assert!(Value::Float(1.0).is_float());
646 assert!(!Value::Int(1).is_float());
647 }
648
649 #[test]
650 fn test_value_is_int() {
651 assert!(Value::Int(1).is_int());
652 assert!(!Value::Float(1.0).is_int());
653 }
654
655 #[test]
656 fn test_value_is_null() {
657 assert!(Value::Null.is_null());
658 assert!(!Value::Int(1).is_null());
659 }
660
661 #[test]
662 fn test_value_is_string() {
663 assert!(Value::String("Hello".to_string()).is_string());
664 assert!(!Value::Int(1).is_string());
665 }
666}