1
#![allow(clippy::unwrap_used)]
2
#![allow(clippy::expect_used)]
3
use std::collections::HashMap;
4
use std::rc::Rc;
5
use std::sync::{Arc, RwLock};
6

            
7
use serde_json::Value;
8
use serde_json::Value as JsonValue;
9

            
10
use crate::ast::Declaration;
11
use crate::ast::{
12
    AbstractLiteral, Atom, Domain, Expression, Literal, Name, Range, SetAttr, SymbolTable,
13
};
14
use crate::context::Context;
15
use crate::error::{Error, Result};
16
use crate::metadata::Metadata;
17
use crate::{bug, error, into_matrix_expr, throw_error, Model};
18
macro_rules! parser_trace {
19
    ($($arg:tt)+) => {
20
        log::trace!(target:"jsonparser",$($arg)+)
21
    };
22
}
23

            
24
macro_rules! parser_debug {
25
    ($($arg:tt)+) => {
26
        log::debug!(target:"jsonparser",$($arg)+)
27
    };
28
}
29

            
30
1800
pub fn model_from_json(str: &str, context: Arc<RwLock<Context<'static>>>) -> Result<Model> {
31
1800
    let mut m = Model::new(context);
32
1800
    let v: JsonValue = serde_json::from_str(str)?;
33
1800
    let statements = v["mStatements"]
34
1800
        .as_array()
35
1800
        .ok_or(error!("mStatements is not an array"))?;
36

            
37
8334
    for statement in statements {
38
6534
        let entry = statement
39
6534
            .as_object()
40
6534
            .ok_or(error!("mStatements contains a non-object"))?
41
6534
            .iter()
42
6534
            .next()
43
6534
            .ok_or(error!("mStatements contains an empty object"))?;
44

            
45
6534
        match entry.0.as_str() {
46
6534
            "Declaration" => {
47
4734
                let decl = entry
48
4734
                    .1
49
4734
                    .as_object()
50
4734
                    .ok_or(error!("Declaration is not an object".to_owned()))?;
51

            
52
                // One field in the declaration should tell us what kind it is.
53
                //
54
                // Find it, ignoring the other fields.
55
                //
56
                // e.g. FindOrGiven,
57

            
58
4734
                let mut valid_decl: bool = false;
59
4734
                let submodel = m.as_submodel_mut();
60
4734
                for (kind, value) in decl {
61
4734
                    match kind.as_str() {
62
4734
                        "FindOrGiven" => {
63
4518
                            parse_variable(value, &mut submodel.symbols_mut())?;
64
4518
                            valid_decl = true;
65
4518
                            break;
66
                        }
67
216
                        "Letting" => {
68
216
                            parse_letting(value, &mut submodel.symbols_mut())?;
69
216
                            valid_decl = true;
70
216
                            break;
71
                        }
72
                        _ => continue,
73
                    }
74
                }
75

            
76
4734
                if !valid_decl {
77
                    throw_error!("Declaration is not a valid kind")?;
78
4734
                }
79
            }
80
1800
            "SuchThat" => {
81
1800
                let constraints_arr = match entry.1.as_array() {
82
1800
                    Some(x) => x,
83
                    None => bug!("SuchThat is not a vector"),
84
                };
85

            
86
1800
                let constraints: Vec<Expression> = constraints_arr
87
1800
                    .iter()
88
3132
                    .map(|x| parse_expression(x).unwrap())
89
1800
                    .collect();
90
1800
                m.as_submodel_mut().add_constraints(constraints);
91
1800
                // println!("Nb constraints {}", m.constraints.len());
92
1800
            }
93
            otherwise => bug!("Unhandled Statement {:#?}", otherwise),
94
        }
95
    }
96

            
97
1800
    Ok(m)
98
1800
}
99

            
100
4518
fn parse_variable(v: &JsonValue, symtab: &mut SymbolTable) -> Result<()> {
101
4518
    let arr = v.as_array().ok_or(error!("FindOrGiven is not an array"))?;
102
4518
    let name = arr[1]
103
4518
        .as_object()
104
4518
        .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
105
4518
        .as_str()
106
4518
        .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
107

            
108
4518
    let name = Name::UserName(name.to_owned());
109

            
110
4518
    let domain = arr[2]
111
4518
        .as_object()
112
4518
        .ok_or(error!("FindOrGiven[2] is not an object"))?
113
4518
        .iter()
114
4518
        .next()
115
4518
        .ok_or(error!("FindOrGiven[2] is an empty object"))?;
116

            
117
4518
    let domain = parse_domain(domain.0, domain.1)?;
118

            
119
4518
    symtab
120
4518
        .insert(Rc::new(Declaration::new_var(name.clone(), domain)))
121
4518
        .ok_or(Error::Parse(format!(
122
4518
            "Could not add {name} to symbol table as it already exists"
123
4518
        )))
124
4518
}
125

            
126
216
fn parse_letting(v: &JsonValue, symtab: &mut SymbolTable) -> Result<()> {
127
216
    let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
128
216
    let name = arr[0]
129
216
        .as_object()
130
216
        .ok_or(error!("Letting[0] is not an object"))?["Name"]
131
216
        .as_str()
132
216
        .ok_or(error!("Letting[0].Name is not a string"))?;
133
216
    let name = Name::UserName(name.to_owned());
134

            
135
    // value letting
136
216
    if let Some(value) = parse_expression(&arr[1]) {
137
126
        symtab
138
126
            .insert(Rc::new(Declaration::new_value_letting(name.clone(), value)))
139
126
            .ok_or(Error::Parse(format!(
140
126
                "Could not add {name} to symbol table as it already exists"
141
126
            )))
142
    } else {
143
        // domain letting
144
90
        let domain = &arr[1]
145
90
            .as_object()
146
90
            .ok_or(error!("Letting[1] is not an object".to_owned()))?["Domain"]
147
90
            .as_object()
148
90
            .ok_or(error!("Letting[1].Domain is not an object"))?
149
90
            .iter()
150
90
            .next()
151
90
            .ok_or(error!("Letting[1].Domain is an empty object"))?;
152

            
153
90
        let domain = parse_domain(domain.0, domain.1)?;
154

            
155
90
        symtab
156
90
            .insert(Rc::new(Declaration::new_domain_letting(
157
90
                name.clone(),
158
90
                domain,
159
90
            )))
160
90
            .ok_or(Error::Parse(format!(
161
90
                "Could not add {name} to symbol table as it already exists"
162
90
            )))
163
    }
164
216
}
165

            
166
5814
fn parse_domain(domain_name: &str, domain_value: &JsonValue) -> Result<Domain> {
167
5814
    match domain_name {
168
5814
        "DomainInt" => Ok(parse_int_domain(domain_value)?),
169
1098
        "DomainBool" => Ok(Domain::BoolDomain),
170
252
        "DomainReference" => Ok(Domain::DomainReference(Name::UserName(
171
90
            domain_value
172
90
                .as_array()
173
90
                .ok_or(error!("DomainReference is not an array"))?[0]
174
90
                .as_object()
175
90
                .ok_or(error!("DomainReference[0] is not an object"))?["Name"]
176
90
                .as_str()
177
90
                .ok_or(error!("DomainReference[0].Name is not a string"))?
178
90
                .into(),
179
        ))),
180
162
        "DomainSet" => {
181
            let dom = domain_value.get(2).and_then(|v| v.as_object());
182
            let domain_obj = dom.expect("domain object exists");
183
            let domain = domain_obj
184
                .iter()
185
                .next()
186
                .ok_or(Error::Parse("DomainSet is an empty object".to_owned()))?;
187
            let domain = match domain_name {
188
                "DomainInt" => {
189
                    println!("DomainInt: {:#?}", domain.1);
190
                    Ok(parse_int_domain(domain.1)?)
191
                }
192
                "DomainBool" => Ok(Domain::BoolDomain),
193
                _ => Err(Error::Parse(
194
                    "FindOrGiven[2] is an unknown object".to_owned(),
195
                )),
196
            }?;
197
            print!("{:?}", domain);
198
            Ok(Domain::DomainSet(SetAttr::None, Box::new(domain)))
199
        }
200

            
201
162
        "DomainMatrix" => {
202
162
            let domain_value = domain_value
203
162
                .as_array()
204
162
                .ok_or(error!("Domain matrix is not an array"))?;
205

            
206
162
            let indexed_by_domain = domain_value[0].clone();
207
162
            let (index_domain_name, index_domain_value) = indexed_by_domain
208
162
                .as_object()
209
162
                .ok_or(error!("DomainMatrix[0] is not an object"))?
210
162
                .iter()
211
162
                .next()
212
162
                .ok_or(error!(""))?;
213

            
214
162
            let (value_domain_name, value_domain_value) = domain_value[1]
215
162
                .as_object()
216
162
                .ok_or(error!(""))?
217
162
                .iter()
218
162
                .next()
219
162
                .ok_or(error!(""))?;
220

            
221
            // Conjure stores a 2-d matrix as a matrix of a matrix.
222
            //
223
            // Therefore, the index is always a Domain.
224

            
225
162
            let mut index_domains: Vec<Domain> = vec![];
226
162

            
227
162
            index_domains.push(parse_domain(index_domain_name, index_domain_value)?);
228

            
229
            // We want to store 2-d matrices as a matrix with two index domains, not a matrix in a
230
            // matrix.
231
            //
232
            // Walk through the value domain until it is not a DomainMatrix, adding the index to
233
            // our list of indices.
234
162
            let mut value_domain = parse_domain(value_domain_name, value_domain_value)?;
235
234
            while let Domain::DomainMatrix(new_value_domain, mut indices) = value_domain {
236
72
                index_domains.append(&mut indices);
237
72
                value_domain = *new_value_domain.clone()
238
            }
239

            
240
162
            Ok(Domain::DomainMatrix(Box::new(value_domain), index_domains))
241
        }
242

            
243
        _ => Err(Error::Parse(
244
            "FindOrGiven[2] is an unknown object".to_owned(), // consider covered
245
        )),
246
    }
247
5814
}
248

            
249
4716
fn parse_int_domain(v: &JsonValue) -> Result<Domain> {
250
4716
    let mut ranges = Vec::new();
251
4716
    let arr = v
252
4716
        .as_array()
253
4716
        .ok_or(error!("DomainInt is not an array".to_owned()))?[1]
254
4716
        .as_array()
255
4716
        .ok_or(error!("DomainInt[1] is not an array".to_owned()))?;
256
9540
    for range in arr {
257
4824
        let range = range
258
4824
            .as_object()
259
4824
            .ok_or(error!("DomainInt[1] contains a non-object"))?
260
4824
            .iter()
261
4824
            .next()
262
4824
            .ok_or(error!("DomainInt[1] contains an empty object"))?;
263
4824
        match range.0.as_str() {
264
4824
            "RangeBounded" => {
265
4554
                let arr = range
266
4554
                    .1
267
4554
                    .as_array()
268
4554
                    .ok_or(error!("RangeBounded is not an array".to_owned()))?;
269
4554
                let mut nums = Vec::new();
270
9108
                for item in arr.iter() {
271
9108
                    let num = parse_domain_value_int(item)
272
9108
                        .ok_or(error!("Could not parse int domain constant"))?;
273
9108
                    nums.push(num);
274
                }
275
4554
                ranges.push(Range::Bounded(nums[0], nums[1]));
276
            }
277
270
            "RangeSingle" => {
278
270
                let num = parse_domain_value_int(range.1)
279
270
                    .ok_or(error!("Could not parse int domain constant"))?;
280
270
                ranges.push(Range::Single(num));
281
            }
282
            _ => return throw_error!("DomainInt[1] contains an unknown object"),
283
        }
284
    }
285
4716
    Ok(Domain::IntDomain(ranges))
286
4716
}
287

            
288
/// Parses a (possibly) integer value inside the range of a domain
289
///
290
/// 1. (positive number) Constant/ConstantInt/1
291
///
292
/// 2. (negative number) Op/MkOpNegate/Constant/ConstantInt/1
293
///
294
/// Unlike `parse_constant` this handles the negation operator. `parse_constant` expects the
295
/// negation to already have been handled as an expression; however, here we do not expect domain
296
/// values to be part of larger expressions, only negated.
297
///
298
9378
fn parse_domain_value_int(obj: &JsonValue) -> Option<i32> {
299
9378
    parser_trace!("trying to parse domain value: {}", obj);
300

            
301
9846
    fn try_parse_positive_int(obj: &JsonValue) -> Option<i32> {
302
9846
        parser_trace!(".. trying as a positive domain value: {}", obj);
303
        // Positive number: Constant/ConstantInt/1
304

            
305
9846
        let leaf_node = obj
306
9846
            .pointer("/Constant/ConstantInt/1")
307
9846
            .or_else(|| obj.pointer("/ConstantInt/1"))?;
308

            
309
9378
        match leaf_node.as_i64()?.try_into() {
310
9378
            Ok(x) => {
311
9378
                parser_trace!(".. success!");
312
9378
                Some(x)
313
            }
314
            Err(_) => {
315
                println!(
316
                    "Could not convert integer constant to i32: {:#?}",
317
                    leaf_node
318
                );
319
                None
320
            }
321
        }
322
9846
    }
323

            
324
468
    fn try_parse_negative_int(obj: &JsonValue) -> Option<i32> {
325
468
        // Negative number: Op/MkOpNegate/Constant/ConstantInt/1
326
468

            
327
468
        // Unwrap negation operator, giving us a Constant/ConstantInt/1
328
468
        //
329
468
        // This is just a positive constant, so try to parse it as such
330
468

            
331
468
        parser_trace!(".. trying as a negative domain value: {}", obj);
332
468
        let inner_constant_node = obj.pointer("/Op/MkOpNegate")?;
333
468
        let inner_num = try_parse_positive_int(inner_constant_node)?;
334

            
335
468
        parser_trace!(".. success!");
336
468
        Some(-inner_num)
337
468
    }
338

            
339
9378
    try_parse_positive_int(obj).or_else(|| try_parse_negative_int(obj))
340
9378
}
341

            
342
// this needs an explicit type signature to force the closures to have the same type
343
type BinOp = Box<dyn Fn(Metadata, Box<Expression>, Box<Expression>) -> Expression>;
344
type UnaryOp = Box<dyn Fn(Metadata, Box<Expression>) -> Expression>;
345
type VecOp = Box<dyn Fn(Metadata, Vec<Expression>) -> Expression>;
346

            
347
22050
fn parse_expression(obj: &JsonValue) -> Option<Expression> {
348
22050
    let binary_operators: HashMap<&str, BinOp> = [
349
22050
        (
350
22050
            "MkOpEq",
351
22050
            Box::new(Expression::Eq) as Box<dyn Fn(_, _, _) -> _>,
352
22050
        ),
353
22050
        (
354
22050
            "MkOpNeq",
355
22050
            Box::new(Expression::Neq) as Box<dyn Fn(_, _, _) -> _>,
356
22050
        ),
357
22050
        (
358
22050
            "MkOpGeq",
359
22050
            Box::new(Expression::Geq) as Box<dyn Fn(_, _, _) -> _>,
360
22050
        ),
361
22050
        (
362
22050
            "MkOpLeq",
363
22050
            Box::new(Expression::Leq) as Box<dyn Fn(_, _, _) -> _>,
364
22050
        ),
365
22050
        (
366
22050
            "MkOpGt",
367
22050
            Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
368
22050
        ),
369
22050
        (
370
22050
            "MkOpLt",
371
22050
            Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
372
22050
        ),
373
22050
        (
374
22050
            "MkOpGt",
375
22050
            Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
376
22050
        ),
377
22050
        (
378
22050
            "MkOpLt",
379
22050
            Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
380
22050
        ),
381
22050
        (
382
22050
            "MkOpDiv",
383
22050
            Box::new(Expression::UnsafeDiv) as Box<dyn Fn(_, _, _) -> _>,
384
22050
        ),
385
22050
        (
386
22050
            "MkOpMod",
387
22050
            Box::new(Expression::UnsafeMod) as Box<dyn Fn(_, _, _) -> _>,
388
22050
        ),
389
22050
        (
390
22050
            "MkOpMinus",
391
22050
            Box::new(Expression::Minus) as Box<dyn Fn(_, _, _) -> _>,
392
22050
        ),
393
22050
        (
394
22050
            "MkOpImply",
395
22050
            Box::new(Expression::Imply) as Box<dyn Fn(_, _, _) -> _>,
396
22050
        ),
397
22050
        (
398
22050
            "MkOpPow",
399
22050
            Box::new(Expression::UnsafePow) as Box<dyn Fn(_, _, _) -> _>,
400
22050
        ),
401
22050
    ]
402
22050
    .into_iter()
403
22050
    .collect();
404
22050

            
405
22050
    let unary_operators: HashMap<&str, UnaryOp> = [
406
22050
        (
407
22050
            "MkOpNot",
408
22050
            Box::new(Expression::Not) as Box<dyn Fn(_, _) -> _>,
409
22050
        ),
410
22050
        (
411
22050
            "MkOpNegate",
412
22050
            Box::new(Expression::Neg) as Box<dyn Fn(_, _) -> _>,
413
22050
        ),
414
22050
        (
415
22050
            "MkOpTwoBars",
416
22050
            Box::new(Expression::Abs) as Box<dyn Fn(_, _) -> _>,
417
22050
        ),
418
22050
        (
419
22050
            "MkOpAnd",
420
22050
            Box::new(Expression::And) as Box<dyn Fn(_, _) -> _>,
421
22050
        ),
422
22050
        ("MkOpOr", Box::new(Expression::Or) as Box<dyn Fn(_, _) -> _>),
423
22050
        (
424
22050
            "MkOpMin",
425
22050
            Box::new(Expression::Min) as Box<dyn Fn(_, _) -> _>,
426
22050
        ),
427
22050
        (
428
22050
            "MkOpMax",
429
22050
            Box::new(Expression::Max) as Box<dyn Fn(_, _) -> _>,
430
22050
        ),
431
22050
        (
432
22050
            "MkOpAllDiff",
433
22050
            Box::new(Expression::AllDiff) as Box<dyn Fn(_, _) -> _>,
434
22050
        ),
435
22050
    ]
436
22050
    .into_iter()
437
22050
    .collect();
438
22050

            
439
22050
    let vec_operators: HashMap<&str, VecOp> = [
440
22050
        (
441
22050
            "MkOpSum",
442
22050
            Box::new(Expression::Sum) as Box<dyn Fn(_, _) -> _>,
443
22050
        ),
444
22050
        (
445
22050
            "MkOpProduct",
446
22050
            Box::new(Expression::Product) as Box<dyn Fn(_, _) -> _>,
447
22050
        ),
448
22050
    ]
449
22050
    .into_iter()
450
22050
    .collect();
451
22050

            
452
83070
    let mut binary_operator_names = binary_operators.iter().map(|x| x.0);
453
31356
    let mut unary_operator_names = unary_operators.iter().map(|x| x.0);
454
22050
    let mut vec_operator_names = vec_operators.iter().map(|x| x.0);
455

            
456
    #[allow(clippy::unwrap_used)]
457
90
    match obj {
458
22050
        Value::Object(op) if op.contains_key("Op") => match &op["Op"] {
459
83070
            Value::Object(bin_op) if binary_operator_names.any(|key| bin_op.contains_key(*key)) => {
460
4770
                Some(parse_bin_op(bin_op, binary_operators).unwrap())
461
            }
462
31356
            Value::Object(un_op) if unary_operator_names.any(|key| un_op.contains_key(*key)) => {
463
2322
                Some(parse_unary_op(un_op, unary_operators).unwrap())
464
            }
465
4338
            Value::Object(vec_op) if vec_operator_names.any(|key| vec_op.contains_key(*key)) => {
466
1422
                Some(parse_vec_op(vec_op, vec_operators).unwrap())
467
            }
468

            
469
1188
            Value::Object(op)
470
1188
                if op.contains_key("MkOpIndexing") || op.contains_key("MkOpSlicing") =>
471
1188
            {
472
1188
                parse_indexing_slicing_op(op)
473
            }
474
            otherwise => bug!("Unhandled Op {:#?}", otherwise),
475
        },
476
12348
        Value::Object(refe) if refe.contains_key("Reference") => {
477
6282
            let name = refe["Reference"].as_array()?[0].as_object()?["Name"].as_str()?;
478
6282
            Some(Expression::Atomic(
479
6282
                Metadata::new(),
480
6282
                Atom::Reference(Name::UserName(name.to_string())),
481
6282
            ))
482
        }
483
6066
        Value::Object(abslit) if abslit.contains_key("AbstractLiteral") => {
484
666
            Some(parse_abstract_matrix_as_expr(obj).unwrap())
485
        }
486

            
487
5400
        Value::Object(constant) if constant.contains_key("Constant") => Some(
488
4680
            parse_constant(constant)
489
4680
                .or_else(|| parse_abstract_matrix_as_expr(obj))
490
4680
                .unwrap(),
491
4680
        ),
492

            
493
720
        Value::Object(constant) if constant.contains_key("ConstantAbstract") => {
494
108
            Some(parse_abstract_matrix_as_expr(obj).unwrap())
495
        }
496

            
497
612
        Value::Object(constant) if constant.contains_key("ConstantInt") => {
498
522
            Some(parse_constant(constant).unwrap())
499
        }
500
90
        Value::Object(constant) if constant.contains_key("ConstantBool") => {
501
            Some(parse_constant(constant).unwrap())
502
        }
503
90
        _ => None,
504
    }
505
22050
}
506

            
507
4770
fn parse_bin_op(
508
4770
    bin_op: &serde_json::Map<String, Value>,
509
4770
    binary_operators: HashMap<&str, BinOp>,
510
4770
) -> Option<Expression> {
511
    // we know there is a single key value pair in this object
512
    // extract the value, ignore the key
513
4770
    let (key, value) = bin_op.into_iter().next()?;
514

            
515
4770
    let constructor = binary_operators.get(key.as_str())?;
516

            
517
4770
    match &value {
518
4770
        Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
519
4770
            let arg1 = parse_expression(&bin_op_args[0])?;
520
4770
            let arg2 = parse_expression(&bin_op_args[1])?;
521
4770
            Some(constructor(Metadata::new(), Box::new(arg1), Box::new(arg2)))
522
        }
523
        otherwise => bug!("Unhandled parse_bin_op {:#?}", otherwise),
524
    }
