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::Moo;
11
use crate::ast::PartitionAttr;
12
use crate::ast::Typeable;
13
use crate::ast::ac_operators::ACOperatorKind;
14
use crate::ast::comprehension::ComprehensionBuilder;
15
use crate::ast::records::Field;
16
use crate::ast::{
17
    AbstractLiteral, Atom, BinaryAttr, DeclarationPtr, Domain, Expression, FuncAttr, IntVal,
18
    JectivityAttr, Literal, MSetAttr, Name, PartialityAttr, Range, RelAttr, ReturnType,
19
    SequenceAttr, SetAttr, SymbolTable, SymbolTablePtr,
20
};
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
22088
pub fn model_from_json(str: &str, context: Arc<RwLock<Context<'static>>>) -> Result<Model> {
41
22088
    let mut m = Model::new(context);
42
22088
    let v: JsonValue = serde_json::from_str(str)?;
43
22088
    let statements = v["mStatements"]
44
22088
        .as_array()
45
22088
        .ok_or(error!("mStatements is not an array"))?;
46

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

            
55
65748
        match entry.0.as_str() {
56
65748
            "Declaration" => {
57
46196
                let decl = entry
58
46196
                    .1
59
46196
                    .as_object()
60
46196
                    .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
46196
                let mut valid_decl: bool = false;
69
46196
                let scope = m.symbols_ptr_unchecked().clone();
70
46196
                let model = &mut m;
71
46196
                for (kind, value) in decl {
72
46196
                    match kind.as_str() {
73
46196
                        "FindOrGiven" => {
74
41860
                            parse_variable(value, &mut model.symbols_mut())?;
75
41820
                            valid_decl = true;
76
41820
                            break;
77
                        }
78
4336
                        "Letting" => {
79
4336
                            parse_letting(value, &scope)?;
80
4316
                            valid_decl = true;
81
4316
                            break;
82
                        }
83
                        _ => continue,
84
                    }
85
                }
86

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

            
97
19552
                let constraints: Vec<Expression> = constraints_arr
98
19552
                    .iter()
99
29740
                    .map(|x| parse_expression(x, m.symbols_ptr_unchecked()))
100
19552
                    .collect::<Result<Vec<_>>>()?;
101
19552
                m.add_constraints(constraints);
102
            }
103
            otherwise => bug!("Unhandled Statement {:#?}", otherwise),
104
        }
105
    }
106
22028
    Ok(m)
107
22088
}
108

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

            
112
41860
    let variable_type = arr[0]
113
41860
        .as_str()
114
41860
        .ok_or(error!("FindOrGiven[0] is not a string"))?;
115

            
116
41860
    let name = arr[1]
117
41860
        .as_object()
118
41860
        .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
119
41860
        .as_str()
120
41860
        .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
121

            
122
41860
    let name = Name::User(Ustr::from(name));
123

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

            
131
41860
    let domain = parse_domain(domain.0, domain.1, symtab)?;
132

            
133
41820
    let decl = match variable_type {
134
41820
        "Find" => DeclarationPtr::new_find(name.clone(), domain),
135
256
        "Given" => DeclarationPtr::new_given(name.clone(), domain),
136
        _ => {
137
            return Err(error!("FindOrGiven[0] is not 'Find' or 'Given'"));
138
        }
139
    };
140

            
141
41820
    symtab.insert(decl).ok_or(Error::Parse(format!(
142
41820
        "Could not add {name} to symbol table as it already exists"
143
41820
    )))
