MicroModelicaCCompiler  4.5.3
util.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  This file is part of QSS Solver.
4 
5  QSS Solver is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  QSS Solver is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with QSS Solver. If not, see <http://www.gnu.org/licenses/>.
17 
18  ******************************************************************************/
19 
20 #include "util.hpp"
21 
22 #include <stddef.h>
23 #include <cstdlib>
24 #include <iterator>
25 #include <sstream>
26 #include <utility>
27 
28 #include "compile_flags.hpp"
29 #include "error.hpp"
31 #include <ir/class.hpp>
32 #include <ir/expression.hpp>
33 #include <ir/equation.hpp>
34 #include <ir/helpers.hpp>
35 #include <ir/index.hpp>
36 #include "model_config.hpp"
37 #include "symbol_table.hpp"
38 
39 namespace MicroModelica {
40 using namespace IR;
41 namespace Util {
42 
44  : _language_especification("C"), _flags(), _compiled_functions(), _file_name(), _ids(0), _package_functions(), _package_prefix()
45 {
46  _annotations.insert(pair<string, int>("StartTime", 0));
47  _annotations.insert(pair<string, int>("StopTime", 1));
48  _annotations.insert(pair<string, int>("Tolerance", 2));
49  _annotations.insert(pair<string, int>("AbsTolerance", 3));
50  _annotations.insert(pair<string, int>("StepSize", 4));
51  _binop[BINOPOR] = "||";
52  _binop[BINOPAND] = "&&";
53  _binop[BINOPLOWER] = "<";
54  _binop[BINOPLOWEREQ] = "<=";
55  _binop[BINOPGREATER] = ">";
56  _binop[BINOPGREATEREQ] = ">=";
57  _binop[BINOPCOMPNE] = "!=";
58  _binop[BINOPCOMPEQ] = "==";
59  _binop[BINOPADD] = "+";
60  _binop[BINOPELADD] = "+";
61  _binop[BINOPSUB] = "-";
62  _binop[BINOPELSUB] = "-";
63  _binop[BINOPDIV] = "/";
64  _binop[BINOPELDIV] = "/";
65  _binop[BINOPMULT] = "*";
66  _binop[BINOPELMULT] = "*";
67  _binop[BINOPEXP] = "^";
68  _binop[BINOPELEXP] = "^";
69  addCompiledFunctions(BuiltInFunction::instance().functions());
70 }
71 
72 Utils::~Utils() {}
73 
74 string Utils::trimString(string str)
75 {
76  // trim trailing spaces
77  string ret = str;
78  size_t endpos = ret.find_last_not_of(" \t");
79  if (string::npos != endpos) {
80  ret = ret.substr(0, endpos + 1);
81  }
82 
83  // trim leading spaces
84  size_t startpos = ret.find_first_not_of(" \t");
85  if (string::npos != startpos) {
86  ret = ret.substr(startpos);
87  }
88  return ret;
89 }
90 
91 string Utils::languageEspecification() { return _language_especification; }
92 
93 void Utils::setCompileFlags(CompileFlags flags) { _flags = flags; }
94 
95 bool Utils::checkTypeString(string t)
96 {
97  if (t != "Integer" && t != "Real" && t != "Boolean") {
98  return false;
99  }
100  return true;
101 }
102 
103 bool Utils::checkExperimentAnnotations(string *annotation)
104 {
105  map<string, int>::iterator it = _annotations.find(*annotation);
106  return it != _annotations.end();
107 }
108 
109 string Utils::opString(BinOpType bot) { return _binop[bot]; }
110 
111 string Utils::getVarName(string name)
112 {
113  string ret;
114  int ub = name.length() - 1;
115  for (int i = 0; i < ub; i++) {
116  ret += name[i];
117  }
118  return ret;
119 }
120 
121 string Utils::iteratorVar(int dim)
122 {
123  stringstream buffer;
124  buffer << "_d" << dim + 1;
125  return buffer.str();
126 }
127 
128 SymbolTable Utils::getValue(fstream *package, string token)
129 {
130  SymbolTable ret;
131  string line;
132  while (getline(*package, line)) {
133  if (!line.compare(token)) {
134  break;
135  }
136  ret.insert(line, line);
137  }
138  return ret;
139 }
140 
141 Option<CompiledPackage> Utils::readPackage(string file_name, bool full_path, string package_name)
142 {
143  fstream package;
144  string name;
145  string compiled_package_name = file_name;
146  if (full_path) {
147  name = file_name;
148  assert(!compiled_package_name.empty());
149  compiled_package_name = package_name;
150  } else {
151  string pname = packageName(file_name);
152  name = packagePath(pname + ".c");
153  name.append(pname).append(".moo");
154  }
155  package.open(name.c_str());
156  if (package.good()) {
157  string line;
159  ImportTable objects;
160  CompiledPackage cp(compiled_package_name);
161  string fname;
162  string prefix = cp.prefix();
163  string derivative;
164  string includeDir;
165  string libraryDir;
166  SymbolTable libraries;
167  while (getline(package, line)) {
168  if (!line.compare("DEPENDENCES")) {
169  objects = getValue(&package, "ENDDEPENDENCES");
170  } else if (!line.compare("FUNCTION")) {
171  fname = getValue(&package, "ENDFUNCTION").first();
172  } else if (!line.compare("DERIVATIVE")) {
173  derivative = getValue(&package, "ENDDERIVATIVE").first();
174  } else if (!line.compare("INCLUDEDIRECTORY")) {
175  includeDir = getValue(&package, "ENDINCLUDEDIRECTORY").first();
176  } else if (!line.compare("LIBRARYDIRECTORY")) {
177  libraryDir = getValue(&package, "ENDLIBRARYDIRECTORY").first();
178  } else if (!line.compare("LIBRARIES")) {
179  libraries = getValue(&package, "ENDLIBRARIES");
180  } else if (!line.compare("ENDDEFINITION")) {
181  CompiledFunction fi(fname, includeDir, libraryDir, libraries, prefix);
182  cft.insert(fname, fi);
183  }
184  }
185  package.close();
186  cp.setObjects(objects);
187  cp.setDefinitions(cft);
188  return Option<CompiledPackage>(cp);
189  }
190  return Option<CompiledPackage>();
191 }
192 
193 bool Utils::readPackage(string fileName, CompiledPackageTable &pt)
194 {
195  Option<CompiledPackage> cp = readPackage(fileName);
196  if (!cp) {
197  return false;
198  }
199  pt.insert(cp.get().name(), cp.get());
200  return true;
201 }
202 
203 bool Utils::searchCompiledPackage(string pname, CompileFlags flags) { return !packagePath(packageName(pname), flags, ".moo").empty(); }
204 
205 bool Utils::checkCodeFiles(string name, string ext)
206 {
207  if (!ext.compare(".mo")) {
208  return true;
209  }
210  ifstream h((name + ".h").c_str());
211  ifstream c((name + ".c").c_str());
212  if (h.good() && c.good()) {
213  h.close();
214  c.close();
215  return true;
216  }
217  return false;
218 }
219 
220 string Utils::packagePath(string name)
221 {
222  list<string> objs = _flags.objects();
223  for (list<string>::iterator it = objs.begin(); it != objs.end(); it++) {
224  string i = *it;
225  string p = *it;
226  size_t found = i.rfind("/");
227  if (found != std::string::npos) {
228  p.erase(p.begin() + found + 1, p.end());
229  i.erase(i.begin(), i.begin() + found + 1);
230  }
231  if (!i.compare(name)) {
232  return p;
233  }
234  }
235  return "";
236 }
237 
238 string Utils::generatePath(std::string path, string file_name)
239 {
240  if (path.back() == '/') {
241  return path + file_name;
242  }
243  return path + SLASH + file_name;
244 }
245 
246 string Utils::packagePath(string pname, CompileFlags flags, string ext)
247 {
248  string fname = flags.path();
249  fname.append(pname + ext);
250  ifstream f(fname.c_str());
251  if (f.good() && checkCodeFiles(flags.path() + pname, ext)) {
252  f.close();
253  return flags.path();
254  } else {
255  f.close();
256  if (flags.hasOutputFile()) {
257  fname = flags.outputFilePath();
258  fname.append(pname + ext);
259  f.open(fname.c_str());
260  if (f.good() && checkCodeFiles(flags.outputFilePath() + SLASH + pname, ext)) {
261  f.close();
262  return flags.outputFilePath();
263  }
264  f.close();
265  }
266  list<string> paths = flags.libraryPaths();
267  for (list<string>::iterator it = paths.begin(); it != paths.end(); it++) {
268  fname = *it;
269  fname.append(SLASH + pname + ext);
270  f.open(fname.c_str());
271  if (f.good() && checkCodeFiles(*it + SLASH + pname, ext)) {
272  f.close();
273  return *it;
274  }
275  f.close();
276  }
277  }
278  return "";
279 }
280 
281 string Utils::packageName(string name)
282 {
283  size_t f = name.find("pkg_");
284  if (f == string::npos) {
285  return "pkg_" + name;
286  }
287  return name;
288 }
289 
290 string Utils::environmentVariable(string ev)
291 {
292  char *li = getenv(ev.c_str());
293  if (li != nullptr) {
294  return li;
295  }
296  return "";
297 }
298 
299 string Utils::getFilePath(string file)
300 {
301  _file_name = file;
302  string path = file;
303  size_t found = path.rfind("/");
304  if (found != std::string::npos) {
305  path.erase(path.begin() + found + 1, path.end());
306  }
307  return path;
308 }
309 
310 string Utils::getFileName(string file)
311 {
312  string fn = file;
313  size_t f = fn.rfind("/");
314  if (f == std::string::npos) {
315  return file;
316  }
317  fn.erase(fn.begin(), fn.begin() + f + 1);
318  return fn;
319 }
320 
321 string Utils::baseFileName(string file)
322 {
323  string base_file = getFileName(file);
324  size_t f = base_file.rfind(".");
325  if (f == std::string::npos) {
326  return base_file;
327  }
328  base_file.erase(base_file.begin() + f, base_file.end());
329  return base_file;
330 }
331 
332 CompiledFunctionTable Utils::compiledFunctions() { return _compiled_functions; }
333 
334 void Utils::addCompiledFunction(CompiledFunction f) { _compiled_functions.insert(f.name(), f); }
335 
336 void Utils::addCompiledFunctions(CompiledFunctionTable fs) { _compiled_functions.merge(fs); }
337 
338 bool Utils::checkCompiledFunctions(string name)
339 {
340  Option<CompiledFunction> cf = _compiled_functions[name];
341  return cf.is_initialized();
342 }
343 
344 bool Utils::checkBuiltInFunctions(string name) { return BuiltInFunction::instance().lookup(name); }
345 
346 Variable Utils::variable(AST_Expression exp)
347 {
348  string var_name;
349  ExpressionType type = exp->expressionType();
350  if (type == EXPCOMPREF) {
351  AST_Expression_ComponentReference var_exp = exp->getAsComponentReference();
352  var_name = *AST_ListFirst(var_exp->names());
353  } else if (type == EXPDERIVATIVE) {
354  AST_Expression_Derivative der = exp->getAsDerivative();
355  AST_Expression args = AST_ListFirst(der->arguments());
356  assert(args->expressionType() == EXPCOMPREF);
357  AST_Expression_ComponentReference var_exp = args->getAsComponentReference();
358  var_name = *AST_ListFirst(var_exp->names());
359  }
360  Option<Variable> var = ModelConfig::instance().lookup(var_name);
361  if (!var) {
362  Error::instance().add(exp->lineNum(), EM_IR | EM_VARIABLE_NOT_FOUND, ER_Error, "utils.cpp:362 %s", var_name.c_str());
363  }
364  return var.get();
365 }
366 
367 Expression Utils::variableExpression(string name, Option<IR::Range> range)
368 {
369  AST_Expression_ComponentReference var = newAST_Expression_ComponentReference();
370  if (range) {
371  RangeDefinitionTable ranges = range->definition();
372  AST_ExpressionList l = newAST_ExpressionList();
373  int dim = 0;
374  for (auto r : ranges) {
375  string idx_var = range->iterator(dim++);
376  AST_Expression idx = newAST_Expression_ComponentReferenceExp(newAST_String(idx_var));
377  l = AST_ListAppend(l, idx);
378  }
380  }
381  return Expression(var);
382 }
383 
384 string Utils::tabs(int t)
385 {
386  string tab;
387  for (int i = 0; i < t; i++) {
388  tab.append(TAB);
389  }
390  return tab;
391 }
392 
393 CompileFlags Utils::compileFlags() { return _flags; }
394 
395 IR::FunctionTable Utils::packageFunctions() { return _package_functions; }
396 
397 void Utils::setPackageFunctions(IR::FunctionTable package_functions) { _package_functions = package_functions; }
398 
399 string Utils::packagePrefix() { return _package_prefix; }
400 
401 void Utils::setPackagePrefix(string package_prefix) { _package_prefix = package_prefix; }
402 
403 } // namespace Util
404 } // namespace MicroModelica
BINOPEXP
@ BINOPEXP
Definition: ast_types.hpp:154
ModelTable< std::string, std::string >
BINOPAND
@ BINOPAND
Definition: ast_types.hpp:139
EXPCOMPREF
@ EXPCOMPREF
Definition: ast_types.hpp:165
BINOPCOMPEQ
@ BINOPCOMPEQ
Definition: ast_types.hpp:145
MicroModelica::Util::Variable
Definition: symbol_table.hpp:75
index.hpp
MicroModelica::IR::CompiledPackageTable
ModelTable< std::string, CompiledPackage > CompiledPackageTable
Definition: helpers.hpp:141
expression.hpp
BINOPELEXP
@ BINOPELEXP
Definition: ast_types.hpp:155
BINOPGREATER
@ BINOPGREATER
Definition: ast_types.hpp:142
MicroModelica::Util::CompileFlags
Definition: compile_flags.hpp:65
symbol_table.hpp
BINOPELMULT
@ BINOPELMULT
Definition: ast_types.hpp:153
BINOPELADD
@ BINOPELADD
Definition: ast_types.hpp:147
ExpressionType
ExpressionType
Definition: ast_types.hpp:163
helpers.hpp
Option
Definition: util_types.hpp:32
BINOPLOWER
@ BINOPLOWER
Definition: ast_types.hpp:140
BINOPMULT
@ BINOPMULT
Definition: ast_types.hpp:152
AST_Expression_ComponentReference_Add
AST_Expression_ComponentReference AST_Expression_ComponentReference_Add(AST_Expression_ComponentReference cr, AST_String s, AST_ExpressionList subs)
Definition: ast_builder.cpp:236
model_config.hpp
newAST_Expression_ComponentReferenceExp
AST_Expression newAST_Expression_ComponentReferenceExp(AST_String s)
Definition: ast_builder.cpp:198
BINOPELDIV
@ BINOPELDIV
Definition: ast_types.hpp:151
EXPDERIVATIVE
@ EXPDERIVATIVE
Definition: ast_types.hpp:167
MicroModelica::IR::Expression
Definition: expression.hpp:64
MicroModelica::Util::ER_Error
@ ER_Error
ER_Error.
Definition: error.hpp:122
BINOPSUB
@ BINOPSUB
Definition: ast_types.hpp:148
AST_ListAppend
list< T1 > * AST_ListAppend(list< T1 > *l, T1 e)
Definition: ast_types.hpp:240
BINOPOR
@ BINOPOR
Definition: ast_types.hpp:138
BINOPGREATEREQ
@ BINOPGREATEREQ
Definition: ast_types.hpp:143
equation.hpp
SLASH
#define SLASH
Definition: util.hpp:70
MicroModelica::Util::Utils::Utils
Utils()
Definition: util.cpp:60
MicroModelica::IR::CompiledFunctionTable
ModelTable< std::string, CompiledFunction > CompiledFunctionTable
Definition: helpers.hpp:117
TAB
#define TAB
Definition: util.hpp:79
EM_VARIABLE_NOT_FOUND
#define EM_VARIABLE_NOT_FOUND
Definition: error.hpp:71
AST_ListFirst
T1 AST_ListFirst(list< T1 > *l)
Definition: ast_types.hpp:271
compile_flags.hpp
BINOPDIV
@ BINOPDIV
Definition: ast_types.hpp:150
newAST_Expression_ComponentReference
AST_Expression_ComponentReference newAST_Expression_ComponentReference()
Definition: ast_builder.cpp:222
EM_IR
#define EM_IR
Definition: error.hpp:66
MicroModelica
Definition: files.cpp:45
BINOPCOMPNE
@ BINOPCOMPNE
Definition: ast_types.hpp:144
built_in_functions.hpp
ModelTable::insert
void insert(Key k, Value v)
Definition: table.hpp:48
BINOPLOWEREQ
@ BINOPLOWEREQ
Definition: ast_types.hpp:141
BINOPADD
@ BINOPADD
Definition: ast_types.hpp:146
BINOPELSUB
@ BINOPELSUB
Definition: ast_types.hpp:149
BinOpType
BinOpType
Definition: ast_types.hpp:137
newAST_ExpressionList
AST_ExpressionList newAST_ExpressionList(AST_Expression e)
Definition: ast_builder.cpp:132
MicroModelica::IR::FunctionTable
ModelTable< std::string, Function > FunctionTable
Definition: class.hpp:130
class.hpp
util.hpp
error.hpp
MicroModelica::IR::CompiledPackage
Definition: helpers.hpp:119
newAST_String
AST_String newAST_String(string s)
Definition: ast_builder.cpp:57