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::PartitionAttr;
12use crate::ast::Typeable;
13use crate::ast::ac_operators::ACOperatorKind;
14use crate::ast::comprehension::ComprehensionBuilder;
15use crate::ast::records::FieldValue;
16use crate::ast::{
17    AbstractLiteral, Atom, BinaryAttr, DeclarationPtr, Domain, Expression, FieldEntry, FuncAttr,
18    IntVal, JectivityAttr, Literal, MSetAttr, Name, PartialityAttr, Range, RelAttr, ReturnType,
19    SequenceAttr, SetAttr, SymbolTable, SymbolTablePtr,
20};
21use crate::ast::{DomainPtr, Metadata};
22use crate::context::Context;
23use crate::error::{Error, Result};
24use crate::{Model, bug, error, into_matrix_expr, throw_error};
25
26#[allow(unused_macros)]
27macro_rules! parser_trace {
28    ($($arg:tt)+) => {
29        log::trace!(target:"jsonparser",$($arg)+)
30    };
31}
32
33#[allow(unused_macros)]
34macro_rules! parser_debug {
35    ($($arg:tt)+) => {
36        log::debug!(target:"jsonparser",$($arg)+)
37    };
38}
39
40pub fn model_from_json(str: &str, context: Arc<RwLock<Context<'static>>>) -> Result<Model> {
41    let mut m = Model::new(context);
42    let v: JsonValue = serde_json::from_str(str)?;
43    let statements = v["mStatements"]
44        .as_array()
45        .ok_or(error!("mStatements is not an array"))?;
46
47    for statement in statements {
48        let entry = statement
49            .as_object()
50            .ok_or(error!("mStatements contains a non-object"))?
51            .iter()
52            .next()
53            .ok_or(error!("mStatements contains an empty object"))?;
54
55        match entry.0.as_str() {
56            "Declaration" => {
57                let decl = entry
58                    .1
59                    .as_object()
60                    .ok_or(error!("Declaration is not an object".to_owned()))?;
61
62                // One field in the declaration should tell us what kind it is.
63                //
64                // Find it, ignoring the other fields.
65                //
66                // e.g. FindOrGiven,
67
68                let mut valid_decl: bool = false;
69                let scope = m.symbols_ptr_unchecked().clone();
70                let model = &mut m;
71                for (kind, value) in decl {
72                    match kind.as_str() {
73                        "FindOrGiven" => {
74                            parse_variable(value, &mut model.symbols_mut())?;
75                            valid_decl = true;
76                            break;
77                        }
78                        "Letting" => {
79                            parse_letting(value, &scope)?;
80                            valid_decl = true;
81                            break;
82                        }
83                        _ => continue,
84                    }
85                }
86
87                if !valid_decl {
88                    throw_error!("Declaration is not a valid kind")?;
89                }
90            }
91            "SuchThat" => {
92                let constraints_arr = match entry.1.as_array() {
93                    Some(x) => x,
94                    None => bug!("SuchThat is not a vector"),
95                };
96
97                let constraints: Vec<Expression> = constraints_arr
98                    .iter()
99                    .map(|x| parse_expression(x, m.symbols_ptr_unchecked()))
100                    .collect::<Result<Vec<_>>>()?;
101                m.add_constraints(constraints);
102            }
103            otherwise => bug!("Unhandled Statement {:#?}", otherwise),
104        }
105    }
106    Ok(m)
107}
108
109fn parse_variable(v: &JsonValue, symtab: &mut SymbolTable) -> Result<()> {
110    let arr = v.as_array().ok_or(error!("FindOrGiven is not an array"))?;
111
112    let variable_type = arr[0]
113        .as_str()
114        .ok_or(error!("FindOrGiven[0] is not a string"))?;
115
116    let name = arr[1]
117        .as_object()
118        .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
119        .as_str()
120        .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
121
122    let name = Name::User(Ustr::from(name));
123
124    let domain = arr[2]
125        .as_object()
126        .ok_or(error!("FindOrGiven[2] is not an object"))?
127        .iter()
128        .next()
129        .ok_or(error!("FindOrGiven[2] is an empty object"))?;
130
131    let domain = parse_domain(domain.0, domain.1, symtab)?;
132
133    let decl = match variable_type {
134        "Find" => DeclarationPtr::new_find(name.clone(), domain),
135        "Given" => DeclarationPtr::new_given(name.clone(), domain),
136        _ => {
137            return Err(error!("FindOrGiven[0] is not 'Find' or 'Given'"));
138        }
139    };
140
141    symtab.insert(decl).ok_or(Error::Parse(format!(
142        "Could not add {name} to symbol table as it already exists"
143    )))
144}
145
146fn parse_letting(v: &JsonValue, scope: &SymbolTablePtr) -> Result<()> {
147    let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
148    let name = arr[0]
149        .as_object()
150        .ok_or(error!("Letting[0] is not an object"))?["Name"]
151        .as_str()
152        .ok_or(error!("Letting[0].Name is not a string"))?;
153    let name = Name::User(Ustr::from(name));
154    // value letting
155    if let Ok(value) = parse_expression(&arr[1], scope) {
156        let mut symtab = scope.write();
157        symtab
158            .insert(DeclarationPtr::new_value_letting(name.clone(), value))
159            .ok_or(Error::Parse(format!(
160                "Could not add {name} to symbol table as it already exists"
161            )))
162    } else {
163        // domain letting
164        let domain = &arr[1]
165            .as_object()
166            .ok_or(error!("Letting[1] is not an object".to_owned()))?["Domain"]
167            .as_object()
168            .ok_or(error!("Letting[1].Domain is not an object"))?
169            .iter()
170            .next()
171            .ok_or(error!("Letting[1].Domain is an empty object"))?;
172
173        let mut symtab = scope.write();
174        let domain = parse_domain(domain.0, domain.1, &mut symtab)?;
175
176        symtab
177            .insert(DeclarationPtr::new_domain_letting(name.clone(), domain))
178            .ok_or(Error::Parse(format!(
179                "Could not add {name} to symbol table as it already exists"
180            )))
181    }
182}
183
184fn parse_domain(
185    domain_name: &str,
186    domain_value: &JsonValue,
187    symbols: &mut SymbolTable,
188) -> Result<DomainPtr> {
189    match domain_name {
190        "DomainInt" => Ok(parse_int_domain(domain_value, symbols)?),
191        "DomainBool" => Ok(Domain::bool()),
192        "DomainReference" => {
193            let name = Name::user(
194                domain_value
195                    .as_array()
196                    .ok_or(error!("DomainReference is not an array"))?[0]
197                    .as_object()
198                    .ok_or(error!("DomainReference[0] is not an object"))?["Name"]
199                    .as_str()
200                    .ok_or(error!("DomainReference[0].Name is not a string"))?,
201            );
202            let ptr = symbols
203                .lookup(&name)
204                .ok_or(error!(format!("Name {name} not found")))?;
205            let dom =
206                Domain::reference(ptr).ok_or(error!("Could not construct reference domain"))?;
207            Ok(dom)
208        }
209        "DomainSet" => {
210            let dom = domain_value.get(2).and_then(|v| v.as_object());
211            let domain_obj = dom.ok_or(error!("DomainSet is missing domain object"))?;
212            let domain = domain_obj
213                .iter()
214                .next()
215                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
216            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
217            let size = domain_value
218                .get(1)
219                .and_then(|v| v.as_object())
220                .ok_or(error!("Set size attributes is not an object"))?;
221            let size = parse_size_attr(size, symbols)?;
222            let attr: SetAttr<IntVal> = SetAttr { size };
223            Ok(Domain::set(attr, domain))
224        }
225        "DomainMSet" => {
226            let dom = domain_value
227                .get(2)
228                .and_then(|v| v.as_object())
229                .expect("domain object exists");
230            let domain = dom
231                .iter()
232                .next()
233                .ok_or(Error::Parse("DomainMSet is an empty object".to_owned()))?;
234            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
235
236            // Parse Attributes
237            let attributes = domain_value
238                .get(1)
239                .and_then(|v| v.as_array())
240                .ok_or(error!("MSet attributes is not a json array"))?;
241
242            let size = attributes
243                .first()
244                .and_then(|v| v.as_object())
245                .ok_or(error!("MSet size attributes is not an object"))?;
246            let size = parse_size_attr(size, symbols)?;
247
248            let occurrence = attributes
249                .get(1)
250                .and_then(|v| v.as_object())
251                .ok_or(error!("MSet occurrence attributes is not an object"))?;
252            let occurrence = parse_occur_attr(occurrence, symbols)?;
253
254            let attr: MSetAttr<IntVal> = MSetAttr { size, occurrence };
255            Ok(Domain::mset(attr, domain))
256        }
257        "DomainPartition" => {
258            let dom = domain_value
259                .get(2)
260                .and_then(|v| v.as_object())
261                .expect("domain object exists");
262            let domain = dom.iter().next().ok_or(Error::Parse(
263                "DomainPartition is an empty object".to_owned(),
264            ))?;
265            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
266
267            let attributes = domain_value
268                .get(1)
269                .and_then(|v| v.as_object())
270                .ok_or(error!("Partition attributes is not an object"))?;
271
272            let mut num_parts = Range::Unbounded;
273            let mut part_len = Range::Unbounded;
274            let mut is_regular = false;
275
276            if let Some(val) = attributes.get("partsNum") {
277                let attr_map = val.as_object().expect("numParts should be an object");
278                num_parts = parse_size_attr(attr_map, symbols)?;
279            }
280            if let Some(val) = attributes.get("partsSize") {
281                let attr_map = val.as_object().expect("partsSize should be an object");
282                part_len = parse_size_attr(attr_map, symbols)?;
283            }
284            if let Some(val) = attributes.get("isRegular").and_then(|v| v.as_bool()) {
285                is_regular = val;
286            }
287
288            let attr: PartitionAttr<IntVal> = PartitionAttr {
289                num_parts,
290                part_len,
291                is_regular,
292            };
293            Ok(Domain::partition(attr, domain))
294        }
295        "DomainMatrix" => {
296            let domain_value = domain_value
297                .as_array()
298                .ok_or(error!("Domain matrix is not an array"))?;
299
300            let indexed_by_domain = domain_value[0].clone();
301            let (index_domain_name, index_domain_value) = indexed_by_domain
302                .as_object()
303                .ok_or(error!("DomainMatrix[0] is not an object"))?
304                .iter()
305                .next()
306                .ok_or(error!(""))?;
307
308            let (value_domain_name, value_domain_value) = domain_value[1]
309                .as_object()
310                .ok_or(error!(""))?
311                .iter()
312                .next()
313                .ok_or(error!(""))?;
314
315            // Conjure stores a 2-d matrix as a matrix of a matrix.
316            //
317            // Therefore, the index is always a Domain.
318
319            let mut index_domains: Vec<DomainPtr> = vec![];
320
321            index_domains.push(parse_domain(
322                index_domain_name,
323                index_domain_value,
324                symbols,
325            )?);
326
327            // We want to store 2-d matrices as a matrix with two index domains, not a matrix in a
328            // matrix.
329            //
330            // Walk through the value domain until it is not a DomainMatrix, adding the index to
331            // our list of indices.
332            let mut value_domain = parse_domain(value_domain_name, value_domain_value, symbols)?;
333            while let Some((new_value_domain, mut indices)) = value_domain.as_matrix() {
334                index_domains.append(&mut indices);
335                value_domain = new_value_domain.clone()
336            }
337
338            Ok(Domain::matrix(value_domain, index_domains))
339        }
340
341        "DomainSequence" => {
342            let dom = domain_value
343                .get(2)
344                .and_then(|v| v.as_object())
345                .expect("domain object exists");
346            let domain = dom
347                .iter()
348                .next()
349                .ok_or(Error::Parse("DomainSequence is an empty object".to_owned()))?;
350            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
351
352            // Parse Attributes
353            let attributes = domain_value
354                .get(1)
355                .and_then(|v| v.as_array())
356                .ok_or(error!("Sequence attributes is not a json array"))?;
357
358            let size = attributes
359                .first()
360                .and_then(|v| v.as_object())
361                .ok_or(error!("Sequence size attributes is not an object"))?;
362            let size = parse_size_attr(size, symbols)?;
363
364            let jectivity = attributes
365                .get(1)
366                .and_then(|v| v.as_str())
367                .ok_or(error!("jectivity is not a string"))?;
368            let jectivity = match jectivity {
369                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
370                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
371                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
372                "JectivityAttr_None" => Some(JectivityAttr::None),
373                _ => None,
374            };
375            let jectivity =
376                jectivity.ok_or(Error::Parse("Jectivity is an unknown type".to_owned()))?;
377
378            let attr: SequenceAttr<IntVal> = SequenceAttr { size, jectivity };
379            match attr.size {
380                Range::Unbounded | Range::UnboundedR(_) => Err(Error::Parse(
381                    "Sequence must have size or maxSize attribute".to_string(),
382                )),
383                _ => Ok(Domain::sequence(attr, domain)),
384            }
385        }
386
387        "DomainTuple" => {
388            let domain_value = domain_value
389                .as_array()
390                .ok_or(error!("Domain tuple is not an array"))?;
391
392            //iterate through the array and parse each domain
393            let domain = domain_value
394                .iter()
395                .map(|x| {
396                    let domain = x
397                        .as_object()
398                        .ok_or(error!("DomainTuple[0] is not an object"))?
399                        .iter()
400                        .next()
401                        .ok_or(error!("DomainTuple[0] is an empty object"))?;
402                    parse_domain(domain.0, domain.1, symbols)
403                })
404                .collect::<Result<Vec<DomainPtr>>>()?;
405
406            Ok(Domain::tuple(domain))
407        }
408        "DomainRecord" | "DomainVariant" => {
409            // Records and Variants can be parsed the same way for the most part
410            let is_record = domain_name == "DomainRecord";
411            // Get the actual string for error message purposes
412            let domain_string = match is_record {
413                true => "Record",
414                false => "Variant",
415            };
416            let domain_value = domain_value.as_array().ok_or(error!(&format!(
417                "Domain {domain_string} is not a json array"
418            )))?;
419
420            let mut entries = vec![];
421
422            for item in domain_value {
423                //collect the name of the field
424                let name = item[0]
425                    .as_object()
426                    .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
427                    .as_str()
428                    .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
429
430                let name = Name::User(Ustr::from(name));
431                // then collect the domain of the field
432                let domain = item[1]
433                    .as_object()
434                    .ok_or(error!("FindOrGiven[2] is not an object"))?
435                    .iter()
436                    .next()
437                    .ok_or(error!("FindOrGiven[2] is an empty object"))?;
438
439                let domain = parse_domain(domain.0, domain.1, symbols)?;
440
441                let rec = FieldEntry { name, domain };
442
443                entries.push(rec);
444            }
445
446            // add fields to symbol table
447            for decl in entries
448                .iter()
449                .cloned()
450                .map(DeclarationPtr::new_record_field)
451            {
452                symbols.insert(decl).ok_or(error!(
453                    "record field should not already be in the symbol table"
454                ))?;
455            }
456            if is_record {
457                Ok(Domain::record(entries))
458            } else {
459                Ok(Domain::variant(entries))
460            }
461        }
462        "DomainFunction" => {
463            let domain = domain_value
464                .get(2)
465                .and_then(|v| v.as_object())
466                .ok_or(error!("Function domain is not an object"))?;
467            let domain = domain
468                .iter()
469                .next()
470                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
471            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
472
473            let codomain = domain_value
474                .get(3)
475                .and_then(|v| v.as_object())
476                .ok_or(error!("Function codomain is not an object"))?;
477            let codomain = codomain
478                .iter()
479                .next()
480                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
481            let codomain = parse_domain(codomain.0.as_str(), codomain.1, symbols)?;
482
483            // Attribute parsing
484            let attributes = domain_value
485                .get(1)
486                .and_then(|v| v.as_array())
487                .ok_or(error!("Function attributes is not a json array"))?;
488            let size = attributes
489                .first()
490                .and_then(|v| v.as_object())
491                .ok_or(error!("Function size attributes is not an object"))?;
492            let size = parse_size_attr(size, symbols)?;
493            let partiality = attributes
494                .get(1)
495                .and_then(|v| v.as_str())
496                .ok_or(error!("Function partiality is not a string"))?;
497            let partiality = match partiality {
498                "PartialityAttr_Partial" => Some(PartialityAttr::Partial),
499                "PartialityAttr_Total" => Some(PartialityAttr::Total),
500                _ => None,
501            };
502            let partiality =
503                partiality.ok_or(Error::Parse("Partiality is an unknown type".to_owned()))?;
504            let jectivity = attributes
505                .get(2)
506                .and_then(|v| v.as_str())
507                .ok_or(error!("Function jectivity is not a string"))?;
508            let jectivity = match jectivity {
509                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
510                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
511                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
512                "JectivityAttr_None" => Some(JectivityAttr::None),
513                _ => None,
514            };
515            let jectivity =
516                jectivity.ok_or(Error::Parse("Jectivity is an unknown type".to_owned()))?;
517
518            let attr: FuncAttr<IntVal> = FuncAttr {
519                size,
520                partiality,
521                jectivity,
522            };
523
524            Ok(Domain::function(attr, domain, codomain))
525        }
526
527        "DomainRelation" => {
528            let domains = domain_value
529                .get(2)
530                .and_then(|v| v.as_array())
531                .ok_or(Error::Parse(
532                    "Relation domains are not a json array".to_owned(),
533                ))?;
534            let domains = domains
535                .iter()
536                .map(|x| {
537                    let domain = x
538                        .as_object()
539                        .ok_or(Error::Parse("Relation domain is not an object".to_owned()))?
540                        .iter()
541                        .next()
542                        .ok_or(Error::Parse(
543                            "Relation domain is an empty object".to_owned(),
544                        ))?;
545                    parse_domain(domain.0, domain.1, symbols)
546                })
547                .collect::<Result<Vec<DomainPtr>>>()?;
548
549            // Attribute parsing
550            let attributes = domain_value
551                .get(1)
552                .and_then(|v| v.as_array())
553                .ok_or(Error::Parse(
554                    "Relation attributes are not a json array".to_owned(),
555                ))?;
556            let size = attributes
557                .first()
558                .and_then(|v| v.as_object())
559                .ok_or(Error::Parse(
560                    "Relation size attributes are not an object".to_owned(),
561                ))?;
562            let size = parse_size_attr(size, symbols)?;
563            let binary = attributes
564                .get(1)
565                .and_then(|v| v.as_array())
566                .ok_or(Error::Parse(
567                    "Relation binary attributes are not a json array".to_owned(),
568                ))?;
569            let binary = binary
570                .iter()
571                .map(|x| {
572                    let attr = x.as_str().ok_or(Error::Parse(
573                        "Relation binary attribute is not a string".to_owned(),
574                    ))?;
575                    match attr {
576                        "BinRelAttr_Reflexive" => Ok(BinaryAttr::Reflexive),
577                        "BinRelAttr_Irreflexive" => Ok(BinaryAttr::Irreflexive),
578                        "BinRelAttr_Coreflexive" => Ok(BinaryAttr::Coreflexive),
579                        "BinRelAttr_Symmetric" => Ok(BinaryAttr::Symmetric),
580                        "BinRelAttr_AntiSymmetric" => Ok(BinaryAttr::AntiSymmetric),
581                        "BinRelAttr_ASymmetric" => Ok(BinaryAttr::ASymmetric),
582                        "BinRelAttr_Transitive" => Ok(BinaryAttr::Transitive),
583                        "BinRelAttr_Total" => Ok(BinaryAttr::Total),
584                        "BinRelAttr_Connex" => Ok(BinaryAttr::Connex),
585                        "BinRelAttr_Euclidean" => Ok(BinaryAttr::Euclidean),
586                        "BinRelAttr_Serial" => Ok(BinaryAttr::Serial),
587                        "BinRelAttr_Equivalence" => Ok(BinaryAttr::Equivalence),
588                        "BinRelAttr_PartialOrder" => Ok(BinaryAttr::PartialOrder),
589                        _ => Err(Error::Parse(
590                            "Relation binary attribute is invalid".to_owned(),
591                        )),
592                    }
593                })
594                .collect::<Result<Vec<BinaryAttr>>>()?;
595
596            let attr: RelAttr<IntVal> = RelAttr { size, binary };
597
598            Ok(Domain::relation(attr, domains))
599        }
600        _ => Err(Error::Parse(
601            "FindOrGiven[2] is an unknown object".to_owned(), // consider covered
602        )),
603    }
604}
605
606fn parse_size_attr(
607    attr_map: &JsonMap<String, JsonValue>,
608    symbols: &mut SymbolTable,
609) -> Result<Range<IntVal>> {
610    let scope = SymbolTablePtr::new();
611    *scope.write() = symbols.clone();
612
613    let attr_obj = attr_map
614        .iter()
615        .next()
616        .ok_or(Error::Parse("SizeAttr is an empty object".to_owned()))?;
617    match attr_obj.0.as_str() {
618        "SizeAttr_None" => Ok(Range::Unbounded),
619        "SizeAttr_MinSize" => {
620            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
621            Ok(Range::UnboundedR(size))
622        }
623        "SizeAttr_MaxSize" => {
624            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
625            Ok(Range::UnboundedL(size))
626        }
627        "SizeAttr_MinMaxSize" => {
628            let min_max = attr_obj
629                .1
630                .as_array()
631                .ok_or(error!("SizeAttr MinMaxSize is not a json array"))?;
632            let min = min_max
633                .first()
634                .ok_or(error!("SizeAttr Min is not present"))?;
635            let min_int = parse_expression_to_int_val(min, &scope)?;
636            let max = min_max
637                .get(1)
638                .ok_or(error!("SizeAttr Max is not present"))?;
639            let max_int = parse_expression_to_int_val(max, &scope)?;
640            Ok(Range::Bounded(min_int, max_int))
641        }
642        "SizeAttr_Size" => {
643            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
644            Ok(Range::Single(size))
645        }
646        _ => Err(Error::Parse("SizeAttr is an unknown type".to_owned())),
647    }
648}
649
650fn parse_occur_attr(
651    attr_map: &JsonMap<String, JsonValue>,
652    symbols: &mut SymbolTable,
653) -> Result<Range<IntVal>> {
654    let scope = SymbolTablePtr::new();
655    *scope.write() = symbols.clone();
656    let attr_obj = attr_map
657        .iter()
658        .next()
659        .ok_or(Error::Parse("OccurAttr is an empty object".to_owned()))?;
660    match attr_obj.0.as_str() {
661        "OccurAttr_None" => Ok(Range::Unbounded),
662        "OccurAttr_MinOccur" => {
663            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
664            Ok(Range::UnboundedR(size_int))
665        }
666        "OccurAttr_MaxOccur" => {
667            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
668            Ok(Range::UnboundedL(size_int))
669        }
670        "OccurAttr_MinMaxOccur" => {
671            let min_max = attr_obj
672                .1
673                .as_array()
674                .ok_or(error!("OccurAttr MinMaxOccur is not a json array"))?;
675            let min = min_max
676                .first()
677                .ok_or(error!("OccurAttr Min is not present"))?;
678            let min_int = parse_expression_to_int_val(min, &scope)?;
679            let max = min_max
680                .get(1)
681                .ok_or(error!("OccurAttr Max is not present"))?;
682            let max_int = parse_expression_to_int_val(max, &scope)?;
683            Ok(Range::Bounded(min_int, max_int))
684        }
685        "OccurAttr_Size" => {
686            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
687            Ok(Range::Single(size_int))
688        }
689        _ => Err(Error::Parse("OccurAttr is an unknown type".to_owned())),
690    }
691}
692
693fn parse_int_domain(v: &JsonValue, symbols: &SymbolTable) -> Result<DomainPtr> {
694    let scope = SymbolTablePtr::new();
695    *scope.write() = symbols.clone();
696
697    let mut ranges = Vec::new();
698    let arr = v
699        .as_array()
700        .ok_or(error!("DomainInt is not an array".to_owned()))?[1]
701        .as_array()
702        .ok_or(error!("DomainInt[1] is not an array".to_owned()))?;
703    for range in arr {
704        let range = range
705            .as_object()
706            .ok_or(error!("DomainInt[1] contains a non-object"))?
707            .iter()
708            .next()
709            .ok_or(error!("DomainInt[1] contains an empty object"))?;
710        match range.0.as_str() {
711            "RangeBounded" => {
712                let arr = range
713                    .1
714                    .as_array()
715                    .ok_or(error!("RangeBounded is not an array".to_owned()))?;
716                let mut nums = Vec::new();
717                for item in arr.iter() {
718                    let num = parse_expression_to_int_val(item, &scope)?;
719                    nums.push(num);
720                }
721                let lower = nums
722                    .first()
723                    .cloned()
724                    .ok_or(error!("RangeBounded lower bound missing"))?;
725                let upper = nums
726                    .get(1)
727                    .cloned()
728                    .ok_or(error!("RangeBounded upper bound missing"))?;
729                ranges.push(Range::Bounded(lower, upper));
730            }
731            "RangeSingle" => {
732                let num = parse_expression_to_int_val(range.1, &scope)?;
733                ranges.push(Range::Single(num));
734            }
735            _ => return throw_error!("DomainInt[1] contains an unknown object"),
736        }
737    }
738    Ok(Domain::int(ranges))
739}
740
741fn parse_expression_to_int_val(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<IntVal> {
742    parser_trace!("trying to parse domain value as expression: {}", obj);
743    let expr = parse_expression(obj, scope)?;
744
745    if let Some(Literal::Int(i)) = expr.clone().into_literal() {
746        return Ok(IntVal::Const(i));
747    }
748
749    if let Expression::Atomic(_, Atom::Reference(reference)) = &expr
750        && let Some(reference_val) = IntVal::new_ref(reference)
751    {
752        return Ok(reference_val);
753    }
754
755    IntVal::new_expr(Moo::new(expr)).ok_or(error!("Could not parse integer expression"))
756}
757
758type BinOp = fn(Metadata, Moo<Expression>, Moo<Expression>) -> Expression;
759type UnaryOp = fn(Metadata, Moo<Expression>) -> Expression;
760
761fn binary_operator(op_name: &str) -> Option<BinOp> {
762    match op_name {
763        "MkOpIn" => Some(Expression::In),
764        "MkOpUnion" => Some(Expression::Union),
765        "MkOpIntersect" => Some(Expression::Intersect),
766        "MkOpSupset" => Some(Expression::Supset),
767        "MkOpSupsetEq" => Some(Expression::SupsetEq),
768        "MkOpSubset" => Some(Expression::Subset),
769        "MkOpSubsetEq" => Some(Expression::SubsetEq),
770        "MkOpEq" => Some(Expression::Eq),
771        "MkOpNeq" => Some(Expression::Neq),
772        "MkOpGeq" => Some(Expression::Geq),
773        "MkOpLeq" => Some(Expression::Leq),
774        "MkOpGt" => Some(Expression::Gt),
775        "MkOpLt" => Some(Expression::Lt),
776        "MkOpLexLt" => Some(Expression::LexLt),
777        "MkOpLexGt" => Some(Expression::LexGt),
778        "MkOpLexLeq" => Some(Expression::LexLeq),
779        "MkOpLexGeq" => Some(Expression::LexGeq),
780        "MkOpDiv" => Some(Expression::UnsafeDiv),
781        "MkOpMod" => Some(Expression::UnsafeMod),
782        "MkOpMinus" => Some(Expression::Minus),
783        "MkOpImply" => Some(Expression::Imply),
784        "MkOpIff" => Some(Expression::Iff),
785        "MkOpPow" => Some(Expression::UnsafePow),
786        "MkOpImage" => Some(Expression::Image),
787        "MkOpImageSet" => Some(Expression::ImageSet),
788        "MkOpPreImage" => Some(Expression::PreImage),
789        "MkOpInverse" => Some(Expression::Inverse),
790        "MkOpRestrict" => Some(Expression::Restrict),
791        "MkOpApart" => Some(Expression::Apart),
792        "MkOpTogether" => Some(Expression::Together),
793        "MkOpParty" => Some(Expression::Party),
794        "MkOpActive" => Some(Expression::Active),
795        "MkOpSubstring" => Some(Expression::Substring),
796        "MkOpSubsequence" => Some(Expression::Subsequence),
797        _ => None,
798    }
799}
800
801fn unary_operator(op_name: &str, inner: Option<&Expression>) -> Option<UnaryOp> {
802    match op_name {
803        "MkOpNot" => Some(Expression::Not),
804        "MkOpNegate" => Some(Expression::Neg),
805        "MkOpTwoBars" => {
806            if let Some(inner) = inner {
807                match inner.return_type() {
808                    ReturnType::Int => Some(Expression::Abs),
809                    ReturnType::Matrix(_)
810                    | ReturnType::Set(_)
811                    | ReturnType::MSet(_)
812                    | ReturnType::Relation(_)
813                    | ReturnType::Function(_, _) => Some(Expression::Card),
814                    _ => None,
815                }
816            } else {
817                // Internal expression cannot be known yet, so we just have to assume
818                Some(Expression::Abs)
819            }
820        }
821        "MkOpAnd" => Some(Expression::And),
822        "MkOpSum" => Some(Expression::Sum),
823        "MkOpProduct" => Some(Expression::Product),
824        "MkOpOr" => Some(Expression::Or),
825        "MkOpMin" => Some(Expression::Min),
826        "MkOpMax" => Some(Expression::Max),
827        "MkOpAllDiff" => Some(Expression::AllDiff),
828        "MkOpToInt" => Some(Expression::ToInt),
829        "MkOpDefined" => Some(Expression::Defined),
830        "MkOpRange" => Some(Expression::Range),
831        "MkOpFactorial" => Some(Expression::Factorial),
832        "MkOpToMSet" => Some(Expression::ToMSet),
833        "MkOpToRelation" => Some(Expression::ToRelation),
834        "MkOpParticipants" => Some(Expression::Participants),
835        "MkOpParts" => Some(Expression::Parts),
836        _ => None,
837    }
838}
839
840pub fn parse_expression(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<Expression> {
841    let fail = |stage: &str| -> Error {
842        Error::Parse(format!(
843            "Could not parse expression at stage `{stage}` for json `{obj}`"
844        ))
845    };
846
847    match obj {
848        Value::Object(op) if op.contains_key("Op") => {
849            let op_obj = op
850                .get("Op")
851                .and_then(Value::as_object)
852                .ok_or_else(|| fail("Op.as_object"))?;
853            let (op_name, _) = op_obj.iter().next().ok_or_else(|| fail("Op.iter().next"))?;
854
855            if op_obj.contains_key("MkOpFlatten") {
856                parse_flatten_op(op_obj, scope)
857            } else if op_obj.contains_key("MkOpTable") {
858                parse_table_op(op_obj, scope)
859            } else if op_obj.contains_key("MkOpIndexing") || op_obj.contains_key("MkOpSlicing") {
860                parse_indexing_slicing_op(op_obj, scope)
861            } else if op_obj.contains_key("MkOpRelationProj") {
862                parse_relation_projection(op_obj, scope)
863            } else if op_obj.contains_key("MkOpToSet") {
864                parse_to_set(op_obj, scope)
865            } else if binary_operator(op_name).is_some() {
866                parse_bin_op(op_obj, scope)
867            } else if unary_operator(op_name, None).is_some() {
868                parse_unary_op(op_obj, scope)
869            } else {
870                Err(fail("Op.unknown"))
871            }
872        }
873        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
874            parse_comprehension(comprehension, scope.clone(), None)
875        }
876        Value::Object(refe) if refe.contains_key("Reference") => {
877            let ref_arr = refe["Reference"]
878                .as_array()
879                .ok_or_else(|| fail("Reference.as_array"))?;
880            let ref_obj = ref_arr
881                .first()
882                .and_then(|x| x.as_object())
883                .ok_or_else(|| fail("Reference[0].as_object"))?;
884            let name = ref_obj
885                .get("Name")
886                .and_then(|x| x.as_str())
887                .ok_or_else(|| fail("Reference[0].Name.as_str"))?;
888            let user_name = Name::User(Ustr::from(name));
889
890            let declaration: DeclarationPtr = scope
891                .read()
892                .lookup(&user_name)
893                .ok_or_else(|| fail("Reference.lookup"))?;
894
895            Ok(Expression::Atomic(
896                Metadata::new(),
897                Atom::Reference(crate::ast::Reference::new(declaration)),
898            ))
899        }
900        // In the case where refering to fields. This not behind a reference
901        Value::Object(refe) if refe.contains_key("Name") => {
902            let name = refe
903                .get("Name")
904                .and_then(|x| x.as_str())
905                .ok_or_else(|| fail("Reference[0].Name.as_str"))?;
906            let user_name = Name::User(Ustr::from(name));
907
908            let declaration: DeclarationPtr = scope
909                .read()
910                .lookup(&user_name)
911                .ok_or_else(|| fail("Reference.lookup"))?;
912
913            Ok(Expression::Atomic(
914                Metadata::new(),
915                Atom::Reference(crate::ast::Reference::new(declaration)),
916            ))
917        }
918        Value::Object(abslit) if abslit.contains_key("AbstractLiteral") => {
919            let abstract_literal = abslit["AbstractLiteral"]
920                .as_object()
921                .ok_or_else(|| fail("AbstractLiteral.as_object"))?;
922
923            if abstract_literal.contains_key("AbsLitSet") {
924                parse_abs_lit(&abslit["AbstractLiteral"]["AbsLitSet"], scope)
925            } else if abstract_literal.contains_key("AbsLitFunction") {
926                parse_abs_function(&abslit["AbstractLiteral"]["AbsLitFunction"], scope)
927            } else if abstract_literal.contains_key("AbsLitMSet") {
928                parse_abs_mset(&abslit["AbstractLiteral"]["AbsLitMSet"], scope)
929            } else if abstract_literal.contains_key("AbsLitVariant") {
930                parse_abs_variant(&abslit["AbstractLiteral"]["AbsLitVariant"], scope)
931            } else if abstract_literal.contains_key("AbsLitRelation") {
932                parse_abs_relation(&abslit["AbstractLiteral"]["AbsLitRelation"], scope)
933            } else if abstract_literal.contains_key("AbstractLiteralPartition") {
934                parse_abs_partition(&abslit["AbstractLiteral"]["AbsLitPartition"], scope)
935            } else if abstract_literal.contains_key("AbsLitSequence") {
936                parse_abs_sequence(&abslit["AbstractLiteral"]["AbsLitSequence"], scope)
937            } else {
938                parse_abstract_matrix_as_expr(obj, scope)
939            }
940        }
941
942        Value::Object(constant) if constant.contains_key("Constant") => {
943            parse_constant(constant, scope).or_else(|_| parse_abstract_matrix_as_expr(obj, scope))
944        }
945
946        Value::Object(constant) if constant.contains_key("ConstantAbstract") => {
947            parse_abstract_matrix_as_expr(obj, scope)
948        }
949
950        Value::Object(constant) if constant.contains_key("ConstantInt") => {
951            parse_constant(constant, scope)
952        }
953        Value::Object(constant) if constant.contains_key("ConstantBool") => {
954            parse_constant(constant, scope)
955        }
956
957        _ => Err(fail("no_match")),
958    }
959}
960
961fn parse_abs_lit(abs_set: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
962    let values = abs_set
963        .as_array()
964        .ok_or(error!("AbsLitSet is not an array"))?;
965    let expressions = values
966        .iter()
967        .map(|values| parse_expression(values, scope))
968        .collect::<Result<Vec<_>>>()?;
969
970    Ok(Expression::AbstractLiteral(
971        Metadata::new(),
972        AbstractLiteral::Set(expressions),
973    ))
974}
975
976fn parse_abs_mset(abs_mset: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
977    let values = abs_mset
978        .as_array()
979        .ok_or(error!("AbsLitMSet is not an array"))?;
980    let expressions = values
981        .iter()
982        .map(|values| parse_expression(values, scope))
983        .collect::<Result<Vec<_>>>()?;
984
985    Ok(Expression::AbstractLiteral(
986        Metadata::new(),
987        AbstractLiteral::MSet(expressions),
988    ))
989}
990
991fn parse_abs_partition(abs_partition: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
992    let parts = abs_partition
993        .as_array()
994        .ok_or(error!("AbsLitPartition is not an array"))?;
995
996    let mut partition: Vec<Vec<_>> = Vec::new();
997
998    for part in parts {
999        let vals = part
1000            .as_array()
1001            .ok_or(error!("Part in AbsLitPartition is not an array"))?;
1002
1003        let exprs = vals
1004            .iter()
1005            .map(|values| parse_expression(values, scope))
1006            .collect::<Result<Vec<_>>>()?;
1007
1008        partition.push(exprs);
1009    }
1010
1011    Ok(Expression::AbstractLiteral(
1012        Metadata::new(),
1013        AbstractLiteral::Partition(partition),
1014    ))
1015}
1016
1017fn parse_abs_sequence(abs_seq: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1018    let values = abs_seq
1019        .as_array()
1020        .ok_or(error!("AbsLitSequence is not an array"))?;
1021    let expressions = values
1022        .iter()
1023        .map(|values| parse_expression(values, scope))
1024        .collect::<Result<Vec<_>>>()?;
1025
1026    Ok(Expression::AbstractLiteral(
1027        Metadata::new(),
1028        AbstractLiteral::Sequence(expressions),
1029    ))
1030}
1031
1032fn parse_abs_tuple(abs_tuple: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1033    let values = abs_tuple
1034        .as_array()
1035        .ok_or(error!("AbsLitTuple is not an array"))?;
1036    let expressions = values
1037        .iter()
1038        .map(|values| parse_expression(values, scope))
1039        .collect::<Result<Vec<_>>>()?;
1040
1041    Ok(Expression::AbstractLiteral(
1042        Metadata::new(),
1043        AbstractLiteral::Tuple(expressions),
1044    ))
1045}
1046
1047//parses an abstract record as an expression
1048fn parse_abs_record(abs_record: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1049    let entries = abs_record
1050        .as_array()
1051        .ok_or(error!("AbsLitRecord is not an array"))?;
1052    let mut rec = vec![];
1053
1054    for entry in entries {
1055        let entry = entry
1056            .as_array()
1057            .ok_or(error!("AbsLitRecord entry is not an array"))?;
1058        let name = entry[0]
1059            .as_object()
1060            .ok_or(error!("AbsLitRecord field name is not an object"))?["Name"]
1061            .as_str()
1062            .ok_or(error!("AbsLitRecord field name is not a string"))?;
1063
1064        let value = parse_expression(&entry[1], scope)?;
1065
1066        let name = Name::User(Ustr::from(name));
1067        let rec_entry = FieldValue {
1068            name: name.clone(),
1069            value,
1070        };
1071        rec.push(rec_entry);
1072    }
1073
1074    Ok(Expression::AbstractLiteral(
1075        Metadata::new(),
1076        AbstractLiteral::Record(rec),
1077    ))
1078}
1079
1080//parses an abstract variant as an expression
1081fn parse_abs_variant(abs_variant: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1082    let entry = abs_variant
1083        .as_array()
1084        .ok_or(error!("AbsLitVariant is not an array"))?;
1085    let name = entry[1]
1086        .as_object()
1087        .ok_or(error!("AbsLitVariant field name is not an object"))?["Name"]
1088        .as_str()
1089        .ok_or(error!("AbsLitVariant field name is not a string"))?;
1090
1091    let value = parse_expression(&entry[2], scope)?;
1092
1093    let name = Name::User(Ustr::from(name));
1094    let rec_entry = FieldValue { name, value };
1095
1096    Ok(Expression::AbstractLiteral(
1097        Metadata::new(),
1098        AbstractLiteral::Variant(Moo::new(rec_entry)),
1099    ))
1100}
1101
1102//parses an abstract function as an expression
1103fn parse_abs_function(abs_function: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1104    let entries = abs_function
1105        .as_array()
1106        .ok_or(error!("AbsLitFunction is not an array"))?;
1107    let mut assignments = vec![];
1108
1109    for entry in entries {
1110        let entry = entry
1111            .as_array()
1112            .ok_or(error!("Explicit function assignment is not an array"))?;
1113        let expression = entry
1114            .iter()
1115            .map(|values| parse_expression(values, scope))
1116            .collect::<Result<Vec<_>>>()?;
1117        let domain_value = expression
1118            .first()
1119            .ok_or(error!("Invalid function domain"))?;
1120        let codomain_value = expression
1121            .get(1)
1122            .ok_or(error!("Invalid function codomain"))?;
1123        let tuple = (domain_value.clone(), codomain_value.clone());
1124        assignments.push(tuple);
1125    }
1126    Ok(Expression::AbstractLiteral(
1127        Metadata::new(),
1128        AbstractLiteral::Function(assignments),
1129    ))
1130}
1131
1132//parses an abstract relation as an expression
1133fn parse_abs_relation(abs_relation: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1134    let entries = abs_relation
1135        .as_array()
1136        .ok_or(error!("AbsLitRelation is not an array"))?;
1137    let mut assignments = vec![];
1138
1139    for entry in entries {
1140        let entry = entry
1141            .as_array()
1142            .ok_or(error!("Explicit relation assignment is not an array"))?;
1143        let expression = entry
1144            .iter()
1145            .map(|values| parse_expression(values, scope))
1146            .collect::<Result<Vec<_>>>()?;
1147        assignments.push(expression);
1148    }
1149    Ok(Expression::AbstractLiteral(
1150        Metadata::new(),
1151        AbstractLiteral::Relation(assignments),
1152    ))
1153}
1154
1155fn parse_comprehension(
1156    comprehension: &serde_json::Map<String, Value>,
1157    scope: SymbolTablePtr,
1158    comprehension_kind: Option<ACOperatorKind>,
1159) -> Result<Expression> {
1160    let fail = |stage: &str| -> Error {
1161        Error::Parse(format!("Could not parse comprehension at stage `{stage}`"))
1162    };
1163
1164    let value = &comprehension["Comprehension"];
1165    let mut comprehension = ComprehensionBuilder::new(scope.clone());
1166    let generator_symboltable = comprehension.generator_symboltable();
1167    let return_expr_symboltable = comprehension.return_expr_symboltable();
1168
1169    let generators_and_guards_array = value
1170        .pointer("/1")
1171        .and_then(Value::as_array)
1172        .ok_or_else(|| fail("Comprehension.pointer(/1).as_array"))?;
1173    let generators_and_guards = generators_and_guards_array.iter();
1174
1175    for gen_or_guard in generators_and_guards {
1176        let gen_or_guard_obj = gen_or_guard
1177            .as_object()
1178            .ok_or_else(|| fail("generator_or_guard.as_object"))?;
1179        let (name, inner) = gen_or_guard_obj
1180            .iter()
1181            .next()
1182            .ok_or_else(|| fail("generator_or_guard.iter().next"))?;
1183        comprehension = match name.as_str() {
1184            "Generator" => {
1185                // TODO: more things than GenDomainNoRepr and Single names here?
1186                let generator_obj = inner
1187                    .as_object()
1188                    .ok_or_else(|| fail("Generator.inner.as_object"))?;
1189                let (name, gen_inner) = generator_obj
1190                    .iter()
1191                    .next()
1192                    .ok_or_else(|| fail("Generator.inner.iter().next"))?;
1193                match name.as_str() {
1194                    "GenDomainNoRepr" => {
1195                        let name = gen_inner
1196                            .pointer("/0/Single/Name")
1197                            .and_then(Value::as_str)
1198                            .ok_or_else(|| {
1199                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
1200                            })?;
1201                        let domain_obj = gen_inner
1202                            .pointer("/1")
1203                            .and_then(Value::as_object)
1204                            .ok_or_else(|| fail("GenDomainNoRepr.pointer(/1).as_object"))?;
1205                        let (domain_name, domain_value) = domain_obj
1206                            .iter()
1207                            .next()
1208                            .ok_or_else(|| fail("GenDomainNoRepr.domain.iter().next"))?;
1209                        let domain = parse_domain(
1210                            domain_name,
1211                            domain_value,
1212                            &mut generator_symboltable.write(),
1213                        )?;
1214                        comprehension.generator(DeclarationPtr::new_find(name.into(), domain))
1215                    }
1216                    "GenInExpr" => {
1217                        let name = gen_inner
1218                            .pointer("/0/Single/Name")
1219                            .and_then(Value::as_str)
1220                            .ok_or_else(|| {
1221                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
1222                            })?;
1223                        let generator_expr = gen_inner
1224                            .pointer("/1")
1225                            .ok_or_else(|| fail("GenInExpr.pointer(/1)"))?;
1226                        let expr = parse_expression(generator_expr, &scope)
1227                            .map_err(|_| fail("GenInExpr.parse_expression"))?;
1228                        comprehension.expression_generator(name.into(), expr)
1229                    }
1230                    _ => {
1231                        bug!("unknown generator type inside comprehension {name}");
1232                    }
1233                }
1234            }
1235
1236            "Condition" => {
1237                let expr = parse_expression(inner, &generator_symboltable)
1238                    .map_err(|_| fail("Condition.parse_expression"))?;
1239                comprehension.guard(expr)
1240            }
1241
1242            x => {
1243                bug!("unknown field inside comprehension {x}");
1244            }
1245        }
1246    }
1247
1248    let return_expr_value = value
1249        .pointer("/0")
1250        .ok_or_else(|| fail("Comprehension.pointer(/0)"))?;
1251    let expr = parse_expression(return_expr_value, &return_expr_symboltable)
1252        .map_err(|_| fail("Comprehension.return_expr.parse_expression"))?;
1253
1254    Ok(Expression::Comprehension(
1255        Metadata::new(),
1256        Moo::new(comprehension.with_return_value(expr, comprehension_kind)),
1257    ))
1258}
1259
1260fn parse_bin_op(
1261    bin_op: &serde_json::Map<String, Value>,
1262    scope: &SymbolTablePtr,
1263) -> Result<Expression> {
1264    // we know there is a single key value pair in this object
1265    // extract the value, ignore the key
1266    let (key, value) = bin_op
1267        .into_iter()
1268        .next()
1269        .ok_or(error!("Binary op object is empty"))?;
1270
1271    let constructor = binary_operator(key.as_str())
1272        .ok_or(error!(format!("Unknown binary operator `{}`", key)))?;
1273
1274    match &value {
1275        Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
1276            let arg1 = parse_expression(&bin_op_args[0], scope)?;
1277            let arg2 = parse_expression(&bin_op_args[1], scope)?;
1278            Ok(constructor(Metadata::new(), Moo::new(arg1), Moo::new(arg2)))
1279        }
1280        _ => Err(error!("Binary operator arguments are not a 2-array")),
1281    }
1282}
1283
1284fn parse_table_op(
1285    op: &serde_json::Map<String, Value>,
1286    scope: &SymbolTablePtr,
1287) -> Result<Expression> {
1288    let args = op
1289        .get("MkOpTable")
1290        .ok_or(error!("MkOpTable missing"))?
1291        .as_array()
1292        .ok_or(error!("MkOpTable is not an array"))?;
1293
1294    if args.len() != 2 {
1295        return Err(error!("MkOpTable arguments are not a 2-array"));
1296    }
1297
1298    let tuple_expr = parse_expression(&args[0], scope)?;
1299    let allowed_rows_expr = parse_expression(&args[1], scope)?;
1300
1301    let (tuple_elems, _) = tuple_expr
1302        .clone()
1303        .unwrap_matrix_unchecked()
1304        .ok_or(error!("MkOpTable first argument is not a matrix"))?;
1305    let (allowed_rows, _) = allowed_rows_expr
1306        .clone()
1307        .unwrap_matrix_unchecked()
1308        .ok_or(error!("MkOpTable second argument is not a matrix"))?;
1309
1310    for row_expr in allowed_rows {
1311        let (row_elems, _) = row_expr
1312            .unwrap_matrix_unchecked()
1313            .ok_or(error!("MkOpTable row is not a matrix"))?;
1314
1315        if row_elems.len() != tuple_elems.len() {
1316            return Err(error!("MkOpTable row width does not match tuple width"));
1317        }
1318    }
1319
1320    Ok(Expression::Table(
1321        Metadata::new(),
1322        Moo::new(tuple_expr),
1323        Moo::new(allowed_rows_expr),
1324    ))
1325}
1326
1327fn parse_indexing_slicing_op(
1328    op: &serde_json::Map<String, Value>,
1329    scope: &SymbolTablePtr,
1330) -> Result<Expression> {
1331    // we know there is a single key value pair in this object
1332    // extract the value, ignore the key
1333    let (key, value) = op
1334        .into_iter()
1335        .next()
1336        .ok_or(error!("Indexing/Slicing op object is empty"))?;
1337
1338    // we know that this is meant to be a mkopindexing, so anything that goes wrong from here is a
1339    // bug!
1340
1341    // Conjure does a[1,2,3] as MkOpIndexing(MkOpIndexing(MkOpIndexing(a,3),2),1).
1342    //
1343    // And  a[1,..,3] as MkOpIndexing(MkOpSlicing(MkOpIndexing(a,3)),1).
1344    //
1345    // However, we want this in a flattened form: Index(a, [1,2,3])
1346    let mut target: Expression;
1347    let mut indices: Vec<Option<Expression>> = vec![];
1348
1349    // true if this has no slicing, false otherwise.
1350    let mut all_known = true;
1351
1352    match key.as_str() {
1353        "MkOpIndexing" => {
1354            match &value {
1355                Value::Array(op_args) if op_args.len() == 2 => {
1356                    target = parse_expression(&op_args[0], scope)?;
1357                    indices.push(Some(parse_expression(&op_args[1], scope)?));
1358                }
1359                _ => return Err(error!("Unknown object inside MkOpIndexing")),
1360            };
1361        }
1362
1363        "MkOpSlicing" => {
1364            all_known = false;
1365            match &value {
1366                Value::Array(op_args) if op_args.len() == 3 => {
1367                    target = parse_expression(&op_args[0], scope)?;
1368                    indices.push(None);
1369                }
1370                _ => return Err(error!("Unknown object inside MkOpSlicing")),
1371            };
1372        }
1373
1374        _ => return Err(error!("Unknown indexing/slicing operator")),
1375    }
1376
1377    loop {
1378        match &mut target {
1379            Expression::UnsafeIndex(_, new_target, new_indices) => {
1380                indices.extend(new_indices.iter().cloned().rev().map(Some));
1381                target = Moo::unwrap_or_clone(new_target.clone());
1382            }
1383
1384            Expression::UnsafeSlice(_, new_target, new_indices) => {
1385                all_known = false;
1386                indices.extend(new_indices.iter().cloned().rev());
1387                target = Moo::unwrap_or_clone(new_target.clone());
1388            }
1389
1390            _ => {
1391                // not a slice or an index, we have reached the target.
1392                break;
1393            }
1394        }
1395    }
1396
1397    indices.reverse();
1398
1399    if all_known {
1400        Ok(Expression::UnsafeIndex(
1401            Metadata::new(),
1402            Moo::new(target),
1403            indices
1404                .into_iter()
1405                .collect::<Option<Vec<_>>>()
1406                .ok_or(error!("Missing index in fully-known indexing operation"))?,
1407        ))
1408    } else {
1409        Ok(Expression::UnsafeSlice(
1410            Metadata::new(),
1411            Moo::new(target),
1412            indices,
1413        ))
1414    }
1415}
1416
1417// Parses relation projection, to get a Vec<Option<Expression>> for the projections
1418fn parse_relation_projection(
1419    op: &serde_json::Map<String, Value>,
1420    scope: &SymbolTablePtr,
1421) -> Result<Expression> {
1422    let args = op
1423        .get("MkOpRelationProj")
1424        .ok_or(error!("MkOpRelationProj missing"))?
1425        .as_array()
1426        .ok_or(error!("MkOpRelationProj is not an array"))?;
1427    let first = args
1428        .first()
1429        .ok_or(error!("MkOpRelationProj missing first argument"))?;
1430    let second = args
1431        .get(1)
1432        .ok_or(error!("MkOpRelationProj missing second argument"))?
1433        .as_array()
1434        .ok_or(error!("MkOpRelationProj second argument is not an array"))?;
1435    let relation = parse_expression(first, scope).ok();
1436    // We build a vec of option expressions.
1437    // In the case where a relation domain is not being projected it is None, otherwise it is Some with the expression
1438    // We parse the 'null' as an error, which is mapped to None after parse_expression()
1439    let projections = second
1440        .iter()
1441        .map(|expr| parse_expression(expr, scope).ok())
1442        .collect();
1443    if let Some(relation) = relation {
1444        Ok(Expression::RelationProj(
1445            Metadata::new(),
1446            Moo::new(relation),
1447            projections,
1448        ))
1449    } else {
1450        Err(error!("MkOpRelationProj does not contain relation"))
1451    }
1452}
1453
1454// The ToSet operator is not truely a unary operator.
1455// The internal expression is 2nd in the array, with 'false' as the first element
1456// Therefore it needs separate parsing
1457fn parse_to_set(op: &serde_json::Map<String, Value>, scope: &SymbolTablePtr) -> Result<Expression> {
1458    let args = op
1459        .get("MkOpToSet")
1460        .ok_or(error!("MkOpToSet missing"))?
1461        .as_array()
1462        .ok_or(error!("MkOpToSet is not an array"))?;
1463    let second = args
1464        .get(1)
1465        .ok_or(error!("MkOpToSet missing second argument"))?;
1466    let inner = parse_expression(second, scope)?;
1467    Ok(Expression::ToSet(Metadata::new(), Moo::new(inner)))
1468}
1469
1470fn parse_flatten_op(
1471    op: &serde_json::Map<String, Value>,
1472    scope: &SymbolTablePtr,
1473) -> Result<Expression> {
1474    let args = op
1475        .get("MkOpFlatten")
1476        .ok_or(error!("MkOpFlatten missing"))?
1477        .as_array()
1478        .ok_or(error!("MkOpFlatten is not an array"))?;
1479
1480    let first = args
1481        .first()
1482        .ok_or(error!("MkOpFlatten missing first argument"))?;
1483    let second = args
1484        .get(1)
1485        .ok_or(error!("MkOpFlatten missing second argument"))?;
1486    let n = parse_expression(first, scope).ok();
1487    let matrix = parse_expression(second, scope)?;
1488
1489    if let Some(n) = n {
1490        Ok(Expression::Flatten(
1491            Metadata::new(),
1492            Some(Moo::new(n)),
1493            Moo::new(matrix),
1494        ))
1495    } else {
1496        Ok(Expression::Flatten(Metadata::new(), None, Moo::new(matrix)))
1497    }
1498}
1499
1500fn parse_unary_op(
1501    un_op: &serde_json::Map<String, Value>,
1502    scope: &SymbolTablePtr,
1503) -> Result<Expression> {
1504    let fail = |stage: &str| -> Error {
1505        Error::Parse(format!("Could not parse unary op at stage `{stage}`"))
1506    };
1507
1508    let (key, value) = un_op
1509        .iter()
1510        .next()
1511        .ok_or_else(|| fail("un_op.iter().next"))?;
1512
1513    // unops are the main things that contain comprehensions
1514    //
1515    // if the current expr is a quantifier like and/or/sum and it contains a comprehension, let the comprehension know what it is inside.
1516    let arg = match value {
1517        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
1518            let comprehension_kind = match key.as_str() {
1519                "MkOpOr" => Some(ACOperatorKind::Or),
1520                "MkOpAnd" => Some(ACOperatorKind::And),
1521                "MkOpSum" => Some(ACOperatorKind::Sum),
1522                "MkOpProduct" => Some(ACOperatorKind::Product),
1523                _ => None,
1524            };
1525            parse_comprehension(comprehension, scope.clone(), comprehension_kind)
1526                .map_err(|_| fail("value.Comprehension.parse_comprehension"))
1527        }
1528        _ => parse_expression(value, scope).map_err(|_| fail("value.parse_expression")),
1529    }
1530    .map_err(|_| fail("arg"))?;
1531
1532    let constructor =
1533        unary_operator(key.as_str(), Some(&arg)).ok_or_else(|| fail("unary_operator"))?;
1534
1535    Ok(constructor(Metadata::new(), Moo::new(arg)))
1536}
1537
1538// Takes in { AbstractLiteral: .... }
1539fn parse_abstract_matrix_as_expr(
1540    value: &serde_json::Value,
1541    scope: &SymbolTablePtr,
1542) -> Result<Expression> {
1543    parser_trace!("trying to parse an abstract literal matrix");
1544    let (values, domain_name, domain_value) =
1545        if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix") {
1546            parser_trace!(".. found JSON pointer /AbstractLiteral/AbstractLitMatrix");
1547            let (domain_name, domain_value) = abs_lit_matrix
1548                .pointer("/0")
1549                .and_then(Value::as_object)
1550                .and_then(|x| x.iter().next())
1551                .ok_or(error!("AbsLitMatrix missing domain"))?;
1552            let values = abs_lit_matrix
1553                .pointer("/1")
1554                .ok_or(error!("AbsLitMatrix missing values"))?;
1555
1556            Some((values, domain_name, domain_value))
1557        }
1558        // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
1559        else if let Some(const_abs_lit_matrix) =
1560            value.pointer("/Constant/ConstantAbstract/AbsLitMatrix")
1561        {
1562            parser_trace!(".. found JSON pointer /Constant/ConstantAbstract/AbsLitMatrix");
1563            let (domain_name, domain_value) = const_abs_lit_matrix
1564                .pointer("/0")
1565                .and_then(Value::as_object)
1566                .and_then(|x| x.iter().next())
1567                .ok_or(error!("ConstantAbstract AbsLitMatrix missing domain"))?;
1568            let values = const_abs_lit_matrix
1569                .pointer("/1")
1570                .ok_or(error!("ConstantAbstract AbsLitMatrix missing values"))?;
1571
1572            Some((values, domain_name, domain_value))
1573        } else if let Some(const_abs_lit_matrix) = value.pointer("/ConstantAbstract/AbsLitMatrix") {
1574            parser_trace!(".. found JSON pointer /ConstantAbstract/AbsLitMatrix");
1575            let (domain_name, domain_value) = const_abs_lit_matrix
1576                .pointer("/0")
1577                .and_then(Value::as_object)
1578                .and_then(|x| x.iter().next())
1579                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing domain"))?;
1580            let values = const_abs_lit_matrix
1581                .pointer("/1")
1582                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing values"))?;
1583            Some((values, domain_name, domain_value))
1584        } else {
1585            None
1586        }
1587        .ok_or(error!("Could not parse abstract literal matrix"))?;
1588
1589    parser_trace!(".. found in domain and values in JSON:");
1590    parser_trace!(".. .. index domain name {domain_name}");
1591    parser_trace!(".. .. values {value}");
1592
1593    let args_parsed = values
1594        .as_array()
1595        .ok_or(error!("Matrix values are not an array"))?
1596        .iter()
1597        .map(|x| parse_expression(x, scope))
1598        .collect::<Result<Vec<Expression>>>()?;
1599
1600    if !args_parsed.is_empty() {
1601        parser_trace!(
1602            ".. successfully parsed values as expressions: {}, ... ",
1603            args_parsed[0]
1604        );
1605    } else {
1606        parser_trace!(".. successfully parsed empty values ",);
1607    }
1608
1609    let mut symbols = scope.write();
1610    match parse_domain(domain_name, domain_value, &mut symbols) {
1611        Ok(domain) => {
1612            parser_trace!("... sucessfully parsed domain as {domain}");
1613            Ok(into_matrix_expr![args_parsed;domain])
1614        }
1615        Err(_) => {
1616            parser_trace!("... failed to parse domain, creating a matrix without one.");
1617            Ok(into_matrix_expr![args_parsed])
1618        }
1619    }
1620}
1621
1622fn parse_constant(
1623    constant: &serde_json::Map<String, Value>,
1624    scope: &SymbolTablePtr,
1625) -> Result<Expression> {
1626    match &constant.get("Constant") {
1627        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
1628            let int_32: i32 = match int["ConstantInt"]
1629                .as_array()
1630                .ok_or(error!("ConstantInt is not an array"))?[1]
1631                .as_i64()
1632                .ok_or(error!("ConstantInt does not contain int"))?
1633                .try_into()
1634            {
1635                Ok(x) => x,
1636                Err(_) => return Err(error!("ConstantInt cannot be represented as i32")),
1637            };
1638
1639            Ok(Expression::Atomic(
1640                Metadata::new(),
1641                Atom::Literal(Literal::Int(int_32)),
1642            ))
1643        }
1644
1645        Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
1646            let b: bool = b["ConstantBool"]
1647                .as_bool()
1648                .ok_or(error!("ConstantBool does not contain bool"))?;
1649            Ok(Expression::Atomic(
1650                Metadata::new(),
1651                Atom::Literal(Literal::Bool(b)),
1652            ))
1653        }
1654
1655        Some(Value::Object(int)) if int.contains_key("ConstantAbstract") => {
1656            if let Some(Value::Object(obj)) = int.get("ConstantAbstract") {
1657                if let Some(arr) = obj.get("AbsLitSet") {
1658                    return parse_abs_lit(arr, scope);
1659                } else if let Some(arr) = obj.get("AbsLitMSet") {
1660                    return parse_abs_mset(arr, scope);
1661                } else if let Some(arr) = obj.get("AbsLitMatrix") {
1662                    return parse_abstract_matrix_as_expr(arr, scope);
1663                } else if let Some(arr) = obj.get("AbsLitTuple") {
1664                    return parse_abs_tuple(arr, scope);
1665                } else if let Some(arr) = obj.get("AbsLitRecord") {
1666                    return parse_abs_record(arr, scope);
1667                } else if let Some(arr) = obj.get("AbsLitPartition") {
1668                    return parse_abs_partition(arr, scope);
1669                } else if let Some(arr) = obj.get("AbsLitFunction") {
1670                    return parse_abs_function(arr, scope);
1671                } else if let Some(arr) = obj.get("AbsLitVariant") {
1672                    return parse_abs_variant(arr, scope);
1673                } else if let Some(arr) = obj.get("AbsLitRelation") {
1674                    return parse_abs_relation(arr, scope);
1675                } else if let Some(arr) = obj.get("AbsLitSequence") {
1676                    return parse_abs_sequence(arr, scope);
1677                }
1678            }
1679            Err(error!("Unhandled ConstantAbstract literal type"))
1680        }
1681
1682        // sometimes (e.g. constant matrices) we can have a ConstantInt / Constant bool that is
1683        // not wrapped in Constant
1684        None => {
1685            let int_expr = constant
1686                .get("ConstantInt")
1687                .and_then(|x| x.as_array())
1688                .and_then(|x| x[1].as_i64())
1689                .and_then(|x| x.try_into().ok())
1690                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
1691
1692            if let Some(expr) = int_expr {
1693                return Ok(expr);
1694            }
1695
1696            let bool_expr = constant
1697                .get("ConstantBool")
1698                .and_then(|x| x.as_bool())
1699                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
1700
1701            if let Some(expr) = bool_expr {
1702                return Ok(expr);
1703            }
1704
1705            Err(error!(format!("Unhandled parse_constant {constant:#?}")))
1706        }
1707        otherwise => Err(error!(format!("Unhandled parse_constant {otherwise:#?}"))),
1708    }
1709}