1
#![allow(clippy::unwrap_used)]
2
#![allow(clippy::expect_used)]
3
use std::cell::RefCell;
4
use std::collections::HashMap;
5
use std::rc::Rc;
6
use std::sync::{Arc, RwLock};
7
use ustr::Ustr;
8

            
9
use serde_json::Map as JsonMap;
10
use serde_json::Value;
11
use serde_json::Value as JsonValue;
12

            
13
use crate::ast::ac_operators::ACOperatorKind;
14
use crate::ast::comprehension::ComprehensionBuilder;
15
use crate::ast::records::RecordValue;
16
use crate::ast::{
17
    AbstractLiteral, Atom, DeclarationPtr, Domain, Expression, FuncAttr, IntVal, JectivityAttr,
18
    Literal, Name, PartialityAttr, Range, RecordEntry, SetAttr, SymbolTable,
19
};
20
use crate::ast::{DeclarationKind, Moo};
21
use crate::ast::{DomainPtr, Metadata};
22
use crate::context::Context;
23
use crate::error::{Error, Result};
24
use crate::{Model, bug, error, into_matrix_expr, throw_error};
25

            
26
#[allow(unused_macros)]
27
macro_rules! parser_trace {
28
    ($($arg:tt)+) => {
29
        log::trace!(target:"jsonparser",$($arg)+)
30
    };
31
}
32

            
33
#[allow(unused_macros)]
34
macro_rules! parser_debug {
35
    ($($arg:tt)+) => {
36
        log::debug!(target:"jsonparser",$($arg)+)
37
    };
38
}
39

            
40
pub fn model_from_json(str: &str, context: Arc<RwLock<Context<'static>>>) -> Result<Model> {
41
    let mut m = Model::new(context);
42
    let v: JsonValue = serde_json::from_str(str)?;
43
    let statements = v["mStatements"]
44
        .as_array()
45
        .ok_or(error!("mStatements is not an array"))?;
46

            
47
    for statement in statements {
48
        let entry = statement
49
            .as_object()
50
            .ok_or(error!("mStatements contains a non-object"))?
51
            .iter()
52
            .next()
53
            .ok_or(error!("mStatements contains an empty object"))?;
54

            
55
        match entry.0.as_str() {
56
            "Declaration" => {
57
                let decl = entry
58
                    .1
59
                    .as_object()
60
                    .ok_or(error!("Declaration is not an object".to_owned()))?;
61

            
62
                // One field in the declaration should tell us what kind it is.
63
                //
64
                // Find it, ignoring the other fields.
65
                //
66
                // e.g. FindOrGiven,
67

            
68
                let mut valid_decl: bool = false;
69
                let scope = m.as_submodel().symbols_ptr_unchecked().clone();
70
                let submodel = m.as_submodel_mut();
71
                for (kind, value) in decl {
72
                    match kind.as_str() {
73
                        "FindOrGiven" => {
74
                            parse_variable(value, &mut submodel.symbols_mut())?;
75
                            valid_decl = true;
76
                            break;
77
                        }
78
                        "Letting" => {
79
                            parse_letting(value, &scope)?;
80
                            valid_decl = true;
81
                            break;
82
                        }
83
                        _ => continue,
84
                    }
85
                }
86

            
87
                if !valid_decl {
88
                    throw_error!("Declaration is not a valid kind")?;
89
                }
90
            }
91
            "SuchThat" => {
92
                let constraints_arr = match entry.1.as_array() {
93
                    Some(x) => x,
94
                    None => bug!("SuchThat is not a vector"),
95
                };
96

            
97
                let constraints: Vec<Expression> = constraints_arr
98
                    .iter()
99
                    .map(|x| {
100
                        parse_expression(x, m.as_submodel_mut().symbols_ptr_unchecked()).unwrap()
101
                    })
102
                    .collect();
103
                m.as_submodel_mut().add_constraints(constraints);
104
                // println!("Nb constraints {}", m.constraints.len());
105
            }
106
            otherwise => bug!("Unhandled Statement {:#?}", otherwise),
107
        }
108
    }
109
    Ok(m)
110
}
111

            
112
fn parse_variable(v: &JsonValue, symtab: &mut SymbolTable) -> Result<()> {
113
    let arr = v.as_array().ok_or(error!("FindOrGiven is not an array"))?;
114
    let name = arr[1]
115
        .as_object()
116
        .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
117
        .as_str()
118
        .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
119

            
120
    let name = Name::User(Ustr::from(name));
121

            
122
    let domain = arr[2]
123
        .as_object()
124
        .ok_or(error!("FindOrGiven[2] is not an object"))?
125
        .iter()
126
        .next()
127
        .ok_or(error!("FindOrGiven[2] is an empty object"))?;
128

            
129
    let domain = parse_domain(domain.0, domain.1, symtab)?;
130

            
131
    symtab
132
        .insert(DeclarationPtr::new_var(name.clone(), domain))
133
        .ok_or(Error::Parse(format!(
134
            "Could not add {name} to symbol table as it already exists"
135
        )))
136
}
137

            
138
fn parse_letting(v: &JsonValue, scope: &Rc<RefCell<SymbolTable>>) -> Result<()> {
139
    let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
140
    let name = arr[0]
141
        .as_object()
142
        .ok_or(error!("Letting[0] is not an object"))?["Name"]
143
        .as_str()
144
        .ok_or(error!("Letting[0].Name is not a string"))?;
145
    let name = Name::User(Ustr::from(name));
146
    // value letting
147
    if let Some(value) = parse_expression(&arr[1], scope) {
148
        let mut symtab = scope.borrow_mut();
149
        symtab
150
            .insert(DeclarationPtr::new_value_letting(name.clone(), value))
151
            .ok_or(Error::Parse(format!(
152
                "Could not add {name} to symbol table as it already exists"
153
            )))
154
    } else {
155
        // domain letting
156
        let domain = &arr[1]
157
            .as_object()
158
            .ok_or(error!("Letting[1] is not an object".to_owned()))?["Domain"]
159
            .as_object()
160
            .ok_or(error!("Letting[1].Domain is not an object"))?
161
            .iter()
162
            .next()
163
            .ok_or(error!("Letting[1].Domain is an empty object"))?;
164

            
165
        let mut symtab = scope.borrow_mut();
166
        let domain = parse_domain(domain.0, domain.1, &mut symtab)?;
167

            
168
        symtab
169
            .insert(DeclarationPtr::new_domain_letting(name.clone(), domain))
170
            .ok_or(Error::Parse(format!(
171
                "Could not add {name} to symbol table as it already exists"
172
            )))
173
    }
174
}
175

            
176
fn parse_domain(
177
    domain_name: &str,
178
    domain_value: &JsonValue,
179
    symbols: &mut SymbolTable,
180
) -> Result<DomainPtr> {
181
    match domain_name {
182
        "DomainInt" => Ok(parse_int_domain(domain_value, symbols)?),
183
        "DomainBool" => Ok(Domain::bool()),
184
        "DomainReference" => {
185
            let name = Name::user(
186
                domain_value
187
                    .as_array()
188
                    .ok_or(error!("DomainReference is not an array"))?[0]
189
                    .as_object()
190
                    .ok_or(error!("DomainReference[0] is not an object"))?["Name"]
191
                    .as_str()
192
                    .ok_or(error!("DomainReference[0].Name is not a string"))?,
193
            );
194
            let ptr = symbols
195
                .lookup(&name)
196
                .ok_or(error!(format!("Name {name} not found")))?;
197
            let dom =
198
                Domain::reference(ptr).ok_or(error!("Could not construct reference domain"))?;
199
            Ok(dom)
200
        }
201
        "DomainSet" => {
202
            let dom = domain_value.get(2).and_then(|v| v.as_object());
203
            let domain_obj = dom.expect("domain object exists");
204
            let domain = domain_obj
205
                .iter()
206
                .next()
207
                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
208
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
209
            let size = domain_value
210
                .get(1)
211
                .and_then(|v| v.as_object())
212
                .ok_or(error!("Set size attributes is not an object"))?;
213
            let size = parse_size_attr(size, symbols)?;
214
            let attr: SetAttr<IntVal> = SetAttr { size };
215
            Ok(Domain::set(attr, domain))
216
        }
217

            
218
        "DomainMatrix" => {
219
            let domain_value = domain_value
220
                .as_array()
221
                .ok_or(error!("Domain matrix is not an array"))?;
222

            
223
            let indexed_by_domain = domain_value[0].clone();
224
            let (index_domain_name, index_domain_value) = indexed_by_domain
225
                .as_object()
226
                .ok_or(error!("DomainMatrix[0] is not an object"))?
227
                .iter()
228
                .next()
229
                .ok_or(error!(""))?;
230

            
231
            let (value_domain_name, value_domain_value) = domain_value[1]
232
                .as_object()
233
                .ok_or(error!(""))?
234
                .iter()
235
                .next()
236
                .ok_or(error!(""))?;
237

            
238
            // Conjure stores a 2-d matrix as a matrix of a matrix.
239
            //
240
            // Therefore, the index is always a Domain.
241

            
242
            let mut index_domains: Vec<DomainPtr> = vec![];
243

            
244
            index_domains.push(parse_domain(
245
                index_domain_name,
246
                index_domain_value,
247
                symbols,
248
            )?);
249

            
250
            // We want to store 2-d matrices as a matrix with two index domains, not a matrix in a
251
            // matrix.
252
            //
253
            // Walk through the value domain until it is not a DomainMatrix, adding the index to
254
            // our list of indices.
255
            let mut value_domain = parse_domain(value_domain_name, value_domain_value, symbols)?;
256
            while let Some((new_value_domain, mut indices)) = value_domain.as_matrix() {
257
                index_domains.append(&mut indices);
258
                value_domain = new_value_domain.clone()
259
            }
260

            
261
            Ok(Domain::matrix(value_domain, index_domains))
262
        }
263
        "DomainTuple" => {
264
            let domain_value = domain_value
265
                .as_array()
266
                .ok_or(error!("Domain tuple is not an array"))?;
267

            
268
            //iterate through the array and parse each domain
269
            let domain = domain_value
270
                .iter()
271
                .map(|x| {
272
                    let domain = x
273
                        .as_object()
274
                        .ok_or(error!("DomainTuple[0] is not an object"))?
275
                        .iter()
276
                        .next()
277
                        .ok_or(error!("DomainTuple[0] is an empty object"))?;
278
                    parse_domain(domain.0, domain.1, symbols)
279
                })
280
                .collect::<Result<Vec<DomainPtr>>>()?;
281

            
282
            Ok(Domain::tuple(domain))
283
        }
284
        "DomainRecord" => {
285
            let domain_value = domain_value
286
                .as_array()
287
                .ok_or(error!("Domain Record is not a json array"))?;
288

            
289
            let mut record_entries = vec![];
290

            
291
            for item in domain_value {
292
                //collect the name of the record field
293
                let name = item[0]
294
                    .as_object()
295
                    .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
296
                    .as_str()
297
                    .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
298

            
299
                let name = Name::User(Ustr::from(name));
300
                // then collect the domain of the record field
301
                let domain = item[1]
302
                    .as_object()
303
                    .ok_or(error!("FindOrGiven[2] is not an object"))?
304
                    .iter()
305
                    .next()
306
                    .ok_or(error!("FindOrGiven[2] is an empty object"))?;
307

            
308
                let domain = parse_domain(domain.0, domain.1, symbols)?;
309

            
310
                let rec = RecordEntry { name, domain };
311

            
312
                record_entries.push(rec);
313
            }
314

            
315
            // add record fields to symbol table
316
            record_entries
317
                .iter()
318
                .cloned()
319
                .map(DeclarationPtr::new_record_field)
320
                .for_each(|decl| {
321
                    symbols
322
                        .insert(decl)
323
                        .expect("record field to not already be in the symbol table")
324
                });
325

            
326
            Ok(Domain::record(record_entries))
327
        }
328
        "DomainFunction" => {
329
            let domain = domain_value
330
                .get(2)
331
                .and_then(|v| v.as_object())
332
                .ok_or(error!("Function domain is not an object"))?;
333
            let domain = domain
334
                .iter()
335
                .next()
336
                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
337
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
338

            
339
            let codomain = domain_value
340
                .get(3)
341
                .and_then(|v| v.as_object())
342
                .ok_or(error!("Function codomain is not an object"))?;
343
            let codomain = codomain
344
                .iter()
345
                .next()
346
                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
347
            let codomain = parse_domain(codomain.0.as_str(), codomain.1, symbols)?;
348

            
349
            // Attribute parsing
350
            let attributes = domain_value
351
                .get(1)
352
                .and_then(|v| v.as_array())
353
                .ok_or(error!("Function attributes is not a json array"))?;
354
            let size = attributes
355
                .first()
356
                .and_then(|v| v.as_object())
357
                .ok_or(error!("Function size attributes is not an object"))?;
358
            let size = parse_size_attr(size, symbols)?;
359
            let partiality = attributes
360
                .get(1)
361
                .and_then(|v| v.as_str())
362
                .ok_or(error!("Function partiality is not a string"))?;
363
            let partiality = match partiality {
364
                "PartialityAttr_Partial" => Some(PartialityAttr::Partial),
365
                "PartialityAttr_Total" => Some(PartialityAttr::Total),
366
                _ => None,
367
            };
368
            if partiality.is_none() {
369
                return Err(Error::Parse("Partiality is an unknown type".to_owned()));
370
            }
371
            let partiality = partiality.unwrap();
372
            let jectivity = attributes
373
                .get(2)
374
                .and_then(|v| v.as_str())
375
                .ok_or(error!("Function jectivity is not a string"))?;
376
            let jectivity = match jectivity {
377
                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
378
                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
379
                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
380
                "JectivityAttr_None" => Some(JectivityAttr::None),
381
                _ => None,
382
            };
383
            if jectivity.is_none() {
384
                return Err(Error::Parse("Jectivity is an unknown type".to_owned()));
385
            }
386
            let jectivity = jectivity.unwrap();
387

            
388
            let attr: FuncAttr<IntVal> = FuncAttr {
389
                size,
390
                partiality,
391
                jectivity,
392
            };
393

            
394
            Ok(Domain::function(attr, domain, codomain))
395
        }
396
        _ => Err(Error::Parse(
397
            "FindOrGiven[2] is an unknown object".to_owned(), // consider covered
398
        )),
399
    }
400
}
401

            
402
fn parse_size_attr(
403
    attr_map: &JsonMap<String, JsonValue>,
404
    symbols: &mut SymbolTable,
405
) -> Result<Range<IntVal>> {
406
    let attr_obj = attr_map
407
        .iter()
408
        .next()
409
        .ok_or(Error::Parse("SizeAttr is an empty object".to_owned()))?;
410
    match attr_obj.0.as_str() {
411
        "SizeAttr_None" => Ok(Range::Unbounded),
412
        "SizeAttr_MinSize" => {
413
            let size_int = parse_domain_value_int(attr_obj.1, symbols)
414
                .ok_or(error!("Could not parse int domain constant"))?;
415
            Ok(Range::UnboundedR(size_int.into()))
416
        }
417
        "SizeAttr_MaxSize" => {
418
            let size_int = parse_domain_value_int(attr_obj.1, symbols)
419
                .ok_or(error!("Could not parse int domain constant"))?;
420
            Ok(Range::UnboundedL(size_int.into()))
421
        }
422
        "SizeAttr_MinMaxSize" => {
423
            let min_max = attr_obj
424
                .1
425
                .as_array()
426
                .ok_or(error!("SizeAttr MinMaxSize is not a json array"))?;
427
            let min = min_max
428
                .first()
429
                .ok_or(error!("SizeAttr Min is not present"))?;
430
            let min_int = parse_domain_value_int(min, symbols)
431
                .ok_or(error!("Could not parse int domain constant"))?;
432
            let max = min_max
433
                .get(1)
434
                .ok_or(error!("SizeAttr Max is not present"))?;
435
            let max_int = parse_domain_value_int(max, symbols)
436
                .ok_or(error!("Could not parse int domain constant"))?;
437
            Ok(Range::Bounded(min_int.into(), max_int.into()))
438
        }
439
        "SizeAttr_Size" => {
440
            let size_int = parse_domain_value_int(attr_obj.1, symbols)
441
                .ok_or(error!("Could not parse int domain constant"))?;
442
            Ok(Range::Single(size_int.into()))
443
        }
444
        _ => Err(Error::Parse("SizeAttr is an unknown type".to_owned())),
445
    }
446
}
447

            
448
fn parse_int_domain(v: &JsonValue, symbols: &SymbolTable) -> Result<DomainPtr> {
449
    let mut ranges = Vec::new();
450
    let arr = v
451
        .as_array()
452
        .ok_or(error!("DomainInt is not an array".to_owned()))?[1]
453
        .as_array()
454
        .ok_or(error!("DomainInt[1] is not an array".to_owned()))?;
455
    for range in arr {
456
        let range = range
457
            .as_object()
458
            .ok_or(error!("DomainInt[1] contains a non-object"))?
459
            .iter()
460
            .next()
461
            .ok_or(error!("DomainInt[1] contains an empty object"))?;
462
        match range.0.as_str() {
463
            "RangeBounded" => {
464
                let arr = range
465
                    .1
466
                    .as_array()
467
                    .ok_or(error!("RangeBounded is not an array".to_owned()))?;
468
                let mut nums = Vec::new();
469
                for item in arr.iter() {
470
                    let num = parse_domain_value_int(item, symbols)
471
                        .ok_or(error!("Could not parse int domain constant"))?;
472
                    nums.push(num);
473
                }
474
                ranges.push(Range::Bounded(nums[0], nums[1]));
475
            }
476
            "RangeSingle" => {
477
                let num = parse_domain_value_int(range.1, symbols)
478
                    .ok_or(error!("Could not parse int domain constant"))?;
479
                ranges.push(Range::Single(num));
480
            }
481
            _ => return throw_error!("DomainInt[1] contains an unknown object"),
482
        }
483
    }
484
    Ok(Domain::int(ranges))
485
}
486

            
487
/// Parses a (possibly) integer value inside the range of a domain
488
///
489
/// 1. (positive number) Constant/ConstantInt/1
490
///
491
/// 2. (negative number) Op/MkOpNegate/Constant/ConstantInt/1
492
///
493
/// Unlike `parse_constant` this handles the negation operator. `parse_constant` expects the
494
/// negation to already have been handled as an expression; however, here we do not expect domain
495
/// values to be part of larger expressions, only negated.
496
///
497
fn parse_domain_value_int(obj: &JsonValue, symbols: &SymbolTable) -> Option<i32> {
498
    parser_trace!("trying to parse domain value: {}", obj);
499

            
500
    fn try_parse_positive_int(obj: &JsonValue) -> Option<i32> {
501
        parser_trace!(".. trying as a positive domain value: {}", obj);
502
        // Positive number: Constant/ConstantInt/1
503

            
504
        let leaf_node = obj
505
            .pointer("/Constant/ConstantInt/1")
506
            .or_else(|| obj.pointer("/ConstantInt/1"))?;
507

            
508
        match leaf_node.as_i64()?.try_into() {
509
            Ok(x) => {
510
                parser_trace!(".. success!");
511
                Some(x)
512
            }
513
            Err(_) => {
514
                println!("Could not convert integer constant to i32: {leaf_node:#?}");
515
                None
516
            }
517
        }
518
    }
519

            
520
    fn try_parse_negative_int(obj: &JsonValue) -> Option<i32> {
521
        // Negative number: Op/MkOpNegate/Constant/ConstantInt/1
522

            
523
        // Unwrap negation operator, giving us a Constant/ConstantInt/1
524
        //
525
        // This is just a positive constant, so try to parse it as such
526

            
527
        parser_trace!(".. trying as a negative domain value: {}", obj);
528
        let inner_constant_node = obj.pointer("/Op/MkOpNegate")?;
529
        let inner_num = try_parse_positive_int(inner_constant_node)?;
530

            
531
        parser_trace!(".. success!");
532
        Some(-inner_num)
533
    }
534

            
535
    // it will be too annoying to store references inside all our int domain ranges, so just
536
    // resolve them here.
537
    //
538
    // this matches savilerow, where lettings must be declared before they are used.
539
    //
540
    // TODO: we shouldn't do this long term, add support for ranges containing domain references.
541
    fn try_parse_reference(obj: &JsonValue, symbols: &SymbolTable) -> Option<i32> {
542
        parser_trace!(".. trying as a domain reference: {}", obj);
543
        let inner_name = obj.pointer("/Reference/0/Name")?.as_str()?;
544
        parser_trace!(
545
            ".. found domain reference to {}, trying to resolve it",
546
            inner_name
547
        );
548
        let name = Name::User(Ustr::from(inner_name));
549
        let decl = symbols.lookup(&name)?;
550
        let DeclarationKind::ValueLetting(d) = &decl.kind() as &DeclarationKind else {
551
            parser_trace!(".. name exists but is not a value letting!");
552
            return None;
553
        };
554

            
555
        let a = d.clone().into_literal()?;
556
        let Literal::Int(a) = a else {
557
            return None;
558
        };
559

            
560
        Some(a)
561
    }
562

            
563
    try_parse_positive_int(obj)
564
        .or_else(|| try_parse_negative_int(obj))
565
        .or_else(|| try_parse_reference(obj, symbols))
566
}
567

            
568
// this needs an explicit type signature to force the closures to have the same type
569
type BinOp = Box<dyn Fn(Metadata, Moo<Expression>, Moo<Expression>) -> Expression>;
570
type UnaryOp = Box<dyn Fn(Metadata, Moo<Expression>) -> Expression>;
571

            
572
pub fn parse_expression(obj: &JsonValue, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
573
    let binary_operators: HashMap<&str, BinOp> = [
574
        (
575
            "MkOpIn",
576
            Box::new(Expression::In) as Box<dyn Fn(_, _, _) -> _>,
577
        ),
578
        (
579
            "MkOpUnion",
580
            Box::new(Expression::Union) as Box<dyn Fn(_, _, _) -> _>,
581
        ),
582
        (
583
            "MkOpIntersect",
584
            Box::new(Expression::Intersect) as Box<dyn Fn(_, _, _) -> _>,
585
        ),
586
        (
587
            "MkOpSupset",
588
            Box::new(Expression::Supset) as Box<dyn Fn(_, _, _) -> _>,
589
        ),
590
        (
591
            "MkOpSupsetEq",
592
            Box::new(Expression::SupsetEq) as Box<dyn Fn(_, _, _) -> _>,
593
        ),
594
        (
595
            "MkOpSubset",
596
            Box::new(Expression::Subset) as Box<dyn Fn(_, _, _) -> _>,
597
        ),
598
        (
599
            "MkOpSubsetEq",
600
            Box::new(Expression::SubsetEq) as Box<dyn Fn(_, _, _) -> _>,
601
        ),
602
        (
603
            "MkOpEq",
604
            Box::new(Expression::Eq) as Box<dyn Fn(_, _, _) -> _>,
605
        ),
606
        (
607
            "MkOpNeq",
608
            Box::new(Expression::Neq) as Box<dyn Fn(_, _, _) -> _>,
609
        ),
610
        (
611
            "MkOpGeq",
612
            Box::new(Expression::Geq) as Box<dyn Fn(_, _, _) -> _>,
613
        ),
614
        (
615
            "MkOpLeq",
616
            Box::new(Expression::Leq) as Box<dyn Fn(_, _, _) -> _>,
617
        ),
618
        (
619
            "MkOpGt",
620
            Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
621
        ),
622
        (
623
            "MkOpLt",
624
            Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
625
        ),
626
        (
627
            "MkOpGt",
628
            Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
629
        ),
630
        (
631
            "MkOpLt",
632
            Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
633
        ),
634
        (
635
            "MkOpLexLt",
636
            Box::new(Expression::LexLt) as Box<dyn Fn(_, _, _) -> _>,
637
        ),
638
        (
639
            "MkOpLexGt",
640
            Box::new(Expression::LexGt) as Box<dyn Fn(_, _, _) -> _>,
641
        ),
642
        (
643
            "MkOpLexLeq",
644
            Box::new(Expression::LexLeq) as Box<dyn Fn(_, _, _) -> _>,
645
        ),
646
        (
647
            "MkOpLexGeq",
648
            Box::new(Expression::LexGeq) as Box<dyn Fn(_, _, _) -> _>,
649
        ),
650
        (
651
            "MkOpDiv",
652
            Box::new(Expression::UnsafeDiv) as Box<dyn Fn(_, _, _) -> _>,
653
        ),
654
        (
655
            "MkOpMod",
656
            Box::new(Expression::UnsafeMod) as Box<dyn Fn(_, _, _) -> _>,
657
        ),
658
        (
659
            "MkOpMinus",
660
            Box::new(Expression::Minus) as Box<dyn Fn(_, _, _) -> _>,
661
        ),
662
        (
663
            "MkOpImply",
664
            Box::new(Expression::Imply) as Box<dyn Fn(_, _, _) -> _>,
665
        ),
666
        (
667
            "MkOpIff",
668
            Box::new(Expression::Iff) as Box<dyn Fn(_, _, _) -> _>,
669
        ),
670
        (
671
            "MkOpPow",
672
            Box::new(Expression::UnsafePow) as Box<dyn Fn(_, _, _) -> _>,
673
        ),
674
        (
675
            "MkOpImage",
676
            Box::new(Expression::Image) as Box<dyn Fn(_, _, _) -> _>,
677
        ),
678
        (
679
            "MkOpImageSet",
680
            Box::new(Expression::ImageSet) as Box<dyn Fn(_, _, _) -> _>,
681
        ),
682
        (
683
            "MkOpPreImage",
684
            Box::new(Expression::PreImage) as Box<dyn Fn(_, _, _) -> _>,
685
        ),
686
        (
687
            "MkOpInverse",
688
            Box::new(Expression::Inverse) as Box<dyn Fn(_, _, _) -> _>,
689
        ),
690
        (
691
            "MkOpRestrict",
692
            Box::new(Expression::Restrict) as Box<dyn Fn(_, _, _) -> _>,
693
        ),
694
    ]
695
    .into_iter()
696
    .collect();
697

            
698
    let unary_operators: HashMap<&str, UnaryOp> = [
699
        (
700
            "MkOpNot",
701
            Box::new(Expression::Not) as Box<dyn Fn(_, _) -> _>,
702
        ),
703
        (
704
            "MkOpNegate",
705
            Box::new(Expression::Neg) as Box<dyn Fn(_, _) -> _>,
706
        ),
707
        (
708
            "MkOpTwoBars",
709
            Box::new(Expression::Abs) as Box<dyn Fn(_, _) -> _>,
710
        ),
711
        (
712
            "MkOpAnd",
713
            Box::new(Expression::And) as Box<dyn Fn(_, _) -> _>,
714
        ),
715
        (
716
            "MkOpSum",
717
            Box::new(Expression::Sum) as Box<dyn Fn(_, _) -> _>,
718
        ),
719
        (
720
            "MkOpProduct",
721
            Box::new(Expression::Product) as Box<dyn Fn(_, _) -> _>,
722
        ),
723
        ("MkOpOr", Box::new(Expression::Or) as Box<dyn Fn(_, _) -> _>),
724
        (
725
            "MkOpMin",
726
            Box::new(Expression::Min) as Box<dyn Fn(_, _) -> _>,
727
        ),
728
        (
729
            "MkOpMax",
730
            Box::new(Expression::Max) as Box<dyn Fn(_, _) -> _>,
731
        ),
732
        (
733
            "MkOpAllDiff",
734
            Box::new(Expression::AllDiff) as Box<dyn Fn(_, _) -> _>,
735
        ),
736
        (
737
            "MkOpToInt",
738
            Box::new(Expression::ToInt) as Box<dyn Fn(_, _) -> _>,
739
        ),
740
        (
741
            "MkOpDefined",
742
            Box::new(Expression::Defined) as Box<dyn Fn(_, _) -> _>,
743
        ),
744
        (
745
            "MkOpRange",
746
            Box::new(Expression::Range) as Box<dyn Fn(_, _) -> _>,
747
        ),
748
    ]
749
    .into_iter()
750
    .collect();
751

            
752
    let mut binary_operator_names = binary_operators.iter().map(|x| x.0);
753
    let mut unary_operator_names = unary_operators.iter().map(|x| x.0);
754
    #[allow(clippy::unwrap_used)]
755
    match obj {
756
        Value::Object(op) if op.contains_key("Op") => match &op["Op"] {
757
            Value::Object(bin_op) if binary_operator_names.any(|key| bin_op.contains_key(*key)) => {
758
                Some(parse_bin_op(bin_op, binary_operators, scope).unwrap())
759
            }
760
            Value::Object(un_op) if unary_operator_names.any(|key| un_op.contains_key(*key)) => {
761
                Some(parse_unary_op(un_op, unary_operators, scope).unwrap())
762
            }
763
            Value::Object(op) if op.contains_key("MkOpFlatten") => parse_flatten_op(op, scope),
764
            Value::Object(op)
765
                if op.contains_key("MkOpIndexing") || op.contains_key("MkOpSlicing") =>
766
            {
767
                parse_indexing_slicing_op(op, scope)
768
            }
769
            otherwise => bug!("Unhandled Op {:#?}", otherwise),
770
        },
771
        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
772
            Some(parse_comprehension(comprehension, Rc::clone(scope), None).unwrap())
773
        }
774
        Value::Object(refe) if refe.contains_key("Reference") => {
775
            let name = refe["Reference"].as_array()?[0].as_object()?["Name"].as_str()?;
776
            let user_name = Name::User(Ustr::from(name));
777

            
778
            let declaration: DeclarationPtr = scope
779
                .borrow()
780
                .lookup(&user_name)
781
                .or_else(|| bug!("Could not find reference {user_name}"))?;
782

            
783
            Some(Expression::Atomic(
784
                Metadata::new(),
785
                Atom::Reference(crate::ast::Reference::new(declaration)),
786
            ))
787
        }
788
        Value::Object(abslit) if abslit.contains_key("AbstractLiteral") => {
789
            if abslit["AbstractLiteral"]
790
                .as_object()?
791
                .contains_key("AbsLitSet")
792
            {
793
                Some(parse_abs_lit(&abslit["AbstractLiteral"]["AbsLitSet"], scope).unwrap())
794
            } else if abslit["AbstractLiteral"]
795
                .as_object()?
796
                .contains_key("AbsLitFunction")
797
            {
798
                Some(
799
                    parse_abs_function(&abslit["AbstractLiteral"]["AbsLitFunction"], scope)
800
                        .unwrap(),
801
                )
802
            } else {
803
                Some(parse_abstract_matrix_as_expr(obj, scope).unwrap())
804
            }
805
        }
806

            
807
        Value::Object(constant) if constant.contains_key("Constant") => Some(
808
            parse_constant(constant, scope)
809
                .or_else(|| parse_abstract_matrix_as_expr(obj, scope))
810
                .unwrap(),
811
        ),
812

            
813
        Value::Object(constant) if constant.contains_key("ConstantAbstract") => {
814
            Some(parse_abstract_matrix_as_expr(obj, scope).unwrap())
815
        }
816

            
817
        Value::Object(constant) if constant.contains_key("ConstantInt") => {
818
            Some(parse_constant(constant, scope).unwrap())
819
        }
820
        Value::Object(constant) if constant.contains_key("ConstantBool") => {
821
            Some(parse_constant(constant, scope).unwrap())
822
        }
823

            
824
        _ => None,
825
    }
