Skip to main content

conjure_cp_core/parse/
parse_model.rs

1#![allow(clippy::unwrap_used)]
2#![allow(clippy::expect_used)]
3use std::sync::{Arc, RwLock};
4use ustr::Ustr;
5
6use serde_json::Map as JsonMap;
7use serde_json::Value;
8use serde_json::Value as JsonValue;
9
10use crate::ast::Moo;
11use crate::ast::abstract_comprehension::AbstractComprehensionBuilder;
12use crate::ast::ac_operators::ACOperatorKind;
13use crate::ast::comprehension::ComprehensionBuilder;
14use crate::ast::records::RecordValue;
15use crate::ast::{
16    AbstractLiteral, Atom, DeclarationPtr, Domain, Expression, FuncAttr, IntVal, JectivityAttr,
17    Literal, MSetAttr, Name, PartialityAttr, Range, RecordEntry, SetAttr, SymbolTable,
18    SymbolTablePtr,
19};
20use crate::ast::{DomainPtr, Metadata};
21use crate::context::Context;
22use crate::error::{Error, Result};
23use crate::{Model, bug, error, into_matrix_expr, throw_error};
24
25#[allow(unused_macros)]
26macro_rules! parser_trace {
27    ($($arg:tt)+) => {
28        log::trace!(target:"jsonparser",$($arg)+)
29    };
30}
31
32#[allow(unused_macros)]
33macro_rules! parser_debug {
34    ($($arg:tt)+) => {
35        log::debug!(target:"jsonparser",$($arg)+)
36    };
37}
38
39pub fn model_from_json(str: &str, context: Arc<RwLock<Context<'static>>>) -> Result<Model> {
40    let mut m = Model::new(context);
41    let v: JsonValue = serde_json::from_str(str)?;
42    let statements = v["mStatements"]
43        .as_array()
44        .ok_or(error!("mStatements is not an array"))?;
45
46    for statement in statements {
47        let entry = statement
48            .as_object()
49            .ok_or(error!("mStatements contains a non-object"))?
50            .iter()
51            .next()
52            .ok_or(error!("mStatements contains an empty object"))?;
53
54        match entry.0.as_str() {
55            "Declaration" => {
56                let decl = entry
57                    .1
58                    .as_object()
59                    .ok_or(error!("Declaration is not an object".to_owned()))?;
60
61                // One field in the declaration should tell us what kind it is.
62                //
63                // Find it, ignoring the other fields.
64                //
65                // e.g. FindOrGiven,
66
67                let mut valid_decl: bool = false;
68                let scope = m.symbols_ptr_unchecked().clone();
69                let model = &mut m;
70                for (kind, value) in decl {
71                    match kind.as_str() {
72                        "FindOrGiven" => {
73                            parse_variable(value, &mut model.symbols_mut())?;
74                            valid_decl = true;
75                            break;
76                        }
77                        "Letting" => {
78                            parse_letting(value, &scope)?;
79                            valid_decl = true;
80                            break;
81                        }
82                        _ => continue,
83                    }
84                }
85
86                if !valid_decl {
87                    throw_error!("Declaration is not a valid kind")?;
88                }
89            }
90            "SuchThat" => {
91                let constraints_arr = match entry.1.as_array() {
92                    Some(x) => x,
93                    None => bug!("SuchThat is not a vector"),
94                };
95
96                let constraints: Vec<Expression> = constraints_arr
97                    .iter()
98                    .map(|x| parse_expression(x, m.symbols_ptr_unchecked()))
99                    .collect::<Result<Vec<_>>>()?;
100                m.add_constraints(constraints);
101            }
102            otherwise => bug!("Unhandled Statement {:#?}", otherwise),
103        }
104    }
105    Ok(m)
106}
107
108fn parse_variable(v: &JsonValue, symtab: &mut SymbolTable) -> Result<()> {
109    let arr = v.as_array().ok_or(error!("FindOrGiven is not an array"))?;
110
111    let variable_type = arr[0]
112        .as_str()
113        .ok_or(error!("FindOrGiven[0] is not a string"))?;
114
115    let name = arr[1]
116        .as_object()
117        .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
118        .as_str()
119        .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
120
121    let name = Name::User(Ustr::from(name));
122
123    let domain = arr[2]
124        .as_object()
125        .ok_or(error!("FindOrGiven[2] is not an object"))?
126        .iter()
127        .next()
128        .ok_or(error!("FindOrGiven[2] is an empty object"))?;
129
130    let domain = parse_domain(domain.0, domain.1, symtab)?;
131
132    let decl = match variable_type {
133        "Find" => DeclarationPtr::new_find(name.clone(), domain),
134        "Given" => DeclarationPtr::new_given(name.clone(), domain),
135        _ => {
136            return Err(error!("FindOrGiven[0] is not 'Find' or 'Given'"));
137        }
138    };
139
140    symtab.insert(decl).ok_or(Error::Parse(format!(
141        "Could not add {name} to symbol table as it already exists"
142    )))
143}
144
145fn parse_letting(v: &JsonValue, scope: &SymbolTablePtr) -> Result<()> {
146    let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
147    let name = arr[0]
148        .as_object()
149        .ok_or(error!("Letting[0] is not an object"))?["Name"]
150        .as_str()
151        .ok_or(error!("Letting[0].Name is not a string"))?;
152    let name = Name::User(Ustr::from(name));
153    // value letting
154    if let Ok(value) = parse_expression(&arr[1], scope) {
155        let mut symtab = scope.write();
156        symtab
157            .insert(DeclarationPtr::new_value_letting(name.clone(), value))
158            .ok_or(Error::Parse(format!(
159                "Could not add {name} to symbol table as it already exists"
160            )))
161    } else {
162        // domain letting
163        let domain = &arr[1]
164            .as_object()
165            .ok_or(error!("Letting[1] is not an object".to_owned()))?["Domain"]
166            .as_object()
167            .ok_or(error!("Letting[1].Domain is not an object"))?
168            .iter()
169            .next()
170            .ok_or(error!("Letting[1].Domain is an empty object"))?;
171
172        let mut symtab = scope.write();
173        let domain = parse_domain(domain.0, domain.1, &mut symtab)?;
174
175        symtab
176            .insert(DeclarationPtr::new_domain_letting(name.clone(), domain))
177            .ok_or(Error::Parse(format!(
178                "Could not add {name} to symbol table as it already exists"
179            )))
180    }
181}
182
183fn parse_domain(
184    domain_name: &str,
185    domain_value: &JsonValue,
186    symbols: &mut SymbolTable,
187) -> Result<DomainPtr> {
188    match domain_name {
189        "DomainInt" => Ok(parse_int_domain(domain_value, symbols)?),
190        "DomainBool" => Ok(Domain::bool()),
191        "DomainReference" => {
192            let name = Name::user(
193                domain_value
194                    .as_array()
195                    .ok_or(error!("DomainReference is not an array"))?[0]
196                    .as_object()
197                    .ok_or(error!("DomainReference[0] is not an object"))?["Name"]
198                    .as_str()
199                    .ok_or(error!("DomainReference[0].Name is not a string"))?,
200            );
201            let ptr = symbols
202                .lookup(&name)
203                .ok_or(error!(format!("Name {name} not found")))?;
204            let dom =
205                Domain::reference(ptr).ok_or(error!("Could not construct reference domain"))?;
206            Ok(dom)
207        }
208        "DomainSet" => {
209            let dom = domain_value.get(2).and_then(|v| v.as_object());
210            let domain_obj = dom.ok_or(error!("DomainSet is missing domain object"))?;
211            let domain = domain_obj
212                .iter()
213                .next()
214                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
215            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
216            let size = domain_value
217                .get(1)
218                .and_then(|v| v.as_object())
219                .ok_or(error!("Set size attributes is not an object"))?;
220            let size = parse_size_attr(size, symbols)?;
221            let attr: SetAttr<IntVal> = SetAttr { size };
222            Ok(Domain::set(attr, domain))
223        }
224        "DomainMSet" => {
225            let dom = domain_value
226                .get(2)
227                .and_then(|v| v.as_object())
228                .expect("domain object exists");
229            let domain = dom
230                .iter()
231                .next()
232                .ok_or(Error::Parse("DomainMSet is an empty object".to_owned()))?;
233            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
234
235            // Parse Attributes
236            let attributes = domain_value
237                .get(1)
238                .and_then(|v| v.as_array())
239                .ok_or(error!("MSet attributes is not a json array"))?;
240
241            let size = attributes
242                .first()
243                .and_then(|v| v.as_object())
244                .ok_or(error!("MSet size attributes is not an object"))?;
245            let size = parse_size_attr(size, symbols)?;
246
247            let occurrence = attributes
248                .get(1)
249                .and_then(|v| v.as_object())
250                .ok_or(error!("MSet occurrence attributes is not an object"))?;
251            let occurrence = parse_occur_attr(occurrence, symbols)?;
252
253            let attr: MSetAttr<IntVal> = MSetAttr { size, occurrence };
254            Ok(Domain::mset(attr, domain))
255        }
256
257        "DomainMatrix" => {
258            let domain_value = domain_value
259                .as_array()
260                .ok_or(error!("Domain matrix is not an array"))?;
261
262            let indexed_by_domain = domain_value[0].clone();
263            let (index_domain_name, index_domain_value) = indexed_by_domain
264                .as_object()
265                .ok_or(error!("DomainMatrix[0] is not an object"))?
266                .iter()
267                .next()
268                .ok_or(error!(""))?;
269
270            let (value_domain_name, value_domain_value) = domain_value[1]
271                .as_object()
272                .ok_or(error!(""))?
273                .iter()
274                .next()
275                .ok_or(error!(""))?;
276
277            // Conjure stores a 2-d matrix as a matrix of a matrix.
278            //
279            // Therefore, the index is always a Domain.
280
281            let mut index_domains: Vec<DomainPtr> = vec![];
282
283            index_domains.push(parse_domain(
284                index_domain_name,
285                index_domain_value,
286                symbols,
287            )?);
288
289            // We want to store 2-d matrices as a matrix with two index domains, not a matrix in a
290            // matrix.
291            //
292            // Walk through the value domain until it is not a DomainMatrix, adding the index to
293            // our list of indices.
294            let mut value_domain = parse_domain(value_domain_name, value_domain_value, symbols)?;
295            while let Some((new_value_domain, mut indices)) = value_domain.as_matrix() {
296                index_domains.append(&mut indices);
297                value_domain = new_value_domain.clone()
298            }
299
300            Ok(Domain::matrix(value_domain, index_domains))
301        }
302        "DomainTuple" => {
303            let domain_value = domain_value
304                .as_array()
305                .ok_or(error!("Domain tuple is not an array"))?;
306
307            //iterate through the array and parse each domain
308            let domain = domain_value
309                .iter()
310                .map(|x| {
311                    let domain = x
312                        .as_object()
313                        .ok_or(error!("DomainTuple[0] is not an object"))?
314                        .iter()
315                        .next()
316                        .ok_or(error!("DomainTuple[0] is an empty object"))?;
317                    parse_domain(domain.0, domain.1, symbols)
318                })
319                .collect::<Result<Vec<DomainPtr>>>()?;
320
321            Ok(Domain::tuple(domain))
322        }
323        "DomainRecord" => {
324            let domain_value = domain_value
325                .as_array()
326                .ok_or(error!("Domain Record is not a json array"))?;
327
328            let mut record_entries = vec![];
329
330            for item in domain_value {
331                //collect the name of the record field
332                let name = item[0]
333                    .as_object()
334                    .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
335                    .as_str()
336                    .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
337
338                let name = Name::User(Ustr::from(name));
339                // then collect the domain of the record field
340                let domain = item[1]
341                    .as_object()
342                    .ok_or(error!("FindOrGiven[2] is not an object"))?
343                    .iter()
344                    .next()
345                    .ok_or(error!("FindOrGiven[2] is an empty object"))?;
346
347                let domain = parse_domain(domain.0, domain.1, symbols)?;
348
349                let rec = RecordEntry { name, domain };
350
351                record_entries.push(rec);
352            }
353
354            // add record fields to symbol table
355            for decl in record_entries
356                .iter()
357                .cloned()
358                .map(DeclarationPtr::new_record_field)
359            {
360                symbols.insert(decl).ok_or(error!(
361                    "record field should not already be in the symbol table"
362                ))?;
363            }
364
365            Ok(Domain::record(record_entries))
366        }
367        "DomainFunction" => {
368            let domain = domain_value
369                .get(2)
370                .and_then(|v| v.as_object())
371                .ok_or(error!("Function domain is not an object"))?;
372            let domain = domain
373                .iter()
374                .next()
375                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
376            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
377
378            let codomain = domain_value
379                .get(3)
380                .and_then(|v| v.as_object())
381                .ok_or(error!("Function codomain is not an object"))?;
382            let codomain = codomain
383                .iter()
384                .next()
385                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
386            let codomain = parse_domain(codomain.0.as_str(), codomain.1, symbols)?;
387
388            // Attribute parsing
389            let attributes = domain_value
390                .get(1)
391                .and_then(|v| v.as_array())
392                .ok_or(error!("Function attributes is not a json array"))?;
393            let size = attributes
394                .first()
395                .and_then(|v| v.as_object())
396                .ok_or(error!("Function size attributes is not an object"))?;
397            let size = parse_size_attr(size, symbols)?;
398            let partiality = attributes
399                .get(1)
400                .and_then(|v| v.as_str())
401                .ok_or(error!("Function partiality is not a string"))?;
402            let partiality = match partiality {
403                "PartialityAttr_Partial" => Some(PartialityAttr::Partial),
404                "PartialityAttr_Total" => Some(PartialityAttr::Total),
405                _ => None,
406            };
407            let partiality =
408                partiality.ok_or(Error::Parse("Partiality is an unknown type".to_owned()))?;
409            let jectivity = attributes
410                .get(2)
411                .and_then(|v| v.as_str())
412                .ok_or(error!("Function jectivity is not a string"))?;
413            let jectivity = match jectivity {
414                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
415                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
416                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
417                "JectivityAttr_None" => Some(JectivityAttr::None),
418                _ => None,
419            };
420            let jectivity =
421                jectivity.ok_or(Error::Parse("Jectivity is an unknown type".to_owned()))?;
422
423            let attr: FuncAttr<IntVal> = FuncAttr {
424                size,
425                partiality,
426                jectivity,
427            };
428
429            Ok(Domain::function(attr, domain, codomain))
430        }
431        _ => Err(Error::Parse(
432            "FindOrGiven[2] is an unknown object".to_owned(), // consider covered
433        )),
434    }
435}
436
437fn parse_size_attr(
438    attr_map: &JsonMap<String, JsonValue>,
439    symbols: &mut SymbolTable,
440) -> Result<Range<IntVal>> {
441    let scope = SymbolTablePtr::new();
442    *scope.write() = symbols.clone();
443
444    let attr_obj = attr_map
445        .iter()
446        .next()
447        .ok_or(Error::Parse("SizeAttr is an empty object".to_owned()))?;
448    match attr_obj.0.as_str() {
449        "SizeAttr_None" => Ok(Range::Unbounded),
450        "SizeAttr_MinSize" => {
451            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
452            Ok(Range::UnboundedR(size))
453        }
454        "SizeAttr_MaxSize" => {
455            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
456            Ok(Range::UnboundedL(size))
457        }
458        "SizeAttr_MinMaxSize" => {
459            let min_max = attr_obj
460                .1
461                .as_array()
462                .ok_or(error!("SizeAttr MinMaxSize is not a json array"))?;
463            let min = min_max
464                .first()
465                .ok_or(error!("SizeAttr Min is not present"))?;
466            let min_int = parse_expression_to_int_val(min, &scope)?;
467            let max = min_max
468                .get(1)
469                .ok_or(error!("SizeAttr Max is not present"))?;
470            let max_int = parse_expression_to_int_val(max, &scope)?;
471            Ok(Range::Bounded(min_int, max_int))
472        }
473        "SizeAttr_Size" => {
474            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
475            Ok(Range::Single(size))
476        }
477        _ => Err(Error::Parse("SizeAttr is an unknown type".to_owned())),
478    }
479}
480
481fn parse_occur_attr(
482    attr_map: &JsonMap<String, JsonValue>,
483    symbols: &mut SymbolTable,
484) -> Result<Range<IntVal>> {
485    let scope = SymbolTablePtr::new();
486    *scope.write() = symbols.clone();
487    let attr_obj = attr_map
488        .iter()
489        .next()
490        .ok_or(Error::Parse("OccurAttr is an empty object".to_owned()))?;
491    match attr_obj.0.as_str() {
492        "OccurAttr_None" => Ok(Range::Unbounded),
493        "OccurAttr_MinOccur" => {
494            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
495            Ok(Range::UnboundedR(size_int))
496        }
497        "OccurAttr_MaxOccur" => {
498            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
499            Ok(Range::UnboundedL(size_int))
500        }
501        "OccurAttr_MinMaxOccur" => {
502            let min_max = attr_obj
503                .1
504                .as_array()
505                .ok_or(error!("OccurAttr MinMaxOccur is not a json array"))?;
506            let min = min_max
507                .first()
508                .ok_or(error!("OccurAttr Min is not present"))?;
509            let min_int = parse_expression_to_int_val(min, &scope)?;
510            let max = min_max
511                .get(1)
512                .ok_or(error!("OccurAttr Max is not present"))?;
513            let max_int = parse_expression_to_int_val(max, &scope)?;
514            Ok(Range::Bounded(min_int, max_int))
515        }
516        "OccurAttr_Size" => {
517            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
518            Ok(Range::Single(size_int))
519        }
520        _ => Err(Error::Parse("OccurAttr is an unknown type".to_owned())),
521    }
522}
523
524fn parse_int_domain(v: &JsonValue, symbols: &SymbolTable) -> Result<DomainPtr> {
525    let scope = SymbolTablePtr::new();
526    *scope.write() = symbols.clone();
527
528    let mut ranges = Vec::new();
529    let arr = v
530        .as_array()
531        .ok_or(error!("DomainInt is not an array".to_owned()))?[1]
532        .as_array()
533        .ok_or(error!("DomainInt[1] is not an array".to_owned()))?;
534    for range in arr {
535        let range = range
536            .as_object()
537            .ok_or(error!("DomainInt[1] contains a non-object"))?
538            .iter()
539            .next()
540            .ok_or(error!("DomainInt[1] contains an empty object"))?;
541        match range.0.as_str() {
542            "RangeBounded" => {
543                let arr = range
544                    .1
545                    .as_array()
546                    .ok_or(error!("RangeBounded is not an array".to_owned()))?;
547                let mut nums = Vec::new();
548                for item in arr.iter() {
549                    let num = parse_expression_to_int_val(item, &scope)?;
550                    nums.push(num);
551                }
552                let lower = nums
553                    .first()
554                    .cloned()
555                    .ok_or(error!("RangeBounded lower bound missing"))?;
556                let upper = nums
557                    .get(1)
558                    .cloned()
559                    .ok_or(error!("RangeBounded upper bound missing"))?;
560                ranges.push(Range::Bounded(lower, upper));
561            }
562            "RangeSingle" => {
563                let num = parse_expression_to_int_val(range.1, &scope)?;
564                ranges.push(Range::Single(num));
565            }
566            _ => return throw_error!("DomainInt[1] contains an unknown object"),
567        }
568    }
569    Ok(Domain::int(ranges))
570}
571
572fn parse_expression_to_int_val(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<IntVal> {
573    parser_trace!("trying to parse domain value as expression: {}", obj);
574    let expr = parse_expression(obj, scope)?;
575
576    if let Some(Literal::Int(i)) = expr.clone().into_literal() {
577        return Ok(IntVal::Const(i));
578    }
579
580    if let Expression::Atomic(_, Atom::Reference(reference)) = &expr
581        && let Some(reference_val) = IntVal::new_ref(reference)
582    {
583        return Ok(reference_val);
584    }
585
586    IntVal::new_expr(Moo::new(expr)).ok_or(error!("Could not parse integer expression"))
587}
588
589type BinOp = fn(Metadata, Moo<Expression>, Moo<Expression>) -> Expression;
590type UnaryOp = fn(Metadata, Moo<Expression>) -> Expression;
591
592fn binary_operator(op_name: &str) -> Option<BinOp> {
593    match op_name {
594        "MkOpIn" => Some(Expression::In),
595        "MkOpUnion" => Some(Expression::Union),
596        "MkOpIntersect" => Some(Expression::Intersect),
597        "MkOpSupset" => Some(Expression::Supset),
598        "MkOpSupsetEq" => Some(Expression::SupsetEq),
599        "MkOpSubset" => Some(Expression::Subset),
600        "MkOpSubsetEq" => Some(Expression::SubsetEq),
601        "MkOpEq" => Some(Expression::Eq),
602        "MkOpNeq" => Some(Expression::Neq),
603        "MkOpGeq" => Some(Expression::Geq),
604        "MkOpLeq" => Some(Expression::Leq),
605        "MkOpGt" => Some(Expression::Gt),
606        "MkOpLt" => Some(Expression::Lt),
607        "MkOpLexLt" => Some(Expression::LexLt),
608        "MkOpLexGt" => Some(Expression::LexGt),
609        "MkOpLexLeq" => Some(Expression::LexLeq),
610        "MkOpLexGeq" => Some(Expression::LexGeq),
611        "MkOpDiv" => Some(Expression::UnsafeDiv),
612        "MkOpMod" => Some(Expression::UnsafeMod),
613        "MkOpMinus" => Some(Expression::Minus),
614        "MkOpImply" => Some(Expression::Imply),
615        "MkOpIff" => Some(Expression::Iff),
616        "MkOpPow" => Some(Expression::UnsafePow),
617        "MkOpImage" => Some(Expression::Image),
618        "MkOpImageSet" => Some(Expression::ImageSet),
619        "MkOpPreImage" => Some(Expression::PreImage),
620        "MkOpInverse" => Some(Expression::Inverse),
621        "MkOpRestrict" => Some(Expression::Restrict),
622        _ => None,
623    }
624}
625
626fn unary_operator(op_name: &str) -> Option<UnaryOp> {
627    match op_name {
628        "MkOpNot" => Some(Expression::Not),
629        "MkOpNegate" => Some(Expression::Neg),
630        "MkOpTwoBars" => Some(Expression::Abs),
631        "MkOpAnd" => Some(Expression::And),
632        "MkOpSum" => Some(Expression::Sum),
633        "MkOpProduct" => Some(Expression::Product),
634        "MkOpOr" => Some(Expression::Or),
635        "MkOpMin" => Some(Expression::Min),
636        "MkOpMax" => Some(Expression::Max),
637        "MkOpAllDiff" => Some(Expression::AllDiff),
638        "MkOpToInt" => Some(Expression::ToInt),
639        "MkOpDefined" => Some(Expression::Defined),
640        "MkOpRange" => Some(Expression::Range),
641        _ => None,
642    }
643}
644
645pub fn parse_expression(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<Expression> {
646    let fail = |stage: &str| -> Error {
647        Error::Parse(format!(
648            "Could not parse expression at stage `{stage}` for json `{obj}`"
649        ))
650    };
651
652    match obj {
653        Value::Object(op) if op.contains_key("Op") => {
654            let op_obj = op
655                .get("Op")
656                .and_then(Value::as_object)
657                .ok_or_else(|| fail("Op.as_object"))?;
658            let (op_name, _) = op_obj.iter().next().ok_or_else(|| fail("Op.iter().next"))?;
659
660            if op_obj.contains_key("MkOpFlatten") {
661                parse_flatten_op(op_obj, scope)
662            } else if op_obj.contains_key("MkOpTable") {
663                parse_table_op(op_obj, scope)
664            } else if op_obj.contains_key("MkOpIndexing") || op_obj.contains_key("MkOpSlicing") {
665                parse_indexing_slicing_op(op_obj, scope)
666            } else if binary_operator(op_name).is_some() {
667                parse_bin_op(op_obj, scope)
668            } else if unary_operator(op_name).is_some() {
669                parse_unary_op(op_obj, scope)
670            } else {
671                Err(fail("Op.unknown"))
672            }
673        }
674        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
675            parse_comprehension(comprehension, scope.clone(), None)
676        }
677        Value::Object(refe) if refe.contains_key("Reference") => {
678            let ref_arr = refe["Reference"]
679                .as_array()
680                .ok_or_else(|| fail("Reference.as_array"))?;
681            let ref_obj = ref_arr
682                .first()
683                .and_then(|x| x.as_object())
684                .ok_or_else(|| fail("Reference[0].as_object"))?;
685            let name = ref_obj
686                .get("Name")
687                .and_then(|x| x.as_str())
688                .ok_or_else(|| fail("Reference[0].Name.as_str"))?;
689            let user_name = Name::User(Ustr::from(name));
690
691            let declaration: DeclarationPtr = scope
692                .read()
693                .lookup(&user_name)
694                .ok_or_else(|| fail("Reference.lookup"))?;
695
696            Ok(Expression::Atomic(
697                Metadata::new(),
698                Atom::Reference(crate::ast::Reference::new(declaration)),
699            ))
700        }
701        Value::Object(abslit) if abslit.contains_key("AbstractLiteral") => {
702            let abstract_literal = abslit["AbstractLiteral"]
703                .as_object()
704                .ok_or_else(|| fail("AbstractLiteral.as_object"))?;
705
706            if abstract_literal.contains_key("AbsLitSet") {
707                parse_abs_lit(&abslit["AbstractLiteral"]["AbsLitSet"], scope)
708            } else if abstract_literal.contains_key("AbsLitFunction") {
709                parse_abs_function(&abslit["AbstractLiteral"]["AbsLitFunction"], scope)
710            } else if abstract_literal.contains_key("AbsLitMSet") {
711                parse_abs_mset(&abslit["AbstractLiteral"]["AbsLitMSet"], scope)
712            } else {
713                parse_abstract_matrix_as_expr(obj, scope)
714            }
715        }
716
717        Value::Object(constant) if constant.contains_key("Constant") => {
718            parse_constant(constant, scope).or_else(|_| parse_abstract_matrix_as_expr(obj, scope))
719        }
720
721        Value::Object(constant) if constant.contains_key("ConstantAbstract") => {
722            parse_abstract_matrix_as_expr(obj, scope)
723        }
724
725        Value::Object(constant) if constant.contains_key("ConstantInt") => {
726            parse_constant(constant, scope)
727        }
728        Value::Object(constant) if constant.contains_key("ConstantBool") => {
729            parse_constant(constant, scope)
730        }
731
732        _ => Err(fail("no_match")),
733    }
734}
735
736fn parse_abs_lit(abs_set: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
737    let values = abs_set
738        .as_array()
739        .ok_or(error!("AbsLitSet is not an array"))?;
740    let expressions = values
741        .iter()
742        .map(|values| parse_expression(values, scope))
743        .collect::<Result<Vec<_>>>()?;
744
745    Ok(Expression::AbstractLiteral(
746        Metadata::new(),
747        AbstractLiteral::Set(expressions),
748    ))
749}
750
751fn parse_abs_mset(abs_mset: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
752    let values = abs_mset
753        .as_array()
754        .ok_or(error!("AbsLitMSet is not an array"))?;
755    let expressions = values
756        .iter()
757        .map(|values| parse_expression(values, scope))
758        .collect::<Result<Vec<_>>>()?;
759
760    Ok(Expression::AbstractLiteral(
761        Metadata::new(),
762        AbstractLiteral::MSet(expressions),
763    ))
764}
765
766fn parse_abs_tuple(abs_tuple: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
767    let values = abs_tuple
768        .as_array()
769        .ok_or(error!("AbsLitTuple is not an array"))?;
770    let expressions = values
771        .iter()
772        .map(|values| parse_expression(values, scope))
773        .collect::<Result<Vec<_>>>()?;
774
775    Ok(Expression::AbstractLiteral(
776        Metadata::new(),
777        AbstractLiteral::Tuple(expressions),
778    ))
779}
780
781//parses an abstract record as an expression
782fn parse_abs_record(abs_record: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
783    let entries = abs_record
784        .as_array()
785        .ok_or(error!("AbsLitRecord is not an array"))?;
786    let mut rec = vec![];
787
788    for entry in entries {
789        let entry = entry
790            .as_array()
791            .ok_or(error!("AbsLitRecord entry is not an array"))?;
792        let name = entry[0]
793            .as_object()
794            .ok_or(error!("AbsLitRecord field name is not an object"))?["Name"]
795            .as_str()
796            .ok_or(error!("AbsLitRecord field name is not a string"))?;
797
798        let value = parse_expression(&entry[1], scope)?;
799
800        let name = Name::User(Ustr::from(name));
801        let rec_entry = RecordValue {
802            name: name.clone(),
803            value,
804        };
805        rec.push(rec_entry);
806    }
807
808    Ok(Expression::AbstractLiteral(
809        Metadata::new(),
810        AbstractLiteral::Record(rec),
811    ))
812}
813
814//parses an abstract function as an expression
815fn parse_abs_function(abs_function: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
816    let entries = abs_function
817        .as_array()
818        .ok_or(error!("AbsLitFunction is not an array"))?;
819    let mut assignments = vec![];
820
821    for entry in entries {
822        let entry = entry
823            .as_array()
824            .ok_or(error!("Explicit function assignment is not an array"))?;
825        let expression = entry
826            .iter()
827            .map(|values| parse_expression(values, scope))
828            .collect::<Result<Vec<_>>>()?;
829        let domain_value = expression
830            .first()
831            .ok_or(error!("Invalid function domain"))?;
832        let codomain_value = expression
833            .get(1)
834            .ok_or(error!("Invalid function codomain"))?;
835        let tuple = (domain_value.clone(), codomain_value.clone());
836        assignments.push(tuple);
837    }
838    Ok(Expression::AbstractLiteral(
839        Metadata::new(),
840        AbstractLiteral::Function(assignments),
841    ))
842}
843
844fn parse_comprehension(
845    comprehension: &serde_json::Map<String, Value>,
846    scope: SymbolTablePtr,
847    comprehension_kind: Option<ACOperatorKind>,
848) -> Result<Expression> {
849    let fail = |stage: &str| -> Error {
850        Error::Parse(format!("Could not parse comprehension at stage `{stage}`"))
851    };
852
853    let value = &comprehension["Comprehension"];
854    let mut comprehension = ComprehensionBuilder::new(scope.clone());
855    let generator_symboltable = comprehension.generator_symboltable();
856    let return_expr_symboltable = comprehension.return_expr_symboltable();
857
858    let generators_and_guards_array = value
859        .pointer("/1")
860        .and_then(Value::as_array)
861        .ok_or_else(|| fail("Comprehension.pointer(/1).as_array"))?;
862    let generators_and_guards = generators_and_guards_array.iter();
863
864    for gen_or_guard in generators_and_guards {
865        let gen_or_guard_obj = gen_or_guard
866            .as_object()
867            .ok_or_else(|| fail("generator_or_guard.as_object"))?;
868        let (name, inner) = gen_or_guard_obj
869            .iter()
870            .next()
871            .ok_or_else(|| fail("generator_or_guard.iter().next"))?;
872        comprehension = match name.as_str() {
873            "Generator" => {
874                // TODO: more things than GenDomainNoRepr and Single names here?
875                let generator_obj = inner
876                    .as_object()
877                    .ok_or_else(|| fail("Generator.inner.as_object"))?;
878                let (name, gen_inner) = generator_obj
879                    .iter()
880                    .next()
881                    .ok_or_else(|| fail("Generator.inner.iter().next"))?;
882                match name.as_str() {
883                    "GenDomainNoRepr" => {
884                        let name = gen_inner
885                            .pointer("/0/Single/Name")
886                            .and_then(Value::as_str)
887                            .ok_or_else(|| {
888                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
889                            })?;
890                        let domain_obj = gen_inner
891                            .pointer("/1")
892                            .and_then(Value::as_object)
893                            .ok_or_else(|| fail("GenDomainNoRepr.pointer(/1).as_object"))?;
894                        let (domain_name, domain_value) = domain_obj
895                            .iter()
896                            .next()
897                            .ok_or_else(|| fail("GenDomainNoRepr.domain.iter().next"))?;
898                        let domain = parse_domain(
899                            domain_name,
900                            domain_value,
901                            &mut generator_symboltable.write(),
902                        )?;
903                        comprehension.generator(DeclarationPtr::new_find(name.into(), domain))
904                    }
905                    // TODO: this is temporary until comprehensions support "in expr" generators
906                    // currently only supports a single generator of this type
907                    "GenInExpr" => return parse_in_expr_comprehension(scope, value, gen_inner),
908                    _ => {
909                        bug!("unknown generator type inside comprehension {name}");
910                    }
911                }
912            }
913
914            "Condition" => {
915                let expr = parse_expression(inner, &generator_symboltable)
916                    .map_err(|_| fail("Condition.parse_expression"))?;
917                comprehension.guard(expr)
918            }
919
920            x => {
921                bug!("unknown field inside comprehension {x}");
922            }
923        }
924    }
925
926    let return_expr_value = value
927        .pointer("/0")
928        .ok_or_else(|| fail("Comprehension.pointer(/0)"))?;
929    let expr = parse_expression(return_expr_value, &return_expr_symboltable)
930        .map_err(|_| fail("Comprehension.return_expr.parse_expression"))?;
931
932    Ok(Expression::Comprehension(
933        Metadata::new(),
934        Moo::new(comprehension.with_return_value(expr, comprehension_kind)),
935    ))
936}
937
938fn parse_in_expr_comprehension(
939    scope: SymbolTablePtr,
940    comprehension_value: &Value,
941    gen_inner: &Value,
942) -> Result<Expression> {
943    let fail = |stage: &str| -> Error {
944        Error::Parse(format!(
945            "Could not parse GenInExpr comprehension at stage `{stage}`"
946        ))
947    };
948
949    let name = gen_inner
950        .pointer("/0/Single/Name")
951        .and_then(Value::as_str)
952        .ok_or_else(|| fail("GenInExpr.pointer(/0/Single/Name).as_str"))?;
953    let generator_expr = gen_inner
954        .pointer("/1")
955        .ok_or_else(|| fail("GenInExpr.pointer(/1)"))?;
956    let expr =
957        parse_expression(generator_expr, &scope).map_err(|_| fail("GenInExpr.parse_expression"))?;
958
959    let comprehension =
960        AbstractComprehensionBuilder::new(&scope).new_expression_generator(expr, name.into());
961    let return_expr_value = comprehension_value
962        .pointer("/0")
963        .ok_or_else(|| fail("comprehension_value.pointer(/0)"))?;
964    let expr = parse_expression(return_expr_value, &comprehension.return_expr_symbols())
965        .map_err(|_| fail("GenInExpr.return_expr.parse_expression"))?;
966
967    Ok(Expression::AbstractComprehension(
968        Metadata::new(),
969        Moo::new(comprehension.with_return_value(expr)),
970    ))
971}
972
973fn parse_bin_op(
974    bin_op: &serde_json::Map<String, Value>,
975    scope: &SymbolTablePtr,
976) -> Result<Expression> {
977    // we know there is a single key value pair in this object
978    // extract the value, ignore the key
979    let (key, value) = bin_op
980        .into_iter()
981        .next()
982        .ok_or(error!("Binary op object is empty"))?;
983
984    let constructor = binary_operator(key.as_str())
985        .ok_or(error!(format!("Unknown binary operator `{}`", key)))?;
986
987    match &value {
988        Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
989            let arg1 = parse_expression(&bin_op_args[0], scope)?;
990            let arg2 = parse_expression(&bin_op_args[1], scope)?;
991            Ok(constructor(Metadata::new(), Moo::new(arg1), Moo::new(arg2)))
992        }
993        _ => Err(error!("Binary operator arguments are not a 2-array")),
994    }
995}
996
997fn parse_table_op(
998    op: &serde_json::Map<String, Value>,
999    scope: &SymbolTablePtr,
1000) -> Result<Expression> {
1001    let args = op
1002        .get("MkOpTable")
1003        .ok_or(error!("MkOpTable missing"))?
1004        .as_array()
1005        .ok_or(error!("MkOpTable is not an array"))?;
1006
1007    if args.len() != 2 {
1008        return Err(error!("MkOpTable arguments are not a 2-array"));
1009    }
1010
1011    let tuple_expr = parse_expression(&args[0], scope)?;
1012    let allowed_rows_expr = parse_expression(&args[1], scope)?;
1013
1014    let (tuple_elems, _) = tuple_expr
1015        .clone()
1016        .unwrap_matrix_unchecked()
1017        .ok_or(error!("MkOpTable first argument is not a matrix"))?;
1018    let (allowed_rows, _) = allowed_rows_expr
1019        .clone()
1020        .unwrap_matrix_unchecked()
1021        .ok_or(error!("MkOpTable second argument is not a matrix"))?;
1022
1023    for row_expr in allowed_rows {
1024        let (row_elems, _) = row_expr
1025            .unwrap_matrix_unchecked()
1026            .ok_or(error!("MkOpTable row is not a matrix"))?;
1027
1028        if row_elems.len() != tuple_elems.len() {
1029            return Err(error!("MkOpTable row width does not match tuple width"));
1030        }
1031    }
1032
1033    Ok(Expression::Table(
1034        Metadata::new(),
1035        Moo::new(tuple_expr),
1036        Moo::new(allowed_rows_expr),
1037    ))
1038}
1039
1040fn parse_indexing_slicing_op(
1041    op: &serde_json::Map<String, Value>,
1042    scope: &SymbolTablePtr,
1043) -> Result<Expression> {
1044    // we know there is a single key value pair in this object
1045    // extract the value, ignore the key
1046    let (key, value) = op
1047        .into_iter()
1048        .next()
1049        .ok_or(error!("Indexing/Slicing op object is empty"))?;
1050
1051    // we know that this is meant to be a mkopindexing, so anything that goes wrong from here is a
1052    // bug!
1053
1054    // Conjure does a[1,2,3] as MkOpIndexing(MkOpIndexing(MkOpIndexing(a,3),2),1).
1055    //
1056    // And  a[1,..,3] as MkOpIndexing(MkOpSlicing(MkOpIndexing(a,3)),1).
1057    //
1058    // However, we want this in a flattened form: Index(a, [1,2,3])
1059    let mut target: Expression;
1060    let mut indices: Vec<Option<Expression>> = vec![];
1061
1062    // true if this has no slicing, false otherwise.
1063    let mut all_known = true;
1064
1065    match key.as_str() {
1066        "MkOpIndexing" => {
1067            match &value {
1068                Value::Array(op_args) if op_args.len() == 2 => {
1069                    target = parse_expression(&op_args[0], scope)?;
1070                    indices.push(Some(parse_expression(&op_args[1], scope)?));
1071                }
1072                _ => return Err(error!("Unknown object inside MkOpIndexing")),
1073            };
1074        }
1075
1076        "MkOpSlicing" => {
1077            all_known = false;
1078            match &value {
1079                Value::Array(op_args) if op_args.len() == 3 => {
1080                    target = parse_expression(&op_args[0], scope)?;
1081                    indices.push(None);
1082                }
1083                _ => return Err(error!("Unknown object inside MkOpSlicing")),
1084            };
1085        }
1086
1087        _ => return Err(error!("Unknown indexing/slicing operator")),
1088    }
1089
1090    loop {
1091        match &mut target {
1092            Expression::UnsafeIndex(_, new_target, new_indices) => {
1093                indices.extend(new_indices.iter().cloned().rev().map(Some));
1094                target = Moo::unwrap_or_clone(new_target.clone());
1095            }
1096
1097            Expression::UnsafeSlice(_, new_target, new_indices) => {
1098                all_known = false;
1099                indices.extend(new_indices.iter().cloned().rev());
1100                target = Moo::unwrap_or_clone(new_target.clone());
1101            }
1102
1103            _ => {
1104                // not a slice or an index, we have reached the target.
1105                break;
1106            }
1107        }
1108    }
1109
1110    indices.reverse();
1111
1112    if all_known {
1113        Ok(Expression::UnsafeIndex(
1114            Metadata::new(),
1115            Moo::new(target),
1116            indices
1117                .into_iter()
1118                .collect::<Option<Vec<_>>>()
1119                .ok_or(error!("Missing index in fully-known indexing operation"))?,
1120        ))
1121    } else {
1122        Ok(Expression::UnsafeSlice(
1123            Metadata::new(),
1124            Moo::new(target),
1125            indices,
1126        ))
1127    }
1128}
1129
1130fn parse_flatten_op(
1131    op: &serde_json::Map<String, Value>,
1132    scope: &SymbolTablePtr,
1133) -> Result<Expression> {
1134    let args = op
1135        .get("MkOpFlatten")
1136        .ok_or(error!("MkOpFlatten missing"))?
1137        .as_array()
1138        .ok_or(error!("MkOpFlatten is not an array"))?;
1139
1140    let first = args
1141        .first()
1142        .ok_or(error!("MkOpFlatten missing first argument"))?;
1143    let second = args
1144        .get(1)
1145        .ok_or(error!("MkOpFlatten missing second argument"))?;
1146    let n = parse_expression(first, scope).ok();
1147    let matrix = parse_expression(second, scope)?;
1148
1149    if let Some(n) = n {
1150        Ok(Expression::Flatten(
1151            Metadata::new(),
1152            Some(Moo::new(n)),
1153            Moo::new(matrix),
1154        ))
1155    } else {
1156        Ok(Expression::Flatten(Metadata::new(), None, Moo::new(matrix)))
1157    }
1158}
1159
1160fn parse_unary_op(
1161    un_op: &serde_json::Map<String, Value>,
1162    scope: &SymbolTablePtr,
1163) -> Result<Expression> {
1164    let fail = |stage: &str| -> Error {
1165        Error::Parse(format!("Could not parse unary op at stage `{stage}`"))
1166    };
1167
1168    let (key, value) = un_op
1169        .iter()
1170        .next()
1171        .ok_or_else(|| fail("un_op.iter().next"))?;
1172    let constructor = unary_operator(key.as_str()).ok_or_else(|| fail("unary_operator"))?;
1173
1174    // unops are the main things that contain comprehensions
1175    //
1176    // if the current expr is a quantifier like and/or/sum and it contains a comprehension, let the comprehension know what it is inside.
1177    let arg = match value {
1178        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
1179            let comprehension_kind = match key.as_str() {
1180                "MkOpOr" => Some(ACOperatorKind::Or),
1181                "MkOpAnd" => Some(ACOperatorKind::And),
1182                "MkOpSum" => Some(ACOperatorKind::Sum),
1183                "MkOpProduct" => Some(ACOperatorKind::Product),
1184                _ => None,
1185            };
1186            parse_comprehension(comprehension, scope.clone(), comprehension_kind)
1187                .map_err(|_| fail("value.Comprehension.parse_comprehension"))
1188        }
1189        _ => parse_expression(value, scope).map_err(|_| fail("value.parse_expression")),
1190    }
1191    .map_err(|_| fail("arg"))?;
1192
1193    Ok(constructor(Metadata::new(), Moo::new(arg)))
1194}
1195
1196// Takes in { AbstractLiteral: .... }
1197fn parse_abstract_matrix_as_expr(
1198    value: &serde_json::Value,
1199    scope: &SymbolTablePtr,
1200) -> Result<Expression> {
1201    parser_trace!("trying to parse an abstract literal matrix");
1202    let (values, domain_name, domain_value) =
1203        if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix") {
1204            parser_trace!(".. found JSON pointer /AbstractLiteral/AbstractLitMatrix");
1205            let (domain_name, domain_value) = abs_lit_matrix
1206                .pointer("/0")
1207                .and_then(Value::as_object)
1208                .and_then(|x| x.iter().next())
1209                .ok_or(error!("AbsLitMatrix missing domain"))?;
1210            let values = abs_lit_matrix
1211                .pointer("/1")
1212                .ok_or(error!("AbsLitMatrix missing values"))?;
1213
1214            Some((values, domain_name, domain_value))
1215        }
1216        // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
1217        else if let Some(const_abs_lit_matrix) =
1218            value.pointer("/Constant/ConstantAbstract/AbsLitMatrix")
1219        {
1220            parser_trace!(".. found JSON pointer /Constant/ConstantAbstract/AbsLitMatrix");
1221            let (domain_name, domain_value) = const_abs_lit_matrix
1222                .pointer("/0")
1223                .and_then(Value::as_object)
1224                .and_then(|x| x.iter().next())
1225                .ok_or(error!("ConstantAbstract AbsLitMatrix missing domain"))?;
1226            let values = const_abs_lit_matrix
1227                .pointer("/1")
1228                .ok_or(error!("ConstantAbstract AbsLitMatrix missing values"))?;
1229
1230            Some((values, domain_name, domain_value))
1231        } else if let Some(const_abs_lit_matrix) = value.pointer("/ConstantAbstract/AbsLitMatrix") {
1232            parser_trace!(".. found JSON pointer /ConstantAbstract/AbsLitMatrix");
1233            let (domain_name, domain_value) = const_abs_lit_matrix
1234                .pointer("/0")
1235                .and_then(Value::as_object)
1236                .and_then(|x| x.iter().next())
1237                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing domain"))?;
1238            let values = const_abs_lit_matrix
1239                .pointer("/1")
1240                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing values"))?;
1241            Some((values, domain_name, domain_value))
1242        } else {
1243            None
1244        }
1245        .ok_or(error!("Could not parse abstract literal matrix"))?;
1246
1247    parser_trace!(".. found in domain and values in JSON:");
1248    parser_trace!(".. .. index domain name {domain_name}");
1249    parser_trace!(".. .. values {value}");
1250
1251    let args_parsed = values
1252        .as_array()
1253        .ok_or(error!("Matrix values are not an array"))?
1254        .iter()
1255        .map(|x| parse_expression(x, scope))
1256        .collect::<Result<Vec<Expression>>>()?;
1257
1258    if !args_parsed.is_empty() {
1259        parser_trace!(
1260            ".. successfully parsed values as expressions: {}, ... ",
1261            args_parsed[0]
1262        );
1263    } else {
1264        parser_trace!(".. successfully parsed empty values ",);
1265    }
1266
1267    let mut symbols = scope.write();
1268    match parse_domain(domain_name, domain_value, &mut symbols) {
1269        Ok(domain) => {
1270            parser_trace!("... sucessfully parsed domain as {domain}");
1271            Ok(into_matrix_expr![args_parsed;domain])
1272        }
1273        Err(_) => {
1274            parser_trace!("... failed to parse domain, creating a matrix without one.");
1275            Ok(into_matrix_expr![args_parsed])
1276        }
1277    }
1278}
1279
1280fn parse_constant(
1281    constant: &serde_json::Map<String, Value>,
1282    scope: &SymbolTablePtr,
1283) -> Result<Expression> {
1284    match &constant.get("Constant") {
1285        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
1286            let int_32: i32 = match int["ConstantInt"]
1287                .as_array()
1288                .ok_or(error!("ConstantInt is not an array"))?[1]
1289                .as_i64()
1290                .ok_or(error!("ConstantInt does not contain int"))?
1291                .try_into()
1292            {
1293                Ok(x) => x,
1294                Err(_) => return Err(error!("ConstantInt cannot be represented as i32")),
1295            };
1296
1297            Ok(Expression::Atomic(
1298                Metadata::new(),
1299                Atom::Literal(Literal::Int(int_32)),
1300            ))
1301        }
1302
1303        Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
1304            let b: bool = b["ConstantBool"]
1305                .as_bool()
1306                .ok_or(error!("ConstantBool does not contain bool"))?;
1307            Ok(Expression::Atomic(
1308                Metadata::new(),
1309                Atom::Literal(Literal::Bool(b)),
1310            ))
1311        }
1312
1313        Some(Value::Object(int)) if int.contains_key("ConstantAbstract") => {
1314            if let Some(Value::Object(obj)) = int.get("ConstantAbstract") {
1315                if let Some(arr) = obj.get("AbsLitSet") {
1316                    return parse_abs_lit(arr, scope);
1317                } else if let Some(arr) = obj.get("AbsLitMSet") {
1318                    return parse_abs_mset(arr, scope);
1319                } else if let Some(arr) = obj.get("AbsLitMatrix") {
1320                    return parse_abstract_matrix_as_expr(arr, scope);
1321                } else if let Some(arr) = obj.get("AbsLitTuple") {
1322                    return parse_abs_tuple(arr, scope);
1323                } else if let Some(arr) = obj.get("AbsLitRecord") {
1324                    return parse_abs_record(arr, scope);
1325                } else if let Some(arr) = obj.get("AbsLitFunction") {
1326                    return parse_abs_function(arr, scope);
1327                }
1328            }
1329            Err(error!("Unhandled ConstantAbstract literal type"))
1330        }
1331
1332        // sometimes (e.g. constant matrices) we can have a ConstantInt / Constant bool that is
1333        // not wrapped in Constant
1334        None => {
1335            let int_expr = constant
1336                .get("ConstantInt")
1337                .and_then(|x| x.as_array())
1338                .and_then(|x| x[1].as_i64())
1339                .and_then(|x| x.try_into().ok())
1340                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
1341
1342            if let Some(expr) = int_expr {
1343                return Ok(expr);
1344            }
1345
1346            let bool_expr = constant
1347                .get("ConstantBool")
1348                .and_then(|x| x.as_bool())
1349                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
1350
1351            if let Some(expr) = bool_expr {
1352                return Ok(expr);
1353            }
1354
1355            Err(error!(format!("Unhandled parse_constant {constant:#?}")))
1356        }
1357        otherwise => Err(error!(format!("Unhandled parse_constant {otherwise:#?}"))),
1358    }
1359}