525
4770
}
526

            
527
1188
fn parse_indexing_slicing_op(op: &serde_json::Map<String, Value>) -> Option<Expression> {
528
    // we know there is a single key value pair in this object
529
    // extract the value, ignore the key
530
1188
    let (key, value) = op.into_iter().next()?;
531

            
532
    // we know that this is meant to be a mkopindexing, so anything that goes wrong from here is a
533
    // bug!
534

            
535
    // Conjure does a[1,2,3] as MkOpIndexing(MkOpIndexing(MkOpIndexing(a,3),2),1).
536
    //
537
    // And  a[1,..,3] as MkOpIndexing(MkOpSlicing(MkOpIndexing(a,3)),1).
538
    //
539
    // However, we want this in a flattened form: Index(a, [1,2,3])
540
    let mut target: Expression;
541
1188
    let mut indices: Vec<Option<Expression>> = vec![];
542
1188

            
543
1188
    // true if this has no slicing, false otherwise.
544
1188
    let mut all_known = true;
545
1188

            
546
1188
    match key.as_str() {
547
1188
        "MkOpIndexing" => {
548
828
            match &value {
549
828
                Value::Array(op_args) if op_args.len() == 2 => {
550
828
                    target = parse_expression(&op_args[0]).expect("expected an expression");
551
828
                    indices.push(Some(
552
828
                        parse_expression(&op_args[1]).expect("expected an expression"),
553
828
                    ));
554
828
                }
555
                otherwise => bug!("Unknown object inside MkOpIndexing: {:#?}", otherwise),
556
            };
557
        }
558

            
559
360
        "MkOpSlicing" => {
560
360
            all_known = false;
561
360
            match &value {
562
360
                Value::Array(op_args) if op_args.len() == 3 => {
563
360
                    target = parse_expression(&op_args[0]).expect("expected an expression");
564
360
                    indices.push(None);
565
360
                }
566
                otherwise => bug!("Unknown object inside MkOpSlicing: {:#?}", otherwise),
567
            };
568
        }
569

            
570
        _ => {
571
            return None;
572
        }
573
    }
574

            
575
    loop {
576
1728
        match &mut target {
577
396
            Expression::UnsafeIndex(_, new_target, new_indices) => {
578
396
                indices.extend(new_indices.iter().cloned().map(Some));
579
396
                target = *new_target.clone();
580
396
            }
581

            
582
144
            Expression::UnsafeSlice(_, new_target, new_indices) => {
583
144
                all_known = false;
584
144
                indices.append(new_indices);
585
144
                target = *new_target.clone();
586
144
            }
587

            
588
            _ => {
589
                // not a slice or an index, we have reached the target.
590
1188
                break;
591
1188
            }
592
1188
        }
593
1188
    }
594
1188

            
595
1188
    indices.reverse();
596
1188

            
597
1188
    if all_known {
598
684
        Some(Expression::UnsafeIndex(
599
684
            Metadata::new(),
600
684
            Box::new(target),
601
864
            indices.into_iter().map(|x| x.unwrap()).collect(),
602
684
        ))
603
    } else {
604
504
        Some(Expression::UnsafeSlice(
605
504
            Metadata::new(),
606
504
            Box::new(target),
607
504
            indices,
608
504
        ))
609
    }
610
1188
}
611

            
612
2322
fn parse_unary_op(
613
2322
    un_op: &serde_json::Map<String, Value>,
614
2322
    unary_operators: HashMap<&str, UnaryOp>,
615
2322
) -> Option<Expression> {
616
2322
    let (key, value) = un_op.into_iter().next()?;
617
2322
    let constructor = unary_operators.get(key.as_str())?;
618

            
619
2322
    let arg = parse_expression(value)?;
620
2322
    Some(constructor(Metadata::new(), Box::new(arg)))
621
2322
}
622

            
623
1422
fn parse_vec_op(
624
1422
    vec_op: &serde_json::Map<String, Value>,
625
1422
    vec_operators: HashMap<&str, VecOp>,
626
1422
) -> Option<Expression> {
627
1422
    let (key, value) = vec_op.into_iter().next()?;
628
1422
    let constructor = vec_operators.get(key.as_str())?;
629

            
630
    parser_debug!("Trying to parse vec_op: {key} ...");
631

            
632
1422
    let mut args_parsed: Option<Vec<Option<Expression>>> = None;
633
1422
    if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix/1") {
634
1422
        parser_trace!("... containing a matrix of literals");
635
1422
        args_parsed = abs_lit_matrix.as_array().map(|x| {
636
1422
            x.iter()
637
1422
                .map(parse_expression)
638
1422
                .collect::<Vec<Option<Expression>>>()
639
1422
        });
640
1422
    }