826
}
827

            
828
fn parse_abs_lit(abs_set: &Value, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
829
    let values = abs_set.as_array()?; // Ensure it's an array
830
    let expressions = values
831
        .iter()
832
        .map(|values| parse_expression(values, scope))
833
        .map(|values| values.expect("invalid subexpression")) // Ensure valid expressions
834
        .collect::<Vec<Expression>>(); // Collect all expressions
835

            
836
    Some(Expression::AbstractLiteral(
837
        Metadata::new(),
838
        AbstractLiteral::Set(expressions),
839
    ))
840
}
841

            
842
fn parse_abs_tuple(abs_tuple: &Value, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
843
    let values = abs_tuple.as_array()?; // Ensure it's an array
844
    let expressions = values
845
        .iter()
846
        .map(|values| parse_expression(values, scope))
847
        .map(|values| values.expect("invalid subexpression")) // Ensure valid expressions
848
        .collect::<Vec<Expression>>(); // Collect all expressions
849

            
850
    Some(Expression::AbstractLiteral(
851
        Metadata::new(),
852
        AbstractLiteral::Tuple(expressions),
853
    ))
854
}
855

            
856
//parses an abstract record as an expression
857
fn parse_abs_record(abs_record: &Value, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
858
    let entries = abs_record.as_array()?; // Ensure it's an array
859
    let mut rec = vec![];
860

            
861
    for entry in entries {
862
        let entry = entry.as_array()?;
863
        let name = entry[0].as_object()?["Name"].as_str()?;
864

            
865
        let value = parse_expression(&entry[1], scope)?;
866

            
867
        let name = Name::User(Ustr::from(name));
868
        let rec_entry = RecordValue {
869
            name: name.clone(),
870
            value,
871
        };
872
        rec.push(rec_entry);
873
    }
874

            
875
    Some(Expression::AbstractLiteral(
876
        Metadata::new(),
877
        AbstractLiteral::Record(rec),
878
    ))
879
}
880

            
881
//parses an abstract function as an expression
882
fn parse_abs_function(
883
    abs_function: &Value,
884
    scope: &Rc<RefCell<SymbolTable>>,
885
) -> Option<Expression> {
886
    let entries = abs_function.as_array()?;
887
    let mut assignments = vec![];
888

            
889
    for entry in entries {
890
        //expect("Explicit function assignment is not an array");
891
        let entry = entry.as_array()?;
892
        let expression = entry
893
            .iter()
894
            .map(|values| parse_expression(values, scope))
895
            .map(|values| values.expect("invalid subexpression")) // Ensure valid expressions
896
            .collect::<Vec<Expression>>(); // Collect all expressions
897
        let domain_value = expression.first().expect("Invalid function domain");
898
        let codomain_value = expression.get(1).expect("Invalid function codomain");
899
        let tuple = (domain_value.clone(), codomain_value.clone());
900
        assignments.push(tuple);
901
    }
902
    Some(Expression::AbstractLiteral(
903
        Metadata::new(),
904
        AbstractLiteral::Function(assignments),
905
    ))
906
}
907

            
908
fn parse_comprehension(
909
    comprehension: &serde_json::Map<String, Value>,
910
    scope: Rc<RefCell<SymbolTable>>,
911
    comprehension_kind: Option<ACOperatorKind>,
912
) -> Option<Expression> {
913
    let value = &comprehension["Comprehension"];
914
    let mut comprehension = ComprehensionBuilder::new(Rc::clone(&scope));
915
    let generator_symboltable = comprehension.generator_symboltable();
916
    let return_expr_symboltable = comprehension.return_expr_symboltable();
917

            
918
    let generators_and_guards = value.pointer("/1")?.as_array()?.iter();
919

            
920
    for value in generators_and_guards {
921
        let value = value.as_object()?;
922
        let (name, value) = value.iter().next()?;
923
        comprehension = match name.as_str() {
924
            "Generator" => {
925
                // TODO: more things than GenDomainNoRepr and Single names here?
926
                let name = value.pointer("/GenDomainNoRepr/0/Single/Name")?.as_str()?;
927
                let (domain_name, domain_value) = value
928
                    .pointer("/GenDomainNoRepr/1")?
929
                    .as_object()?
930
                    .iter()
931
                    .next()?;
932
                let domain = parse_domain(
933
                    domain_name,
934
                    domain_value,
935
                    &mut generator_symboltable.borrow_mut(),
936
                )
937
                .ok()?;
938
                comprehension.generator(DeclarationPtr::new_var(
939
                    Name::User(Ustr::from(name)),
940
                    domain,
941
                ))
942
            }
943

            
944
            "Condition" => comprehension.guard(parse_expression(value, &generator_symboltable)?),
945

            
946
            x => {
947
                bug!("unknown field inside comprehension {x}");
948
            }
949
        }
950
    }
951

            
952
    let expr = parse_expression(value.pointer("/0")?, &return_expr_symboltable)?;
953

            
954
    Some(Expression::Comprehension(
955
        Metadata::new(),
956
        Moo::new(comprehension.with_return_value(expr, comprehension_kind)),
957
    ))
958
}
959

            
960
fn parse_bin_op(
961
    bin_op: &serde_json::Map<String, Value>,
962
    binary_operators: HashMap<&str, BinOp>,
963
    scope: &Rc<RefCell<SymbolTable>>,
964
) -> Option<Expression> {
965
    // we know there is a single key value pair in this object
966
    // extract the value, ignore the key
967
    let (key, value) = bin_op.into_iter().next()?;
968

            
969
    let constructor = binary_operators.get(key.as_str())?;
970

            
971
    match &value {
972
        Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
973
            let arg1 = parse_expression(&bin_op_args[0], scope)?;
974
            let arg2 = parse_expression(&bin_op_args[1], scope)?;
975
            Some(constructor(Metadata::new(), Moo::new(arg1), Moo::new(arg2)))
976
        }
977
        otherwise => bug!("Unhandled parse_bin_op {:#?}", otherwise),
978
    }