144
41860
}
145

            
146
4336
fn parse_letting(v: &JsonValue, scope: &SymbolTablePtr) -> Result<()> {
147
4336
    let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
148
4336
    let name = arr[0]
149
4336
        .as_object()
150
4336
        .ok_or(error!("Letting[0] is not an object"))?["Name"]
151
4336
        .as_str()
152
4336
        .ok_or(error!("Letting[0].Name is not a string"))?;
153
4336
    let name = Name::User(Ustr::from(name));
154
    // value letting
155
4336
    if let Ok(value) = parse_expression(&arr[1], scope) {
156
3676
        let mut symtab = scope.write();
157
3676
        symtab
158
3676
            .insert(DeclarationPtr::new_value_letting(name.clone(), value))
159
3676
            .ok_or(Error::Parse(format!(
160
3676
                "Could not add {name} to symbol table as it already exists"
161
3676
            )))
162
    } else {
163
        // domain letting
164
660
        let domain = &arr[1]
165
660
            .as_object()
166
660
            .ok_or(error!("Letting[1] is not an object".to_owned()))?["Domain"]
167
660
            .as_object()
168
660
            .ok_or(error!("Letting[1].Domain is not an object"))?
169
660
            .iter()
170
660
            .next()
171
660
            .ok_or(error!("Letting[1].Domain is an empty object"))?;
172

            
173
660
        let mut symtab = scope.write();
174
660
        let domain = parse_domain(domain.0, domain.1, &mut symtab)?;
175

            
176
660
        symtab
177
660
            .insert(DeclarationPtr::new_domain_letting(name.clone(), domain))
178
660
            .ok_or(Error::Parse(format!(
179
660
                "Could not add {name} to symbol table as it already exists"
180
660
            )))
181
    }
182
4336
}
183

            
184
78988
fn parse_domain(
185
78988
    domain_name: &str,
186
78988
    domain_value: &JsonValue,
187
78988
    symbols: &mut SymbolTable,
188
78988
) -> Result<DomainPtr> {
189
78988
    match domain_name {
190
78988
        "DomainInt" => Ok(parse_int_domain(domain_value, symbols)?),
191
18812
        "DomainBool" => Ok(Domain::bool()),
192
9672
        "DomainReference" => {
193
1196
            let name = Name::user(
194
1196
                domain_value
195
1196
                    .as_array()
196
1196
                    .ok_or(error!("DomainReference is not an array"))?[0]
197
1196
                    .as_object()
198
1196
                    .ok_or(error!("DomainReference[0] is not an object"))?["Name"]
199
1196
                    .as_str()
200
1196
                    .ok_or(error!("DomainReference[0].Name is not a string"))?,
201
            );
202
1196
            let ptr = symbols
203
1196
                .lookup(&name)
204
1196
                .ok_or(error!(format!("Name {name} not found")))?;
205
1196
            let dom =
206
1196
                Domain::reference(ptr).ok_or(error!("Could not construct reference domain"))?;
207
1196
            Ok(dom)
208
        }
209
8476
        "DomainSet" => {
210
776
            let dom = domain_value.get(2).and_then(|v| v.as_object());
211
776
            let domain_obj = dom.ok_or(error!("DomainSet is missing domain object"))?;
212
776
            let domain = domain_obj
213
776
                .iter()
214
776
                .next()
215
776
                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
216
776
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
217
776
            let size = domain_value
218
776
                .get(1)
219
776
                .and_then(|v| v.as_object())
220
776
                .ok_or(error!("Set size attributes is not an object"))?;
221
776
            let size = parse_size_attr(size, symbols)?;
222
776
            let attr: SetAttr<IntVal> = SetAttr { size };
223
776
            Ok(Domain::set(attr, domain))
224
        }
225
7700
        "DomainMSet" => {
226
484
            let dom = domain_value
227
484
                .get(2)
228
484
                .and_then(|v| v.as_object())
229
484
                .expect("domain object exists");
230
484
            let domain = dom
231
484
                .iter()
232
484
                .next()
233
484
                .ok_or(Error::Parse("DomainMSet is an empty object".to_owned()))?;
234
484
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
235

            
236
            // Parse Attributes
237
484
            let attributes = domain_value
238
484
                .get(1)
239
484
                .and_then(|v| v.as_array())
240
484
                .ok_or(error!("MSet attributes is not a json array"))?;
241

            
242
484
            let size = attributes
243
484
                .first()
244
484
                .and_then(|v| v.as_object())
245
484
                .ok_or(error!("MSet size attributes is not an object"))?;
246
484
            let size = parse_size_attr(size, symbols)?;
247

            
248
484
            let occurrence = attributes
249
484
                .get(1)
250
484
                .and_then(|v| v.as_object())
251
484
                .ok_or(error!("MSet occurrence attributes is not an object"))?;
252
484
            let occurrence = parse_occur_attr(occurrence, symbols)?;
253

            
254
484
            let attr: MSetAttr<IntVal> = MSetAttr { size, occurrence };
255
484
            Ok(Domain::mset(attr, domain))
256
        }
257
7216
        "DomainPartition" => {
258
376
            let dom = domain_value
259
376
                .get(2)
260
376
                .and_then(|v| v.as_object())
261
376
                .expect("domain object exists");
262
376
            let domain = dom.iter().next().ok_or(Error::Parse(
263
376
                "DomainPartition is an empty object".to_owned(),
264
376
            ))?;
265
376
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
266

            
267
376
            let attributes = domain_value
268
376
                .get(1)
269
376
                .and_then(|v| v.as_object())
270
376
                .ok_or(error!("Partition attributes is not an object"))?;
271

            
272
376
            let mut num_parts = Range::Unbounded;
273
376
            let mut part_len = Range::Unbounded;
274
376
            let mut is_regular = false;
275

            
276
376
            if let Some(val) = attributes.get("partsNum") {
277
376
                let attr_map = val.as_object().expect("numParts should be an object");
278
376
                num_parts = parse_size_attr(attr_map, symbols)?;
279
            }
280
376
            if let Some(val) = attributes.get("partsSize") {
281
376
                let attr_map = val.as_object().expect("partsSize should be an object");
282
376
                part_len = parse_size_attr(attr_map, symbols)?;
283
            }
284
376
            if let Some(val) = attributes.get("isRegular").and_then(|v| v.as_bool()) {
285
376
                is_regular = val;
286
376
            }
287

            
288
376
            let attr: PartitionAttr<IntVal> = PartitionAttr {
289
376
                num_parts,
290
376
                part_len,
291
376
                is_regular,
292
376
            };
293
376
            Ok(Domain::partition(attr, domain))
294
        }
295
6840
        "DomainMatrix" => {
296
4292
            let domain_value = domain_value
297
4292
                .as_array()
298
4292
                .ok_or(error!("Domain matrix is not an array"))?;
299

            
300
4292
            let indexed_by_domain = domain_value[0].clone();
301
4292
            let (index_domain_name, index_domain_value) = indexed_by_domain
302
4292
                .as_object()
303
4292
                .ok_or(error!("DomainMatrix[0] is not an object"))?
304
4292
                .iter()
305
4292
                .next()
306
4292
                .ok_or(error!(""))?;
307

            
308
4292
            let (value_domain_name, value_domain_value) = domain_value[1]
309
4292
                .as_object()
310
4292
                .ok_or(error!(""))?
311
4292
                .iter()
312
4292
                .next()
313
4292
                .ok_or(error!(""))?;
314

            
315
            // Conjure stores a 2-d matrix as a matrix of a matrix.
316
            //
317
            // Therefore, the index is always a Domain.
318

            
319
4292
            let mut index_domains: Vec<DomainPtr> = vec![];
320

            
321
4292
            index_domains.push(parse_domain(
322
4292
                index_domain_name,
323
4292
                index_domain_value,
324
4292
                symbols,
325
            )?);
326

            
327
            // We want to store 2-d matrices as a matrix with two index domains, not a matrix in a
328
            // matrix.
329
            //
330
            // Walk through the value domain until it is not a DomainMatrix, adding the index to
331
            // our list of indices.
332
4292
            let mut value_domain = parse_domain(value_domain_name, value_domain_value, symbols)?;
333
5012
            while let Some((new_value_domain, mut indices)) = value_domain.as_matrix() {
334
720
                index_domains.append(&mut indices);
335
720
                value_domain = new_value_domain.clone()
336
            }
337

            
338
4292
            Ok(Domain::matrix(value_domain, index_domains))
339
        }
340

            
341
2548
        "DomainSequence" => {
342
340
            let dom = domain_value
343
340
                .get(2)
344
340
                .and_then(|v| v.as_object())
345
340
                .expect("domain object exists");
346
340
            let domain = dom
347
340
                .iter()
348
340
                .next()
349
340
                .ok_or(Error::Parse("DomainSequence is an empty object".to_owned()))?;
350
340
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
351

            
352
            // Parse Attributes
353
340
            let attributes = domain_value
354
340
                .get(1)
355
340
                .and_then(|v| v.as_array())
356
340
                .ok_or(error!("Sequence attributes is not a json array"))?;
357

            
358
340
            let size = attributes
359
340
                .first()
360
340
                .and_then(|v| v.as_object())
361
340
                .ok_or(error!("Sequence size attributes is not an object"))?;
362
340
            let size = parse_size_attr(size, symbols)?;
363

            
364
340
            let jectivity = attributes
365
340
                .get(1)
366
340
                .and_then(|v| v.as_str())
367
340
                .ok_or(error!("jectivity is not a string"))?;
368
340
            let jectivity = match jectivity {
369
340
                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
370
140
                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
371
100
                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
372
60
                "JectivityAttr_None" => Some(JectivityAttr::None),
373
                _ => None,
374
            };
375
340
            let jectivity =
376
340
                jectivity.ok_or(Error::Parse("Jectivity is an unknown type".to_owned()))?;
377

            
378
340
            let attr: SequenceAttr<IntVal> = SequenceAttr { size, jectivity };
379
340
            match attr.size {
380
20
                Range::Unbounded | Range::UnboundedR(_) => Err(Error::Parse(
381
20
                    "Sequence must have size or maxSize attribute".to_string(),
382
20
                )),
383
320
                _ => Ok(Domain::sequence(attr, domain)),
384
            }
385
        }
386

            
387
2208
        "DomainTuple" => {
388
600
            let domain_value = domain_value
389
600
                .as_array()
390
600
                .ok_or(error!("Domain tuple is not an array"))?;
391

            
392
            //iterate through the array and parse each domain
393
600
            let domain = domain_value
394
600
                .iter()
395
1240
                .map(|x| {
396
1240
                    let domain = x
397
1240
                        .as_object()
398
1240
                        .ok_or(error!("DomainTuple[0] is not an object"))?
399
1240
                        .iter()
400
1240
                        .next()
401
1240
                        .ok_or(error!("DomainTuple[0] is an empty object"))?;
402
1240
                    parse_domain(domain.0, domain.1, symbols)
403
1240
                })
404
600
                .collect::<Result<Vec<DomainPtr>>>()?;
405

            
406
600
            Ok(Domain::tuple(domain))
407
        }
408
1608
        "DomainRecord" | "DomainVariant" => {
409
            // Records and Variants can be parsed the same way for the most part
410
320
            let is_record = domain_name == "DomainRecord";
411
            // Get the actual string for error message purposes
412
320
            let domain_string = match is_record {
413
120
                true => "Record",
414
200
                false => "Variant",
415
            };
416
320
            let domain_value = domain_value.as_array().ok_or(error!(&format!(
417
320
                "Domain {domain_string} is not a json array"
418
320
            )))?;
419

            
420
320
            let mut entries = vec![];
421

            
422
720
            for item in domain_value {
423
                //collect the name of the field
424
720
                let name = item[0]
425
720
                    .as_object()
426
720
                    .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
427
720
                    .as_str()
428
720
                    .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
429

            
430
720
                let name = Name::User(Ustr::from(name));
431
                // then collect the domain of the field
432
720
                let domain = item[1]
433
720
                    .as_object()
434
720
                    .ok_or(error!("FindOrGiven[2] is not an object"))?
435
720
                    .iter()
436
720
                    .next()
437
720
                    .ok_or(error!("FindOrGiven[2] is an empty object"))?;
438

            
439
720
                let rec = Field {
440
720
                    name,
441
720
                    value: parse_domain(domain.0, domain.1, symbols)?,
442
                };
443

            
444
720
                entries.push(rec);
445
            }
446

            
447
320
            if is_record {
448
120
                Ok(Domain::record(entries))
449
            } else {
450
200
                Ok(Domain::variant(entries))
451
            }
452
        }
453
1288
        "DomainFunction" => {
454
796
            let domain = domain_value
455
796
                .get(2)
456
796
                .and_then(|v| v.as_object())
457
796
                .ok_or(error!("Function domain is not an object"))?;
458
796
            let domain = domain
459
796
                .iter()
460
796
                .next()
461
796
                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
462
796
            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
463

            
464
796
            let codomain = domain_value
465
796
                .get(3)
466
796
                .and_then(|v| v.as_object())
467
796
                .ok_or(error!("Function codomain is not an object"))?;
468
796
            let codomain = codomain
469
796
                .iter()
470
796
                .next()
471
796
                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
472
796
            let codomain = parse_domain(codomain.0.as_str(), codomain.1, symbols)?;
473

            
474
            // Attribute parsing
475
796
            let attributes = domain_value
476
796
                .get(1)
477
796
                .and_then(|v| v.as_array())
478
796
                .ok_or(error!("Function attributes is not a json array"))?;
479
796
            let size = attributes
480
796
                .first()
481
796
                .and_then(|v| v.as_object())
482
796
                .ok_or(error!("Function size attributes is not an object"))?;
483
796
            let size = parse_size_attr(size, symbols)?;
484
796
            let partiality = attributes
485
796
                .get(1)
486
796
                .and_then(|v| v.as_str())
487
796
                .ok_or(error!("Function partiality is not a string"))?;
488
796
            let partiality = match partiality {
489
796
                "PartialityAttr_Partial" => Some(PartialityAttr::Partial),
490
92
                "PartialityAttr_Total" => Some(PartialityAttr::Total),
491
                _ => None,
492
            };
493
796
            let partiality =
494
796
                partiality.ok_or(Error::Parse("Partiality is an unknown type".to_owned()))?;
495
796
            let jectivity = attributes
496
796
                .get(2)
497
796
                .and_then(|v| v.as_str())
498
796
                .ok_or(error!("Function jectivity is not a string"))?;
499
796
            let jectivity = match jectivity {
500
796
                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
501
668
                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
502
604
                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
503
548
                "JectivityAttr_None" => Some(JectivityAttr::None),
504
                _ => None,
505
            };
506
796
            let jectivity =
507
796
                jectivity.ok_or(Error::Parse("Jectivity is an unknown type".to_owned()))?;
508

            
509
796
            let attr: FuncAttr<IntVal> = FuncAttr {
510
796
                size,
511
796
                partiality,
512
796
                jectivity,
513
796
            };
514

            
515
796
            Ok(Domain::function(attr, domain, codomain))
516
        }
517

            
518
492
        "DomainRelation" => {
519
492
            let domains = domain_value
520
492
                .get(2)
521
492
                .and_then(|v| v.as_array())
522
492
                .ok_or(Error::Parse(
523
492
                    "Relation domains are not a json array".to_owned(),
524
492
                ))?;
525
492
            let domains = domains
526
492
                .iter()
527
1112
                .map(|x| {
528
1112
                    let domain = x
529
1112
                        .as_object()
530
1112
                        .ok_or(Error::Parse("Relation domain is not an object".to_owned()))?
531
1112
                        .iter()
532
1112
                        .next()
533
1112
                        .ok_or(Error::Parse(
534
1112
                            "Relation domain is an empty object".to_owned(),
535
1112
                        ))?;
536
1112
                    parse_domain(domain.0, domain.1, symbols)
537
1112
                })
538
492
                .collect::<Result<Vec<DomainPtr>>>()?;
539

            
540
            // Attribute parsing
541
492
            let attributes = domain_value
542
492
                .get(1)
543
492
                .and_then(|v| v.as_array())
544
492
                .ok_or(Error::Parse(
545
492
                    "Relation attributes are not a json array".to_owned(),
546
492
                ))?;
547
492
            let size = attributes
548
492
                .first()
549
492
                .and_then(|v| v.as_object())
550
492
                .ok_or(Error::Parse(
551
492
                    "Relation size attributes are not an object".to_owned(),
552
492
                ))?;
553
492
            let size = parse_size_attr(size, symbols)?;
554
492
            let binary = attributes
555
492
                .get(1)
556
492
                .and_then(|v| v.as_array())
557
492
                .ok_or(Error::Parse(
558
492
                    "Relation binary attributes are not a json array".to_owned(),
559
492
                ))?;
560
492
            let binary = binary
561
492
                .iter()
562
532
                .map(|x| {
563
520
                    let attr = x.as_str().ok_or(Error::Parse(
564
520
                        "Relation binary attribute is not a string".to_owned(),
565
520
                    ))?;
566
520
                    match attr {
567
520
                        "BinRelAttr_Reflexive" => Ok(BinaryAttr::Reflexive),
568
480
                        "BinRelAttr_Irreflexive" => Ok(BinaryAttr::Irreflexive),
569
440
                        "BinRelAttr_Coreflexive" => Ok(BinaryAttr::Coreflexive),
570
400
                        "BinRelAttr_Symmetric" => Ok(BinaryAttr::Symmetric),
571
360
                        "BinRelAttr_AntiSymmetric" => Ok(BinaryAttr::AntiSymmetric),
572
320
                        "BinRelAttr_ASymmetric" => Ok(BinaryAttr::ASymmetric),
573
280
                        "BinRelAttr_Transitive" => Ok(BinaryAttr::Transitive),
574
240
                        "BinRelAttr_Total" => Ok(BinaryAttr::Total),
575
200
                        "BinRelAttr_Connex" => Ok(BinaryAttr::Connex),
576
160
                        "BinRelAttr_Euclidean" => Ok(BinaryAttr::Euclidean),
577
120
                        "BinRelAttr_Serial" => Ok(BinaryAttr::Serial),
578
80
                        "BinRelAttr_Equivalence" => Ok(BinaryAttr::Equivalence),
579
40
                        "BinRelAttr_PartialOrder" => Ok(BinaryAttr::PartialOrder),
580
                        _ => Err(Error::Parse(
581
                            "Relation binary attribute is invalid".to_owned(),
582
                        )),
583
                    }
584
520
                })
585
492
                .collect::<Result<Vec<BinaryAttr>>>()?;
586

            
587
492
            let attr: RelAttr<IntVal> = RelAttr { size, binary };
588

            
589
492
            Ok(Domain::relation(attr, domains))
590
        }
591
        _ => Err(Error::Parse(
592
            "FindOrGiven[2] is an unknown object".to_owned(), // consider covered
593
        )),
594
    }
595
78988
}
596

            
597
3640
fn parse_size_attr(
598
3640
    attr_map: &JsonMap<String, JsonValue>,
599
3640
    symbols: &mut SymbolTable,
600
3640
) -> Result<Range<IntVal>> {
601
3640
    let scope = SymbolTablePtr::new();
602
3640
    *scope.write() = symbols.clone();
603

            
604
3640
    let attr_obj = attr_map
605
3640
        .iter()
606
3640
        .next()
607
3640
        .ok_or(Error::Parse("SizeAttr is an empty object".to_owned()))?;
608
3640
    match attr_obj.0.as_str() {
609
3640
        "SizeAttr_None" => Ok(Range::Unbounded),
610
1652
        "SizeAttr_MinSize" => {
611
532
            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
612
532
            Ok(Range::UnboundedR(size))
613
        }
614
1120
        "SizeAttr_MaxSize" => {
615
328
            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
616
328
            Ok(Range::UnboundedL(size))
617
        }
618
792
        "SizeAttr_MinMaxSize" => {
619
308
            let min_max = attr_obj
620
308
                .1
621
308
                .as_array()
622
308
                .ok_or(error!("SizeAttr MinMaxSize is not a json array"))?;
623
308
            let min = min_max
624
308
                .first()
625
308
                .ok_or(error!("SizeAttr Min is not present"))?;
626
308
            let min_int = parse_expression_to_int_val(min, &scope)?;
627
308
            let max = min_max
628
308
                .get(1)
629
308
                .ok_or(error!("SizeAttr Max is not present"))?;
630
308
            let max_int = parse_expression_to_int_val(max, &scope)?;
631
308
            Ok(Range::Bounded(min_int, max_int))
632
        }
633
484
        "SizeAttr_Size" => {
634
484
            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
635
484
            Ok(Range::Single(size))
636
        }
637
        _ => Err(Error::Parse("SizeAttr is an unknown type".to_owned())),
638
    }
639
3640
}
640

            
641
484
fn parse_occur_attr(
642
484
    attr_map: &JsonMap<String, JsonValue>,
643
484
    symbols: &mut SymbolTable,
644
484
) -> Result<Range<IntVal>> {
645
484
    let scope = SymbolTablePtr::new();
646
484
    *scope.write() = symbols.clone();
647
484
    let attr_obj = attr_map
648
484
        .iter()
649
484
        .next()
650
484
        .ok_or(Error::Parse("OccurAttr is an empty object".to_owned()))?;
651
484
    match attr_obj.0.as_str() {
652
484
        "OccurAttr_None" => Ok(Range::Unbounded),
653
324
        "OccurAttr_MinOccur" => {
654
40
            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
655
40
            Ok(Range::UnboundedR(size_int))
656
        }
657
284
        "OccurAttr_MaxOccur" => {
658
204
            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
659
204
            Ok(Range::UnboundedL(size_int))
660
        }
661
80
        "OccurAttr_MinMaxOccur" => {
662
80
            let min_max = attr_obj
663
80
                .1
664
80
                .as_array()
665
80
                .ok_or(error!("OccurAttr MinMaxOccur is not a json array"))?;
666
80
            let min = min_max
667
80
                .first()
668
80
                .ok_or(error!("OccurAttr Min is not present"))?;
669
80
            let min_int = parse_expression_to_int_val(min, &scope)?;
670
80
            let max = min_max
671
80
                .get(1)
672
80
                .ok_or(error!("OccurAttr Max is not present"))?;
673
80
            let max_int = parse_expression_to_int_val(max, &scope)?;
674
80
            Ok(Range::Bounded(min_int, max_int))
675
        }
676
        "OccurAttr_Size" => {
677
            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
678
            Ok(Range::Single(size_int))
679
        }
680
        _ => Err(Error::Parse("OccurAttr is an unknown type".to_owned())),
681
    }
682
484
}
683

            
684
60176
fn parse_int_domain(v: &JsonValue, symbols: &SymbolTable) -> Result<DomainPtr> {
685
60176
    let scope = SymbolTablePtr::new();
686
60176
    *scope.write() = symbols.clone();
687

            
688
60176
    let mut ranges = Vec::new();
689
60176
    let arr = v
690
60176
        .as_array()
691
60176
        .ok_or(error!("DomainInt is not an array".to_owned()))?[1]
692
60176
        .as_array()
693
60176
        .ok_or(error!("DomainInt[1] is not an array".to_owned()))?;
694
62376
    for range in arr {
695
62232
        let range = range
696
62232
            .as_object()
697
62232
            .ok_or(error!("DomainInt[1] contains a non-object"))?
698
62232
            .iter()
699
62232
            .next()
700
62232
            .ok_or(error!("DomainInt[1] contains an empty object"))?;
701
62232
        match range.0.as_str() {
702
62232
            "RangeBounded" => {
703
58480
                let arr = range
704
58480
                    .1
705
58480
                    .as_array()
706
58480
                    .ok_or(error!("RangeBounded is not an array".to_owned()))?;
707
58480
                let mut nums = Vec::new();
708
116960
                for item in arr.iter() {
709
116960
                    let num = parse_expression_to_int_val(item, &scope)?;
710
116960
                    nums.push(num);
711
                }
712
58480
                let lower = nums
713
58480
                    .first()
714
58480
                    .cloned()
715
58480
                    .ok_or(error!("RangeBounded lower bound missing"))?;
716
58480
                let upper = nums
717
58480
                    .get(1)
718
58480
                    .cloned()
719
58480
                    .ok_or(error!("RangeBounded upper bound missing"))?;
720
58480
                ranges.push(Range::Bounded(lower, upper));
721
            }
722
3752
            "RangeSingle" => {
723
3732
                let num = parse_expression_to_int_val(range.1, &scope)?;
724
3732
                ranges.push(Range::Single(num));
725
            }
726
20
            _ => return throw_error!("DomainInt[1] contains an unknown object"),
727
        }
728
    }
729
60156
    Ok(Domain::int(ranges))
730
60176
}
731

            
732
123056
fn parse_expression_to_int_val(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<IntVal> {
733
123056
    parser_trace!("trying to parse domain value as expression: {}", obj);
734
123056
    let expr = parse_expression(obj, scope)?;
735

            
736
123056
    if let Some(Literal::Int(i)) = expr.clone().into_literal() {
737
119668
        return Ok(IntVal::Const(i as i64));
738
3388
    }
739

            
740
2172
    if let Expression::Atomic(_, Atom::Reference(reference)) = &expr
741
2172
        && let Ok(reference_val) = IntVal::new_ref(reference)
742
    {
743
2172
        return Ok(reference_val);
744
1216
    }
745

            
746
1216
    IntVal::new_expr(Moo::new(expr))
747
1216
        .map_err(|e| error!(format!("Could not parse integer expression: {e}")))
748
123056
}
749

            
750
type BinOp = fn(Metadata, Moo<Expression>, Moo<Expression>) -> Expression;
751
type UnaryOp = fn(Metadata, Moo<Expression>) -> Expression;
752

            
753
110212
fn binary_operator(op_name: &str) -> Option<BinOp> {
754
110212
    match op_name {
755
110212
        "MkOpIn" => Some(Expression::In),
756
109572
        "MkOpUnion" => Some(Expression::Union),
757
109252
        "MkOpIntersect" => Some(Expression::Intersect),
758
108972
        "MkOpSupset" => Some(Expression::Supset),
759
108652
        "MkOpSupsetEq" => Some(Expression::SupsetEq),
760
108332
        "MkOpSubset" => Some(Expression::Subset),
761
107932
        "MkOpSubsetEq" => Some(Expression::SubsetEq),
762
107540
        "MkOpEq" => Some(Expression::Eq),
763
77540
        "MkOpNeq" => Some(Expression::Neq),
764
72020
        "MkOpGeq" => Some(Expression::Geq),
765
68220
        "MkOpLeq" => Some(Expression::Leq),
766
60956
        "MkOpGt" => Some(Expression::Gt),
767
58372
        "MkOpLt" => Some(Expression::Lt),
768
54108
        "MkOpLexLt" => Some(Expression::LexLt),
769
53460
        "MkOpLexGt" => Some(Expression::LexGt),
770
53460
        "MkOpLexLeq" => Some(Expression::LexLeq),
771
52580
        "MkOpLexGeq" => Some(Expression::LexGeq),
772
52580
        "MkOpDiv" => Some(Expression::UnsafeDiv),
773
47540
        "MkOpMod" => Some(Expression::UnsafeMod),
774
45540
        "MkOpMinus" => Some(Expression::Minus),
775
41876
        "MkOpImply" => Some(Expression::Imply),
776
37868
        "MkOpIff" => Some(Expression::Iff),
777
37452
        "MkOpPow" => Some(Expression::UnsafePow),
778
34892
        "MkOpImage" => Some(Expression::Image),
779
34812
        "MkOpImageSet" => Some(Expression::ImageSet),
780
34732
        "MkOpPreImage" => Some(Expression::PreImage),
781
34564
        "MkOpInverse" => Some(Expression::Inverse),
782
34484
        "MkOpRestrict" => Some(Expression::Restrict),
783
34372
        "MkOpApart" => Some(Expression::Apart),
784
34292
        "MkOpTogether" => Some(Expression::Together),
785
34212
        "MkOpParty" => Some(Expression::Party),
786
34124
        "MkOpSubstring" => Some(Expression::Substring),
787
33964
        "MkOpSubsequence" => Some(Expression::Subsequence),
788
33964
        _ => None,
789
    }
790
110212
}
791

            
792
67928
fn unary_operator(op_name: &str, inner: Option<&Expression>) -> Option<UnaryOp> {
793
67928
    match op_name {
794
67928
        "MkOpNot" => Some(Expression::Not),
795
64088
        "MkOpNegate" => Some(Expression::Neg),
796
42808
        "MkOpTwoBars" => {
797
1872
            if let Some(inner) = inner {
798
936
                match inner.return_type() {
799
760
                    ReturnType::Int => Some(Expression::Abs),
800
                    ReturnType::Matrix(_)
801
                    | ReturnType::Set(_)
802
                    | ReturnType::MSet(_)
803
                    | ReturnType::Relation(_)
804
176
                    | ReturnType::Function(_, _) => Some(Expression::Card),
805
                    _ => None,
806
                }
807
            } else {
808
                // Internal expression cannot be known yet, so we just have to assume
809
936
                Some(Expression::Abs)
810
            }
811
        }
812
40936
        "MkOpAnd" => Some(Expression::And),
813
32952
        "MkOpSum" => Some(Expression::Sum),
814
18424
        "MkOpProduct" => Some(Expression::Product),
815
15296
        "MkOpOr" => Some(Expression::Or),
816
9360
        "MkOpMin" => Some(Expression::Min),
817
7120
        "MkOpMax" => Some(Expression::Max),
818
5080
        "MkOpAllDiff" => Some(Expression::AllDiff),
819
1176
        "MkOpToInt" => Some(Expression::ToInt),
820
744
        "MkOpDefined" => Some(Expression::Defined),
821
600
        "MkOpRange" => Some(Expression::Range),
822
432
        "MkOpFactorial" => Some(Expression::Factorial),
823
432
        "MkOpToMSet" => Some(Expression::ToMSet),
824
272
        "MkOpToRelation" => Some(Expression::ToRelation),
825
192
        "MkOpParticipants" => Some(Expression::Participants),
826
96
        "MkOpParts" => Some(Expression::Parts),
827
        _ => None,
828
    }
829
67928
}
830

            
831
82115
fn parse_reference_name(obj: &JsonValue) -> Result<Name> {
832
    // { Name: "x" } directly
833
82115
    if let Some(name) = obj.get("Name").and_then(|x| x.as_str()) {
834
40
        return Ok(Name::User(Ustr::from(name)));
835
82075
    }
836

            
837
    // {
838
    //   Reference: [
839
    //     { Name: "x" }
840
    //   ]
841
    // }
842
82075
    let ref_arr = obj["Reference"]
843
82075
        .as_array()
844
82075
        .ok_or_else(|| error!("Reference.as_array"))?;
845
82075
    let ref_obj = ref_arr
846
82075
        .first()
847
82075
        .and_then(|x| x.as_object())
848
82075
        .ok_or_else(|| error!("Reference[0].as_object"))?;
849
82075
    let name = ref_obj
850
82075
        .get("Name")
851
82075
        .and_then(|x| x.as_str())
852
82075
        .ok_or_else(|| error!("Reference[0].Name.as_str"))?;
853
82075
    Ok(Name::User(Ustr::from(name)))
854
82115
}
855

            
856
354115
pub fn parse_expression(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<Expression> {
857
354115
    let fail = |stage: &str| -> Error {
858
1456
        Error::Parse(format!(
859
1456
            "Could not parse expression at stage `{stage}` for json `{obj}`"
860
1456
        ))
861
1456
    };
862

            
863
1000
    match obj {
864
353319
        Value::Object(op) if op.contains_key("Op") => {
865
87513
            let op_obj = op
866
87513
                .get("Op")
867
87513
                .and_then(Value::as_object)
868
87513
                .ok_or_else(|| fail("Op.as_object"))?;
869
87513
            let (op_name, _) = op_obj.iter().next().ok_or_else(|| fail("Op.iter().next"))?;
870

            
871
87513
            if op_obj.contains_key("MkOpFlatten") {
872
708
                parse_flatten_op(op_obj, scope)
873
86805
            } else if op_obj.contains_key("MkOpTable") {
874
120
                parse_table_op(op_obj, scope)
875
86685
            } else if op_obj.contains_key("MkOpIndexing") || op_obj.contains_key("MkOpSlicing") {
876
14393
                parse_indexing_slicing_op(op_obj, scope)
877
72292
            } else if op_obj.contains_key("MkOpActive") {
878
40
                parse_active_op(op_obj, scope)
879
72252
            } else if op_obj.contains_key("MkOpRelationProj") {
880
44
                parse_relation_projection(op_obj, scope)
881
72208
            } else if op_obj.contains_key("MkOpToSet") {
882
120
                parse_to_set(op_obj, scope)
883
72088
            } else if binary_operator(op_name).is_some() {
884
38124
                parse_bin_op(op_obj, scope)
885
33964
            } else if unary_operator(op_name, None).is_some() {
886
33964
                parse_unary_op(op_obj, scope)
887
            } else {
888
                Err(fail("Op.unknown"))
889
            }
890
        }
891
265806
        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
892
16
            parse_comprehension(comprehension, scope.clone(), None)
893
        }
894
265790
        Value::Object(refe) if refe.contains_key("Reference") => {
895
81954
            let user_name = parse_reference_name(obj)?;
896

            
897
81954
            let declaration: DeclarationPtr = scope
898
81954
                .read()
899
81954
                .lookup(&user_name)
900
81954
                .ok_or_else(|| fail("Reference.lookup"))?;
901

            
902
81954
            Ok(Expression::Atomic(
903
81954
                Metadata::new(),
904
81954
                Atom::Reference(crate::ast::Reference::new(declaration)),
905
81954
            ))
906
        }
907
        // In the case where refering to fields. This not behind a reference
908
183836
        Value::Object(refe) if refe.contains_key("Name") => {
909
            let name = refe
910
                .get("Name")
911
                .and_then(|x| x.as_str())
912
                .ok_or_else(|| fail("Reference[0].Name.as_str"))?;
913
            let user_name = Name::User(Ustr::from(name));
914

            
915
            let declaration: DeclarationPtr = scope
916
                .read()
917
                .lookup(&user_name)
918
                .ok_or_else(|| fail("Reference.lookup"))?;
919

            
920
            Ok(Expression::Atomic(
921
                Metadata::new(),
922
                Atom::Reference(crate::ast::Reference::new(declaration)),
923
            ))
924
        }
925
183836
        Value::Object(abslit) if abslit.contains_key("AbstractLiteral") => {
926
14832
            let abstract_literal = abslit["AbstractLiteral"]
927
14832
                .as_object()
928
14832
                .ok_or_else(|| fail("AbstractLiteral.as_object"))?;
929

            
930
14832
            if abstract_literal.contains_key("AbsLitSet") {
931
80
                parse_abs_lit(&abslit["AbstractLiteral"]["AbsLitSet"], scope)
932
14752
            } else if abstract_literal.contains_key("AbsLitFunction") {
933
40
                parse_abs_function(&abslit["AbstractLiteral"]["AbsLitFunction"], scope)
934
14712
            } else if abstract_literal.contains_key("AbsLitMSet") {
935
                parse_abs_mset(&abslit["AbstractLiteral"]["AbsLitMSet"], scope)
936
14712
            } else if abstract_literal.contains_key("AbsLitVariant") {
937
40
                parse_abs_variant(&abslit["AbstractLiteral"]["AbsLitVariant"], scope)
938
14672
            } else if abstract_literal.contains_key("AbsLitRelation") {
939
                parse_abs_relation(&abslit["AbstractLiteral"]["AbsLitRelation"], scope)
940
14672
            } else if abstract_literal.contains_key("AbstractLiteralPartition") {
941
                parse_abs_partition(&abslit["AbstractLiteral"]["AbsLitPartition"], scope)
942
14672
            } else if abstract_literal.contains_key("AbsLitSequence") {
943
                parse_abs_sequence(&abslit["AbstractLiteral"]["AbsLitSequence"], scope)
944
            } else {
945
14672
                parse_abstract_matrix_as_expr(obj, scope)
946
            }
947
        }
948

            
949
169004
        Value::Object(constant) if constant.contains_key("Constant") => {
950
151464
            parse_constant(constant, scope).or_else(|_| parse_abstract_matrix_as_expr(obj, scope))
951
        }
952

            
953
17540
        Value::Object(constant) if constant.contains_key("ConstantAbstract") => {
954
820
            parse_abstract_matrix_as_expr(obj, scope)
955
        }
956

            
957
16720
        Value::Object(constant) if constant.contains_key("ConstantInt") => {
958
15720
            parse_constant(constant, scope)
959
        }
960
1000
        Value::Object(constant) if constant.contains_key("ConstantBool") => {
961
340
            parse_constant(constant, scope)
962
        }
963

            
964
1456
        _ => Err(fail("no_match")),
965
    }
966
354115
}
967

            
968
2376
fn parse_abs_lit(abs_set: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
969
2376
    let values = abs_set
970
2376
        .as_array()
971
2376
        .ok_or(error!("AbsLitSet is not an array"))?;
972
2376
    let expressions = values
973
2376
        .iter()
974
6024
        .map(|values| parse_expression(values, scope))
975
2376
        .collect::<Result<Vec<_>>>()?;
976

            
977
2376
    Ok(Expression::AbstractLiteral(
978
2376
        Metadata::new(),
979
2376
        AbstractLiteral::Set(expressions),
980
2376
    ))
981
2376
}
982

            
983
40
fn parse_abs_mset(abs_mset: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
984
40
    let values = abs_mset
985
40
        .as_array()
986
40
        .ok_or(error!("AbsLitMSet is not an array"))?;
987
40
    let expressions = values
988
40
        .iter()
989
120
        .map(|values| parse_expression(values, scope))
990
40
        .collect::<Result<Vec<_>>>()?;
991

            
992
40
    Ok(Expression::AbstractLiteral(
993
40
        Metadata::new(),
994
40
        AbstractLiteral::MSet(expressions),
995
40
    ))
996
40
}
997

            
998
40
fn parse_abs_partition(abs_partition: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
999
40
    let parts = abs_partition
40
        .as_array()
40
        .ok_or(error!("AbsLitPartition is not an array"))?;
40
    let mut partition: Vec<Vec<_>> = Vec::new();
120
    for part in parts {
120
        let vals = part
120
            .as_array()
120
            .ok_or(error!("Part in AbsLitPartition is not an array"))?;
120
        let exprs = vals
120
            .iter()
160
            .map(|values| parse_expression(values, scope))
120
            .collect::<Result<Vec<_>>>()?;
120
        partition.push(exprs);
    }
40
    Ok(Expression::AbstractLiteral(
40
        Metadata::new(),
40
        AbstractLiteral::Partition(partition),
40
    ))
40
}
120
fn parse_abs_sequence(abs_seq: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
120
    let values = abs_seq
120
        .as_array()
120
        .ok_or(error!("AbsLitSequence is not an array"))?;
120
    let expressions = values
120
        .iter()
400
        .map(|values| parse_expression(values, scope))
120
        .collect::<Result<Vec<_>>>()?;
120
    Ok(Expression::AbstractLiteral(
120
        Metadata::new(),
120
        AbstractLiteral::Sequence(expressions),
120
    ))
120
}
280
fn parse_abs_tuple(abs_tuple: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
280
    let values = abs_tuple
280
        .as_array()
280
        .ok_or(error!("AbsLitTuple is not an array"))?;
280
    let expressions = values
280
        .iter()
640
        .map(|values| parse_expression(values, scope))
280
        .collect::<Result<Vec<_>>>()?;
280
    Ok(Expression::AbstractLiteral(
280
        Metadata::new(),
280
        AbstractLiteral::Tuple(expressions),
280
    ))
280
}
//parses an abstract record as an expression
100
fn parse_abs_record(abs_record: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
100
    let entries = abs_record
100
        .as_array()
100
        .ok_or(error!("AbsLitRecord is not an array"))?;
100
    let mut rec = vec![];
200
    for entry in entries {
200
        let entry = entry
200
            .as_array()
200
            .ok_or(error!("AbsLitRecord entry is not an array"))?;
200
        let name = entry[0]
200
            .as_object()
200
            .ok_or(error!("AbsLitRecord field name is not an object"))?["Name"]
200
            .as_str()
200
            .ok_or(error!("AbsLitRecord field name is not a string"))?;
200
        let value = parse_expression(&entry[1], scope)?;
200
        let name = Name::User(Ustr::from(name));
200
        let rec_entry = Field {
200
            name: name.clone(),
200
            value,
200
        };
200
        rec.push(rec_entry);
    }
100
    Ok(Expression::AbstractLiteral(
100
        Metadata::new(),
100
        AbstractLiteral::Record(rec),
100
    ))
100
}
//parses an abstract variant as an expression
40
fn parse_abs_variant(abs_variant: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
40
    let entry = abs_variant
40
        .as_array()
40
        .ok_or(error!("AbsLitVariant is not an array"))?;
40
    let name = entry[1]
40
        .as_object()
40
        .ok_or(error!("AbsLitVariant field name is not an object"))?["Name"]
40
        .as_str()
40
        .ok_or(error!("AbsLitVariant field name is not a string"))?;
40
    let value = parse_expression(&entry[2], scope)?;
40
    let name = Name::User(Ustr::from(name));
40
    let rec_entry = Field { name, value };
40
    Ok(Expression::AbstractLiteral(
40
        Metadata::new(),
40
        AbstractLiteral::Variant(Moo::new(rec_entry)),
40
    ))
40
}
//parses an abstract function as an expression
120
fn parse_abs_function(abs_function: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
120
    let entries = abs_function
120
        .as_array()
120
        .ok_or(error!("AbsLitFunction is not an array"))?;
120
    let mut assignments = vec![];
240
    for entry in entries {
240
        let entry = entry
240
            .as_array()
240
            .ok_or(error!("Explicit function assignment is not an array"))?;
240
        let expression = entry
240
            .iter()
480
            .map(|values| parse_expression(values, scope))
240
            .collect::<Result<Vec<_>>>()?;
240
        let domain_value = expression
240
            .first()
240
            .ok_or(error!("Invalid function domain"))?;
240
        let codomain_value = expression
240
            .get(1)
240
            .ok_or(error!("Invalid function codomain"))?;
240
        let tuple = (domain_value.clone(), codomain_value.clone());
240
        assignments.push(tuple);
    }
120
    Ok(Expression::AbstractLiteral(
120
        Metadata::new(),
120
        AbstractLiteral::Function(assignments),
120
    ))
120
}
//parses an abstract relation as an expression
80
fn parse_abs_relation(abs_relation: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
80
    let entries = abs_relation
80
        .as_array()
80
        .ok_or(error!("AbsLitRelation is not an array"))?;
80
    let mut assignments = vec![];
200
    for entry in entries {
200
        let entry = entry
200
            .as_array()
200
            .ok_or(error!("Explicit relation assignment is not an array"))?;
200
        let expression = entry
200
            .iter()
480
            .map(|values| parse_expression(values, scope))
200
            .collect::<Result<Vec<_>>>()?;
200
        assignments.push(expression);
    }
80
    Ok(Expression::AbstractLiteral(
80
        Metadata::new(),
80
        AbstractLiteral::Relation(assignments),
80
    ))
80
}
4400
fn parse_comprehension(
4400
    comprehension: &serde_json::Map<String, Value>,
4400
    scope: SymbolTablePtr,
4400
    comprehension_kind: Option<ACOperatorKind>,
4400
) -> Result<Expression> {
4400
    let fail = |stage: &str| -> Error {
        Error::Parse(format!("Could not parse comprehension at stage `{stage}`"))
    };
4400
    let value = &comprehension["Comprehension"];
4400
    let mut comprehension = ComprehensionBuilder::new(scope.clone());
4400
    let generator_symboltable = comprehension.generator_symboltable();
4400
    let return_expr_symboltable = comprehension.return_expr_symboltable();
4400
    let generators_and_guards_array = value
4400
        .pointer("/1")
4400
        .and_then(Value::as_array)
4400
        .ok_or_else(|| fail("Comprehension.pointer(/1).as_array"))?;
4400
    let generators_and_guards = generators_and_guards_array.iter();
5428
    for gen_or_guard in generators_and_guards {
5428
        let gen_or_guard_obj = gen_or_guard
5428
            .as_object()
5428
            .ok_or_else(|| fail("generator_or_guard.as_object"))?;
5428
        let (name, inner) = gen_or_guard_obj
5428
            .iter()
5428
            .next()
5428
            .ok_or_else(|| fail("generator_or_guard.iter().next"))?;
5428
        comprehension = match name.as_str() {
5428
            "Generator" => {
                // TODO: more things than GenDomainNoRepr and Single names here?
4828
                let generator_obj = inner
4828
                    .as_object()
4828
                    .ok_or_else(|| fail("Generator.inner.as_object"))?;
4828
                let (name, gen_inner) = generator_obj
4828
                    .iter()
4828
                    .next()
4828
                    .ok_or_else(|| fail("Generator.inner.iter().next"))?;
4828
                match name.as_str() {
4828
                    "GenDomainNoRepr" => {
4752
                        let name = gen_inner
4752
                            .pointer("/0/Single/Name")
4752
                            .and_then(Value::as_str)
4752
                            .ok_or_else(|| {
                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
                            })?;
4752
                        let domain_obj = gen_inner
4752
                            .pointer("/1")
4752
                            .and_then(Value::as_object)
4752
                            .ok_or_else(|| fail("GenDomainNoRepr.pointer(/1).as_object"))?;
4752
                        let (domain_name, domain_value) = domain_obj
4752
                            .iter()
4752
                            .next()
4752
                            .ok_or_else(|| fail("GenDomainNoRepr.domain.iter().next"))?;
4752
                        let domain = parse_domain(
4752
                            domain_name,
4752
                            domain_value,
4752
                            &mut generator_symboltable.write(),
                        )?;
4752
                        comprehension.generator(DeclarationPtr::new_find(name.into(), domain))
                    }
76
                    "GenInExpr" => {
76
                        let name = gen_inner
76
                            .pointer("/0/Single/Name")
76
                            .and_then(Value::as_str)
76
                            .ok_or_else(|| {
                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
                            })?;
76
                        let generator_expr = gen_inner
76
                            .pointer("/1")
76
                            .ok_or_else(|| fail("GenInExpr.pointer(/1)"))?;
76
                        let expr = parse_expression(generator_expr, &scope)
76
                            .map_err(|_| fail("GenInExpr.parse_expression"))?;
76
                        comprehension.expression_generator(name.into(), expr)
                    }
                    _ => {
                        bug!("unknown generator type inside comprehension {name}");
                    }
                }
            }
600
            "Condition" => {
600
                let expr = parse_expression(inner, &generator_symboltable)
600
                    .map_err(|_| fail("Condition.parse_expression"))?;
600
                comprehension.guard(expr)
            }
            x => {
                bug!("unknown field inside comprehension {x}");
            }
        }
    }
4400
    let return_expr_value = value
4400
        .pointer("/0")
4400
        .ok_or_else(|| fail("Comprehension.pointer(/0)"))?;
4400
    let expr = parse_expression(return_expr_value, &return_expr_symboltable)
4400
        .map_err(|_| fail("Comprehension.return_expr.parse_expression"))?;
4400
    Ok(Expression::Comprehension(
4400
        Metadata::new(),
4400
        Moo::new(comprehension.with_return_value(expr, comprehension_kind)),
4400
    ))
4400
}
38124
fn parse_bin_op(
38124
    bin_op: &serde_json::Map<String, Value>,
38124
    scope: &SymbolTablePtr,
38124
) -> Result<Expression> {
    // we know there is a single key value pair in this object
    // extract the value, ignore the key
38124
    let (key, value) = bin_op
38124
        .into_iter()
38124
        .next()
38124
        .ok_or(error!("Binary op object is empty"))?;
38124
    let constructor = binary_operator(key.as_str())
38124
        .ok_or(error!(format!("Unknown binary operator `{}`", key)))?;
38124
    match &value {
38124
        Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
38124
            let arg1 = parse_expression(&bin_op_args[0], scope)?;
38124
            let arg2 = parse_expression(&bin_op_args[1], scope)?;
38124
            Ok(constructor(Metadata::new(), Moo::new(arg1), Moo::new(arg2)))
        }
        _ => Err(error!("Binary operator arguments are not a 2-array")),
    }
38124
}
120
fn parse_table_op(
120
    op: &serde_json::Map<String, Value>,
120
    scope: &SymbolTablePtr,
120
) -> Result<Expression> {
120
    let args = op
120
        .get("MkOpTable")
120
        .ok_or(error!("MkOpTable missing"))?
120
        .as_array()
120
        .ok_or(error!("MkOpTable is not an array"))?;
120
    if args.len() != 2 {
        return Err(error!("MkOpTable arguments are not a 2-array"));
120
    }
120
    let tuple_expr = parse_expression(&args[0], scope)?;
120
    let allowed_rows_expr = parse_expression(&args[1], scope)?;
120
    let (tuple_elems, _) = tuple_expr
120
        .clone()
120
        .unwrap_matrix_unchecked()
120
        .ok_or(error!("MkOpTable first argument is not a matrix"))?;
120
    let (allowed_rows, _) = allowed_rows_expr
120
        .clone()
120
        .unwrap_matrix_unchecked()
120
        .ok_or(error!("MkOpTable second argument is not a matrix"))?;
320
    for row_expr in allowed_rows {
320
        let (row_elems, _) = row_expr
320
            .unwrap_matrix_unchecked()
320
            .ok_or(error!("MkOpTable row is not a matrix"))?;
320
        if row_elems.len() != tuple_elems.len() {
            return Err(error!("MkOpTable row width does not match tuple width"));
320
        }
    }
120
    Ok(Expression::Table(
120
        Metadata::new(),
120
        Moo::new(tuple_expr),
120
        Moo::new(allowed_rows_expr),
120
    ))
120
}
/// 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).
12593
fn parse_record_field(
12593
    op_args: &[Value],
12593
    scope: &SymbolTablePtr,
12593
) -> Result<Option<(Expression, Name)>> {
12593
    if op_args.len() != 2 {
        return Err(error!("Expected 2 arguments to record indexing operation"));
12593
    }
12593
    let lhs = parse_expression(&op_args[0], scope)?;
12593
    match lhs.return_type() {
        // If indexing into a record, parse string field name
        // and check that such a field exists
81
        ReturnType::Record(ents) | ReturnType::Variant(ents) => {
161
            let field_name = parse_reference_name(&op_args[1])?;
241
            let has_name = ents.iter().any(|x| x.name.eq(&field_name));
161
            if !has_name {
                return Err(error!(format!(
                    "Unknown field `{field_name}` in record `{lhs}`"
                )));
161
            }
161
            Ok(Some((lhs, field_name)))
        }
12432
        _ => Ok(None),
    }
12593
}
40
fn parse_active_op(
40
    op: &serde_json::Map<String, Value>,
40
    scope: &SymbolTablePtr,
40
) -> Result<Expression> {
    // we know there is a single key value pair in this object
    // extract the value, ignore the key
40
    let (_, value) = op
40
        .into_iter()
40
        .next()
40
        .ok_or(error!("MkOpActive op object is empty"))?;
40
    let Value::Array(op_args) = &value else {
        return Err(error!("MkOpActive op array is not an array"));
    };
40
    let Some((lhs, rhs)) = parse_record_field(op_args, scope)? else {
        return Err(error!("MkOpActive op expected record or variant"));
    };
40
    Ok(Expression::Active(Metadata::new(), Moo::new(lhs), rhs))
40
}
14393
fn parse_indexing_slicing_op(
14393
    op: &serde_json::Map<String, Value>,
14393
    scope: &SymbolTablePtr,
14393
) -> Result<Expression> {
    // we know there is a single key value pair in this object
    // extract the value, ignore the key
14393
    let (key, value) = op
14393
        .into_iter()
14393
        .next()
14393
        .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;
14393
    let mut indices: Vec<Option<Expression>> = vec![];
    // true if this has no slicing, false otherwise.
14393
    let mut all_known = true;
14393
    match key.as_str() {
14393
        "MkOpIndexing" => {
12553
            match &value {
12553
                Value::Array(op_args) if op_args.len() == 2 => {
12553
                    target = parse_expression(&op_args[0], scope)?;
12553
                    match parse_record_field(op_args, scope)? {
                        // For record indexing, generate nested RecordField exprs
121
                        Some((lhs, rhs)) => {
121
                            target = Expression::RecordField(Metadata::new(), Moo::new(lhs), rhs)
                        }
                        // Append any other indices to the flat list as normal
12432
                        _ => indices.push(Some(parse_expression(&op_args[1], scope)?)),
                    }
                }
                _ => return Err(error!("Unknown object inside MkOpIndexing")),
            };
        }
1840
        "MkOpSlicing" => {
1840
            all_known = false;
1840
            match &value {
1840
                Value::Array(op_args) if op_args.len() == 3 => {
                    // NB: records can't be sliced into so no need to check!
1840
                    target = parse_expression(&op_args[0], scope)?;
1840
                    indices.push(None);
                }
                _ => return Err(error!("Unknown object inside MkOpSlicing")),
            };
        }
        _ => return Err(error!("Unknown indexing/slicing operator")),
    }
    loop {
17881
        match &mut target {
3008
            Expression::UnsafeIndex(_, new_target, new_indices) => {
3008
                indices.extend(new_indices.iter().cloned().rev().map(Some));
3008
                target = Moo::unwrap_or_clone(new_target.clone());
3008
            }
480
            Expression::UnsafeSlice(_, new_target, new_indices) => {
480
                all_known = false;
480
                indices.extend(new_indices.iter().cloned().rev());
480
                target = Moo::unwrap_or_clone(new_target.clone());
480
            }
            _ => {
                // not a slice or an index, we have reached the target.
14393
                break;
            }
        }
    }
    // If we had a record field and no other indices, the list will be empty
14393
    if indices.is_empty() {
121
        return Ok(target);
14272
    }
14272
    indices.reverse();
14272
    if all_known {
        Ok(Expression::UnsafeIndex(
11952
            Metadata::new(),
11952
            Moo::new(target),
11952
            indices
11952
                .into_iter()
11952
                .collect::<Option<Vec<_>>>()
11952
                .ok_or(error!("Missing index in fully-known indexing operation"))?,
        ))
    } else {
2320
        Ok(Expression::UnsafeSlice(
2320
            Metadata::new(),
2320
            Moo::new(target),
2320
            indices,
2320
        ))
    }
14393
}
// Parses relation projection, to get a Vec<Option<Expression>> for the projections
44
fn parse_relation_projection(
44
    op: &serde_json::Map<String, Value>,
44
    scope: &SymbolTablePtr,
44
) -> Result<Expression> {
44
    let args = op
44
        .get("MkOpRelationProj")
44
        .ok_or(error!("MkOpRelationProj missing"))?
44
        .as_array()
44
        .ok_or(error!("MkOpRelationProj is not an array"))?;
44
    let first = args
44
        .first()
44
        .ok_or(error!("MkOpRelationProj missing first argument"))?;
44
    let second = args
44
        .get(1)
44
        .ok_or(error!("MkOpRelationProj missing second argument"))?
44
        .as_array()
44
        .ok_or(error!("MkOpRelationProj second argument is not an array"))?;
44
    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()
44
    let projections = second
44
        .iter()
132
        .map(|expr| parse_expression(expr, scope).ok())
44
        .collect();
44
    if let Some(relation) = relation {
44
        Ok(Expression::RelationProj(
44
            Metadata::new(),
44
            Moo::new(relation),
44
            projections,
44
        ))
    } else {
        Err(error!("MkOpRelationProj does not contain relation"))
    }
44
}
// 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
120
fn parse_to_set(op: &serde_json::Map<String, Value>, scope: &SymbolTablePtr) -> Result<Expression> {
120
    let args = op
120
        .get("MkOpToSet")
120
        .ok_or(error!("MkOpToSet missing"))?
120
        .as_array()
120
        .ok_or(error!("MkOpToSet is not an array"))?;
120
    let second = args
120
        .get(1)
120
        .ok_or(error!("MkOpToSet missing second argument"))?;
120
    let inner = parse_expression(second, scope)?;
120
    Ok(Expression::ToSet(Metadata::new(), Moo::new(inner)))
120
}
708
fn parse_flatten_op(
708
    op: &serde_json::Map<String, Value>,
708
    scope: &SymbolTablePtr,
708
) -> Result<Expression> {
708
    let args = op
708
        .get("MkOpFlatten")
708
        .ok_or(error!("MkOpFlatten missing"))?
708
        .as_array()
708
        .ok_or(error!("MkOpFlatten is not an array"))?;
708
    let first = args
708
        .first()
708
        .ok_or(error!("MkOpFlatten missing first argument"))?;
708
    let second = args
708
        .get(1)
708
        .ok_or(error!("MkOpFlatten missing second argument"))?;
708
    let n = parse_expression(first, scope).ok();
708
    let matrix = parse_expression(second, scope)?;
708
    if let Some(n) = n {
        Ok(Expression::Flatten(
            Metadata::new(),
            Some(Moo::new(n)),
            Moo::new(matrix),
        ))
    } else {
708
        Ok(Expression::Flatten(Metadata::new(), None, Moo::new(matrix)))
    }
708
}
33964
fn parse_unary_op(
33964
    un_op: &serde_json::Map<String, Value>,
33964
    scope: &SymbolTablePtr,
33964
) -> Result<Expression> {
33964
    let fail = |stage: &str| -> Error {
        Error::Parse(format!("Could not parse unary op at stage `{stage}`"))
    };
33964
    let (key, value) = un_op
33964
        .iter()
33964
        .next()
33964
        .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.
33964
    let arg = match value {
33964
        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
4384
            let comprehension_kind = match key.as_str() {
4384
                "MkOpOr" => Some(ACOperatorKind::Or),
3176
                "MkOpAnd" => Some(ACOperatorKind::And),
820
                "MkOpSum" => Some(ACOperatorKind::Sum),
220
                "MkOpProduct" => Some(ACOperatorKind::Product),
220
                _ => None,
            };
4384
            parse_comprehension(comprehension, scope.clone(), comprehension_kind)
4384
                .map_err(|_| fail("value.Comprehension.parse_comprehension"))
        }
29580
        _ => parse_expression(value, scope).map_err(|_| fail("value.parse_expression")),
    }