641
    // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
642
    else if let Some(const_abs_lit_matrix) =
643
        value.pointer("/Constant/ConstantAbstract/AbsLitMatrix/1")
644
    {
645
        parser_trace!("... containing a matrix of constants");
646
        args_parsed = const_abs_lit_matrix.as_array().map(|x| {
647
            x.iter()
648
                .map(parse_expression)
649
                .collect::<Vec<Option<Expression>>>()
650
        });
651
    }
652

            
653
1422
    let args_parsed = args_parsed?;
654

            
655
1422
    let number_of_args = args_parsed.len();
656
    parser_debug!("... with {number_of_args} args {args_parsed:#?}");
657

            
658
1422
    let valid_args: Vec<Expression> = args_parsed.into_iter().flatten().collect();
659
1422
    if number_of_args != valid_args.len() {
660
        None
661
    } else {
662
        parser_debug!("... success!");
663
1422
        Some(constructor(Metadata::new(), valid_args))
664
    }
665
1422
}
666

            
667
// Takes in { AbstractLiteral: .... }
668
882
fn parse_abstract_matrix_as_expr(value: &serde_json::Value) -> Option<Expression> {
669
882
    parser_trace!("trying to parse an abstract literal matrix");
670
882
    let (values, domain_name, domain_value) =
671
882
        if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix") {
672
666
            parser_trace!(".. found JSON pointer /AbstractLiteral/AbstractLitMatrix");
673
666
            let (domain_name, domain_value) =
674
666
                abs_lit_matrix.pointer("/0")?.as_object()?.iter().next()?;
675
666
            let values = abs_lit_matrix.pointer("/1")?;
676

            
677
666
            Some((values, domain_name, domain_value))
678
        }
