libutap  0.93
Uppaal Timed Automata Parser
statementbuilder.cpp
Go to the documentation of this file.
1 // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 
3 /* libutap - Uppaal Timed Automata Parser.
4  Copyright (C) 2002-2006 Uppsala University and Aalborg University.
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public License
8  as published by the Free Software Foundation; either version 2.1 of
9  the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  USA
20 */
21 
22 #include "utap/statementbuilder.h"
23 
24 #include <vector>
25 #include <climits>
26 #include <cmath>
27 #include <cstdio>
28 #include <cassert>
29 #include <cinttypes>
30 #include <stdexcept>
31 #include <sstream>
32 #include <boost/tuple/tuple.hpp>
33 
34 using namespace UTAP;
35 using namespace Constants;
36 
37 using std::vector;
38 using std::pair;
39 using std::make_pair;
40 using std::min;
41 using std::max;
42 using std::string;
43 
45  : ExpressionBuilder(system)
46 {
47  currentFun = NULL;
48  currentTemplate = NULL;
50 }
51 
53 {
54  for (auto b: blocks) delete b;
55 }
56 
58  std::set<symbol_t> &dependencies, expression_t expr)
59 {
60  std::set<symbol_t> symbols;
61  expr.collectPossibleReads(symbols);
62  while (!symbols.empty())
63  {
64  symbol_t s = *symbols.begin();
65  symbols.erase(s);
66  if (dependencies.find(s) == dependencies.end())
67  {
68  dependencies.insert(s);
69  if (s.getData())
70  {
71  variable_t *v = static_cast<variable_t*>(s.getData());
72  v->expr.collectPossibleReads(symbols);
73  }
74  }
75  }
76 }
77 
79  std::set<symbol_t> &dependencies, type_t type)
80 {
81  if (type.getKind() == RANGE)
82  {
83  expression_t lower, upper;
84  boost::tie(lower, upper) = type.getRange();
85  collectDependencies(dependencies, lower);
86  collectDependencies(dependencies, upper);
87  collectDependencies(dependencies, type[0]);
88  }
89  else
90  {
91  for (size_t i = 0; i < type.size(); i++)
92  {
93  collectDependencies(dependencies, type[i]);
94  }
95  }
96 }
97 
99 {
100  /* Pop array size of fragments stack.
101  */
102  expression_t expr = fragments[0];
103  fragments.pop();
104 
105  /* Create type.
106  */
107  exprNat(0);
108  fragments.push(expr);
109  exprNat(1);
110  exprBinary(MINUS);
112  typeArrayOfType(n + 1);
113 }
114 
116 {
117  type_t size = typeFragments[0];
118  typeFragments.pop();
119  typeFragments[n - 1] =
121 
122  /* If template local declaration, then mark all symbols in 'size'
123  * and those that they depend on as restricted. Otherwise we would
124  * not be able to compute the offset of a process in a set of
125  * processes.
126  */
127  if (currentTemplate)
128  {
130  }
131 
132  if ((!size.isInteger() && !size.isScalar()) || !size.is(RANGE))
133  {
134  handleError("$Array_must_be_defined_over_an_integer_range_or_a_scalar_set");
135  }
136 }
137 
143 void StatementBuilder::typeStruct(PREFIX prefix, uint32_t n)
144 {
145  vector<type_t> f(fields.end() - n, fields.end());
146  vector<string> l(labels.end() - n, labels.end());
147 
148  fields.erase(fields.end() - n, fields.end());
149  labels.erase(labels.end() - n, labels.end());
150 
152  applyPrefix(prefix, type_t::createRecord(f, l, position)));
153 }
154 
159 void StatementBuilder::structField(const char* name)
160 {
161  type_t type = typeFragments[0];
162  typeFragments.pop();
163 
164  // Constant fields are not allowed
165  if (type.is(CONSTANT))
166  {
167  handleError("$Constant_fields_not_allowed_in_struct");
168  }
169 
170  fields.push_back(type);
171  labels.push_back(name);
172 
173  /* Check the base type. We should check this in the type
174  * checker. The problem is that we do not maintain the position of
175  * types, hence we cannot place the error message if we wait until
176  * the type check phase.
177  */
178  type_t base = type.stripArray();
179  if (!base.isRecord() && !base.isScalar() && !base.isIntegral())
180  {
181  handleError("$Invalid_type_in_structure");
182  }
183 }
184 
190 void StatementBuilder::declTypeDef(const char* name)
191 {
192  bool duplicate = frames.top().getIndexOf(name) != -1;
194  typeFragments.pop();
195  if (duplicate)
196  {
197  throw TypeException(boost::format("$Duplicate_definition_of %1%") % name);
198  }
199 
200  frames.top().addSymbol(name, type);
201 }
202 
203 static bool initRec(type_t type, int thisTypeOnly)
204 {
205  type = type.strip();
206  switch (type.getKind())
207  {
208  case RECORD:
209  for (size_t i = 0; i < type.size(); i++)
210  {
211  if (!initRec(type[i], thisTypeOnly))
212  {
213  return false;
214  }
215  }
216  return true;
217 
218  case ARRAY:
219  if (type.getArraySize().isScalar())
220  {
221  return false;
222  }
223  return initRec(type.getSub(), thisTypeOnly);
224 
225  default:
226  return thisTypeOnly == 0
227  ? type.isIntegral()
228  : (thisTypeOnly == 1
229  ? type.isClock()
230  : type.isDouble());
231  }
232 }
233 
234 static bool initialisable(type_t type)
235 {
236  return initRec(type, 0) || initRec(type, 1) || initRec(type, 2);
237 }
238 
239 static bool mustInitialise(type_t type)
240 {
241  assert(type.getKind() != FUNCTION);
242  assert(type.getKind() != PROCESS);
243  assert(type.getKind() != INSTANCE);
244  assert(type.getKind() != LSCINSTANCE);
245 
246  switch (type.getKind())
247  {
248  case CONSTANT:
249  return true;
250  case RECORD:
251  for (size_t i = 0; i < type.size(); i++)
252  {
253  if (mustInitialise(type[i]))
254  {
255  return true;
256  }
257  }
258  return false;
259  default:
260  return type.size() > 0 && mustInitialise(type[0]);
261  }
262 }
263 
271 void StatementBuilder::declVar(const char* name, bool hasInit)
272 {
273  // Pop initial value
274  expression_t init;
275  if (hasInit)
276  {
277  init = fragments[0];
278  fragments.pop();
279  }
280 
281  // Construct type
282  type_t type = typeFragments[0];
283  typeFragments.pop();
284 
285  // Check whether initialiser is allowed/required
286  if (hasInit && !initialisable(type))
287  {
288  handleError("$Cannot_have_initialiser");
289  }
290 
291  if (!hasInit && mustInitialise(type))
292  {
293  handleError("$Constants_must_have_an_initialiser");
294  }
295 
296  if (currentFun && !initialisable(type))
297  {
298  handleError("$Type_is_not_allowed_in_functions");
299  }
300 
301  // Add variable to system
302  addVariable(type, name, init);
303 }
304 
305 // Array and struct initialisers are represented as expressions having
306 // one or more values (i.e. if the stack machine program that the
307 // expression represent is evaluated, then one or more values will be
308 // left on the stack).
309 //
310 // An array or struct initialiser has the structure of a list of field
311 // initialisers. Each field initialiser is a named expression
312 // (although the name can be NULL, in which case the field is
313 // anonymous). The field is actually represented like any other
314 // expression on the expression stack, except that is has a singular
315 // record type (i.e. a record type with only one element) on the form
316 // (name,type), where name is the name of the field and type is the
317 // type of the expression. A list of field initialisers is then
318 // created by concatenating several singular recorcd types into one
319 // record.
320 //
321 // Example: The initialiser { 2, x: 3, 4 } is represented as an
322 // expression evaluating to [2,3,4] on the stack, and the type of
323 // expression is [(NULL, typeof(2)) x ("x", typeof(3)) x (NULL,
324 // typeof(4))].
325 //
326 // For struct's, care must be taken when the type of the initialiser
327 // is compared to that of the declared struct. If another constant
328 // struct is used as an initialiser, then this struct must have the
329 // same type name as the struct being declared. If a struct
330 // initialiser is used (i.e. a list of fields), then the type
331 // requirements are much less strict.
332 
333 void StatementBuilder::declFieldInit(const char *name)
334 {
335  type_t type = fragments[0].getType().createLabel(name, position);
336  fragments[0].setType(type);
337 }
338 
340 {
341  // Pop fields
342  vector<expression_t> fields(num);
343  for (uint32_t i = 0; i < num; i++)
344  {
345  fields[i] = fragments[num - 1 - i];
346  }
347  fragments.pop(num);
348 
349  // Compute new type (each field has a label type, see declFieldInit())
350  vector<type_t> types;
351  vector<string> labels;
352  for (uint32_t i = 0; i < num; i++)
353  {
354  type_t type = fields[i].getType();
355  types.push_back(type[0]);
356  labels.push_back(type.getLabel(0));
357  fields[i].setType(type[0]);
358  }
359 
360  // Create list expression
362  LIST, fields, position,
363  type_t::createRecord(types, labels, position)));
364 }
365 
366 /********************************************************************
367  * Function declarations
368  */
369 void StatementBuilder::declParameter(const char* name, bool ref)
370 {
371  type_t type = typeFragments[0];
372  typeFragments.pop();
373 
374  if (ref)
375  {
376  type = type.createPrefix(REF);
377  }
378 
379  params.addSymbol(name, type);
380 }
381 
382 void StatementBuilder::declFuncBegin(const char* name)
383 {
384  assert(currentFun == NULL);
385 
386  type_t return_type = typeFragments[0];
387  typeFragments.pop();
388 
389  vector<type_t> types;
390  vector<string> labels;
391  for (size_t i = 0; i < params.getSize(); i++)
392  {
393  types.push_back(params[i].getType());
394  labels.push_back(params[i].getName());
395  }
396  type_t type = type_t::createFunction(return_type, types, labels, position);
397  if (!addFunction(type, name))
398  {
399  boost::format err = boost::format("$Duplicate_definition_of %1%") % name;
400  handleError(err.str());
401  }
402 
403  /* We maintain a stack of frames. As the function has a local
404  * scope, we push a new frame and move the parameters to it.
405  */
407  params.moveTo(frames.top()); // params is emptied here
408 
409  /* Create function block.
410  */
411  currentFun->body = new BlockStatement(frames.top());
412  blocks.push_back(currentFun->body);
413 }
414 
416 {
417  assert(!blocks.empty());
418  assert(currentFun);
419 
420  /* Recover from unterminated blocks - delete any excess blocks.
421  */
422  while (blocks.size() > 1)
423  {
424  delete blocks.back();
425  blocks.pop_back();
426  }
427 
428  assert(currentFun->body == blocks.back());
429 
430  /* If function has a non void return type, then check that last
431  * statement is a return statement.
432  */
433  BlockStatement *body = currentFun->body;
434  if (!currentFun->uid.getType()[0].isVoid() && !body->returns())
435  {
436  handleError("$Return_statement_expected");
437  }
438 
439  /* Pop outer function block.
440  */
441  blocks.pop_back();
442 
443  /* Restore global frame.
444  */
445  popFrame();
446 
447  /* Reset current function pointer to NULL.
448  */
449  currentFun = NULL;
450 }
451 
452 /*********************************************************************
453  * Statements
454  */
456 {
458  blocks.push_back(new BlockStatement(frames.top()));
459 }
460 
462 {
463  // Append the block which is being terminated as a statement to
464  // the containing block.
465  BlockStatement *block = blocks.back();
466  blocks.pop_back();
467  blocks.back()->push_stat(block);
468 
469  // Restore containing frame
470  popFrame();
471 }
472 
474 {
475  blocks.back()->push_stat(new EmptyStatement());
476 }
477 
479 {
480 }
481 
483 { // 3 expr, 1 stat
484  Statement* substat = blocks.back()->pop_stat();
485  ForStatement* forstat = new ForStatement(fragments[2], fragments[1],
486  fragments[0], substat);
487  blocks.back()->push_stat(forstat);
488 
489  fragments.pop(3);
490 }
491 
492 void StatementBuilder::iterationBegin (const char *name)
493 {
494  type_t type = typeFragments[0];
495  typeFragments.pop();
496 
497  /* The iterator cannot be modified.
498  */
499  if (!type.is(CONSTANT))
500  {
501  type = type.createPrefix(CONSTANT);
502  }
503 
504  /* The iteration statement has a local scope for the iterator.
505  */
507 
508  /* Add variable.
509  */
510  variable_t *variable = addVariable(type, name, expression_t());
511 
512  /* Create a new statement for the loop. We need to already create
513  * this here as the statement is the only thing that can keep the
514  * reference to the frame.
515  */
516  blocks.back()->push_stat(
517  new IterationStatement(variable->uid, frames.top(), NULL));
518 }
519 
520 void StatementBuilder::iterationEnd (const char *name)
521 {
522  /* Retrieve the statement that we iterate over.
523  */
524  Statement* statement = blocks.back()->pop_stat();
525 
526  /* Add statement to loop construction.
527  */
528  static_cast<IterationStatement *>(blocks.back()->back())->stat = statement;
529 
530  /* Restore the frame pointer.
531  */
532  popFrame();
533 }
534 
536 {
537 }
538 
540 { // 1 expr, 1 stat
541  Statement* substat = blocks.back()->pop_stat();
542  WhileStatement* whilestat = new WhileStatement(fragments[0], substat);
543  blocks.back()->push_stat(whilestat);
544 
545  fragments.pop();
546 }
547 
549 {
550 }
551 
553 { // 1 stat, 1 expr
554  Statement* substat = blocks.back()->pop_stat();
555  blocks.back()->push_stat(new DoWhileStatement(substat, fragments[0]));
556  fragments.pop();
557 }
558 
559 void StatementBuilder::ifEnd(bool elsePart)
560 { // 1 expr, 1 or 2 statements
561  Statement *falseCase = (elsePart ? blocks.back()->pop_stat() : NULL);
562  Statement *trueCase = blocks.back()->pop_stat();
563  IfStatement *ifstat = new IfStatement(fragments[0], trueCase, falseCase);
564 
565  blocks.back()->push_stat(ifstat);
566 
567  fragments.pop();
568 }
569 
571 { // 1 expr
572  blocks.back()->push_stat(new ExprStatement(fragments[0]));
573  fragments.pop();
574 }
575 
577 { // 1 expr if argument is true
578  if (!currentFun)
579  {
580  handleError("$Cannot_return_outside_of_function_declaration");
581  }
582  else
583  {
584  /* Only functions with non-void return type are allowed to have
585  * arguments on return.
586  */
587  type_t return_type = currentFun->uid.getType()[0];
588  if (return_type.isVoid() && args)
589  {
590  handleError("$return_with_a_value_in_function_returning_void");
591  }
592  else if (!return_type.isVoid() && !args)
593  {
594  handleError("$return_with_no_value_in_function_returning_non-void");
595  }
596 
597  ReturnStatement* stat;
598  if (args)
599  {
600  stat = new ReturnStatement(fragments[0]);
601  fragments.pop();
602  }
603  else
604  {
605  stat = new ReturnStatement();
606  }
607  blocks.back()->push_stat(stat);
608  }
609 }
610 
612 {
613  blocks.back()->push_stat(new AssertStatement(fragments[0]));
614  fragments.pop();
615 }
616 
617 /********************************************************************
618  * Expressions
619  */
620 
622 {
624 
625  /* Check for recursive function calls. We could move this to
626  * the type checker.
627  */
628  if (currentFun != NULL && currentFun->uid == fragments[0].getSymbol())
629  {
630  handleError("$Recursion_is_not_allowed");
631  }
632 }
symbol_t uid
The symbol of the variables.
Definition: system.h:45
void typeArrayOfSize(size_t) override
Called to create an array type.
bool isClock() const
Shortcut for is(CLOCK).
Definition: type.h:235
static bool initRec(type_t type, int thisTypeOnly)
std::set< symbol_t > restricted
Restricted variables.
Definition: system.h:337
bool isVoid() const
Shortcut for is(VOID_TYPE).
Definition: type.h:244
bool isIntegral() const
Returns true if this is a boolean or integer.
Definition: type.cpp:343
uint32_t getSize() const
Returns the number of symbols in this frame.
Definition: symbols.cpp:328
void declInitialiserList(uint32_t num) override
void popFrame()
Pop the topmost frame.
bool isInteger() const
Shortcut for is(INT).
Definition: type.h:202
std::vector< std::string > labels
The labels of a struct.
static expression_t createNary(Constants::kind_t, const std::vector< expression_t > &, position_t=position_t(), type_t=type_t())
Create an n-ary expression.
A reference to a symbol.
Definition: symbols.h:107
type_t createPrefix(Constants::kind_t kind, position_t=position_t()) const
Creates a new type by adding a prefix to it.
Definition: type.cpp:532
std::vector< type_t > fields
The types of a struct.
void typeBoundedInt(PREFIX) override
Called whenever an integer type with a range is parsed.
Statement class for the iterator loop-construction.
Definition: statement.h:91
void declTypeDef(const char *name) override
A type definition.
static bool mustInitialise(type_t type)
void iterationBegin(const char *name) override
void declParameter(const char *name, bool) override
void pushFrame(frame_t)
Push a new frame.
void iterationEnd(const char *name) override
std::pair< expression_t, expression_t > getRange() const
Returns the range of a RANGE type.
Definition: type.cpp:266
void typeArrayOfType(size_t) override
Called to create an array type.
Partial implementation of the builder interface: The ExpressionBuilder implements all expression rela...
const std::string & getLabel(uint32_t) const
Returns the i&#39;th label.
Definition: type.cpp:99
StatementBuilder(TimedAutomataSystem *)
type_t strip() const
Removes any leading prefixes, RANGE, REF and LABEL types and returns the result.
Definition: type.cpp:285
static frame_t createFrame()
Creates and returns a new root-frame.
Definition: symbols.cpp:474
void returnStatement(bool) override
static type_t createFunction(type_t, const std::vector< type_t > &, const std::vector< std::string > &, position_t=position_t())
Creates a new function type.
Definition: type.cpp:451
template_t * currentTemplate
The template currently being parsed.
Base type for variables, clocks, etc.
Definition: system.h:43
type_t stripArray() const
Removes any leading prefixes, RANGE, REF, LABEL and ARRAY types and returns the result.
Definition: type.cpp:297
function_t * currentFun
The function currently being parsed.
type_t getSub() const
Returns the element type of an array.
Definition: type.cpp:193
ExpressionFragments fragments
Expression stack.
std::stack< frame_t > frames
Frame stack.
void handleError(const std::string &) override
Exception indicating a type error.
Definition: builder.h:39
static type_t createTypeDef(const std::string &, type_t, position_t=position_t())
Creates a new type definition.
Definition: type.cpp:475
void emptyStatement() override
static void collectDependencies(std::set< symbol_t > &, expression_t)
void exprStatement() override
expression_t expr
The initialiser.
Definition: system.h:46
A reference to a type.
Definition: type.h:93
type_t getType() const
Returns the type of this symbol.
Definition: symbols.cpp:205
void structField(const char *name) override
Used to declare the fields of a structure.
frame_t params
The params frame is used temporarily during parameter parsing.
size_t size() const
Returns the number of children.
Definition: type.cpp:81
symbol_t uid
The symbol of the function.
Definition: system.h:112
void declFieldInit(const char *name) override
virtual bool addFunction(type_t type, const char *name)=0
static type_t createRecord(const std::vector< type_t > &, const std::vector< std::string > &, position_t=position_t())
Creates a new record type.
Definition: type.cpp:437
BlockStatement * body
Pointer to the block.
Definition: system.h:116
void ifEnd(bool) override
void exprNat(int32_t) override
A reference to an expression.
Definition: expression.h:70
static bool initialisable(type_t type)
type_t getArraySize() const
Returns the size of an array (this is itself a type).
Definition: type.cpp:227
void * getData()
Returns the user data of this symbol.
Definition: symbols.cpp:216
void typeStruct(PREFIX, uint32_t fields) override
Used to construct a new struct type, which is then pushed onto the type stack.
void moveTo(frame_t)
Move all symbols from this to a given one (leaving this empty).
Definition: symbols.cpp:392
void declFuncBegin(const char *name) override
void assertStatement() override
bool is(Constants::kind_t kind) const
Returns true if the type has kind kind or if type is a prefix, RANGE or REF type and the getChild()...
Definition: type.cpp:176
symbol_t addSymbol(const std::string &name, type_t, void *user=NULL)
Adds a symbol of the given name and type to the frame.
Definition: symbols.cpp:352
void exprBinary(Constants::kind_t binaryop) override
std::vector< BlockStatement * > blocks
Stack of nested statement blocks.
Definition: lexer.cc:817
void doWhileBegin() override
type_t applyPrefix(PREFIX, type_t type)
Given a prefix and a type, this method creates a new type by applying the prefix. ...
bool isScalar() const
Shortcut for is(SCALAR).
Definition: type.h:232
void collectPossibleReads(std::set< symbol_t > &, bool collectRandom=false) const
void exprCallBegin() override
virtual variable_t * addVariable(type_t type, const char *name, expression_t init)=0
TypeFragments typeFragments
Type stack.
static int types
Definition: parser.cc:127
static type_t createArray(type_t sub, type_t size, position_t=position_t())
Creates an array type.
Definition: type.cpp:467
bool isDouble() const
Shortcut for is(DOUBLE).
Definition: type.h:250
bool isRecord() const
Shortcut for is(RECORD).
Definition: type.h:238
Constants::kind_t getKind() const
Returns the kind of type object.
Definition: type.cpp:120
void declVar(const char *name, bool init) override
Declare a new variable of the given name.