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