this repo has no description
at develop 6.0 kB view raw
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2 3/* 4 * Main authors: 5 * Kevin Leo <kevin.leo@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/MIPdomains.hh> 13#include <minizinc/astexception.hh> 14#include <minizinc/astiterator.hh> 15#include <minizinc/builtins.hh> 16#include <minizinc/copy.hh> 17#include <minizinc/eval_par.hh> 18#include <minizinc/flatten.hh> 19#include <minizinc/flatten_internal.hh> 20#include <minizinc/hash.hh> 21#include <minizinc/optimize.hh> 22#include <minizinc/parser.hh> 23#include <minizinc/passes/compile_pass.hh> 24#include <minizinc/prettyprinter.hh> 25#include <minizinc/timer.hh> 26#include <minizinc/typecheck.hh> 27 28#include <fstream> 29#include <utility> 30 31namespace MiniZinc { 32 33using std::string; 34using std::vector; 35 36Env* change_library(Env& e, vector<string>& includePaths, const string& globals_dir, 37 CompilePassFlags& compflags, bool verbose = false) { 38 GCLock lock; 39 CopyMap cm; 40 Model* m = e.envi().originalModel != nullptr ? e.envi().originalModel : e.envi().model; 41 auto* new_mod = new Model(); 42 new_mod->setFilename(m->filename()); 43 new_mod->setFilepath(m->filepath()); 44 45 vector<string> new_includePaths; 46 47 if (std::find(includePaths.begin(), includePaths.end(), globals_dir) == includePaths.end()) { 48 new_includePaths.push_back(globals_dir); 49 } 50 new_includePaths.insert(new_includePaths.end(), includePaths.begin(), includePaths.end()); 51 52 // Collect include items 53 vector<ASTString> include_names; 54 for (Item* item : *m) { 55 if (auto* inc = item->dynamicCast<IncludeI>()) { 56 include_names.push_back(inc->m()->filepath()); 57 } else { 58 new_mod->addItem(copy(e.envi(), cm, item)); 59 } 60 } 61 62 std::stringstream ss; 63 for (auto& name : include_names) { 64 ss << "include \"" << Printer::escapeStringLit(name) << "\";"; 65 } 66 67 vector<SyntaxError> syntax_errors; 68 Env* fenv = new Env(new_mod); 69 // Model* inc_mod = parse(*fenv, include_names, {}, new_includePaths, true, true, verbose, 70 // std::cerr); 71 std::ostringstream dummy_file; 72 dummy_file << m->filepath() << "_Dummy.mzn"; 73 Model* inc_mod = parse_from_string(*fenv, ss.str(), dummy_file.str(), new_includePaths, false, 74 false, true, verbose, std::cerr, syntax_errors); 75 if (inc_mod == nullptr) { 76 for (const SyntaxError& se : syntax_errors) { 77 std::cerr << std::endl; 78 std::cerr << se.what() << ": " << se.msg() << std::endl; 79 std::cerr << se.loc() << std::endl; 80 } 81 return nullptr; 82 } 83 auto* new_inc = new IncludeI(Location().introduce(), string("MultiPassDummy.mzn")); 84 new_inc->m(inc_mod); 85 inc_mod->setParent(new_mod); 86 new_mod->addItem(new_inc); 87 88 return fenv; 89} 90 91CompilePass::CompilePass(Env* e, FlatteningOptions& opts, CompilePassFlags& cflags, 92 string globals_library, vector<string> include_paths, bool change_lib, 93 bool ignore_unknown) 94 : _env(e), 95 _fopts(opts), 96 _compflags(cflags), 97 _library(std::move(globals_library)), 98 _includePaths(std::move(include_paths)), 99 _changeLibrary(change_lib), 100 _ignoreUnknownIds(ignore_unknown) {} 101 102Env* CompilePass::run(Env* store, std::ostream& log) { 103 Timer lasttime; 104 if (_compflags.verbose) { 105 log << "\n\tCompilePass: Flatten with \'" << _library << "\' library ...\n"; 106 } 107 108 Env* new_env; 109 if (_changeLibrary) { 110 new_env = change_library(*_env, _includePaths, _library, _compflags, _compflags.verbose); 111 if (new_env == nullptr) { 112 return nullptr; 113 } 114 new_env->envi().copyPathMapsAndState(store->envi()); 115 } else { 116 new_env = _env; 117 } 118 new_env->envi().ignoreUnknownIds = _ignoreUnknownIds; 119 120 vector<TypeError> typeErrors; 121 MiniZinc::typecheck(*new_env, new_env->model(), typeErrors, 122 _compflags.modelCheckOnly || _compflags.modelInterfaceOnly, 123 _compflags.allowMultiAssign); 124 if (!typeErrors.empty()) { 125 std::ostringstream errstream; 126 for (auto& typeError : typeErrors) { 127 errstream << typeError.what() << ": " << typeError.msg() << std::endl; 128 errstream << typeError.loc() << std::endl; 129 } 130 throw Error(errstream.str()); 131 } 132 133 register_builtins(*new_env); 134 135 try { 136 flatten(*new_env, _fopts); 137 } catch (LocationException& e) { 138 if (_compflags.verbose) { 139 log << std::endl; 140 } 141 std::ostringstream errstream; 142 errstream << e.what() << ": " << std::endl; 143 new_env->dumpErrorStack(errstream); 144 errstream << " " << e.msg() << std::endl; 145 throw Error(errstream.str()); 146 } 147 148 if (!_compflags.noMIPdomains) { 149 if (_compflags.verbose) { 150 log << "MIP domains ..."; 151 } 152 mip_domains(*new_env, _compflags.statistics); 153 if (_compflags.verbose) { 154 log << " done (" << lasttime.stoptime() << ")" << std::endl; 155 } 156 } 157 158 if (_compflags.optimize) { 159 if (_compflags.verbose) { 160 log << "Optimizing ..."; 161 } 162 optimize(*new_env, _compflags.chainCompression); 163 if (_compflags.verbose) { 164 log << " done (" << lasttime.stoptime() << ")" << std::endl; 165 } 166 } 167 168 for (const auto& i : new_env->warnings()) { 169 log << (_compflags.werror ? "\n ERROR: " : "\n WARNING: ") << i; 170 } 171 if (_compflags.werror && !new_env->warnings().empty()) { 172 throw Error("errors encountered"); 173 } 174 new_env->clearWarnings(); 175 176 if (!_compflags.newfzn) { 177 if (_compflags.verbose) { 178 log << "Converting to old FlatZinc ..."; 179 } 180 oldflatzinc(*new_env); 181 if (_compflags.verbose) { 182 log << " done (" << lasttime.stoptime() << ")" << std::endl; 183 } 184 } else { 185 new_env->flat()->compact(); 186 new_env->output()->compact(); 187 } 188 189 if (_compflags.verbose) { 190 log << " done (" << lasttime.stoptime() << ")" << std::endl; 191 } 192 193 return new_env; 194} 195 196CompilePass::~CompilePass(){}; 197 198} // namespace MiniZinc