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::Field;
16use crate::ast::{
17    AbstractLiteral, Atom, BinaryAttr, DeclarationPtr, Domain, Expression, FuncAttr, IntVal,
18    JectivityAttr, Literal, MSetAttr, Name, PartialityAttr, Range, RelAttr, ReturnType,
19    SequenceAttr, SetAttr, SymbolTable, SymbolTablePtr,
20};
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 rec = Field {
440                    name,
441                    value: parse_domain(domain.0, domain.1, symbols)?,
442                };
443
444                entries.push(rec);
445            }
446
447            if is_record {
448                Ok(Domain::record(entries))
449            } else {
450                Ok(Domain::variant(entries))
451            }
452        }
453        "DomainFunction" => {
454            let domain = domain_value
455                .get(2)
456                .and_then(|v| v.as_object())
457                .ok_or(error!("Function domain is not an object"))?;
458            let domain = domain
459                .iter()
460                .next()
461                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
462            let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
463
464            let codomain = domain_value
465                .get(3)
466                .and_then(|v| v.as_object())
467                .ok_or(error!("Function codomain is not an object"))?;
468            let codomain = codomain
469                .iter()
470                .next()
471                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
472            let codomain = parse_domain(codomain.0.as_str(), codomain.1, symbols)?;
473
474            // Attribute parsing
475            let attributes = domain_value
476                .get(1)
477                .and_then(|v| v.as_array())
478                .ok_or(error!("Function attributes is not a json array"))?;
479            let size = attributes
480                .first()
481                .and_then(|v| v.as_object())
482                .ok_or(error!("Function size attributes is not an object"))?;
483            let size = parse_size_attr(size, symbols)?;
484            let partiality = attributes
485                .get(1)
486                .and_then(|v| v.as_str())
487                .ok_or(error!("Function partiality is not a string"))?;
488            let partiality = match partiality {
489                "PartialityAttr_Partial" => Some(PartialityAttr::Partial),
490                "PartialityAttr_Total" => Some(PartialityAttr::Total),
491                _ => None,
492            };
493            let partiality =
494                partiality.ok_or(Error::Parse("Partiality is an unknown type".to_owned()))?;
495            let jectivity = attributes
496                .get(2)
497                .and_then(|v| v.as_str())
498                .ok_or(error!("Function jectivity is not a string"))?;
499            let jectivity = match jectivity {
500                "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
501                "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
502                "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
503                "JectivityAttr_None" => Some(JectivityAttr::None),
504                _ => None,
505            };
506            let jectivity =
507                jectivity.ok_or(Error::Parse("Jectivity is an unknown type".to_owned()))?;
508
509            let attr: FuncAttr<IntVal> = FuncAttr {
510                size,
511                partiality,
512                jectivity,
513            };
514
515            Ok(Domain::function(attr, domain, codomain))
516        }
517
518        "DomainRelation" => {
519            let domains = domain_value
520                .get(2)
521                .and_then(|v| v.as_array())
522                .ok_or(Error::Parse(
523                    "Relation domains are not a json array".to_owned(),
524                ))?;
525            let domains = domains
526                .iter()
527                .map(|x| {
528                    let domain = x
529                        .as_object()
530                        .ok_or(Error::Parse("Relation domain is not an object".to_owned()))?
531                        .iter()
532                        .next()
533                        .ok_or(Error::Parse(
534                            "Relation domain is an empty object".to_owned(),
535                        ))?;
536                    parse_domain(domain.0, domain.1, symbols)
537                })
538                .collect::<Result<Vec<DomainPtr>>>()?;
539
540            // Attribute parsing
541            let attributes = domain_value
542                .get(1)
543                .and_then(|v| v.as_array())
544                .ok_or(Error::Parse(
545                    "Relation attributes are not a json array".to_owned(),
546                ))?;
547            let size = attributes
548                .first()
549                .and_then(|v| v.as_object())
550                .ok_or(Error::Parse(
551                    "Relation size attributes are not an object".to_owned(),
552                ))?;
553            let size = parse_size_attr(size, symbols)?;
554            let binary = attributes
555                .get(1)
556                .and_then(|v| v.as_array())
557                .ok_or(Error::Parse(
558                    "Relation binary attributes are not a json array".to_owned(),
559                ))?;
560            let binary = binary
561                .iter()
562                .map(|x| {
563                    let attr = x.as_str().ok_or(Error::Parse(
564                        "Relation binary attribute is not a string".to_owned(),
565                    ))?;
566                    match attr {
567                        "BinRelAttr_Reflexive" => Ok(BinaryAttr::Reflexive),
568                        "BinRelAttr_Irreflexive" => Ok(BinaryAttr::Irreflexive),
569                        "BinRelAttr_Coreflexive" => Ok(BinaryAttr::Coreflexive),
570                        "BinRelAttr_Symmetric" => Ok(BinaryAttr::Symmetric),
571                        "BinRelAttr_AntiSymmetric" => Ok(BinaryAttr::AntiSymmetric),
572                        "BinRelAttr_ASymmetric" => Ok(BinaryAttr::ASymmetric),
573                        "BinRelAttr_Transitive" => Ok(BinaryAttr::Transitive),
574                        "BinRelAttr_Total" => Ok(BinaryAttr::Total),
575                        "BinRelAttr_Connex" => Ok(BinaryAttr::Connex),
576                        "BinRelAttr_Euclidean" => Ok(BinaryAttr::Euclidean),
577                        "BinRelAttr_Serial" => Ok(BinaryAttr::Serial),
578                        "BinRelAttr_Equivalence" => Ok(BinaryAttr::Equivalence),
579                        "BinRelAttr_PartialOrder" => Ok(BinaryAttr::PartialOrder),
580                        _ => Err(Error::Parse(
581                            "Relation binary attribute is invalid".to_owned(),
582                        )),
583                    }
584                })
585                .collect::<Result<Vec<BinaryAttr>>>()?;
586
587            let attr: RelAttr<IntVal> = RelAttr { size, binary };
588
589            Ok(Domain::relation(attr, domains))
590        }
591        _ => Err(Error::Parse(
592            "FindOrGiven[2] is an unknown object".to_owned(), // consider covered
593        )),
594    }
595}
596
597fn parse_size_attr(
598    attr_map: &JsonMap<String, JsonValue>,
599    symbols: &mut SymbolTable,
600) -> Result<Range<IntVal>> {
601    let scope = SymbolTablePtr::new();
602    *scope.write() = symbols.clone();
603
604    let attr_obj = attr_map
605        .iter()
606        .next()
607        .ok_or(Error::Parse("SizeAttr is an empty object".to_owned()))?;
608    match attr_obj.0.as_str() {
609        "SizeAttr_None" => Ok(Range::Unbounded),
610        "SizeAttr_MinSize" => {
611            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
612            Ok(Range::UnboundedR(size))
613        }
614        "SizeAttr_MaxSize" => {
615            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
616            Ok(Range::UnboundedL(size))
617        }
618        "SizeAttr_MinMaxSize" => {
619            let min_max = attr_obj
620                .1
621                .as_array()
622                .ok_or(error!("SizeAttr MinMaxSize is not a json array"))?;
623            let min = min_max
624                .first()
625                .ok_or(error!("SizeAttr Min is not present"))?;
626            let min_int = parse_expression_to_int_val(min, &scope)?;
627            let max = min_max
628                .get(1)
629                .ok_or(error!("SizeAttr Max is not present"))?;
630            let max_int = parse_expression_to_int_val(max, &scope)?;
631            Ok(Range::Bounded(min_int, max_int))
632        }
633        "SizeAttr_Size" => {
634            let size = parse_expression_to_int_val(attr_obj.1, &scope)?;
635            Ok(Range::Single(size))
636        }
637        _ => Err(Error::Parse("SizeAttr is an unknown type".to_owned())),
638    }
639}
640
641fn parse_occur_attr(
642    attr_map: &JsonMap<String, JsonValue>,
643    symbols: &mut SymbolTable,
644) -> Result<Range<IntVal>> {
645    let scope = SymbolTablePtr::new();
646    *scope.write() = symbols.clone();
647    let attr_obj = attr_map
648        .iter()
649        .next()
650        .ok_or(Error::Parse("OccurAttr is an empty object".to_owned()))?;
651    match attr_obj.0.as_str() {
652        "OccurAttr_None" => Ok(Range::Unbounded),
653        "OccurAttr_MinOccur" => {
654            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
655            Ok(Range::UnboundedR(size_int))
656        }
657        "OccurAttr_MaxOccur" => {
658            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
659            Ok(Range::UnboundedL(size_int))
660        }
661        "OccurAttr_MinMaxOccur" => {
662            let min_max = attr_obj
663                .1
664                .as_array()
665                .ok_or(error!("OccurAttr MinMaxOccur is not a json array"))?;
666            let min = min_max
667                .first()
668                .ok_or(error!("OccurAttr Min is not present"))?;
669            let min_int = parse_expression_to_int_val(min, &scope)?;
670            let max = min_max
671                .get(1)
672                .ok_or(error!("OccurAttr Max is not present"))?;
673            let max_int = parse_expression_to_int_val(max, &scope)?;
674            Ok(Range::Bounded(min_int, max_int))
675        }
676        "OccurAttr_Size" => {
677            let size_int = parse_expression_to_int_val(attr_obj.1, &scope)?;
678            Ok(Range::Single(size_int))
679        }
680        _ => Err(Error::Parse("OccurAttr is an unknown type".to_owned())),
681    }
682}
683
684fn parse_int_domain(v: &JsonValue, symbols: &SymbolTable) -> Result<DomainPtr> {
685    let scope = SymbolTablePtr::new();
686    *scope.write() = symbols.clone();
687
688    let mut ranges = Vec::new();
689    let arr = v
690        .as_array()
691        .ok_or(error!("DomainInt is not an array".to_owned()))?[1]
692        .as_array()
693        .ok_or(error!("DomainInt[1] is not an array".to_owned()))?;
694    for range in arr {
695        let range = range
696            .as_object()
697            .ok_or(error!("DomainInt[1] contains a non-object"))?
698            .iter()
699            .next()
700            .ok_or(error!("DomainInt[1] contains an empty object"))?;
701        match range.0.as_str() {
702            "RangeBounded" => {
703                let arr = range
704                    .1
705                    .as_array()
706                    .ok_or(error!("RangeBounded is not an array".to_owned()))?;
707                let mut nums = Vec::new();
708                for item in arr.iter() {
709                    let num = parse_expression_to_int_val(item, &scope)?;
710                    nums.push(num);
711                }
712                let lower = nums
713                    .first()
714                    .cloned()
715                    .ok_or(error!("RangeBounded lower bound missing"))?;
716                let upper = nums
717                    .get(1)
718                    .cloned()
719                    .ok_or(error!("RangeBounded upper bound missing"))?;
720                ranges.push(Range::Bounded(lower, upper));
721            }
722            "RangeSingle" => {
723                let num = parse_expression_to_int_val(range.1, &scope)?;
724                ranges.push(Range::Single(num));
725            }
726            _ => return throw_error!("DomainInt[1] contains an unknown object"),
727        }
728    }
729    Ok(Domain::int(ranges))
730}
731
732fn parse_expression_to_int_val(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<IntVal> {
733    parser_trace!("trying to parse domain value as expression: {}", obj);
734    let expr = parse_expression(obj, scope)?;
735
736    if let Some(Literal::Int(i)) = expr.clone().into_literal() {
737        return Ok(IntVal::Const(i as i64));
738    }
739
740    if let Expression::Atomic(_, Atom::Reference(reference)) = &expr
741        && let Ok(reference_val) = IntVal::new_ref(reference)
742    {
743        return Ok(reference_val);
744    }
745
746    IntVal::new_expr(Moo::new(expr))
747        .map_err(|e| error!(format!("Could not parse integer expression: {e}")))
748}
749
750type BinOp = fn(Metadata, Moo<Expression>, Moo<Expression>) -> Expression;
751type UnaryOp = fn(Metadata, Moo<Expression>) -> Expression;
752
753fn binary_operator(op_name: &str) -> Option<BinOp> {
754    match op_name {
755        "MkOpIn" => Some(Expression::In),
756        "MkOpUnion" => Some(Expression::Union),
757        "MkOpIntersect" => Some(Expression::Intersect),
758        "MkOpSupset" => Some(Expression::Supset),
759        "MkOpSupsetEq" => Some(Expression::SupsetEq),
760        "MkOpSubset" => Some(Expression::Subset),
761        "MkOpSubsetEq" => Some(Expression::SubsetEq),
762        "MkOpEq" => Some(Expression::Eq),
763        "MkOpNeq" => Some(Expression::Neq),
764        "MkOpGeq" => Some(Expression::Geq),
765        "MkOpLeq" => Some(Expression::Leq),
766        "MkOpGt" => Some(Expression::Gt),
767        "MkOpLt" => Some(Expression::Lt),
768        "MkOpLexLt" => Some(Expression::LexLt),
769        "MkOpLexGt" => Some(Expression::LexGt),
770        "MkOpLexLeq" => Some(Expression::LexLeq),
771        "MkOpLexGeq" => Some(Expression::LexGeq),
772        "MkOpDiv" => Some(Expression::UnsafeDiv),
773        "MkOpMod" => Some(Expression::UnsafeMod),
774        "MkOpMinus" => Some(Expression::Minus),
775        "MkOpImply" => Some(Expression::Imply),
776        "MkOpIff" => Some(Expression::Iff),
777        "MkOpPow" => Some(Expression::UnsafePow),
778        "MkOpImage" => Some(Expression::Image),
779        "MkOpImageSet" => Some(Expression::ImageSet),
780        "MkOpPreImage" => Some(Expression::PreImage),
781        "MkOpInverse" => Some(Expression::Inverse),
782        "MkOpRestrict" => Some(Expression::Restrict),
783        "MkOpApart" => Some(Expression::Apart),
784        "MkOpTogether" => Some(Expression::Together),
785        "MkOpParty" => Some(Expression::Party),
786        "MkOpSubstring" => Some(Expression::Substring),
787        "MkOpSubsequence" => Some(Expression::Subsequence),
788        _ => None,
789    }
790}
791
792fn unary_operator(op_name: &str, inner: Option<&Expression>) -> Option<UnaryOp> {
793    match op_name {
794        "MkOpNot" => Some(Expression::Not),
795        "MkOpNegate" => Some(Expression::Neg),
796        "MkOpTwoBars" => {
797            if let Some(inner) = inner {
798                match inner.return_type() {
799                    ReturnType::Int => Some(Expression::Abs),
800                    ReturnType::Matrix(_)
801                    | ReturnType::Set(_)
802                    | ReturnType::MSet(_)
803                    | ReturnType::Relation(_)
804                    | ReturnType::Function(_, _) => Some(Expression::Card),
805                    _ => None,
806                }
807            } else {
808                // Internal expression cannot be known yet, so we just have to assume
809                Some(Expression::Abs)
810            }
811        }
812        "MkOpAnd" => Some(Expression::And),
813        "MkOpSum" => Some(Expression::Sum),
814        "MkOpProduct" => Some(Expression::Product),
815        "MkOpOr" => Some(Expression::Or),
816        "MkOpMin" => Some(Expression::Min),
817        "MkOpMax" => Some(Expression::Max),
818        "MkOpAllDiff" => Some(Expression::AllDiff),
819        "MkOpToInt" => Some(Expression::ToInt),
820        "MkOpDefined" => Some(Expression::Defined),
821        "MkOpRange" => Some(Expression::Range),
822        "MkOpFactorial" => Some(Expression::Factorial),
823        "MkOpToMSet" => Some(Expression::ToMSet),
824        "MkOpToRelation" => Some(Expression::ToRelation),
825        "MkOpParticipants" => Some(Expression::Participants),
826        "MkOpParts" => Some(Expression::Parts),
827        _ => None,
828    }
829}
830
831fn parse_reference_name(obj: &JsonValue) -> Result<Name> {
832    // { Name: "x" } directly
833    if let Some(name) = obj.get("Name").and_then(|x| x.as_str()) {
834        return Ok(Name::User(Ustr::from(name)));
835    }
836
837    // {
838    //   Reference: [
839    //     { Name: "x" }
840    //   ]
841    // }
842    let ref_arr = obj["Reference"]
843        .as_array()
844        .ok_or_else(|| error!("Reference.as_array"))?;
845    let ref_obj = ref_arr
846        .first()
847        .and_then(|x| x.as_object())
848        .ok_or_else(|| error!("Reference[0].as_object"))?;
849    let name = ref_obj
850        .get("Name")
851        .and_then(|x| x.as_str())
852        .ok_or_else(|| error!("Reference[0].Name.as_str"))?;
853    Ok(Name::User(Ustr::from(name)))
854}
855
856pub fn parse_expression(obj: &JsonValue, scope: &SymbolTablePtr) -> Result<Expression> {
857    let fail = |stage: &str| -> Error {
858        Error::Parse(format!(
859            "Could not parse expression at stage `{stage}` for json `{obj}`"
860        ))
861    };
862
863    match obj {
864        Value::Object(op) if op.contains_key("Op") => {
865            let op_obj = op
866                .get("Op")
867                .and_then(Value::as_object)
868                .ok_or_else(|| fail("Op.as_object"))?;
869            let (op_name, _) = op_obj.iter().next().ok_or_else(|| fail("Op.iter().next"))?;
870
871            if op_obj.contains_key("MkOpFlatten") {
872                parse_flatten_op(op_obj, scope)
873            } else if op_obj.contains_key("MkOpTable") {
874                parse_table_op(op_obj, scope)
875            } else if op_obj.contains_key("MkOpIndexing") || op_obj.contains_key("MkOpSlicing") {
876                parse_indexing_slicing_op(op_obj, scope)
877            } else if op_obj.contains_key("MkOpActive") {
878                parse_active_op(op_obj, scope)
879            } else if op_obj.contains_key("MkOpRelationProj") {
880                parse_relation_projection(op_obj, scope)
881            } else if op_obj.contains_key("MkOpToSet") {
882                parse_to_set(op_obj, scope)
883            } else if binary_operator(op_name).is_some() {
884                parse_bin_op(op_obj, scope)
885            } else if unary_operator(op_name, None).is_some() {
886                parse_unary_op(op_obj, scope)
887            } else {
888                Err(fail("Op.unknown"))
889            }
890        }
891        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
892            parse_comprehension(comprehension, scope.clone(), None)
893        }
894        Value::Object(refe) if refe.contains_key("Reference") => {
895            let user_name = parse_reference_name(obj)?;
896
897            let declaration: DeclarationPtr = scope
898                .read()
899                .lookup(&user_name)
900                .ok_or_else(|| fail("Reference.lookup"))?;
901
902            Ok(Expression::Atomic(
903                Metadata::new(),
904                Atom::Reference(crate::ast::Reference::new(declaration)),
905            ))
906        }
907        // In the case where refering to fields. This not behind a reference
908        Value::Object(refe) if refe.contains_key("Name") => {
909            let name = refe
910                .get("Name")
911                .and_then(|x| x.as_str())
912                .ok_or_else(|| fail("Reference[0].Name.as_str"))?;
913            let user_name = Name::User(Ustr::from(name));
914
915            let declaration: DeclarationPtr = scope
916                .read()
917                .lookup(&user_name)
918                .ok_or_else(|| fail("Reference.lookup"))?;
919
920            Ok(Expression::Atomic(
921                Metadata::new(),
922                Atom::Reference(crate::ast::Reference::new(declaration)),
923            ))
924        }
925        Value::Object(abslit) if abslit.contains_key("AbstractLiteral") => {
926            let abstract_literal = abslit["AbstractLiteral"]
927                .as_object()
928                .ok_or_else(|| fail("AbstractLiteral.as_object"))?;
929
930            if abstract_literal.contains_key("AbsLitSet") {
931                parse_abs_lit(&abslit["AbstractLiteral"]["AbsLitSet"], scope)
932            } else if abstract_literal.contains_key("AbsLitFunction") {
933                parse_abs_function(&abslit["AbstractLiteral"]["AbsLitFunction"], scope)
934            } else if abstract_literal.contains_key("AbsLitMSet") {
935                parse_abs_mset(&abslit["AbstractLiteral"]["AbsLitMSet"], scope)
936            } else if abstract_literal.contains_key("AbsLitVariant") {
937                parse_abs_variant(&abslit["AbstractLiteral"]["AbsLitVariant"], scope)
938            } else if abstract_literal.contains_key("AbsLitRelation") {
939                parse_abs_relation(&abslit["AbstractLiteral"]["AbsLitRelation"], scope)
940            } else if abstract_literal.contains_key("AbstractLiteralPartition") {
941                parse_abs_partition(&abslit["AbstractLiteral"]["AbsLitPartition"], scope)
942            } else if abstract_literal.contains_key("AbsLitSequence") {
943                parse_abs_sequence(&abslit["AbstractLiteral"]["AbsLitSequence"], scope)
944            } else {
945                parse_abstract_matrix_as_expr(obj, scope)
946            }
947        }
948
949        Value::Object(constant) if constant.contains_key("Constant") => {
950            parse_constant(constant, scope).or_else(|_| parse_abstract_matrix_as_expr(obj, scope))
951        }
952
953        Value::Object(constant) if constant.contains_key("ConstantAbstract") => {
954            parse_abstract_matrix_as_expr(obj, scope)
955        }
956
957        Value::Object(constant) if constant.contains_key("ConstantInt") => {
958            parse_constant(constant, scope)
959        }
960        Value::Object(constant) if constant.contains_key("ConstantBool") => {
961            parse_constant(constant, scope)
962        }
963
964        _ => Err(fail("no_match")),
965    }
966}
967
968fn parse_abs_lit(abs_set: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
969    let values = abs_set
970        .as_array()
971        .ok_or(error!("AbsLitSet is not an array"))?;
972    let expressions = values
973        .iter()
974        .map(|values| parse_expression(values, scope))
975        .collect::<Result<Vec<_>>>()?;
976
977    Ok(Expression::AbstractLiteral(
978        Metadata::new(),
979        AbstractLiteral::Set(expressions),
980    ))
981}
982
983fn parse_abs_mset(abs_mset: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
984    let values = abs_mset
985        .as_array()
986        .ok_or(error!("AbsLitMSet is not an array"))?;
987    let expressions = values
988        .iter()
989        .map(|values| parse_expression(values, scope))
990        .collect::<Result<Vec<_>>>()?;
991
992    Ok(Expression::AbstractLiteral(
993        Metadata::new(),
994        AbstractLiteral::MSet(expressions),
995    ))
996}
997
998fn parse_abs_partition(abs_partition: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
999    let parts = abs_partition
1000        .as_array()
1001        .ok_or(error!("AbsLitPartition is not an array"))?;
1002
1003    let mut partition: Vec<Vec<_>> = Vec::new();
1004
1005    for part in parts {
1006        let vals = part
1007            .as_array()
1008            .ok_or(error!("Part in AbsLitPartition is not an array"))?;
1009
1010        let exprs = vals
1011            .iter()
1012            .map(|values| parse_expression(values, scope))
1013            .collect::<Result<Vec<_>>>()?;
1014
1015        partition.push(exprs);
1016    }
1017
1018    Ok(Expression::AbstractLiteral(
1019        Metadata::new(),
1020        AbstractLiteral::Partition(partition),
1021    ))
1022}
1023
1024fn parse_abs_sequence(abs_seq: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1025    let values = abs_seq
1026        .as_array()
1027        .ok_or(error!("AbsLitSequence is not an array"))?;
1028    let expressions = values
1029        .iter()
1030        .map(|values| parse_expression(values, scope))
1031        .collect::<Result<Vec<_>>>()?;
1032
1033    Ok(Expression::AbstractLiteral(
1034        Metadata::new(),
1035        AbstractLiteral::Sequence(expressions),
1036    ))
1037}
1038
1039fn parse_abs_tuple(abs_tuple: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1040    let values = abs_tuple
1041        .as_array()
1042        .ok_or(error!("AbsLitTuple is not an array"))?;
1043    let expressions = values
1044        .iter()
1045        .map(|values| parse_expression(values, scope))
1046        .collect::<Result<Vec<_>>>()?;
1047
1048    Ok(Expression::AbstractLiteral(
1049        Metadata::new(),
1050        AbstractLiteral::Tuple(expressions),
1051    ))
1052}
1053
1054//parses an abstract record as an expression
1055fn parse_abs_record(abs_record: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1056    let entries = abs_record
1057        .as_array()
1058        .ok_or(error!("AbsLitRecord is not an array"))?;
1059    let mut rec = vec![];
1060
1061    for entry in entries {
1062        let entry = entry
1063            .as_array()
1064            .ok_or(error!("AbsLitRecord entry is not an array"))?;
1065        let name = entry[0]
1066            .as_object()
1067            .ok_or(error!("AbsLitRecord field name is not an object"))?["Name"]
1068            .as_str()
1069            .ok_or(error!("AbsLitRecord field name is not a string"))?;
1070
1071        let value = parse_expression(&entry[1], scope)?;
1072
1073        let name = Name::User(Ustr::from(name));
1074        let rec_entry = Field {
1075            name: name.clone(),
1076            value,
1077        };
1078        rec.push(rec_entry);
1079    }
1080
1081    Ok(Expression::AbstractLiteral(
1082        Metadata::new(),
1083        AbstractLiteral::Record(rec),
1084    ))
1085}
1086
1087//parses an abstract variant as an expression
1088fn parse_abs_variant(abs_variant: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1089    let entry = abs_variant
1090        .as_array()
1091        .ok_or(error!("AbsLitVariant is not an array"))?;
1092    let name = entry[1]
1093        .as_object()
1094        .ok_or(error!("AbsLitVariant field name is not an object"))?["Name"]
1095        .as_str()
1096        .ok_or(error!("AbsLitVariant field name is not a string"))?;
1097
1098    let value = parse_expression(&entry[2], scope)?;
1099
1100    let name = Name::User(Ustr::from(name));
1101    let rec_entry = Field { name, value };
1102
1103    Ok(Expression::AbstractLiteral(
1104        Metadata::new(),
1105        AbstractLiteral::Variant(Moo::new(rec_entry)),
1106    ))
1107}
1108
1109//parses an abstract function as an expression
1110fn parse_abs_function(abs_function: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1111    let entries = abs_function
1112        .as_array()
1113        .ok_or(error!("AbsLitFunction is not an array"))?;
1114    let mut assignments = vec![];
1115
1116    for entry in entries {
1117        let entry = entry
1118            .as_array()
1119            .ok_or(error!("Explicit function assignment is not an array"))?;
1120        let expression = entry
1121            .iter()
1122            .map(|values| parse_expression(values, scope))
1123            .collect::<Result<Vec<_>>>()?;
1124        let domain_value = expression
1125            .first()
1126            .ok_or(error!("Invalid function domain"))?;
1127        let codomain_value = expression
1128            .get(1)
1129            .ok_or(error!("Invalid function codomain"))?;
1130        let tuple = (domain_value.clone(), codomain_value.clone());
1131        assignments.push(tuple);
1132    }
1133    Ok(Expression::AbstractLiteral(
1134        Metadata::new(),
1135        AbstractLiteral::Function(assignments),
1136    ))
1137}
1138
1139//parses an abstract relation as an expression
1140fn parse_abs_relation(abs_relation: &Value, scope: &SymbolTablePtr) -> Result<Expression> {
1141    let entries = abs_relation
1142        .as_array()
1143        .ok_or(error!("AbsLitRelation is not an array"))?;
1144    let mut assignments = vec![];
1145
1146    for entry in entries {
1147        let entry = entry
1148            .as_array()
1149            .ok_or(error!("Explicit relation assignment is not an array"))?;
1150        let expression = entry
1151            .iter()
1152            .map(|values| parse_expression(values, scope))
1153            .collect::<Result<Vec<_>>>()?;
1154        assignments.push(expression);
1155    }
1156    Ok(Expression::AbstractLiteral(
1157        Metadata::new(),
1158        AbstractLiteral::Relation(assignments),
1159    ))
1160}
1161
1162fn parse_comprehension(
1163    comprehension: &serde_json::Map<String, Value>,
1164    scope: SymbolTablePtr,
1165    comprehension_kind: Option<ACOperatorKind>,
1166) -> Result<Expression> {
1167    let fail = |stage: &str| -> Error {
1168        Error::Parse(format!("Could not parse comprehension at stage `{stage}`"))
1169    };
1170
1171    let value = &comprehension["Comprehension"];
1172    let mut comprehension = ComprehensionBuilder::new(scope.clone());
1173    let generator_symboltable = comprehension.generator_symboltable();
1174    let return_expr_symboltable = comprehension.return_expr_symboltable();
1175
1176    let generators_and_guards_array = value
1177        .pointer("/1")
1178        .and_then(Value::as_array)
1179        .ok_or_else(|| fail("Comprehension.pointer(/1).as_array"))?;
1180    let generators_and_guards = generators_and_guards_array.iter();
1181
1182    for gen_or_guard in generators_and_guards {
1183        let gen_or_guard_obj = gen_or_guard
1184            .as_object()
1185            .ok_or_else(|| fail("generator_or_guard.as_object"))?;
1186        let (name, inner) = gen_or_guard_obj
1187            .iter()
1188            .next()
1189            .ok_or_else(|| fail("generator_or_guard.iter().next"))?;
1190        comprehension = match name.as_str() {
1191            "Generator" => {
1192                // TODO: more things than GenDomainNoRepr and Single names here?
1193                let generator_obj = inner
1194                    .as_object()
1195                    .ok_or_else(|| fail("Generator.inner.as_object"))?;
1196                let (name, gen_inner) = generator_obj
1197                    .iter()
1198                    .next()
1199                    .ok_or_else(|| fail("Generator.inner.iter().next"))?;
1200                match name.as_str() {
1201                    "GenDomainNoRepr" => {
1202                        let name = gen_inner
1203                            .pointer("/0/Single/Name")
1204                            .and_then(Value::as_str)
1205                            .ok_or_else(|| {
1206                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
1207                            })?;
1208                        let domain_obj = gen_inner
1209                            .pointer("/1")
1210                            .and_then(Value::as_object)
1211                            .ok_or_else(|| fail("GenDomainNoRepr.pointer(/1).as_object"))?;
1212                        let (domain_name, domain_value) = domain_obj
1213                            .iter()
1214                            .next()
1215                            .ok_or_else(|| fail("GenDomainNoRepr.domain.iter().next"))?;
1216                        let domain = parse_domain(
1217                            domain_name,
1218                            domain_value,
1219                            &mut generator_symboltable.write(),
1220                        )?;
1221                        comprehension.generator(DeclarationPtr::new_find(name.into(), domain))
1222                    }
1223                    "GenInExpr" => {
1224                        let name = gen_inner
1225                            .pointer("/0/Single/Name")
1226                            .and_then(Value::as_str)
1227                            .ok_or_else(|| {
1228                                fail("GenDomainNoRepr.pointer(/0/Single/Name).as_str")
1229                            })?;
1230                        let generator_expr = gen_inner
1231                            .pointer("/1")
1232                            .ok_or_else(|| fail("GenInExpr.pointer(/1)"))?;
1233                        let expr = parse_expression(generator_expr, &scope)
1234                            .map_err(|_| fail("GenInExpr.parse_expression"))?;
1235                        comprehension.expression_generator(name.into(), expr)
1236                    }
1237                    _ => {
1238                        bug!("unknown generator type inside comprehension {name}");
1239                    }
1240                }
1241            }
1242
1243            "Condition" => {
1244                let expr = parse_expression(inner, &generator_symboltable)
1245                    .map_err(|_| fail("Condition.parse_expression"))?;
1246                comprehension.guard(expr)
1247            }
1248
1249            x => {
1250                bug!("unknown field inside comprehension {x}");
1251            }
1252        }
1253    }
1254
1255    let return_expr_value = value
1256        .pointer("/0")
1257        .ok_or_else(|| fail("Comprehension.pointer(/0)"))?;
1258    let expr = parse_expression(return_expr_value, &return_expr_symboltable)
1259        .map_err(|_| fail("Comprehension.return_expr.parse_expression"))?;
1260
1261    Ok(Expression::Comprehension(
1262        Metadata::new(),
1263        Moo::new(comprehension.with_return_value(expr, comprehension_kind)),
1264    ))
1265}
1266
1267fn parse_bin_op(
1268    bin_op: &serde_json::Map<String, Value>,
1269    scope: &SymbolTablePtr,
1270) -> Result<Expression> {
1271    // we know there is a single key value pair in this object
1272    // extract the value, ignore the key
1273    let (key, value) = bin_op
1274        .into_iter()
1275        .next()
1276        .ok_or(error!("Binary op object is empty"))?;
1277
1278    let constructor = binary_operator(key.as_str())
1279        .ok_or(error!(format!("Unknown binary operator `{}`", key)))?;
1280
1281    match &value {
1282        Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
1283            let arg1 = parse_expression(&bin_op_args[0], scope)?;
1284            let arg2 = parse_expression(&bin_op_args[1], scope)?;
1285            Ok(constructor(Metadata::new(), Moo::new(arg1), Moo::new(arg2)))
1286        }
1287        _ => Err(error!("Binary operator arguments are not a 2-array")),
1288    }
1289}
1290
1291fn parse_table_op(
1292    op: &serde_json::Map<String, Value>,
1293    scope: &SymbolTablePtr,
1294) -> Result<Expression> {
1295    let args = op
1296        .get("MkOpTable")
1297        .ok_or(error!("MkOpTable missing"))?
1298        .as_array()
1299        .ok_or(error!("MkOpTable is not an array"))?;
1300
1301    if args.len() != 2 {
1302        return Err(error!("MkOpTable arguments are not a 2-array"));
1303    }
1304
1305    let tuple_expr = parse_expression(&args[0], scope)?;
1306    let allowed_rows_expr = parse_expression(&args[1], scope)?;
1307
1308    let (tuple_elems, _) = tuple_expr
1309        .clone()
1310        .unwrap_matrix_unchecked()
1311        .ok_or(error!("MkOpTable first argument is not a matrix"))?;
1312    let (allowed_rows, _) = allowed_rows_expr
1313        .clone()
1314        .unwrap_matrix_unchecked()
1315        .ok_or(error!("MkOpTable second argument is not a matrix"))?;
1316
1317    for row_expr in allowed_rows {
1318        let (row_elems, _) = row_expr
1319            .unwrap_matrix_unchecked()
1320            .ok_or(error!("MkOpTable row is not a matrix"))?;
1321
1322        if row_elems.len() != tuple_elems.len() {
1323            return Err(error!("MkOpTable row width does not match tuple width"));
1324        }
1325    }
1326
1327    Ok(Expression::Table(
1328        Metadata::new(),
1329        Moo::new(tuple_expr),
1330        Moo::new(allowed_rows_expr),
1331    ))
1332}
1333
1334/// If LHS is a record/variant and RHS is a field name,
1335/// returns Ok(Some(record_expr, field_name)).
1336/// If LHS is any other type, return Ok(None).
1337fn parse_record_field(
1338    op_args: &[Value],
1339    scope: &SymbolTablePtr,
1340) -> Result<Option<(Expression, Name)>> {
1341    if op_args.len() != 2 {
1342        return Err(error!("Expected 2 arguments to record indexing operation"));
1343    }
1344
1345    let lhs = parse_expression(&op_args[0], scope)?;
1346    match lhs.return_type() {
1347        // If indexing into a record, parse string field name
1348        // and check that such a field exists
1349        ReturnType::Record(ents) | ReturnType::Variant(ents) => {
1350            let field_name = parse_reference_name(&op_args[1])?;
1351            let has_name = ents.iter().any(|x| x.name.eq(&field_name));
1352            if !has_name {
1353                return Err(error!(format!(
1354                    "Unknown field `{field_name}` in record `{lhs}`"
1355                )));
1356            }
1357            Ok(Some((lhs, field_name)))
1358        }
1359        _ => Ok(None),
1360    }
1361}
1362
1363fn parse_active_op(
1364    op: &serde_json::Map<String, Value>,
1365    scope: &SymbolTablePtr,
1366) -> Result<Expression> {
1367    // we know there is a single key value pair in this object
1368    // extract the value, ignore the key
1369    let (_, value) = op
1370        .into_iter()
1371        .next()
1372        .ok_or(error!("MkOpActive op object is empty"))?;
1373
1374    let Value::Array(op_args) = &value else {
1375        return Err(error!("MkOpActive op array is not an array"));
1376    };
1377    let Some((lhs, rhs)) = parse_record_field(op_args, scope)? else {
1378        return Err(error!("MkOpActive op expected record or variant"));
1379    };
1380    Ok(Expression::Active(Metadata::new(), Moo::new(lhs), rhs))
1381}
1382
1383fn parse_indexing_slicing_op(
1384    op: &serde_json::Map<String, Value>,
1385    scope: &SymbolTablePtr,
1386) -> Result<Expression> {
1387    // we know there is a single key value pair in this object
1388    // extract the value, ignore the key
1389    let (key, value) = op
1390        .into_iter()
1391        .next()
1392        .ok_or(error!("Indexing/Slicing op object is empty"))?;
1393
1394    // we know that this is meant to be a mkopindexing, so anything that goes wrong from here is a
1395    // bug!
1396
1397    // Conjure does a[1,2,3] as MkOpIndexing(MkOpIndexing(MkOpIndexing(a,3),2),1).
1398    //
1399    // And  a[1,..,3] as MkOpIndexing(MkOpSlicing(MkOpIndexing(a,3)),1).
1400    //
1401    // However, we want this in a flattened form: Index(a, [1,2,3])
1402    let mut target: Expression;
1403    let mut indices: Vec<Option<Expression>> = vec![];
1404
1405    // true if this has no slicing, false otherwise.
1406    let mut all_known = true;
1407
1408    match key.as_str() {
1409        "MkOpIndexing" => {
1410            match &value {
1411                Value::Array(op_args) if op_args.len() == 2 => {
1412                    target = parse_expression(&op_args[0], scope)?;
1413
1414                    match parse_record_field(op_args, scope)? {
1415                        // For record indexing, generate nested RecordField exprs
1416                        Some((lhs, rhs)) => {
1417                            target = Expression::RecordField(Metadata::new(), Moo::new(lhs), rhs)
1418                        }
1419                        // Append any other indices to the flat list as normal
1420                        _ => indices.push(Some(parse_expression(&op_args[1], scope)?)),
1421                    }
1422                }
1423                _ => return Err(error!("Unknown object inside MkOpIndexing")),
1424            };
1425        }
1426
1427        "MkOpSlicing" => {
1428            all_known = false;
1429            match &value {
1430                Value::Array(op_args) if op_args.len() == 3 => {
1431                    // NB: records can't be sliced into so no need to check!
1432                    target = parse_expression(&op_args[0], scope)?;
1433                    indices.push(None);
1434                }
1435                _ => return Err(error!("Unknown object inside MkOpSlicing")),
1436            };
1437        }
1438
1439        _ => return Err(error!("Unknown indexing/slicing operator")),
1440    }
1441
1442    loop {
1443        match &mut target {
1444            Expression::UnsafeIndex(_, new_target, new_indices) => {
1445                indices.extend(new_indices.iter().cloned().rev().map(Some));
1446                target = Moo::unwrap_or_clone(new_target.clone());
1447            }
1448
1449            Expression::UnsafeSlice(_, new_target, new_indices) => {
1450                all_known = false;
1451                indices.extend(new_indices.iter().cloned().rev());
1452                target = Moo::unwrap_or_clone(new_target.clone());
1453            }
1454
1455            _ => {
1456                // not a slice or an index, we have reached the target.
1457                break;
1458            }
1459        }
1460    }
1461
1462    // If we had a record field and no other indices, the list will be empty
1463    if indices.is_empty() {
1464        return Ok(target);
1465    }
1466
1467    indices.reverse();
1468
1469    if all_known {
1470        Ok(Expression::UnsafeIndex(
1471            Metadata::new(),
1472            Moo::new(target),
1473            indices
1474                .into_iter()
1475                .collect::<Option<Vec<_>>>()
1476                .ok_or(error!("Missing index in fully-known indexing operation"))?,
1477        ))
1478    } else {
1479        Ok(Expression::UnsafeSlice(
1480            Metadata::new(),
1481            Moo::new(target),
1482            indices,
1483        ))
1484    }
1485}
1486
1487// Parses relation projection, to get a Vec<Option<Expression>> for the projections
1488fn parse_relation_projection(
1489    op: &serde_json::Map<String, Value>,
1490    scope: &SymbolTablePtr,
1491) -> Result<Expression> {
1492    let args = op
1493        .get("MkOpRelationProj")
1494        .ok_or(error!("MkOpRelationProj missing"))?
1495        .as_array()
1496        .ok_or(error!("MkOpRelationProj is not an array"))?;
1497    let first = args
1498        .first()
1499        .ok_or(error!("MkOpRelationProj missing first argument"))?;
1500    let second = args
1501        .get(1)
1502        .ok_or(error!("MkOpRelationProj missing second argument"))?
1503        .as_array()
1504        .ok_or(error!("MkOpRelationProj second argument is not an array"))?;
1505    let relation = parse_expression(first, scope).ok();
1506    // We build a vec of option expressions.
1507    // In the case where a relation domain is not being projected it is None, otherwise it is Some with the expression
1508    // We parse the 'null' as an error, which is mapped to None after parse_expression()
1509    let projections = second
1510        .iter()
1511        .map(|expr| parse_expression(expr, scope).ok())
1512        .collect();
1513    if let Some(relation) = relation {
1514        Ok(Expression::RelationProj(
1515            Metadata::new(),
1516            Moo::new(relation),
1517            projections,
1518        ))
1519    } else {
1520        Err(error!("MkOpRelationProj does not contain relation"))
1521    }
1522}
1523
1524// The ToSet operator is not truely a unary operator.
1525// The internal expression is 2nd in the array, with 'false' as the first element
1526// Therefore it needs separate parsing
1527fn parse_to_set(op: &serde_json::Map<String, Value>, scope: &SymbolTablePtr) -> Result<Expression> {
1528    let args = op
1529        .get("MkOpToSet")
1530        .ok_or(error!("MkOpToSet missing"))?
1531        .as_array()
1532        .ok_or(error!("MkOpToSet is not an array"))?;
1533    let second = args
1534        .get(1)
1535        .ok_or(error!("MkOpToSet missing second argument"))?;
1536    let inner = parse_expression(second, scope)?;
1537    Ok(Expression::ToSet(Metadata::new(), Moo::new(inner)))
1538}
1539
1540fn parse_flatten_op(
1541    op: &serde_json::Map<String, Value>,
1542    scope: &SymbolTablePtr,
1543) -> Result<Expression> {
1544    let args = op
1545        .get("MkOpFlatten")
1546        .ok_or(error!("MkOpFlatten missing"))?
1547        .as_array()
1548        .ok_or(error!("MkOpFlatten is not an array"))?;
1549
1550    let first = args
1551        .first()
1552        .ok_or(error!("MkOpFlatten missing first argument"))?;
1553    let second = args
1554        .get(1)
1555        .ok_or(error!("MkOpFlatten missing second argument"))?;
1556    let n = parse_expression(first, scope).ok();
1557    let matrix = parse_expression(second, scope)?;
1558
1559    if let Some(n) = n {
1560        Ok(Expression::Flatten(
1561            Metadata::new(),
1562            Some(Moo::new(n)),
1563            Moo::new(matrix),
1564        ))
1565    } else {
1566        Ok(Expression::Flatten(Metadata::new(), None, Moo::new(matrix)))
1567    }
1568}
1569
1570fn parse_unary_op(
1571    un_op: &serde_json::Map<String, Value>,
1572    scope: &SymbolTablePtr,
1573) -> Result<Expression> {
1574    let fail = |stage: &str| -> Error {
1575        Error::Parse(format!("Could not parse unary op at stage `{stage}`"))
1576    };
1577
1578    let (key, value) = un_op
1579        .iter()
1580        .next()
1581        .ok_or_else(|| fail("un_op.iter().next"))?;
1582
1583    // unops are the main things that contain comprehensions
1584    //
1585    // if the current expr is a quantifier like and/or/sum and it contains a comprehension, let the comprehension know what it is inside.
1586    let arg = match value {
1587        Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
1588            let comprehension_kind = match key.as_str() {
1589                "MkOpOr" => Some(ACOperatorKind::Or),
1590                "MkOpAnd" => Some(ACOperatorKind::And),
1591                "MkOpSum" => Some(ACOperatorKind::Sum),
1592                "MkOpProduct" => Some(ACOperatorKind::Product),
1593                _ => None,
1594            };
1595            parse_comprehension(comprehension, scope.clone(), comprehension_kind)
1596                .map_err(|_| fail("value.Comprehension.parse_comprehension"))
1597        }
1598        _ => parse_expression(value, scope).map_err(|_| fail("value.parse_expression")),
1599    }
1600    .map_err(|_| fail("arg"))?;
1601
1602    let constructor =
1603        unary_operator(key.as_str(), Some(&arg)).ok_or_else(|| fail("unary_operator"))?;
1604
1605    Ok(constructor(Metadata::new(), Moo::new(arg)))
1606}
1607
1608// Takes in { AbstractLiteral: .... }
1609fn parse_abstract_matrix_as_expr(
1610    value: &serde_json::Value,
1611    scope: &SymbolTablePtr,
1612) -> Result<Expression> {
1613    parser_trace!("trying to parse an abstract literal matrix");
1614    let (values, domain_name, domain_value) =
1615        if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix") {
1616            parser_trace!(".. found JSON pointer /AbstractLiteral/AbstractLitMatrix");
1617            let (domain_name, domain_value) = abs_lit_matrix
1618                .pointer("/0")
1619                .and_then(Value::as_object)
1620                .and_then(|x| x.iter().next())
1621                .ok_or(error!("AbsLitMatrix missing domain"))?;
1622            let values = abs_lit_matrix
1623                .pointer("/1")
1624                .ok_or(error!("AbsLitMatrix missing values"))?;
1625
1626            Some((values, domain_name, domain_value))
1627        }
1628        // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
1629        else if let Some(const_abs_lit_matrix) =
1630            value.pointer("/Constant/ConstantAbstract/AbsLitMatrix")
1631        {
1632            parser_trace!(".. found JSON pointer /Constant/ConstantAbstract/AbsLitMatrix");
1633            let (domain_name, domain_value) = const_abs_lit_matrix
1634                .pointer("/0")
1635                .and_then(Value::as_object)
1636                .and_then(|x| x.iter().next())
1637                .ok_or(error!("ConstantAbstract AbsLitMatrix missing domain"))?;
1638            let values = const_abs_lit_matrix
1639                .pointer("/1")
1640                .ok_or(error!("ConstantAbstract AbsLitMatrix missing values"))?;
1641
1642            Some((values, domain_name, domain_value))
1643        } else if let Some(const_abs_lit_matrix) = value.pointer("/ConstantAbstract/AbsLitMatrix") {
1644            parser_trace!(".. found JSON pointer /ConstantAbstract/AbsLitMatrix");
1645            let (domain_name, domain_value) = const_abs_lit_matrix
1646                .pointer("/0")
1647                .and_then(Value::as_object)
1648                .and_then(|x| x.iter().next())
1649                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing domain"))?;
1650            let values = const_abs_lit_matrix
1651                .pointer("/1")
1652                .ok_or(error!("ConstantAbstract/AbsLitMatrix missing values"))?;
1653            Some((values, domain_name, domain_value))
1654        } else {
1655            None
1656        }
1657        .ok_or(error!("Could not parse abstract literal matrix"))?;
1658
1659    parser_trace!(".. found in domain and values in JSON:");
1660    parser_trace!(".. .. index domain name {domain_name}");
1661    parser_trace!(".. .. values {value}");
1662
1663    let args_parsed = values
1664        .as_array()
1665        .ok_or(error!("Matrix values are not an array"))?
1666        .iter()
1667        .map(|x| parse_expression(x, scope))
1668        .collect::<Result<Vec<Expression>>>()?;
1669
1670    if !args_parsed.is_empty() {
1671        parser_trace!(
1672            ".. successfully parsed values as expressions: {}, ... ",
1673            args_parsed[0]
1674        );
1675    } else {
1676        parser_trace!(".. successfully parsed empty values ",);
1677    }
1678
1679    let mut symbols = scope.write();
1680    match parse_domain(domain_name, domain_value, &mut symbols) {
1681        Ok(domain) => {
1682            parser_trace!("... sucessfully parsed domain as {domain}");
1683            Ok(into_matrix_expr![args_parsed;domain])
1684        }
1685        Err(_) => {
1686            parser_trace!("... failed to parse domain, creating a matrix without one.");
1687            Ok(into_matrix_expr![args_parsed])
1688        }
1689    }
1690}
1691
1692fn parse_constant(
1693    constant: &serde_json::Map<String, Value>,
1694    scope: &SymbolTablePtr,
1695) -> Result<Expression> {
1696    match &constant.get("Constant") {
1697        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
1698            let int_32: i32 = match int["ConstantInt"]
1699                .as_array()
1700                .ok_or(error!("ConstantInt is not an array"))?[1]
1701                .as_i64()
1702                .ok_or(error!("ConstantInt does not contain int"))?
1703                .try_into()
1704            {
1705                Ok(x) => x,
1706                Err(_) => return Err(error!("ConstantInt cannot be represented as i32")),
1707            };
1708
1709            Ok(Expression::Atomic(
1710                Metadata::new(),
1711                Atom::Literal(Literal::Int(int_32)),
1712            ))
1713        }
1714
1715        Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
1716            let b: bool = b["ConstantBool"]
1717                .as_bool()
1718                .ok_or(error!("ConstantBool does not contain bool"))?;
1719            Ok(Expression::Atomic(
1720                Metadata::new(),
1721                Atom::Literal(Literal::Bool(b)),
1722            ))
1723        }
1724
1725        Some(Value::Object(int)) if int.contains_key("ConstantAbstract") => {
1726            if let Some(Value::Object(obj)) = int.get("ConstantAbstract") {
1727                if let Some(arr) = obj.get("AbsLitSet") {
1728                    return parse_abs_lit(arr, scope);
1729                } else if let Some(arr) = obj.get("AbsLitMSet") {
1730                    return parse_abs_mset(arr, scope);
1731                } else if let Some(arr) = obj.get("AbsLitMatrix") {
1732                    return parse_abstract_matrix_as_expr(arr, scope);
1733                } else if let Some(arr) = obj.get("AbsLitTuple") {
1734                    return parse_abs_tuple(arr, scope);
1735                } else if let Some(arr) = obj.get("AbsLitRecord") {
1736                    return parse_abs_record(arr, scope);
1737                } else if let Some(arr) = obj.get("AbsLitPartition") {
1738                    return parse_abs_partition(arr, scope);
1739                } else if let Some(arr) = obj.get("AbsLitFunction") {
1740                    return parse_abs_function(arr, scope);
1741                } else if let Some(arr) = obj.get("AbsLitVariant") {
1742                    return parse_abs_variant(arr, scope);
1743                } else if let Some(arr) = obj.get("AbsLitRelation") {
1744                    return parse_abs_relation(arr, scope);
1745                } else if let Some(arr) = obj.get("AbsLitSequence") {
1746                    return parse_abs_sequence(arr, scope);
1747                }
1748            }
1749            Err(error!("Unhandled ConstantAbstract literal type"))
1750        }
1751
1752        // sometimes (e.g. constant matrices) we can have a ConstantInt / Constant bool that is
1753        // not wrapped in Constant
1754        None => {
1755            let int_expr = constant
1756                .get("ConstantInt")
1757                .and_then(|x| x.as_array())
1758                .and_then(|x| x[1].as_i64())
1759                .and_then(|x| x.try_into().ok())
1760                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
1761
1762            if let Some(expr) = int_expr {
1763                return Ok(expr);
1764            }
1765
1766            let bool_expr = constant
1767                .get("ConstantBool")
1768                .and_then(|x| x.as_bool())
1769                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
1770
1771            if let Some(expr) = bool_expr {
1772                return Ok(expr);
1773            }
1774
1775            Err(error!(format!("Unhandled parse_constant {constant:#?}")))
1776        }
1777        otherwise => Err(error!(format!("Unhandled parse_constant {otherwise:#?}"))),
1778    }
1779}
1780
1781#[cfg(test)]
1782mod tests {
1783    use super::*;
1784    use crate::ast::HasDomain;
1785    use serde_json::json;
1786
1787    #[test]
1788    fn parses_record_index() {
1789        let scope = SymbolTablePtr::new();
1790        scope.write().insert(DeclarationPtr::new_find(
1791            Name::user("x"),
1792            Domain::record(vec![Field {
1793                name: Name::user("a"),
1794                value: Domain::bool(),
1795            }]),
1796        ));
1797
1798        let value = json!({
1799            "Op": {
1800                "MkOpIndexing": [
1801                    {
1802                        "Reference": [
1803                            {
1804                                "Name": "x"
1805                            },
1806                            null
1807                        ]
1808                    },
1809                    {
1810                        "Reference": [
1811                            {
1812                                "Name": "a"
1813                            },
1814                            null
1815                        ]
1816                    }
1817                ]
1818            }
1819        });
1820
1821        let expr = parse_expression(&value, &scope).expect("record index should parse");
1822        let Expression::RecordField(_, rec_expr, field_name) = expr else {
1823            panic!("expected record field access");
1824        };
1825        let Expression::Atomic(_, Atom::Reference(re)) = rec_expr.as_ref() else {
1826            panic!("expected LHS to be a record reference");
1827        };
1828        assert_eq!(re.name().clone(), Name::user("x"));
1829        assert!(re.domain_of().as_record().is_some());
1830        assert_eq!(field_name, Name::user("a"));
1831    }
1832}