1
#![allow(clippy::unwrap_used)]
2
#![allow(clippy::expect_used)]
3
use std::sync::{Arc, RwLock};
4
use ustr::Ustr;
5

            
6
use serde_json::Map as JsonMap;
7
use serde_json::Value;
8
use serde_json::Value as JsonValue;
9

            
10
use crate::ast::EnumVariantVal;
11
use crate::ast::Moo;
12
use crate::ast::PartitionAttr;
13
use crate::ast::PermutationAttr;
14
use crate::ast::Reference;
15
use crate::ast::Typeable;
16
use crate::ast::ac_operators::ACOperatorKind;
17
use crate::ast::comprehension::ComprehensionBuilder;
18
use crate::ast::enumerated::{EnumVariant, EnumeratedType};
19
use crate::ast::records::Field;
20
use crate::ast::{
21
    AbstractLiteral, Atom, BinaryAttr, DeclarationPtr, Domain, Expression, FuncAttr, IntVal,
22
    JectivityAttr, Literal, MSetAttr, Name, PartialityAttr, Range, RelAttr, ReturnType,
23
    SequenceAttr, SetAttr, SymbolTable, SymbolTablePtr,
24
};
25
use crate::ast::{DomainPtr, Metadata};
26
use crate::context::Context;
27
use crate::error::{Error, Result};
28
use crate::{Model, bug, error, into_matrix_expr, throw_error};
29

            
30
#[allow(unused_macros)]
31
macro_rules! parser_trace {
32
    ($($arg:tt)+) => {
33
        log::trace!(target:"jsonparser",$($arg)+)
34
    };
35
}
36

            
37
#[allow(unused_macros)]
38
macro_rules! parser_debug {
39
    ($($arg:tt)+) => {
40
        log::debug!(target:"jsonparser",$($arg)+)
41
    };
42
}
43

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

            
51
5266
    for statement in statements {
52
10422
        let entry = statement
53
10422
            .as_object()
54
10422
            .ok_or(error!("mStatements contains a non-object"))?
55
            .iter()
56
            .next()
57
10422
            .ok_or(error!("mStatements contains an empty object"))?;
58

            
59
10422
        match entry.0.as_str() {
60
            "Declaration" => {
61
8028
                let decl = entry
62
8028
                    .1
63
8028
                    .as_object()
64
8028
                    .ok_or(error!("Declaration is not an object".to_owned()))?;
65

            
66
                // One field in the declaration should tell us what kind it is.
67
                //
68
                // Find it, ignoring the other fields.
69
                //
70
                // e.g. FindOrGiven,
71

            
72
8028
                let mut valid_decl: bool = false;
73
8028
                let scope = m.symbols_ptr_unchecked().clone();
74
8028
                let model = &mut m;
75
8028
                for (kind, value) in decl {
76
8028
                    match kind.as_str() {
77
                        "FindOrGiven" => {
78
6240
                            parse_variable(value, &mut model.symbols_mut())?;
79
6182
                            valid_decl = true;
80
6182
                            break;
81
                        }
82
                        "Letting" => {
83
1788
                            parse_letting(value, &scope)?;
84
1759
                            valid_decl = true;
85
1759
                            break;
86
                        }
87
                        "LettingDomainDefnEnum" => {
88
                            parse_enum_declaration(value, &scope)?;
89
                            valid_decl = true;
90
                            break;
91
                        }
92
                        "LettingDomainDefnUnnamed" => {
93
                            parse_unnamed_type(value, &scope)?;
94
                            valid_decl = true;
95
                            break;
96
                        }
97
                        _ => continue,
98
                    }
99
                }
100

            
101
7941
                if !valid_decl {
102
                    throw_error!("Declaration is not a valid kind")?;
103
7941
                }
104
            }
105
            "SuchThat" => {
106
2394
                let constraints_arr = match entry.1.as_array() {
107
2394
                    Some(x) => x,
108
                    None => bug!("SuchThat is not a vector"),
109
                };
110

            
111
2394
                let constraints: Vec<Expression> = constraints_arr
112
2394
                    .iter()
113
2782
                    .map(|x| parse_expression(x, m.symbols_ptr_unchecked()))
114
                    .collect::<Result<Vec<_>>>()?;
115
2394
                m.add_constraints(constraints);
116
            }
117
            otherwise => bug!("Unhandled Statement {:#?}", otherwise),
118
        }
119
    }
120
5179
    Ok(m)
