1#![allow(clippy::unwrap_used)]
2#![allow(clippy::expect_used)]
3use std::cell::RefCell;
4use std::collections::HashMap;
5use std::rc::Rc;
6use std::sync::{Arc, RwLock};
7use ustr::Ustr;
8
9use serde_json::Map as JsonMap;
10use serde_json::Value;
11use serde_json::Value as JsonValue;
12
13use crate::ast::ac_operators::ACOperatorKind;
14use crate::ast::comprehension::ComprehensionBuilder;
15use crate::ast::records::RecordValue;
16use crate::ast::{
17 AbstractLiteral, Atom, DeclarationPtr, Domain, Expression, FuncAttr, IntVal, JectivityAttr,
18 Literal, Name, PartialityAttr, Range, RecordEntry, SetAttr, SymbolTable,
19};
20use crate::ast::{DeclarationKind, Moo};
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.as_submodel().symbols_ptr_unchecked().clone();
70 let submodel = m.as_submodel_mut();
71 for (kind, value) in decl {
72 match kind.as_str() {
73 "FindOrGiven" => {
74 parse_variable(value, &mut submodel.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| {
100 parse_expression(x, m.as_submodel_mut().symbols_ptr_unchecked()).unwrap()
101 })
102 .collect();
103 m.as_submodel_mut().add_constraints(constraints);
104 }
106 otherwise => bug!("Unhandled Statement {:#?}", otherwise),
107 }
108 }
109 Ok(m)
110}
111
112fn parse_variable(v: &JsonValue, symtab: &mut SymbolTable) -> Result<()> {
113 let arr = v.as_array().ok_or(error!("FindOrGiven is not an array"))?;
114 let name = arr[1]
115 .as_object()
116 .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
117 .as_str()
118 .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
119
120 let name = Name::User(Ustr::from(name));
121
122 let domain = arr[2]
123 .as_object()
124 .ok_or(error!("FindOrGiven[2] is not an object"))?
125 .iter()
126 .next()
127 .ok_or(error!("FindOrGiven[2] is an empty object"))?;
128
129 let domain = parse_domain(domain.0, domain.1, symtab)?;
130
131 symtab
132 .insert(DeclarationPtr::new_var(name.clone(), domain))
133 .ok_or(Error::Parse(format!(
134 "Could not add {name} to symbol table as it already exists"
135 )))
136}
137
138fn parse_letting(v: &JsonValue, scope: &Rc<RefCell<SymbolTable>>) -> Result<()> {
139 let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
140 let name = arr[0]
141 .as_object()
142 .ok_or(error!("Letting[0] is not an object"))?["Name"]
143 .as_str()
144 .ok_or(error!("Letting[0].Name is not a string"))?;
145 let name = Name::User(Ustr::from(name));
146 if let Some(value) = parse_expression(&arr[1], scope) {
148 let mut symtab = scope.borrow_mut();
149 symtab
150 .insert(DeclarationPtr::new_value_letting(name.clone(), value))
151 .ok_or(Error::Parse(format!(
152 "Could not add {name} to symbol table as it already exists"
153 )))
154 } else {
155 let domain = &arr[1]
157 .as_object()
158 .ok_or(error!("Letting[1] is not an object".to_owned()))?["Domain"]
159 .as_object()
160 .ok_or(error!("Letting[1].Domain is not an object"))?
161 .iter()
162 .next()
163 .ok_or(error!("Letting[1].Domain is an empty object"))?;
164
165 let mut symtab = scope.borrow_mut();
166 let domain = parse_domain(domain.0, domain.1, &mut symtab)?;
167
168 symtab
169 .insert(DeclarationPtr::new_domain_letting(name.clone(), domain))
170 .ok_or(Error::Parse(format!(
171 "Could not add {name} to symbol table as it already exists"
172 )))
173 }
174}
175
176fn parse_domain(
177 domain_name: &str,
178 domain_value: &JsonValue,
179 symbols: &mut SymbolTable,
180) -> Result<DomainPtr> {
181 match domain_name {
182 "DomainInt" => Ok(parse_int_domain(domain_value, symbols)?),
183 "DomainBool" => Ok(Domain::bool()),
184 "DomainReference" => {
185 let name = Name::user(
186 domain_value
187 .as_array()
188 .ok_or(error!("DomainReference is not an array"))?[0]
189 .as_object()
190 .ok_or(error!("DomainReference[0] is not an object"))?["Name"]
191 .as_str()
192 .ok_or(error!("DomainReference[0].Name is not a string"))?,
193 );
194 let ptr = symbols
195 .lookup(&name)
196 .ok_or(error!(format!("Name {name} not found")))?;
197 let dom =
198 Domain::reference(ptr).ok_or(error!("Could not construct reference domain"))?;
199 Ok(dom)
200 }
201 "DomainSet" => {
202 let dom = domain_value.get(2).and_then(|v| v.as_object());
203 let domain_obj = dom.expect("domain object exists");
204 let domain = domain_obj
205 .iter()
206 .next()
207 .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
208 let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
209 let size = domain_value
210 .get(1)
211 .and_then(|v| v.as_object())
212 .ok_or(error!("Set size attributes is not an object"))?;
213 let size = parse_size_attr(size, symbols)?;
214 let attr: SetAttr<IntVal> = SetAttr { size };
215 Ok(Domain::set(attr, domain))
216 }
217
218 "DomainMatrix" => {
219 let domain_value = domain_value
220 .as_array()
221 .ok_or(error!("Domain matrix is not an array"))?;
222
223 let indexed_by_domain = domain_value[0].clone();
224 let (index_domain_name, index_domain_value) = indexed_by_domain
225 .as_object()
226 .ok_or(error!("DomainMatrix[0] is not an object"))?
227 .iter()
228 .next()
229 .ok_or(error!(""))?;
230
231 let (value_domain_name, value_domain_value) = domain_value[1]
232 .as_object()
233 .ok_or(error!(""))?
234 .iter()
235 .next()
236 .ok_or(error!(""))?;
237
238 let mut index_domains: Vec<DomainPtr> = vec![];
243
244 index_domains.push(parse_domain(
245 index_domain_name,
246 index_domain_value,
247 symbols,
248 )?);
249
250 let mut value_domain = parse_domain(value_domain_name, value_domain_value, symbols)?;
256 while let Some((new_value_domain, mut indices)) = value_domain.as_matrix() {
257 index_domains.append(&mut indices);
258 value_domain = new_value_domain.clone()
259 }
260
261 Ok(Domain::matrix(value_domain, index_domains))
262 }
263 "DomainTuple" => {
264 let domain_value = domain_value
265 .as_array()
266 .ok_or(error!("Domain tuple is not an array"))?;
267
268 let domain = domain_value
270 .iter()
271 .map(|x| {
272 let domain = x
273 .as_object()
274 .ok_or(error!("DomainTuple[0] is not an object"))?
275 .iter()
276 .next()
277 .ok_or(error!("DomainTuple[0] is an empty object"))?;
278 parse_domain(domain.0, domain.1, symbols)
279 })
280 .collect::<Result<Vec<DomainPtr>>>()?;
281
282 Ok(Domain::tuple(domain))
283 }
284 "DomainRecord" => {
285 let domain_value = domain_value
286 .as_array()
287 .ok_or(error!("Domain Record is not a json array"))?;
288
289 let mut record_entries = vec![];
290
291 for item in domain_value {
292 let name = item[0]
294 .as_object()
295 .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
296 .as_str()
297 .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
298
299 let name = Name::User(Ustr::from(name));
300 let domain = item[1]
302 .as_object()
303 .ok_or(error!("FindOrGiven[2] is not an object"))?
304 .iter()
305 .next()
306 .ok_or(error!("FindOrGiven[2] is an empty object"))?;
307
308 let domain = parse_domain(domain.0, domain.1, symbols)?;
309
310 let rec = RecordEntry { name, domain };
311
312 record_entries.push(rec);
313 }
314
315 record_entries
317 .iter()
318 .cloned()
319 .map(DeclarationPtr::new_record_field)
320 .for_each(|decl| {
321 symbols
322 .insert(decl)
323 .expect("record field to not already be in the symbol table")
324 });
325
326 Ok(Domain::record(record_entries))
327 }
328 "DomainFunction" => {
329 let domain = domain_value
330 .get(2)
331 .and_then(|v| v.as_object())
332 .ok_or(error!("Function domain is not an object"))?;
333 let domain = domain
334 .iter()
335 .next()
336 .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
337 let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
338
339 let codomain = domain_value
340 .get(3)
341 .and_then(|v| v.as_object())
342 .ok_or(error!("Function codomain is not an object"))?;
343 let codomain = codomain
344 .iter()
345 .next()
346 .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
347 let codomain = parse_domain(codomain.0.as_str(), codomain.1, symbols)?;
348
349 let attributes = domain_value
351 .get(1)
352 .and_then(|v| v.as_array())
353 .ok_or(error!("Function attributes is not a json array"))?;
354 let size = attributes
355 .first()
356 .and_then(|v| v.as_object())
357 .ok_or(error!("Function size attributes is not an object"))?;
358 let size = parse_size_attr(size, symbols)?;
359 let partiality = attributes
360 .get(1)
361 .and_then(|v| v.as_str())
362 .ok_or(error!("Function partiality is not a string"))?;
363 let partiality = match partiality {
364 "PartialityAttr_Partial" => Some(PartialityAttr::Partial),
365 "PartialityAttr_Total" => Some(PartialityAttr::Total),
366 _ => None,
367 };
368 if partiality.is_none() {
369 return Err(Error::Parse("Partiality is an unknown type".to_owned()));
370 }
371 let partiality = partiality.unwrap();
372 let jectivity = attributes
373 .get(2)
374 .and_then(|v| v.as_str())
375 .ok_or(error!("Function jectivity is not a string"))?;
376 let jectivity = match jectivity {
377 "JectivityAttr_Injective" => Some(JectivityAttr::Injective),
378 "JectivityAttr_Surjective" => Some(JectivityAttr::Surjective),
379 "JectivityAttr_Bijective" => Some(JectivityAttr::Bijective),
380 "JectivityAttr_None" => Some(JectivityAttr::None),
381 _ => None,
382 };
383 if jectivity.is_none() {
384 return Err(Error::Parse("Jectivity is an unknown type".to_owned()));
385 }
386 let jectivity = jectivity.unwrap();
387
388 let attr: FuncAttr<IntVal> = FuncAttr {
389 size,
390 partiality,
391 jectivity,
392 };
393
394 Ok(Domain::function(attr, domain, codomain))
395 }
396 _ => Err(Error::Parse(
397 "FindOrGiven[2] is an unknown object".to_owned(), )),
399 }
400}
401
402fn parse_size_attr(
403 attr_map: &JsonMap<String, JsonValue>,
404 symbols: &mut SymbolTable,
405) -> Result<Range<IntVal>> {
406 let attr_obj = attr_map
407 .iter()
408 .next()
409 .ok_or(Error::Parse("SizeAttr is an empty object".to_owned()))?;
410 match attr_obj.0.as_str() {
411 "SizeAttr_None" => Ok(Range::Unbounded),
412 "SizeAttr_MinSize" => {
413 let size_int = parse_domain_value_int(attr_obj.1, symbols)
414 .ok_or(error!("Could not parse int domain constant"))?;
415 Ok(Range::UnboundedR(size_int.into()))
416 }
417 "SizeAttr_MaxSize" => {
418 let size_int = parse_domain_value_int(attr_obj.1, symbols)
419 .ok_or(error!("Could not parse int domain constant"))?;
420 Ok(Range::UnboundedL(size_int.into()))
421 }
422 "SizeAttr_MinMaxSize" => {
423 let min_max = attr_obj
424 .1
425 .as_array()
426 .ok_or(error!("SizeAttr MinMaxSize is not a json array"))?;
427 let min = min_max
428 .first()
429 .ok_or(error!("SizeAttr Min is not present"))?;
430 let min_int = parse_domain_value_int(min, symbols)
431 .ok_or(error!("Could not parse int domain constant"))?;
432 let max = min_max
433 .get(1)
434 .ok_or(error!("SizeAttr Max is not present"))?;
435 let max_int = parse_domain_value_int(max, symbols)
436 .ok_or(error!("Could not parse int domain constant"))?;
437 Ok(Range::Bounded(min_int.into(), max_int.into()))
438 }
439 "SizeAttr_Size" => {
440 let size_int = parse_domain_value_int(attr_obj.1, symbols)
441 .ok_or(error!("Could not parse int domain constant"))?;
442 Ok(Range::Single(size_int.into()))
443 }
444 _ => Err(Error::Parse("SizeAttr is an unknown type".to_owned())),
445 }
446}
447
448fn parse_int_domain(v: &JsonValue, symbols: &SymbolTable) -> Result<DomainPtr> {
449 let mut ranges = Vec::new();
450 let arr = v
451 .as_array()
452 .ok_or(error!("DomainInt is not an array".to_owned()))?[1]
453 .as_array()
454 .ok_or(error!("DomainInt[1] is not an array".to_owned()))?;
455 for range in arr {
456 let range = range
457 .as_object()
458 .ok_or(error!("DomainInt[1] contains a non-object"))?
459 .iter()
460 .next()
461 .ok_or(error!("DomainInt[1] contains an empty object"))?;
462 match range.0.as_str() {
463 "RangeBounded" => {
464 let arr = range
465 .1
466 .as_array()
467 .ok_or(error!("RangeBounded is not an array".to_owned()))?;
468 let mut nums = Vec::new();
469 for item in arr.iter() {
470 let num = parse_domain_value_int(item, symbols)
471 .ok_or(error!("Could not parse int domain constant"))?;
472 nums.push(num);
473 }
474 ranges.push(Range::Bounded(nums[0], nums[1]));
475 }
476 "RangeSingle" => {
477 let num = parse_domain_value_int(range.1, symbols)
478 .ok_or(error!("Could not parse int domain constant"))?;
479 ranges.push(Range::Single(num));
480 }
481 _ => return throw_error!("DomainInt[1] contains an unknown object"),
482 }
483 }
484 Ok(Domain::int(ranges))
485}
486
487fn parse_domain_value_int(obj: &JsonValue, symbols: &SymbolTable) -> Option<i32> {
498 parser_trace!("trying to parse domain value: {}", obj);
499
500 fn try_parse_positive_int(obj: &JsonValue) -> Option<i32> {
501 parser_trace!(".. trying as a positive domain value: {}", obj);
502 let leaf_node = obj
505 .pointer("/Constant/ConstantInt/1")
506 .or_else(|| obj.pointer("/ConstantInt/1"))?;
507
508 match leaf_node.as_i64()?.try_into() {
509 Ok(x) => {
510 parser_trace!(".. success!");
511 Some(x)
512 }
513 Err(_) => {
514 println!("Could not convert integer constant to i32: {leaf_node:#?}");
515 None
516 }
517 }
518 }
519
520 fn try_parse_negative_int(obj: &JsonValue) -> Option<i32> {
521 parser_trace!(".. trying as a negative domain value: {}", obj);
528 let inner_constant_node = obj.pointer("/Op/MkOpNegate")?;
529 let inner_num = try_parse_positive_int(inner_constant_node)?;
530
531 parser_trace!(".. success!");
532 Some(-inner_num)
533 }
534
535 fn try_parse_reference(obj: &JsonValue, symbols: &SymbolTable) -> Option<i32> {
542 parser_trace!(".. trying as a domain reference: {}", obj);
543 let inner_name = obj.pointer("/Reference/0/Name")?.as_str()?;
544 parser_trace!(
545 ".. found domain reference to {}, trying to resolve it",
546 inner_name
547 );
548 let name = Name::User(Ustr::from(inner_name));
549 let decl = symbols.lookup(&name)?;
550 let DeclarationKind::ValueLetting(d) = &decl.kind() as &DeclarationKind else {
551 parser_trace!(".. name exists but is not a value letting!");
552 return None;
553 };
554
555 let a = d.clone().into_literal()?;
556 let Literal::Int(a) = a else {
557 return None;
558 };
559
560 Some(a)
561 }
562
563 try_parse_positive_int(obj)
564 .or_else(|| try_parse_negative_int(obj))
565 .or_else(|| try_parse_reference(obj, symbols))
566}
567
568type BinOp = Box<dyn Fn(Metadata, Moo<Expression>, Moo<Expression>) -> Expression>;
570type UnaryOp = Box<dyn Fn(Metadata, Moo<Expression>) -> Expression>;
571
572pub fn parse_expression(obj: &JsonValue, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
573 let binary_operators: HashMap<&str, BinOp> = [
574 (
575 "MkOpIn",
576 Box::new(Expression::In) as Box<dyn Fn(_, _, _) -> _>,
577 ),
578 (
579 "MkOpUnion",
580 Box::new(Expression::Union) as Box<dyn Fn(_, _, _) -> _>,
581 ),
582 (
583 "MkOpIntersect",
584 Box::new(Expression::Intersect) as Box<dyn Fn(_, _, _) -> _>,
585 ),
586 (
587 "MkOpSupset",
588 Box::new(Expression::Supset) as Box<dyn Fn(_, _, _) -> _>,
589 ),
590 (
591 "MkOpSupsetEq",
592 Box::new(Expression::SupsetEq) as Box<dyn Fn(_, _, _) -> _>,
593 ),
594 (
595 "MkOpSubset",
596 Box::new(Expression::Subset) as Box<dyn Fn(_, _, _) -> _>,
597 ),
598 (
599 "MkOpSubsetEq",
600 Box::new(Expression::SubsetEq) as Box<dyn Fn(_, _, _) -> _>,
601 ),
602 (
603 "MkOpEq",
604 Box::new(Expression::Eq) as Box<dyn Fn(_, _, _) -> _>,
605 ),
606 (
607 "MkOpNeq",
608 Box::new(Expression::Neq) as Box<dyn Fn(_, _, _) -> _>,
609 ),
610 (
611 "MkOpGeq",
612 Box::new(Expression::Geq) as Box<dyn Fn(_, _, _) -> _>,
613 ),
614 (
615 "MkOpLeq",
616 Box::new(Expression::Leq) as Box<dyn Fn(_, _, _) -> _>,
617 ),
618 (
619 "MkOpGt",
620 Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
621 ),
622 (
623 "MkOpLt",
624 Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
625 ),
626 (
627 "MkOpGt",
628 Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
629 ),
630 (
631 "MkOpLt",
632 Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
633 ),
634 (
635 "MkOpLexLt",
636 Box::new(Expression::LexLt) as Box<dyn Fn(_, _, _) -> _>,
637 ),
638 (
639 "MkOpLexGt",
640 Box::new(Expression::LexGt) as Box<dyn Fn(_, _, _) -> _>,
641 ),
642 (
643 "MkOpLexLeq",
644 Box::new(Expression::LexLeq) as Box<dyn Fn(_, _, _) -> _>,
645 ),
646 (
647 "MkOpLexGeq",
648 Box::new(Expression::LexGeq) as Box<dyn Fn(_, _, _) -> _>,
649 ),
650 (
651 "MkOpDiv",
652 Box::new(Expression::UnsafeDiv) as Box<dyn Fn(_, _, _) -> _>,
653 ),
654 (
655 "MkOpMod",
656 Box::new(Expression::UnsafeMod) as Box<dyn Fn(_, _, _) -> _>,
657 ),
658 (
659 "MkOpMinus",
660 Box::new(Expression::Minus) as Box<dyn Fn(_, _, _) -> _>,
661 ),
662 (
663 "MkOpImply",
664 Box::new(Expression::Imply) as Box<dyn Fn(_, _, _) -> _>,
665 ),
666 (
667 "MkOpIff",
668 Box::new(Expression::Iff) as Box<dyn Fn(_, _, _) -> _>,
669 ),
670 (
671 "MkOpPow",
672 Box::new(Expression::UnsafePow) as Box<dyn Fn(_, _, _) -> _>,
673 ),
674 (
675 "MkOpImage",
676 Box::new(Expression::Image) as Box<dyn Fn(_, _, _) -> _>,
677 ),
678 (
679 "MkOpImageSet",
680 Box::new(Expression::ImageSet) as Box<dyn Fn(_, _, _) -> _>,
681 ),
682 (
683 "MkOpPreImage",
684 Box::new(Expression::PreImage) as Box<dyn Fn(_, _, _) -> _>,
685 ),
686 (
687 "MkOpInverse",
688 Box::new(Expression::Inverse) as Box<dyn Fn(_, _, _) -> _>,
689 ),
690 (
691 "MkOpRestrict",
692 Box::new(Expression::Restrict) as Box<dyn Fn(_, _, _) -> _>,
693 ),
694 ]
695 .into_iter()
696 .collect();
697
698 let unary_operators: HashMap<&str, UnaryOp> = [
699 (
700 "MkOpNot",
701 Box::new(Expression::Not) as Box<dyn Fn(_, _) -> _>,
702 ),
703 (
704 "MkOpNegate",
705 Box::new(Expression::Neg) as Box<dyn Fn(_, _) -> _>,
706 ),
707 (
708 "MkOpTwoBars",
709 Box::new(Expression::Abs) as Box<dyn Fn(_, _) -> _>,
710 ),
711 (
712 "MkOpAnd",
713 Box::new(Expression::And) as Box<dyn Fn(_, _) -> _>,
714 ),
715 (
716 "MkOpSum",
717 Box::new(Expression::Sum) as Box<dyn Fn(_, _) -> _>,
718 ),
719 (
720 "MkOpProduct",
721 Box::new(Expression::Product) as Box<dyn Fn(_, _) -> _>,
722 ),
723 ("MkOpOr", Box::new(Expression::Or) as Box<dyn Fn(_, _) -> _>),
724 (
725 "MkOpMin",
726 Box::new(Expression::Min) as Box<dyn Fn(_, _) -> _>,
727 ),
728 (
729 "MkOpMax",
730 Box::new(Expression::Max) as Box<dyn Fn(_, _) -> _>,
731 ),
732 (
733 "MkOpAllDiff",
734 Box::new(Expression::AllDiff) as Box<dyn Fn(_, _) -> _>,
735 ),
736 (
737 "MkOpToInt",
738 Box::new(Expression::ToInt) as Box<dyn Fn(_, _) -> _>,
739 ),
740 (
741 "MkOpDefined",
742 Box::new(Expression::Defined) as Box<dyn Fn(_, _) -> _>,
743 ),
744 (
745 "MkOpRange",
746 Box::new(Expression::Range) as Box<dyn Fn(_, _) -> _>,
747 ),
748 ]
749 .into_iter()
750 .collect();
751
752 let mut binary_operator_names = binary_operators.iter().map(|x| x.0);
753 let mut unary_operator_names = unary_operators.iter().map(|x| x.0);
754 #[allow(clippy::unwrap_used)]
755 match obj {
756 Value::Object(op) if op.contains_key("Op") => match &op["Op"] {
757 Value::Object(bin_op) if binary_operator_names.any(|key| bin_op.contains_key(*key)) => {
758 Some(parse_bin_op(bin_op, binary_operators, scope).unwrap())
759 }
760 Value::Object(un_op) if unary_operator_names.any(|key| un_op.contains_key(*key)) => {
761 Some(parse_unary_op(un_op, unary_operators, scope).unwrap())
762 }
763 Value::Object(op) if op.contains_key("MkOpFlatten") => parse_flatten_op(op, scope),
764 Value::Object(op)
765 if op.contains_key("MkOpIndexing") || op.contains_key("MkOpSlicing") =>
766 {
767 parse_indexing_slicing_op(op, scope)
768 }
769 otherwise => bug!("Unhandled Op {:#?}", otherwise),
770 },
771 Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
772 Some(parse_comprehension(comprehension, Rc::clone(scope), None).unwrap())
773 }
774 Value::Object(refe) if refe.contains_key("Reference") => {
775 let name = refe["Reference"].as_array()?[0].as_object()?["Name"].as_str()?;
776 let user_name = Name::User(Ustr::from(name));
777
778 let declaration: DeclarationPtr = scope
779 .borrow()
780 .lookup(&user_name)
781 .or_else(|| bug!("Could not find reference {user_name}"))?;
782
783 Some(Expression::Atomic(
784 Metadata::new(),
785 Atom::Reference(crate::ast::Reference::new(declaration)),
786 ))
787 }
788 Value::Object(abslit) if abslit.contains_key("AbstractLiteral") => {
789 if abslit["AbstractLiteral"]
790 .as_object()?
791 .contains_key("AbsLitSet")
792 {
793 Some(parse_abs_lit(&abslit["AbstractLiteral"]["AbsLitSet"], scope).unwrap())
794 } else if abslit["AbstractLiteral"]
795 .as_object()?
796 .contains_key("AbsLitFunction")
797 {
798 Some(
799 parse_abs_function(&abslit["AbstractLiteral"]["AbsLitFunction"], scope)
800 .unwrap(),
801 )
802 } else {
803 Some(parse_abstract_matrix_as_expr(obj, scope).unwrap())
804 }
805 }
806
807 Value::Object(constant) if constant.contains_key("Constant") => Some(
808 parse_constant(constant, scope)
809 .or_else(|| parse_abstract_matrix_as_expr(obj, scope))
810 .unwrap(),
811 ),
812
813 Value::Object(constant) if constant.contains_key("ConstantAbstract") => {
814 Some(parse_abstract_matrix_as_expr(obj, scope).unwrap())
815 }
816
817 Value::Object(constant) if constant.contains_key("ConstantInt") => {
818 Some(parse_constant(constant, scope).unwrap())
819 }
820 Value::Object(constant) if constant.contains_key("ConstantBool") => {
821 Some(parse_constant(constant, scope).unwrap())
822 }
823
824 _ => None,
825 }
826}
827
828fn parse_abs_lit(abs_set: &Value, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
829 let values = abs_set.as_array()?; let expressions = values
831 .iter()
832 .map(|values| parse_expression(values, scope))
833 .map(|values| values.expect("invalid subexpression")) .collect::<Vec<Expression>>(); Some(Expression::AbstractLiteral(
837 Metadata::new(),
838 AbstractLiteral::Set(expressions),
839 ))
840}
841
842fn parse_abs_tuple(abs_tuple: &Value, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
843 let values = abs_tuple.as_array()?; let expressions = values
845 .iter()
846 .map(|values| parse_expression(values, scope))
847 .map(|values| values.expect("invalid subexpression")) .collect::<Vec<Expression>>(); Some(Expression::AbstractLiteral(
851 Metadata::new(),
852 AbstractLiteral::Tuple(expressions),
853 ))
854}
855
856fn parse_abs_record(abs_record: &Value, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
858 let entries = abs_record.as_array()?; let mut rec = vec![];
860
861 for entry in entries {
862 let entry = entry.as_array()?;
863 let name = entry[0].as_object()?["Name"].as_str()?;
864
865 let value = parse_expression(&entry[1], scope)?;
866
867 let name = Name::User(Ustr::from(name));
868 let rec_entry = RecordValue {
869 name: name.clone(),
870 value,
871 };
872 rec.push(rec_entry);
873 }
874
875 Some(Expression::AbstractLiteral(
876 Metadata::new(),
877 AbstractLiteral::Record(rec),
878 ))
879}
880
881fn parse_abs_function(
883 abs_function: &Value,
884 scope: &Rc<RefCell<SymbolTable>>,
885) -> Option<Expression> {
886 let entries = abs_function.as_array()?;
887 let mut assignments = vec![];
888
889 for entry in entries {
890 let entry = entry.as_array()?;
892 let expression = entry
893 .iter()
894 .map(|values| parse_expression(values, scope))
895 .map(|values| values.expect("invalid subexpression")) .collect::<Vec<Expression>>(); let domain_value = expression.first().expect("Invalid function domain");
898 let codomain_value = expression.get(1).expect("Invalid function codomain");
899 let tuple = (domain_value.clone(), codomain_value.clone());
900 assignments.push(tuple);
901 }
902 Some(Expression::AbstractLiteral(
903 Metadata::new(),
904 AbstractLiteral::Function(assignments),
905 ))
906}
907
908fn parse_comprehension(
909 comprehension: &serde_json::Map<String, Value>,
910 scope: Rc<RefCell<SymbolTable>>,
911 comprehension_kind: Option<ACOperatorKind>,
912) -> Option<Expression> {
913 let value = &comprehension["Comprehension"];
914 let mut comprehension = ComprehensionBuilder::new(Rc::clone(&scope));
915 let generator_symboltable = comprehension.generator_symboltable();
916 let return_expr_symboltable = comprehension.return_expr_symboltable();
917
918 let generators_and_guards = value.pointer("/1")?.as_array()?.iter();
919
920 for value in generators_and_guards {
921 let value = value.as_object()?;
922 let (name, value) = value.iter().next()?;
923 comprehension = match name.as_str() {
924 "Generator" => {
925 let name = value.pointer("/GenDomainNoRepr/0/Single/Name")?.as_str()?;
927 let (domain_name, domain_value) = value
928 .pointer("/GenDomainNoRepr/1")?
929 .as_object()?
930 .iter()
931 .next()?;
932 let domain = parse_domain(
933 domain_name,
934 domain_value,
935 &mut generator_symboltable.borrow_mut(),
936 )
937 .ok()?;
938 comprehension.generator(DeclarationPtr::new_var(
939 Name::User(Ustr::from(name)),
940 domain,
941 ))
942 }
943
944 "Condition" => comprehension.guard(parse_expression(value, &generator_symboltable)?),
945
946 x => {
947 bug!("unknown field inside comprehension {x}");
948 }
949 }
950 }
951
952 let expr = parse_expression(value.pointer("/0")?, &return_expr_symboltable)?;
953
954 Some(Expression::Comprehension(
955 Metadata::new(),
956 Moo::new(comprehension.with_return_value(expr, comprehension_kind)),
957 ))
958}
959
960fn parse_bin_op(
961 bin_op: &serde_json::Map<String, Value>,
962 binary_operators: HashMap<&str, BinOp>,
963 scope: &Rc<RefCell<SymbolTable>>,
964) -> Option<Expression> {
965 let (key, value) = bin_op.into_iter().next()?;
968
969 let constructor = binary_operators.get(key.as_str())?;
970
971 match &value {
972 Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
973 let arg1 = parse_expression(&bin_op_args[0], scope)?;
974 let arg2 = parse_expression(&bin_op_args[1], scope)?;
975 Some(constructor(Metadata::new(), Moo::new(arg1), Moo::new(arg2)))
976 }
977 otherwise => bug!("Unhandled parse_bin_op {:#?}", otherwise),
978 }
979}
980
981fn parse_indexing_slicing_op(
982 op: &serde_json::Map<String, Value>,
983 scope: &Rc<RefCell<SymbolTable>>,
984) -> Option<Expression> {
985 let (key, value) = op.into_iter().next()?;
988
989 let mut target: Expression;
998 let mut indices: Vec<Option<Expression>> = vec![];
999
1000 let mut all_known = true;
1002
1003 match key.as_str() {
1004 "MkOpIndexing" => {
1005 match &value {
1006 Value::Array(op_args) if op_args.len() == 2 => {
1007 target = parse_expression(&op_args[0], scope).expect("expected an expression");
1008 indices.push(Some(
1009 parse_expression(&op_args[1], scope).expect("expected an expression"),
1010 ));
1011 }
1012 otherwise => bug!("Unknown object inside MkOpIndexing: {:#?}", otherwise),
1013 };
1014 }
1015
1016 "MkOpSlicing" => {
1017 all_known = false;
1018 match &value {
1019 Value::Array(op_args) if op_args.len() == 3 => {
1020 target = parse_expression(&op_args[0], scope).expect("expected an expression");
1021 indices.push(None);
1022 }
1023 otherwise => bug!("Unknown object inside MkOpSlicing: {:#?}", otherwise),
1024 };
1025 }
1026
1027 _ => {
1028 return None;
1029 }
1030 }
1031
1032 loop {
1033 match &mut target {
1034 Expression::UnsafeIndex(_, new_target, new_indices) => {
1035 indices.extend(new_indices.iter().cloned().rev().map(Some));
1036 target = Moo::unwrap_or_clone(new_target.clone());
1037 }
1038
1039 Expression::UnsafeSlice(_, new_target, new_indices) => {
1040 all_known = false;
1041 indices.extend(new_indices.iter().cloned().rev());
1042 target = Moo::unwrap_or_clone(new_target.clone());
1043 }
1044
1045 _ => {
1046 break;
1048 }
1049 }
1050 }
1051
1052 indices.reverse();
1053
1054 if all_known {
1055 Some(Expression::UnsafeIndex(
1056 Metadata::new(),
1057 Moo::new(target),
1058 indices.into_iter().map(|x| x.unwrap()).collect(),
1059 ))
1060 } else {
1061 Some(Expression::UnsafeSlice(
1062 Metadata::new(),
1063 Moo::new(target),
1064 indices,
1065 ))
1066 }
1067}
1068
1069fn parse_flatten_op(
1070 op: &serde_json::Map<String, Value>,
1071 scope: &Rc<RefCell<SymbolTable>>,
1072) -> Option<Expression> {
1073 let args = op.get("MkOpFlatten")?.as_array()?;
1074
1075 let n = parse_expression(&args[0], scope);
1076 let matrix = parse_expression(&args[1], scope)?;
1077
1078 if let Some(n) = n {
1079 Some(Expression::Flatten(
1080 Metadata::new(),
1081 Some(Moo::new(n)),
1082 Moo::new(matrix),
1083 ))
1084 } else {
1085 Some(Expression::Flatten(Metadata::new(), None, Moo::new(matrix)))
1086 }
1087}
1088
1089fn parse_unary_op(
1090 un_op: &serde_json::Map<String, Value>,
1091 unary_operators: HashMap<&str, UnaryOp>,
1092 scope: &Rc<RefCell<SymbolTable>>,
1093) -> Option<Expression> {
1094 let (key, value) = un_op.into_iter().next()?;
1095 let constructor = unary_operators.get(key.as_str())?;
1096
1097 let arg = match value {
1101 Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
1102 let comprehension_kind = match key.as_str() {
1103 "MkOpOr" => Some(ACOperatorKind::Or),
1104 "MkOpAnd" => Some(ACOperatorKind::And),
1105 "MkOpSum" => Some(ACOperatorKind::Sum),
1106 "MkOpProduct" => Some(ACOperatorKind::Product),
1107 _ => None,
1108 };
1109 Some(parse_comprehension(comprehension, Rc::clone(scope), comprehension_kind).unwrap())
1110 }
1111 _ => parse_expression(value, scope),
1112 }?;
1113
1114 Some(constructor(Metadata::new(), Moo::new(arg)))
1115}
1116
1117fn parse_abstract_matrix_as_expr(
1119 value: &serde_json::Value,
1120 scope: &Rc<RefCell<SymbolTable>>,
1121) -> Option<Expression> {
1122 parser_trace!("trying to parse an abstract literal matrix");
1123 let (values, domain_name, domain_value) =
1124 if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix") {
1125 parser_trace!(".. found JSON pointer /AbstractLiteral/AbstractLitMatrix");
1126 let (domain_name, domain_value) =
1127 abs_lit_matrix.pointer("/0")?.as_object()?.iter().next()?;
1128 let values = abs_lit_matrix.pointer("/1")?;
1129
1130 Some((values, domain_name, domain_value))
1131 }
1132 else if let Some(const_abs_lit_matrix) =
1134 value.pointer("/Constant/ConstantAbstract/AbsLitMatrix")
1135 {
1136 parser_trace!(".. found JSON pointer /Constant/ConstantAbstract/AbsLitMatrix");
1137 let (domain_name, domain_value) = const_abs_lit_matrix
1138 .pointer("/0")?
1139 .as_object()?
1140 .iter()
1141 .next()?;
1142 let values = const_abs_lit_matrix.pointer("/1")?;
1143
1144 Some((values, domain_name, domain_value))
1145 } else if let Some(const_abs_lit_matrix) = value.pointer("/ConstantAbstract/AbsLitMatrix") {
1146 parser_trace!(".. found JSON pointer /ConstantAbstract/AbsLitMatrix");
1147 let (domain_name, domain_value) = const_abs_lit_matrix
1148 .pointer("/0")?
1149 .as_object()?
1150 .iter()
1151 .next()?;
1152 let values = const_abs_lit_matrix.pointer("/1")?;
1153 Some((values, domain_name, domain_value))
1154 } else {
1155 None
1156 }?;
1157
1158 parser_trace!(".. found in domain and values in JSON:");
1159 parser_trace!(".. .. index domain name {domain_name}");
1160 parser_trace!(".. .. values {value}");
1161
1162 let args_parsed = values.as_array().map(|x| {
1163 x.iter()
1164 .map(|x| parse_expression(x, scope))
1165 .map(|x| x.expect("invalid subexpression"))
1166 .collect::<Vec<Expression>>()
1167 })?;
1168
1169 if !args_parsed.is_empty() {
1170 parser_trace!(
1171 ".. successfully parsed values as expressions: {}, ... ",
1172 args_parsed[0]
1173 );
1174 } else {
1175 parser_trace!(".. successfully parsed empty values ",);
1176 }
1177
1178 let mut symbols = scope.borrow_mut();
1179 match parse_domain(domain_name, domain_value, &mut symbols) {
1180 Ok(domain) => {
1181 parser_trace!("... sucessfully parsed domain as {domain}");
1182 Some(into_matrix_expr![args_parsed;domain])
1183 }
1184 Err(_) => {
1185 parser_trace!("... failed to parse domain, creating a matrix without one.");
1186 Some(into_matrix_expr![args_parsed])
1187 }
1188 }
1189}
1190
1191fn parse_constant(
1192 constant: &serde_json::Map<String, Value>,
1193 scope: &Rc<RefCell<SymbolTable>>,
1194) -> Option<Expression> {
1195 match &constant.get("Constant") {
1196 Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
1197 let int_32: i32 = match int["ConstantInt"].as_array()?[1].as_i64()?.try_into() {
1198 Ok(x) => x,
1199 Err(_) => {
1200 println!(
1201 "Could not convert integer constant to i32: {:#?}",
1202 int["ConstantInt"]
1203 );
1204 return None;
1205 }
1206 };
1207
1208 Some(Expression::Atomic(
1209 Metadata::new(),
1210 Atom::Literal(Literal::Int(int_32)),
1211 ))
1212 }
1213
1214 Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
1215 let b: bool = b["ConstantBool"].as_bool()?;
1216 Some(Expression::Atomic(
1217 Metadata::new(),
1218 Atom::Literal(Literal::Bool(b)),
1219 ))
1220 }
1221
1222 Some(Value::Object(int)) if int.contains_key("ConstantAbstract") => {
1223 if let Some(Value::Object(obj)) = int.get("ConstantAbstract") {
1224 if let Some(arr) = obj.get("AbsLitSet") {
1225 return parse_abs_lit(arr, scope);
1226 } else if let Some(arr) = obj.get("AbsLitMatrix") {
1227 return parse_abstract_matrix_as_expr(arr, scope);
1228 } else if let Some(arr) = obj.get("AbsLitTuple") {
1229 return parse_abs_tuple(arr, scope);
1230 } else if let Some(arr) = obj.get("AbsLitRecord") {
1231 return parse_abs_record(arr, scope);
1232 } else if let Some(arr) = obj.get("AbsLitFunction") {
1233 return parse_abs_function(arr, scope);
1234 }
1235 }
1236 None
1237 }
1238
1239 None => {
1242 let int_expr = constant
1243 .get("ConstantInt")
1244 .and_then(|x| x.as_array())
1245 .and_then(|x| x[1].as_i64())
1246 .and_then(|x| x.try_into().ok())
1247 .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
1248
1249 if let e @ Some(_) = int_expr {
1250 return e;
1251 }
1252
1253 let bool_expr = constant
1254 .get("ConstantBool")
1255 .and_then(|x| x.as_bool())
1256 .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
1257
1258 if let e @ Some(_) = bool_expr {
1259 return e;
1260 }
1261
1262 bug!("Unhandled parse_constant {:#?}", constant);
1263 }
1264 otherwise => bug!("Unhandled parse_constant {:#?}", otherwise),
1265 }
1266}