679
        // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
680
108
        else if let Some(const_abs_lit_matrix) =
681
216
            value.pointer("/Constant/ConstantAbstract/AbsLitMatrix")
682
        {
683
108
            parser_trace!(".. found JSON pointer /Constant/ConstantAbstract/AbsLitMatrix");
684
108
            let (domain_name, domain_value) = const_abs_lit_matrix
685
108
                .pointer("/0")?
686
108
                .as_object()?
687
108
                .iter()
688
108
                .next()?;
689
108
            let values = const_abs_lit_matrix.pointer("/1")?;
690

            
691
108
            Some((values, domain_name, domain_value))
692
108
        } else if let Some(const_abs_lit_matrix) = value.pointer("/ConstantAbstract/AbsLitMatrix") {
693
108
            parser_trace!(".. found JSON pointer /ConstantAbstract/AbsLitMatrix");
694
108
            let (domain_name, domain_value) = const_abs_lit_matrix
695
108
                .pointer("/0")?
696
108
                .as_object()?
697
108
                .iter()
698
108
                .next()?;
699
108
            let values = const_abs_lit_matrix.pointer("/1")?;
700
108
            Some((values, domain_name, domain_value))
701
        } else {
702
            None
703
        }?;
704

            
705
882
    parser_trace!(".. found in domain and values in JSON:");