33964
    .map_err(|_| fail("arg"))?;
33964
    let constructor =
33964
        unary_operator(key.as_str(), Some(&arg)).ok_or_else(|| fail("unary_operator"))?;
33964
    Ok(constructor(Metadata::new(), Moo::new(arg)))
33964
}
// Takes in { AbstractLiteral: .... }
17492
fn parse_abstract_matrix_as_expr(
17492
    value: &serde_json::Value,
17492
    scope: &SymbolTablePtr,
17492
) -> Result<Expression> {
17492
    parser_trace!("trying to parse an abstract literal matrix");
16492
    let (values, domain_name, domain_value) =
17492
        if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix") {
14672
            parser_trace!(".. found JSON pointer /AbstractLiteral/AbstractLitMatrix");
14672
            let (domain_name, domain_value) = abs_lit_matrix
14672
                .pointer("/0")
14672
                .and_then(Value::as_object)
14672
                .and_then(|x| x.iter().next())
14672
                .ok_or(error!("AbsLitMatrix missing domain"))?;
14672
            let values = abs_lit_matrix
14672
                .pointer("/1")
14672
                .ok_or(error!("AbsLitMatrix missing values"))?;
14672
            Some((values, domain_name, domain_value))
        }
        // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
1000
        else if let Some(const_abs_lit_matrix) =