121
5266
}
122

            
123
fn parse_unnamed_type(_value: &Value, _scope: &SymbolTablePtr) -> Result<()> {
124
    todo!()
125
}
126

            
127
6240
fn parse_variable(v: &JsonValue, symtab: &mut SymbolTable) -> Result<()> {
128
6240
    let arr = v.as_array().ok_or(error!("FindOrGiven is not an array"))?;
129

            
130
6240
    let variable_type = arr[0]
131
6240
        .as_str()
132
6240
        .ok_or(error!("FindOrGiven[0] is not a string"))?;
133

            
134
6240
    let name = parse_name(&arr[1])?;
135

            
136
6240
    let domain = arr[2]
137
6240
        .as_object()
138
6240
        .ok_or(error!("FindOrGiven[2] is not an object"))?
139
        .iter()
140
        .next()
141
6240
        .ok_or(error!("FindOrGiven[2] is an empty object"))?;
142

            
143
6240
    let domain = parse_domain(domain.0, domain.1, symtab)?;
144

            
145
6182
    let decl = match variable_type {
146
5908
        "Find" => DeclarationPtr::new_find(name.clone(), domain),
147
274
        "Given" => DeclarationPtr::new_given(name.clone(), domain),
148
        _ => {
149
            return Err(error!("FindOrGiven[0] is not 'Find' or 'Given'"));
150
        }
151
    };
152

            
153
6182
    symtab.insert(decl).ok_or(Error::Parse(format!(
154
6182
        "Could not add {name} to symbol table as it already exists"
155
6182
    )))
156
6240
}
157

            
158
1788
fn parse_letting(v: &JsonValue, scope: &SymbolTablePtr) -> Result<()> {
159
1788
    let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
160
1788
    let name = parse_name(&arr[0])?;
161

            
162
    // value letting
163
1788
    match parse_expression(&arr[1], scope) {
164
        Ok(value) => {
165
1532
            let mut symtab = scope.write();
166
1532
            symtab
167
1532
                .insert(DeclarationPtr::new_value_letting(name.clone(), value))
168
1532
                .ok_or(Error::Parse(format!(
169
1532
                    "Could not add {name} to symbol table as it already exists"
170
1532
                )))
171
        }
172
        Err(expression_error) => {
173
            // A letting whose value is not an expression may be a domain letting. Use
174
            // `get` here rather than indexing so an unsupported value expression is
175
            // reported as a parse error instead of panicking on a missing `Domain` key.
176
256
            let domain = arr[1]
177
256
                .as_object()
178
256
                .and_then(|value| value.get("Domain"))
179
256
                .ok_or(expression_error)?
180
                .as_object()
181
256
                .ok_or(error!("Letting[1].Domain is not an object"))?
182
                .iter()
183
                .next()
184
256
                .ok_or(error!("Letting[1].Domain is an empty object"))?;
185

            
186
256
            let mut symtab = scope.write();
187
256
            let domain = parse_domain(domain.0, domain.1, &mut symtab)?;
188

            
189
256
            symtab
190
256
                .insert(DeclarationPtr::new_domain_letting(name.clone(), domain))
191
256
                .ok_or(Error::Parse(format!(
192
256
                    "Could not add {name} to symbol table as it already exists"
193
256
                )))
194
        }
195
    }
196
1788
}
197

            
198
fn parse_enum_declaration(v: &JsonValue, scope: &SymbolTablePtr) -> Result<()> {
199
    let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
200
    let name = parse_name(&arr[0])?;
201

            
202
    let mut symbols = scope.write();
203

            
204
    let definition = arr[1]
205
        .as_array()
206
        .ok_or(error!("LettingDomainDefnEnum is not an array"))?;
207

            
208
    let variants = definition
209
        .iter()
210
        .map(parse_name)
211
        .collect::<Result<Vec<_>>>()?;
212

            
213
    let ty = Moo::new(EnumeratedType::new(name.clone(), variants.clone()));
214

            
215
    for (i, variant_name) in variants.iter().enumerate() {
216
        let variant = Expression::Atomic(
217
            Metadata::new(),
218
            Atom::Literal(Literal::EnumVariant(EnumVariant::new(ty.clone(), i as u32))),
219
        );
220

            
221
        symbols
222
            .insert(DeclarationPtr::new_value_letting(
223
                variant_name.clone(),
224
                variant,
225
            ))
226
            .ok_or(Error::Parse(format!(
227
                "Could not add {variant_name} to symbol table as it already exists"
228
            )))?;
229
    }
230

            
231
    symbols
232
        .insert(DeclarationPtr::new_enumerated(name.clone(), ty))
233
        .ok_or(Error::Parse(format!(
234
            "Could not add {name} to symbol table as it already exists"
235
        )))?;
236

            
237
    Ok(())
238
}
239

            
240
9308
fn parse_reference(v: &JsonValue, scope: &SymbolTablePtr) -> Result<Reference> {
241
9308
    let array = v
242
9308
        .as_object()
243
9308
        .ok_or(error!("Value is not an object"))?
244
9308
        .get("Reference")
245
9308
        .ok_or(error!("Reference does not exist"))?
246
        .as_array()
247
9308
        .ok_or(error!("Reference is not an array"))?;
248

            
249
9308
    let name_value = array
250
9308
        .first()
251
9308
        .ok_or(error!("Reference does not contain name"))?;
252
9308
    let name = parse_name(name_value)?;
253
9308
    let decl = scope
254
9308
        .read()
255
9308
        .lookup(&name)
256
9308
        .ok_or(error!(format!("Symbol table does not contain '{name}'")))?;
257

            
258
    // TODO: Second value?
259

            
260
9308
    Ok(Reference::new(decl))
261
9308
}
262

            
263
16425
fn parse_domain(
264
16425
    domain_name: &str,
265
16425
    domain_value: &JsonValue,
266
16425
    symbols: &mut SymbolTable,
267
16425
) -> Result<DomainPtr> {
268
16425
    match domain_name {
269
9875
        "DomainInt" => Ok(parse_int_domain(domain_value, symbols)?),
270
821
        "DomainBool" => Ok(Domain::bool()),
271
        "DomainReference" => {
272
306
            let arr = domain_value
273
306
                .as_array()
274
306
                .ok_or(error!("DomainReference is not an array"))?;
275
306
            let name = parse_name(&arr[0])?;
276
306
            let ptr = symbols
277
306
                .lookup(&name)
278
306
                .ok_or(error!(format!("Name {name} not found")))?;
279
            let dom =
280
306
                Domain::reference(ptr).ok_or(error!("Could not construct reference domain"))?;
281
306
            Ok(dom)
282
        }
283
        "DomainSet" => {
284
734
            let dom = domain_value.get(2).and_then(|v| v.as_object());
285
734
            let domain_obj = dom.ok_or(error!("DomainSet is missing domain object"))?;
286
734
            let domain = domain_obj
287
734
                .iter()
288
734
                .next()
289
734
                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
290
734
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
291
734
            let size = domain_value
292
734
                .get(1)
293
734
                .and_then(|v| v.as_object())
294
734
                .ok_or(error!("Set size attributes is not an object"))?;
295
734
            let size = parse_size_attr(size, symbols)?;
296
734
            let attr: SetAttr<IntVal> = SetAttr::new(size);
297
734
            Ok(Domain::set(attr, domain))
298
        }
299
        "DomainMSet" => {
300
708
            let dom = domain_value
301
708
                .get(2)
302
708
                .and_then(|v| v.as_object())
303
708
                .expect("domain object exists");
304
708
            let domain = dom
305
708
                .iter()
306
708
                .next()
307
708
                .ok_or(Error::Parse("DomainMSet is an empty object".to_owned()))?;
308
708
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
309

            
310
            // Parse Attributes
311
708
            let attributes = domain_value
312
708
                .get(1)
313
708
                .and_then(|v| v.as_array())
314
708
                .ok_or(error!("MSet attributes is not a json array"))?;
315

            
316
708
            let size = attributes
317
708
                .first()
318
708
                .and_then(|v| v.as_object())
319
708
                .ok_or(error!("MSet size attributes is not an object"))?;
320
708
            let size = parse_size_attr(size, symbols)?;
321

            
322
708
            let occurrence = attributes
323
708
                .get(1)
324
708
                .and_then(|v| v.as_object())
325
708
                .ok_or(error!("MSet occurrence attributes is not an object"))?;
326
708
            let occurrence = parse_occur_attr(occurrence, symbols)?;
327

            
328
708
            let attr: MSetAttr<IntVal> = MSetAttr {
329
708
                size,
330
708
                occurrence,
331
708
                representation: None,
332
708
            };
333
708
            Ok(Domain::mset(attr, domain))
334
        }
335
        "DomainPartition" => {
336
538
            let dom = domain_value
337
538
                .get(2)
338
538
                .and_then(|v| v.as_object())
339
538
                .expect("domain object exists");
340
538
            let domain = dom.iter().next().ok_or(Error::Parse(
341
538
                "DomainPartition is an empty object".to_owned(),
342
538
            ))?;
343
538
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
344

            
345
538
            let attributes = domain_value
346
538
                .get(1)
347
538
                .and_then(|v| v.as_object())
348
538
                .ok_or(error!("Partition attributes is not an object"))?;
349

            
350
538
            let mut num_parts = Range::Unbounded;
351
538
            let mut part_len = Range::Unbounded;
352
538
            let mut is_regular = false;
353

            
354
538
            if let Some(val) = attributes.get("partsNum") {
355
538
                let attr_map = val.as_object().expect("numParts should be an object");
356
538
                num_parts = parse_size_attr(attr_map, symbols)?;
357
            }
358
538
            if let Some(val) = attributes.get("partsSize") {
359
538
                let attr_map = val.as_object().expect("partsSize should be an object");
360
538
                part_len = parse_size_attr(attr_map, symbols)?;
361
            }
362
538
            if let Some(val) = attributes.get("isRegular").and_then(|v| v.as_bool()) {
363
538
                is_regular = val;
364
            }
365

            
366
538
            let attr: PartitionAttr<IntVal> = PartitionAttr {
367
538
                num_parts,
368
538
                part_len,
369
538
                is_regular,
370
538
                representation: None,
371
538
            };
372
538
            Ok(Domain::partition(attr, domain))
373
        }
374
        "DomainPermutation" => {
375
            let dom = domain_value
376
                .get(2)
377
                .and_then(|v| v.as_object())
378
                .expect("domain object exists");
379
            let domain = dom.iter().next().ok_or(Error::Parse(
380
                "DomainPermutation is an empty object".to_owned(),
381
            ))?;
382
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
383

            
384
            let attributes = domain_value
385
                .get(1)
386
                .and_then(|v| v.as_object())
387
                .ok_or(error!("Permutation attributes is not an object"))?;
388

            
389
            let mut num_moved = Range::Unbounded;
390
            if let Some(val) = attributes.get("numMoved") {
391
                let attr_map = val.as_object().expect("numMoved should be an object");
392
                num_moved = parse_size_attr(attr_map, symbols)?;
393
            }
394

            
395
            let attr: PermutationAttr<IntVal> = PermutationAttr {
396
                num_moved,
397
                representation: None,
398
            };
399
            Ok(Domain::permutation(attr, domain))
400
        }
401
        "DomainMatrix" => {
402
222
            let domain_value = domain_value
403
222
                .as_array()
404
222
                .ok_or(error!("Domain matrix is not an array"))?;
405

            
406
222
            let indexed_by_domain = domain_value[0].clone();
407
222
            let (index_domain_name, index_domain_value) = indexed_by_domain
408
222
                .as_object()
409
222
                .ok_or(error!("DomainMatrix[0] is not an object"))?
410
                .iter()
411
                .next()
412
222
                .ok_or(error!(""))?;
413

            
414
222
            let (value_domain_name, value_domain_value) = domain_value[1]
415
222
                .as_object()
416
222
                .ok_or(error!(""))?
417
                .iter()
418
                .next()
419
222
                .ok_or(error!(""))?;
420

            
421
            // Conjure stores a 2-d matrix as a matrix of a matrix.
422
            //
423
            // Therefore, the index is always a Domain.
424

            
425
222
            let mut index_domains: Vec<DomainPtr> = vec![];
426

            
427
222
            index_domains.push(parse_domain(
428
222
                index_domain_name,
429
222
                index_domain_value,
430
222
                symbols,
431
222
            )?);
432

            
433
            // We want to store 2-d matrices as a matrix with two index domains, not a matrix in a
434
            // matrix.
435
            //
436
            // Walk through the value domain until it is not a DomainMatrix, adding the index to
437
            // our list of indices.
438
222
            let mut value_domain = parse_domain(value_domain_name, value_domain_value, symbols)?;
439
282
            while let Some((new_value_domain, mut indices)) = value_domain.as_matrix() {
440
60
                index_domains.append(&mut indices);
441
60
                value_domain = new_value_domain.clone()
442
            }
443

            
444
222
            Ok(Domain::matrix(value_domain, index_domains))
445
        }
446

            
447
        "DomainSequence" => {
448
493
            let dom = domain_value
449
493
                .get(2)
450
493
                .and_then(|v| v.as_object())
451
493
                .expect("domain object exists");
452
493
            let domain = dom
453
493
                .iter()
454
493
                .next()
455
493
                .ok_or(Error::Parse("DomainSequence is an empty object".to_owned()))?;
456
493
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
457

            
458
            // Parse Attributes
459
493
            let attributes = domain_value
460
493
                .get(1)
461
493
                .and_then(|v| v.as_array())
462
493
                .ok_or(error!("Sequence attributes is not a json array"))?;
463

            
464
493
            let size = attributes
465
493
                .first()
466
493
                .and_then(|v| v.as_object())
467
493
                .ok_or(error!("Sequence size attributes is not an object"))?;
468
493
            let size = parse_size_attr(size, symbols)?;
469

            
470
493
            let jectivity = attributes
471
493
                .get(1)
472
493
                .and_then(|v| v.as_str())
473
493
                .ok_or(error!("jectivity is not a string"))?;
474
493
            let jectivity = match jectivity {
475
290
                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
476
58
                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
477
58
                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
478
87
                "JectivityAttr_None" => Some(JectivityAttr::None),
479
                _ => None,
480
            };
481
            let jectivity =
482
493
                jectivity.ok_or(Error::Parse("Jectivity is an unknown type".to_owned()))?;
483

            
484
493
            let attr: SequenceAttr<IntVal> = SequenceAttr {
485
493
                size,
486
493
                jectivity,
487
493
                representation: None,
488
493
            };
489
493
            match attr.size {
490
29
                Range::Unbounded | Range::UnboundedR(_) => Err(Error::Parse(
491
29
                    "Sequence must have size or maxSize attribute".to_string(),
492
29
                )),
493
464
                _ => Ok(Domain::sequence(attr, domain)),
494
            }
495
        }
496

            
497
        "DomainTuple" => {
498
522
            let domain_value = domain_value
499
522
                .as_array()
500
522
                .ok_or(error!("Domain tuple is not an array"))?;
501

            
502
            //iterate through the array and parse each domain
503
522
            let domain = domain_value
504
522
                .iter()
505
1102
                .map(|x| {
506
1102
                    let domain = x
507
1102
                        .as_object()
508
1102
                        .ok_or(error!("DomainTuple[0] is not an object"))?
509
                        .iter()
510
                        .next()
511
1102
                        .ok_or(error!("DomainTuple[0] is an empty object"))?;
512
1102
                    parse_domain(domain.0, domain.1, symbols)
513
1102
                })
514
                .collect::<Result<Vec<DomainPtr>>>()?;
515

            
516
522
            Ok(Domain::tuple(domain))
517
        }
518
        "DomainRecord" | "DomainVariant" => {
519
            // Records and Variants can be parsed the same way for the most part
520
406
            let is_record = domain_name == "DomainRecord";
521
            // Get the actual string for error message purposes
522
406
            let domain_string = match is_record {
523
116
                true => "Record",
524
290
                false => "Variant",
525
            };
526
406
            let domain_value = domain_value.as_array().ok_or(error!(&format!(
527
406
                "Domain {domain_string} is not a json array"
528
406
            )))?;
529

            
530
406
            let mut entries = vec![];
531

            
532
406
            for item in domain_value {
533
                // collect the name of the field
534
928
                let name = parse_name(&item[0])?;
535

            
536
                // then collect the domain of the field
537
928
                let domain = item[1]
538
928
                    .as_object()
539
928
                    .ok_or(error!("FindOrGiven[2] is not an object"))?
540
                    .iter()
541
                    .next()
542
928
                    .ok_or(error!("FindOrGiven[2] is an empty object"))?;
543

            
544
                let rec = Field {
545
928
                    name,
546
928
                    value: parse_domain(domain.0, domain.1, symbols)?,
547
                };
548

            
549
928
                entries.push(rec);
550
            }
551

            
552
406
            if is_record {
553
116
                Ok(Domain::record(entries))
554
            } else {
555
290
                Ok(Domain::variant(entries))
556
            }
557
        }
558
        "DomainFunction" => {
559
1092
            let domain = domain_value
560
1092
                .get(2)
561
1092
                .and_then(|v| v.as_object())
562
1092
                .ok_or(error!("Function domain is not an object"))?;
563
1092
            let domain = domain
564
1092
                .iter()
565
1092
                .next()
566
1092
                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
567
1092
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
568

            
569
1092
            let codomain = domain_value
570
1092
                .get(3)
571
1092
                .and_then(|v| v.as_object())
572
1092
                .ok_or(error!("Function codomain is not an object"))?;
573
1092
            let codomain = codomain
574
1092
                .iter()
575
1092
                .next()
576
1092
                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
577
1092
            let codomain = parse_domain(codomain.0.as_str(), codomain.1, symbols)?;
578

            
579
            // Attribute parsing
580
1092
            let attributes = domain_value
581
1092
                .get(1)
582
1092
                .and_then(|v| v.as_array())
583
1092
                .ok_or(error!("Function attributes is not a json array"))?;
584
1092
            let size = attributes
585
1092
                .first()
586
1092
                .and_then(|v| v.as_object())
587
1092
                .ok_or(error!("Function size attributes is not an object"))?;
588
1092
            let size = parse_size_attr(size, symbols)?;
589
1092
            let partiality = attributes
590
1092
                .get(1)
591
1092
                .and_then(|v| v.as_str())
592
1092
                .ok_or(error!("Function partiality is not a string"))?;
593
1092
            let partiality = match partiality {
594
960
                "PartialityAttr_Partial" => Some(PartialityAttr::Partial),
595
132
                "PartialityAttr_Total" => Some(PartialityAttr::Total),
596
                _ => None,
597
            };
598
            let partiality =
599
1092
                partiality.ok_or(Error::Parse("Partiality is an unknown type".to_owned()))?;
600
1092
            let jectivity = attributes
601
1092
                .get(2)
602
1092
                .and_then(|v| v.as_str())
603
1092
                .ok_or(error!("Function jectivity is not a string"))?;
604
1092
            let jectivity = match jectivity {
605
164
                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
606
86
                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
607
78
                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
608
764
                "JectivityAttr_None" => Some(JectivityAttr::None),
609
                _ => None,
610
            };
611
            let jectivity =
612
1092
                jectivity.ok_or(Error::Parse("Jectivity is an unknown type".to_owned()))?;
613

            
614
1092
            let attr: FuncAttr<IntVal> = FuncAttr {
615
1092
                size,
616
1092
                partiality,
617
1092
                jectivity,
618
1092
                representation: None,
619
1092
            };
620

            
621
1092
            Ok(Domain::function(attr, domain, codomain))
622
        }
623
        "DomainRelation" => {
624
708
            let domains = domain_value
625
708
                .get(2)
626
708
                .and_then(|v| v.as_array())
627
708
                .ok_or(Error::Parse(
628
708
                    "Relation domains are not a json array".to_owned(),
629
708
                ))?;
630
708
            let domains = domains
631
708
                .iter()
632
1598
                .map(|x| {
633
1598
                    let domain = x
634
1598
                        .as_object()
635
1598
                        .ok_or(Error::Parse("Relation domain is not an object".to_owned()))?
636
                        .iter()
637
                        .next()
638
1598
                        .ok_or(Error::Parse(
639
1598
                            "Relation domain is an empty object".to_owned(),
640
1598
                        ))?;
641
1598
                    parse_domain(domain.0, domain.1, symbols)
642
1598
                })
643
                .collect::<Result<Vec<DomainPtr>>>()?;
644

            
645
            // Attribute parsing
646
708
            let attributes = domain_value
647
708
                .get(1)
648
708
                .and_then(|v| v.as_array())
649
708
                .ok_or(Error::Parse(
650
708
                    "Relation attributes are not a json array".to_owned(),
651
708
                ))?;
652
708
            let size = attributes
653
708
                .first()
654
708
                .and_then(|v| v.as_object())
655
708
                .ok_or(Error::Parse(
656
708
                    "Relation size attributes are not an object".to_owned(),
657
708
                ))?;
658
708
            let size = parse_size_attr(size, symbols)?;
659
708
            let binary = attributes
660
708
                .get(1)
661
708
                .and_then(|v| v.as_array())
662
708
                .ok_or(Error::Parse(
663
708
                    "Relation binary attributes are not a json array".to_owned(),
664
708
                ))?;
665
708
            let binary = binary
666
708
                .iter()
667
754
                .map(|x| {
668
754
                    let attr = x.as_str().ok_or(Error::Parse(
669
754
                        "Relation binary attribute is not a string".to_owned(),
670
754
                    ))?;
671
754
                    match attr {
672
58
                        "BinRelAttr_Reflexive" => Ok(BinaryAttr::Reflexive),
673
58
                        "BinRelAttr_Irreflexive" => Ok(BinaryAttr::Irreflexive),
674
58
                        "BinRelAttr_Coreflexive" => Ok(BinaryAttr::Coreflexive),
675
58
                        "BinRelAttr_Symmetric" => Ok(BinaryAttr::Symmetric),
676
58
                        "BinRelAttr_AntiSymmetric" => Ok(BinaryAttr::AntiSymmetric),
677
58
                        "BinRelAttr_ASymmetric" => Ok(BinaryAttr::ASymmetric),
678
58
                        "BinRelAttr_Transitive" => Ok(BinaryAttr::Transitive),
679
58
                        "BinRelAttr_Total" => Ok(BinaryAttr::Total),
680
58
                        "BinRelAttr_Connex" => Ok(BinaryAttr::Connex),
681
58
                        "BinRelAttr_Euclidean" => Ok(BinaryAttr::Euclidean),
682
58
                        "BinRelAttr_Serial" => Ok(BinaryAttr::Serial),
683
58
                        "BinRelAttr_Equivalence" => Ok(BinaryAttr::Equivalence),
684
58
                        "BinRelAttr_PartialOrder" => Ok(BinaryAttr::PartialOrder),
685
                        "BinRelAttr_LeftTotal" => Ok(BinaryAttr::LeftTotal),
686
                        "BinRelAttr_RightTotal" => Ok(BinaryAttr::RightTotal),
687
                        "BinRelAttr_LinearOrder" => Ok(BinaryAttr::LinearOrder),
688
                        "BinRelAttr_WeakOrder" => Ok(BinaryAttr::WeakOrder),
689
                        "BinRelAttr_PreOrder" => Ok(BinaryAttr::PreOrder),
690
                        "BinRelAttr_StrictPartialOrder" => Ok(BinaryAttr::StrictPartialOrder),
691
                        _ => Err(Error::Parse(
692
                            "Relation binary attribute is invalid".to_owned(),
693
                        )),
694
                    }
695
754
                })
696
                .collect::<Result<Vec<BinaryAttr>>>()?;
697

            
698
708
            let attr: RelAttr<IntVal> = RelAttr {
699
708
                size,
700
708
                binary,
701
708
                representation: None,
702
708
            };
703

            
704
708
            Ok(Domain::relation(attr, domains))
705
        }
706
        "DomainEnum" => {
707
            let scope = SymbolTablePtr::new();
708
            *scope.write() = symbols.clone();
709

            
710
            let arr = domain_value
711
                .as_array()
712
                .ok_or(Error::Parse("DomainEnum is not an array".to_owned()))?;
713

            
714
            let name = parse_name(&arr[0])?;
715
            let decl = symbols
716
                .lookup(&name)
717
                .ok_or(Error::Parse(format!("Enum {name} does not exist")))?;
718

            
719
            let Some(et) = decl.as_enumerated_type() else {
720
                return Err(Error::Parse(format!(
721
                    "Declaration {name} is not an enumerated type"
722
                )));
723
            };
724

            
725
            let ranges =
726
                parse_range_list(&arr[1], |r| parse_reference(r, &scope).map(EnumVariantVal))?;
727

            
728
            Ok(Domain::enumerated(et.clone(), ranges))
729
        }
730
        _ => Err(Error::Parse(
731
            "FindOrGiven[2] is an unknown object".to_owned(), // consider covered
732
        )),
733
    }
734
16425
}
735

            
736
18686
fn parse_name(v: &JsonValue) -> Result<Name> {
737
18686
    let name = v
738
18686
        .as_object()
739
18686
        .ok_or(error!("Value is not an object"))?
740
18686
        .get("Name")
741
18686
        .ok_or(error!("Name does not exist"))?
742
        .as_str()
743
18686
        .ok_or(error!("Name is not a string"))?;
744

            
745
18686
    Ok(Name::User(Ustr::from(name)))
746
18686
}
747

            
748
4811
fn parse_size_attr(
749
4811
    attr_map: &JsonMap<String, JsonValue>,
750
4811
    symbols: &mut SymbolTable,
751
4811
) -> Result<Range<IntVal>> {
752
4811
    let scope = SymbolTablePtr::new();
753
4811
    *scope.write() = symbols.clone();
754

            
755
4811
    let attr_obj = attr_map
756
4811
        .iter()
757
4811
        .next()
758
4811
        .ok_or(Error::Parse("SizeAttr is an empty object".to_owned()))?;
759
4811
    match attr_obj.0.as_str() {
760
2736
        "SizeAttr_None" => Ok(Range::Unbounded),
761
        "SizeAttr_MinSize" => {
762
471
            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
763
471
            Ok(Range::UnboundedR(size))
764
        }
765
        "SizeAttr_MaxSize" => {
766
422
            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
767
422
            Ok(Range::UnboundedL(size))
768
        }
769
        "SizeAttr_MinMaxSize" => {
770
368
            let min_max = attr_obj
771
368
                .1
772
368
                .as_array()
773
368
                .ok_or(error!("SizeAttr MinMaxSize is not a json array"))?;
774
368
            let min = min_max
775
368
                .first()
776
368
                .ok_or(error!("SizeAttr Min is not present"))?;
777
368
            let min_int = parse_expression_to_int_val(min, &scope)?;
778
368
            let max = min_max
779
368
                .get(1)
780
368
                .ok_or(error!("SizeAttr Max is not present"))?;
781
368
            let max_int = parse_expression_to_int_val(max, &scope)?;
782
368
            Ok(Range::Bounded(min_int, max_int))
783
        }
784
        "SizeAttr_Size" => {
785
814
            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
786
814
            Ok(Range::Single(size))
787
        }
788
        _ => Err(Error::Parse("SizeAttr is an unknown type".to_owned())),
789
    }
790
4811
}
791

            
792
708
fn parse_occur_attr(
793
708
    attr_map: &JsonMap<String, JsonValue>,
794
708
    symbols: &mut SymbolTable,
795
708
) -> Result<Range<IntVal>> {
796
708
    let scope = SymbolTablePtr::new();
797
708
    *scope.write() = symbols.clone();
798
708
    let attr_obj = attr_map
799
708
        .iter()
800
708
        .next()
801
708
        .ok_or(Error::Parse("OccurAttr is an empty object".to_owned()))?;
802
708
    match attr_obj.0.as_str() {
803
236
        "OccurAttr_None" => Ok(Range::Unbounded),
804
        "OccurAttr_MinOccur" => {
805
58
            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
806
58
            Ok(Range::UnboundedR(size_int))
807
        }
808
        "OccurAttr_MaxOccur" => {
809
298
            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
810
298
            Ok(Range::UnboundedL(size_int))
811
        }
812
        "OccurAttr_MinMaxOccur" => {
813
116
            let min_max = attr_obj
814
116
                .1
815
116
                .as_array()
816
116
                .ok_or(error!("OccurAttr MinMaxOccur is not a json array"))?;
817
116
            let min = min_max
818
116
                .first()
819
116
                .ok_or(error!("OccurAttr Min is not present"))?;
820
116
            let min_int = parse_expression_to_int_val(min, &scope)?;
821
116
            let max = min_max
822
116
                .get(1)
823
116
                .ok_or(error!("OccurAttr Max is not present"))?;
824
116
            let max_int = parse_expression_to_int_val(max, &scope)?;
825
116
            Ok(Range::Bounded(min_int, max_int))
826
        }
827
        "OccurAttr_Size" => {
828
            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
829
            Ok(Range::Single(size_int))
830
        }
831
        _ => Err(Error::Parse("OccurAttr is an unknown type".to_owned())),
832
    }
833
708
}
834

            
835
9875
fn parse_int_domain(v: &JsonValue, symbols: &SymbolTable) -> Result<DomainPtr> {
836
9875
    let scope = SymbolTablePtr::new();
837
9875
    *scope.write() = symbols.clone();
838
9875
    let range_values = &v
839
9875
        .as_array()
840
9875
        .ok_or(Error::Parse("DomainInt[1] is not an array".to_owned()))?[1];
841
9875
    if range_values.as_array().is_some_and(Vec::is_empty) {
842
260
        return Ok(Domain::int_ground(vec![Range::Unbounded]));
843
9615
    }
844
19128
    let ranges = parse_range_list(range_values, |v| parse_expression_to_int_val(v, &scope))?;
845
9586
    Ok(Domain::int(ranges))
846
9875
}
847

            
848
9735
fn parse_range<T: Clone>(
849
9735
    v: &JsonValue,
850
    // scope: &SymbolTablePtr,
851
9735
    parser: &impl Fn(&JsonValue) -> Result<T>,
852
9735
) -> Result<Range<T>> {
853
9735
    let range = v
854
9735
        .as_object()
855
9735
        .ok_or(error!("Range is not an bject"))?
856
        .iter()
857
        .next()
858
9735
        .ok_or(error!("Range is an empty object"))?;
859

            
860
9735
    match range.0.as_str() {
861
        "RangeBounded" => {
862
9422
            let arr = range
863
9422
                .1
864
9422
                .as_array()
865
9422
                .ok_or(error!("RangeBounded is not an array".to_owned()))?;
866
9422
            let mut nums = Vec::new();
867
9422
            for item in arr.iter() {
868
18844
                let num = parser(item)?;
869
18844
                nums.push(num);
870
            }
871
9422
            let lower = nums
872
9422
                .first()
873
9422
                .cloned()
874
9422
                .ok_or(error!("RangeBounded lower bound missing"))?;
875
9422
            let upper = nums
876
9422
                .get(1)
877
9422
                .cloned()
878
9422
                .ok_or(error!("RangeBounded upper bound missing"))?;
879
9422
            Ok(Range::Bounded(lower, upper))
880
        }
881
        "RangeSingle" => {
882
284
            let num = parser(range.1)?;
883
284
            Ok(Range::Single(num))
884
        }
885
29
        _ => throw_error!("DomainInt[1] contains an unknown object"),
886
    }
887
9735
}
888

            
889
9615
fn parse_range_list<T: Clone>(
890
9615
    v: &JsonValue,
891
    // scope: &SymbolTablePtr,
892
9615
    parser: impl Fn(&JsonValue) -> Result<T>,
893
9615
) -> Result<Vec<Range<T>>> {
894
9615
    v.as_array()
895
9615
        .ok_or(error!("Value is not an array".to_owned()))?
896
        .iter()
897
9735
        .map(|r| parse_range(r, &parser))
898
        .collect()
899
9615
}
900

            
901
22159
fn parse_expression_to_int_val(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<IntVal> {
902
22159
    parser_trace!("trying to parse domain value as expression: {}", obj);
903
22159
    let expr = parse_expression(obj, scope)?;
904

            
905
22159
    if let Some(Literal::Int(i)) = expr.clone().into_literal() {
906
21193
        return Ok(IntVal::Const(i as i64));
907
966
    }
908

            
909
966
    if let Expression::Atomic(_, Atom::Reference(reference)) = &expr
910
910
        && let Ok(reference_val) = IntVal::new_ref(reference)
911
    {
912
910
        return Ok(reference_val);
913
56
    }
914

            
915
56
    IntVal::new_expr(Moo::new(expr))
916
        .map_err(|e| error!(format!("Could not parse integer expression: {e}")))
917
22159
}
918

            
919
type BinOp = fn(Metadata, Moo<Expression>, Moo<Expression>) -> Expression;
920
type UnaryOp = fn(Metadata, Moo<Expression>) -> Expression;
921

            
922
9196
fn binary_operator(op_name: &str) -> Option<BinOp> {
923
9196
    match op_name {
924
348
        "MkOpIn" => Some(Expression::In),
925
48
        "MkOpUnion" => Some(Expression::Union),
926
        "MkOpIntersect" => Some(Expression::Intersect),
927
        "MkOpSupset" => Some(Expression::Supset),
928
        "MkOpSupsetEq" => Some(Expression::SupsetEq),
929
        "MkOpSubset" => Some(Expression::Subset),
930
        "MkOpSubsetEq" => Some(Expression::SubsetEq),
931
3954
        "MkOpEq" => Some(Expression::Eq),
932
284
        "MkOpNeq" => Some(Expression::Neq),
933
146
        "MkOpGeq" => Some(Expression::Geq),
934
336
        "MkOpLeq" => Some(Expression::Leq),
935
248
        "MkOpGt" => Some(Expression::Gt),
936
8
        "MkOpLt" => Some(Expression::Lt),
937
8
        "MkOpLexLt" => Some(Expression::LexLt),
938
        "MkOpLexGt" => Some(Expression::LexGt),
939
        "MkOpLexLeq" => Some(Expression::LexLeq),
940
        "MkOpLexGeq" => Some(Expression::LexGeq),
941
        "MkOpDiv" => Some(Expression::UnsafeDiv),
942
        "MkOpMod" => Some(Expression::UnsafeMod),
943
112
        "MkOpMinus" => Some(Expression::Minus),
944
176
        "MkOpImply" => Some(Expression::Imply),
945
16
        "MkOpIff" => Some(Expression::Iff),
946
8
        "MkOpPow" => Some(Expression::UnsafePow),
947
116
        "MkOpImage" => Some(Expression::Image),
948
116
        "MkOpImageSet" => Some(Expression::ImageSet),
949
220
        "MkOpPreImage" => Some(Expression::PreImage),
950
116
        "MkOpInverse" => Some(Expression::Inverse),
951
        "MkOpCompose" => Some(Expression::Compose),
952
164
        "MkOpRestrict" => Some(Expression::Restrict),
953
116
        "MkOpApart" => Some(Expression::Apart),
954
116
        "MkOpTogether" => Some(Expression::Together),
955
124
        "MkOpParty" => Some(Expression::Party),
956
232
        "MkOpSubstring" => Some(Expression::Substring),
957
        "MkOpSubsequence" => Some(Expression::Subsequence),
958
2184
        _ => None,
959
    }
960
9196
}
961

            
962
4368
fn unary_operator(op_name: &str, inner: Option<&Expression>) -> Option<UnaryOp> {
963
4368
    match op_name {
964
120
        "MkOpNot" => Some(Expression::Not),
965
214
        "MkOpNegate" => Some(Expression::Neg),
966
        "MkOpTwoBars" => {
967
1106
            if let Some(inner) = inner {
968
553
                match inner.return_type() {
969
29
                    ReturnType::Int => Some(Expression::Abs),
970
                    ReturnType::Matrix(_)
971
                    | ReturnType::Set(_)
972
                    | ReturnType::MSet(_)
973
                    | ReturnType::Function(_, _)
974
524
                    | ReturnType::Relation(_) => Some(Expression::Card),
975
                    _ => None,
976
                }
977
            } else {
978
                // Internal expression cannot be known yet, so we just have to assume
979
553
                Some(Expression::Abs)
980
            }
981
        }
982
908
        "MkOpAnd" => Some(Expression::And),
983
672
        "MkOpSum" => Some(Expression::Sum),
984
8
        "MkOpProduct" => Some(Expression::Product),
985
152
        "MkOpOr" => Some(Expression::Or),
986
        "MkOpMin" => Some(Expression::Min),
987
32
        "MkOpMax" => Some(Expression::Max),
988
24
        "MkOpAllDiff" => Some(Expression::AllDiff),
989
112
        "MkOpToInt" => Some(Expression::ToInt),
990
188
        "MkOpDefined" => Some(Expression::Defined),
991
        "MkOpPermInverse" => Some(Expression::PermInverse),
992
220
        "MkOpRange" => Some(Expression::Range),
993
        "MkOpFactorial" => Some(Expression::Factorial),
994
232
        "MkOpToMSet" => Some(Expression::ToMSet),
995
116
        "MkOpToRelation" => Some(Expression::ToRelation),
996
        "MkOpPred" => Some(Expression::Pred),
997
        "MkOpSucc" => Some(Expression::Succ),
998
132
        "MkOpParticipants" => Some(Expression::Participants),
999
132
        "MkOpParts" => Some(Expression::Parts),
        _ => None,
    }
4368
}
117
fn parse_reference_name(obj: &JsonValue) -> Result<Name> {
    // { Name: "x" } directly
117
    if let Some(name) = obj.get("Name").and_then(|x| x.as_str()) {
58
        return Ok(Name::User(Ustr::from(name)));
59
    }
    // {
    //   Reference: [
    //     { Name: "x" }
    //   ]
    // }
59
    let ref_arr = obj["Reference"]
59
        .as_array()
        .ok_or_else(|| error!("Reference.as_array"))?;
59
    let ref_obj = ref_arr
59
        .first()
59
        .and_then(|x| x.as_object())
        .ok_or_else(|| error!("Reference[0].as_object"))?;
59
    let name = ref_obj
59
        .get("Name")
59
        .and_then(|x| x.as_str())
        .ok_or_else(|| error!("Reference[0].Name.as_str"))?;
59
    Ok(Name::User(Ustr::from(name)))
117
}
46819
pub fn parse_expression(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<Expression> {
388
    let fail = |stage: &str| -> Error {
388
        Error::Parse(format!(
388
            "Could not parse expression at stage `{stage}` for json `{obj}`"
388
        ))
388
    };
46819
    match obj {
46687
        Value::Object(op) if op.contains_key("Op") => {
7519
            let op_obj = op
7519
                .get("Op")
7519
                .and_then(Value::as_object)
                .ok_or_else(|| fail("Op.as_object"))?;
7519
            let (op_name, _) = op_obj.iter().next().ok_or_else(|| fail("Op.iter().next"))?;
7519
            if op_obj.contains_key("MkOpFlatten") {
8
                parse_flatten_op(op_obj, scope)
7511
            } else if op_obj.contains_key("MkOpTable") {
                parse_table_op(op_obj, scope)
7511
            } else if op_obj.contains_key("MkOpIndexing") || op_obj.contains_key("MkOpSlicing") {
1515
                parse_indexing_slicing_op(op_obj, scope)
5996
            } else if op_obj.contains_key("MkOpActive") {
58
                parse_active_op(op_obj, scope)
5938
            } else if op_obj.contains_key("MkOpRelationProj") {
62
                parse_relation_projection(op_obj, scope)
5876
            } else if op_obj.contains_key("MkOpToSet") {
186
                parse_to_set(op_obj, scope)
5690
            } else if binary_operator(op_name).is_some() {
3506
                parse_bin_op(op_obj, scope)
2184
            } else if unary_operator(op_name, None).is_some() {
2184
                parse_unary_op(op_obj, scope)
            } else {
                Err(fail("Op.unknown"))
            }
        }
39168
        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
16
            parse_comprehension(comprehension, scope.clone())
        }
39152
        Value::Object(refe) if refe.contains_key("Reference") => {
9308
            let reference = parse_reference(obj, scope)?;
9308
            Ok(Expression::Atomic(
9308
                Metadata::new(),
9308
                Atom::Reference(reference),
9308
            ))
        }
        // In the case where refering to fields. This not behind a reference
29844
        Value::Object(refe) if refe.contains_key("Name") => {
            let name = refe
                .get("Name")
                .and_then(|x| x.as_str())
                .ok_or_else(|| fail("Reference[0].Name.as_str"))?;
            let user_name = Name::User(Ustr::from(name));
            let declaration: DeclarationPtr = scope
                .read()
                .lookup(&user_name)
                .ok_or_else(|| fail("Reference.lookup"))?;
            Ok(Expression::Atomic(
                Metadata::new(),
                Atom::Reference(crate::ast::Reference::new(declaration)),
            ))
        }
29844
        Value::Object(abslit) if abslit.contains_key("AbstractLiteral") => {
629
            let abstract_literal = abslit["AbstractLiteral"]
629
                .as_object()
                .ok_or_else(|| fail("AbstractLiteral.as_object"))?;
629
            if abstract_literal.contains_key("AbsLitSet") {
                parse_abs_lit(&abslit["AbstractLiteral"]["AbsLitSet"], scope)
629
            } else if abstract_literal.contains_key("AbsLitFunction") {
58
                parse_abs_function(&abslit["AbstractLiteral"]["AbsLitFunction"], scope)
571
            } else if abstract_literal.contains_key("AbsLitMSet") {
                parse_abs_mset(&abslit["AbstractLiteral"]["AbsLitMSet"], scope)
571
            } else if abstract_literal.contains_key("AbsLitVariant") {
58
                parse_abs_variant(&abslit["AbstractLiteral"]["AbsLitVariant"], scope)
513
            } else if abstract_literal.contains_key("AbsLitRelation") {
                parse_abs_relation(&abslit["AbstractLiteral"]["AbsLitRelation"], scope)
513
            } else if abstract_literal.contains_key("AbsLitPartition") {
1
                parse_abs_partition(&abslit["AbstractLiteral"]["AbsLitPartition"], scope)
512
            } else if abstract_literal.contains_key("AbsLitPermutation") {
                parse_abs_permutation(&abslit["AbstractLiteral"]["AbsLitPermutation"], scope)
512
            } else if abstract_literal.contains_key("AbsLitSequence") {
                parse_abs_sequence(&abslit["AbstractLiteral"]["AbsLitSequence"], scope)
            } else {
512
                parse_abstract_matrix_as_expr(obj, scope)
            }
        }
29215
        Value::Object(constant) if constant.contains_key("Constant") => {
24219
            parse_constant(constant, scope).or_else(|_| parse_abstract_matrix_as_expr(obj, scope))
        }
4996
        Value::Object(constant) if constant.contains_key("ConstantAbstract") => {
143
            let literal = constant
143
                .get("ConstantAbstract")
143
                .and_then(Value::as_object)
                .ok_or_else(|| fail("ConstantAbstract.as_object"))?;
143
            if literal.contains_key("AbsLitMatrix") {
140
                parse_abstract_matrix_as_expr(obj, scope)
            } else {
3
                parse_constant_abstract(literal, scope)
            }
        }
4853
        Value::Object(constant) if constant.contains_key("ConstantInt") => {
4307
            parse_constant(constant, scope)
        }
546
        Value::Object(constant) if constant.contains_key("ConstantBool") => {
290
            parse_constant(constant, scope)
        }
388
        _ => Err(fail("no_match")),
    }
46819
}
537
fn parse_abs_lit(abs_set: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
537
    let values = abs_set
537
        .as_array()
537
        .ok_or(error!("AbsLitSet is not an array"))?;
537
    let expressions = values
537
        .iter()
1069
        .map(|values| parse_expression(values, scope))
        .collect::<Result<Vec<_>>>()?;
537
    Ok(Expression::AbstractLiteral(
537
        Metadata::new(),
537
        AbstractLiteral::Set(expressions),
537
    ))
537
}
3
fn parse_constant_abstract(
3
    literal: &serde_json::Map<String, Value>,
3
    scope: &SymbolTablePtr,
3
) -> Result<Expression> {
3
    if let Some(value) = literal.get("AbsLitSet") {
3
        parse_abs_lit(value, scope)
    } else if let Some(value) = literal.get("AbsLitMSet") {
        parse_abs_mset(value, scope)
    } else if let Some(value) = literal.get("AbsLitTuple") {
        parse_abs_tuple(value, scope)
    } else if let Some(value) = literal.get("AbsLitRecord") {
        parse_abs_record(value, scope)
    } else if let Some(value) = literal.get("AbsLitPartition") {
        parse_abs_partition(value, scope)
    } else if let Some(value) = literal.get("AbsLitPermutation") {
        parse_abs_permutation(value, scope)
    } else if let Some(value) = literal.get("AbsLitFunction") {
        parse_abs_function(value, scope)
    } else if let Some(value) = literal.get("AbsLitVariant") {
        parse_abs_variant(value, scope)
    } else if let Some(value) = literal.get("AbsLitRelation") {
        parse_abs_relation(value, scope)
    } else if let Some(value) = literal.get("AbsLitSequence") {
        parse_abs_sequence(value, scope)
    } else {
        Err(error!("Unhandled ConstantAbstract literal type"))
    }
3
}
58
fn parse_abs_mset(abs_mset: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
58
    let values = abs_mset
58
        .as_array()
58
        .ok_or(error!("AbsLitMSet is not an array"))?;
58
    let expressions = values
58
        .iter()
174
        .map(|values| parse_expression(values, scope))
        .collect::<Result<Vec<_>>>()?;
58
    Ok(Expression::AbstractLiteral(
58
        Metadata::new(),
58
        AbstractLiteral::MSet(expressions),
58
    ))
58
}
59
fn parse_abs_partition(abs_partition: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
59
    let parts = abs_partition
59
        .as_array()
59
        .ok_or(error!("AbsLitPartition is not an array"))?;
59
    let mut partition: Vec<Vec<_>> = Vec::new();
59
    for part in parts {
176
        let vals = part
176
            .as_array()
176
            .ok_or(error!("Part in AbsLitPartition is not an array"))?;
176
        let exprs = vals
176
            .iter()
236
            .map(|values| parse_expression(values, scope))
            .collect::<Result<Vec<_>>>()?;
176
        partition.push(exprs);
    }
59
    Ok(Expression::AbstractLiteral(
59
        Metadata::new(),
59
        AbstractLiteral::Partition(partition),
59
    ))
59
}
fn parse_abs_permutation(abs_permutation: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
    let cycles = abs_permutation
        .as_array()
        .ok_or(error!("AbsLitPermutation is not an array"))?;
    let mut permutation: Vec<Vec<_>> = Vec::new();
    for cycle in cycles {
        let vals = cycle
            .as_array()
            .ok_or(error!("Cycle in AbsLitPermutation is not an array"))?;
        let exprs = vals
            .iter()
            .map(|values| parse_expression(values, scope))
            .collect::<Result<Vec<_>>>()?;
        permutation.push(exprs);
    }
    Ok(Expression::AbstractLiteral(
        Metadata::new(),
        AbstractLiteral::Permutation(permutation),
    ))
}
174
fn parse_abs_sequence(abs_seq: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
174
    let values = abs_seq
174
        .as_array()
174
        .ok_or(error!("AbsLitSequence is not an array"))?;
174
    let expressions = values
174
        .iter()
580
        .map(|values| parse_expression(values, scope))
        .collect::<Result<Vec<_>>>()?;
174
    Ok(Expression::AbstractLiteral(
174
        Metadata::new(),
174
        AbstractLiteral::Sequence(expressions),
174
    ))
174
}
116
fn parse_abs_tuple(abs_tuple: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
116
    let values = abs_tuple
116
        .as_array()
116
        .ok_or(error!("AbsLitTuple is not an array"))?;
116
    let expressions = values
116
        .iter()
232
        .map(|values| parse_expression(values, scope))
        .collect::<Result<Vec<_>>>()?;
116
    Ok(Expression::AbstractLiteral(
116
        Metadata::new(),
116
        AbstractLiteral::Tuple(expressions),
116
    ))
116
}
//parses an abstract record as an expression
58
fn parse_abs_record(abs_record: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
58
    let entries = abs_record
58
        .as_array()
58
        .ok_or(error!("AbsLitRecord is not an array"))?;
58
    let mut rec = vec![];
58
    for entry in entries {
116
        let entry = entry
116
            .as_array()
116
            .ok_or(error!("AbsLitRecord entry is not an array"))?;
116
        let name = parse_name(&entry[0])?;
116
        let value = parse_expression(&entry[1], scope)?;
116
        let rec_entry = Field {
116
            name: name.clone(),
116
            value,
116
        };
116
        rec.push(rec_entry);
    }
58
    Ok(Expression::AbstractLiteral(
58
        Metadata::new(),
58
        AbstractLiteral::Record(rec),
58
    ))
58
}
//parses an abstract variant as an expression
58
fn parse_abs_variant(abs_variant: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
58
    let entry = abs_variant
58
        .as_array()
58
        .ok_or(error!("AbsLitVariant is not an array"))?;
58
    let name = entry[1]
58
        .as_object()
58
        .ok_or(error!("AbsLitVariant field name is not an object"))?["Name"]
        .as_str()
58
        .ok_or(error!("AbsLitVariant field name is not a string"))?;
58
    let value = parse_expression(&entry[2], scope)?;
58
    let name = Name::User(Ustr::from(name));
58
    let rec_entry = Field { name, value };
58
    Ok(Expression::AbstractLiteral(
58
        Metadata::new(),
58
        AbstractLiteral::Variant(Moo::new(rec_entry)),
58
    ))
58
}
//parses an abstract function as an expression
174
fn parse_abs_function(abs_function: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
174
    let entries = abs_function
174
        .as_array()
174
        .ok_or(error!("AbsLitFunction is not an array"))?;
174
    let mut assignments = vec![];
174
    for entry in entries {
348
        let entry = entry
348
            .as_array()
348
            .ok_or(error!("Explicit function assignment is not an array"))?;
348
        let expression = entry
348
            .iter()
696
            .map(|values| parse_expression(values, scope))
            .collect::<Result<Vec<_>>>()?;
348
        let domain_value = expression
348
            .first()
348
            .ok_or(error!("Invalid function domain"))?;
348
        let codomain_value = expression
348
            .get(1)
348
            .ok_or(error!("Invalid function codomain"))?;
348
        let tuple = (domain_value.clone(), codomain_value.clone());
348
        assignments.push(tuple);
    }
174
    Ok(Expression::AbstractLiteral(
174
        Metadata::new(),
174
        AbstractLiteral::Function(assignments),
174
    ))
174
}
//parses an abstract relation as an expression
116
fn parse_abs_relation(abs_relation: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
116
    let entries = abs_relation
116
        .as_array()
116
        .ok_or(error!("AbsLitRelation is not an array"))?;
116
    let mut assignments = vec![];
116
    for entry in entries {
290
        let entry = entry
290
            .as_array()
290
            .ok_or(error!("Explicit relation assignment is not an array"))?;
290
        let expression = entry
290
            .iter()
696
            .map(|values| parse_expression(values, scope))
            .collect::<Result<Vec<_>>>()?;
290
        assignments.push(expression);
    }
116
    Ok(Expression::AbstractLiteral(
116
        Metadata::new(),
116
        AbstractLiteral::Relation(assignments),
116
    ))
116
}
398
fn parse_comprehension(
398
    comprehension: &serde_json::Map<String, Value>,
398
    scope: SymbolTablePtr,
398
) -> Result<Expression> {
    let fail = |stage: &str| -> Error {
        Error::Parse(format!("Could not parse comprehension at stage `{stage}`"))
    };
398
    let value = &comprehension["Comprehension"];
398
    let mut comprehension = ComprehensionBuilder::new(scope.clone());
398
    let generator_symboltable = comprehension.generator_symboltable();
398
    let return_expr_symboltable = comprehension.return_expr_symboltable();
398
    let generators_and_guards_array = value
398
        .pointer("/1")
398
        .and_then(Value::as_array)
        .ok_or_else(|| fail("Comprehension.pointer(/1).as_array"))?;
398
    let generators_and_guards = generators_and_guards_array.iter();
398
    for gen_or_guard in generators_and_guards {
660
        let gen_or_guard_obj = gen_or_guard
660
            .as_object()
            .ok_or_else(|| fail("generator_or_guard.as_object"))?;
660
        let (name, inner) = gen_or_guard_obj
660
            .iter()
660
            .next()
            .ok_or_else(|| fail("generator_or_guard.iter().next"))?;
660
        comprehension = match name.as_str() {
            "Generator" => {
                // TODO: more things than GenDomainNoRepr and Single names here?
540
                let generator_obj = inner
540
                    .as_object()
                    .ok_or_else(|| fail("Generator.inner.as_object"))?;
540
                let (name, gen_inner) = generator_obj
540
                    .iter()
540
                    .next()
                    .ok_or_else(|| fail("Generator.inner.iter().next"))?;
540
                match name.as_str() {
                    "GenDomainNoRepr" => {
508
                        let name = gen_inner
508
                            .pointer("/0/Single/Name")
508
                            .and_then(Value::as_str)
                            .ok_or_else(|| {
                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
                            })?;
508
                        let domain_obj = gen_inner
508
                            .pointer("/1")
508
                            .and_then(Value::as_object)
                            .ok_or_else(|| fail("GenDomainNoRepr.pointer(/1).as_object"))?;
508
                        let (domain_name, domain_value) = domain_obj
508
                            .iter()
508
                            .next()
                            .ok_or_else(|| fail("GenDomainNoRepr.domain.iter().next"))?;
508
                        let domain = parse_domain(
508
                            domain_name,
508
                            domain_value,
508
                            &mut generator_symboltable.write(),
508
                        )?;
508
                        comprehension.generator(DeclarationPtr::new_find(name.into(), domain))
                    }
                    "GenInExpr" => {
32
                        let name = gen_inner
32
                            .pointer("/0/Single/Name")
32
                            .and_then(Value::as_str)
                            .ok_or_else(|| {
                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
                            })?;
32
                        let generator_expr = gen_inner
32
                            .pointer("/1")
                            .ok_or_else(|| fail("GenInExpr.pointer(/1)"))?;
32
                        let expr = parse_expression(generator_expr, &scope)
                            .map_err(|_| fail("GenInExpr.parse_expression"))?;
32
                        comprehension.expression_generator(name.into(), expr)
                    }
                    _ => {
                        bug!("unknown generator type inside comprehension {name}");
                    }
                }
            }
            "Condition" => {
120
                let expr = parse_expression(inner, &generator_symboltable)
                    .map_err(|_| fail("Condition.parse_expression"))?;
120
                comprehension.guard(expr)
            }
            x => {
                bug!("unknown field inside comprehension {x}");
            }
        }
    }
398
    let return_expr_value = value
398
        .pointer("/0")
        .ok_or_else(|| fail("Comprehension.pointer(/0)"))?;
398
    let expr = parse_expression(return_expr_value, &return_expr_symboltable)
        .map_err(|_| fail("Comprehension.return_expr.parse_expression"))?;
398
    Ok(Expression::Comprehension(
398
        Metadata::new(),
398
        Moo::new(comprehension.with_return_value(expr)),
398
    ))
398
}
2184
fn unary_skip_operator(op_name: &str) -> Option<ACOperatorKind> {
2184
    match op_name {
454
        "MkOpAnd" => Some(ACOperatorKind::And),
76
        "MkOpOr" => Some(ACOperatorKind::Or),
336
        "MkOpSum" => Some(ACOperatorKind::Sum),
4
        "MkOpProduct" => Some(ACOperatorKind::Product),
        // Not true AC operators (no universal identity element), but still need their own
        // skip-operator tag so a symbolic guard lowers correctly instead of silently substituting
        // Sum's identity (0).
        "MkOpMin" => Some(ACOperatorKind::Min),
16
        "MkOpMax" => Some(ACOperatorKind::Max),
1298
        _ => None,
    }
2184
}
2184
fn set_comprehension_skip_operator(
2184
    expr: Expression,
2184
    skip_operator: Option<ACOperatorKind>,
2184
) -> Expression {
2184
    let Expression::Comprehension(meta, comprehension) = expr else {
1802
        return expr;
    };
382
    if let Some(skip_operator) = skip_operator {
382
        let mut comprehension = Moo::unwrap_or_clone(comprehension);
382
        comprehension.skip_operator = Some(skip_operator);
382
        Expression::Comprehension(meta, Moo::new(comprehension))
    } else {
        Expression::Comprehension(meta, comprehension)
    }
2184
}
3506
fn parse_bin_op(
3506
    bin_op: &serde_json::Map<String, Value>,
3506
    scope: &SymbolTablePtr,
3506
) -> Result<Expression> {
    // we know there is a single key value pair in this object
    // extract the value, ignore the key
3506
    let (key, value) = bin_op
3506
        .into_iter()
3506
        .next()
3506
        .ok_or(error!("Binary op object is empty"))?;
3506
    let constructor = binary_operator(key.as_str())
3506
        .ok_or(error!(format!("Unknown binary operator `{}`", key)))?;
3506
    match &value {
3506
        Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
3506
            let arg1 = parse_expression(&bin_op_args[0], scope)?;
3506
            let arg2 = parse_expression(&bin_op_args[1], scope)?;
            // Conjure spells set difference with minus, so the operand types decide which of the
            // two it is -- the same choice the Essence parser makes.
3506
            if key == "MkOpMinus"
56
                && (matches!(arg1.try_return_type(), Some(ReturnType::Set(_)))
40
                    || matches!(arg2.try_return_type(), Some(ReturnType::Set(_))))
            {
16
                return Ok(Expression::Difference(
16
                    Metadata::new(),
16
                    Moo::new(arg1),
16
                    Moo::new(arg2),
16
                ));
3490
            }
3490
            Ok(constructor(Metadata::new(), Moo::new(arg1), Moo::new(arg2)))
        }
        _ => Err(error!("Binary operator arguments are not a 2-array")),
    }
3506
}
fn parse_table_op(
    op: &serde_json::Map<String, Value>,
    scope: &SymbolTablePtr,
) -> Result<Expression> {
    let args = op
        .get("MkOpTable")
        .ok_or(error!("MkOpTable missing"))?
        .as_array()
        .ok_or(error!("MkOpTable is not an array"))?;
    if args.len() != 2 {
        return Err(error!("MkOpTable arguments are not a 2-array"));
    }
    let tuple_expr = parse_expression(&args[0], scope)?;
    let allowed_rows_expr = parse_expression(&args[1], scope)?;
    let (tuple_elems, _) = tuple_expr
        .clone()
        .unwrap_matrix_unchecked()
        .ok_or(error!("MkOpTable first argument is not a matrix"))?;
    let (allowed_rows, _) = allowed_rows_expr
        .clone()
        .unwrap_matrix_unchecked()
        .ok_or(error!("MkOpTable second argument is not a matrix"))?;
    for row_expr in allowed_rows {
        let (row_elems, _) = row_expr
            .unwrap_matrix_unchecked()
            .ok_or(error!("MkOpTable row is not a matrix"))?;
        if row_elems.len() != tuple_elems.len() {
            return Err(error!("MkOpTable row width does not match tuple width"));
        }
    }
    Ok(Expression::Table(
        Metadata::new(),
        Moo::new(tuple_expr),
        Moo::new(allowed_rows_expr),
    ))
}
/// If LHS is a record/variant and RHS is a field name,
/// returns Ok(Some(record_expr, field_name)).
/// If LHS is any other type, return Ok(None).
1573
fn parse_record_field(
1573
    op_args: &[Value],
1573
    scope: &SymbolTablePtr,
1573
) -> Result<Option<(Expression, Name)>> {
1573
    if op_args.len() != 2 {
        return Err(error!("Expected 2 arguments to record indexing operation"));
1573
    }
1573
    let lhs = parse_expression(&op_args[0], scope)?;
1573
    match lhs.return_type() {
        // If indexing into a record, parse string field name
        // and check that such a field exists
        ReturnType::Record(ents) | ReturnType::Variant(ents) => {
117
            let field_name = parse_reference_name(&op_args[1])?;
175
            let has_name = ents.iter().any(|x| x.name.eq(&field_name));
117
            if !has_name {
                return Err(error!(format!(
                    "Unknown field `{field_name}` in record `{lhs}`"
                )));
117
            }
117
            Ok(Some((lhs, field_name)))
        }
1456
        _ => Ok(None),
    }
1573
}
58
fn parse_active_op(
58
    op: &serde_json::Map<String, Value>,
58
    scope: &SymbolTablePtr,
58
) -> Result<Expression> {
    // we know there is a single key value pair in this object
    // extract the value, ignore the key
58
    let (_, value) = op
58
        .into_iter()
58
        .next()
58
        .ok_or(error!("MkOpActive op object is empty"))?;
58
    let Value::Array(op_args) = &value else {
        return Err(error!("MkOpActive op array is not an array"));
    };
58
    let Some((lhs, rhs)) = parse_record_field(op_args, scope)? else {
        return Err(error!("MkOpActive op expected record or variant"));
    };
58
    Ok(Expression::Active(Metadata::new(), Moo::new(lhs), rhs))
58
}
1515
fn parse_indexing_slicing_op(
1515
    op: &serde_json::Map<String, Value>,
1515
    scope: &SymbolTablePtr,
1515
) -> Result<Expression> {
    // we know there is a single key value pair in this object
    // extract the value, ignore the key
1515
    let (key, value) = op
1515
        .into_iter()
1515
        .next()
1515
        .ok_or(error!("Indexing/Slicing op object is empty"))?;
    // we know that this is meant to be a mkopindexing, so anything that goes wrong from here is a
    // bug!
    // Conjure does a[1,2,3] as MkOpIndexing(MkOpIndexing(MkOpIndexing(a,3),2),1).
    //
    // And  a[1,..,3] as MkOpIndexing(MkOpSlicing(MkOpIndexing(a,3)),1).
    //
    // However, we want this in a flattened form: Index(a, [1,2,3])
    let mut target: Expression;
1515
    let mut indices: Vec<Option<Expression>> = vec![];
    // true if this has no slicing, false otherwise.
1515
    let mut all_known = true;
1515
    match key.as_str() {
        "MkOpIndexing" => {
1515
            match &value {
1515
                Value::Array(op_args) if op_args.len() == 2 => {
1515
                    target = parse_expression(&op_args[0], scope)?;
1515
                    match parse_record_field(op_args, scope)? {
                        // For record indexing, generate nested RecordField exprs
                        Some((lhs, rhs)) => {
59
                            target = Expression::RecordField(Metadata::new(), Moo::new(lhs), rhs)
                        }
                        // Append any other indices to the flat list as normal
1456
                        _ => indices.push(Some(parse_expression(&op_args[1], scope)?)),
                    }
                }
                _ => return Err(error!("Unknown object inside MkOpIndexing")),
            };
        }
        "MkOpSlicing" => {
            all_known = false;
            match &value {
                Value::Array(op_args) if op_args.len() == 3 => {
                    // NB: records can't be sliced into so no need to check!
                    target = parse_expression(&op_args[0], scope)?;
                    indices.push(None);
                }
                _ => return Err(error!("Unknown object inside MkOpSlicing")),
            };
        }
        _ => return Err(error!("Unknown indexing/slicing operator")),
    }
    loop {
1923
        match &mut target {
            Expression::UnsafeIndex(_, new_target, new_indices) => {
408
                indices.extend(new_indices.iter().cloned().rev().map(Some));
408
                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.
1515
                break;
            }
        }
    }
    // If we had a record field and no other indices, the list will be empty
1515
    if indices.is_empty() {
59
        return Ok(target);
1456
    }
1456
    indices.reverse();
1456
    if all_known {
        Ok(Expression::UnsafeIndex(
1456
            Metadata::new(),
1456
            Moo::new(target),
1456
            indices
1456
                .into_iter()
1456
                .collect::<Option<Vec<_>>>()
1456
                .ok_or(error!("Missing index in fully-known indexing operation"))?,
        ))
    } else {
        Ok(Expression::UnsafeSlice(
            Metadata::new(),
            Moo::new(target),
            indices,
        ))
    }
1515
}
// Parses relation projection, to get a Vec<Option<Expression>> for the projections
62
fn parse_relation_projection(
62
    op: &serde_json::Map<String, Value>,
62
    scope: &SymbolTablePtr,
62
) -> Result<Expression> {
62
    let args = op
62
        .get("MkOpRelationProj")
62
        .ok_or(error!("MkOpRelationProj missing"))?
        .as_array()
62
        .ok_or(error!("MkOpRelationProj is not an array"))?;
62
    let first = args
62
        .first()
62
        .ok_or(error!("MkOpRelationProj missing first argument"))?;
62
    let second = args
62
        .get(1)
62
        .ok_or(error!("MkOpRelationProj missing second argument"))?
        .as_array()
62
        .ok_or(error!("MkOpRelationProj second argument is not an array"))?;
62
    let relation = parse_expression(first, scope).ok();
    // We build a vec of option expressions.
    // In the case where a relation domain is not being projected it is None, otherwise it is Some with the expression
    // We parse the 'null' as an error, which is mapped to None after parse_expression()
62
    let projections = second
62
        .iter()
186
        .map(|expr| parse_expression(expr, scope).ok())
        .collect();
62
    if let Some(relation) = relation {
62
        Ok(Expression::RelationProj(
62
            Metadata::new(),
62
            Moo::new(relation),
62
            projections,
62
        ))
    } else {
        Err(error!("MkOpRelationProj does not contain relation"))
    }
62
}
// The ToSet operator is not truely a unary operator.
// The internal expression is 2nd in the array, with 'false' as the first element
// Therefore it needs separate parsing
186
fn parse_to_set(op: &serde_json::Map<String, Value>, scope: &SymbolTablePtr) -> Result<Expression> {
186
    let args = op
186
        .get("MkOpToSet")
186
        .ok_or(error!("MkOpToSet missing"))?
        .as_array()
186
        .ok_or(error!("MkOpToSet is not an array"))?;
186
    let second = args
186
        .get(1)
186
        .ok_or(error!("MkOpToSet missing second argument"))?;
186
    let inner = parse_expression(second, scope)?;
186
    Ok(Expression::ToSet(Metadata::new(), Moo::new(inner)))
186
}
8
fn parse_flatten_op(
8
    op: &serde_json::Map<String, Value>,
8
    scope: &SymbolTablePtr,
8
) -> Result<Expression> {
8
    let args = op
8
        .get("MkOpFlatten")
8
        .ok_or(error!("MkOpFlatten missing"))?
        .as_array()
8
        .ok_or(error!("MkOpFlatten is not an array"))?;
8
    let first = args
8
        .first()
8
        .ok_or(error!("MkOpFlatten missing first argument"))?;
8
    let second = args
8
        .get(1)
8
        .ok_or(error!("MkOpFlatten missing second argument"))?;
8
    let n = parse_expression(first, scope).ok();
8
    let matrix = parse_expression(second, scope)?;
8
    if let Some(n) = n {
        Ok(Expression::Flatten(
            Metadata::new(),
            Some(Moo::new(n)),
            Moo::new(matrix),
        ))
    } else {
8
        Ok(Expression::Flatten(Metadata::new(), None, Moo::new(matrix)))
    }
8
}
2184
fn parse_unary_op(
2184
    un_op: &serde_json::Map<String, Value>,
2184
    scope: &SymbolTablePtr,
2184
) -> Result<Expression> {
    let fail = |stage: &str| -> Error {
        Error::Parse(format!("Could not parse unary op at stage `{stage}`"))
    };
2184
    let (key, value) = un_op
2184
        .iter()
2184
        .next()
        .ok_or_else(|| fail("un_op.iter().next"))?;
    // 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.
2184
    let arg = match value {
2184
        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
382
            parse_comprehension(comprehension, scope.clone())
                .map_err(|_| fail("value.Comprehension.parse_comprehension"))
        }
1802
        _ => parse_expression(value, scope).map_err(|_| fail("value.parse_expression")),
    }
    .map_err(|_| fail("arg"))?;
