1use indexmap::IndexMap;
2use serde_json;
3use std::collections::HashMap;
4use std::fmt;
5use std::sync::atomic::{AtomicU64, Ordering};
6use std::sync::{Arc, Mutex};
7
8use crate::ast::{Param, Stmt};
9#[cfg(feature = "vm")]
10use crate::bytecode::Chunk;
11
12static NEXT_FN_ID: AtomicU64 = AtomicU64::new(1);
13
14#[derive(Debug, Clone)]
16pub enum Value {
17 Int(i64),
18 Float(f64),
19 Bool(bool),
20 Str(String),
21 Bytes(Vec<u8>),
22 List(Vec<Value>),
23 Dict(IndexMap<String, Value>),
24 Tuple(Vec<Value>),
25 Option(Option<Box<Value>>),
26 Result(Result<Box<Value>, Box<Value>>),
27 Fn(IonFn),
28 BuiltinFn(String, BuiltinFn),
29 BuiltinClosure(String, BuiltinClosureFn),
36 Set(Vec<Value>),
38 HostStruct {
40 type_name: String,
41 fields: IndexMap<String, Value>,
42 },
43 HostEnum {
45 enum_name: String,
46 variant: String,
47 data: Vec<Value>,
48 },
49 #[cfg(feature = "concurrency")]
51 Task(std::sync::Arc<dyn crate::async_rt::TaskHandle>),
52 #[cfg(feature = "concurrency")]
54 Channel(crate::async_rt::ChannelEnd),
55 Cell(Arc<Mutex<Value>>),
57 Range {
59 start: i64,
60 end: i64,
61 inclusive: bool,
62 },
63 Unit,
64}
65
66#[derive(Debug, Clone)]
68pub struct IonFn {
69 pub fn_id: u64,
70 pub name: String,
71 pub params: Vec<Param>,
72 pub body: Vec<Stmt>,
73 pub captures: HashMap<String, Value>,
75}
76
77impl IonFn {
78 pub fn new(
79 name: String,
80 params: Vec<Param>,
81 body: Vec<Stmt>,
82 captures: HashMap<String, Value>,
83 ) -> Self {
84 Self {
85 fn_id: NEXT_FN_ID.fetch_add(1, Ordering::Relaxed),
86 name,
87 params,
88 body,
89 captures,
90 }
91 }
92}
93
94#[cfg(feature = "vm")]
96pub type FnChunkCache = HashMap<u64, Chunk>;
97
98pub type BuiltinFn = fn(&[Value]) -> Result<Value, String>;
100
101#[derive(Clone)]
104pub struct BuiltinClosureFn(
105 pub Arc<dyn Fn(&[Value]) -> Result<Value, String> + Send + Sync>,
106);
107
108impl fmt::Debug for BuiltinClosureFn {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 write!(f, "<closure>")
111 }
112}
113
114impl BuiltinClosureFn {
115 pub fn new<F>(func: F) -> Self
116 where
117 F: Fn(&[Value]) -> Result<Value, String> + Send + Sync + 'static,
118 {
119 Self(Arc::new(func))
120 }
121
122 pub fn call(&self, args: &[Value]) -> Result<Value, String> {
123 (self.0)(args)
124 }
125}
126
127impl Value {
128 pub fn type_name(&self) -> &'static str {
129 match self {
130 Value::Int(_) => ion_static_str!("int"),
131 Value::Float(_) => ion_static_str!("float"),
132 Value::Bool(_) => ion_static_str!("bool"),
133 Value::Str(_) => ion_static_str!("string"),
134 Value::Bytes(_) => ion_static_str!("bytes"),
135 Value::List(_) => ion_static_str!("list"),
136 Value::Dict(_) => ion_static_str!("dict"),
137 Value::Tuple(_) => ion_static_str!("tuple"),
138 Value::Set(_) => ion_static_str!("set"),
139 Value::Option(_) => ion_static_str!("Option"),
140 Value::Result(_) => ion_static_str!("Result"),
141 Value::Fn(_) => ion_static_str!("fn"),
142 Value::BuiltinFn(_, _) => ion_static_str!("builtin_fn"),
143 Value::BuiltinClosure(_, _) => ion_static_str!("builtin_fn"),
144 Value::HostStruct { .. } => ion_static_str!("struct"),
145 Value::HostEnum { .. } => ion_static_str!("enum"),
146 #[cfg(feature = "concurrency")]
147 Value::Task(_) => ion_static_str!("Task"),
148 #[cfg(feature = "concurrency")]
149 Value::Channel(_) => ion_static_str!("Channel"),
150 Value::Cell(_) => ion_static_str!("cell"),
151 Value::Range { .. } => ion_static_str!("range"),
152 Value::Unit => ion_static_str!("()"),
153 }
154 }
155
156 pub fn is_truthy(&self) -> bool {
157 match self {
158 Value::Bool(b) => *b,
159 Value::Int(n) => *n != 0,
160 Value::Bytes(b) => !b.is_empty(),
161 Value::Option(None) => false,
162 Value::Unit => false,
163 _ => true,
164 }
165 }
166
167 pub fn as_int(&self) -> Option<i64> {
168 match self {
169 Value::Int(n) => Some(*n),
170 _ => None,
171 }
172 }
173
174 pub fn as_float(&self) -> Option<f64> {
175 match self {
176 Value::Float(n) => Some(*n),
177 Value::Int(n) => Some(*n as f64),
178 _ => None,
179 }
180 }
181
182 pub fn as_str(&self) -> Option<&str> {
183 match self {
184 Value::Str(s) => Some(s),
185 _ => None,
186 }
187 }
188
189 pub fn as_bool(&self) -> Option<bool> {
190 match self {
191 Value::Bool(b) => Some(*b),
192 _ => None,
193 }
194 }
195
196 pub fn range_to_list(start: i64, end: i64, inclusive: bool) -> Vec<Value> {
198 if inclusive {
199 (start..=end).map(Value::Int).collect()
200 } else {
201 (start..end).map(Value::Int).collect()
202 }
203 }
204
205 pub fn range_len(start: i64, end: i64, inclusive: bool) -> i64 {
207 if inclusive {
208 (end - start + 1).max(0)
209 } else {
210 (end - start).max(0)
211 }
212 }
213}
214
215impl fmt::Display for Value {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 match self {
218 Value::Int(n) => write!(f, "{}", n),
219 Value::Float(n) => {
220 if *n == n.floor() && n.is_finite() {
221 write!(f, "{:.1}", n)
222 } else {
223 write!(f, "{}", n)
224 }
225 }
226 Value::Bool(b) => write!(f, "{}", b),
227 Value::Str(s) => write!(f, "{}", s),
228 Value::Bytes(bytes) => {
229 write!(f, "b\"")?;
230 for &b in bytes {
231 match b {
232 b'\\' => write!(f, "\\\\")?,
233 b'"' => write!(f, "\\\"")?,
234 b'\n' => write!(f, "\\n")?,
235 b'\t' => write!(f, "\\t")?,
236 b'\r' => write!(f, "\\r")?,
237 0x20..=0x7e => write!(f, "{}", b as char)?,
238 _ => write!(f, "\\x{:02x}", b)?,
239 }
240 }
241 write!(f, "\"")
242 }
243 Value::List(items) => {
244 write!(f, "[")?;
245 for (i, item) in items.iter().enumerate() {
246 if i > 0 {
247 write!(f, ", ")?;
248 }
249 write!(f, "{}", item)?;
250 }
251 write!(f, "]")
252 }
253 Value::Dict(map) => {
254 write!(f, "#{{")?;
255 for (i, (k, v)) in map.iter().enumerate() {
256 if i > 0 {
257 write!(f, ", ")?;
258 }
259 write!(f, "\"{}\": {}", k, v)?;
260 }
261 write!(f, "}}")
262 }
263 Value::Tuple(items) => {
264 write!(f, "(")?;
265 for (i, item) in items.iter().enumerate() {
266 if i > 0 {
267 write!(f, ", ")?;
268 }
269 write!(f, "{}", item)?;
270 }
271 if items.len() == 1 {
272 write!(f, ",")?;
273 }
274 write!(f, ")")
275 }
276 Value::Set(items) => {
277 write!(f, "set{{")?;
278 for (i, item) in items.iter().enumerate() {
279 if i > 0 {
280 write!(f, ", ")?;
281 }
282 write!(f, "{}", item)?;
283 }
284 write!(f, "}}")
285 }
286 Value::Option(opt) => match opt {
287 Some(v) => write!(f, "Some({})", v),
288 None => write!(f, "None"),
289 },
290 Value::Result(res) => match res {
291 Ok(v) => write!(f, "Ok({})", v),
292 Err(e) => write!(f, "Err({})", e),
293 },
294 Value::Fn(func) => write!(f, "<fn {}>", func.name),
295 Value::BuiltinFn(name, _) => write!(f, "<builtin {}>", name),
296 Value::BuiltinClosure(name, _) => write!(f, "<builtin {}>", name),
297 #[cfg(feature = "concurrency")]
298 Value::Task(_) => write!(f, "<Task>"),
299 #[cfg(feature = "concurrency")]
300 Value::Channel(ch) => match ch {
301 crate::async_rt::ChannelEnd::Sender(_) => write!(f, "<ChannelTx>"),
302 crate::async_rt::ChannelEnd::Receiver(_) => write!(f, "<ChannelRx>"),
303 },
304 Value::HostStruct { type_name, fields } => {
305 write!(f, "{} {{ ", type_name)?;
306 for (i, (k, v)) in fields.iter().enumerate() {
307 if i > 0 {
308 write!(f, ", ")?;
309 }
310 write!(f, "{}: {}", k, v)?;
311 }
312 write!(f, " }}")
313 }
314 Value::HostEnum {
315 enum_name,
316 variant,
317 data,
318 } => {
319 write!(f, "{}::{}", enum_name, variant)?;
320 if !data.is_empty() {
321 write!(f, "(")?;
322 for (i, v) in data.iter().enumerate() {
323 if i > 0 {
324 write!(f, ", ")?;
325 }
326 write!(f, "{}", v)?;
327 }
328 write!(f, ")")?;
329 }
330 Ok(())
331 }
332 Value::Cell(cell) => {
333 let inner = cell.lock().unwrap();
334 write!(f, "cell({})", *inner)
335 }
336 Value::Range {
337 start,
338 end,
339 inclusive,
340 } => {
341 if *inclusive {
342 write!(f, "{}..={}", start, end)
343 } else {
344 write!(f, "{}..{}", start, end)
345 }
346 }
347 Value::Unit => write!(f, "()"),
348 }
349 }
350}
351
352impl PartialEq for Value {
353 fn eq(&self, other: &Self) -> bool {
354 match (self, other) {
355 (Value::Int(a), Value::Int(b)) => a == b,
356 (Value::Float(a), Value::Float(b)) => a == b,
357 (Value::Int(a), Value::Float(b)) => (*a as f64) == *b,
358 (Value::Float(a), Value::Int(b)) => *a == (*b as f64),
359 (Value::Bool(a), Value::Bool(b)) => a == b,
360 (Value::Str(a), Value::Str(b)) => a == b,
361 (Value::Bytes(a), Value::Bytes(b)) => a == b,
362 (Value::List(a), Value::List(b)) => a == b,
363 (Value::Tuple(a), Value::Tuple(b)) => a == b,
364 (Value::Dict(a), Value::Dict(b)) => a == b,
365 (Value::Set(a), Value::Set(b)) => a.len() == b.len() && a.iter().all(|v| b.contains(v)),
366 (Value::Option(a), Value::Option(b)) => a == b,
367 (Value::Result(Ok(a)), Value::Result(Ok(b))) => a == b,
368 (Value::Result(Err(a)), Value::Result(Err(b))) => a == b,
369 (
370 Value::HostStruct {
371 type_name: a_name,
372 fields: a_fields,
373 },
374 Value::HostStruct {
375 type_name: b_name,
376 fields: b_fields,
377 },
378 ) => a_name == b_name && a_fields == b_fields,
379 (
380 Value::HostEnum {
381 enum_name: a_en,
382 variant: a_v,
383 data: a_d,
384 },
385 Value::HostEnum {
386 enum_name: b_en,
387 variant: b_v,
388 data: b_d,
389 },
390 ) => a_en == b_en && a_v == b_v && a_d == b_d,
391 (Value::Cell(a), Value::Cell(b)) => Arc::ptr_eq(a, b),
392 (
393 Value::Range {
394 start: s1,
395 end: e1,
396 inclusive: i1,
397 },
398 Value::Range {
399 start: s2,
400 end: e2,
401 inclusive: i2,
402 },
403 ) => s1 == s2 && e1 == e2 && i1 == i2,
404 (Value::Unit, Value::Unit) => true,
405 (Value::Option(None), Value::Unit) => false,
406 _ => false,
408 }
409 }
410}
411
412impl Value {
415 pub fn to_json(&self) -> serde_json::Value {
417 match self {
418 Value::Int(n) => serde_json::Value::Number((*n).into()),
419 Value::Float(n) => serde_json::Number::from_f64(*n)
420 .map(serde_json::Value::Number)
421 .unwrap_or(serde_json::Value::Null),
422 Value::Bool(b) => serde_json::Value::Bool(*b),
423 Value::Str(s) => serde_json::Value::String(s.clone()),
424 Value::List(items) => {
425 serde_json::Value::Array(items.iter().map(|v| v.to_json()).collect())
426 }
427 Value::Dict(map) => {
428 let obj: serde_json::Map<String, serde_json::Value> =
429 map.iter().map(|(k, v)| (k.clone(), v.to_json())).collect();
430 serde_json::Value::Object(obj)
431 }
432 Value::Tuple(items) => {
433 serde_json::Value::Array(items.iter().map(|v| v.to_json()).collect())
434 }
435 Value::Set(items) => {
436 serde_json::Value::Array(items.iter().map(|v| v.to_json()).collect())
437 }
438 Value::Option(Some(v)) => v.to_json(),
439 Value::Option(None) | Value::Unit => serde_json::Value::Null,
440 Value::Result(Ok(v)) => v.to_json(),
441 Value::Result(Err(v)) => {
442 let mut map = serde_json::Map::new();
443 map.insert("error".to_string(), v.to_json());
444 serde_json::Value::Object(map)
445 }
446 Value::HostStruct { fields, .. } => {
447 let obj: serde_json::Map<String, serde_json::Value> = fields
448 .iter()
449 .map(|(k, v)| (k.clone(), v.to_json()))
450 .collect();
451 serde_json::Value::Object(obj)
452 }
453 Value::HostEnum {
454 enum_name,
455 variant,
456 data,
457 } => {
458 let mut map = serde_json::Map::new();
459 map.insert(
460 "_type".to_string(),
461 serde_json::Value::String(format!("{}::{}", enum_name, variant)),
462 );
463 if !data.is_empty() {
464 map.insert(
465 "data".to_string(),
466 serde_json::Value::Array(data.iter().map(|v| v.to_json()).collect()),
467 );
468 }
469 serde_json::Value::Object(map)
470 }
471 #[cfg(feature = "concurrency")]
472 Value::Task(_) | Value::Channel(_) => serde_json::Value::Null,
473 Value::Cell(cell) => cell.lock().unwrap().to_json(),
474 Value::Bytes(b) => {
475 let hex: String = b.iter().map(|byte| format!("{:02x}", byte)).collect();
476 serde_json::Value::String(hex)
477 }
478 Value::Range {
479 start,
480 end,
481 inclusive,
482 } => serde_json::Value::Array(
483 Value::range_to_list(*start, *end, *inclusive)
484 .iter()
485 .map(|v| v.to_json())
486 .collect(),
487 ),
488 Value::Fn(_) | Value::BuiltinFn(_, _) | Value::BuiltinClosure(_, _) => {
489 serde_json::Value::Null
490 }
491 }
492 }
493
494 #[cfg(feature = "msgpack")]
496 pub fn to_msgpack(&self) -> Result<Vec<u8>, String> {
497 let mp = self.to_msgpack_value();
498 let mut buf = Vec::new();
499 rmpv::encode::write_value(&mut buf, &mp)
500 .map_err(|e| format!("{}{}", ion_str!("msgpack_encode error: "), e))?;
501 Ok(buf)
502 }
503
504 #[cfg(feature = "msgpack")]
506 pub fn from_msgpack(data: &[u8]) -> Result<Value, String> {
507 let mut cursor = std::io::Cursor::new(data);
508 let mp = rmpv::decode::read_value(&mut cursor)
509 .map_err(|e| format!("{}{}", ion_str!("msgpack_decode error: "), e))?;
510 Ok(Self::from_msgpack_value(mp))
511 }
512
513 #[cfg(feature = "msgpack")]
514 fn to_msgpack_value(&self) -> rmpv::Value {
515 match self {
516 Value::Int(n) => rmpv::Value::Integer((*n).into()),
517 Value::Float(n) => rmpv::Value::F64(*n),
518 Value::Bool(b) => rmpv::Value::Boolean(*b),
519 Value::Str(s) => rmpv::Value::String(s.clone().into()),
520 Value::Bytes(b) => rmpv::Value::Binary(b.clone()),
521 Value::List(items) => {
522 rmpv::Value::Array(items.iter().map(|v| v.to_msgpack_value()).collect())
523 }
524 Value::Dict(map) => {
525 let pairs: Vec<(rmpv::Value, rmpv::Value)> = map
526 .iter()
527 .map(|(k, v)| (rmpv::Value::String(k.clone().into()), v.to_msgpack_value()))
528 .collect();
529 rmpv::Value::Map(pairs)
530 }
531 Value::Tuple(items) => {
532 rmpv::Value::Array(items.iter().map(|v| v.to_msgpack_value()).collect())
533 }
534 Value::Set(items) => {
535 rmpv::Value::Array(items.iter().map(|v| v.to_msgpack_value()).collect())
536 }
537 Value::Option(Some(v)) => v.to_msgpack_value(),
538 Value::Option(None) | Value::Unit => rmpv::Value::Nil,
539 Value::Result(Ok(v)) => v.to_msgpack_value(),
540 Value::Result(Err(v)) => {
541 let pairs = vec![(rmpv::Value::String("error".into()), v.to_msgpack_value())];
542 rmpv::Value::Map(pairs)
543 }
544 Value::HostStruct { fields, .. } => {
545 let pairs: Vec<(rmpv::Value, rmpv::Value)> = fields
546 .iter()
547 .map(|(k, v)| (rmpv::Value::String(k.clone().into()), v.to_msgpack_value()))
548 .collect();
549 rmpv::Value::Map(pairs)
550 }
551 Value::HostEnum {
552 enum_name,
553 variant,
554 data,
555 } => {
556 let mut pairs = vec![(
557 rmpv::Value::String("_type".into()),
558 rmpv::Value::String(format!("{}::{}", enum_name, variant).into()),
559 )];
560 if !data.is_empty() {
561 pairs.push((
562 rmpv::Value::String("data".into()),
563 rmpv::Value::Array(data.iter().map(|v| v.to_msgpack_value()).collect()),
564 ));
565 }
566 rmpv::Value::Map(pairs)
567 }
568 #[cfg(feature = "concurrency")]
569 Value::Task(_) | Value::Channel(_) => rmpv::Value::Nil,
570 Value::Cell(cell) => cell.lock().unwrap().to_msgpack_value(),
571 Value::Range {
572 start,
573 end,
574 inclusive,
575 } => rmpv::Value::Array(
576 Value::range_to_list(*start, *end, *inclusive)
577 .iter()
578 .map(|v| v.to_msgpack_value())
579 .collect(),
580 ),
581 Value::Fn(_) | Value::BuiltinFn(_, _) | Value::BuiltinClosure(_, _) => {
582 rmpv::Value::Nil
583 }
584 }
585 }
586
587 #[cfg(feature = "msgpack")]
588 fn from_msgpack_value(mp: rmpv::Value) -> Value {
589 match mp {
590 rmpv::Value::Nil => Value::Option(None),
591 rmpv::Value::Boolean(b) => Value::Bool(b),
592 rmpv::Value::Integer(n) => {
593 if let Some(i) = n.as_i64() {
594 Value::Int(i)
595 } else if let Some(u) = n.as_u64() {
596 Value::Int(u as i64)
597 } else {
598 Value::Int(0)
599 }
600 }
601 rmpv::Value::F32(f) => Value::Float(f as f64),
602 rmpv::Value::F64(f) => Value::Float(f),
603 rmpv::Value::String(s) => Value::Str(s.into_str().unwrap_or_default().to_string()),
604 rmpv::Value::Binary(b) => Value::Bytes(b),
605 rmpv::Value::Array(arr) => {
606 Value::List(arr.into_iter().map(Self::from_msgpack_value).collect())
607 }
608 rmpv::Value::Map(pairs) => {
609 let dict: IndexMap<String, Value> = pairs
610 .into_iter()
611 .filter_map(|(k, v)| {
612 let key = match k {
613 rmpv::Value::String(s) => s.into_str().map(|s| s.to_string()),
614 _ => None,
615 };
616 key.map(|k| (k, Self::from_msgpack_value(v)))
617 })
618 .collect();
619 Value::Dict(dict)
620 }
621 rmpv::Value::Ext(_, data) => Value::Bytes(data),
622 }
623 }
624
625 pub fn from_json(json: serde_json::Value) -> Value {
627 match json {
628 serde_json::Value::Null => Value::Option(None),
629 serde_json::Value::Bool(b) => Value::Bool(b),
630 serde_json::Value::Number(n) => {
631 if let Some(i) = n.as_i64() {
632 Value::Int(i)
633 } else if let Some(f) = n.as_f64() {
634 Value::Float(f)
635 } else {
636 Value::Int(0)
637 }
638 }
639 serde_json::Value::String(s) => Value::Str(s),
640 serde_json::Value::Array(arr) => {
641 Value::List(arr.into_iter().map(Value::from_json).collect())
642 }
643 serde_json::Value::Object(map) => {
644 let dict: IndexMap<String, Value> = map
645 .into_iter()
646 .map(|(k, v)| (k, Value::from_json(v)))
647 .collect();
648 Value::Dict(dict)
649 }
650 }
651 }
652}