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

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

            
7
use crate::ast::{DecisionVariable, Domain, Expression, Factor, Literal, Name, Range};
8
use crate::bug;
9
use crate::context::Context;
10
use crate::error::{Error, Result};
11
use crate::metadata::Metadata;
12
use crate::Model;
13

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

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

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

            
33
2737
    for statement in statements {
34
2091
        let entry = statement
35
2091
            .as_object()
36
2091
            .ok_or(Error::Parse("mStatements contains a non-object".to_owned()))?
37
2091
            .iter()
38
2091
            .next()
39
2091
            .ok_or(Error::Parse(
40
2091
                "mStatements contains an empty object".to_owned(),
41
2091
            ))?;
42
2091
        match entry.0.as_str() {
43
2091
            "Declaration" => {
44
1428
                let (name, var) = parse_variable(entry.1)?;
45
1428
                m.add_variable(name, var);
46
            }
47
663
            "SuchThat" => {
48
663
                let constraints_arr = match entry.1.as_array() {
49
663
                    Some(x) => x,
50
                    None => bug!("SuchThat is not a vector"),
51
                };
52

            
53
663
                let constraints: Vec<Expression> =
54
663
                    constraints_arr.iter().flat_map(parse_expression).collect();
55
663
                m.add_constraints(constraints);
56
                // println!("Nb constraints {}", m.constraints.len());
57
            }
58
            otherwise => bug!("Unhandled Statement {:#?}", otherwise),
59
        }
60
    }
61

            
62
646
    Ok(m)