2184
    let skip_operator = unary_skip_operator(key.as_str());
2184
    let arg = set_comprehension_skip_operator(arg, skip_operator);
    let constructor =
2184
        unary_operator(key.as_str(), Some(&arg)).ok_or_else(|| fail("unary_operator"))?;
2184
    Ok(constructor(Metadata::new(), Moo::new(arg)))
2184
}
// Takes in { AbstractLiteral: .... }
732
fn parse_abstract_matrix_as_expr(
732
    value: &serde_json::Value,
732
    scope: &SymbolTablePtr,
732
) -> Result<Expression> {
732
    parser_trace!("trying to parse an abstract literal matrix");
    let (values, domain_name, domain_value) =
732
        if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix") {
512
            parser_trace!(".. found JSON pointer /AbstractLiteral/AbstractLitMatrix");
512
            let (domain_name, domain_value) = abs_lit_matrix
512
                .pointer("/0")
512
                .and_then(Value::as_object)
512
                .and_then(|x| x.iter().next())
512
                .ok_or(error!("AbsLitMatrix missing domain"))?;
512
            let values = abs_lit_matrix
512
                .pointer("/1")
512
                .ok_or(error!("AbsLitMatrix missing values"))?;
512
            Some((values, domain_name, domain_value))
        }
        // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
