1use std::cell::RefCell;
2use std::fmt;
3use std::fmt::Display;
4use std::rc::Rc;
5use tenda_scanner::Literal;
6
7use crate::associative_array::{AssociativeArray, AssociativeArrayKey};
8use crate::date::Date;
9use crate::function::Function;
10
11#[derive(Debug, Clone, PartialEq)]
12pub enum Value {
13 Number(f64),
14 Boolean(bool),
15 String(String),
16 Function(Function),
17 List(Rc<RefCell<Vec<Value>>>),
18 Range(usize, usize),
19 AssociativeArray(Rc<RefCell<AssociativeArray>>),
20 Date(Date),
21 Nil,
22}
23
24impl Value {
25 pub fn kind(&self) -> ValueType {
26 use Value::*;
27
28 match self {
29 Number(_) => ValueType::Number,
30 Boolean(_) => ValueType::Boolean,
31 String(_) => ValueType::String,
32 Function(_) => ValueType::Function,
33 List(_) => ValueType::List,
34 Range(_, _) => ValueType::Range,
35 Nil => ValueType::Nil,
36 AssociativeArray(_) => ValueType::AssociativeArray,
37 Date(_) => ValueType::Date,
38 }
39 }
40
41 pub fn to_bool(&self) -> bool {
42 match self {
43 Value::Number(value) => *value != 0.0,
44 Value::Boolean(value) => *value,
45 Value::String(_) => true,
46 Value::Function(_) => true,
47 Value::List(_) => true,
48 Value::Range(_, _) => true,
49 Value::Nil => false,
50 Value::AssociativeArray(_) => true,
51 Value::Date(_) => true,
52 }
53 }
54
55 pub fn is_iterable(&self) -> bool {
56 matches!(self, Value::List(_) | Value::Range(_, _))
57 }
58}
59
60impl Display for Value {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 use Value::*;
63
64 write!(
65 f,
66 "{}",
67 match self {
68 Number(value) => match value {
69 v if v.is_infinite() => {
70 if v.is_sign_positive() {
71 Literal::POSITIVE_INFINITY_LITERAL.to_string()
72 } else {
73 Literal::NEGATIVE_INFINITY_LITERAL.to_string()
74 }
75 }
76 v if v.is_nan() => Literal::NAN_LITERAL.to_string(),
77 _ => value.to_string(),
78 },
79 Boolean(value) => match *value {
80 true => Literal::TRUE_LITERAL.to_string(),
81 false => Literal::FALSE_LITERAL.to_string(),
82 },
83 String(value) => format!("\"{}\"", value),
84 Function(value) => format!("<função {:#x}>", value.id),
85 List(value) => format!(
86 "[{}]",
87 value
88 .borrow()
89 .iter()
90 .map(|v| match v {
91 Value::String(s) => format!("\"{}\"", escape_special_chars(s)),
92 _ => v.to_string(),
93 })
94 .collect::<Vec<_>>()
95 .join(", ")
96 ),
97 Range(start, end) => format!("{} até {}", start, end),
98 Nil => Literal::NIL_LITERAL.to_string(),
99 AssociativeArray(value) => format!(
100 "{{ {} }}",
101 value
102 .borrow()
103 .iter()
104 .map(|(k, v)| match v {
105 Value::String(s) => (k, format!("\"{}\"", escape_special_chars(s))),
106 _ => (k, v.to_string()),
107 })
108 .map(|(k, v)| match k {
109 AssociativeArrayKey::String(key) => format!("\"{}\": {}", key, v),
110 AssociativeArrayKey::Number(key) => format!("{}: {}", key, v),
111 })
112 .collect::<Vec<_>>()
113 .join(", ")
114 ),
115 Date(value) => value.to_iso_string(),
116 }
117 )
118 }
119}
120
121impl From<Literal> for Value {
122 fn from(literal: Literal) -> Self {
123 use Literal::*;
124
125 match literal {
126 Number(value) => Value::Number(value),
127 String(value) => Value::String(value),
128 Boolean(value) => Value::Boolean(value),
129 Nil => Value::Nil,
130 }
131 }
132}
133
134impl IntoIterator for Value {
135 type Item = Value;
136 type IntoIter = std::vec::IntoIter<Value>;
137
138 fn into_iter(self) -> Self::IntoIter {
139 if !self.is_iterable() {
140 panic!("value is not iterable");
141 }
142
143 match self {
144 Value::List(list) => list.borrow_mut().clone().into_iter(),
145 Value::Range(start, end) => (start..=end)
146 .map(|i| Value::Number(i as f64))
147 .collect::<Vec<_>>()
148 .into_iter(),
149 _ => unreachable!(),
150 }
151 }
152}
153
154#[derive(Debug, PartialEq, Clone)]
155pub enum ValueType {
156 Number,
157 Boolean,
158 String,
159 Function,
160 List,
161 Range,
162 Nil,
163 AssociativeArray,
164 Date,
165}
166
167impl From<Value> for ValueType {
168 fn from(value: Value) -> Self {
169 value.kind()
170 }
171}
172
173impl Display for ValueType {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175 use ValueType::*;
176
177 let str = match self {
178 Number => "número".to_string(),
179 Boolean => "lógico".to_string(),
180 String => "texto".to_string(),
181 Function => "função".to_string(),
182 List => "lista".to_string(),
183 Range => "intervalo".to_string(),
184 AssociativeArray => "dicionário".to_string(),
185 Date => "data".to_string(),
186 Nil => "Nada".to_string(),
187 };
188
189 write!(f, "{}", str)
190 }
191}
192
193pub fn escape_special_chars(s: &str) -> String {
194 let mut result = String::with_capacity(s.len());
195
196 for c in s.chars() {
197 match c {
198 '\0' => result.push_str("\\0"),
199 '\x07' => result.push_str("\\a"),
200 '\x08' => result.push_str("\\b"),
201 '\x0C' => result.push_str("\\f"),
202 '\x0B' => result.push_str("\\v"),
203 '\x1B' => result.push_str("\\e"),
204 '\r' => result.push_str("\\r"),
205 '\n' => result.push_str("\\n"),
206 '\t' => result.push_str("\\t"),
207 '\\' => result.push_str("\\\\"),
208 '"' => result.push_str("\\\""),
209 '\'' => result.push_str("\\\'"),
210
211 c if c.is_control() => {
212 let byte = c as u32;
213 result.push_str(&format!("\\x{byte:02X}"));
214 }
215
216 _ => result.push(c),
217 }
218 }
219
220 result
221}
222
223pub fn escape_value(value: &Value) -> String {
224 match value {
225 Value::String(s) => format!("\"{}\"", escape_special_chars(s)),
226 _ => value.to_string(),
227 }
228}