63
646
}
64

            
65
1428
fn parse_variable(v: &JsonValue) -> Result<(Name, DecisionVariable)> {
66
1428
    let arr = v
67
1428
        .as_object()
68
1428
        .ok_or(Error::Parse("Declaration is not an object".to_owned()))?["FindOrGiven"]
69
1428
        .as_array()
70
1428
        .ok_or(Error::Parse("FindOrGiven is not an array".to_owned()))?;
71
1428
    let name = arr[1]
72
1428
        .as_object()
73
1428
        .ok_or(Error::Parse("FindOrGiven[1] is not an object".to_owned()))?["Name"]
74
1428
        .as_str()
75
1428
        .ok_or(Error::Parse(
76
1428
            "FindOrGiven[1].Name is not a string".to_owned(),
77
1428
        ))?;
78
1428
    let name = Name::UserName(name.to_owned());
79
1428
    let domain = arr[2]
80
1428
        .as_object()
81
1428
        .ok_or(Error::Parse("FindOrGiven[2] is not an object".to_owned()))?
82
1428
        .iter()
83
1428
        .next()
84
1428
        .ok_or(Error::Parse("FindOrGiven[2] is an empty object".to_owned()))?;
85
1428
    let domain = match domain.0.as_str() {
86
1428
        "DomainInt" => Ok(parse_int_domain(domain.1)?),
87
323
        "DomainBool" => Ok(Domain::BoolDomain),
88
        _ => Err(Error::Parse(
89
            "FindOrGiven[2] is an unknown object".to_owned(), // consider covered
90
        )),
91
    }?;
92
1428
    Ok((name, DecisionVariable { domain }))
93
1428
}
94

            
95
1105
fn parse_int_domain(v: &JsonValue) -> Result<Domain> {
96
1105
    let mut ranges = Vec::new();
97
1105
    let arr = v
98
1105
        .as_array()
99
1105
        .ok_or(Error::Parse("DomainInt is not an array".to_owned()))?[1]
100
1105
        .as_array()
101
1105
        .ok_or(Error::Parse("DomainInt[1] is not an array".to_owned()))?;
102
2210
    for range in arr {
103
1105
        let range = range
104
1105
            .as_object()
105
1105
            .ok_or(Error::Parse(
106
1105
                "DomainInt[1] contains a non-object".to_owned(),
107
1105
            ))?
108
1105
            .iter()
109
1105
            .next()
110
1105
            .ok_or(Error::Parse(
111
1105
                "DomainInt[1] contains an empty object".to_owned(),
112
1105
            ))?;
113
1105
        match range.0.as_str() {
114
1105
            "RangeBounded" => {
115
1088
                let arr = range
116
1088
                    .1
117
1088
                    .as_array()
118
1088
                    .ok_or(Error::Parse("RangeBounded is not an array".to_owned()))?;
119
1088
                let mut nums = Vec::new();
120
2176
                for item in arr.iter() {
121
2176
                    let num = item["Constant"]["ConstantInt"][1]
122
2176
                        .as_i64()
123
2176
                        .ok_or(Error::Parse(
124
2176
                            "Could not parse int domain constant".to_owned(),
125
2176
                        ))?;
126
2176
                    let num32 = i32::try_from(num).map_err(|_| {
127
                        Error::Parse("Could not parse int domain constant".to_owned())
128
2176
                    })?;
129
2176
                    nums.push(num32);
130
                }
131
1088
                ranges.push(Range::Bounded(nums[0], nums[1]));
132
            }
133
17
            "RangeSingle" => {
134
17
                let num = &range.1["Constant"]["ConstantInt"][1]
135
17
                    .as_i64()
136
17
                    .ok_or(Error::Parse(
137
17
                        "Could not parse int domain constant".to_owned(),
138
17
                    ))?;
139
17
                let num32 = i32::try_from(*num)
140
17
                    .map_err(|_| Error::Parse("Could not parse int domain constant".to_owned()))?;
141
17
                ranges.push(Range::Single(num32));
142
            }
143
            _ => {
144
                return Err(Error::Parse(
145
                    "DomainInt[1] contains an unknown object".to_owned(),
146
                ))
147
            }
148
        }
149
    }
150
1105
    Ok(Domain::IntDomain(ranges))
151
1105
}
152

            
153
// this needs an explicit type signature to force the closures to have the same type
154
type BinOp = Box<dyn Fn(Metadata, Box<Expression>, Box<Expression>) -> Expression>;
155
type UnaryOp = Box<dyn Fn(Metadata, Box<Expression>) -> Expression>;
156
type VecOp = Box<dyn Fn(Metadata, Vec<Expression>) -> Expression>;
157

            
158
3944
fn parse_expression(obj: &JsonValue) -> Option<Expression> {
159
3944
    let binary_operators: HashMap<&str, BinOp> = [
160
3944
        (
161
3944
            "MkOpEq",
162
3944
            Box::new(Expression::Eq) as Box<dyn Fn(_, _, _) -> _>,
163
3944
        ),
164
3944
        (
165
3944
            "MkOpNeq",
166
3944
            Box::new(Expression::Neq) as Box<dyn Fn(_, _, _) -> _>,
167
3944
        ),
168
3944
        (
169
3944
            "MkOpGeq",
170
3944
            Box::new(Expression::Geq) as Box<dyn Fn(_, _, _) -> _>,
171
3944
        ),
172
3944
        (
173
3944
            "MkOpLeq",
174
3944
            Box::new(Expression::Leq) as Box<dyn Fn(_, _, _) -> _>,
175
3944
        ),
176
3944
        (
177
3944
            "MkOpGt",
178
3944
            Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
179
3944
        ),
180
3944
        (
181
3944
            "MkOpLt",
182
3944
            Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
183
3944
        ),
184
3944
        (
185
3944
            "MkOpGt",
186
3944
            Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
187
3944
        ),
188
3944
        (
189
3944
            "MkOpLt",
190
3944
            Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
191
3944
        ),
192
3944
        (
193
3944
            "MkOpDiv",
194
3944
            Box::new(Expression::UnsafeDiv) as Box<dyn Fn(_, _, _) -> _>,
195
3944
        ),
196
3944
    ]
197
3944
    .into_iter()
198
3944
    .collect();
199
3944

            
200
3944
    let unary_operators: HashMap<&str, UnaryOp> = [(
201
3944
        "MkOpNot",
202
3944
        Box::new(Expression::Not) as Box<dyn Fn(_, _) -> _>,
203
3944
    )]
204
3944
    .into_iter()
205
3944
    .collect();
206
3944

            
207
3944
    let vec_operators: HashMap<&str, VecOp> = [
208
3944
        (
209
3944
            "MkOpSum",
210
3944
            Box::new(Expression::Sum) as Box<dyn Fn(_, _) -> _>,
211
3944
        ),
212
3944
        (
213
3944
            "MkOpAnd",
214
3944
            Box::new(Expression::And) as Box<dyn Fn(_, _) -> _>,
215
3944
        ),
216
3944
        ("MkOpOr", Box::new(Expression::Or) as Box<dyn Fn(_, _) -> _>),
217
3944
        (
218
3944
            "MkOpMin",
219
3944
            Box::new(Expression::Min) as Box<dyn Fn(_, _) -> _>,
220
3944
        ),
221
3944
        (
222
3944
            "MkOpMax",
223
3944
            Box::new(Expression::Max) as Box<dyn Fn(_, _) -> _>,
224
3944
        ),
225
3944
        (
226
3944
            "MkOpAllDiff",
227
3944
            Box::new(Expression::AllDiff) as Box<dyn Fn(_, _) -> _>,
228
3944
        ),
229
3944
    ]
230
3944
    .into_iter()
231
3944
    .collect();
232
3944

            
233
8483
    let mut binary_operator_names = binary_operators.iter().map(|x| x.0);
234
3944
    let mut unary_operator_names = unary_operators.iter().map(|x| x.0);
235
3944
    let mut vec_operator_names = vec_operators.iter().map(|x| x.0);
236

            
237
    match obj {
238
3944
        Value::Object(op) if op.contains_key("Op") => match &op["Op"] {
239
8483
            Value::Object(bin_op) if binary_operator_names.any(|key| bin_op.contains_key(*key)) => {
240
748
                parse_bin_op(bin_op, binary_operators)
241
            }
242
833
            Value::Object(un_op) if unary_operator_names.any(|key| un_op.contains_key(*key)) => {
243
34
                parse_unary_op(un_op, unary_operators)
244
            }
245
2890
            Value::Object(vec_op) if vec_operator_names.any(|key| vec_op.contains_key(*key)) => {
246
799
                parse_vec_op(vec_op, vec_operators)
247
            }
248
            otherwise => bug!("Unhandled Op {:#?}", otherwise),
249
        },
250
2363
        Value::Object(refe) if refe.contains_key("Reference") => {
251
1547
            let name = refe["Reference"].as_array()?[0].as_object()?["Name"].as_str()?;
252
1547
            Some(Expression::FactorE(
253
1547
                Metadata::new(),
254
1547
                Factor::Reference(Name::UserName(name.to_string())),
255
1547
            ))
256
        }
257
816
        Value::Object(constant) if constant.contains_key("Constant") => parse_constant(constant),
258
136
        Value::Object(constant) if constant.contains_key("ConstantInt") => parse_constant(constant),
259
        Value::Object(constant) if constant.contains_key("ConstantBool") => {
260
            parse_constant(constant)
261
        }
262
        otherwise => bug!("Unhandled Expression {:#?}", otherwise),
263
    }
264
3944
}
265

            
266
748
fn parse_bin_op(
267
748
    bin_op: &serde_json::Map<String, Value>,
268
748
    binary_operators: HashMap<&str, BinOp>,
269
748
) -> Option<Expression> {
270
    // we know there is a single key value pair in this object
271
    // extract the value, ignore the key
272
748
    let (key, value) = bin_op.into_iter().next()?;
273

            
274
748
    let constructor = binary_operators.get(key.as_str())?;
275

            
276
748
    match &value {
277
748
        Value::Array(bin_op_args) if bin_op_args.len() == 2 => {
278
748
            let arg1 = parse_expression(&bin_op_args[0])?;
279
748
            let arg2 = parse_expression(&bin_op_args[1])?;
280
748
            Some(constructor(Metadata::new(), Box::new(arg1), Box::new(arg2)))
281
        }
282
        otherwise => bug!("Unhandled parse_bin_op {:#?}", otherwise),
283
    }
284
748
}
285

            
286
34
fn parse_unary_op(
287
34
    un_op: &serde_json::Map<String, Value>,
288
34
    unary_operators: HashMap<&str, UnaryOp>,
289
34
) -> Option<Expression> {
290
34
    let (key, value) = un_op.into_iter().next()?;
291
34
    let constructor = unary_operators.get(key.as_str())?;
292

            
293
34
    let arg = parse_expression(value)?;
294
34
    Some(constructor(Metadata::new(), Box::new(arg)))
295
34
}
296

            
297
799
fn parse_vec_op(
298
799
    vec_op: &serde_json::Map<String, Value>,
299
799
    vec_operators: HashMap<&str, VecOp>,
300
799
) -> Option<Expression> {
301
799
    let (key, value) = vec_op.into_iter().next()?;
302
799
    let constructor = vec_operators.get(key.as_str())?;
303

            
304
    parser_debug!("Trying to parse vec_op: {key} ...");
305

            
306
799
    let mut args_parsed: Option<Vec<Option<Expression>>> = None;
307
799
    if let Some(abs_lit_matrix) = value.pointer("/AbstractLiteral/AbsLitMatrix/1") {
308
731
        parser_trace!("... containing a matrix of literals");
309
731
        args_parsed = abs_lit_matrix.as_array().map(|x| {
310
731
            x.iter()
311
731
                .map(parse_expression)
312
731
                .collect::<Vec<Option<Expression>>>()
313
731
        });
314
731
    }
315
    // the input of this expression is constant - e.g. or([]), or([false]), min([2]), etc.
316
68
    else if let Some(const_abs_lit_matrix) =
317
68
        value.pointer("/Constant/ConstantAbstract/AbsLitMatrix/1")
318
    {
319
68
        parser_trace!("... containing a matrix of constants");
320
68
        args_parsed = const_abs_lit_matrix.as_array().map(|x| {
321
68
            x.iter()
322
68
                .map(parse_expression)
323
68
                .collect::<Vec<Option<Expression>>>()
324
68
        });
325
68
    }
326

            
327
799
    let args_parsed = args_parsed?;
328

            
329
799
    let number_of_args = args_parsed.len();
330
    parser_debug!("... with {number_of_args} args {args_parsed:#?}");
331

            
332
799
    let valid_args: Vec<Expression> = args_parsed.into_iter().flatten().collect();
333
799
    if number_of_args != valid_args.len() {
334
        None
335
    } else {
336
        parser_debug!("... success!");
337
799
        Some(constructor(Metadata::new(), valid_args))
338
    }
339
799
}
340

            
341
816
fn parse_constant(constant: &serde_json::Map<String, Value>) -> Option<Expression> {
342
816
    match &constant.get("Constant") {
343
680
        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
344
544
            let int_32: i32 = match int["ConstantInt"].as_array()?[1].as_i64()?.try_into() {
345
544
                Ok(x) => x,
346
                Err(_) => {
347
                    println!(
348
                        "Could not convert integer constant to i32: {:#?}",
349
                        int["ConstantInt"]
350
                    );
351
                    return None;
352
                }
353
            };
354

            
355
544
            Some(Expression::FactorE(
356
544
                Metadata::new(),
357
544
                Factor::Literal(Literal::Int(int_32)),
358
544
            ))
359
        }
360

            
361
136
        Some(Value::Object(b)) if b.contains_key("ConstantBool") => {
362
136
            let b: bool = b["ConstantBool"].as_bool().unwrap();
363
136
            Some(Expression::FactorE(
364
136
                Metadata::new(),
365
136
                Factor::Literal(Literal::Bool(b)),
366
136
            ))
367
        }
368

            
369
        // sometimes (e.g. constant matrices) we can have a ConstantInt / Constant bool that is
370
        // not wrapped in Constant
371
        None => {
372
136
            let int_expr = constant["ConstantInt"]
373
136
                .as_array()
374
136
                .and_then(|x| x[1].as_i64())
375
136
                .and_then(|x| x.try_into().ok())
376
136
                .map(|x| Expression::FactorE(Metadata::new(), Factor::Literal(Literal::Int(x))));
377

            
378
136
            if let e @ Some(_) = int_expr {
379
136
                return e;
380
            }
381

            
382
            let bool_expr = constant["ConstantBool"]
383
                .as_bool()
384
                .map(|x| Expression::FactorE(Metadata::new(), Factor::Literal(Literal::Bool(x))));
385

            
386
            if let e @ Some(_) = bool_expr {
387
                return e;
388
            }
389

            
390
            bug!("Unhandled parse_constant {:#?}", constant);
391
        }
392
        otherwise => bug!("Unhandled parse_constant {:#?}", otherwise),
393
    }
394
816
}