220
        else if let Some(const_abs_lit_matrix) =
220
            value.pointer("/Constant/ConstantAbstract/AbsLitMatrix")
        {
40
            parser_trace!(".. found JSON pointer /Constant/ConstantAbstract/AbsLitMatrix");
40
            let (domain_name, domain_value) = const_abs_lit_matrix
40
                .pointer("/0")
40
                .and_then(Value::as_object)
40
                .and_then(|x| x.iter().next())
40
                .ok_or(error!("ConstantAbstract AbsLitMatrix missing domain"))?;
40
            let values = const_abs_lit_matrix
40
                .pointer("/1")
40
                .ok_or(error!("ConstantAbstract AbsLitMatrix missing values"))?;
40
            Some((values, domain_name, domain_value))
180
        } else if let Some(const_abs_lit_matrix) = value.pointer("/ConstantAbstract/AbsLitMatrix") {
140
            parser_trace!(".. found JSON pointer /ConstantAbstract/AbsLitMatrix");
140
            let (domain_name, domain_value) = const_abs_lit_matrix
140
                .pointer("/0")
140
                .and_then(Value::as_object)
140
                .and_then(|x| x.iter().next())
140
                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing domain"))?;
140
            let values = const_abs_lit_matrix
140
                .pointer("/1")
140
                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing values"))?;
140
            Some((values, domain_name, domain_value))
        } else {
40
            None
        }
