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

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

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

            
62
714
    Ok(m)
63
714
}
64

            
65
1632
fn parse_variable(v: &JsonValue) -> Result<(Name, DecisionVariable)> {
66
1632
    let arr = v
67
1632
        .as_object()
68
1632
        .ok_or(Error::Parse("Declaration is not an object".to_owned()))?["FindOrGiven"]
69
1632
        .as_array()
70
1632
        .ok_or(Error::Parse("FindOrGiven is not an array".to_owned()))?;
71
1632
    let name = arr[1]
72
1632
        .as_object()
73
1632
        .ok_or(Error::Parse("FindOrGiven[1] is not an object".to_owned()))?["Name"]
74
1632
        .as_str()
75
1632
        .ok_or(Error::Parse(
76
1632
            "FindOrGiven[1].Name is not a string".to_owned(),
77
1632
        ))?;
78
1632
    let name = Name::UserName(name.to_owned());
79
1632
    let domain = arr[2]
80
1632
        .as_object()
81
1632
        .ok_or(Error::Parse("FindOrGiven[2] is not an object".to_owned()))?
82
1632
        .iter()
83
1632
        .next()
84
1632
        .ok_or(Error::Parse("FindOrGiven[2] is an empty object".to_owned()))?;
85
1632
    let domain = match domain.0.as_str() {
86
1632
        "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
1632
    Ok((name, DecisionVariable { domain }))
93
1632
}
94

            
95
1309
fn parse_int_domain(v: &JsonValue) -> Result<Domain> {
96
1309
    let mut ranges = Vec::new();
97
1309
    let arr = v
98
1309
        .as_array()
99
1309
        .ok_or(Error::Parse("DomainInt is not an array".to_owned()))?[1]
100
1309
        .as_array()
101
1309
        .ok_or(Error::Parse("DomainInt[1] is not an array".to_owned()))?;
102
2618
    for range in arr {
103
1309
        let range = range
104
1309
            .as_object()
105
1309
            .ok_or(Error::Parse(
106
1309
                "DomainInt[1] contains a non-object".to_owned(),
107
1309
            ))?
108
1309
            .iter()
109
1309
            .next()
110
1309
            .ok_or(Error::Parse(
111
1309
                "DomainInt[1] contains an empty object".to_owned(),
112
1309
            ))?;
113
1309
        match range.0.as_str() {
114
1309
            "RangeBounded" => {
115
1292
                let arr = range
116
1292
                    .1
117
1292
                    .as_array()
118
1292
                    .ok_or(Error::Parse("RangeBounded is not an array".to_owned()))?;
119
1292
                let mut nums = Vec::new();
120
2584
                for item in arr.iter() {
121
2584
                    let num = item["Constant"]["ConstantInt"][1]
122
2584
                        .as_i64()
123
2584
                        .ok_or(Error::Parse(
124
2584
                            "Could not parse int domain constant".to_owned(),
125
2584
                        ))?;
126
2584
                    let num32 = i32::try_from(num).map_err(|_| {
127
                        Error::Parse("Could not parse int domain constant".to_owned())
128
2584
                    })?;
129
2584
                    nums.push(num32);
130
                }
131
1292
                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
1309
    Ok(Domain::IntDomain(ranges))
151
1309
}
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
4420
fn parse_expression(obj: &JsonValue) -> Option<Expression> {
159
4420
    let binary_operators: HashMap<&str, BinOp> = [
160
4420
        (
161
4420
            "MkOpEq",
162
4420
            Box::new(Expression::Eq) as Box<dyn Fn(_, _, _) -> _>,
163
4420
        ),
164
4420
        (
165
4420
            "MkOpNeq",
166
4420
            Box::new(Expression::Neq) as Box<dyn Fn(_, _, _) -> _>,
167
4420
        ),
168
4420
        (
169
4420
            "MkOpGeq",
170
4420
            Box::new(Expression::Geq) as Box<dyn Fn(_, _, _) -> _>,
171
4420
        ),
172
4420
        (
173
4420
            "MkOpLeq",
174
4420
            Box::new(Expression::Leq) as Box<dyn Fn(_, _, _) -> _>,
175
4420
        ),
176
4420
        (
177
4420
            "MkOpGt",
178
4420
            Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
179
4420
        ),
180
4420
        (
181
4420
            "MkOpLt",
182
4420
            Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
183
4420
        ),
184
4420
        (
185
4420
            "MkOpGt",
186
4420
            Box::new(Expression::Gt) as Box<dyn Fn(_, _, _) -> _>,
187
4420
        ),
188
4420
        (
189
4420
            "MkOpLt",
190
4420
            Box::new(Expression::Lt) as Box<dyn Fn(_, _, _) -> _>,
191
4420
        ),
192
4420
        (
193
4420
            "MkOpDiv",
194
4420
            Box::new(Expression::UnsafeDiv) as Box<dyn Fn(_, _, _) -> _>,
195
4420
        ),
196
4420
    ]
197
4420
    .into_iter()
198
4420
    .collect();
199
4420

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

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

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

            
237
    match obj {
238
4420
        Value::Object(op) if op.contains_key("Op") => match &op["Op"] {
239
9775
            Value::Object(bin_op) if binary_operator_names.any(|key| bin_op.contains_key(*key)) => {
240
935
                parse_bin_op(bin_op, binary_operators)
241
            }
242
867
            Value::Object(un_op) if unary_operator_names.any(|key| un_op.contains_key(*key)) => {
243
68
                parse_unary_op(un_op, unary_operators)
244
            }
245
2635
            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
2618
        Value::Object(refe) if refe.contains_key("Reference") => {
251
1751
            let name = refe["Reference"].as_array()?[0].as_object()?["Name"].as_str()?;
252
1751
            Some(Expression::FactorE(
253
1751
                Metadata::new(),
254
1751
                Factor::Reference(Name::UserName(name.to_string())),
255
1751
            ))
256
        }
257
867
        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
4420
}
265

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

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

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

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

            
293
68
    let arg = parse_expression(value)?;
294
68
    Some(constructor(Metadata::new(), Box::new(arg)))
295
68
}
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
867
fn parse_constant(constant: &serde_json::Map<String, Value>) -> Option<Expression> {
342
867
    match &constant.get("Constant") {
343
731
        Some(Value::Object(int)) if int.contains_key("ConstantInt") => {
344
595
            let int_32: i32 = match int["ConstantInt"].as_array()?[1].as_i64()?.try_into() {
345
595
                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
595
            Some(Expression::FactorE(
356
595
                Metadata::new(),
357
595
                Factor::Literal(Literal::Int(int_32)),
358
595
            ))
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
867
}