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