706
882
    parser_trace!(".. .. index domain name {domain_name}");
707
882
    parser_trace!(".. .. values {value}");
708

            
709
882
    let args_parsed = values.as_array().map(|x| {
710
882
        x.iter()
711
882
            .map(parse_expression)
712
1908
            .map(|x| x.expect("invalid subexpression"))
713
882
            .collect::<Vec<Expression>>()
714
882
    })?;
715

            
716
882
    if !args_parsed.is_empty() {
717
864
        parser_trace!(
718
            ".. successfully parsed values as expressions: {}, ... ",
719
            args_parsed[0]
720
        );
721
    } else {
722
18
        parser_trace!(".. successfully parsed empty values ",);
723
    }
724
882
    match parse_domain(domain_name, domain_value) {
725
882
        Ok(domain) => {
726
882
            parser_trace!("... sucessfully parsed domain as {domain}");
727
882
            Some(into_matrix_expr![args_parsed;domain])
728
        }
729
        Err(_) => {
730
            parser_trace!("... failed to parse domain, creating a matrix without one.");
731
            Some(into_matrix_expr![args_parsed])
732
        }
733
    }
734
882
}
735

            
736
5202
fn parse_constant(constant: &serde_json::Map<String, Value>) -> Option<Expression> {
737
5202
    match &constant.get("Constant") {
738
4680
        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
739
4266
            let int_32: i32 = match int["ConstantInt"].as_array()?[1].as_i64()?.try_into() {
740
4266
                Ok(x) => x,
741
                Err(_) => {
742
                    println!(
743
                        "Could not convert integer constant to i32: {:#?}",
744
                        int["ConstantInt"]
745
                    );
746
                    return None;
747
                }
748
            };
749

            
750
4266
            Some(Expression::Atomic(
751
4266
                Metadata::new(),
752
4266
                Atom::Literal(Literal::Int(int_32)),
753
4266
            ))
754
        }
755

            
756
414
        Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
757
288
            let b: bool = b["ConstantBool"].as_bool()?;
758
288
            Some(Expression::Atomic(
759
288
                Metadata::new(),
760
288
                Atom::Literal(Literal::Bool(b)),
761
288
            ))
762
        }
