1pub mod bitwise_operations;
2pub mod indexing;
3pub mod iterator;
4pub mod mathematical_operations;
5pub mod members;
6pub mod relational_operations;
7pub mod truth;
8pub mod types;
9
10use crate::{
11 error::{Result, Span},
12 nodes::{Block, MemberKind},
13};
14use rust_decimal::Decimal;
15use std::{
16 cell::RefCell,
17 collections::HashMap,
18 fmt::{Debug, Display},
19 rc::Rc,
20};
21
22pub type WrappedValue<'tree> = Rc<RefCell<Value<'tree>>>;
23
24#[derive(PartialEq, Clone)]
25pub enum Value<'tree> {
26 Number(Decimal),
27 Bool(bool),
28 String(String),
29 Range {
30 start: Option<i128>,
31 end: Option<i128>,
32 },
33 List(Vec<WrappedValue<'tree>>),
34 Function {
35 args: &'tree [String],
36 block: &'tree Block,
37 },
38 BuiltIn(BuiltIn),
39 Class {
40 statics: HashMap<&'tree str, WrappedValue<'tree>>,
41 non_statics: Vec<&'tree MemberKind>,
42 },
43 Object(HashMap<&'tree str, WrappedValue<'tree>>),
44 Null,
45}
46
47impl<'tree> Value<'tree> {
48 pub fn wrapped(self) -> WrappedValue<'tree> {
49 Rc::new(RefCell::new(self))
50 }
51}
52
53#[derive(Clone)]
54pub enum BuiltIn {
55 Function(
56 for<'tree> fn(args: Vec<WrappedValue<'tree>>, span: &Span) -> Result<WrappedValue<'tree>>,
57 ),
58 Method(
59 for<'tree> fn(
60 this: &WrappedValue<'tree>,
61 args: Vec<WrappedValue<'tree>>,
62 span: &Span,
63 ) -> Result<WrappedValue<'tree>>,
64 ),
65 Print {
66 newline: bool,
67 stderr: bool,
68 },
69 Exit,
70 Debug,
71}
72
73impl PartialEq for BuiltIn {
74 fn eq(&self, _other: &Self) -> bool {
75 false
76 }
77}
78
79macro_rules! dbg_map {
80 ($map:ident) => {
81 dbg_map!(@inner $map, "", "", "")
82 };
83 (:? $map:ident) => {
84 dbg_map!(@inner $map, "\x1b[31m", "\x1b[0m", ":?")
85 };
86 (@inner $map:ident, $col:literal, $reset:literal, $dbg:literal) => {
87 $map.iter()
88 .map(|(k, v)| {
89 format!(
90 concat!(" ", $col, "{k}", $reset, " = {v},\n"),
91 k = k,
92 v = format!(concat!("{", $dbg, "}"), v.borrow())
93 .split('\n')
94 .collect::<Vec<_>>()
95 .join("\n "),
96 )
97 })
98 .collect::<Vec<_>>()
99 .join("")
100 };
101}
102
103impl Display for Value<'_> {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 match self {
106 Value::Number(value) => Display::fmt(&value, f),
107 Value::Bool(value) => Display::fmt(&value, f),
108 Value::String(value) => Display::fmt(&value, f),
109 Value::Range { start, end } => match (start, end) {
110 (Some(start), Some(end)) => write!(f, "{start}..={end}"),
111 (Some(start), None) => write!(f, "{start}.."),
112 (None, Some(end)) => write!(f, "..={end}"),
113 (None, None) => write!(f, ".."),
114 },
115 Value::List(list) => write!(
116 f,
117 "[{}]",
118 list.iter()
119 .map(|val| val.borrow().to_string())
120 .collect::<Vec<_>>()
121 .join(", ")
122 ),
123 Value::Function { .. } | Value::BuiltIn(..) => {
124 write!(f, "<function>")
125 }
126 Value::Class { statics, .. } => write!(f, "<class> {{\n{}}}", dbg_map!(statics)),
127 Value::Object(fields) => write!(f, "<object> {{\n{}}}", dbg_map!(fields)),
128 Value::Null => write!(f, "null"),
129 }
130 }
131}
132
133impl Debug for Value<'_> {
134 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135 match self {
136 Value::Number(value) => write!(f, "\x1b[33m{value}\x1b[0m"),
137 Value::Bool(value) => write!(f, "\x1b[34m{value}\x1b[0m"),
138 Value::String(value) => write!(f, "\x1b[32m'{value}'\x1b[0m"),
139 Value::Range { start, end } => match (start, end) {
140 (Some(start), Some(end)) => {
141 write!(f, "\x1b[33m{start}\x1b[0m..=\x1b[33m{end}\x1b[0m")
142 }
143 (Some(start), None) => write!(f, "\x1b[33m{start}\x1b[0m.."),
144 (None, Some(end)) => write!(f, "..=\x1b[33m{end}\x1b[0m"),
145 (None, None) => write!(f, ".."),
146 },
147 Value::List(list) => write!(
148 f,
149 "[{}]",
150 list.iter()
151 .map(|val| format!("{:?}", val.borrow()))
152 .collect::<Vec<_>>()
153 .join(", ")
154 ),
155 Value::Function { .. } | Value::BuiltIn(..) => {
156 write!(f, "\x1b[1m<function>\x1b[0m")
157 }
158 Value::Class { statics, .. } => {
159 write!(f, "\x1b[1m<class>\x1b[0m {{\n{}}}", dbg_map!(:? statics))
160 }
161 Value::Object(fields) => {
162 write!(f, "\x1b[1m<object>\x1b[0m {{\n{}}}", dbg_map!(:? fields))
163 }
164 Value::Null => write!(f, "\x1b[90mnull\x1b[0m"),
165 }
166 }
167}
168
169pub trait ToValue {
170 fn to_value<'tree>(&self) -> Value<'tree>;
171}