979
}
980

            
981
fn parse_indexing_slicing_op(
982
    op: &serde_json::Map<String, Value>,
983
    scope: &Rc<RefCell<SymbolTable>>,
984
) -> Option<Expression> {
985
    // we know there is a single key value pair in this object
986
    // extract the value, ignore the key
987
    let (key, value) = op.into_iter().next()?;
988

            
989
    // we know that this is meant to be a mkopindexing, so anything that goes wrong from here is a
990
    // bug!
991

            
992
    // Conjure does a[1,2,3] as MkOpIndexing(MkOpIndexing(MkOpIndexing(a,3),2),1).
993
    //
994
    // And  a[1,..,3] as MkOpIndexing(MkOpSlicing(MkOpIndexing(a,3)),1).
995
    //
996
    // However, we want this in a flattened form: Index(a, [1,2,3])
997
    let mut target: Expression;
998
    let mut indices: Vec<Option<Expression>> = vec![];
999

            
    // true if this has no slicing, false otherwise.
    let mut all_known = true;
    match key.as_str() {
        "MkOpIndexing" => {
            match &value {
                Value::Array(op_args) if op_args.len() == 2 => {
                    target = parse_expression(&op_args[0], scope).expect("expected an expression");
                    indices.push(Some(
                        parse_expression(&op_args[1], scope).expect("expected an expression"),
                    ));
                }
                otherwise => bug!("Unknown object inside MkOpIndexing: {:#?}", otherwise),
            };
        }
        "MkOpSlicing" => {
            all_known = false;
            match &value {
                Value::Array(op_args) if op_args.len() == 3 => {
                    target = parse_expression(&op_args[0], scope).expect("expected an expression");
                    indices.push(None);
                }
                otherwise => bug!("Unknown object inside MkOpSlicing: {:#?}", otherwise),
            };
        }
        _ => {
            return None;
        }
    }
    loop {
        match &mut target {
            Expression::UnsafeIndex(_, new_target, new_indices) => {
                indices.extend(new_indices.iter().cloned().rev().map(Some));
                target = Moo::unwrap_or_clone(new_target.clone());
            }
            Expression::UnsafeSlice(_, new_target, new_indices) => {
                all_known = false;
                indices.extend(new_indices.iter().cloned().rev());
                target = Moo::unwrap_or_clone(new_target.clone());
            }
            _ => {
                // not a slice or an index, we have reached the target.
                break;
            }
        }
    }
    indices.reverse();
    if all_known {
        Some(Expression::UnsafeIndex(
            Metadata::new(),
            Moo::new(target),
            indices.into_iter().map(|x| x.unwrap()).collect(),
        ))
    } else {
        Some(Expression::UnsafeSlice(
            Metadata::new(),
            Moo::new(target),
            indices,
        ))
    }
}
fn parse_flatten_op(
    op: &serde_json::Map<String, Value>,
    scope: &Rc<RefCell<SymbolTable>>,
) -> Option<Expression> {
    let args = op.get("MkOpFlatten")?.as_array()?;
    let n = parse_expression(&args[0], scope);
    let matrix = parse_expression(&args[1], scope)?;
    if let Some(n) = n {
        Some(Expression::Flatten(
            Metadata::new(),
            Some(Moo::new(n)),
            Moo::new(matrix),
        ))
    } else {
        Some(Expression::Flatten(Metadata::new(), None, Moo::new(matrix)))
    }
}
fn parse_unary_op(
    un_op: &serde_json::Map<String, Value>,
    unary_operators: HashMap<&str, UnaryOp>,
    scope: &Rc<RefCell<SymbolTable>>,
) -> Option<Expression> {
    let (key, value) = un_op.into_iter().next()?;
    let constructor = unary_operators.get(key.as_str())?;
    // unops are the main things that contain comprehensions
    //
    // if the current expr is a quantifier like and/or/sum and it contains a comprehension, let the comprehension know what it is inside.
    let arg = match value {
        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
            let comprehension_kind = match key.as_str() {
                "MkOpOr" => Some(ACOperatorKind::Or),
                "MkOpAnd" => Some(ACOperatorKind::And),
                "MkOpSum" => Some(ACOperatorKind::Sum),
                "MkOpProduct" => Some(ACOperatorKind::Product),
                _ => None,
            };
            Some(parse_comprehension(comprehension, Rc::clone(scope), comprehension_kind).unwrap())
        }
        _ => parse_expression(value, scope),
    }?;
    Some(constructor(Metadata::new(), Moo::new(arg)))
}
// Takes in { AbstractLiteral: .... }
fn parse_abstract_matrix_as_expr(
    value: &serde_json::Value,
    scope: &Rc<RefCell<SymbolTable>>,
) -> Option<Expression> {
    parser_trace!("trying to parse an abstract literal matrix");
    let (values, domain_name, domain_value) =
        if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix") {
            parser_trace!(".. found JSON pointer /AbstractLiteral/AbstractLitMatrix");
            let (domain_name, domain_value) =
                abs_lit_matrix.pointer("/0")?.as_object()?.iter().next()?;
            let values = abs_lit_matrix.pointer("/1")?;
            Some((values, domain_name, domain_value))
        }
        // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
        else if let Some(const_abs_lit_matrix) =
            value.pointer("/Constant/ConstantAbstract/AbsLitMatrix")
        {
            parser_trace!(".. found JSON pointer /Constant/ConstantAbstract/AbsLitMatrix");
            let (domain_name, domain_value) = const_abs_lit_matrix
                .pointer("/0")?
                .as_object()?
                .iter()
                .next()?;
            let values = const_abs_lit_matrix.pointer("/1")?;
            Some((values, domain_name, domain_value))
        } else if let Some(const_abs_lit_matrix) = value.pointer("/ConstantAbstract/AbsLitMatrix") {
            parser_trace!(".. found JSON pointer /ConstantAbstract/AbsLitMatrix");
            let (domain_name, domain_value) = const_abs_lit_matrix
                .pointer("/0")?
                .as_object()?
                .iter()
                .next()?;
            let values = const_abs_lit_matrix.pointer("/1")?;
            Some((values, domain_name, domain_value))
        } else {
            None
        }?;
    parser_trace!(".. found in domain and values in JSON:");
    parser_trace!(".. .. index domain name {domain_name}");
    parser_trace!(".. .. values {value}");
    let args_parsed = values.as_array().map(|x| {
        x.iter()
            .map(|x| parse_expression(x, scope))
            .map(|x| x.expect("invalid subexpression"))
            .collect::<Vec<Expression>>()
    })?;
    if !args_parsed.is_empty() {
        parser_trace!(
            ".. successfully parsed values as expressions: {}, ... ",
            args_parsed[0]
        );
    } else {
        parser_trace!(".. successfully parsed empty values ",);
    }
    let mut symbols = scope.borrow_mut();
    match parse_domain(domain_name, domain_value, &mut symbols) {
        Ok(domain) => {
            parser_trace!("... sucessfully parsed domain as {domain}");
            Some(into_matrix_expr![args_parsed;domain])
        }
        Err(_) => {
            parser_trace!("... failed to parse domain, creating a matrix without one.");
            Some(into_matrix_expr![args_parsed])
        }
    }
}
fn parse_constant(
    constant: &serde_json::Map<String, Value>,
    scope: &Rc<RefCell<SymbolTable>>,
) -> Option<Expression> {
    match &constant.get("Constant") {
        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
            let int_32: i32 = match int["ConstantInt"].as_array()?[1].as_i64()?.try_into() {
                Ok(x) => x,
                Err(_) => {
                    println!(
                        "Could not convert integer constant to i32: {:#?}",
                        int["ConstantInt"]
                    );
                    return None;
                }
            };
            Some(Expression::Atomic(
                Metadata::new(),
                Atom::Literal(Literal::Int(int_32)),
            ))
        }
        Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
            let b: bool = b["ConstantBool"].as_bool()?;
            Some(Expression::Atomic(
                Metadata::new(),
                Atom::Literal(Literal::Bool(b)),
            ))
        }
        Some(Value::Object(int)) if int.contains_key("ConstantAbstract") => {
            if let Some(Value::Object(obj)) = int.get("ConstantAbstract") {
                if let Some(arr) = obj.get("AbsLitSet") {
                    return parse_abs_lit(arr, scope);
                } else if let Some(arr) = obj.get("AbsLitMatrix") {
                    return parse_abstract_matrix_as_expr(arr, scope);
                } else if let Some(arr) = obj.get("AbsLitTuple") {
                    return parse_abs_tuple(arr, scope);
                } else if let Some(arr) = obj.get("AbsLitRecord") {
                    return parse_abs_record(arr, scope);
                } else if let Some(arr) = obj.get("AbsLitFunction") {
                    return parse_abs_function(arr, scope);
                }
            }
            None
        }
        // sometimes (e.g. constant matrices) we can have a ConstantInt / Constant bool that is
        // not wrapped in Constant
        None => {
            let int_expr = constant
                .get("ConstantInt")
                .and_then(|x| x.as_array())
                .and_then(|x| x[1].as_i64())
                .and_then(|x| x.try_into().ok())
                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
            if let e @ Some(_) = int_expr {
                return e;
            }
            let bool_expr = constant
                .get("ConstantBool")
                .and_then(|x| x.as_bool())
                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
            if let e @ Some(_) = bool_expr {
                return e;
            }
            bug!("Unhandled parse_constant {:#?}", constant);
        }
        otherwise => bug!("Unhandled parse_constant {:#?}", otherwise),
    }
}