1
use std::collections::HashMap;
2
use std::rc::Rc;
3
use std::sync::{Arc, RwLock};
4

            
5
use serde_json::Value;
6
use serde_json::Value as JsonValue;
7

            
8
use crate::ast::declaration::Declaration;
9
use crate::ast::{Atom, Domain, Expression, Literal, Name, Range, SymbolTable};
10
use crate::context::Context;
11
use crate::error::{Error, Result};
12
use crate::metadata::Metadata;
13
use crate::Model;
14
use crate::{bug, error, throw_error};
15

            
16
macro_rules! parser_trace {
17
    ($($arg:tt)+) => {
18
        log::trace!(target:"jsonparser",$($arg)+)
19
    };
20
}
21

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

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

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

            
43
6052
        match entry.0.as_str() {
44
6052
            "Declaration" => {
45
4471
                let decl = entry
46
4471
                    .1
47
4471
                    .as_object()
48
4471
                    .ok_or(error!("Declaration is not an object".to_owned()))?;
49

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

            
56
4471
                let mut valid_decl: bool = false;
57
4471
                for (kind, value) in decl {
58
4471
                    match kind.as_str() {
59
4471
                        "FindOrGiven" => {
60
4369
                            parse_variable(value, &mut m.symbols_mut())?;
61
4369
                            valid_decl = true;
62
4369
                            break;
63
                        }
64
102
                        "Letting" => {
65
102
                            parse_letting(value, &mut m.symbols_mut())?;
66
102
                            valid_decl = true;
67
102
                            break;
68
                        }
69
                        _ => continue,
70
                    }
71
                }
72

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

            
83
1581
                let constraints: Vec<Expression> =
84
1581
                    constraints_arr.iter().flat_map(parse_expression).collect();
85
1581
                m.add_constraints(constraints);
86
                // println!("Nb constraints {}", m.constraints.len());
87
            }
88
            otherwise => bug!("Unhandled Statement {:#?}", otherwise),
89
        }
90
    }
91

            
92
1564
    Ok(m)
