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