1use crate::ast::Expr;
4use crate::error::{JsonnetError, Result};
5use std::collections::HashMap;
6use std::fmt;
7
8#[derive(Debug, Clone, PartialEq)]
10#[derive(Default)]
11pub enum JsonnetValue {
12 #[default]
14 Null,
15 Boolean(bool),
17 Number(f64),
19 String(String),
21 Array(Vec<JsonnetValue>),
23 Object(HashMap<String, JsonnetValue>),
25 Function(JsonnetFunction),
27 Builtin(JsonnetBuiltin),
29}
30
31impl JsonnetValue {
32 pub fn null() -> Self {
34 JsonnetValue::Null
35 }
36
37 pub fn boolean(b: bool) -> Self {
39 JsonnetValue::Boolean(b)
40 }
41
42 pub fn number(n: f64) -> Self {
44 JsonnetValue::Number(n)
45 }
46
47 pub fn string(s: impl Into<String>) -> Self {
49 JsonnetValue::String(s.into())
50 }
51
52 pub fn array(values: Vec<JsonnetValue>) -> Self {
54 JsonnetValue::Array(values)
55 }
56
57 pub fn object(fields: HashMap<String, JsonnetValue>) -> Self {
59 JsonnetValue::Object(fields)
60 }
61
62 pub fn is_truthy(&self) -> bool {
64 match self {
65 JsonnetValue::Null => false,
66 JsonnetValue::Boolean(b) => *b,
67 JsonnetValue::Number(n) => *n != 0.0,
68 JsonnetValue::String(s) => !s.is_empty(),
69 JsonnetValue::Array(a) => !a.is_empty(),
70 JsonnetValue::Object(o) => !o.is_empty(),
71 JsonnetValue::Function(_) => true,
72 JsonnetValue::Builtin(_) => true,
73 }
74 }
75
76 pub fn type_name(&self) -> &'static str {
78 match self {
79 JsonnetValue::Null => "null",
80 JsonnetValue::Boolean(_) => "boolean",
81 JsonnetValue::Number(_) => "number",
82 JsonnetValue::String(_) => "string",
83 JsonnetValue::Array(_) => "array",
84 JsonnetValue::Object(_) => "object",
85 JsonnetValue::Function(_) => "function",
86 JsonnetValue::Builtin(_) => "function",
87 }
88 }
89
90 pub fn to_json_value(&self) -> serde_json::Value {
92 match self {
93 JsonnetValue::Null => serde_json::Value::Null,
94 JsonnetValue::Boolean(b) => serde_json::Value::Bool(*b),
95 JsonnetValue::Number(n) => serde_json::json!(*n),
96 JsonnetValue::String(s) => serde_json::Value::String(s.clone()),
97 JsonnetValue::Array(arr) => {
98 let json_arr: Vec<serde_json::Value> = arr.iter().map(|v| v.to_json_value()).collect();
99 serde_json::Value::Array(json_arr)
100 }
101 JsonnetValue::Object(obj) => {
102 let mut json_obj = serde_json::Map::new();
103 for (k, v) in obj {
104 json_obj.insert(k.clone(), v.to_json_value());
105 }
106 serde_json::Value::Object(json_obj)
107 }
108 JsonnetValue::Function(_) => {
109 serde_json::Value::Null
110 }
111 JsonnetValue::Builtin(_) => {
112 serde_json::Value::String("<function>".to_string())
114 }
115 }
116 }
117
118 pub fn as_string(&self) -> Result<&str> {
120 match self {
121 JsonnetValue::String(s) => Ok(s),
122 _ => Err(JsonnetError::type_error(format!("Expected string, got {}", self.type_name()))),
123 }
124 }
125
126 pub fn as_number(&self) -> Result<f64> {
128 match self {
129 JsonnetValue::Number(n) => Ok(*n),
130 _ => Err(JsonnetError::type_error(format!("Expected number, got {}", self.type_name()))),
131 }
132 }
133
134 pub fn as_boolean(&self) -> Result<bool> {
136 match self {
137 JsonnetValue::Boolean(b) => Ok(*b),
138 _ => Err(JsonnetError::type_error(format!("Expected boolean, got {}", self.type_name()))),
139 }
140 }
141
142 pub fn as_array(&self) -> Result<&Vec<JsonnetValue>> {
144 match self {
145 JsonnetValue::Array(arr) => Ok(arr),
146 _ => Err(JsonnetError::type_error(format!("Expected array, got {}", self.type_name()))),
147 }
148 }
149
150 pub fn as_object(&self) -> Result<&HashMap<String, JsonnetValue>> {
152 match self {
153 JsonnetValue::Object(obj) => Ok(obj),
154 _ => Err(JsonnetError::type_error(format!("Expected object, got {}", self.type_name()))),
155 }
156 }
157
158 pub fn get_field(&self, field: &str) -> Result<&JsonnetValue> {
160 match self {
161 JsonnetValue::Object(obj) => {
162 obj.get(field)
163 .ok_or_else(|| JsonnetError::undefined_field(field.to_string()))
164 }
165 _ => Err(JsonnetError::type_error(format!("Expected object, got {}", self.type_name()))),
166 }
167 }
168
169 pub fn get_index(&self, index: i64) -> Result<&JsonnetValue> {
171 match self {
172 JsonnetValue::Array(arr) => {
173 let idx = if index < 0 {
174 (arr.len() as i64 + index) as usize
175 } else {
176 index as usize
177 };
178
179 arr.get(idx)
180 .ok_or_else(|| JsonnetError::index_out_of_bounds(index))
181 }
182 _ => Err(JsonnetError::type_error(format!("Expected array, got {}", self.type_name()))),
183 }
184 }
185
186 pub fn equals(&self, other: &JsonnetValue) -> bool {
188 match (self, other) {
189 (JsonnetValue::Null, JsonnetValue::Null) => true,
190 (JsonnetValue::Boolean(a), JsonnetValue::Boolean(b)) => a == b,
191 (JsonnetValue::Number(a), JsonnetValue::Number(b)) => (a - b).abs() < f64::EPSILON,
192 (JsonnetValue::String(a), JsonnetValue::String(b)) => a == b,
193 (JsonnetValue::Array(a), JsonnetValue::Array(b)) => {
194 a.len() == b.len() && a.iter().zip(b.iter()).all(|(x, y)| x.equals(y))
195 }
196 (JsonnetValue::Object(a), JsonnetValue::Object(b)) => {
197 a.len() == b.len() && a.iter().all(|(k, v)| {
198 b.get(k).is_some_and(|bv| v.equals(bv))
199 })
200 }
201 _ => false,
202 }
203 }
204
205 pub fn add(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
207 match (self, other) {
208 (JsonnetValue::Number(a), JsonnetValue::Number(b)) => Ok(JsonnetValue::number(a + b)),
209 (JsonnetValue::String(a), JsonnetValue::String(b)) => Ok(JsonnetValue::string(format!("{}{}", a, b))),
210 (JsonnetValue::Array(a), JsonnetValue::Array(b)) => {
211 let mut result = a.clone();
212 result.extend(b.clone());
213 Ok(JsonnetValue::Array(result))
214 }
215 _ => Err(JsonnetError::runtime_error("Cannot add these types")),
216 }
217 }
218
219 pub fn sub(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
220 match (self, other) {
221 (JsonnetValue::Number(a), JsonnetValue::Number(b)) => Ok(JsonnetValue::number(a - b)),
222 _ => Err(JsonnetError::runtime_error("Cannot subtract these types")),
223 }
224 }
225
226 pub fn mul(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
227 match (self, other) {
228 (JsonnetValue::Number(a), JsonnetValue::Number(b)) => Ok(JsonnetValue::number(a * b)),
229 _ => Err(JsonnetError::runtime_error("Cannot multiply these types")),
230 }
231 }
232
233 pub fn div(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
234 match (self, other) {
235 (JsonnetValue::Number(a), JsonnetValue::Number(b)) => {
236 if *b == 0.0 {
237 Err(JsonnetError::runtime_error("Division by zero"))
238 } else {
239 Ok(JsonnetValue::number(a / b))
240 }
241 }
242 _ => Err(JsonnetError::runtime_error("Cannot divide these types")),
243 }
244 }
245
246 pub fn modulo(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
247 match (self, other) {
248 (JsonnetValue::Number(a), JsonnetValue::Number(b)) => {
249 if *b == 0.0 {
250 Err(JsonnetError::runtime_error("Modulo by zero"))
251 } else {
252 Ok(JsonnetValue::number(a % b))
253 }
254 }
255 _ => Err(JsonnetError::runtime_error("Cannot modulo these types")),
256 }
257 }
258
259 pub fn lt(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
261 match (self, other) {
262 (JsonnetValue::Number(a), JsonnetValue::Number(b)) => Ok(JsonnetValue::boolean(a < b)),
263 (JsonnetValue::String(a), JsonnetValue::String(b)) => Ok(JsonnetValue::boolean(a < b)),
264 _ => Err(JsonnetError::runtime_error("Cannot compare these types")),
265 }
266 }
267
268 pub fn le(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
269 match (self, other) {
270 (JsonnetValue::Number(a), JsonnetValue::Number(b)) => Ok(JsonnetValue::boolean(a <= b)),
271 (JsonnetValue::String(a), JsonnetValue::String(b)) => Ok(JsonnetValue::boolean(a <= b)),
272 _ => Err(JsonnetError::runtime_error("Cannot compare these types")),
273 }
274 }
275
276 pub fn gt(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
277 match (self, other) {
278 (JsonnetValue::Number(a), JsonnetValue::Number(b)) => Ok(JsonnetValue::boolean(a > b)),
279 (JsonnetValue::String(a), JsonnetValue::String(b)) => Ok(JsonnetValue::boolean(a > b)),
280 _ => Err(JsonnetError::runtime_error("Cannot compare these types")),
281 }
282 }
283
284 pub fn ge(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
285 match (self, other) {
286 (JsonnetValue::Number(a), JsonnetValue::Number(b)) => Ok(JsonnetValue::boolean(a >= b)),
287 (JsonnetValue::String(a), JsonnetValue::String(b)) => Ok(JsonnetValue::boolean(a >= b)),
288 _ => Err(JsonnetError::runtime_error("Cannot compare these types")),
289 }
290 }
291
292 pub fn eq(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
293 Ok(JsonnetValue::boolean(self.equals(other)))
294 }
295
296 pub fn ne(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
297 Ok(JsonnetValue::boolean(!self.equals(other)))
298 }
299
300 pub fn and(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
302 if self.is_truthy() {
303 Ok(other.clone())
304 } else {
305 Ok(self.clone())
306 }
307 }
308
309 pub fn or(&self, other: &JsonnetValue) -> Result<JsonnetValue> {
310 if self.is_truthy() {
311 Ok(self.clone())
312 } else {
313 Ok(other.clone())
314 }
315 }
316
317 pub fn not(&self) -> Result<JsonnetValue> {
319 Ok(JsonnetValue::boolean(!self.is_truthy()))
320 }
321
322 pub fn neg(&self) -> Result<JsonnetValue> {
323 match self {
324 JsonnetValue::Number(n) => Ok(JsonnetValue::number(-n)),
325 _ => Err(JsonnetError::runtime_error("Cannot negate this type")),
326 }
327 }
328}
329
330impl fmt::Display for JsonnetValue {
331 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
332 match self {
333 JsonnetValue::Null => write!(f, "null"),
334 JsonnetValue::Boolean(b) => write!(f, "{}", b),
335 JsonnetValue::Number(n) => write!(f, "{}", n),
336 JsonnetValue::String(s) => write!(f, "{:?}", s),
337 JsonnetValue::Array(arr) => {
338 write!(f, "[")?;
339 for (i, item) in arr.iter().enumerate() {
340 if i > 0 {
341 write!(f, ", ")?;
342 }
343 write!(f, "{}", item)?;
344 }
345 write!(f, "]")
346 }
347 JsonnetValue::Object(obj) => {
348 write!(f, "{{")?;
349 for (i, (key, value)) in obj.iter().enumerate() {
350 if i > 0 {
351 write!(f, ", ")?;
352 }
353 write!(f, "{}: {}", key, value)?;
354 }
355 write!(f, "}}")
356 }
357 JsonnetValue::Function(_) => write!(f, "<function>"),
358 JsonnetValue::Builtin(_) => write!(f, "<builtin>"),
359 }
360 }
361}
362
363
364#[derive(Debug, Clone, PartialEq)]
366pub enum JsonnetBuiltin {
367 Length,
368 StdLibFunction(String),
369 }
371
372impl JsonnetBuiltin {
373 pub fn call(&self, args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
374 match self {
375 JsonnetBuiltin::Length => crate::stdlib::StdLib::length(args),
376 JsonnetBuiltin::StdLibFunction(func_name) => crate::stdlib::StdLib::call_function(func_name, args),
377 }
378 }
379}
380
381#[derive(Debug, Clone)]
383pub struct JsonnetFunction {
384 pub parameters: Vec<String>,
385 pub body: Box<Expr>,
386 pub environment: HashMap<String, JsonnetValue>,
387}
388
389impl PartialEq for JsonnetFunction {
390 fn eq(&self, _other: &JsonnetFunction) -> bool {
391 false
393 }
394}
395
396impl JsonnetFunction {
397 pub fn new(parameters: Vec<String>, body: Box<Expr>, environment: HashMap<String, JsonnetValue>) -> Self {
399 JsonnetFunction {
400 parameters,
401 body,
402 environment,
403 }
404 }
405
406 pub fn call(&self, args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
408 if args.len() != self.parameters.len() {
409 return Err(JsonnetError::invalid_function_call(format!(
410 "Expected {} arguments, got {}",
411 self.parameters.len(),
412 args.len()
413 )));
414 }
415
416 let mut env = self.environment.clone();
418 for (param, arg) in self.parameters.iter().zip(args) {
419 env.insert(param.clone(), arg);
420 }
421
422 Err(JsonnetError::runtime_error("Function evaluation not yet implemented"))
426 }
427}
428