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::Value;
10use serde_json::Value as JsonValue;
11
12use crate::ast::comprehension::{ComprehensionBuilder, ComprehensionKind};
13use crate::ast::records::RecordValue;
14use crate::ast::{
15 AbstractLiteral, Atom, DeclarationPtr, Domain, Expression, Literal, Name, Range, RecordEntry,
16 SetAttr, SymbolTable,
17};
18use crate::ast::{DeclarationKind, Moo};
19use crate::context::Context;
20use crate::error::{Error, Result};
21use crate::metadata::Metadata;
22use crate::{Model, bug, error, into_matrix_expr, throw_error};
23
24#[allow(unused_macros)]
25macro_rules! parser_trace {
26 ($($arg:tt)+) => {
27 log::trace!(target:"jsonparser",$($arg)+)
28 };
29}
30
31#[allow(unused_macros)]
32macro_rules! parser_debug {
33 ($($arg:tt)+) => {
34 log::debug!(target:"jsonparser",$($arg)+)
35 };
36}
37
38pub fn model_from_json(str: &str, context: Arc<RwLock<Context<'static>>>) -> Result<Model> {
39 let mut m = Model::new(context);
40 let v: JsonValue = serde_json::from_str(str)?;
41 let statements = v["mStatements"]
42 .as_array()
43 .ok_or(error!("mStatements is not an array"))?;
44
45 for statement in statements {
46 let entry = statement
47 .as_object()
48 .ok_or(error!("mStatements contains a non-object"))?
49 .iter()
50 .next()
51 .ok_or(error!("mStatements contains an empty object"))?;
52
53 match entry.0.as_str() {
54 "Declaration" => {
55 let decl = entry
56 .1
57 .as_object()
58 .ok_or(error!("Declaration is not an object".to_owned()))?;
59
60 let mut valid_decl: bool = false;
67 let scope = m.as_submodel().symbols_ptr_unchecked().clone();
68 let submodel = m.as_submodel_mut();
69 for (kind, value) in decl {
70 match kind.as_str() {
71 "FindOrGiven" => {
72 parse_variable(value, &mut submodel.symbols_mut())?;
73 valid_decl = true;
74 break;
75 }
76 "Letting" => {
77 parse_letting(value, &scope)?;
78 valid_decl = true;
79 break;
80 }
81 _ => continue,
82 }
83 }
84
85 if !valid_decl {
86 throw_error!("Declaration is not a valid kind")?;
87 }
88 }
89 "SuchThat" => {
90 let constraints_arr = match entry.1.as_array() {
91 Some(x) => x,
92 None => bug!("SuchThat is not a vector"),
93 };
94
95 let constraints: Vec<Expression> = constraints_arr
96 .iter()
97 .map(|x| {
98 parse_expression(x, m.as_submodel_mut().symbols_ptr_unchecked()).unwrap()
99 })
100 .collect();
101 m.as_submodel_mut().add_constraints(constraints);
102 }
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 let name = arr[1]
113 .as_object()
114 .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
115 .as_str()
116 .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
117
118 let name = Name::User(Ustr::from(name));
119
120 let domain = arr[2]
121 .as_object()
122 .ok_or(error!("FindOrGiven[2] is not an object"))?
123 .iter()
124 .next()
125 .ok_or(error!("FindOrGiven[2] is an empty object"))?;
126
127 let domain = parse_domain(domain.0, domain.1, symtab)?;
128
129 symtab
130 .insert(DeclarationPtr::new_var(name.clone(), domain))
131 .ok_or(Error::Parse(format!(
132 "Could not add {name} to symbol table as it already exists"
133 )))
134}
135
136fn parse_letting(v: &JsonValue, scope: &Rc<RefCell<SymbolTable>>) -> Result<()> {
137 let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
138 let name = arr[0]
139 .as_object()
140 .ok_or(error!("Letting[0] is not an object"))?["Name"]
141 .as_str()
142 .ok_or(error!("Letting[0].Name is not a string"))?;
143 let name = Name::User(Ustr::from(name));
144 if let Some(value) = parse_expression(&arr[1], scope) {
146 let mut symtab = scope.borrow_mut();
147 symtab
148 .insert(DeclarationPtr::new_value_letting(name.clone(), value))
149 .ok_or(Error::Parse(format!(
150 "Could not add {name} to symbol table as it already exists"
151 )))
152 } else {
153 let domain = &arr[1]
155 .as_object()
156 .ok_or(error!("Letting[1] is not an object".to_owned()))?["Domain"]
157 .as_object()
158 .ok_or(error!("Letting[1].Domain is not an object"))?
159 .iter()
160 .next()
161 .ok_or(error!("Letting[1].Domain is an empty object"))?;
162
163 let mut symtab = scope.borrow_mut();
164 let domain = parse_domain(domain.0, domain.1, &mut symtab)?;
165
166 symtab
167 .insert(DeclarationPtr::new_domain_letting(name.clone(), domain))
168 .ok_or(Error::Parse(format!(
169 "Could not add {name} to symbol table as it already exists"
170 )))
171 }
172}
173
174fn parse_domain(
175 domain_name: &str,
176 domain_value: &JsonValue,
177 symbols: &mut SymbolTable,
178) -> Result<Domain> {
179 match domain_name {
180 "DomainInt" => Ok(parse_int_domain(domain_value, symbols)?),
181 "DomainBool" => Ok(Domain::Bool),
182 "DomainReference" => Ok(Domain::Reference(Name::User(
183 domain_value
184 .as_array()
185 .ok_or(error!("DomainReference is not an array"))?[0]
186 .as_object()
187 .ok_or(error!("DomainReference[0] is not an object"))?["Name"]
188 .as_str()
189 .ok_or(error!("DomainReference[0].Name is not a string"))?
190 .into(),
191 ))),
192 "DomainSet" => {
193 let dom = domain_value.get(2).and_then(|v| v.as_object());
194 let domain_obj = dom.expect("domain object exists");
195 let domain = domain_obj
196 .iter()
197 .next()
198 .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
199 let domain = parse_domain(domain.0.as_str(), domain.1, symbols)?;
200 Ok(Domain::Set(SetAttr::None, Box::new(domain)))
201 }
202
203 "DomainMatrix" => {
204 let domain_value = domain_value
205 .as_array()
206 .ok_or(error!("Domain matrix is not an array"))?;
207
208 let indexed_by_domain = domain_value[0].clone();
209 let (index_domain_name, index_domain_value) = indexed_by_domain
210 .as_object()
211 .ok_or(error!("DomainMatrix[0] is not an object"))?
212 .iter()
213 .next()
214 .ok_or(error!(""))?;
215
216 let (value_domain_name, value_domain_value) = domain_value[1]
217 .as_object()
218 .ok_or(error!(""))?
219 .iter()
220 .next()
221 .ok_or(error!(""))?;
222
223 let mut index_domains: Vec<Domain> = vec![];
228
229 index_domains.push(parse_domain(
230 index_domain_name,
231 index_domain_value,
232 symbols,
233 )?);
234
235 let mut value_domain = parse_domain(value_domain_name, value_domain_value, symbols)?;
241 while let Domain::Matrix(new_value_domain, mut indices) = value_domain {
242 index_domains.append(&mut indices);
243 value_domain = *new_value_domain.clone()
244 }
245
246 Ok(Domain::Matrix(Box::new(value_domain), index_domains))
247 }
248 "DomainTuple" => {
249 let domain_value = domain_value
250 .as_array()
251 .ok_or(error!("Domain tuple is not an array"))?;
252
253 let domain = domain_value
255 .iter()
256 .map(|x| {
257 let domain = x
258 .as_object()
259 .ok_or(error!("DomainTuple[0] is not an object"))?
260 .iter()
261 .next()
262 .ok_or(error!("DomainTuple[0] is an empty object"))?;
263 parse_domain(domain.0, domain.1, symbols)
264 })
265 .collect::<Result<Vec<Domain>>>()?;
266
267 Ok(Domain::Tuple(domain))
268 }
269 "DomainRecord" => {
270 let domain_value = domain_value
271 .as_array()
272 .ok_or(error!("Domain Record is not a json array"))?;
273
274 let mut record_entries = vec![];
275
276 for item in domain_value {
277 let name = item[0]
279 .as_object()
280 .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
281 .as_str()
282 .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
283
284 let name = Name::User(Ustr::from(name));
285 let domain = item[1]
287 .as_object()
288 .ok_or(error!("FindOrGiven[2] is not an object"))?
289 .iter()
290 .next()
291 .ok_or(error!("FindOrGiven[2] is an empty object"))?;
292
293 let domain = parse_domain(domain.0, domain.1, symbols)?;
294
295 let rec = RecordEntry { name, domain };
296
297 record_entries.push(rec);
298 }
299
300 record_entries
302 .iter()
303 .cloned()
304 .map(DeclarationPtr::new_record_field)
305 .for_each(|decl| {
306 symbols
307 .insert(decl)
308 .expect("record field to not already be in the symbol table")
309 });
310
311 Ok(Domain::Record(record_entries))
312 }
313
314 _ => Err(Error::Parse(
315 "FindOrGiven[2] is an unknown object".to_owned(), )),
317 }
318}
319
320fn parse_int_domain(v: &JsonValue, symbols: &SymbolTable) -> Result<Domain> {
321 let mut ranges = Vec::new();
322 let arr = v
323 .as_array()
324 .ok_or(error!("DomainInt is not an array".to_owned()))?[1]
325 .as_array()
326 .ok_or(error!("DomainInt[1] is not an array".to_owned()))?;
327 for range in arr {
328 let range = range
329 .as_object()
330 .ok_or(error!("DomainInt[1] contains a non-object"))?
331 .iter()
332 .next()
333 .ok_or(error!("DomainInt[1] contains an empty object"))?;
334 match range.0.as_str() {
335 "RangeBounded" => {
336 let arr = range
337 .1
338 .as_array()
339 .ok_or(error!("RangeBounded is not an array".to_owned()))?;
340 let mut nums = Vec::new();
341 for item in arr.iter() {
342 let num = parse_domain_value_int(item, symbols)
343 .ok_or(error!("Could not parse int domain constant"))?;
344 nums.push(num);
345 }
346 ranges.push(Range::Bounded(nums[0], nums[1]));
347 }
348 "RangeSingle" => {
349 let num = parse_domain_value_int(range.1, symbols)
350 .ok_or(error!("Could not parse int domain constant"))?;
351 ranges.push(Range::Single(num));
352 }
353 _ => return throw_error!("DomainInt[1] contains an unknown object"),
354 }
355 }
356 Ok(Domain::Int(ranges))
357}
358
359fn parse_domain_value_int(obj: &JsonValue, symbols: &SymbolTable) -> Option<i32> {
370 parser_trace!("trying to parse domain value: {}", obj);
371
372 fn try_parse_positive_int(obj: &JsonValue) -> Option<i32> {
373 parser_trace!(".. trying as a positive domain value: {}", obj);
374 let leaf_node = obj
377 .pointer("/Constant/ConstantInt/1")
378 .or_else(|| obj.pointer("/ConstantInt/1"))?;
379
380 match leaf_node.as_i64()?.try_into() {
381 Ok(x) => {
382 parser_trace!(".. success!");
383 Some(x)
384 }
385 Err(_) => {
386 println!("Could not convert integer constant to i32: {leaf_node:#?}");
387 None
388 }
389 }
390 }
391
392 fn try_parse_negative_int(obj: &JsonValue) -> Option<i32> {
393 parser_trace!(".. trying as a negative domain value: {}", obj);
400 let inner_constant_node = obj.pointer("/Op/MkOpNegate")?;
401 let inner_num = try_parse_positive_int(inner_constant_node)?;
402
403 parser_trace!(".. success!");
404 Some(-inner_num)
405 }
406
407 fn try_parse_reference(obj: &JsonValue, symbols: &SymbolTable) -> Option<i32> {
414 parser_trace!(".. trying as a domain reference: {}", obj);
415 let inner_name = obj.pointer("/Reference/0/Name")?.as_str()?;
416 parser_trace!(
417 ".. found domain reference to {}, trying to resolve it",
418 inner_name
419 );
420 let name = Name::User(Ustr::from(inner_name));
421 let decl = symbols.lookup(&name)?;
422 let DeclarationKind::ValueLetting(d) = &decl.kind() as &DeclarationKind else {
423 parser_trace!(".. name exists but is not a value letting!");
424 return None;
425 };
426
427 let a = d.clone().into_literal()?;
428 let Literal::Int(a) = a else {
429 return None;
430 };
431
432 Some(a)
433 }
434
435 try_parse_positive_int(obj)
436 .or_else(|| try_parse_negative_int(obj))
437 .or_else(|| try_parse_reference(obj, symbols))
438}
439
440type BinOp = Box<dyn Fn(Metadata, Moo<Expression>, Moo<Expression>) -> Expression>;
442type UnaryOp = Box<dyn Fn(Metadata, Moo<Expression>) -> Expression>;
443
444pub fn parse_expression(obj: &JsonValue, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
445 let binary_operators: HashMap<&str, BinOp> = [
446 (
447 "MkOpIn",
448 Box::new(Expression::In) as Box<dyn Fn(_, _, _) -> _>,
449 ),
450 (
451 "MkOpUnion",
452 Box::new(Expression::Union) as Box<dyn Fn(_, _, _) -> _>,
453 ),
454 (
455 "MkOpIntersect",
456 Box::new(Expression::Intersect) as Box<dyn Fn(_, _, _) -> _>,
457 ),
458 (
459 "MkOpSupset",
460 Box::new(Expression::Supset) as Box<dyn Fn(_, _, _) -> _>,
461 ),
462 (
463 "MkOpSupsetEq",
464 Box::new(Expression::SupsetEq) as Box<dyn Fn(_, _, _) -> _>,
465 ),
466 (
467 "MkOpSubset",
468 Box::new(Expression::Subset) as Box<dyn Fn(_, _, _) -> _>,
469 ),
470 (
471 "MkOpSubsetEq",
472 Box::new(Expression::SubsetEq) as Box<dyn Fn(_, _, _) -> _>,
473 ),
474 (
475 "MkOpEq",
476 Box::new(Expression::Eq) as Box<dyn Fn(_, _, _) -> _>,
477 ),
478 (
479 "MkOpNeq",
480 Box::new(Expression::Neq) as Box<dyn Fn(_, _, _) -> _>,
481 ),
482 (
483 "MkOpGeq",
484 Box::new(Expression::Geq) as Box<dyn Fn(_, _, _) -> _>,
485 ),
486 (
487 "MkOpLeq",
488 Box::new(Expression::Leq) as Box<dyn Fn(_, _, _) -> _>,
489 ),
490 (
491 "MkOpGt",
492 Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
493 ),
494 (
495 "MkOpLt",
496 Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
497 ),
498 (
499 "MkOpGt",
500 Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
501 ),
502 (
503 "MkOpLt",
504 Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
505 ),
506 (
507 "MkOpDiv",
508 Box::new(Expression::UnsafeDiv) as Box<dyn Fn(_, _, _) -> _>,
509 ),
510 (
511 "MkOpMod",
512 Box::new(Expression::UnsafeMod) as Box<dyn Fn(_, _, _) -> _>,
513 ),
514 (
515 "MkOpMinus",
516 Box::new(Expression::Minus) as Box<dyn Fn(_, _, _) -> _>,
517 ),
518 (
519 "MkOpImply",
520 Box::new(Expression::Imply) as Box<dyn Fn(_, _, _) -> _>,
521 ),
522 (
523 "MkOpIff",
524 Box::new(Expression::Iff) as Box<dyn Fn(_, _, _) -> _>,
525 ),
526 (
527 "MkOpPow",
528 Box::new(Expression::UnsafePow) as Box<dyn Fn(_, _, _) -> _>,
529 ),
530 ]
531 .into_iter()
532 .collect();
533
534 let unary_operators: HashMap<&str, UnaryOp> = [
535 (
536 "MkOpNot",
537 Box::new(Expression::Not) as Box<dyn Fn(_, _) -> _>,
538 ),
539 (
540 "MkOpNegate",
541 Box::new(Expression::Neg) as Box<dyn Fn(_, _) -> _>,
542 ),
543 (
544 "MkOpTwoBars",
545 Box::new(Expression::Abs) as Box<dyn Fn(_, _) -> _>,
546 ),
547 (
548 "MkOpAnd",
549 Box::new(Expression::And) as Box<dyn Fn(_, _) -> _>,
550 ),
551 (
552 "MkOpSum",
553 Box::new(Expression::Sum) as Box<dyn Fn(_, _) -> _>,
554 ),
555 (
556 "MkOpProduct",
557 Box::new(Expression::Product) as Box<dyn Fn(_, _) -> _>,
558 ),
559 ("MkOpOr", Box::new(Expression::Or) as Box<dyn Fn(_, _) -> _>),
560 (
561 "MkOpMin",
562 Box::new(Expression::Min) as Box<dyn Fn(_, _) -> _>,
563 ),
564 (
565 "MkOpMax",
566 Box::new(Expression::Max) as Box<dyn Fn(_, _) -> _>,
567 ),
568 (
569 "MkOpAllDiff",
570 Box::new(Expression::AllDiff) as Box<dyn Fn(_, _) -> _>,
571 ),
572 (
573 "MkOpToInt",
574 Box::new(Expression::ToInt) as Box<dyn Fn(_, _) -> _>,
575 ),
576 ]
577 .into_iter()
578 .collect();
579
580 let mut binary_operator_names = binary_operators.iter().map(|x| x.0);
581 let mut unary_operator_names = unary_operators.iter().map(|x| x.0);
582 #[allow(clippy::unwrap_used)]
583 match obj {
584 Value::Object(op) if op.contains_key("Op") => match &op["Op"] {
585 Value::Object(bin_op) if binary_operator_names.any(|key| bin_op.contains_key(*key)) => {
586 Some(parse_bin_op(bin_op, binary_operators, scope).unwrap())
587 }
588 Value::Object(un_op) if unary_operator_names.any(|key| un_op.contains_key(*key)) => {
589 Some(parse_unary_op(un_op, unary_operators, scope).unwrap())
590 }
591 Value::Object(op)
592 if op.contains_key("MkOpIndexing") || op.contains_key("MkOpSlicing") =>
593 {
594 parse_indexing_slicing_op(op, scope)
595 }
596 otherwise => bug!("Unhandled Op {:#?}", otherwise),
597 },
598 Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
599 Some(parse_comprehension(comprehension, Rc::clone(scope), None).unwrap())
600 }
601 Value::Object(refe) if refe.contains_key("Reference") => {
602 let name = refe["Reference"].as_array()?[0].as_object()?["Name"].as_str()?;
603 let user_name = Name::User(Ustr::from(name));
604
605 let declaration: DeclarationPtr = scope
606 .borrow()
607 .lookup(&user_name)
608 .or_else(|| bug!("Could not find reference {user_name}"))?;
609
610 Some(Expression::Atomic(
611 Metadata::new(),
612 Atom::Reference(declaration),
613 ))
614 }
615 Value::Object(abslit) if abslit.contains_key("AbstractLiteral") => {
616 if abslit["AbstractLiteral"]
617 .as_object()?
618 .contains_key("AbsLitSet")
619 {
620 Some(parse_abs_lit(&abslit["AbstractLiteral"]["AbsLitSet"], scope).unwrap())
621 } else {
622 Some(parse_abstract_matrix_as_expr(obj, scope).unwrap())
623 }
624 }
625
626 Value::Object(constant) if constant.contains_key("Constant") => Some(
627 parse_constant(constant, scope)
628 .or_else(|| parse_abstract_matrix_as_expr(obj, scope))
629 .unwrap(),
630 ),
631
632 Value::Object(constant) if constant.contains_key("ConstantAbstract") => {
633 Some(parse_abstract_matrix_as_expr(obj, scope).unwrap())
634 }
635
636 Value::Object(constant) if constant.contains_key("ConstantInt") => {
637 Some(parse_constant(constant, scope).unwrap())
638 }
639 Value::Object(constant) if constant.contains_key("ConstantBool") => {
640 Some(parse_constant(constant, scope).unwrap())
641 }
642
643 _ => None,
644 }
645}
646
647fn parse_abs_lit(abs_set: &Value, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
648 let values = abs_set.as_array()?; let expressions = values
650 .iter()
651 .map(|values| parse_expression(values, scope))
652 .map(|values| values.expect("invalid subexpression")) .collect::<Vec<Expression>>(); Some(Expression::AbstractLiteral(
656 Metadata::new(),
657 AbstractLiteral::Set(expressions),
658 ))
659}
660
661fn parse_abs_tuple(abs_tuple: &Value, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
662 let values = abs_tuple.as_array()?; let expressions = values
664 .iter()
665 .map(|values| parse_expression(values, scope))
666 .map(|values| values.expect("invalid subexpression")) .collect::<Vec<Expression>>(); Some(Expression::AbstractLiteral(
670 Metadata::new(),
671 AbstractLiteral::Tuple(expressions),
672 ))
673}
674
675fn parse_abs_record(abs_record: &Value, scope: &Rc<RefCell<SymbolTable>>) -> Option<Expression> {
677 let entries = abs_record.as_array()?; let mut rec = vec![];
679
680 for entry in entries {
681 let entry = entry.as_array()?;
682 let name = entry[0].as_object()?["Name"].as_str()?;
683
684 let value = parse_expression(&entry[1], scope)?;
685
686 let name = Name::User(Ustr::from(name));
687 let rec_entry = RecordValue {
688 name: name.clone(),
689 value,
690 };
691 rec.push(rec_entry);
692 }
693
694 Some(Expression::AbstractLiteral(
695 Metadata::new(),
696 AbstractLiteral::Record(rec),
697 ))
698}
699
700fn parse_comprehension(
701 comprehension: &serde_json::Map<String, Value>,
702 scope: Rc<RefCell<SymbolTable>>,
703 comprehension_kind: Option<ComprehensionKind>,
704) -> Option<Expression> {
705 let value = &comprehension["Comprehension"];
706 let mut comprehension = ComprehensionBuilder::new(Rc::clone(&scope));
707 let generator_symboltable = comprehension.generator_symboltable();
708 let return_expr_symboltable = comprehension.return_expr_symboltable();
709
710 let generators_and_guards = value.pointer("/1")?.as_array()?.iter();
711
712 for value in generators_and_guards {
713 let value = value.as_object()?;
714 let (name, value) = value.iter().next()?;
715 comprehension = match name.as_str() {
716 "Generator" => {
717 let name = value.pointer("/GenDomainNoRepr/0/Single/Name")?.as_str()?;
719 let (domain_name, domain_value) = value
720 .pointer("/GenDomainNoRepr/1")?
721 .as_object()?
722 .iter()
723 .next()?;
724 let domain = parse_domain(
725 domain_name,
726 domain_value,
727 &mut generator_symboltable.borrow_mut(),
728 )
729 .ok()?;
730 comprehension.generator(DeclarationPtr::new_var(
731 Name::User(Ustr::from(name)),
732 domain,
733 ))
734 }
735
736 "Condition" => comprehension.guard(parse_expression(value, &generator_symboltable)?),
737
738 x => {
739 bug!("unknown field inside comprehension {x}");
740 }
741 }
742 }
743
744 let expr = parse_expression(value.pointer("/0")?, &return_expr_symboltable)?;
745
746 Some(Expression::Comprehension(
747 Metadata::new(),
748 Moo::new(comprehension.with_return_value(expr, comprehension_kind)),
749 ))
750}
751
752fn parse_bin_op(
753 bin_op: &serde_json::Map<String, Value>,
754 binary_operators: HashMap<&str, BinOp>,
755 scope: &Rc<RefCell<SymbolTable>>,
756) -> Option<Expression> {
757 let (key, value) = bin_op.into_iter().next()?;
760
761 let constructor = binary_operators.get(key.as_str())?;
762
763 match &value {
764 Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
765 let arg1 = parse_expression(&bin_op_args[0], scope)?;
766 let arg2 = parse_expression(&bin_op_args[1], scope)?;
767 Some(constructor(Metadata::new(), Moo::new(arg1), Moo::new(arg2)))
768 }
769 otherwise => bug!("Unhandled parse_bin_op {:#?}", otherwise),
770 }
771}
772
773fn parse_indexing_slicing_op(
774 op: &serde_json::Map<String, Value>,
775 scope: &Rc<RefCell<SymbolTable>>,
776) -> Option<Expression> {
777 let (key, value) = op.into_iter().next()?;
780
781 let mut target: Expression;
790 let mut indices: Vec<Option<Expression>> = vec![];
791
792 let mut all_known = true;
794
795 match key.as_str() {
796 "MkOpIndexing" => {
797 match &value {
798 Value::Array(op_args) if op_args.len() == 2 => {
799 target = parse_expression(&op_args[0], scope).expect("expected an expression");
800 indices.push(Some(
801 parse_expression(&op_args[1], scope).expect("expected an expression"),
802 ));
803 }
804 otherwise => bug!("Unknown object inside MkOpIndexing: {:#?}", otherwise),
805 };
806 }
807
808 "MkOpSlicing" => {
809 all_known = false;
810 match &value {
811 Value::Array(op_args) if op_args.len() == 3 => {
812 target = parse_expression(&op_args[0], scope).expect("expected an expression");
813 indices.push(None);
814 }
815 otherwise => bug!("Unknown object inside MkOpSlicing: {:#?}", otherwise),
816 };
817 }
818
819 _ => {
820 return None;
821 }
822 }
823
824 loop {
825 match &mut target {
826 Expression::UnsafeIndex(_, new_target, new_indices) => {
827 indices.extend(new_indices.iter().cloned().rev().map(Some));
828 target = Moo::unwrap_or_clone(new_target.clone());
829 }
830
831 Expression::UnsafeSlice(_, new_target, new_indices) => {
832 all_known = false;
833 indices.extend(new_indices.iter().cloned().rev());
834 target = Moo::unwrap_or_clone(new_target.clone());
835 }
836
837 _ => {
838 break;
840 }
841 }
842 }
843
844 indices.reverse();
845
846 if all_known {
847 Some(Expression::UnsafeIndex(
848 Metadata::new(),
849 Moo::new(target),
850 indices.into_iter().map(|x| x.unwrap()).collect(),
851 ))
852 } else {
853 Some(Expression::UnsafeSlice(
854 Metadata::new(),
855 Moo::new(target),
856 indices,
857 ))
858 }
859}
860
861fn parse_unary_op(
862 un_op: &serde_json::Map<String, Value>,
863 unary_operators: HashMap<&str, UnaryOp>,
864 scope: &Rc<RefCell<SymbolTable>>,
865) -> Option<Expression> {
866 let (key, value) = un_op.into_iter().next()?;
867 let constructor = unary_operators.get(key.as_str())?;
868
869 let arg = match value {
873 Value::Object(comprehension) if comprehension.contains_key("Comprehension") => {
874 let comprehension_kind = match key.as_str() {
875 "MkOpOr" => Some(ComprehensionKind::Or),
876 "MkOpAnd" => Some(ComprehensionKind::And),
877 "MkOpSum" => Some(ComprehensionKind::Sum),
878 _ => None,
879 };
880 Some(parse_comprehension(comprehension, Rc::clone(scope), comprehension_kind).unwrap())
881 }
882 _ => parse_expression(value, scope),
883 }?;
884
885 Some(constructor(Metadata::new(), Moo::new(arg)))
886}
887
888fn parse_abstract_matrix_as_expr(
890 value: &serde_json::Value,
891 scope: &Rc<RefCell<SymbolTable>>,
892) -> Option<Expression> {
893 parser_trace!("trying to parse an abstract literal matrix");
894 let (values, domain_name, domain_value) =
895 if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix") {
896 parser_trace!(".. found JSON pointer /AbstractLiteral/AbstractLitMatrix");
897 let (domain_name, domain_value) =
898 abs_lit_matrix.pointer("/0")?.as_object()?.iter().next()?;
899 let values = abs_lit_matrix.pointer("/1")?;
900
901 Some((values, domain_name, domain_value))
902 }
903 else if let Some(const_abs_lit_matrix) =
905 value.pointer("/Constant/ConstantAbstract/AbsLitMatrix")
906 {
907 parser_trace!(".. found JSON pointer /Constant/ConstantAbstract/AbsLitMatrix");
908 let (domain_name, domain_value) = const_abs_lit_matrix
909 .pointer("/0")?
910 .as_object()?
911 .iter()
912 .next()?;
913 let values = const_abs_lit_matrix.pointer("/1")?;
914
915 Some((values, domain_name, domain_value))
916 } else if let Some(const_abs_lit_matrix) = value.pointer("/ConstantAbstract/AbsLitMatrix") {
917 parser_trace!(".. found JSON pointer /ConstantAbstract/AbsLitMatrix");
918 let (domain_name, domain_value) = const_abs_lit_matrix
919 .pointer("/0")?
920 .as_object()?
921 .iter()
922 .next()?;
923 let values = const_abs_lit_matrix.pointer("/1")?;
924 Some((values, domain_name, domain_value))
925 } else {
926 None
927 }?;
928
929 parser_trace!(".. found in domain and values in JSON:");
930 parser_trace!(".. .. index domain name {domain_name}");
931 parser_trace!(".. .. values {value}");
932
933 let args_parsed = values.as_array().map(|x| {
934 x.iter()
935 .map(|x| parse_expression(x, scope))
936 .map(|x| x.expect("invalid subexpression"))
937 .collect::<Vec<Expression>>()
938 })?;
939
940 if !args_parsed.is_empty() {
941 parser_trace!(
942 ".. successfully parsed values as expressions: {}, ... ",
943 args_parsed[0]
944 );
945 } else {
946 parser_trace!(".. successfully parsed empty values ",);
947 }
948
949 let mut symbols = scope.borrow_mut();
950 match parse_domain(domain_name, domain_value, &mut symbols) {
951 Ok(domain) => {
952 parser_trace!("... sucessfully parsed domain as {domain}");
953 Some(into_matrix_expr![args_parsed;domain])
954 }
955 Err(_) => {
956 parser_trace!("... failed to parse domain, creating a matrix without one.");
957 Some(into_matrix_expr![args_parsed])
958 }
959 }
960}
961
962fn parse_constant(
963 constant: &serde_json::Map<String, Value>,
964 scope: &Rc<RefCell<SymbolTable>>,
965) -> Option<Expression> {
966 match &constant.get("Constant") {
967 Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
968 let int_32: i32 = match int["ConstantInt"].as_array()?[1].as_i64()?.try_into() {
969 Ok(x) => x,
970 Err(_) => {
971 println!(
972 "Could not convert integer constant to i32: {:#?}",
973 int["ConstantInt"]
974 );
975 return None;
976 }
977 };
978
979 Some(Expression::Atomic(
980 Metadata::new(),
981 Atom::Literal(Literal::Int(int_32)),
982 ))
983 }
984
985 Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
986 let b: bool = b["ConstantBool"].as_bool()?;
987 Some(Expression::Atomic(
988 Metadata::new(),
989 Atom::Literal(Literal::Bool(b)),
990 ))
991 }
992
993 Some(Value::Object(int)) if int.contains_key("ConstantAbstract") => {
994 if let Some(Value::Object(obj)) = int.get("ConstantAbstract") {
995 if let Some(arr) = obj.get("AbsLitSet") {
996 return parse_abs_lit(arr, scope);
997 } else if let Some(arr) = obj.get("AbsLitMatrix") {
998 return parse_abstract_matrix_as_expr(arr, scope);
999 } else if let Some(arr) = obj.get("AbsLitTuple") {
1000 return parse_abs_tuple(arr, scope);
1001 } else if let Some(arr) = obj.get("AbsLitRecord") {
1002 return parse_abs_record(arr, scope);
1003 }
1004 }
1005 None
1006 }
1007
1008 None => {
1011 let int_expr = constant
1012 .get("ConstantInt")
1013 .and_then(|x| x.as_array())
1014 .and_then(|x| x[1].as_i64())
1015 .and_then(|x| x.try_into().ok())
1016 .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
1017
1018 if let e @ Some(_) = int_expr {
1019 return e;
1020 }
1021
1022 let bool_expr = constant
1023 .get("ConstantBool")
1024 .and_then(|x| x.as_bool())
1025 .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
1026
1027 if let e @ Some(_) = bool_expr {
1028 return e;
1029 }
1030
1031 bug!("Unhandled parse_constant {:#?}", constant);
1032 }
1033 otherwise => bug!("Unhandled parse_constant {:#?}", otherwise),
1034 }
1035}