763

            
764
126
        Some(Value::Object(int)) if int.contains_key("ConstantAbstract") => {
765
            // TODO: add more types of expressions
766
126
            if let Some(Value::Object(obj)) = int.get("ConstantAbstract") {
767
126
                if let Some(arr) = obj.get("AbsLitSet") {
768
18
                    let mut expressions: Vec<Expression> = Vec::new();
769

            
770
54
                    for expr in arr.as_array()?.iter().filter_map(parse_expression) {
771
54
                        if let Expression::Atomic(_, Atom::Literal(literal)) = expr {
772
54
                            expressions
773
54
                                .push(Expression::Atomic(Metadata::new(), Atom::Literal(literal)))
774
                        }
775
                        //  support other expressions as well
776
                    }
777
18
                    return Some(Expression::AbstractLiteral(
778
18
                        Metadata::new(),
779
18
                        AbstractLiteral::Set(expressions),
780
18
                    ));
781
108
                }
782
            }
783
108
            None
784
        }
785

            
786
        // sometimes (e.g. constant matrices) we can have a ConstantInt / Constant bool that is
787
        // not wrapped in Constant
788
        None => {
789
522
            let int_expr = constant["ConstantInt"]
790
522
                .as_array()
791
522
                .and_then(|x| x[1].as_i64())
792
522
                .and_then(|x| x.try_into().ok())
793
522
                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
794

            
795
522
            if let e @ Some(_) = int_expr {
796
522
                return e;
797
            }
798

            
799
            let bool_expr = constant["ConstantBool"]
800
                .as_bool()
801
                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
802

            
803
            if let e @ Some(_) = bool_expr {
804
                return e;
805
            }
806

            
807
            bug!("Unhandled parse_constant {:#?}", constant);
808
        }
809
        otherwise => bug!("Unhandled parse_constant {:#?}", otherwise),
810
    }
811
5202
}