93
1564
}
94

            
95
4369
fn parse_variable(v: &JsonValue, symtab: &mut SymbolTable) -> Result<()> {
96
4369
    let arr = v.as_array().ok_or(error!("FindOrGiven is not an array"))?;
97
4369
    let name = arr[1]
98
4369
        .as_object()
99
4369
        .ok_or(error!("FindOrGiven[1] is not an object"))?["Name"]
100
4369
        .as_str()
101
4369
        .ok_or(error!("FindOrGiven[1].Name is not a string"))?;
102

            
103
4369
    let name = Name::UserName(name.to_owned());
104
4369
    let domain = arr[2]
105
4369
        .as_object()
106
4369
        .ok_or(error!("FindOrGiven[2] is not an object"))?
107
4369
        .iter()
108
4369
        .next()
109
4369
        .ok_or(error!("FindOrGiven[2] is an empty object"))?;
110
4369
    let domain = match domain.0.as_str() {
111
4369
        "DomainInt" => Ok(parse_int_domain(domain.1)?),
112
935
        "DomainBool" => Ok(Domain::BoolDomain),
113
34
        "DomainReference" => Ok(Domain::DomainReference(Name::UserName(
114
34
            domain
115
34
                .1
116
34
                .as_array()
117
34
                .ok_or(error!("DomainReference is not an array"))?[0]
118
34
                .as_object()
119
34
                .ok_or(error!("DomainReference[0] is not an object"))?["Name"]
120
34
                .as_str()
121
34
                .ok_or(error!("DomainReference[0].Name is not a string"))?
122
34
                .into(),
123
        ))),
124
        _ => throw_error!(
125
            "FindOrGiven[2] is an unknown object" // consider covered
126
        ),
127
    }?;
128

            
129
4369
    symtab
130
4369
        .insert(Rc::new(Declaration::new_var(name.clone(), domain)))
131
4369
        .ok_or(Error::Parse(format!(
132
4369
            "Could not add {name} to symbol table as it already exists"
133
4369
        )))
134
4369
}
135

            
136
102
fn parse_letting(v: &JsonValue, symtab: &mut SymbolTable) -> Result<()> {
137
102
    let arr = v.as_array().ok_or(error!("Letting is not an array"))?;
138
102
    let name = arr[0]
139
102
        .as_object()
140
102
        .ok_or(error!("Letting[0] is not an object"))?["Name"]
141
102
        .as_str()
142
102
        .ok_or(error!("Letting[0].Name is not a string"))?;
143
102
    let name = Name::UserName(name.to_owned());
144

            
145
    // value letting
146
102
    if let Some(value) = parse_expression(&arr[1]) {
147
68
        symtab
148
68
            .insert(Rc::new(Declaration::new_value_letting(name.clone(), value)))
149
68
            .ok_or(Error::Parse(format!(
150
68
                "Could not add {name} to symbol table as it already exists"
151
68
            )))
152
    } else {
153
        // domain letting
154
34
        let domain = &arr[1]
155
34
            .as_object()
156
34
            .ok_or(error!("Letting[1] is not an object".to_owned()))?["Domain"]
157
34
            .as_object()
158
34
            .ok_or(error!("Letting[1].Domain is not an object"))?
159
34
            .iter()
160
34
            .next()
161
34
            .ok_or(error!("Letting[1].Domain is an empty object"))?;
162

            
163
34
        let domain = match domain.0.as_str() {
164
34
            "DomainInt" => Ok(parse_int_domain(domain.1)?),
165
17
            "DomainBool" => Ok(Domain::BoolDomain),
166
            _ => throw_error!("Letting[1] is an unknown object".to_owned()),
167
        }?;
168

            
169
34
        symtab
170
34
            .insert(Rc::new(Declaration::new_domain_letting(
171
34
                name.clone(),
172
34
                domain,
173
34
            )))
174
34
            .ok_or(Error::Parse(format!(
175
34
                "Could not add {name} to symbol table as it already exists"
176
34
            )))
177
    }
178
102
}
179

            
180
3451
fn parse_int_domain(v: &JsonValue) -> Result<Domain> {
181
3451
    let mut ranges = Vec::new();
182
3451
    let arr = v
183
3451
        .as_array()
184
3451
        .ok_or(error!("DomainInt is not an array".to_owned()))?[1]
185
3451
        .as_array()
186
3451
        .ok_or(error!("DomainInt[1] is not an array".to_owned()))?;
187
6902
    for range in arr {
188
3451
        let range = range
189
3451
            .as_object()
190
3451
            .ok_or(error!("DomainInt[1] contains a non-object"))?
191
3451
            .iter()
192
3451
            .next()
193
3451
            .ok_or(error!("DomainInt[1] contains an empty object"))?;
194
3451
        match range.0.as_str() {
195
3451
            "RangeBounded" => {
196
3349
                let arr = range
197
3349
                    .1
198
3349
                    .as_array()
199
3349
                    .ok_or(error!("RangeBounded is not an array".to_owned()))?;
200
3349
                let mut nums = Vec::new();
201
6698
                for item in arr.iter() {
202
6698
                    let num = parse_domain_value_int(item)
203
6698
                        .ok_or(error!("Could not parse int domain constant"))?;
204
6698
                    nums.push(num);
205
                }
206
3349
                ranges.push(Range::Bounded(nums[0], nums[1]));
207
            }
208
102
            "RangeSingle" => {
209
102
                let num = parse_domain_value_int(range.1)
210
102
                    .ok_or(error!("Could not parse int domain constant"))?;
211
102
                ranges.push(Range::Single(num));
212
            }
213
            _ => return throw_error!("DomainInt[1] contains an unknown object"),
214
        }
215
    }
216
3451
    Ok(Domain::IntDomain(ranges))
217
3451
}
218

            
219
/// Parses a (possibly) integer value inside the range of a domain
220
///
221
/// 1. (positive number) Constant/ConstantInt/1
222
///
223
/// 2. (negative number) Op/MkOpNegate/Constant/ConstantInt/1
224
///
225
/// Unlike `parse_constant` this handles the negation operator. `parse_constant` expects the
226
/// negation to already have been handled as an expression; however, here we do not expect domain
227
/// values to be part of larger expressions, only negated.
228
///
229
6800
fn parse_domain_value_int(obj: &JsonValue) -> Option<i32> {
230
6800
    parser_trace!("trying to parse domain value: {}", obj);
231

            
232
7242
    fn try_parse_positive_int(obj: &JsonValue) -> Option<i32> {
233
7242
        parser_trace!(".. trying as a positive domain value: {}", obj);
234
        // Positive number: Constant/ConstantInt/1
235

            
236
7242
        let leaf_node = obj.pointer("/Constant/ConstantInt/1")?;
237

            
238
6800
        match leaf_node.as_i64()?.try_into() {
239
6800
            Ok(x) => {
240
6800
                parser_trace!(".. success!");
241
6800
                Some(x)
242
            }
243
            Err(_) => {
244
                println!(
245
                    "Could not convert integer constant to i32: {:#?}",
246
                    leaf_node
247
                );
248
                None
249
            }
250
        }
251
7242
    }
252

            
253
442
    fn try_parse_negative_int(obj: &JsonValue) -> Option<i32> {
254
442
        // Negative number: Op/MkOpNegate/Constant/ConstantInt/1
255
442

            
256
442
        // Unwrap negation operator, giving us a Constant/ConstantInt/1
257
442
        //
258
442
        // This is just a positive constant, so try to parse it as such
259
442

            
260
442
        parser_trace!(".. trying as a negative domain value: {}", obj);
261
442
        let inner_constant_node = obj.pointer("/Op/MkOpNegate")?;
262
442
        let inner_num = try_parse_positive_int(inner_constant_node)?;
263

            
264
442
        parser_trace!(".. success!");
265
442
        Some(-inner_num)
266
442
    }
267

            
268
6800
    try_parse_positive_int(obj).or_else(|| try_parse_negative_int(obj))
269
6800
}
270

            
271
// this needs an explicit type signature to force the closures to have the same type
272
type BinOp = Box<dyn Fn(Metadata, Box<Expression>, Box<Expression>) -> Expression>;
273
type UnaryOp = Box<dyn Fn(Metadata, Box<Expression>) -> Expression>;
274
type VecOp = Box<dyn Fn(Metadata, Vec<Expression>) -> Expression>;
275

            
276
18700
fn parse_expression(obj: &JsonValue) -> Option<Expression> {
277
18700
    let binary_operators: HashMap<&str, BinOp> = [
278
18700
        (
279
18700
            "MkOpEq",
280
18700
            Box::new(Expression::Eq) as Box<dyn Fn(_, _, _) -> _>,
281
18700
        ),
282
18700
        (
283
18700
            "MkOpNeq",
284
18700
            Box::new(Expression::Neq) as Box<dyn Fn(_, _, _) -> _>,
285
18700
        ),
286
18700
        (
287
18700
            "MkOpGeq",
288
18700
            Box::new(Expression::Geq) as Box<dyn Fn(_, _, _) -> _>,
289
18700
        ),
290
18700
        (
291
18700
            "MkOpLeq",
292
18700
            Box::new(Expression::Leq) as Box<dyn Fn(_, _, _) -> _>,
293
18700
        ),
294
18700
        (
295
18700
            "MkOpGt",
296
18700
            Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
297
18700
        ),
298
18700
        (
299
18700
            "MkOpLt",
300
18700
            Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
301
18700
        ),
302
18700
        (
303
18700
            "MkOpGt",
304
18700
            Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
305
18700
        ),
306
18700
        (
307
18700
            "MkOpLt",
308
18700
            Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
309
18700
        ),
310
18700
        (
311
18700
            "MkOpDiv",
312
18700
            Box::new(Expression::UnsafeDiv) as Box<dyn Fn(_, _, _) -> _>,
313
18700
        ),
314
18700
        (
315
18700
            "MkOpMod",
316
18700
            Box::new(Expression::UnsafeMod) as Box<dyn Fn(_, _, _) -> _>,
317
18700
        ),
318
18700
        (
319
18700
            "MkOpMinus",
320
18700
            Box::new(Expression::Minus) as Box<dyn Fn(_, _, _) -> _>,
321
18700
        ),
322
18700
        (
323
18700
            "MkOpImply",
324
18700
            Box::new(Expression::Imply) as Box<dyn Fn(_, _, _) -> _>,
325
18700
        ),
326
18700
        (
327
18700
            "MkOpPow",
328
18700
            Box::new(Expression::UnsafePow) as Box<dyn Fn(_, _, _) -> _>,
329
18700
        ),
330
18700
    ]
331
18700
    .into_iter()
332
18700
    .collect();
333
18700

            
334
18700
    let unary_operators: HashMap<&str, UnaryOp> = [
335
18700
        (
336
18700
            "MkOpNot",
337
18700
            Box::new(Expression::Not) as Box<dyn Fn(_, _) -> _>,
338
18700
        ),
339
18700
        (
340
18700
            "MkOpNegate",
341
18700
            Box::new(Expression::Neg) as Box<dyn Fn(_, _) -> _>,
342
18700
        ),
343
18700
        (
344
18700
            "MkOpTwoBars",
345
18700
            Box::new(Expression::Abs) as Box<dyn Fn(_, _) -> _>,
346
18700
        ),
347
18700
    ]
348
18700
    .into_iter()
349
18700
    .collect();
350
18700

            
351
18700
    let vec_operators: HashMap<&str, VecOp> = [
352
18700
        (
353
18700
            "MkOpSum",
354
18700
            Box::new(Expression::Sum) as Box<dyn Fn(_, _) -> _>,
355
18700
        ),
356
18700
        (
357
18700
            "MkOpProduct",
358
18700
            Box::new(Expression::Product) as Box<dyn Fn(_, _) -> _>,
359
18700
        ),
360
18700
        (
361
18700
            "MkOpAnd",
362
18700
            Box::new(Expression::And) as Box<dyn Fn(_, _) -> _>,
363
18700
        ),
364
18700
        ("MkOpOr", Box::new(Expression::Or) as Box<dyn Fn(_, _) -> _>),
365
18700
        (
366
18700
            "MkOpMin",
367
18700
            Box::new(Expression::Min) as Box<dyn Fn(_, _) -> _>,
368
18700
        ),
369
18700
        (
370
18700
            "MkOpMax",
371
18700
            Box::new(Expression::Max) as Box<dyn Fn(_, _) -> _>,
372
18700
        ),
373
18700
        (
374
18700
            "MkOpAllDiff",
375
18700
            Box::new(Expression::AllDiff) as Box<dyn Fn(_, _) -> _>,
376
18700
        ),
377
18700
    ]
378
18700
    .into_iter()
379
18700
    .collect();
380
18700

            
381
68544
    let mut binary_operator_names = binary_operators.iter().map(|x| x.0);
382
18700
    let mut unary_operator_names = unary_operators.iter().map(|x| x.0);
383
18700
    let mut vec_operator_names = vec_operators.iter().map(|x| x.0);
384

            
385
34
    match obj {
386
18700
        Value::Object(op) if op.contains_key("Op") => match &op["Op"] {
387
68544
            Value::Object(bin_op) if binary_operator_names.any(|key| bin_op.contains_key(*key)) => {
388
5202
                parse_bin_op(bin_op, binary_operators)
389
            }
390
8840
            Value::Object(un_op) if unary_operator_names.any(|key| un_op.contains_key(*key)) => {
391
1190
                parse_unary_op(un_op, unary_operators)
392
            }
393
8160
            Value::Object(vec_op) if vec_operator_names.any(|key| vec_op.contains_key(*key)) => {
394
2210
                parse_vec_op(vec_op, vec_operators)
395
            }
396
            otherwise => bug!("Unhandled Op {:#?}", otherwise),
397
        },
398
10098
        Value::Object(refe) if refe.contains_key("Reference") => {
399
6137
            let name = refe["Reference"].as_array()?[0].as_object()?["Name"].as_str()?;
400
6137
            Some(Expression::Atomic(
401
6137
                Metadata::new(),
402
6137
                Atom::Reference(Name::UserName(name.to_string())),
403
6137
            ))
404
        }
405
3961
        Value::Object(constant) if constant.contains_key("Constant") => parse_constant(constant),
406
170
        Value::Object(constant) if constant.contains_key("ConstantInt") => parse_constant(constant),
407
34
        Value::Object(constant) if constant.contains_key("ConstantBool") => {
408
            parse_constant(constant)
409
        }
410
34
        _ => None,
411
    }
412
18700
}
413

            
414
5202
fn parse_bin_op(
415
5202
    bin_op: &serde_json::Map<String, Value>,
416
5202
    binary_operators: HashMap<&str, BinOp>,
417
5202
) -> Option<Expression> {
418
    // we know there is a single key value pair in this object
419
    // extract the value, ignore the key
420
5202
    let (key, value) = bin_op.into_iter().next()?;
421

            
422
5202
    let constructor = binary_operators.get(key.as_str())?;
423

            
424
5202
    match &value {
425
5202
        Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
426
5202
            let arg1 = parse_expression(&bin_op_args[0])?;
427
5202
            let arg2 = parse_expression(&bin_op_args[1])?;
428
5202
            Some(constructor(Metadata::new(), Box::new(arg1), Box::new(arg2)))
429
        }
430
        otherwise => bug!("Unhandled parse_bin_op {:#?}", otherwise),
431
    }
