MicroModelicaCCompiler  4.5.3
mmo_ir.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 "mmo_ir.hpp"
21 
22 #include <iterator>
23 
24 #include <ast/class.hpp>
25 #include <ast/composition.hpp>
26 #include <ast/element.hpp>
27 #include <ast/equation.hpp>
28 #include <ast/expression.hpp>
29 #include <ast/modification.hpp>
30 #include <ast/statement.hpp>
31 #include <ir/class.hpp>
32 #include <ir/expression.hpp>
33 #include <ir/helpers.hpp>
34 #include <ir/stored_definition.hpp>
35 #include <util/error.hpp>
36 #include <util/symbol_table.hpp>
37 #include <util/type.hpp>
38 #include <util/visitors/array_use.hpp>
39 #include <util/visitors/eval_init_exp.hpp>
40 #include <util/visitors/discrete_assignment.hpp>
41 
42 namespace MicroModelica {
43 using namespace Util;
44 namespace IR {
45 
46 /* MicroModelica Intermediate Representation */
47 
49  : _std(), _class(nullptr), _father_class(nullptr), _initialCode(false), _classModification(false), _compositionElement(false)
50 {
51 }
52 
54 
55 void MicroModelicaIR::visit(AST_Class x)
56 {
57  Error::instance().setClassName(*(x->name()));
58  AST_TypePrefix p = x->prefix();
59  if (p & CP_PACKAGE) {
60  _std.setPackage(*x->name());
61  _class = &(_std.package());
62  } else if ((p & CP_FUNCTION) || (p & CP_IMPURE) || (p & CP_PURE)) {
63  _function = Function(*x->name());
64  _class = &_function;
65  } else {
66  _std.setModel(*x->name());
67  _class = &(_std.model());
69  }
70 }
71 
72 void MicroModelicaIR::leave(AST_Class x)
73 {
74  _class = nullptr;
75  AST_TypePrefix p = x->prefix();
76  if ((p & CP_FUNCTION) || (p & CP_IMPURE) || (p & CP_PURE)) {
78  if (_father_class) {
80  }
81  } else if (p & CP_MODEL) {
82  _father_class = nullptr;
83  }
84 }
85 
86 void MicroModelicaIR::visit(AST_Composition x) {}
87 
88 void MicroModelicaIR::leave(AST_Composition x) {}
89 
90 void MicroModelicaIR::visit(AST_CompositionElement x) { _compositionElement = true; }
91 
92 void MicroModelicaIR::leave(AST_CompositionElement x) { _compositionElement = false; }
93 
94 void MicroModelicaIR::visit(AST_CompositionEqsAlgs x) { _initialCode = x->isInitial(); }
95 
96 void MicroModelicaIR::leave(AST_CompositionEqsAlgs x) { _initialCode = false; }
97 
98 void MicroModelicaIR::visit(AST_External_Function_Call x) { _class->insert(x); }
99 
100 void MicroModelicaIR::visit(AST_Element x)
101 {
102  ElementType e = x->elementType();
103  if (e == IMPORT) {
104  AST_Element_ImportClause i = x->getAsImportClause();
105  _class->insert(i->name());
106  } else if (e == COMPONENT) {
107  AST_Element_Component c = x->getAsComponent();
108  AST_TypePrefix tp = c->typePrefix();
109  AST_DeclarationListReverseIterator it;
110  AST_DeclarationList dl = c->nameList();
112  {
113  vector<int> size;
114  bool array = current_element(it)->hasIndexes();
115  if (array) {
116  EvalInitExp eval;
117  AST_ExpressionList elist = current_element(it)->indexes();
118  AST_ExpressionListIterator elistit;
119  foreach (elistit, elist) {
120  size.push_back(eval.apply(current_element(elistit)));
121  }
122  }
124  if (tp & TP_CONSTANT) {
125  Variable vi(newType_Integer(), tp, current_element(it)->modification(), nullptr, size, array);
126  _class->insert(current_element(it)->name(), vi, t);
127  } else {
128  Variable new_var;
129  if ((tp & TP_PARAMETER) && c->isInteger()) {
130  new_var = Variable(newType_Integer(), tp, current_element(it)->modification(), nullptr, size, array);
131  } else if (c->isString()) {
132  new_var = Variable(newType_String(), tp, current_element(it)->modification(), nullptr, size, array);
133  } else if ((tp & TP_DISCRETE) && c->isInteger()) {
134  new_var = Variable(newType_Integer(), tp, current_element(it)->modification(), nullptr, size, array);
135  } else {
136  new_var = Variable(newType_Real(), tp, current_element(it)->modification(), nullptr, size, array);
137  }
138  _class->insert(current_element(it)->name(), new_var, t);
139  }
140  }
141  } else if (e == ELCLASS) {
142  AST_Class c = x->getAsClassWrapper()->getClass();
143  c->accept(this);
144  }
145 }
146 
147 void MicroModelicaIR::visit(AST_Modification x)
148 {
149  if (x->modificationType() == MODASSIGN) {
150  Error::instance().add(x->lineNum(), EM_AST | EM_CLASS_DEFINITION, ER_Error, "Assign modifier.");
151  }
152  if (x->modificationType() == MODCLASS) {
153  _classModification = true;
154  }
155 }
156 
157 void MicroModelicaIR::leave(AST_Modification x)
158 {
159  if (x->modificationType() == MODCLASS) {
160  _classModification = false;
161  }
162 }
163 
164 void MicroModelicaIR::visit(AST_Comment x) {}
165 
166 AST_StatementList MicroModelicaIR::getStatementList(AST_EquationList eqs)
167 {
168  AST_StatementList stms = newAST_StatementList();
169  AST_EquationListIterator eqs_it;
170  foreach (eqs_it, eqs) {
171  AST_Statement stm = transformEquation(current_element(eqs_it));
172  if (stm) {
173  stms = AST_ListAppend(stms, stm);
174  }
175  }
176  return stms;
177 }
178 
179 bool MicroModelicaIR::checkForEquation(AST_Equation_For for_eq)
180 {
181  AST_EquationList for_eqs = for_eq->equationList();
182  AST_EquationListIterator eqs_it;
183  AST_StatementList when_stms = newAST_StatementList();
184  AST_EquationList split_for_eqs = newAST_EquationList();
185  foreach (eqs_it, for_eqs) {
186  if (current_element(eqs_it)->equationType() == EQWHEN) {
187  when_stms = AST_ListAppend(when_stms, transformWhenEquation(current_element(eqs_it)->getAsWhen()));
188  } else {
189  split_for_eqs = AST_ListAppend(split_for_eqs, current_element(eqs_it));
190  }
191  }
192  if (!when_stms->empty()) {
193  AST_Statement stm = newAST_Statement_For(for_eq->forIndexList(), when_stms);
194  visit(stm);
195  }
196  if (!split_for_eqs->empty()) {
197  AST_ForIndexList fil = for_eq->forIndexList();
198  AST_ForIndexListIterator it;
199  foreach (it, fil) {
200  visit(current_element(it));
201  }
202  AST_Equation eq = newAST_Equation_For(for_eq->forIndexList(), split_for_eqs);
203  _class->insert(eq);
204  }
205  return when_stms->empty();
206 }
207 
208 AST_Statement MicroModelicaIR::transformWhenEquation(AST_Equation_When when_eq)
209 {
210  AST_StatementList true_stms = getStatementList(when_eq->equationList());
211  AST_Statement_ElseList else_when_stms = newAST_Statement_ElseList();
212  AST_Equation_ElseList else_when_eqs = when_eq->equationElseWhen();
213  AST_Equation_ElseListIterator else_when_eqs_it;
214  foreach (else_when_eqs_it, else_when_eqs) {
215  AST_Equation_Else eq_else_when = current_element(else_when_eqs_it);
216  AST_StatementList current_else_when_stms = getStatementList(eq_else_when->equations());
217  AST_Statement_Else add_stm_else = newAST_Statement_Else(eq_else_when->condition(), current_else_when_stms);
218  else_when_stms = AST_ListAppend(else_when_stms, add_stm_else);
219  }
220  return newAST_Statement_When(when_eq->condition(), true_stms, else_when_stms, when_eq->comment());
221 }
222 
223 bool MicroModelicaIR::checkWhenEquation(AST_Equation eq)
224 {
225  AST_Statement stm = nullptr;
226  if (eq->equationType() == EQFOR) {
227  return checkForEquation(eq->getAsFor());
228  } else if (eq->equationType() == EQWHEN) {
229  stm = transformWhenEquation(eq->getAsWhen());
230  visit(stm);
231  return true;
232  }
233  return false;
234 }
235 
236 AST_Statement MicroModelicaIR::transformEquation(AST_Equation x)
237 {
238  AST_Statement stm = nullptr;
239  if (x->equationType() == EQEQUALITY) {
240  AST_Equation_Equality eqe = x->getAsEquality();
241  AST_Expression_ComponentReference lhs = eqe->left()->getAsComponentReference();
242  stm = newAST_Statement_Assign(lhs, eqe->right());
243  } else if (x->equationType() == EQCALL) {
244  AST_Equation_Call eq_call = x->getAsCall();
245  AST_Expression call = eq_call->call();
246  if (call->expressionType() == EXPCALL) {
247  AST_Expression_Call exp_call = call->getAsCall();
248  AST_Expression_ComponentReference output_name = newAST_Expression_ComponentReference();
249  AST_ExpressionList l = newAST_ExpressionList();
250  output_name = AST_Expression_ComponentReference_Add(output_name, newAST_String(exp_call->name()), l);
251  stm = newAST_Statement_OutputAssign(exp_call->outputArguments(), output_name, exp_call->arguments());
252  }
253  } else if (x->equationType() == EQFOR) {
254  AST_Equation_For for_eq = x->getAsFor();
255  AST_StatementList stms = getStatementList(for_eq->equationList());
256  stm = newAST_Statement_For(for_eq->forIndexList(), stms);
257  } else if (x->equationType() == EQIF) {
258  AST_Equation_If if_eq = x->getAsIf();
259  AST_StatementList true_stms = getStatementList(if_eq->equationList());
260  AST_StatementList else_stms = getStatementList(if_eq->equationElseList());
261  AST_Statement_ElseList else_if_stms = newAST_Statement_ElseList();
262  AST_Equation_ElseList else_if_eqs = if_eq->equationElseIf();
263  AST_Equation_ElseListIterator else_if_eqs_it;
264  foreach (else_if_eqs_it, else_if_eqs) {
265  AST_Equation_Else eq_else_if = current_element(else_if_eqs_it);
266  AST_StatementList current_else_if_stms = getStatementList(eq_else_if->equations());
267  AST_Statement_Else add_stm_else = newAST_Statement_Else(eq_else_if->condition(), current_else_if_stms);
268  else_if_stms = AST_ListAppend(else_if_stms, add_stm_else);
269  }
270  stm = newAST_Statement_If(if_eq->condition(), true_stms, else_if_stms, else_stms);
271  }
272  return stm;
273 }
274 
275 void MicroModelicaIR::visit(AST_Equation x)
276 {
277  if (_initialCode) {
279  return;
280  }
281  if (checkWhenEquation(x)) {
282  return;
283  }
284  if (x->equationType() == EQFOR) {
285  AST_ForIndexList fil = x->getAsFor()->forIndexList();
286  AST_ForIndexListIterator it;
287  foreach (it, fil) {
288  visit(current_element(it));
289  }
290  } else {
291  AST_Equation_Equality eqe = x->getAsEquality();
292  DiscreteAssignment da;
293  da.apply(eqe->left());
294  ArrayUse au;
295  au.apply(eqe->left());
296  au.apply(eqe->right());
297  }
298  _class->insert(x);
299 }
300 
301 void MicroModelicaIR::visit(AST_ForIndex x)
302 {
303  Variable vi(newType_Integer(), TP_FOR, nullptr, nullptr, vector<int>(1, 1), false);
304  _class->insert(*x->variable(), vi);
305 }
306 
307 void MicroModelicaIR::visit(AST_Equation_Else x) {}
308 
309 void MicroModelicaIR::visit(AST_Expression x) {}
310 
311 void MicroModelicaIR::visit(AST_Argument x)
312 {
313  if (x->argumentType() == AR_MODIFICATION) {
314  AST_Argument_Modification am = x->getAsModification();
315  if (am->hasModification() && _classModification == false) {
316  _class->insert(am);
317  }
318  }
319 }
320 
321 void MicroModelicaIR::visitForStms(AST_Statement_For for_stm)
322 {
323  AST_ForIndexList fil = for_stm->forIndexList();
324  AST_ForIndexListIterator it;
325  foreach (it, fil) {
327  }
328  AST_StatementList stms = for_stm->statements();
329  AST_StatementListIterator stm_it;
330  foreach (stm_it, stms) {
331  if (current_element(stm_it)->statementType() == STFOR) {
332  visitForStms(current_element(stm_it)->getAsFor());
333  }
334  if (current_element(stm_it)->statementType() == STWHEN) {
335  AST_StatementList when_stms = current_element(stm_it)->getAsWhen()->statements();
336  AST_StatementListIterator when_stm_it;
337  foreach (when_stm_it, when_stms) {
338  if (current_element(when_stm_it)->statementType() == STFOR) {
339  visitForStms(current_element(when_stm_it)->getAsFor());
340  }
341  }
342  }
343  }
344 }
345 
346 void MicroModelicaIR::visit(AST_Statement x)
347 {
348  if (x->statementType() == STFOR) {
349  visitForStms(x->getAsFor());
350  }
351  StatementArrayUse au;
352  au.apply(x);
354 }
355 
356 void MicroModelicaIR::leave(AST_Statement x) {}
357 
358 void MicroModelicaIR::visit(AST_Statement_Else x)
359 {
360  AST_StatementList stl = x->statements();
361  AST_StatementListIterator sti;
362  foreach (sti, stl) {
364  }
365 }
366 
367 void MicroModelicaIR::visit(AST_StoredDefinition x) {}
368 
369 void MicroModelicaIR::leave(AST_StoredDefinition x) { _std.postProcess(); }
370 
371 int MicroModelicaIR::apply(AST_Node x)
372 {
373  x->accept(this);
374  return Error::instance().errors();
375 }
376 } // namespace IR
377 } // namespace MicroModelica
newAST_Statement_Assign
AST_Statement newAST_Statement_Assign(AST_Expression_ComponentReference cr, AST_Expression exp)
Definition: ast_builder.cpp:567
equation.hpp
newAST_Equation_For
AST_Equation newAST_Equation_For(AST_ForIndexList ind, AST_EquationList eql)
Definition: ast_builder.cpp:420
MicroModelica::Util::Error::instance
static Error & instance()
Definition: error.hpp:128
EQWHEN
@ EQWHEN
Definition: ast_types.hpp:161
MicroModelica::IR::MicroModelicaIR::visitForStms
void visitForStms(AST_Statement_For for_stm)
Definition: mmo_ir.cpp:338
MicroModelica::IR::StoredDefinition::model
Model & model()
Definition: stored_definition.cpp:75
MODASSIGN
@ MODASSIGN
Definition: ast_types.hpp:189
MicroModelica::IR::MicroModelicaIR::leave
void leave(AST_Class x)
Definition: mmo_ir.cpp:89
newAST_Statement_ElseList
AST_Statement_ElseList newAST_Statement_ElseList()
Definition: ast_builder.cpp:489
MicroModelica::Util::Variable
Definition: symbol_table.hpp:75
MicroModelica::IR::MicroModelicaIR::checkForEquation
bool checkForEquation(AST_Equation_For for_eq)
Definition: mmo_ir.cpp:196
expression.hpp
newAST_Statement_If
AST_Statement newAST_Statement_If(AST_Expression cond, AST_StatementList true_st, AST_Statement_ElseList else_st, AST_StatementList false_st)
Definition: ast_builder.cpp:547
ELCLASS
@ ELCLASS
Definition: ast_types.hpp:159
symbol_table.hpp
newAST_Statement_Else
AST_Statement_Else newAST_Statement_Else(AST_Expression cond, AST_StatementList st)
Definition: ast_builder.cpp:545
MicroModelica::IR::DEC_LOCAL
@ DEC_LOCAL
Definition: class.hpp:92
element.hpp
EQIF
@ EQIF
Definition: ast_types.hpp:161
MicroModelica::IR::MicroModelicaIR::transformWhenEquation
AST_Statement transformWhenEquation(AST_Equation_When when_eq)
Definition: mmo_ir.cpp:225
TP_CONSTANT
@ TP_CONSTANT
Definition: ast_types.hpp:200
helpers.hpp
composition.hpp
CP_IMPURE
@ CP_IMPURE
Definition: ast_types.hpp:223
newType_Integer
Type_Integer newType_Integer()
Definition: type.cpp:56
EQFOR
@ EQFOR
Definition: ast_types.hpp:161
MicroModelica::IR::StoredDefinition::postProcess
void postProcess()
Definition: stored_definition.cpp:83
MicroModelica::IR::Class::insert
virtual void insert(string n)=0
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
newType_Real
Type_Real newType_Real()
Definition: type.cpp:45
newAST_EquationList
AST_EquationList newAST_EquationList()
Definition: ast_builder.cpp:151
MicroModelica::IR::MicroModelicaIR::checkWhenEquation
bool checkWhenEquation(AST_Equation eq)
Definition: mmo_ir.cpp:240
STFOR
@ STFOR
Definition: ast_types.hpp:191
TP_PARAMETER
@ TP_PARAMETER
Definition: ast_types.hpp:197
MicroModelica::Util::ER_Error
@ ER_Error
ER_Error.
Definition: error.hpp:122
MicroModelica::IR::MicroModelicaIR::_class
ClassPtr _class
Definition: mmo_ir.hpp:125
EM_CLASS_DEFINITION
#define EM_CLASS_DEFINITION
Definition: error.hpp:111
newAST_Statement_OutputAssign
AST_Statement newAST_Statement_OutputAssign(AST_ExpressionList out_vars, AST_Expression_ComponentReference funname, AST_ExpressionList args)
Definition: ast_builder.cpp:562
MicroModelica::IR::MicroModelicaIR::apply
int apply(AST_Node x)
Definition: mmo_ir.cpp:388
MicroModelica::IR::DEC_Type
DEC_Type
Definition: class.hpp:75
AST_TypePrefix
int AST_TypePrefix
Definition: ast_types.hpp:50
TP_FOR
@ TP_FOR
Definition: ast_types.hpp:201
type.hpp
MicroModelica::IR::MicroModelicaIR::transformEquation
AST_Statement transformEquation(AST_Equation eq)
Definition: mmo_ir.cpp:253
AST_ListAppend
list< T1 > * AST_ListAppend(list< T1 > *l, T1 e)
Definition: ast_types.hpp:240
MicroModelica::Util::Error::setClassName
void setClassName(std::string class_name)
Definition: error.cpp:38
MicroModelica::Util::Error::add
void add(int pos, unsigned int code, ER_Type t, const std::string message,...)
Definition: error.cpp:42
MicroModelica::IR::MicroModelicaIR::_initialCode
bool _initialCode
Definition: mmo_ir.hpp:127
newAST_StatementList
AST_StatementList newAST_StatementList()
Definition: ast_builder.cpp:481
MicroModelica::Util::Error::errors
int errors()
Definition: error.cpp:257
EXPCALL
@ EXPCALL
Definition: ast_types.hpp:173
foreachReverse
#define foreachReverse(it, list)
Definition: ast_types.hpp:36
MicroModelica::IR::StoredDefinition::addFunction
void addFunction(Function &f)
Definition: stored_definition.cpp:67
MicroModelica::IR::MicroModelicaIR::visit
void visit(AST_Class x)
Definition: mmo_ir.cpp:72
AR_MODIFICATION
@ AR_MODIFICATION
Definition: ast_types.hpp:206
MicroModelica::IR::MicroModelicaIR::_classModification
bool _classModification
Definition: mmo_ir.hpp:128
EQCALL
@ EQCALL
Definition: ast_types.hpp:161
MicroModelica::IR::MicroModelicaIR::_std
StoredDefinition _std
Definition: mmo_ir.hpp:124
newAST_Statement_When
AST_Statement newAST_Statement_When(AST_Expression cond, AST_StatementList sts, AST_Statement_ElseList else_st, AST_Comment c)
Definition: ast_builder.cpp:557
newAST_Expression_ComponentReference
AST_Expression_ComponentReference newAST_Expression_ComponentReference()
Definition: ast_builder.cpp:222
class.hpp
CP_PURE
@ CP_PURE
Definition: ast_types.hpp:222
ElementType
ElementType
Definition: ast_types.hpp:159
MicroModelica::IR::StoredDefinition::setModel
void setModel(string name)
Definition: stored_definition.cpp:63
newAST_Statement_For
AST_Statement newAST_Statement_For(AST_ForIndexList index, AST_StatementList st)
Definition: ast_builder.cpp:553
modification.hpp
MicroModelica
Definition: files.cpp:45
stored_definition.hpp
MODCLASS
@ MODCLASS
Definition: ast_types.hpp:189
MicroModelica::IR::MicroModelicaIR::_compositionElement
bool _compositionElement
Definition: mmo_ir.hpp:129
MicroModelica::IR::MicroModelicaIR::getStatementList
AST_StatementList getStatementList(AST_EquationList eqs)
Definition: mmo_ir.cpp:183
CP_PACKAGE
@ CP_PACKAGE
Definition: ast_types.hpp:224
TP_DISCRETE
@ TP_DISCRETE
Definition: ast_types.hpp:196
MicroModelica::IR::MicroModelicaIR::~MicroModelicaIR
~MicroModelicaIR()
Definition: mmo_ir.cpp:70
EQEQUALITY
@ EQEQUALITY
Definition: ast_types.hpp:161
CP_FUNCTION
@ CP_FUNCTION
Definition: ast_types.hpp:225
EM_AST
#define EM_AST
Definition: error.hpp:65
MicroModelica::IR::MicroModelicaIR::_function
Function _function
Definition: mmo_ir.hpp:130
STWHEN
@ STWHEN
Definition: ast_types.hpp:191
newAST_ExpressionList
AST_ExpressionList newAST_ExpressionList(AST_Expression e)
Definition: ast_builder.cpp:132
newType_String
Type_String newType_String()
Definition: type.cpp:74
CP_MODEL
@ CP_MODEL
Definition: ast_types.hpp:215
mmo_ir.hpp
MicroModelica::IR::DEC_PUBLIC
@ DEC_PUBLIC
Definition: class.hpp:92
COMPONENT
@ COMPONENT
Definition: ast_types.hpp:159
IMPORT
@ IMPORT
Definition: ast_types.hpp:159
MicroModelica::IR::MicroModelicaIR::MicroModelicaIR
MicroModelicaIR(string name)
Definition: mmo_ir.cpp:65
MicroModelica::IR::StoredDefinition::package
Package & package()
Definition: stored_definition.cpp:77
class.hpp
current_element
#define current_element(it)
Definition: ast_types.hpp:34
MicroModelica::IR::MicroModelicaIR::_father_class
ClassPtr _father_class
Definition: mmo_ir.hpp:126
MicroModelica::IR::StoredDefinition::setPackage
void setPackage(string name)
Definition: stored_definition.cpp:65
error.hpp
expression.hpp
newAST_String
AST_String newAST_String(string s)
Definition: ast_builder.cpp:57
statement.hpp