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