1
//! The Model Syntax tree for the Minion bindings.
2

            
3
use std::collections::HashMap;
4

            
5
pub type VarName = String;
6

            
7
pub struct Model {
8
    /// A lookup table of all named variables.
9
    pub named_variables: SymbolTable,
10
    pub constraints: Vec<Constraint>,
11
}
12

            
13
impl Model {
14
7
    pub fn new() -> Model {
15
7
        Model {
16
7
            named_variables: SymbolTable::new(),
17
7
            constraints: Vec::new(),
18
7
        }
19
7
    }
20
}
21

            
22
impl Default for Model {
23
    fn default() -> Self {
24
        Self::new()
25
    }
26
}
27

            
28
#[derive(Debug)]
29
pub enum Constraint {
30
    SumLeq(Vec<Var>, Var),
31
    SumGeq(Vec<Var>, Var),
32
    Eq(Var, Var),
33
    Ineq(Var, Var, Constant),
34
    WatchedAnd(Vec<Constraint>),
35
}
36

            
37
/// A variable can either be a named variable, or an anomynous "constant as a variable".
38
///
39
/// The latter is not stored in the symbol table, or counted in Minions internal list of all
40
/// variables, but is used to allow the use of a constant in the place of a variable in a
41
/// constraint.
42
#[derive(Debug)]
43
pub enum Var {
44
    NameRef(VarName),
45
    ConstantAsVar(i32),
46
}
47

            
48
#[derive(Debug, Eq, PartialEq)]
49
pub enum Constant {
50
    Bool(bool),
51
    Integer(i32),
52
}
53

            
54
#[derive(Debug, Copy, Clone)]
55
pub enum VarDomain {
56
    Bound(i32, i32),
57
    Discrete(i32, i32),
58
    SparseBound(i32, i32),
59
    Bool(bool),
60
}
61

            
62
pub struct SymbolTable {
63
    table: HashMap<VarName, VarDomain>,
64

            
65
    // for now doubles both as Minion's SearchOrder and print order
66
    var_order: Vec<VarName>,
67
}
68

            
69
impl SymbolTable {
70
7
    fn new() -> SymbolTable {
71
7
        SymbolTable {
72
7
            table: HashMap::new(),
73
7
            var_order: Vec::new(),
74
7
        }
75
7
    }
76

            
77
    /// Creates a new variable and adds it to the symbol table.
78
    /// If a variable already exists with the given name, an error is thrown.
79
21
    pub fn add_var(&mut self, name: VarName, vartype: VarDomain) -> Option<()> {
80
21
        if self.table.contains_key(&name) {
81
            return None;
82
21
        }
83
21

            
84
21
        self.table.insert(name.clone(), vartype);
85
21
        self.var_order.push(name);
86
21

            
87
21
        Some(())
88
21
    }
89

            
90
21
    pub fn get_vartype(&self, name: VarName) -> Option<VarDomain> {
91
21
        self.table.get(&name).cloned()
92
21
    }
93

            
94
7
    pub fn get_variable_order(&self) -> Vec<VarName> {
95
7
        self.var_order.clone()
96
7
    }
97

            
98
    pub fn contains(&self, name: VarName) -> bool {
99
        self.table.contains_key(&name)
100
    }
101
}