732
        .ok_or(error!("Could not parse abstract literal matrix"))?;
692
    parser_trace!(".. found in domain and values in JSON:");
692
    parser_trace!(".. .. index domain name {domain_name}");
692
    parser_trace!(".. .. values {value}");
692
    let args_parsed = values
692
        .as_array()
692
        .ok_or(error!("Matrix values are not an array"))?
        .iter()
1872
        .map(|x| parse_expression(x, scope))
        .collect::<Result<Vec<Expression>>>()?;
692
    if !args_parsed.is_empty() {
692
        parser_trace!(
            ".. successfully parsed values as expressions: {}, ... ",
576
            args_parsed[0]
        );
    } else {
        parser_trace!(".. successfully parsed empty values ",);
    }
692
    let mut symbols = scope.write();
692
    match parse_domain(domain_name, domain_value, &mut symbols) {
        Ok(domain) => {
692
            parser_trace!("... sucessfully parsed domain as {domain}");
692
            Ok(into_matrix_expr![args_parsed;domain])
        }
        Err(_) => {
            parser_trace!("... failed to parse domain, creating a matrix without one.");
            Ok(into_matrix_expr![args_parsed])
        }
    }
732
}
28816
fn parse_constant(
28816
    constant: &serde_json::Map<String, Value>,
28816
    scope: &SymbolTablePtr,
28816
) -> Result<Expression> {
28816
    match &constant.get("Constant") {
24219
        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
22800
            let int_32: i32 = match int["ConstantInt"]
22800
                .as_array()
22800
                .ok_or(error!("ConstantInt is not an array"))?[1]
                .as_i64()
22800
                .ok_or(error!("ConstantInt does not contain int"))?
                .try_into()
            {
22800
                Ok(x) => x,
                Err(_) => return Err(error!("ConstantInt cannot be represented as i32")),
            };
22800
            Ok(Expression::Atomic(
22800
                Metadata::new(),
22800
                Atom::Literal(Literal::Int(int_32)),
22800
            ))
        }
1419
        Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
149
            let b: bool = b["ConstantBool"]
149
                .as_bool()
149
                .ok_or(error!("ConstantBool does not contain bool"))?;
149
            Ok(Expression::Atomic(
149
                Metadata::new(),
149
                Atom::Literal(Literal::Bool(b)),
149
            ))
        }
