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