432
5202
}
433

            
434
1190
fn parse_unary_op(
435
1190
    un_op: &serde_json::Map<String, Value>,
436
1190
    unary_operators: HashMap<&str, UnaryOp>,
437
1190
) -> Option<Expression> {
438
1190
    let (key, value) = un_op.into_iter().next()?;
439
1190
    let constructor = unary_operators.get(key.as_str())?;
440

            
441
1190
    let arg = parse_expression(value)?;
442
1190
    Some(constructor(Metadata::new(), Box::new(arg)))
443
1190
}
444

            
445
2210
fn parse_vec_op(
446
2210
    vec_op: &serde_json::Map<String, Value>,
447
2210
    vec_operators: HashMap<&str, VecOp>,
448
2210
) -> Option<Expression> {
449
2210
    let (key, value) = vec_op.into_iter().next()?;
450
2210
    let constructor = vec_operators.get(key.as_str())?;
451

            
452
    parser_debug!("Trying to parse vec_op: {key} ...");
453

            
454
2210
    let mut args_parsed: Option<Vec<Option<Expression>>> = None;
455
2210
    if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix/1") {
456
2142
        parser_trace!("... containing a matrix of literals");
457
2142
        args_parsed = abs_lit_matrix.as_array().map(|x| {
458
2142
            x.iter()
459
2142
                .map(parse_expression)
460
2142
                .collect::<Vec<Option<Expression>>>()
461
2142
        });
462
2142
    }