2820
            value.pointer("/Constant/ConstantAbstract/AbsLitMatrix")
        {
1000
            parser_trace!(".. found JSON pointer /Constant/ConstantAbstract/AbsLitMatrix");
1000
            let (domain_name, domain_value) = const_abs_lit_matrix
1000
                .pointer("/0")
1000
                .and_then(Value::as_object)
1000
                .and_then(|x| x.iter().next())
1000
                .ok_or(error!("ConstantAbstract AbsLitMatrix missing domain"))?;
1000
            let values = const_abs_lit_matrix
1000
                .pointer("/1")
1000
                .ok_or(error!("ConstantAbstract AbsLitMatrix missing values"))?;
1000
            Some((values, domain_name, domain_value))
1820
        } else if let Some(const_abs_lit_matrix) = value.pointer("/ConstantAbstract/AbsLitMatrix") {
820
            parser_trace!(".. found JSON pointer /ConstantAbstract/AbsLitMatrix");
820
            let (domain_name, domain_value) = const_abs_lit_matrix
820
                .pointer("/0")
820
                .and_then(Value::as_object)
820
                .and_then(|x| x.iter().next())
820
                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing domain"))?;
820
            let values = const_abs_lit_matrix
820
                .pointer("/1")
820
                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing values"))?;
820
            Some((values, domain_name, domain_value))
        } else {
1000
            None
        }
