this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
3/*
4 * Main authors:
5 * Jason Nguyen <jason.nguyen@monash.edu>
6 */
7
8/* This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12#include <minizinc/json_parser.hh>
13#include <minizinc/param_config.hh>
14#include <minizinc/prettyprinter.hh>
15
16#include <sstream>
17
18namespace MiniZinc {
19
20void ParamConfig::load(const std::string& filename) {
21 if (JSONParser::fileIsJSON(filename)) {
22 try {
23 Env confenv;
24 JSONParser jp(confenv.envi());
25 Model m;
26 GCLock lock;
27 jp.parse(&m, filename, false);
28 for (auto& i : m) {
29 if (auto* ai = i->dynamicCast<AssignI>()) {
30 addValue(ai->id(), ai->e());
31 } else if (auto* ii = i->dynamicCast<IncludeI>()) {
32 auto flag = ParamConfig::flagName(ii->f());
33 if (_blacklist.count(flag) > 0) {
34 throw ParamException("Parameter '" + flag + "' is not allowed in configuration file");
35 }
36 _values.push_back(flag);
37 _values.push_back(ParamConfig::modelToString(*(ii->m())));
38 }
39 }
40 } catch (ParamException& e) {
41 throw;
42 } catch (Exception& e) {
43 throw ParamException(e.what());
44 }
45 } else {
46 throw ParamException("Invalid configuration file");
47 }
48}
49
50void ParamConfig::addValue(const ASTString& flag_input, Expression* e) {
51 auto flag = ParamConfig::flagName(flag_input);
52 if (_blacklist.count(flag) > 0) {
53 throw ParamException("Parameter '" + flag + "' is not allowed in configuration file");
54 }
55 std::stringstream val_ss;
56 switch (e->eid()) {
57 case Expression::E_ARRAYLIT: {
58 auto* al = e->cast<ArrayLit>();
59 for (auto* exp : al->getVec()) {
60 addValue(flag, exp);
61 }
62 break;
63 }
64 case Expression::E_BOOLLIT: {
65 if (e->cast<BoolLit>()->v()) {
66 _values.push_back(flag);
67 } else {
68 // If this flag has a negated version, use it
69 auto it = _boolSwitches.find(flag);
70 if (it != _boolSwitches.end()) {
71 _values.push_back(it->second);
72 }
73 }
74 break;
75 }
76 case Expression::E_STRINGLIT:
77 _values.push_back(flag);
78 val_ss << e->cast<StringLit>()->v();
79 _values.push_back(val_ss.str());
80 break;
81 case Expression::E_INTLIT:
82 _values.push_back(flag);
83 val_ss << e->cast<IntLit>()->v();
84 _values.push_back(val_ss.str());
85 break;
86 case Expression::E_FLOATLIT:
87 _values.push_back(flag);
88 val_ss << e->cast<FloatLit>()->v();
89 val_ss << e;
90 _values.push_back(val_ss.str());
91 break;
92 break;
93 default:
94 throw ParamException("Unsupported parameter type for '" + flag + "'");
95 }
96}
97
98std::string ParamConfig::flagName(const ASTString& flag_input) {
99 std::stringstream flag_ss;
100 if (!flag_input.beginsWith("-")) {
101 flag_ss << "--";
102 }
103 flag_ss << flag_input;
104 return flag_ss.str();
105}
106
107std::string ParamConfig::modelToString(Model& model) {
108 std::stringstream ss;
109 for (auto& i : model) {
110 if (auto* ai = i->dynamicCast<AssignI>()) {
111 auto flag = ParamConfig::flagName(ai->id());
112 auto* e = ai->e();
113 switch (e->eid()) {
114 case Expression::E_ARRAYLIT: {
115 auto* al = e->cast<ArrayLit>();
116 for (auto* exp : al->getVec()) {
117 ss << " " << flag;
118 ss << " " << exp;
119 }
120 break;
121 }
122 case Expression::E_BOOLLIT:
123 if (e->cast<BoolLit>()->v()) {
124 ss << " " << flag;
125 }
126 break;
127 case Expression::E_STRINGLIT:
128 ss << " " << flag;
129 ss << " " << ai->e()->cast<StringLit>()->v();
130 break;
131 case Expression::E_INTLIT:
132 ss << " " << flag;
133 ss << " " << ai->e()->cast<IntLit>()->v();
134 break;
135 case Expression::E_FLOATLIT:
136 ss << " " << flag;
137 ss << " " << ai->e()->cast<FloatLit>()->v();
138 break;
139 default:
140 throw ParamException("Unsupported parameter type for '" + flag + "'");
141 }
142 } else if (auto* ii = i->dynamicCast<IncludeI>()) {
143 ss << " " << ParamConfig::flagName(ii->f());
144 ss << " \"" << Printer::escapeStringLit(modelToString(*(ii->m()))) << "\"";
145 }
146 }
147 return ss.str().substr(1);
148}
149
150const std::vector<std::string>& ParamConfig::argv() { return _values; }
151
152void ParamConfig::blacklist(const std::string& disallowed) { _blacklist.insert(disallowed); }
153
154void ParamConfig::blacklist(const std::vector<std::string>& disallowed) {
155 for (const auto& param : disallowed) {
156 _blacklist.insert(param);
157 }
158}
159
160void ParamConfig::negatedFlag(const std::string& flag, const std::string& negated) {
161 _boolSwitches.insert(std::make_pair(flag, negated));
162}
163
164} // namespace MiniZinc