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::EnumVariantVal;
11use crate::ast::Moo;
12use crate::ast::PartitionAttr;
13use crate::ast::PermutationAttr;
14use crate::ast::Reference;
15use crate::ast::Typeable;
16use crate::ast::ac_operators::ACOperatorKind;
17use crate::ast::comprehension::ComprehensionBuilder;
18use crate::ast::enumerated::{EnumVariant, EnumeratedType};
19use crate::ast::records::Field;
20use crate::ast::{
21    AbstractLiteral, Atom, BinaryAttr, DeclarationPtr, Domain, Expression, FuncAttr, IntVal,
22    JectivityAttr, Literal, MSetAttr, Name, PartialityAttr, Range, RelAttr, ReturnType,
23    SequenceAttr, SetAttr, SymbolTable, SymbolTablePtr,
24};
25use crate::ast::{DomainPtr, Metadata};
26use crate::context::Context;
27use crate::error::{Error, Result};
28use crate::{Model, bug, error, into_matrix_expr, throw_error};
29
30#[allow(unused_macros)]
31macro_rules! parser_trace {
32    ($($arg:tt)+) => {
33        log::trace!(target:"jsonparser",$($arg)+)
34    };
35}
36
37#[allow(unused_macros)]
38macro_rules! parser_debug {
39    ($($arg:tt)+) => {
40        log::debug!(target:"jsonparser",$($arg)+)
41    };
42}
43
44pub fn model_from_json(str: &str, context: Arc<RwLock<Context<'static>>>) -> Result<Model> {
45    let mut m = Model::new(context);
46    let v: JsonValue = serde_json::from_str(str)?;
47    let statements = v["mStatements"]
48        .as_array()
49        .ok_or(error!("mStatements is not an array"))?;
50
51    for statement in statements {
52        let entry = statement
53            .as_object()
54            .ok_or(error!("mStatements contains a non-object"))?
55            .iter()
56            .next()
57            .ok_or(error!("mStatements contains an empty object"))?;
58
59        match entry.0.as_str() {
60            "Declaration" => {
61                let decl = entry
62                    .1
63                    .as_object()
64                    .ok_or(error!("Declaration is not an object".to_owned()))?;
65
66                // One field in the declaration should tell us what kind it is.
67                //
68                // Find it, ignoring the other fields.
69                //
70                // e.g. FindOrGiven,
71
72                let mut valid_decl: bool = false;
73                let scope = m.symbols_ptr_unchecked().clone();
74                let model = &mut m;
75                for (kind, value) in decl {
76                    match kind.as_str() {
77                        "FindOrGiven" => {
78                            parse_variable(value, &mut model.symbols_mut())?;
79                            valid_decl = true;
80                            break;
81                        }
82                        "Letting" => {
83                            parse_letting(value, &scope)?;
84                            valid_decl = true;
85                            break;
86                        }
87                        "LettingDomainDefnEnum" => {
88                            parse_enum_declaration(value, &scope)?;
89                            valid_decl = true;
90                            break;
91                        }
92                        "LettingDomainDefnUnnamed" => {
93                            parse_unnamed_type(value, &scope)?;
94                            valid_decl = true;
95                            break;
96                        }
97                        _ => continue,
98                    }
99                }
100
101                if !valid_decl {
102                    throw_error!("Declaration is not a valid kind")?;
103                }
104            }
105            "SuchThat" => {
106                let constraints_arr = match entry.1.as_array() {
107                    Some(x) => x,
108                    None => bug!("SuchThat is not a vector"),
109                };
110
111                let constraints: Vec<Expression> = constraints_arr
112                    .iter()
113                    .map(|x| parse_expression(x, m.symbols_ptr_unchecked()))
114                    .collect::<Result<Vec<_>>>()?;
115                m.add_constraints(constraints);
116            }
117            otherwise => bug!("Unhandled Statement {:#?}", otherwise),
118        }
119    }
120    Ok(m)
121}
122
123fn parse_unnamed_type(_value: &Value, _scope: &SymbolTablePtr) -> Result<()> {
124    todo!()
125}
126
127fn parse_variable(v: &JsonValue, symtab: &mut SymbolTable) -> Result<()> {
128    let arr = v.as_array().ok_or(error!("FindOrGiven is not an array"))?;
129
130    let variable_type = arr[0]
131        .as_str()
132        .ok_or(error!("FindOrGiven[0] is not a string"))?;
133
134    let name = parse_name(&arr[1])?;
135
136    let domain = arr[2]
137        .as_object()
138        .ok_or(error!("FindOrGiven[2] is not an object"))?
139        .iter()
140        .next()
141        .ok_or(error!("FindOrGiven[2] is an empty object"))?;
142
143    let domain = parse_domain(domain.0, domain.1, symtab)?;
144
145    let decl = match variable_type {
146        "Find" => DeclarationPtr::new_find(name.clone(), domain),
147        "Given" => DeclarationPtr::new_given(name.clone(), domain),
148        _ => {
149            return Err(error!("FindOrGiven[0] is not 'Find' or 'Given'"));
150        }
151    };
152
153    symtab.insert(decl).ok_or(Error::Parse(format!(
154        "Could not add {name} to symbol table as it already exists"
155    )))
156}
157
158fn parse_letting(v: &JsonValue, scope: &SymbolTablePtr) -> Result<()> {
159    let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
160    let name = parse_name(&arr[0])?;
161
162    // value letting
163    match parse_expression(&arr[1], scope) {
164        Ok(value) => {
165            let mut symtab = scope.write();
166            symtab
167                .insert(DeclarationPtr::new_value_letting(name.clone(), value))
168                .ok_or(Error::Parse(format!(
169                    "Could not add {name} to symbol table as it already exists"
170                )))
171        }
172        Err(expression_error) => {
173            // A letting whose value is not an expression may be a domain letting. Use
174            // `get` here rather than indexing so an unsupported value expression is
175            // reported as a parse error instead of panicking on a missing `Domain` key.
176            let domain = arr[1]
177                .as_object()
178                .and_then(|value| value.get("Domain"))
179                .ok_or(expression_error)?
180                .as_object()
181                .ok_or(error!("Letting[1].Domain is not an object"))?
182                .iter()
183                .next()
184                .ok_or(error!("Letting[1].Domain is an empty object"))?;
185
186            let mut symtab = scope.write();
187            let domain = parse_domain(domain.0, domain.1, &mut symtab)?;
188
189            symtab
190                .insert(DeclarationPtr::new_domain_letting(name.clone(), domain))
191                .ok_or(Error::Parse(format!(
192                    "Could not add {name} to symbol table as it already exists"
193                )))
194        }
195    }
196}
197
198fn parse_enum_declaration(v: &JsonValue, scope: &SymbolTablePtr) -> Result<()> {
199    let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
200    let name = parse_name(&arr[0])?;
201
202    let mut symbols = scope.write();
203
204    let definition = arr[1]
205        .as_array()
206        .ok_or(error!("LettingDomainDefnEnum is not an array"))?;
207
208    let variants = definition
209        .iter()
210        .map(parse_name)
211        .collect::<Result<Vec<_>>>()?;
212
213    let ty = Moo::new(EnumeratedType::new(name.clone(), variants.clone()));
214
215    for (i, variant_name) in variants.iter().enumerate() {
216        let variant = Expression::Atomic(
217            Metadata::new(),
218            Atom::Literal(Literal::EnumVariant(EnumVariant::new(ty.clone(), i as u32))),
219        );
220
221        symbols
222            .insert(DeclarationPtr::new_value_letting(
223                variant_name.clone(),
224                variant,
225            ))
226            .ok_or(Error::Parse(format!(
227                "Could not add {variant_name} to symbol table as it already exists"
228            )))?;
229    }
230
231    symbols
232        .insert(DeclarationPtr::new_enumerated(name.clone(), ty))
233        .ok_or(Error::Parse(format!(
234            "Could not add {name} to symbol table as it already exists"
235        )))?;
236
237    Ok(())
238}
239
240fn parse_reference(v: &JsonValue, scope: &SymbolTablePtr) -> Result<Reference> {
241    let array = v
242        .as_object()
243        .ok_or(error!("Value is not an object"))?
244        .get("Reference")
245        .ok_or(error!("Reference does not exist"))?
246        .as_array()
247        .ok_or(error!("Reference is not an array"))?;
248
249    let name_value = array
250        .first()
251        .ok_or(error!("Reference does not contain name"))?;
252    let name = parse_name(name_value)?;
253    let decl = scope
254        .read()
255        .lookup(&name)
256        .ok_or(error!(format!("Symbol table does not contain '{name}'")))?;
257
258    // TODO: Second value?
259
260    Ok(Reference::new(decl))
261}
262
263fn parse_domain(
264    domain_name: &str,
265    domain_value: &JsonValue,
266    symbols: &mut SymbolTable,
267) -> Result<DomainPtr> {
268    match domain_name {
269        "DomainInt" => Ok(parse_int_domain(domain_value, symbols)?),
270        "DomainBool" => Ok(Domain::bool()),
271        "DomainReference" => {
272            let arr = domain_value
273                .as_array()
274                .ok_or(error!("DomainReference is not an array"))?;
275            let name = parse_name(&arr[0])?;
276            let ptr = symbols
277                .lookup(&name)
278                .ok_or(error!(format!("Name {name} not found")))?;
279            let dom =
280                Domain::reference(ptr).ok_or(error!("Could not construct reference domain"))?;
281            Ok(dom)
282        }
283        "DomainSet" => {
284            let dom = domain_value.get(2).and_then(|v| v.as_object());
285            let domain_obj = dom.ok_or(error!("DomainSet is missing domain object"))?;
286            let domain = domain_obj
287                .iter()
288                .next()
289                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
290            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
291            let size = domain_value
292                .get(1)
293                .and_then(|v| v.as_object())
294                .ok_or(error!("Set size attributes is not an object"))?;
295            let size = parse_size_attr(size, symbols)?;
296            let attr: SetAttr<IntVal> = SetAttr::new(size);
297            Ok(Domain::set(attr, domain))
298        }
299        "DomainMSet" => {
300            let dom = domain_value
301                .get(2)
302                .and_then(|v| v.as_object())
303                .expect("domain object exists");
304            let domain = dom
305                .iter()
306                .next()
307                .ok_or(Error::Parse("DomainMSet is an empty object".to_owned()))?;
308            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
309
310            // Parse Attributes
311            let attributes = domain_value
312                .get(1)
313                .and_then(|v| v.as_array())
314                .ok_or(error!("MSet attributes is not a json array"))?;
315
316            let size = attributes
317                .first()
318                .and_then(|v| v.as_object())
319                .ok_or(error!("MSet size attributes is not an object"))?;
320            let size = parse_size_attr(size, symbols)?;
321
322            let occurrence = attributes
323                .get(1)
324                .and_then(|v| v.as_object())
325                .ok_or(error!("MSet occurrence attributes is not an object"))?;
326            let occurrence = parse_occur_attr(occurrence, symbols)?;
327
328            let attr: MSetAttr<IntVal> = MSetAttr {
329                size,
330                occurrence,
331                representation: None,
332            };
333            Ok(Domain::mset(attr, domain))
334        }
335        "DomainPartition" => {
336            let dom = domain_value
337                .get(2)
338                .and_then(|v| v.as_object())
339                .expect("domain object exists");
340            let domain = dom.iter().next().ok_or(Error::Parse(
341                "DomainPartition is an empty object".to_owned(),
342            ))?;
343            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
344
345            let attributes = domain_value
346                .get(1)
347                .and_then(|v| v.as_object())
348                .ok_or(error!("Partition attributes is not an object"))?;
349
350            let mut num_parts = Range::Unbounded;
351            let mut part_len = Range::Unbounded;
352            let mut is_regular = false;
353
354            if let Some(val) = attributes.get("partsNum") {
355                let attr_map = val.as_object().expect("numParts should be an object");
356                num_parts = parse_size_attr(attr_map, symbols)?;
357            }
358            if let Some(val) = attributes.get("partsSize") {
359                let attr_map = val.as_object().expect("partsSize should be an object");
360                part_len = parse_size_attr(attr_map, symbols)?;
361            }
362            if let Some(val) = attributes.get("isRegular").and_then(|v| v.as_bool()) {
363                is_regular = val;
364            }
365
366            let attr: PartitionAttr<IntVal> = PartitionAttr {
367                num_parts,
368                part_len,
369                is_regular,
370                representation: None,
371            };
372            Ok(Domain::partition(attr, domain))
373        }
374        "DomainPermutation" => {
375            let dom = domain_value
376                .get(2)
377                .and_then(|v| v.as_object())
378                .expect("domain object exists");
379            let domain = dom.iter().next().ok_or(Error::Parse(
380                "DomainPermutation is an empty object".to_owned(),
381            ))?;
382            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
383
384            let attributes = domain_value
385                .get(1)
386                .and_then(|v| v.as_object())
387                .ok_or(error!("Permutation attributes is not an object"))?;
388
389            let mut num_moved = Range::Unbounded;
390            if let Some(val) = attributes.get("numMoved") {
391                let attr_map = val.as_object().expect("numMoved should be an object");
392                num_moved = parse_size_attr(attr_map, symbols)?;
393            }
394
395            let attr: PermutationAttr<IntVal> = PermutationAttr {
396                num_moved,
397                representation: None,
398            };
399            Ok(Domain::permutation(attr, domain))
400        }
401        "DomainMatrix" => {
402            let domain_value = domain_value
403                .as_array()
404                .ok_or(error!("Domain matrix is not an array"))?;
405
406            let indexed_by_domain = domain_value[0].clone();
407            let (index_domain_name, index_domain_value) = indexed_by_domain
408                .as_object()
409                .ok_or(error!("DomainMatrix[0] is not an object"))?
410                .iter()
411                .next()
412                .ok_or(error!(""))?;
413
414            let (value_domain_name, value_domain_value) = domain_value[1]
415                .as_object()
416                .ok_or(error!(""))?
417                .iter()
418                .next()
419                .ok_or(error!(""))?;
420
421            // Conjure stores a 2-d matrix as a matrix of a matrix.
422            //
423            // Therefore, the index is always a Domain.
424
425            let mut index_domains: Vec<DomainPtr> = vec![];
426
427            index_domains.push(parse_domain(
428                index_domain_name,
429                index_domain_value,
430                symbols,
431            )?);
432
433            // We want to store 2-d matrices as a matrix with two index domains, not a matrix in a
434            // matrix.
435            //
436            // Walk through the value domain until it is not a DomainMatrix, adding the index to
437            // our list of indices.
438            let mut value_domain = parse_domain(value_domain_name, value_domain_value, symbols)?;
439            while let Some((new_value_domain, mut indices)) = value_domain.as_matrix() {
440                index_domains.append(&mut indices);
441                value_domain = new_value_domain.clone()
442            }
443
444            Ok(Domain::matrix(value_domain, index_domains))
445        }
446
447        "DomainSequence" => {
448            let dom = domain_value
449                .get(2)
450                .and_then(|v| v.as_object())
451                .expect("domain object exists");
452            let domain = dom
453                .iter()
454                .next()
455                .ok_or(Error::Parse("DomainSequence is an empty object".to_owned()))?;
456            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
457
458            // Parse Attributes
459            let attributes = domain_value
460                .get(1)
461                .and_then(|v| v.as_array())
462                .ok_or(error!("Sequence attributes is not a json array"))?;
463
464            let size = attributes
465                .first()
466                .and_then(|v| v.as_object())
467                .ok_or(error!("Sequence size attributes is not an object"))?;
468            let size = parse_size_attr(size, symbols)?;
469
470            let jectivity = attributes
471                .get(1)
472                .and_then(|v| v.as_str())
473                .ok_or(error!("jectivity is not a string"))?;
474            let jectivity = match jectivity {
475                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
476                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
477                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
478                "JectivityAttr_None" => Some(JectivityAttr::None),
479                _ => None,
480            };
481            let jectivity =
482                jectivity.ok_or(Error::Parse("Jectivity is an unknown type".to_owned()))?;
483
484            let attr: SequenceAttr<IntVal> = SequenceAttr {
485                size,
486                jectivity,
487                representation: None,
488            };
489            match attr.size {
490                Range::Unbounded | Range::UnboundedR(_) => Err(Error::Parse(
491                    "Sequence must have size or maxSize attribute".to_string(),
492                )),
493                _ => Ok(Domain::sequence(attr, domain)),
494            }
495        }
496
497        "DomainTuple" => {
498            let domain_value = domain_value
499                .as_array()
500                .ok_or(error!("Domain tuple is not an array"))?;
501
502            //iterate through the array and parse each domain
503            let domain = domain_value
504                .iter()
505                .map(|x| {
506                    let domain = x
507                        .as_object()
508                        .ok_or(error!("DomainTuple[0] is not an object"))?
509                        .iter()
510                        .next()
511                        .ok_or(error!("DomainTuple[0] is an empty object"))?;
512                    parse_domain(domain.0, domain.1, symbols)
513                })
514                .collect::<Result<Vec<DomainPtr>>>()?;
515
516            Ok(Domain::tuple(domain))
517        }
518        "DomainRecord" | "DomainVariant" => {
519            // Records and Variants can be parsed the same way for the most part
520            let is_record = domain_name == "DomainRecord";
521            // Get the actual string for error message purposes
522            let domain_string = match is_record {
523                true => "Record",
524                false => "Variant",
525            };
526            let domain_value = domain_value.as_array().ok_or(error!(&format!(
527                "Domain {domain_string} is not a json array"
528            )))?;
529
530            let mut entries = vec![];
531
532            for item in domain_value {
533                // collect the name of the field
534                let name = parse_name(&item[0])?;
535
536                // then collect the domain of the field
537                let domain = item[1]
538                    .as_object()
539                    .ok_or(error!("FindOrGiven[2] is not an object"))?
540                    .iter()
541                    .next()
542                    .ok_or(error!("FindOrGiven[2] is an empty object"))?;
543
544                let rec = Field {
545                    name,
546                    value: parse_domain(domain.0, domain.1, symbols)?,
547                };
548
549                entries.push(rec);
550            }
551
552            if is_record {
553                Ok(Domain::record(entries))
554            } else {
555                Ok(Domain::variant(entries))
556            }
557        }
558        "DomainFunction" => {
559            let domain = domain_value
560                .get(2)
561                .and_then(|v| v.as_object())
562                .ok_or(error!("Function domain is not an object"))?;
563            let domain = domain
564                .iter()
565                .next()
566                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
567            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
568
569            let codomain = domain_value
570                .get(3)
571                .and_then(|v| v.as_object())
572                .ok_or(error!("Function codomain is not an object"))?;
573            let codomain = codomain
574                .iter()
575                .next()
576                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
577            let codomain = parse_domain(codomain.0.as_str(), codomain.1, symbols)?;
578
579            // Attribute parsing
580            let attributes = domain_value
581                .get(1)
582                .and_then(|v| v.as_array())
583                .ok_or(error!("Function attributes is not a json array"))?;
584            let size = attributes
585                .first()
586                .and_then(|v| v.as_object())
587                .ok_or(error!("Function size attributes is not an object"))?;
588            let size = parse_size_attr(size, symbols)?;
589            let partiality = attributes
590                .get(1)
591                .and_then(|v| v.as_str())
592                .ok_or(error!("Function partiality is not a string"))?;
593            let partiality = match partiality {
594                "PartialityAttr_Partial" => Some(PartialityAttr::Partial),
595                "PartialityAttr_Total" => Some(PartialityAttr::Total),
596                _ => None,
597            };
598            let partiality =
599                partiality.ok_or(Error::Parse("Partiality is an unknown type".to_owned()))?;
600            let jectivity = attributes
601                .get(2)
602                .and_then(|v| v.as_str())
603                .ok_or(error!("Function jectivity is not a string"))?;
604            let jectivity = match jectivity {
605                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
606                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
607                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
608                "JectivityAttr_None" => Some(JectivityAttr::None),
609                _ => None,
610            };
611            let jectivity =
612                jectivity.ok_or(Error::Parse("Jectivity is an unknown type".to_owned()))?;
613
614            let attr: FuncAttr<IntVal> = FuncAttr {
615                size,
616                partiality,
617                jectivity,
618                representation: None,
619            };
620
621            Ok(Domain::function(attr, domain, codomain))
622        }
623        "DomainRelation" => {
624            let domains = domain_value
625                .get(2)
626                .and_then(|v| v.as_array())
627                .ok_or(Error::Parse(
628                    "Relation domains are not a json array".to_owned(),
629                ))?;
630            let domains = domains
631                .iter()
632                .map(|x| {
633                    let domain = x
634                        .as_object()
635                        .ok_or(Error::Parse("Relation domain is not an object".to_owned()))?
636                        .iter()
637                        .next()
638                        .ok_or(Error::Parse(
639                            "Relation domain is an empty object".to_owned(),
640                        ))?;
641                    parse_domain(domain.0, domain.1, symbols)
642                })
643                .collect::<Result<Vec<DomainPtr>>>()?;
644
645            // Attribute parsing
646            let attributes = domain_value
647                .get(1)
648                .and_then(|v| v.as_array())
649                .ok_or(Error::Parse(
650                    "Relation attributes are not a json array".to_owned(),
651                ))?;
652            let size = attributes
653                .first()
654                .and_then(|v| v.as_object())
655                .ok_or(Error::Parse(
656                    "Relation size attributes are not an object".to_owned(),
657                ))?;
658            let size = parse_size_attr(size, symbols)?;
659            let binary = attributes
660                .get(1)
661                .and_then(|v| v.as_array())
662                .ok_or(Error::Parse(
663                    "Relation binary attributes are not a json array".to_owned(),
664                ))?;
665            let binary = binary
666                .iter()
667                .map(|x| {
668                    let attr = x.as_str().ok_or(Error::Parse(
669                        "Relation binary attribute is not a string".to_owned(),
670                    ))?;
671                    match attr {
672                        "BinRelAttr_Reflexive" => Ok(BinaryAttr::Reflexive),
673                        "BinRelAttr_Irreflexive" => Ok(BinaryAttr::Irreflexive),
674                        "BinRelAttr_Coreflexive" => Ok(BinaryAttr::Coreflexive),
675                        "BinRelAttr_Symmetric" => Ok(BinaryAttr::Symmetric),
676                        "BinRelAttr_AntiSymmetric" => Ok(BinaryAttr::AntiSymmetric),
677                        "BinRelAttr_ASymmetric" => Ok(BinaryAttr::ASymmetric),
678                        "BinRelAttr_Transitive" => Ok(BinaryAttr::Transitive),
679                        "BinRelAttr_Total" => Ok(BinaryAttr::Total),
680                        "BinRelAttr_Connex" => Ok(BinaryAttr::Connex),
681                        "BinRelAttr_Euclidean" => Ok(BinaryAttr::Euclidean),
682                        "BinRelAttr_Serial" => Ok(BinaryAttr::Serial),
683                        "BinRelAttr_Equivalence" => Ok(BinaryAttr::Equivalence),
684                        "BinRelAttr_PartialOrder" => Ok(BinaryAttr::PartialOrder),
685                        "BinRelAttr_LeftTotal" => Ok(BinaryAttr::LeftTotal),
686                        "BinRelAttr_RightTotal" => Ok(BinaryAttr::RightTotal),
687                        "BinRelAttr_LinearOrder" => Ok(BinaryAttr::LinearOrder),
688                        "BinRelAttr_WeakOrder" => Ok(BinaryAttr::WeakOrder),
689                        "BinRelAttr_PreOrder" => Ok(BinaryAttr::PreOrder),
690                        "BinRelAttr_StrictPartialOrder" => Ok(BinaryAttr::StrictPartialOrder),
691                        _ => Err(Error::Parse(
692                            "Relation binary attribute is invalid".to_owned(),
693                        )),
694                    }
695                })
696                .collect::<Result<Vec<BinaryAttr>>>()?;
697
698            let attr: RelAttr<IntVal> = RelAttr {
699                size,
700                binary,
701                representation: None,
702            };
703
704            Ok(Domain::relation(attr, domains))
705        }
706        "DomainEnum" => {
707            let scope = SymbolTablePtr::new();
708            *scope.write() = symbols.clone();
709
710            let arr = domain_value
711                .as_array()
712                .ok_or(Error::Parse("DomainEnum is not an array".to_owned()))?;
713
714            let name = parse_name(&arr[0])?;
715            let decl = symbols
716                .lookup(&name)
717                .ok_or(Error::Parse(format!("Enum {name} does not exist")))?;
718
719            let Some(et) = decl.as_enumerated_type() else {
720                return Err(Error::Parse(format!(
721                    "Declaration {name} is not an enumerated type"
722                )));
723            };
724
725            let ranges =
726                parse_range_list(&arr[1], |r| parse_reference(r, &scope).map(EnumVariantVal))?;
727
728            Ok(Domain::enumerated(et.clone(), ranges))
729        }
730        _ => Err(Error::Parse(
731            "FindOrGiven[2] is an unknown object".to_owned(), // consider covered
732        )),
733    }
734}
735
736fn parse_name(v: &JsonValue) -> Result<Name> {
737    let name = v
738        .as_object()
739        .ok_or(error!("Value is not an object"))?
740        .get("Name")
741        .ok_or(error!("Name does not exist"))?
742        .as_str()
743        .ok_or(error!("Name is not a string"))?;
744
745    Ok(Name::User(Ustr::from(name)))
746}
747
748fn parse_size_attr(
749    attr_map: &JsonMap<String, JsonValue>,
750    symbols: &mut SymbolTable,
751) -> Result<Range<IntVal>> {
752    let scope = SymbolTablePtr::new();
753    *scope.write() = symbols.clone();
754
755    let attr_obj = attr_map
756        .iter()
757        .next()
758        .ok_or(Error::Parse("SizeAttr is an empty object".to_owned()))?;
759    match attr_obj.0.as_str() {
760        "SizeAttr_None" => Ok(Range::Unbounded),
761        "SizeAttr_MinSize" => {
762            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
763            Ok(Range::UnboundedR(size))
764        }
765        "SizeAttr_MaxSize" => {
766            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
767            Ok(Range::UnboundedL(size))
768        }
769        "SizeAttr_MinMaxSize" => {
770            let min_max = attr_obj
771                .1
772                .as_array()
773                .ok_or(error!("SizeAttr MinMaxSize is not a json array"))?;
774            let min = min_max
775                .first()
776                .ok_or(error!("SizeAttr Min is not present"))?;
777            let min_int = parse_expression_to_int_val(min, &scope)?;
778            let max = min_max
779                .get(1)
780                .ok_or(error!("SizeAttr Max is not present"))?;
781            let max_int = parse_expression_to_int_val(max, &scope)?;
782            Ok(Range::Bounded(min_int, max_int))
783        }
784        "SizeAttr_Size" => {
785            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
786            Ok(Range::Single(size))
787        }
788        _ => Err(Error::Parse("SizeAttr is an unknown type".to_owned())),
789    }
790}
791
792fn parse_occur_attr(
793    attr_map: &JsonMap<String, JsonValue>,
794    symbols: &mut SymbolTable,
795) -> Result<Range<IntVal>> {
796    let scope = SymbolTablePtr::new();
797    *scope.write() = symbols.clone();
798    let attr_obj = attr_map
799        .iter()
800        .next()
801        .ok_or(Error::Parse("OccurAttr is an empty object".to_owned()))?;
802    match attr_obj.0.as_str() {
803        "OccurAttr_None" => Ok(Range::Unbounded),
804        "OccurAttr_MinOccur" => {
805            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
806            Ok(Range::UnboundedR(size_int))
807        }
808        "OccurAttr_MaxOccur" => {
809            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
810            Ok(Range::UnboundedL(size_int))
811        }
812        "OccurAttr_MinMaxOccur" => {
813            let min_max = attr_obj
814                .1
815                .as_array()
816                .ok_or(error!("OccurAttr MinMaxOccur is not a json array"))?;
817            let min = min_max
818                .first()
819                .ok_or(error!("OccurAttr Min is not present"))?;
820            let min_int = parse_expression_to_int_val(min, &scope)?;
821            let max = min_max
822                .get(1)
823                .ok_or(error!("OccurAttr Max is not present"))?;
824            let max_int = parse_expression_to_int_val(max, &scope)?;
825            Ok(Range::Bounded(min_int, max_int))
826        }
827        "OccurAttr_Size" => {
828            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
829            Ok(Range::Single(size_int))
830        }
831        _ => Err(Error::Parse("OccurAttr is an unknown type".to_owned())),
832    }
833}
834
835fn parse_int_domain(v: &JsonValue, symbols: &SymbolTable) -> Result<DomainPtr> {
836    let scope = SymbolTablePtr::new();
837    *scope.write() = symbols.clone();
838    let range_values = &v
839        .as_array()
840        .ok_or(Error::Parse("DomainInt[1] is not an array".to_owned()))?[1];
841    if range_values.as_array().is_some_and(Vec::is_empty) {
842        return Ok(Domain::int_ground(vec![Range::Unbounded]));
843    }
844    let ranges = parse_range_list(range_values, |v| parse_expression_to_int_val(v, &scope))?;
845    Ok(Domain::int(ranges))
846}
847
848fn parse_range<T: Clone>(
849    v: &JsonValue,
850    // scope: &SymbolTablePtr,
851    parser: &impl Fn(&JsonValue) -> Result<T>,
852) -> Result<Range<T>> {
853    let range = v
854        .as_object()
855        .ok_or(error!("Range is not an bject"))?
856        .iter()
857        .next()
858        .ok_or(error!("Range is an empty object"))?;
859
860    match range.0.as_str() {
861        "RangeBounded" => {
862            let arr = range
863                .1
864                .as_array()
865                .ok_or(error!("RangeBounded is not an array".to_owned()))?;
866            let mut nums = Vec::new();
867            for item in arr.iter() {
868                let num = parser(item)?;
869                nums.push(num);
870            }
871            let lower = nums
872                .first()
873                .cloned()
874                .ok_or(error!("RangeBounded lower bound missing"))?;
875            let upper = nums
876                .get(1)
877                .cloned()
878                .ok_or(error!("RangeBounded upper bound missing"))?;
879            Ok(Range::Bounded(lower, upper))
880        }
881        "RangeSingle" => {
882            let num = parser(range.1)?;
883            Ok(Range::Single(num))
884        }
885        _ => throw_error!("DomainInt[1] contains an unknown object"),
886    }
887}
888
889fn parse_range_list<T: Clone>(
890    v: &JsonValue,
891    // scope: &SymbolTablePtr,
892    parser: impl Fn(&JsonValue) -> Result<T>,
893) -> Result<Vec<Range<T>>> {
894    v.as_array()
895        .ok_or(error!("Value is not an array".to_owned()))?
896        .iter()
897        .map(|r| parse_range(r, &parser))
898        .collect()
899}
900
901fn parse_expression_to_int_val(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<IntVal> {
902    parser_trace!("trying to parse domain value as expression: {}", obj);
903    let expr = parse_expression(obj, scope)?;
904
905    if let Some(Literal::Int(i)) = expr.clone().into_literal() {
906        return Ok(IntVal::Const(i as i64));
907    }
908
909    if let Expression::Atomic(_, Atom::Reference(reference)) = &expr
910        && let Ok(reference_val) = IntVal::new_ref(reference)
911    {
912        return Ok(reference_val);
913    }
914
915    IntVal::new_expr(Moo::new(expr))
916        .map_err(|e| error!(format!("Could not parse integer expression: {e}")))
917}
918
919type BinOp = fn(Metadata, Moo<Expression>, Moo<Expression>) -> Expression;
920type UnaryOp = fn(Metadata, Moo<Expression>) -> Expression;
921
922fn binary_operator(op_name: &str) -> Option<BinOp> {
923    match op_name {
924        "MkOpIn" => Some(Expression::In),
925        "MkOpUnion" => Some(Expression::Union),
926        "MkOpIntersect" => Some(Expression::Intersect),
927        "MkOpSupset" => Some(Expression::Supset),
928        "MkOpSupsetEq" => Some(Expression::SupsetEq),
929        "MkOpSubset" => Some(Expression::Subset),
930        "MkOpSubsetEq" => Some(Expression::SubsetEq),
931        "MkOpEq" => Some(Expression::Eq),
932        "MkOpNeq" => Some(Expression::Neq),
933        "MkOpGeq" => Some(Expression::Geq),
934        "MkOpLeq" => Some(Expression::Leq),
935        "MkOpGt" => Some(Expression::Gt),
936        "MkOpLt" => Some(Expression::Lt),
937        "MkOpLexLt" => Some(Expression::LexLt),
938        "MkOpLexGt" => Some(Expression::LexGt),
939        "MkOpLexLeq" => Some(Expression::LexLeq),
940        "MkOpLexGeq" => Some(Expression::LexGeq),
941        "MkOpDiv" => Some(Expression::UnsafeDiv),
942        "MkOpMod" => Some(Expression::UnsafeMod),
943        "MkOpMinus" => Some(Expression::Minus),
944        "MkOpImply" => Some(Expression::Imply),
945        "MkOpIff" => Some(Expression::Iff),
946        "MkOpPow" => Some(Expression::UnsafePow),
947        "MkOpImage" => Some(Expression::Image),
948        "MkOpImageSet" => Some(Expression::ImageSet),
949        "MkOpPreImage" => Some(Expression::PreImage),
950        "MkOpInverse" => Some(Expression::Inverse),
951        "MkOpCompose" => Some(Expression::Compose),
952        "MkOpRestrict" => Some(Expression::Restrict),
953        "MkOpApart" => Some(Expression::Apart),
954        "MkOpTogether" => Some(Expression::Together),
955        "MkOpParty" => Some(Expression::Party),
956        "MkOpSubstring" => Some(Expression::Substring),
957        "MkOpSubsequence" => Some(Expression::Subsequence),
958        _ => None,
959    }
960}
961
962fn unary_operator(op_name: &str, inner: Option<&Expression>) -> Option<UnaryOp> {
963    match op_name {
964        "MkOpNot" => Some(Expression::Not),
965        "MkOpNegate" => Some(Expression::Neg),
966        "MkOpTwoBars" => {
967            if let Some(inner) = inner {
968                match inner.return_type() {
969                    ReturnType::Int => Some(Expression::Abs),
970                    ReturnType::Matrix(_)
971                    | ReturnType::Set(_)
972                    | ReturnType::MSet(_)
973                    | ReturnType::Function(_, _)
974                    | ReturnType::Relation(_) => Some(Expression::Card),
975                    _ => None,
976                }
977            } else {
978                // Internal expression cannot be known yet, so we just have to assume
979                Some(Expression::Abs)
980            }
981        }
982        "MkOpAnd" => Some(Expression::And),
983        "MkOpSum" => Some(Expression::Sum),
984        "MkOpProduct" => Some(Expression::Product),
985        "MkOpOr" => Some(Expression::Or),
986        "MkOpMin" => Some(Expression::Min),
987        "MkOpMax" => Some(Expression::Max),
988        "MkOpAllDiff" => Some(Expression::AllDiff),
989        "MkOpToInt" => Some(Expression::ToInt),
990        "MkOpDefined" => Some(Expression::Defined),
991        "MkOpPermInverse" => Some(Expression::PermInverse),
992        "MkOpRange" => Some(Expression::Range),
993        "MkOpFactorial" => Some(Expression::Factorial),
994        "MkOpToMSet" => Some(Expression::ToMSet),
995        "MkOpToRelation" => Some(Expression::ToRelation),
996        "MkOpPred" => Some(Expression::Pred),
997        "MkOpSucc" => Some(Expression::Succ),
998        "MkOpParticipants" => Some(Expression::Participants),
999        "MkOpParts" => Some(Expression::Parts),
1000        _ => None,
1001    }
1002}
1003
1004fn parse_reference_name(obj: &JsonValue) -> Result<Name> {
1005    // { Name: "x" } directly
1006    if let Some(name) = obj.get("Name").and_then(|x| x.as_str()) {
1007        return Ok(Name::User(Ustr::from(name)));
1008    }
1009
1010    // {
1011    //   Reference: [
1012    //     { Name: "x" }
1013    //   ]
1014    // }
1015    let ref_arr = obj["Reference"]
1016        .as_array()
1017        .ok_or_else(|| error!("Reference.as_array"))?;
1018    let ref_obj = ref_arr
1019        .first()
1020        .and_then(|x| x.as_object())
1021        .ok_or_else(|| error!("Reference[0].as_object"))?;
1022    let name = ref_obj
1023        .get("Name")
1024        .and_then(|x| x.as_str())
1025        .ok_or_else(|| error!("Reference[0].Name.as_str"))?;
1026    Ok(Name::User(Ustr::from(name)))
1027}
1028
1029pub fn parse_expression(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<Expression> {
1030    let fail = |stage: &str| -> Error {
1031        Error::Parse(format!(
1032            "Could not parse expression at stage `{stage}` for json `{obj}`"
1033        ))
1034    };
1035
1036    match obj {
1037        Value::Object(op) if op.contains_key("Op") => {
1038            let op_obj = op
1039                .get("Op")
1040                .and_then(Value::as_object)
1041                .ok_or_else(|| fail("Op.as_object"))?;
1042            let (op_name, _) = op_obj.iter().next().ok_or_else(|| fail("Op.iter().next"))?;
1043
1044            if op_obj.contains_key("MkOpFlatten") {
1045                parse_flatten_op(op_obj, scope)
1046            } else if op_obj.contains_key("MkOpTable") {
1047                parse_table_op(op_obj, scope)
1048            } else if op_obj.contains_key("MkOpIndexing") || op_obj.contains_key("MkOpSlicing") {
1049                parse_indexing_slicing_op(op_obj, scope)
1050            } else if op_obj.contains_key("MkOpActive") {
1051                parse_active_op(op_obj, scope)
1052            } else if op_obj.contains_key("MkOpRelationProj") {
1053                parse_relation_projection(op_obj, scope)
1054            } else if op_obj.contains_key("MkOpToSet") {
1055                parse_to_set(op_obj, scope)
1056            } else if binary_operator(op_name).is_some() {
1057                parse_bin_op(op_obj, scope)
1058            } else if unary_operator(op_name, None).is_some() {
1059                parse_unary_op(op_obj, scope)
1060            } else {
1061                Err(fail("Op.unknown"))
1062            }
1063        }
1064        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
1065            parse_comprehension(comprehension, scope.clone())
1066        }
1067        Value::Object(refe) if refe.contains_key("Reference") => {
1068            let reference = parse_reference(obj, scope)?;
1069
1070            Ok(Expression::Atomic(
1071                Metadata::new(),
1072                Atom::Reference(reference),
1073            ))
1074        }
1075        // In the case where refering to fields. This not behind a reference
1076        Value::Object(refe) if refe.contains_key("Name") => {
1077            let name = refe
1078                .get("Name")
1079                .and_then(|x| x.as_str())
1080                .ok_or_else(|| fail("Reference[0].Name.as_str"))?;
1081            let user_name = Name::User(Ustr::from(name));
1082
1083            let declaration: DeclarationPtr = scope
1084                .read()
1085                .lookup(&user_name)
1086                .ok_or_else(|| fail("Reference.lookup"))?;
1087
1088            Ok(Expression::Atomic(
1089                Metadata::new(),
1090                Atom::Reference(crate::ast::Reference::new(declaration)),
1091            ))
1092        }
1093        Value::Object(abslit) if abslit.contains_key("AbstractLiteral") => {
1094            let abstract_literal = abslit["AbstractLiteral"]
1095                .as_object()
1096                .ok_or_else(|| fail("AbstractLiteral.as_object"))?;
1097
1098            if abstract_literal.contains_key("AbsLitSet") {
1099                parse_abs_lit(&abslit["AbstractLiteral"]["AbsLitSet"], scope)
1100            } else if abstract_literal.contains_key("AbsLitFunction") {
1101                parse_abs_function(&abslit["AbstractLiteral"]["AbsLitFunction"], scope)
1102            } else if abstract_literal.contains_key("AbsLitMSet") {
1103                parse_abs_mset(&abslit["AbstractLiteral"]["AbsLitMSet"], scope)
1104            } else if abstract_literal.contains_key("AbsLitVariant") {
1105                parse_abs_variant(&abslit["AbstractLiteral"]["AbsLitVariant"], scope)
1106            } else if abstract_literal.contains_key("AbsLitRelation") {
1107                parse_abs_relation(&abslit["AbstractLiteral"]["AbsLitRelation"], scope)
1108            } else if abstract_literal.contains_key("AbsLitPartition") {
1109                parse_abs_partition(&abslit["AbstractLiteral"]["AbsLitPartition"], scope)
1110            } else if abstract_literal.contains_key("AbsLitPermutation") {
1111                parse_abs_permutation(&abslit["AbstractLiteral"]["AbsLitPermutation"], scope)
1112            } else if abstract_literal.contains_key("AbsLitSequence") {
1113                parse_abs_sequence(&abslit["AbstractLiteral"]["AbsLitSequence"], scope)
1114            } else {
1115                parse_abstract_matrix_as_expr(obj, scope)
1116            }
1117        }
1118
1119        Value::Object(constant) if constant.contains_key("Constant") => {
1120            parse_constant(constant, scope).or_else(|_| parse_abstract_matrix_as_expr(obj, scope))
1121        }
1122
1123        Value::Object(constant) if constant.contains_key("ConstantAbstract") => {
1124            let literal = constant
1125                .get("ConstantAbstract")
1126                .and_then(Value::as_object)
1127                .ok_or_else(|| fail("ConstantAbstract.as_object"))?;
1128            if literal.contains_key("AbsLitMatrix") {
1129                parse_abstract_matrix_as_expr(obj, scope)
1130            } else {
1131                parse_constant_abstract(literal, scope)
1132            }
1133        }
1134
1135        Value::Object(constant) if constant.contains_key("ConstantInt") => {
1136            parse_constant(constant, scope)
1137        }
1138        Value::Object(constant) if constant.contains_key("ConstantBool") => {
1139            parse_constant(constant, scope)
1140        }
1141
1142        _ => Err(fail("no_match")),
1143    }
1144}
1145
1146fn parse_abs_lit(abs_set: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1147    let values = abs_set
1148        .as_array()
1149        .ok_or(error!("AbsLitSet is not an array"))?;
1150    let expressions = values
1151        .iter()
1152        .map(|values| parse_expression(values, scope))
1153        .collect::<Result<Vec<_>>>()?;
1154
1155    Ok(Expression::AbstractLiteral(
1156        Metadata::new(),
1157        AbstractLiteral::Set(expressions),
1158    ))
1159}
1160
1161fn parse_constant_abstract(
1162    literal: &serde_json::Map<String, Value>,
1163    scope: &SymbolTablePtr,
1164) -> Result<Expression> {
1165    if let Some(value) = literal.get("AbsLitSet") {
1166        parse_abs_lit(value, scope)
1167    } else if let Some(value) = literal.get("AbsLitMSet") {
1168        parse_abs_mset(value, scope)
1169    } else if let Some(value) = literal.get("AbsLitTuple") {
1170        parse_abs_tuple(value, scope)
1171    } else if let Some(value) = literal.get("AbsLitRecord") {
1172        parse_abs_record(value, scope)
1173    } else if let Some(value) = literal.get("AbsLitPartition") {
1174        parse_abs_partition(value, scope)
1175    } else if let Some(value) = literal.get("AbsLitPermutation") {
1176        parse_abs_permutation(value, scope)
1177    } else if let Some(value) = literal.get("AbsLitFunction") {
1178        parse_abs_function(value, scope)
1179    } else if let Some(value) = literal.get("AbsLitVariant") {
1180        parse_abs_variant(value, scope)
1181    } else if let Some(value) = literal.get("AbsLitRelation") {
1182        parse_abs_relation(value, scope)
1183    } else if let Some(value) = literal.get("AbsLitSequence") {
1184        parse_abs_sequence(value, scope)
1185    } else {
1186        Err(error!("Unhandled ConstantAbstract literal type"))
1187    }
1188}
1189
1190fn parse_abs_mset(abs_mset: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1191    let values = abs_mset
1192        .as_array()
1193        .ok_or(error!("AbsLitMSet is not an array"))?;
1194    let expressions = values
1195        .iter()
1196        .map(|values| parse_expression(values, scope))
1197        .collect::<Result<Vec<_>>>()?;
1198
1199    Ok(Expression::AbstractLiteral(
1200        Metadata::new(),
1201        AbstractLiteral::MSet(expressions),
1202    ))
1203}
1204
1205fn parse_abs_partition(abs_partition: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1206    let parts = abs_partition
1207        .as_array()
1208        .ok_or(error!("AbsLitPartition is not an array"))?;
1209
1210    let mut partition: Vec<Vec<_>> = Vec::new();
1211
1212    for part in parts {
1213        let vals = part
1214            .as_array()
1215            .ok_or(error!("Part in AbsLitPartition is not an array"))?;
1216
1217        let exprs = vals
1218            .iter()
1219            .map(|values| parse_expression(values, scope))
1220            .collect::<Result<Vec<_>>>()?;
1221
1222        partition.push(exprs);
1223    }
1224
1225    Ok(Expression::AbstractLiteral(
1226        Metadata::new(),
1227        AbstractLiteral::Partition(partition),
1228    ))
1229}
1230
1231fn parse_abs_permutation(abs_permutation: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1232    let cycles = abs_permutation
1233        .as_array()
1234        .ok_or(error!("AbsLitPermutation is not an array"))?;
1235
1236    let mut permutation: Vec<Vec<_>> = Vec::new();
1237
1238    for cycle in cycles {
1239        let vals = cycle
1240            .as_array()
1241            .ok_or(error!("Cycle in AbsLitPermutation is not an array"))?;
1242
1243        let exprs = vals
1244            .iter()
1245            .map(|values| parse_expression(values, scope))
1246            .collect::<Result<Vec<_>>>()?;
1247
1248        permutation.push(exprs);
1249    }
1250
1251    Ok(Expression::AbstractLiteral(
1252        Metadata::new(),
1253        AbstractLiteral::Permutation(permutation),
1254    ))
1255}
1256
1257fn parse_abs_sequence(abs_seq: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1258    let values = abs_seq
1259        .as_array()
1260        .ok_or(error!("AbsLitSequence is not an array"))?;
1261    let expressions = values
1262        .iter()
1263        .map(|values| parse_expression(values, scope))
1264        .collect::<Result<Vec<_>>>()?;
1265
1266    Ok(Expression::AbstractLiteral(
1267        Metadata::new(),
1268        AbstractLiteral::Sequence(expressions),
1269    ))
1270}
1271
1272fn parse_abs_tuple(abs_tuple: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1273    let values = abs_tuple
1274        .as_array()
1275        .ok_or(error!("AbsLitTuple is not an array"))?;
1276    let expressions = values
1277        .iter()
1278        .map(|values| parse_expression(values, scope))
1279        .collect::<Result<Vec<_>>>()?;
1280
1281    Ok(Expression::AbstractLiteral(
1282        Metadata::new(),
1283        AbstractLiteral::Tuple(expressions),
1284    ))
1285}
1286
1287//parses an abstract record as an expression
1288fn parse_abs_record(abs_record: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1289    let entries = abs_record
1290        .as_array()
1291        .ok_or(error!("AbsLitRecord is not an array"))?;
1292    let mut rec = vec![];
1293
1294    for entry in entries {
1295        let entry = entry
1296            .as_array()
1297            .ok_or(error!("AbsLitRecord entry is not an array"))?;
1298
1299        let name = parse_name(&entry[0])?;
1300
1301        let value = parse_expression(&entry[1], scope)?;
1302
1303        let rec_entry = Field {
1304            name: name.clone(),
1305            value,
1306        };
1307        rec.push(rec_entry);
1308    }
1309
1310    Ok(Expression::AbstractLiteral(
1311        Metadata::new(),
1312        AbstractLiteral::Record(rec),
1313    ))
1314}
1315
1316//parses an abstract variant as an expression
1317fn parse_abs_variant(abs_variant: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1318    let entry = abs_variant
1319        .as_array()
1320        .ok_or(error!("AbsLitVariant is not an array"))?;
1321    let name = entry[1]
1322        .as_object()
1323        .ok_or(error!("AbsLitVariant field name is not an object"))?["Name"]
1324        .as_str()
1325        .ok_or(error!("AbsLitVariant field name is not a string"))?;
1326
1327    let value = parse_expression(&entry[2], scope)?;
1328
1329    let name = Name::User(Ustr::from(name));
1330    let rec_entry = Field { name, value };
1331
1332    Ok(Expression::AbstractLiteral(
1333        Metadata::new(),
1334        AbstractLiteral::Variant(Moo::new(rec_entry)),
1335    ))
1336}
1337
1338//parses an abstract function as an expression
1339fn parse_abs_function(abs_function: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1340    let entries = abs_function
1341        .as_array()
1342        .ok_or(error!("AbsLitFunction is not an array"))?;
1343    let mut assignments = vec![];
1344
1345    for entry in entries {
1346        let entry = entry
1347            .as_array()
1348            .ok_or(error!("Explicit function assignment is not an array"))?;
1349        let expression = entry
1350            .iter()
1351            .map(|values| parse_expression(values, scope))
1352            .collect::<Result<Vec<_>>>()?;
1353        let domain_value = expression
1354            .first()
1355            .ok_or(error!("Invalid function domain"))?;
1356        let codomain_value = expression
1357            .get(1)
1358            .ok_or(error!("Invalid function codomain"))?;
1359        let tuple = (domain_value.clone(), codomain_value.clone());
1360        assignments.push(tuple);
1361    }
1362    Ok(Expression::AbstractLiteral(
1363        Metadata::new(),
1364        AbstractLiteral::Function(assignments),
1365    ))
1366}
1367
1368//parses an abstract relation as an expression
1369fn parse_abs_relation(abs_relation: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1370    let entries = abs_relation
1371        .as_array()
1372        .ok_or(error!("AbsLitRelation is not an array"))?;
1373    let mut assignments = vec![];
1374
1375    for entry in entries {
1376        let entry = entry
1377            .as_array()
1378            .ok_or(error!("Explicit relation assignment is not an array"))?;
1379        let expression = entry
1380            .iter()
1381            .map(|values| parse_expression(values, scope))
1382            .collect::<Result<Vec<_>>>()?;
1383        assignments.push(expression);
1384    }
1385    Ok(Expression::AbstractLiteral(
1386        Metadata::new(),
1387        AbstractLiteral::Relation(assignments),
1388    ))
1389}
1390
1391fn parse_comprehension(
1392    comprehension: &serde_json::Map<String, Value>,
1393    scope: SymbolTablePtr,
1394) -> Result<Expression> {
1395    let fail = |stage: &str| -> Error {
1396        Error::Parse(format!("Could not parse comprehension at stage `{stage}`"))
1397    };
1398
1399    let value = &comprehension["Comprehension"];
1400    let mut comprehension = ComprehensionBuilder::new(scope.clone());
1401    let generator_symboltable = comprehension.generator_symboltable();
1402    let return_expr_symboltable = comprehension.return_expr_symboltable();
1403
1404    let generators_and_guards_array = value
1405        .pointer("/1")
1406        .and_then(Value::as_array)
1407        .ok_or_else(|| fail("Comprehension.pointer(/1).as_array"))?;
1408    let generators_and_guards = generators_and_guards_array.iter();
1409
1410    for gen_or_guard in generators_and_guards {
1411        let gen_or_guard_obj = gen_or_guard
1412            .as_object()
1413            .ok_or_else(|| fail("generator_or_guard.as_object"))?;
1414        let (name, inner) = gen_or_guard_obj
1415            .iter()
1416            .next()
1417            .ok_or_else(|| fail("generator_or_guard.iter().next"))?;
1418        comprehension = match name.as_str() {
1419            "Generator" => {
1420                // TODO: more things than GenDomainNoRepr and Single names here?
1421                let generator_obj = inner
1422                    .as_object()
1423                    .ok_or_else(|| fail("Generator.inner.as_object"))?;
1424                let (name, gen_inner) = generator_obj
1425                    .iter()
1426                    .next()
1427                    .ok_or_else(|| fail("Generator.inner.iter().next"))?;
1428                match name.as_str() {
1429                    "GenDomainNoRepr" => {
1430                        let name = gen_inner
1431                            .pointer("/0/Single/Name")
1432                            .and_then(Value::as_str)
1433                            .ok_or_else(|| {
1434                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
1435                            })?;
1436                        let domain_obj = gen_inner
1437                            .pointer("/1")
1438                            .and_then(Value::as_object)
1439                            .ok_or_else(|| fail("GenDomainNoRepr.pointer(/1).as_object"))?;
1440                        let (domain_name, domain_value) = domain_obj
1441                            .iter()
1442                            .next()
1443                            .ok_or_else(|| fail("GenDomainNoRepr.domain.iter().next"))?;
1444                        let domain = parse_domain(
1445                            domain_name,
1446                            domain_value,
1447                            &mut generator_symboltable.write(),
1448                        )?;
1449                        comprehension.generator(DeclarationPtr::new_find(name.into(), domain))
1450                    }
1451                    "GenInExpr" => {
1452                        let name = gen_inner
1453                            .pointer("/0/Single/Name")
1454                            .and_then(Value::as_str)
1455                            .ok_or_else(|| {
1456                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
1457                            })?;
1458                        let generator_expr = gen_inner
1459                            .pointer("/1")
1460                            .ok_or_else(|| fail("GenInExpr.pointer(/1)"))?;
1461                        let expr = parse_expression(generator_expr, &scope)
1462                            .map_err(|_| fail("GenInExpr.parse_expression"))?;
1463                        comprehension.expression_generator(name.into(), expr)
1464                    }
1465                    _ => {
1466                        bug!("unknown generator type inside comprehension {name}");
1467                    }
1468                }
1469            }
1470
1471            "Condition" => {
1472                let expr = parse_expression(inner, &generator_symboltable)
1473                    .map_err(|_| fail("Condition.parse_expression"))?;
1474                comprehension.guard(expr)
1475            }
1476
1477            x => {
1478                bug!("unknown field inside comprehension {x}");
1479            }
1480        }
1481    }
1482
1483    let return_expr_value = value
1484        .pointer("/0")
1485        .ok_or_else(|| fail("Comprehension.pointer(/0)"))?;
1486    let expr = parse_expression(return_expr_value, &return_expr_symboltable)
1487        .map_err(|_| fail("Comprehension.return_expr.parse_expression"))?;
1488
1489    Ok(Expression::Comprehension(
1490        Metadata::new(),
1491        Moo::new(comprehension.with_return_value(expr)),
1492    ))
1493}
1494
1495fn unary_skip_operator(op_name: &str) -> Option<ACOperatorKind> {
1496    match op_name {
1497        "MkOpAnd" => Some(ACOperatorKind::And),
1498        "MkOpOr" => Some(ACOperatorKind::Or),
1499        "MkOpSum" => Some(ACOperatorKind::Sum),
1500        "MkOpProduct" => Some(ACOperatorKind::Product),
1501        // Not true AC operators (no universal identity element), but still need their own
1502        // skip-operator tag so a symbolic guard lowers correctly instead of silently substituting
1503        // Sum's identity (0).
1504        "MkOpMin" => Some(ACOperatorKind::Min),
1505        "MkOpMax" => Some(ACOperatorKind::Max),
1506        _ => None,
1507    }
1508}
1509
1510fn set_comprehension_skip_operator(
1511    expr: Expression,
1512    skip_operator: Option<ACOperatorKind>,
1513) -> Expression {
1514    let Expression::Comprehension(meta, comprehension) = expr else {
1515        return expr;
1516    };
1517    if let Some(skip_operator) = skip_operator {
1518        let mut comprehension = Moo::unwrap_or_clone(comprehension);
1519        comprehension.skip_operator = Some(skip_operator);
1520        Expression::Comprehension(meta, Moo::new(comprehension))
1521    } else {
1522        Expression::Comprehension(meta, comprehension)
1523    }
1524}
1525
1526fn parse_bin_op(
1527    bin_op: &serde_json::Map<String, Value>,
1528    scope: &SymbolTablePtr,
1529) -> Result<Expression> {
1530    // we know there is a single key value pair in this object
1531    // extract the value, ignore the key
1532    let (key, value) = bin_op
1533        .into_iter()
1534        .next()
1535        .ok_or(error!("Binary op object is empty"))?;
1536
1537    let constructor = binary_operator(key.as_str())
1538        .ok_or(error!(format!("Unknown binary operator `{}`", key)))?;
1539
1540    match &value {
1541        Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
1542            let arg1 = parse_expression(&bin_op_args[0], scope)?;
1543            let arg2 = parse_expression(&bin_op_args[1], scope)?;
1544
1545            // Conjure spells set difference with minus, so the operand types decide which of the
1546            // two it is -- the same choice the Essence parser makes.
1547            if key == "MkOpMinus"
1548                && (matches!(arg1.try_return_type(), Some(ReturnType::Set(_)))
1549                    || matches!(arg2.try_return_type(), Some(ReturnType::Set(_))))
1550            {
1551                return Ok(Expression::Difference(
1552                    Metadata::new(),
1553                    Moo::new(arg1),
1554                    Moo::new(arg2),
1555                ));
1556            }
1557
1558            Ok(constructor(Metadata::new(), Moo::new(arg1), Moo::new(arg2)))
1559        }
1560        _ => Err(error!("Binary operator arguments are not a 2-array")),
1561    }
1562}
1563
1564fn parse_table_op(
1565    op: &serde_json::Map<String, Value>,
1566    scope: &SymbolTablePtr,
1567) -> Result<Expression> {
1568    let args = op
1569        .get("MkOpTable")
1570        .ok_or(error!("MkOpTable missing"))?
1571        .as_array()
1572        .ok_or(error!("MkOpTable is not an array"))?;
1573
1574    if args.len() != 2 {
1575        return Err(error!("MkOpTable arguments are not a 2-array"));
1576    }
1577
1578    let tuple_expr = parse_expression(&args[0], scope)?;
1579    let allowed_rows_expr = parse_expression(&args[1], scope)?;
1580
1581    let (tuple_elems, _) = tuple_expr
1582        .clone()
1583        .unwrap_matrix_unchecked()
1584        .ok_or(error!("MkOpTable first argument is not a matrix"))?;
1585    let (allowed_rows, _) = allowed_rows_expr
1586        .clone()
1587        .unwrap_matrix_unchecked()
1588        .ok_or(error!("MkOpTable second argument is not a matrix"))?;
1589
1590    for row_expr in allowed_rows {
1591        let (row_elems, _) = row_expr
1592            .unwrap_matrix_unchecked()
1593            .ok_or(error!("MkOpTable row is not a matrix"))?;
1594
1595        if row_elems.len() != tuple_elems.len() {
1596            return Err(error!("MkOpTable row width does not match tuple width"));
1597        }
1598    }
1599
1600    Ok(Expression::Table(
1601        Metadata::new(),
1602        Moo::new(tuple_expr),
1603        Moo::new(allowed_rows_expr),
1604    ))
1605}
1606
1607/// If LHS is a record/variant and RHS is a field name,
1608/// returns Ok(Some(record_expr, field_name)).
1609/// If LHS is any other type, return Ok(None).
1610fn parse_record_field(
1611    op_args: &[Value],
1612    scope: &SymbolTablePtr,
1613) -> Result<Option<(Expression, Name)>> {
1614    if op_args.len() != 2 {
1615        return Err(error!("Expected 2 arguments to record indexing operation"));
1616    }
1617
1618    let lhs = parse_expression(&op_args[0], scope)?;
1619    match lhs.return_type() {
1620        // If indexing into a record, parse string field name
1621        // and check that such a field exists
1622        ReturnType::Record(ents) | ReturnType::Variant(ents) => {
1623            let field_name = parse_reference_name(&op_args[1])?;
1624            let has_name = ents.iter().any(|x| x.name.eq(&field_name));
1625            if !has_name {
1626                return Err(error!(format!(
1627                    "Unknown field `{field_name}` in record `{lhs}`"
1628                )));
1629            }
1630            Ok(Some((lhs, field_name)))
1631        }
1632        _ => Ok(None),
1633    }
1634}
1635
1636fn parse_active_op(
1637    op: &serde_json::Map<String, Value>,
1638    scope: &SymbolTablePtr,
1639) -> Result<Expression> {
1640    // we know there is a single key value pair in this object
1641    // extract the value, ignore the key
1642    let (_, value) = op
1643        .into_iter()
1644        .next()
1645        .ok_or(error!("MkOpActive op object is empty"))?;
1646
1647    let Value::Array(op_args) = &value else {
1648        return Err(error!("MkOpActive op array is not an array"));
1649    };
1650    let Some((lhs, rhs)) = parse_record_field(op_args, scope)? else {
1651        return Err(error!("MkOpActive op expected record or variant"));
1652    };
1653    Ok(Expression::Active(Metadata::new(), Moo::new(lhs), rhs))
1654}
1655
1656fn parse_indexing_slicing_op(
1657    op: &serde_json::Map<String, Value>,
1658    scope: &SymbolTablePtr,
1659) -> Result<Expression> {
1660    // we know there is a single key value pair in this object
1661    // extract the value, ignore the key
1662    let (key, value) = op
1663        .into_iter()
1664        .next()
1665        .ok_or(error!("Indexing/Slicing op object is empty"))?;
1666
1667    // we know that this is meant to be a mkopindexing, so anything that goes wrong from here is a
1668    // bug!
1669
1670    // Conjure does a[1,2,3] as MkOpIndexing(MkOpIndexing(MkOpIndexing(a,3),2),1).
1671    //
1672    // And  a[1,..,3] as MkOpIndexing(MkOpSlicing(MkOpIndexing(a,3)),1).
1673    //
1674    // However, we want this in a flattened form: Index(a, [1,2,3])
1675    let mut target: Expression;
1676    let mut indices: Vec<Option<Expression>> = vec![];
1677
1678    // true if this has no slicing, false otherwise.
1679    let mut all_known = true;
1680
1681    match key.as_str() {
1682        "MkOpIndexing" => {
1683            match &value {
1684                Value::Array(op_args) if op_args.len() == 2 => {
1685                    target = parse_expression(&op_args[0], scope)?;
1686
1687                    match parse_record_field(op_args, scope)? {
1688                        // For record indexing, generate nested RecordField exprs
1689                        Some((lhs, rhs)) => {
1690                            target = Expression::RecordField(Metadata::new(), Moo::new(lhs), rhs)
1691                        }
1692                        // Append any other indices to the flat list as normal
1693                        _ => indices.push(Some(parse_expression(&op_args[1], scope)?)),
1694                    }
1695                }
1696                _ => return Err(error!("Unknown object inside MkOpIndexing")),
1697            };
1698        }
1699
1700        "MkOpSlicing" => {
1701            all_known = false;
1702            match &value {
1703                Value::Array(op_args) if op_args.len() == 3 => {
1704                    // NB: records can't be sliced into so no need to check!
1705                    target = parse_expression(&op_args[0], scope)?;
1706                    indices.push(None);
1707                }
1708                _ => return Err(error!("Unknown object inside MkOpSlicing")),
1709            };
1710        }
1711
1712        _ => return Err(error!("Unknown indexing/slicing operator")),
1713    }
1714
1715    loop {
1716        match &mut target {
1717            Expression::UnsafeIndex(_, new_target, new_indices) => {
1718                indices.extend(new_indices.iter().cloned().rev().map(Some));
1719                target = Moo::unwrap_or_clone(new_target.clone());
1720            }
1721
1722            Expression::UnsafeSlice(_, new_target, new_indices) => {
1723                all_known = false;
1724                indices.extend(new_indices.iter().cloned().rev());
1725                target = Moo::unwrap_or_clone(new_target.clone());
1726            }
1727
1728            _ => {
1729                // not a slice or an index, we have reached the target.
1730                break;
1731            }
1732        }
1733    }
1734
1735    // If we had a record field and no other indices, the list will be empty
1736    if indices.is_empty() {
1737        return Ok(target);
1738    }
1739
1740    indices.reverse();
1741
1742    if all_known {
1743        Ok(Expression::UnsafeIndex(
1744            Metadata::new(),
1745            Moo::new(target),
1746            indices
1747                .into_iter()
1748                .collect::<Option<Vec<_>>>()
1749                .ok_or(error!("Missing index in fully-known indexing operation"))?,
1750        ))
1751    } else {
1752        Ok(Expression::UnsafeSlice(
1753            Metadata::new(),
1754            Moo::new(target),
1755            indices,
1756        ))
1757    }
1758}
1759
1760// Parses relation projection, to get a Vec<Option<Expression>> for the projections
1761fn parse_relation_projection(
1762    op: &serde_json::Map<String, Value>,
1763    scope: &SymbolTablePtr,
1764) -> Result<Expression> {
1765    let args = op
1766        .get("MkOpRelationProj")
1767        .ok_or(error!("MkOpRelationProj missing"))?
1768        .as_array()
1769        .ok_or(error!("MkOpRelationProj is not an array"))?;
1770    let first = args
1771        .first()
1772        .ok_or(error!("MkOpRelationProj missing first argument"))?;
1773    let second = args
1774        .get(1)
1775        .ok_or(error!("MkOpRelationProj missing second argument"))?
1776        .as_array()
1777        .ok_or(error!("MkOpRelationProj second argument is not an array"))?;
1778    let relation = parse_expression(first, scope).ok();
1779    // We build a vec of option expressions.
1780    // In the case where a relation domain is not being projected it is None, otherwise it is Some with the expression
1781    // We parse the 'null' as an error, which is mapped to None after parse_expression()
1782    let projections = second
1783        .iter()
1784        .map(|expr| parse_expression(expr, scope).ok())
1785        .collect();
1786    if let Some(relation) = relation {
1787        Ok(Expression::RelationProj(
1788            Metadata::new(),
1789            Moo::new(relation),
1790            projections,
1791        ))
1792    } else {
1793        Err(error!("MkOpRelationProj does not contain relation"))
1794    }
1795}
1796
1797// The ToSet operator is not truely a unary operator.
1798// The internal expression is 2nd in the array, with 'false' as the first element
1799// Therefore it needs separate parsing
1800fn parse_to_set(op: &serde_json::Map<String, Value>, scope: &SymbolTablePtr) -> Result<Expression> {
1801    let args = op
1802        .get("MkOpToSet")
1803        .ok_or(error!("MkOpToSet missing"))?
1804        .as_array()
1805        .ok_or(error!("MkOpToSet is not an array"))?;
1806    let second = args
1807        .get(1)
1808        .ok_or(error!("MkOpToSet missing second argument"))?;
1809    let inner = parse_expression(second, scope)?;
1810    Ok(Expression::ToSet(Metadata::new(), Moo::new(inner)))
1811}
1812
1813fn parse_flatten_op(
1814    op: &serde_json::Map<String, Value>,
1815    scope: &SymbolTablePtr,
1816) -> Result<Expression> {
1817    let args = op
1818        .get("MkOpFlatten")
1819        .ok_or(error!("MkOpFlatten missing"))?
1820        .as_array()
1821        .ok_or(error!("MkOpFlatten is not an array"))?;
1822
1823    let first = args
1824        .first()
1825        .ok_or(error!("MkOpFlatten missing first argument"))?;
1826    let second = args
1827        .get(1)
1828        .ok_or(error!("MkOpFlatten missing second argument"))?;
1829    let n = parse_expression(first, scope).ok();
1830    let matrix = parse_expression(second, scope)?;
1831
1832    if let Some(n) = n {
1833        Ok(Expression::Flatten(
1834            Metadata::new(),
1835            Some(Moo::new(n)),
1836            Moo::new(matrix),
1837        ))
1838    } else {
1839        Ok(Expression::Flatten(Metadata::new(), None, Moo::new(matrix)))
1840    }
1841}
1842
1843fn parse_unary_op(
1844    un_op: &serde_json::Map<String, Value>,
1845    scope: &SymbolTablePtr,
1846) -> Result<Expression> {
1847    let fail = |stage: &str| -> Error {
1848        Error::Parse(format!("Could not parse unary op at stage `{stage}`"))
1849    };
1850
1851    let (key, value) = un_op
1852        .iter()
1853        .next()
1854        .ok_or_else(|| fail("un_op.iter().next"))?;
1855
1856    // unops are the main things that contain comprehensions
1857    //
1858    // if the current expr is a quantifier like and/or/sum and it contains a comprehension, let the comprehension know what it is inside.
1859    let arg = match value {
1860        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
1861            parse_comprehension(comprehension, scope.clone())
1862                .map_err(|_| fail("value.Comprehension.parse_comprehension"))
1863        }
1864        _ => parse_expression(value, scope).map_err(|_| fail("value.parse_expression")),
1865    }
1866    .map_err(|_| fail("arg"))?;
1867
1868    let skip_operator = unary_skip_operator(key.as_str());
1869    let arg = set_comprehension_skip_operator(arg, skip_operator);
1870
1871    let constructor =
1872        unary_operator(key.as_str(), Some(&arg)).ok_or_else(|| fail("unary_operator"))?;
1873
1874    Ok(constructor(Metadata::new(), Moo::new(arg)))
1875}
1876
1877// Takes in { AbstractLiteral: .... }
1878fn parse_abstract_matrix_as_expr(
1879    value: &serde_json::Value,
1880    scope: &SymbolTablePtr,
1881) -> Result<Expression> {
1882    parser_trace!("trying to parse an abstract literal matrix");
1883    let (values, domain_name, domain_value) =
1884        if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix") {
1885            parser_trace!(".. found JSON pointer /AbstractLiteral/AbstractLitMatrix");
1886            let (domain_name, domain_value) = abs_lit_matrix
1887                .pointer("/0")
1888                .and_then(Value::as_object)
1889                .and_then(|x| x.iter().next())
1890                .ok_or(error!("AbsLitMatrix missing domain"))?;
1891            let values = abs_lit_matrix
1892                .pointer("/1")
1893                .ok_or(error!("AbsLitMatrix missing values"))?;
1894
1895            Some((values, domain_name, domain_value))
1896        }
1897        // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
1898        else if let Some(const_abs_lit_matrix) =
1899            value.pointer("/Constant/ConstantAbstract/AbsLitMatrix")
1900        {
1901            parser_trace!(".. found JSON pointer /Constant/ConstantAbstract/AbsLitMatrix");
1902            let (domain_name, domain_value) = const_abs_lit_matrix
1903                .pointer("/0")
1904                .and_then(Value::as_object)
1905                .and_then(|x| x.iter().next())
1906                .ok_or(error!("ConstantAbstract AbsLitMatrix missing domain"))?;
1907            let values = const_abs_lit_matrix
1908                .pointer("/1")
1909                .ok_or(error!("ConstantAbstract AbsLitMatrix missing values"))?;
1910
1911            Some((values, domain_name, domain_value))
1912        } else if let Some(const_abs_lit_matrix) = value.pointer("/ConstantAbstract/AbsLitMatrix") {
1913            parser_trace!(".. found JSON pointer /ConstantAbstract/AbsLitMatrix");
1914            let (domain_name, domain_value) = const_abs_lit_matrix
1915                .pointer("/0")
1916                .and_then(Value::as_object)
1917                .and_then(|x| x.iter().next())
1918                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing domain"))?;
1919            let values = const_abs_lit_matrix
1920                .pointer("/1")
1921                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing values"))?;
1922            Some((values, domain_name, domain_value))
1923        } else {
1924            None
1925        }
1926        .ok_or(error!("Could not parse abstract literal matrix"))?;
1927
1928    parser_trace!(".. found in domain and values in JSON:");
1929    parser_trace!(".. .. index domain name {domain_name}");
1930    parser_trace!(".. .. values {value}");
1931
1932    let args_parsed = values
1933        .as_array()
1934        .ok_or(error!("Matrix values are not an array"))?
1935        .iter()
1936        .map(|x| parse_expression(x, scope))
1937        .collect::<Result<Vec<Expression>>>()?;
1938
1939    if !args_parsed.is_empty() {
1940        parser_trace!(
1941            ".. successfully parsed values as expressions: {}, ... ",
1942            args_parsed[0]
1943        );
1944    } else {
1945        parser_trace!(".. successfully parsed empty values ",);
1946    }
1947
1948    let mut symbols = scope.write();
1949    match parse_domain(domain_name, domain_value, &mut symbols) {
1950        Ok(domain) => {
1951            parser_trace!("... sucessfully parsed domain as {domain}");
1952            Ok(into_matrix_expr![args_parsed;domain])
1953        }
1954        Err(_) => {
1955            parser_trace!("... failed to parse domain, creating a matrix without one.");
1956            Ok(into_matrix_expr![args_parsed])
1957        }
1958    }
1959}
1960
1961fn parse_constant(
1962    constant: &serde_json::Map<String, Value>,
1963    scope: &SymbolTablePtr,
1964) -> Result<Expression> {
1965    match &constant.get("Constant") {
1966        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
1967            let int_32: i32 = match int["ConstantInt"]
1968                .as_array()
1969                .ok_or(error!("ConstantInt is not an array"))?[1]
1970                .as_i64()
1971                .ok_or(error!("ConstantInt does not contain int"))?
1972                .try_into()
1973            {
1974                Ok(x) => x,
1975                Err(_) => return Err(error!("ConstantInt cannot be represented as i32")),
1976            };
1977
1978            Ok(Expression::Atomic(
1979                Metadata::new(),
1980                Atom::Literal(Literal::Int(int_32)),
1981            ))
1982        }
1983
1984        Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
1985            let b: bool = b["ConstantBool"]
1986                .as_bool()
1987                .ok_or(error!("ConstantBool does not contain bool"))?;
1988            Ok(Expression::Atomic(
1989                Metadata::new(),
1990                Atom::Literal(Literal::Bool(b)),
1991            ))
1992        }
1993
1994        Some(Value::Object(int)) if int.contains_key("ConstantAbstract") => {
1995            if let Some(Value::Object(obj)) = int.get("ConstantAbstract") {
1996                if let Some(arr) = obj.get("AbsLitSet") {
1997                    return parse_abs_lit(arr, scope);
1998                } else if let Some(arr) = obj.get("AbsLitMSet") {
1999                    return parse_abs_mset(arr, scope);
2000                } else if let Some(arr) = obj.get("AbsLitMatrix") {
2001                    return parse_abstract_matrix_as_expr(arr, scope);
2002                } else if let Some(arr) = obj.get("AbsLitTuple") {
2003                    return parse_abs_tuple(arr, scope);
2004                } else if let Some(arr) = obj.get("AbsLitRecord") {
2005                    return parse_abs_record(arr, scope);
2006                } else if let Some(arr) = obj.get("AbsLitPartition") {
2007                    return parse_abs_partition(arr, scope);
2008                } else if let Some(arr) = obj.get("AbsLitPermutation") {
2009                    return parse_abs_permutation(arr, scope);
2010                } else if let Some(arr) = obj.get("AbsLitFunction") {
2011                    return parse_abs_function(arr, scope);
2012                } else if let Some(arr) = obj.get("AbsLitVariant") {
2013                    return parse_abs_variant(arr, scope);
2014                } else if let Some(arr) = obj.get("AbsLitRelation") {
2015                    return parse_abs_relation(arr, scope);
2016                } else if let Some(arr) = obj.get("AbsLitSequence") {
2017                    return parse_abs_sequence(arr, scope);
2018                }
2019            }
2020            Err(error!("Unhandled ConstantAbstract literal type"))
2021        }
2022
2023        // sometimes (e.g. constant matrices) we can have a ConstantInt / Constant bool that is
2024        // not wrapped in Constant
2025        None => {
2026            let int_expr = constant
2027                .get("ConstantInt")
2028                .and_then(|x| x.as_array())
2029                .and_then(|x| x[1].as_i64())
2030                .and_then(|x| x.try_into().ok())
2031                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
2032
2033            if let Some(expr) = int_expr {
2034                return Ok(expr);
2035            }
2036
2037            let bool_expr = constant
2038                .get("ConstantBool")
2039                .and_then(|x| x.as_bool())
2040                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
2041
2042            if let Some(expr) = bool_expr {
2043                return Ok(expr);
2044            }
2045
2046            Err(error!(format!("Unhandled parse_constant {constant:#?}")))
2047        }
2048        otherwise => Err(error!(format!("Unhandled parse_constant {otherwise:#?}"))),
2049    }
2050}
2051
2052#[cfg(test)]
2053mod tests {
2054    use super::*;
2055    use crate::ast::HasDomain;
2056    use crate::{domain_int, range};
2057    use serde_json::json;
2058
2059    #[test]
2060    fn parses_record_index() {
2061        let scope = SymbolTablePtr::new();
2062        scope.write().insert(DeclarationPtr::new_find(
2063            Name::user("x"),
2064            Domain::record(vec![Field {
2065                name: Name::user("a"),
2066                value: Domain::bool(),
2067            }]),
2068        ));
2069
2070        let value = json!({
2071            "Op": {
2072                "MkOpIndexing": [
2073                    {
2074                        "Reference": [
2075                            {
2076                                "Name": "x"
2077                            },
2078                            null
2079                        ]
2080                    },
2081                    {
2082                        "Reference": [
2083                            {
2084                                "Name": "a"
2085                            },
2086                            null
2087                        ]
2088                    }
2089                ]
2090            }
2091        });
2092
2093        let expr = parse_expression(&value, &scope).expect("record index should parse");
2094        let Expression::RecordField(_, rec_expr, field_name) = expr else {
2095            panic!("expected record field access");
2096        };
2097        let Expression::Atomic(_, Atom::Reference(re)) = rec_expr.as_ref() else {
2098            panic!("expected LHS to be a record reference");
2099        };
2100        assert_eq!(re.name().clone(), Name::user("x"));
2101        assert!(re.domain_of().as_record().is_some());
2102        assert_eq!(field_name, Name::user("a"));
2103    }
2104
2105    #[test]
2106    fn parses_nested_constant_abstract_sets() {
2107        let scope = SymbolTablePtr::new();
2108        let value = json!({
2109            "ConstantAbstract": {
2110                "AbsLitSet": [
2111                    {
2112                        "ConstantAbstract": {
2113                            "AbsLitSet": [
2114                                { "ConstantInt": [{ "TagInt": [] }, 1] },
2115                                { "ConstantInt": [{ "TagInt": [] }, 2] }
2116                            ]
2117                        }
2118                    },
2119                    {
2120                        "ConstantAbstract": {
2121                            "AbsLitSet": [
2122                                { "ConstantInt": [{ "TagInt": [] }, 3] }
2123                            ]
2124                        }
2125                    }
2126                ]
2127            }
2128        });
2129
2130        let expr = parse_expression(&value, &scope).expect("nested constant sets should parse");
2131        let Expression::AbstractLiteral(_, AbstractLiteral::Set(outer_values)) = expr else {
2132            panic!("expected an outer set literal");
2133        };
2134        assert_eq!(outer_values.len(), 2);
2135        assert!(outer_values.iter().all(|value| matches!(
2136            value,
2137            Expression::AbstractLiteral(_, AbstractLiteral::Set(_))
2138        )));
2139    }
2140
2141    #[test]
2142    fn parses_abstract_literal_wrapped_partition_with_non_constant_elements() {
2143        // Conjure emits a partition literal under the bare `AbstractLiteral` wrapper (rather
2144        // than `Constant`/`ConstantAbstract`) whenever one of its elements is not itself a
2145        // constant, e.g. `partition({x,2},{y,4})` where x, y are decision variables. Captured
2146        // verbatim (modulo whitespace) from `conjure pretty --output-format=astjson` on such a
2147        // model.
2148        let scope = SymbolTablePtr::new();
2149        scope
2150            .write()
2151            .insert(DeclarationPtr::new_find(Name::user("x"), domain_int!(1..4)));
2152        scope
2153            .write()
2154            .insert(DeclarationPtr::new_find(Name::user("y"), domain_int!(1..4)));
2155
2156        let value = json!({
2157            "AbstractLiteral": {
2158                "AbsLitPartition": [
2159                    [
2160                        { "Reference": [{ "Name": "x" }, null] },
2161                        { "Constant": { "ConstantInt": [{ "TagInt": [] }, 2] } }
2162                    ],
2163                    [
2164                        { "Reference": [{ "Name": "y" }, null] },
2165                        { "Constant": { "ConstantInt": [{ "TagInt": [] }, 4] } }
2166                    ]
2167                ]
2168            }
2169        });
2170
2171        let expr = parse_expression(&value, &scope)
2172            .expect("AbstractLiteral-wrapped partition should parse");
2173        let Expression::AbstractLiteral(_, AbstractLiteral::Partition(parts)) = expr else {
2174            panic!("expected a partition literal, got {expr:?}");
2175        };
2176        assert_eq!(parts.len(), 2);
2177        assert_eq!(parts[0].len(), 2);
2178        assert_eq!(parts[1].len(), 2);
2179    }
2180}