463
    // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
464
68
    else if let Some(const_abs_lit_matrix) =
465
68
        value.pointer("/Constant/ConstantAbstract/AbsLitMatrix/1")
466
    {
467
68
        parser_trace!("... containing a matrix of constants");
468
68
        args_parsed = const_abs_lit_matrix.as_array().map(|x| {
469
68
            x.iter()
470
68
                .map(parse_expression)
471
68
                .collect::<Vec<Option<Expression>>>()
472
68
        });
473
68
    }
474

            
475
2210
    let args_parsed = args_parsed?;
476

            
477
2210
    let number_of_args = args_parsed.len();
478
    parser_debug!("... with {number_of_args} args {args_parsed:#?}");
479

            
480
2210
    let valid_args: Vec<Expression> = args_parsed.into_iter().flatten().collect();
481
2210
    if number_of_args != valid_args.len() {
482
        None
483
    } else {
484
        parser_debug!("... success!");
485
2210
        Some(constructor(Metadata::new(), valid_args))
486
    }
487
2210
}
488

            
489
3927
fn parse_constant(constant: &serde_json::Map<String, Value>) -> Option<Expression> {
490
3927
    match &constant.get("Constant") {
491
3791
        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
492
3587
            let int_32: i32 = match int["ConstantInt"].as_array()?[1].as_i64()?.try_into() {
493
3587
                Ok(x) => x,
494
                Err(_) => {
495
                    println!(
496
                        "Could not convert integer constant to i32: {:#?}",
497
                        int["ConstantInt"]
498
                    );
499
                    return None;
500
                }
501
            };
502

            
503
3587
            Some(Expression::Atomic(
504
3587
                Metadata::new(),
505
3587
                Atom::Literal(Literal::Int(int_32)),
506
3587
            ))
507
        }
508

            
509
204
        Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
510
204
            let b: bool = b["ConstantBool"].as_bool()?;
511
204
            Some(Expression::Atomic(
512
204
                Metadata::new(),
513
204
                Atom::Literal(Literal::Bool(b)),
514
204
            ))
515
        }
516

            
517
        // sometimes (e.g. constant matrices) we can have a ConstantInt / Constant bool that is
518
        // not wrapped in Constant
519
        None => {
520
136
            let int_expr = constant["ConstantInt"]
521
136
                .as_array()
522
136
                .and_then(|x| x[1].as_i64())
523
136
                .and_then(|x| x.try_into().ok())
524
136
                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Int(x))));
525

            
526
136
            if let e @ Some(_) = int_expr {
527
136
                return e;
528
            }
529

            
530
            let bool_expr = constant["ConstantBool"]
531
                .as_bool()
532
                .map(|x| Expression::Atomic(Metadata::new(), Atom::Literal(Literal::Bool(x))));
533

            
534
            if let e @ Some(_) = bool_expr {
535
                return e;
536
            }
537

            
538
            bug!("Unhandled parse_constant {:#?}", constant);
539
        }
540
        otherwise => bug!("Unhandled parse_constant {:#?}", otherwise),
541
    }
542
3927
}