17492
        .ok_or(error!("Could not parse abstract literal matrix"))?;
16492
    parser_trace!(".. found in domain and values in JSON:");
16492
    parser_trace!(".. .. index domain name {domain_name}");
16492
    parser_trace!(".. .. values {value}");
16492
    let args_parsed = values
16492
        .as_array()
16492
        .ok_or(error!("Matrix values are not an array"))?
16492
        .iter()
36164
        .map(|x| parse_expression(x, scope))
16492
        .collect::<Result<Vec<Expression>>>()?;
16492
    if !args_parsed.is_empty() {
16452
        parser_trace!(
            ".. successfully parsed values as expressions: {}, ... ",
128
            args_parsed[0]
        );
    } else {
40
        parser_trace!(".. successfully parsed empty values ",);
    }
16492
    let mut symbols = scope.write();
16492
    match parse_domain(domain_name, domain_value, &mut symbols) {
16492
        Ok(domain) => {
16492
            parser_trace!("... sucessfully parsed domain as {domain}");
16492
            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])
        }
    }
17492
}
167524
fn parse_constant(
167524
    constant: &serde_json::Map<String, Value>,
167524
    scope: &SymbolTablePtr,
167524
) -> Result<Expression> {
167524
    match &constant.get("Constant") {
151464
        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
146484
            let int_32: i32 = match int["ConstantInt"]
146484
                .as_array()
146484
                .ok_or(error!("ConstantInt is not an array"))?[1]
146484
                .as_i64()
146484
                .ok_or(error!("ConstantInt does not contain int"))?
146484
                .try_into()
            {
146484
                Ok(x) => x,
                Err(_) => return Err(error!("ConstantInt cannot be represented as i32")),
            };
146484
            Ok(Expression::Atomic(
146484
                Metadata::new(),
146484
                Atom::Literal(Literal::Int(int_32)),
146484
            ))
        }
4980
        Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
944
            let b: bool = b["ConstantBool"]
944
                .as_bool()
944
                .ok_or(error!("ConstantBool does not contain bool"))?;
944
            Ok(Expression::Atomic(
944
                Metadata::new(),
944
                Atom::Literal(Literal::Bool(b)),
944
            ))
        }