1270
        Some(Value::Object(int)) if int.contains_key("ConstantAbstract") => {
1270
            if let Some(Value::Object(obj)) = int.get("ConstantAbstract") {
1270
                if let Some(arr) = obj.get("AbsLitSet") {
534
                    return parse_abs_lit(arr, scope);
736
                } else if let Some(arr) = obj.get("AbsLitMSet") {
58
                    return parse_abs_mset(arr, scope);
678
                } else if let Some(arr) = obj.get("AbsLitMatrix") {
40
                    return parse_abstract_matrix_as_expr(arr, scope);
638
                } else if let Some(arr) = obj.get("AbsLitTuple") {
116
                    return parse_abs_tuple(arr, scope);
522
                } else if let Some(arr) = obj.get("AbsLitRecord") {
58
                    return parse_abs_record(arr, scope);
464
                } else if let Some(arr) = obj.get("AbsLitPartition") {
58
                    return parse_abs_partition(arr, scope);
406
                } else if let Some(arr) = obj.get("AbsLitPermutation") {
                    return parse_abs_permutation(arr, scope);
406
                } else if let Some(arr) = obj.get("AbsLitFunction") {
116
                    return parse_abs_function(arr, scope);
290
                } else if let Some(arr) = obj.get("AbsLitVariant") {
                    return parse_abs_variant(arr, scope);
290
                } else if let Some(arr) = obj.get("AbsLitRelation") {
116
                    return parse_abs_relation(arr, scope);
174
                } else if let Some(arr) = obj.get("AbsLitSequence") {
174
                    return parse_abs_sequence(arr, scope);
                }
            }
            Err(error!("Unhandled ConstantAbstract literal type"))
        }
        // sometimes (e.g. constant matrices) we can have a ConstantInt / Constant bool that is
        // not wrapped in Constant
        None => {
4597
            let int_expr = constant
4597
                .get("ConstantInt")
4307
                .and_then(|x| x.as_array())
4307
                .and_then(|x| x[1].as_i64())
4307
                .and_then(|x| x.try_into().ok())
4307
                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
4597
            if let Some(expr) = int_expr {
4307
                return Ok(expr);
290
            }
290
            let bool_expr = constant
290
                .get("ConstantBool")
290
                .and_then(|x| x.as_bool())
290
                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
290
            if let Some(expr) = bool_expr {
290
                return Ok(expr);
            }
            Err(error!(format!("Unhandled parse_constant {constant:#?}")))
        }
        otherwise => Err(error!(format!("Unhandled parse_constant {otherwise:#?}"))),
    }
