MicroModelicaCCompiler  4.5.3
statement.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 #include <sstream>
20 
21 #include <ast/ast_builder.hpp>
22 #include <ast/statement.hpp>
23 #include <ir/helpers.hpp>
24 #include <ir/statement.hpp>
25 #include <util/model_config.hpp>
26 #include <util/util.hpp>
28 #include <util/visitors/called_functions.hpp>
29 
30 namespace MicroModelica {
31 using namespace Util;
32 namespace IR {
33 
34 Statement::Statement(AST_Statement stm, Option<Range> range, bool initial, const string& block)
35  : _stm(stm), _range(range), _block(block), _lhs_assignments(), _rhs_assignments(), _lhs_discretes(), _lhs_states()
36 {
37  initialize();
38 }
39 
40 Statement::Statement(AST_Statement stm, bool initial, const string& block)
41  : _stm(stm), _range(), _block(block), _lhs_assignments(), _rhs_assignments(), _lhs_discretes(), _lhs_states()
42 {
43  initialize();
44 }
45 
46 void Statement::initialize()
47 {
48  StatementCalledFunctions cf;
49  setRange();
50  _calledFunctions = cf.apply(_stm);
51  _lhs_assignments = generateExps(STATEMENT::LHS);
52  _rhs_assignments = generateExps(STATEMENT::RHS);
53  _lhs_discretes = generateExps(STATEMENT::LHS_DISCRETES);
54  _lhs_states = generateExps(STATEMENT::LHS_STATES);
55 }
56 
57 void Statement::setRange()
58 {
59  // In case of for statements, the statement can have a range even if
60  // defined in a single event, so change the range accordingly.
61  if (_stm->statementType() == STFOR) {
62  AST_Statement_For for_stm = _stm->getAsFor();
63  _range = Range(for_stm);
64  }
65 }
66 
67 ExpressionList Statement::generateExps(STATEMENT::AssignTerm asg)
68 {
69  ExpressionList asgs;
70  switch (_stm->statementType()) {
71  case STIF: {
72  AST_Statement_If sti = _stm->getAsIf();
73  AST_StatementList stl = sti->statements();
74  AST_StatementListIterator stlit;
75  if (asg == STATEMENT::RHS) {
76  asgs.push_back(Expression(sti->condition()));
77  } else if (asg == STATEMENT::LHS_DISCRETES || asg == STATEMENT::LHS_STATES) {
78  asgs.push_back(emptyRef());
79  }
80  foreach (stlit, stl) {
81  Statement st(current_element(stlit));
82  asgs.splice(asgs.end(), st.generateExps(asg));
83  }
84  AST_Statement_ElseList stelsel = sti->else_if();
85  AST_Statement_ElseListIterator stelselit;
86  foreach (stelselit, stelsel) {
87  if (asg == STATEMENT::RHS) {
88  asgs.push_back(Expression(current_element(stelselit)->condition()));
89  } else if (asg == STATEMENT::LHS_DISCRETES || asg == STATEMENT::LHS_STATES) {
90  asgs.push_back(emptyRef());
91  }
92  stl = current_element(stelselit)->statements();
93  foreach (stlit, stl) {
94  Statement st(current_element(stlit));
95  asgs.splice(asgs.end(), st.generateExps(asg));
96  }
97  }
98  stl = sti->else_statements();
99  if (!stl->empty()) {
100  foreach (stlit, stl) {
101  Statement st(current_element(stlit));
102  asgs.splice(asgs.end(), st.generateExps(asg));
103  }
104  }
105  break;
106  }
107  case STASSIGN: {
108  if (asg == STATEMENT::LHS || asg == STATEMENT::LHS_DISCRETES || asg == STATEMENT::LHS_STATES) {
109  asgs.push_back(Expression(_stm->getAsAssign()->lhs()));
110  } else {
111  asgs.push_back(Expression(_stm->getAsAssign()->exp()));
112  }
113  break;
114  }
115  case STFOR: {
116  AST_Statement_For stf = _stm->getAsFor();
117  AST_StatementList stms = stf->statements();
118  AST_StatementListIterator stmit;
119  Range range(stf);
120  foreach (stmit, stms) {
121  Statement st(current_element(stmit), range);
122  asgs.splice(asgs.end(), st.generateExps(asg));
123  }
124  break;
125  }
126  case STOUTASSING: {
127  AST_Statement_OutputAssigment out_stm = _stm->getAsOutputAssigment();
128  if (asg == STATEMENT::LHS || asg == STATEMENT::LHS_DISCRETES || asg == STATEMENT::LHS_STATES) {
129  AST_ExpressionList exps = out_stm->out_expressions();
130  AST_ExpressionListIterator exp_it;
131  foreach (exp_it, exps) {
132  asgs.push_back(Expression(current_element(exp_it)));
133  }
134  } else {
135  AST_Expression call_exp = newAST_Expression_Call(newAST_String(out_stm->functionName()), nullptr, out_stm->arguments());
136  asgs.push_back(Expression(call_exp));
137  }
138  break;
139  }
140  default:
141  break;
142  }
143  return asgs;
144 }
145 
146 bool Statement::checkStateAssignment(Expression exp) const
147 {
148  assert(exp.isReference());
149  Option<Variable> var = exp.reference();
150  assert(var);
151  return var->isState();
152 }
153 
154 bool Statement::isForStatement() const { return _stm->statementType() == STFOR; }
155 
156 string Statement::printAssignment(AST_Statement_Assign asg) const
157 {
158  stringstream code;
159  switch (asg->exp()->expressionType()) {
160  case EXPCALLARG:
161  code << "CMD_terminate();";
162  break;
163  default: {
164  Expression lhs(asg->lhs());
165  Expression rhs(asg->exp());
166  bool state_assignment = checkStateAssignment(lhs);
167  if (state_assignment) {
168  ModelConfig::instance().setReinit(true);
169  }
170  code << lhs << " = " << rhs << ";";
171  if (state_assignment) {
172  ModelConfig::instance().setReinit(false);
173  }
174  break;
175  }
176  }
177  return code.str();
178 }
179 
180 string Statement::print() const
181 {
182  stringstream buffer;
183  switch (_stm->statementType()) {
184  case STIF: {
185  AST_Statement_If sti = _stm->getAsIf();
186  Expression ifcond(sti->condition());
187  buffer << _block << "if(" << ifcond << ") {" << endl;
188  AST_StatementList stl = sti->statements();
189  AST_StatementListIterator stlit;
190  foreach (stlit, stl) {
191  Statement st(current_element(stlit), false, _block + TAB);
192  buffer << st << endl;
193  }
194  buffer << _block << "}";
195  AST_Statement_ElseList stelsel = sti->else_if();
196  AST_Statement_ElseListIterator stelselit;
197  foreach (stelselit, stelsel) {
198  Expression eifcond(current_element(stelselit)->condition());
199  buffer << _block << "else if(" << eifcond << ") {" << endl;
200  stl = current_element(stelselit)->statements();
201  foreach (stlit, stl) {
202  Statement st(current_element(stlit), false, _block + TAB);
203  buffer << st << endl;
204  }
205  buffer << _block << "}";
206  }
207  stl = sti->else_statements();
208  if (!stl->empty()) {
209  buffer << _block << "else {" << endl;
210  foreach (stlit, stl) {
211  Statement st(current_element(stlit), false, _block + TAB);
212  buffer << st << endl;
213  }
214  buffer << _block << "}";
215  }
216  break;
217  }
218  case STASSIGN: {
219  buffer << _block << printAssignment(_stm->getAsAssign());
220  break;
221  }
222  case STFOR: {
223  AST_Statement_For stf = _stm->getAsFor();
224  Range range(stf);
225  buffer << range;
226  AST_StatementList stms = stf->statements();
227  AST_StatementListIterator stmit;
228  foreach (stmit, stms) {
229  Statement st(current_element(stmit), false, range.block());
230  buffer << st << endl;
231  }
232  buffer << range.end();
233  break;
234  }
235  case STOUTASSING: {
236  AST_Statement_OutputAssigment out_stm = _stm->getAsOutputAssigment();
237  AST_Expression call_exp =
238  newAST_Expression_Call(newAST_String(out_stm->functionName()), nullptr, out_stm->arguments(), out_stm->out_expressions());
239  Expression call(call_exp);
240  buffer << call << ";";
241  break;
242  }
243  default:
244  break;
245  }
246  return buffer.str();
247 }
248 
249 bool Statement::isAssignment() const { return _stm->statementType() == STASSIGN; }
250 
251 Expression Statement::emptyRef()
252 {
253  AST_Expression lhs = newAST_Expression_ComponentReferenceExp(newAST_String("dummy"));
254  return Expression(lhs);
255 }
256 
257 ExpressionList Statement::assignments(STATEMENT::AssignTerm asg) const
258 {
259  assert(asg != STATEMENT::LHS_DISCRETES);
260  switch (asg) {
261  case STATEMENT::LHS:
262  return _lhs_assignments;
263  case STATEMENT::RHS:
264  return _rhs_assignments;
265  default:
266  return ExpressionList();
267  }
268  return ExpressionList();
269 }
270 
271 bool Statement::autonomous() const
272 {
273  bool autonomous = true;
274  for (const auto& exp : _rhs_assignments) {
275  autonomous = autonomous && exp.autonomous();
276  }
277  return autonomous;
278 }
279 
280 std::ostream& operator<<(std::ostream& out, const Statement& s) { return out << s.print(); }
281 } // namespace IR
282 } // namespace MicroModelica
MicroModelica::IR::Range
Definition: index.hpp:164
ast_builder.hpp
MicroModelica::IR::STATEMENT::LHS
@ LHS
Definition: statement.hpp:51
EXPCALLARG
@ EXPCALLARG
Definition: ast_types.hpp:171
helpers.hpp
Option
Definition: util_types.hpp:32
model_config.hpp
newAST_Expression_ComponentReferenceExp
AST_Expression newAST_Expression_ComponentReferenceExp(AST_String s)
Definition: ast_builder.cpp:198
MicroModelica::IR::Statement::Statement
Statement()
Definition: statement.hpp:58
STFOR
@ STFOR
Definition: ast_types.hpp:191
MicroModelica::IR::Expression
Definition: expression.hpp:64
MicroModelica::IR::ExpressionList
list< Expression > ExpressionList
Definition: expression.hpp:95
MicroModelica::IR::STATEMENT::RHS
@ RHS
Definition: statement.hpp:51
MicroModelica::IR::operator<<
std::ostream & operator<<(std::ostream &out, const Statement &s)
Definition: statement.cpp:297
MicroModelica::IR::STATEMENT::AssignTerm
AssignTerm
Definition: statement.hpp:51
TAB
#define TAB
Definition: util.hpp:79
STASSIGN
@ STASSIGN
Definition: ast_types.hpp:191
STOUTASSING
@ STOUTASSING
Definition: ast_types.hpp:191
STIF
@ STIF
Definition: ast_types.hpp:191
process_statement.hpp
block
int block
Definition: ast_builder.cpp:41
MicroModelica
Definition: files.cpp:45
MicroModelica::IR::STATEMENT::LHS_STATES
@ LHS_STATES
Definition: statement.hpp:51
MicroModelica::IR::STATEMENT::LHS_DISCRETES
@ LHS_DISCRETES
Definition: statement.hpp:51
MicroModelica::IR::Statement
Definition: statement.hpp:54
MicroModelica::IR::Statement::generateExps
ExpressionList generateExps(STATEMENT::AssignTerm asg)
Definition: statement.cpp:84
newAST_Expression_Call
AST_Expression newAST_Expression_Call(AST_String name, AST_String rest, AST_ExpressionList args)
Definition: ast_builder.cpp:331
MicroModelica::IR::Statement::print
string print() const
Definition: statement.cpp:197
statement.hpp
current_element
#define current_element(it)
Definition: ast_types.hpp:34
util.hpp
newAST_String
AST_String newAST_String(string s)
Definition: ast_builder.cpp:57
statement.hpp