4036
        Some(Value::Object(int)) if int.contains_key("ConstantAbstract") => {
4036
            if let Some(Value::Object(obj)) = int.get("ConstantAbstract") {
4036
                if let Some(arr) = obj.get("AbsLitSet") {
2296
                    return parse_abs_lit(arr, scope);
1740
                } else if let Some(arr) = obj.get("AbsLitMSet") {
40
                    return parse_abs_mset(arr, scope);
1700
                } else if let Some(arr) = obj.get("AbsLitMatrix") {
1000
                    return parse_abstract_matrix_as_expr(arr, scope);
700
                } else if let Some(arr) = obj.get("AbsLitTuple") {
280
                    return parse_abs_tuple(arr, scope);
420
                } else if let Some(arr) = obj.get("AbsLitRecord") {
100
                    return parse_abs_record(arr, scope);
320
                } else if let Some(arr) = obj.get("AbsLitPartition") {
40
                    return parse_abs_partition(arr, scope);
280
                } else if let Some(arr) = obj.get("AbsLitFunction") {
80
                    return parse_abs_function(arr, scope);
200
                } else if let Some(arr) = obj.get("AbsLitVariant") {
                    return parse_abs_variant(arr, scope);
200
                } else if let Some(arr) = obj.get("AbsLitRelation") {
80
                    return parse_abs_relation(arr, scope);
120
                } else if let Some(arr) = obj.get("AbsLitSequence") {
120
                    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 => {
16060
            let int_expr = constant
16060
                .get("ConstantInt")
16060
                .and_then(|x| x.as_array())
16060
                .and_then(|x| x[1].as_i64())
16060
                .and_then(|x| x.try_into().ok())
16060
                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
16060
            if let Some(expr) = int_expr {
15720
                return Ok(expr);
340
            }
340
            let bool_expr = constant
340
                .get("ConstantBool")
340
                .and_then(|x| x.as_bool())
340
                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
340
            if let Some(expr) = bool_expr {
340
                return Ok(expr);
            }
            Err(error!(format!("Unhandled parse_constant {constant:#?}")))
        }
        otherwise => Err(error!(format!("Unhandled parse_constant {otherwise:#?}"))),
    }
167524
}
#[cfg(test)]
mod tests {
    use super::*;
    use crate::ast::HasDomain;
    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
    }
}