28816
}
#[cfg(test)]
mod tests {
    use super::*;
    use crate::ast::HasDomain;
    use crate::{domain_int, range};
    use serde_json::json;
    #[test]
1
    fn parses_record_index() {
1
        let scope = SymbolTablePtr::new();
1
        scope.write().insert(DeclarationPtr::new_find(
1
            Name::user("x"),
1
            Domain::record(vec![Field {
1
                name: Name::user("a"),
1
                value: Domain::bool(),
1
            }]),
1
        ));
1
        let value = json!({
1
            "Op": {
1
                "MkOpIndexing": [
                    {
1
                        "Reference": [
                            {
1
                                "Name": "x"
                            },
                            null
                        ]
                    },
                    {
1
                        "Reference": [
                            {
1
                                "Name": "a"
                            },
                            null
                        ]
                    }
                ]
            }
        });
1
        let expr = parse_expression(&value, &scope).expect("record index should parse");
1
        let Expression::RecordField(_, rec_expr, field_name) = expr else {
            panic!("expected record field access");
        };
1
        let Expression::Atomic(_, Atom::Reference(re)) = rec_expr.as_ref() else {
            panic!("expected LHS to be a record reference");
        };
1
        assert_eq!(re.name().clone(), Name::user("x"));
1
        assert!(re.domain_of().as_record().is_some());
1
        assert_eq!(field_name, Name::user("a"));
1
    }
    #[test]
1
    fn parses_nested_constant_abstract_sets() {
1
        let scope = SymbolTablePtr::new();
1
        let value = json!({
1
            "ConstantAbstract": {
1
                "AbsLitSet": [
                    {
1
                        "ConstantAbstract": {
1
                            "AbsLitSet": [
1
                                { "ConstantInt": [{ "TagInt": [] }, 1] },
1
                                { "ConstantInt": [{ "TagInt": [] }, 2] }
                            ]
                        }
                    },
                    {
1
                        "ConstantAbstract": {
1
                            "AbsLitSet": [
1
                                { "ConstantInt": [{ "TagInt": [] }, 3] }
                            ]
                        }
                    }
                ]
            }
        });
1
        let expr = parse_expression(&value, &scope).expect("nested constant sets should parse");
1
        let Expression::AbstractLiteral(_, AbstractLiteral::Set(outer_values)) = expr else {
            panic!("expected an outer set literal");
        };
1
        assert_eq!(outer_values.len(), 2);
2
        assert!(outer_values.iter().all(|value| matches!(
2
            value,
            Expression::AbstractLiteral(_, AbstractLiteral::Set(_))
        )));
1
    }
    #[test]
1
    fn parses_abstract_literal_wrapped_partition_with_non_constant_elements() {
        // Conjure emits a partition literal under the bare `AbstractLiteral` wrapper (rather
        // than `Constant`/`ConstantAbstract`) whenever one of its elements is not itself a
        // constant, e.g. `partition({x,2},{y,4})` where x, y are decision variables. Captured
        // verbatim (modulo whitespace) from `conjure pretty --output-format=astjson` on such a
        // model.
1
        let scope = SymbolTablePtr::new();
1
        scope
1
            .write()
1
            .insert(DeclarationPtr::new_find(Name::user("x"), domain_int!(1..4)));
1
        scope
1
            .write()
1
            .insert(DeclarationPtr::new_find(Name::user("y"), domain_int!(1..4)));
1
        let value = json!({
1
            "AbstractLiteral": {
1
                "AbsLitPartition": [
                    [
1
                        { "Reference": [{ "Name": "x" }, null] },
1
                        { "Constant": { "ConstantInt": [{ "TagInt": [] }, 2] } }
                    ],
                    [
1
                        { "Reference": [{ "Name": "y" }, null] },
1
                        { "Constant": { "ConstantInt": [{ "TagInt": [] }, 4] } }
                    ]
                ]
            }
        });
1
        let expr = parse_expression(&value, &scope)
1
            .expect("AbstractLiteral-wrapped partition should parse");
1
        let Expression::AbstractLiteral(_, AbstractLiteral::Partition(parts)) = expr else {
            panic!("expected a partition literal, got {expr:?}");
        };
1
        assert_eq!(parts.len(), 2);
1
        assert_eq!(parts[0].len(), 2);
1
        assert_eq!(parts[1].len(), 2);
1
    }
}