1use indexmap::IndexMap;
5use std::fmt;
6use std::sync::Arc;
7
8use super::env::WeakEnv;
9use crate::parser::ast::{LambdaBody, SchemaField, Stmt};
10
11#[derive(Debug, Clone)]
12pub enum Value<'a> {
13 Null,
14 Bool(bool),
15 Int(i64),
16 Float(f64),
17 Str(Arc<str>),
18 List(Arc<Vec<Value<'a>>>),
19 Object(Arc<IndexMap<String, Value<'a>>>),
21 Schema(Arc<SchemaDef<'a>>),
22 Enum(Arc<EnumDef<'a>>),
24 Function(Arc<FunctionDef<'a>>),
25}
26
27#[derive(Debug, Clone, PartialEq)]
29pub struct EnumDef<'a> {
30 pub name: &'a str,
31 pub members: Vec<&'a str>,
32}
33
34#[derive(Debug, Clone, PartialEq)]
35pub struct SchemaDef<'a> {
36 pub name: &'a str,
37 pub fields: Vec<SchemaField<'a>>,
38 pub field_enums: std::collections::HashMap<&'a str, Arc<EnumDef<'a>>>,
42}
43
44pub struct FunctionDef<'a> {
45 pub params: Vec<&'a str>,
46 pub body: FuncBody<'a>,
47 pub closure: WeakEnv<'a>,
50 pub defined_in_root: bool,
53}
54
55#[derive(Clone)]
56pub enum FuncBody<'a> {
57 Lambda(LambdaBody<'a>),
58 Block(Vec<Stmt<'a>>),
60}
61
62impl fmt::Debug for FunctionDef<'_> {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 write!(f, "<fn({})>", self.params.join(", "))
65 }
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
69pub enum TypeTag {
70 Null,
71 Bool,
72 Int,
73 Float,
74 Str,
75 List,
76 Object,
77 Schema,
78 Enum,
79 Function,
80}
81
82impl<'a> Value<'a> {
83 pub fn tag(&self) -> TypeTag {
84 match self {
85 Value::Null => TypeTag::Null,
86 Value::Bool(_) => TypeTag::Bool,
87 Value::Int(_) => TypeTag::Int,
88 Value::Float(_) => TypeTag::Float,
89 Value::Str(_) => TypeTag::Str,
90 Value::List(_) => TypeTag::List,
91 Value::Object(_) => TypeTag::Object,
92 Value::Schema(_) => TypeTag::Schema,
93 Value::Enum(_) => TypeTag::Enum,
94 Value::Function(_) => TypeTag::Function,
95 }
96 }
97
98 pub fn type_name(&self) -> &'static str {
99 match self.tag() {
100 TypeTag::Null => "Null",
101 TypeTag::Bool => "Bool",
102 TypeTag::Int => "Int",
103 TypeTag::Float => "Float",
104 TypeTag::Str => "String",
105 TypeTag::List => "List",
106 TypeTag::Object => "Object",
107 TypeTag::Schema => "Schema",
108 TypeTag::Enum => "Enum",
109 TypeTag::Function => "Function",
110 }
111 }
112
113 pub fn object(map: IndexMap<String, Value<'a>>) -> Self {
114 Value::Object(Arc::new(map))
115 }
116
117 pub fn list(items: Vec<Value<'a>>) -> Self {
118 Value::List(Arc::new(items))
119 }
120
121 pub fn str(s: impl AsRef<str>) -> Self {
122 Value::Str(Arc::from(s.as_ref()))
123 }
124}
125
126impl PartialEq for Value<'_> {
129 fn eq(&self, other: &Self) -> bool {
130 use Value::*;
131 match (self, other) {
132 (Null, Null) => true,
133 (Bool(a), Bool(b)) => a == b,
134 (Int(a), Int(b)) => a == b,
135 (Float(a), Float(b)) => a == b,
136 (Int(a), Float(b)) | (Float(b), Int(a)) => *a as f64 == *b,
137 (Str(a), Str(b)) => a == b,
138 (List(a), List(b)) => a == b,
139 (Object(a), Object(b)) => a == b,
140 (Schema(a), Schema(b)) => Arc::ptr_eq(a, b),
141 (Function(a), Function(b)) => Arc::ptr_eq(a, b),
142 _ => false,
143 }
144 }
145}