libutap  0.93
Uppaal Timed Automata Parser
expressionbuilder.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 <vector>
23 #include <climits>
24 #include <cmath>
25 #include <cstdio>
26 #include <cassert>
27 #include <cinttypes>
28 #include <cstring>
29 #include <boost/format.hpp>
30 
31 #include "utap/expressionbuilder.h"
32 
33 using namespace UTAP;
34 using namespace Constants;
35 
36 using std::vector;
37 using std::string;
38 using std::map;
39 
40 bool isMITL (expression_t e) {
41  return (e.getKind () == MITLFORMULA ||
42  e.getKind () == MITLRELEASE ||
43  e.getKind () == MITLUNTIL ||
44  e.getKind () == MITLCONJ ||
45  e.getKind () == MITLDISJ ||
46  e.getKind () == MITLNEXT ||
47  e.getKind () == MITLATOM ||
48  e.getKind () == MITLEXISTS ||
49  e.getKind () == MITLFORALL
50  );
51 }
52 
55 }
56 
58 {
59  assert(n <= size());
60  while (n--) pop();
61 }
62 
64  : system(system)
65 {
66  pushFrame(system->getGlobals().frame);
67  scalar_count = 0;
68 }
69 
71  uint32_t position, uint32_t offset, uint32_t line, const string& path)
72 {
73  system->addPosition(position, offset, line, path);
74 }
75 
76 void ExpressionBuilder::handleError(const string& msg)
77 {
78  system->addError(position, msg);
79 }
80 
81 void ExpressionBuilder::handleWarning(const string& msg)
82 {
83  system->addWarning(position, msg);
84 }
85 
87 {
88  frames.push(frame);
89 }
90 
92 {
93  frames.pop();
94 }
95 
96 bool ExpressionBuilder::resolve(const string& name, symbol_t &uid)
97 {
98  assert(!frames.empty());
99  return frames.top().resolve(name, uid);
100 }
101 
103 {
104  return fragments;
105 }
106 
107 bool ExpressionBuilder::isType(const char* name)
108 {
109  symbol_t uid;
110  if (!resolve(name, uid))
111  {
112  return false;
113  }
114  return uid.getType().getKind() == TYPEDEF;
115 }
116 
118 {
119  return expression_t::createConstant(value, position);
120 }
121 
123 {
124  return expression_t::createDouble(value, position);
125 }
126 
128 {
129  switch (prefix)
130  {
131  case PREFIX_CONST:
132  return type.createPrefix(CONSTANT, position);
133  case PREFIX_SYSTEM_META:
134  // Meta in the syntax corresponds to a static variable internally.
135  // Internal "meta" variables correspond to state meta variables.
136  return type.createPrefix(SYSTEM_META, position);
137  case PREFIX_URGENT:
138  return type.createPrefix(URGENT, position);
139  case PREFIX_BROADCAST:
140  return type.createPrefix(BROADCAST, position);
143  case PREFIX_HYBRID:
144  return type.createPrefix(HYBRID, position);
145  default:
146  return type;
147  }
148 }
149 
151 {
153 }
154 
156 {
157  typeFragments.pop();
158 }
159 
161 {
163  typeFragments.push(applyPrefix(prefix, type));
164 }
165 
167 {
169  if (prefix != PREFIX_CONST)
170  {
171  type = type_t::createRange(type,
174  position);
175  }
176  typeFragments.push(applyPrefix(prefix, type));
177 }
178 
180 {
182  typeFragments.push(applyPrefix(prefix, type));
183 }
184 
186 {
188  type = type_t::createRange(type, fragments[1], fragments[0], position);
189  fragments.pop(2);
190  typeFragments.push(applyPrefix(prefix, type));
191 }
192 
194 {
196  typeFragments.push(applyPrefix(prefix, type));
197 }
198 
200 {
202  typeFragments.push(applyPrefix(prefix, type));
203 }
204 
206 {
208  typeFragments.push(type);
209 }
210 
212  std::set<symbol_t> &dependencies, expression_t expr)
213 {
214  std::set<symbol_t> symbols;
215  expr.collectPossibleReads(symbols);
216  while (!symbols.empty())
217  {
218  symbol_t s = *symbols.begin();
219  symbols.erase(s);
220  if (dependencies.find(s) == dependencies.end())
221  {
222  dependencies.insert(s);
223  if (s.getData())
224  {
225  variable_t *v = static_cast<variable_t*>(s.getData());
226  v->expr.collectPossibleReads(symbols);
227  }
228  }
229  }
230 }
231 
233 {
234  expression_t lower, upper;
235 
236  exprNat(1);
237  exprBinary(MINUS);
238  upper = fragments[0];
239  lower = makeConstant(0);
240  fragments.pop();
241 
243  type = type_t::createRange(type, lower, upper, position);
244  type = applyPrefix(prefix, type);
245 
246  string count = (boost::format("%1%") % scalar_count++).str();
247 
248  type = type.createLabel(string("#scalarset") + count, position);
249 
250  if (currentTemplate)
251  {
252  /* Local scalar definitions are local to a particular process
253  * - not to the template. Therefore we prefix it with the
254  * template name and rename the template name to the process
255  * name whenever evaluating a P.symbol expression (where P is
256  * a processs). See exprDot().
257  */
258  type = type.createLabel(currentTemplate->uid.getName() + "::", position);
259 
260  /* There are restrictions on how the size of a scalar set is
261  * given (may not depend on free process parameters).
262  * Therefore mark all symbols in upper and those that they
263  * depend on as restricted.
264  */
266  }
267  typeFragments.push(type);
268 }
269 
270 void ExpressionBuilder::typeName(PREFIX prefix, const char* name)
271 {
272  symbol_t uid;
273  assert(resolve(name, uid));
274 
275  if (!resolve(name, uid) || uid.getType().getKind() != TYPEDEF)
276  {
278  throw TypeException("$Identifier_is_undeclared_or_not_a_type_name");
279  }
280 
281  type_t type = uid.getType()[0];
282 
283  /* We create a label here such that we can track the
284  * position. This is not needed for type checking (we only use
285  * name equivalence for scalarset, and they have a name embedded
286  * in the type, see typeScalar()).
287  */
288  type = type.createLabel(uid.getName(), position);
289  typeFragments.push(applyPrefix(prefix, type));
290 }
291 
293 {
294  expression_t expr = makeConstant(1);
296  fragments.push(expr);
297 }
298 
300 {
301  expression_t expr = makeConstant(0);
303  fragments.push(expr);
304 }
305 
307 {
310  fragments.push(expr);
311 }
312 
313 void ExpressionBuilder::exprId(const char *name)
314 {
315  symbol_t uid;
316 
317  if (!resolve(name, uid))
318  {
319  exprFalse();
320  throw TypeException(boost::format("$Unknown_identifier: %1%") % name);
321  }
322 
324 }
325 
327 {
329 }
330 
332 {
334 }
335 
337 {
338 }
339 
340 // expects n argument expressions on the stack
342 {
343  expression_t e;
344  type_t type;
345  instance_t *instance;
346 
347  /* n+1'th element from the top is the identifier.
348  */
349  expression_t id = fragments[n];
350 
351  /* Create vector of sub expressions: The first expression
352  * evaluates to the function or processset. The remaining
353  * expressions are the arguments.
354  */
355  vector<expression_t> expr;
356  for (int i = n; i >= 0; i--)
357  {
358  expr.push_back(fragments[i]);
359  }
360  fragments.pop(n + 1);
361 
362  /* The expression we create depends on whether id is a
363  * function or a processset.
364  */
365  switch (id.getType().getKind())
366  {
367  case FUNCTION:
368  if (expr.size() != id.getType().size())
369  {
370  handleError("$Wrong_number_of_arguments");
371  }
372  e = expression_t::createNary(FUNCALL, expr, position, id.getType()[0]);
373  break;
374 
375  case PROCESSSET:
376  if (expr.size() - 1!= id.getType().size())
377  {
378  handleError("$Wrong_number_of_arguments");
379  }
380  instance = static_cast<instance_t*>(id.getSymbol().getData());
381 
382  /* Process set lookups are represented as expressions indexing
383  * into an array. To satisfy the type checker, we create a
384  * type matching this structure.
385  */
386  type = type_t::createProcess(instance->templ->frame);
387  for (size_t i = 0; i < instance->unbound; i++)
388  {
389  type = type_t::createArray(type, instance->parameters[instance->unbound - i - 1].getType());
390  }
391 
392  /* Now create the expression. Each argument to the proces set
393  * lookup is represented as an ARRAY expression.
394  */
395  e = id;
396  e.setType(type);
397  for (size_t i = 1; i < expr.size(); i++)
398  {
399  type = type.getSub();
400  e = expression_t::createBinary(ARRAY, e, expr[i], position, type);
401  }
402  break;
403 
404  default:
405  handleError("$Function_expected");
406  e = makeConstant(0);
407  break;
408  }
409 
410  fragments.push(e);
411 }
412 
413 // 2 expr // array[index]
415 {
416  // Pop sub-expressions
417  expression_t var = fragments[1];
418  expression_t index = fragments[0];
419  fragments.pop(2);
420 
421  type_t element;
422  type_t type = var.getType();
423  if (type.isArray())
424  {
425  element = type.getSub();
426  }
427  else
428  {
429  element = type_t();
430  }
431 
433  ARRAY, var, index, position, element));
434 }
435 
436 // 1 expr
438 {
441 }
442 
444 {
446  PREINCREMENT, fragments[0], position, fragments[0].getType());
447 }
448 
450 {
453 }
454 
456 {
458  PREDECREMENT, fragments[0], position, fragments[0].getType());
459 }
460 
462 {
464  kind, fragments[0], position);
465 }
466 
468 {
469  expression_t lvalue = fragments[1];
470  expression_t rvalue = fragments[0];
471  fragments.pop(1);
473  kind, lvalue, rvalue, position, lvalue.getType());
474 }
475 
477 {
478  expression_t value1 = fragments[2];
479  expression_t value2 = fragments[1];
480  expression_t value3 = fragments[0];
481  fragments.pop(2);
483  kind, value1, value2, value3, position, value1.getType());
484 }
485 
487 {
488  expression_t lvalue = fragments[1];
489  expression_t rvalue = fragments[0];
490  fragments.pop(2);
492  op, lvalue, rvalue, position, lvalue.getType()));
493 }
494 
495 void ExpressionBuilder::exprUnary(kind_t unaryop) // 1 expr
496 {
497  switch (unaryop)
498  {
499  case PLUS:
500  /* Unary plus can be ignored */
501  break;
502  case MINUS:
503  unaryop = UNARY_MINUS;
504  /* Fall through! */
505  default:
507  }
508 }
509 
510 void ExpressionBuilder::exprBinary(kind_t binaryop) // 2 expr
511 {
512  kind_t mitlop = (binaryop == AND ? MITLCONJ : MITLDISJ);
513  kind_t op = binaryop;
514  expression_t left = fragments[1];
515  expression_t right = fragments[0];
516  if (isMITL (left ) || isMITL (right))
517  {
518  op = mitlop;
519  if (!(isMITL (left) && isMITL (right)))
520  {
521  if (isMITL (left) )
522  {
523  op = mitlop;
524  right = toMITLAtom (right);
525  }
526  else if (isMITL (right))
527  {
528  op = mitlop;
529  left = toMITLAtom (left);
530  }
531  }
532  }
533  fragments.pop(2);
535  op, left, right, position));
536 }
537 
538 void ExpressionBuilder::exprNary(kind_t kind, uint32_t num)
539 {
540  // Pop fields
541  vector<expression_t> fields(num);
542  for (uint32_t i = 0; i < num; i++)
543  {
544  fields[i] = fragments[num - 1 - i];
545  }
546  fragments.pop(num);
547 
548  // Create N-ary expression
550 }
551 
552 void ExpressionBuilder::exprScenario(const char* name)
553 {
554  symbol_t uid;
555  bool check [[maybe_unused]] = resolve(name, uid);
556  assert(check);
560 }
561 
563 {
564  symbol_t uid;
565  bool check [[maybe_unused]] = resolve(system->obsTA, uid);
566  assert(check);
567  expression_t obs = expression_t::createIdentifier(uid); //std::cout << obs << std::endl;
568  int32_t i = obs.getType().findIndexOf("lmin");
570  type_t::createPrimitive(Constants::BOOL)); //std::cout << left << std::endl;
571 
573  i = obs.getType().findIndexOf("lmax");
575  type_t::createPrimitive(Constants::BOOL)); //std::cout << right << std::endl;
577  SCENARIO2, left, right, position);
578 }
579 
580 void ExpressionBuilder::exprTernary(kind_t ternaryop, bool firstMissing) // 3 expr
581 {
582  expression_t first = firstMissing ? makeConstant(1) : fragments[2];
583  expression_t second = fragments[1];
584  expression_t third = fragments[0];
585  fragments.pop(firstMissing ? 2 : 3);
587  ternaryop, first, second, third, position));
588 }
589 
591 {
592  expression_t c = fragments[2];
593  expression_t t = fragments[1];
594  expression_t e = fragments[0];
595  fragments.pop(3);
597  INLINEIF, c, t, e, position, t.getType()));
598 }
599 
601 {
602  expression_t e1 = fragments[1];
603  expression_t e2 = fragments[0];
604  fragments.pop(2);
606  COMMA, e1, e2, position, e2.getType()));
607 }
608 
609 void ExpressionBuilder::exprDot(const char *id)
610 {
611  expression_t expr = fragments[0];
612  type_t type = expr.getType();
613  if (type.isRecord())
614  {
615  int32_t i = type.findIndexOf(id);
616  if (i == -1)
617  {
618  string s = expr.toString(true);
619  ParserBuilder::handleError("%s $has_no_member_named %s",
620  s.c_str(), id);
621  }
622  else
623  {
624  expr = expression_t::createDot(expr, i, position, type.getSub(i));
625  }
626  }
627  else if (type.isProcess())
628  {
629  symbol_t name = expr.getSymbol();
630  instance_t *process = (instance_t *)name.getData();
631  int32_t i = type.findIndexOf(id);
632  if (i == -1)
633  {
634  string s = expr.toString(true);
635  ParserBuilder::handleError("%s $has_no_member_named %s",
636  s.c_str(), id);
637  }
638  else if (type.getSub(i).isLocation())
639  {
640  expr = expression_t::createDot(expr, i, position,
642  }
643  else
644  {
645  type = type.getSub(i).rename(process->templ->uid.getName() + "::",
646  name.getName() + "::");
647  map<symbol_t, expression_t>::const_iterator arg;
648  for (arg = process->mapping.begin(); arg != process->mapping.end(); arg++)
649  {
650  type = type.subst(arg->first, arg->second);
651  }
652  expr = expression_t::createDot(expr, i, position, type);
653  }
654  }
655 
656  else if (type.is (PROCESSVAR)) {
657  symbol_t uid;
658  //temporarily set the frame to that of its associated template
659  if (dynamicFrames.find(expr.getSymbol ().getName ()) == dynamicFrames.end ()) {
660  throw TypeException (boost::format("$Unknown_identifier: %1%") % expr.getSymbol ().getName ());
661  }
662  pushFrame (dynamicFrames [expr.getSymbol ().getName ()]);
663 
664  if (!resolve(id, uid))
665  {
666  exprFalse();
667  throw TypeException(boost::format("$Unknown_identifier: %1%") % id);
668  }
669  popFrame ();//Remove that frame again
671 
672  vector<expression_t> exprs;
673  exprs.push_back (identifier);
674  exprs.push_back (expr);
675 
676  expr =(expression_t::createNary (DYNAMICEVAL,exprs,position, identifier.getType ().isLocation () ?
678 
679  identifier.getType ()));//type_t::createPrimitive (Constants::BOOL,position)));
680  }
681 
682  else
683  {
684  string s = expr.toString(true);
685  ParserBuilder::handleError("%s $is_not_a_structure", s.c_str());
686  }
687  fragments[0] = expr;
688 }
689 
691 {
692  type_t type = typeFragments[0];
693  typeFragments.pop();
694 
695  if (!type.is(CONSTANT))
696  {
697  type = type.createPrefix(CONSTANT);
698  }
699 
701  symbol_t symbol = frames.top().addSymbol(name, type);
702 
703  if (!type.isInteger() && !type.isScalar())
704  {
705  handleError("$Quantifier_must_range_over_integer_or_scalar_set");
706  }
707 }
708 
709 void ExpressionBuilder::exprForAllEnd(const char *name)
710 {
711  /* Create the forall expression. The symbol is added as an identifier
712  * expression as the first child. Notice that the frame is discarded
713  * but the identifier expression will maintain a reference to the
714  * symbol so it will not be deallocated.
715  */
717  FORALL,
719  fragments[0], position);
720  popFrame();
721 }
722 
724 {
725  exprForAllBegin(name);
726 }
727 
728 void ExpressionBuilder::exprExistsEnd(const char *name)
729 {
730  /* Create the exist expression. The symbol is added as an identifier
731  * expression as the first child. Notice that the frame is discarded
732  * but the identifier expression will maintain a reference to the
733  * symbol so it will not be deallocated.
734  */
737  frames.top()[0], position), fragments[0], position);
738  popFrame();
739 }
740 
741 void ExpressionBuilder::exprSumBegin(const char *name)
742 {
743  exprForAllBegin(name);
744 }
745 
746 void ExpressionBuilder::exprSumEnd(const char *name)
747 {
748  /* Create the sum expression. The symbol is added as an identifier
749  * expression as the first child. Notice that the frame is discarded
750  * but the identifier expression will maintain a reference to the
751  * symbol so it will not be deallocated.
752  */
755  frames.top()[0], position), fragments[0], position);
756  popFrame();
757 }
758 
760 {
761  auto boundVar = fragments[2];
762  auto bound = fragments[1];
763  auto control = fragments[0];
764  fragments.pop(3);
766  SMC_CONTROL, boundVar, bound, control,
767  position));
768 }
769 
771  Constants::kind_t comp,
772  double probBound)
773 {
774  auto invert = (comp == LE);
775  auto& boundTypeOrBoundedExpr = fragments[3];
776  auto& bound = fragments[2];
777  auto& runs = fragments[1];
778  auto& predicate = fragments[0];
779 
780  auto args = std::vector<expression_t>{
781  runs, boundTypeOrBoundedExpr, bound,
782  invert ? expression_t::createUnary(NOT, predicate, position) : predicate,
783  expression_t::createDouble(invert ? 1.0-probBound : probBound, position)
784  };
785 
786  fragments.pop(4);
788  invert
789  ? (pathType == BOX ? PROBAMINDIAMOND : PROBAMINBOX)
790  : (pathType == BOX ? PROBAMINBOX : PROBAMINDIAMOND),
791  args, position));
792 }
793 
795 {
796  auto& boundTypeOrBoundedExpr = fragments[4];
797  auto& bound = fragments[3];
798  auto& runs = fragments[2];
799  auto& predicate = fragments[1];
800  auto& untilCond = fragments[0];
801 
802  auto args = std::vector<expression_t>{
803  runs, boundTypeOrBoundedExpr, bound, predicate, untilCond
804  };
805 
806  fragments.pop(5);
808  (pathType == BOX ? PROBABOX : PROBADIAMOND),
809  args, position));
810 }
811 
813  Constants::kind_t pathType2)
814 {
815  auto& boundTypeOrBoundedExpr1 = fragments[7];
816  auto& bound1 = fragments[6];
817  auto& runs1 = fragments[5];
818  auto& predicate1 = fragments[4];
819 
820  auto& boundTypeOrBoundedExpr2 = fragments[3];
821  auto& bound2 = fragments[2];
822  auto& runs2 = fragments[1];
823  auto& predicate2 = fragments[0];
824 
825  if (runs1.getValue()!=-1 || runs2.getValue()!=-1)
826  throw TypeException("The number of runs is not supported in probability comparison");
827 
828  auto args = std::vector<expression_t>{
829  boundTypeOrBoundedExpr1, bound1, expression_t::createConstant(pathType1), predicate1,
830  boundTypeOrBoundedExpr2, bound2, expression_t::createConstant(pathType2), predicate2
831  };
832 
833  fragments.pop(8);
835 }
836 
837 void ExpressionBuilder::exprProbaExpected(const char* aggregatingOp)
838 {
839  auto& boundTypeOrBoundedExpr = fragments[3];
840  auto& bound = fragments[2];
841  auto& runs = fragments[1];
842  auto& expression = fragments[0];
843 
844  if (runs.getKind()==CONSTANT && runs.getType().isInteger() &&
845  runs.getValue()<0)
847 
848  int aggOpId;
849  if (strcmp("min", aggregatingOp) == 0)
850  aggOpId = 0;
851  else if (strcmp("max", aggregatingOp) == 0)
852  aggOpId = 1;
853  else throw TypeException("min or max expected");
854  // TODO: add "acc" when the semantics is defined.
855 
856  auto args = std::vector<expression_t>{
857  runs, boundTypeOrBoundedExpr, bound,
859  expression
860  };
861  fragments.pop(4);
863 }
864 
865 void ExpressionBuilder::exprSimulate(int nbExpr, bool hasReach,
866  int numberOfAcceptingRuns)
867 {
868  // Stack:
869  // conditional bound name
870  // expr bound
871  // nbExpr * expr
872  // if (hasReach) => expr
873  auto offset = nbExpr + (hasReach ? 1 : 0);
874  auto& boundTypeOrBoundedExpr = fragments[2+offset];
875  auto& bound = fragments[1+offset];
876  auto& runs = fragments[0+offset];
877 
878  auto args = std::vector<expression_t>{};
879  args.reserve(offset+4); // 3-from-above + offset*expressions + numberOfAcceptingRuns
880 
881  if (runs.getKind()==CONSTANT && runs.getType().isInteger() &&
882  runs.getValue()<0)
884 
885  args.push_back(runs);
886  args.push_back(boundTypeOrBoundedExpr);
887  args.push_back(bound);
888  for(int i=0; i<nbExpr; ++i)
889  args.push_back(fragments[offset-1-i]); // recover the original order
890 
891  if (hasReach) {
892  auto& predicate = fragments[0];
893  args.push_back(predicate);
894  args.push_back(expression_t::createConstant(numberOfAcceptingRuns));
895  }
896 
897  fragments.pop(offset+3);
898  if (hasReach)
900  else
902 }
903 
905 {
906  expression_t mitl;
907  mitl = fragments[0];
908  if (!isMITL(mitl))
909  {
910  mitl = toMITLAtom(mitl);
911  }
912  fragments.pop();
914  fragments.push (form);
915 }
916 
917 void ExpressionBuilder::exprMitlUntil(int low, int high)
918 {
919  expression_t left,right,lowd,highd;
920  std::vector<expression_t> args;
921  left = fragments[1];
922  right = fragments[0];
923  fragments.pop(2);
924  if (!isMITL(left))
925  {
926  left = toMITLAtom(left);
927  }
928  if (!isMITL(right))
929  {
930  right = toMITLAtom(right);
931  }
932  lowd = expression_t::createConstant(low);
933  highd = expression_t::createConstant(high);
934  args.push_back(left);
935  args.push_back(lowd);
936  args.push_back(highd);
937  args.push_back(right);
938 
940  fragments.push(form);
941  }
942 void ExpressionBuilder::exprMitlRelease(int low, int high )
943 {
944  expression_t left,right,lowd,highd;
945  std::vector<expression_t> args;
946  left = fragments[1];
947  right = fragments[0];
948  fragments.pop(2);
949  if (!isMITL(left))
950  {
951  left = toMITLAtom(left);
952  }
953  if (!isMITL(right))
954  {
955  right = toMITLAtom(right);
956  }
957  lowd = expression_t::createConstant(low);
958  highd = expression_t::createConstant(high);
959  args.push_back(left);
960  args.push_back(lowd);
961  args.push_back(highd);
962  args.push_back(right);
964  }
965 /*transform the diamond <>[low,high]phi into a (true U[low,high] phi) structure */
966 void ExpressionBuilder::exprMitlDiamond(int low, int high )
967 {
968  expression_t left,right,lowd,highd;
969  std::vector<expression_t> args;
971  right = fragments[0];
972  fragments.pop(1);
973  if (!isMITL(right))
974  {
975  right = toMITLAtom(right);
976  }
977  lowd = expression_t::createConstant(low);
978  highd = expression_t::createConstant(high);
979  args.push_back(left);
980  args.push_back(lowd);
981  args.push_back(highd);
982  args.push_back(right);
983 
985  fragments.push(form);
986  }
987 
988 /*transform the diamond [][low,high]phi into a (false R[low,high] phi) structure */
989 void ExpressionBuilder::exprMitlBox(int low, int high )
990 {
991  expression_t left,right,lowd,highd;
992  std::vector<expression_t> args;
994  right = fragments[0];
995  fragments.pop(1);
996  if (!isMITL(right))
997  {
998  right = toMITLAtom(right);
999  }
1000  lowd = expression_t::createConstant(low);
1001  highd = expression_t::createConstant(high);
1002  args.push_back(left);
1003  args.push_back(lowd);
1004  args.push_back(highd);
1005  args.push_back(right);
1006 
1008  fragments.push(form);
1009  }
1010 
1012 {
1013  expression_t left,right;
1014  left = fragments[1];
1015  right = fragments[0];
1016  fragments.pop(2);
1018  fragments.push(form);
1019  }
1021 {
1022  expression_t left,right;
1023  left = fragments[1];
1024  right = fragments[0];
1025  fragments.pop(2);
1027  }
1029 {
1030  expression_t next;
1031  next = fragments[0];
1032  fragments.pop();
1033  if (!isMITL(next))
1034  {
1035  next = toMITLAtom(next);
1036  }
1037 
1038 
1040 
1041 }
1043 {
1044  expression_t atom;
1045  atom = fragments[0];
1046 
1047  if (!isMITL(atom))
1048  {
1049  fragments.pop();
1051  }
1052 }
1053 
1055  vector<expression_t> expr;
1056  expression_t id = fragments[n];
1057  for (int i = n; i >= 0; i--)
1058  {
1059  expr.push_back(fragments[i]);
1060  }
1061  fragments.pop(n+1);
1063 }
1064 
1066 
1068 }
1069 
1071  expression_t id = fragments[0];
1073  fragments.pop();
1075 }
1076 
1077 
1078 void ExpressionBuilder::exprForAllDynamicBegin(const char* name,const char* temp)
1079 {
1081  frames.top().addSymbol(name,type_t::createPrimitive(PROCESSVAR,position));
1082  template_t* templ = system->getDynamicTemplate(string(temp));
1083  if (!templ) {
1084  throw TypeException(boost::format("Unknown dynamic template "+string(temp)+ " used in for all"));
1085  }
1086  //dynamicFrames[name]=templ->frame;
1087  pushDynamicFrameOf(templ,name);
1088 }
1090 {
1091 
1092  //At this instant we should have expression on top of the stack and the template identifier
1093  //below it
1094  expression_t expr = fragments[0];
1097  fragments.pop(2);
1098 
1099  bool mitl = isMITL(expr);
1100 
1101  if (mitl)
1102  {
1103  if (expr.getKind() == MITLATOM)
1104  {
1105  expr = expr.get(0).clone();
1106  mitl = false;
1107  }
1108  }
1109 
1110  vector<expression_t> exprs;
1111  exprs.push_back(identifier);
1112  exprs.push_back(process);
1113  exprs.push_back(expr);
1114 
1115 
1117  popFrame();
1118  popDynamicFrameOf(name);
1119 }
1120 void ExpressionBuilder::exprExistsDynamicBegin(const char* name,const char* temp)
1121 {
1124  template_t* templ = system->getDynamicTemplate(string(temp));
1125  if (!templ) {
1126  throw TypeException(boost::format("Unknown dynamic template "+string(temp)+ " used in exists"));
1127  }
1128  //dynamicFrames [name]=templ->frame;
1129  pushDynamicFrameOf(templ,name);
1130 }
1131 
1133 {
1134  expression_t expr = fragments[0];
1137  fragments.pop(2);
1138 
1139  vector<expression_t> exprs;
1140  bool mitl = isMITL(expr);
1141 
1142  if (mitl)
1143  {
1144  if (expr.getKind() == MITLATOM)
1145  {
1146  expr = expr.get(0).clone();
1147  mitl = false;
1148  }
1149  }
1150 
1151  exprs.push_back(identifier);
1152  exprs.push_back(process);
1153  exprs.push_back(expr);
1154 
1155 
1157  popFrame();
1158  popDynamicFrameOf(name);
1159 }
1160 void ExpressionBuilder::exprSumDynamicBegin(const char* name,const char* temp)
1161 {
1164  template_t* templ = system->getDynamicTemplate(string(temp));
1165  if (!templ) {
1166  throw TypeException(boost::format("Unknown dynamic template "+string(temp)+ " used in sum"));
1167  }
1168  //dynamicFrames [name]=templ->frame;
1169  pushDynamicFrameOf(templ,name);
1170 }
1171 
1173 {
1174  expression_t expr = fragments[0];
1177  fragments.pop(2);
1178 
1179  vector<expression_t> exprs;
1180  exprs.push_back(identifier);
1181  exprs.push_back(process);
1182  exprs.push_back(expr);
1183 
1185  popFrame();
1186  popDynamicFrameOf(name);
1187 }
1188 
1189 void ExpressionBuilder::exprForeachDynamicBegin(const char* name,const char* temp)
1190 {
1193  if (!system->getDynamicTemplate(string(temp))) {
1194  throw TypeException(boost::format("Unknown dynamic template "+string(temp)+ " used in foreach"));
1195  }
1196  //dynamicFrames [name]=system->getDynamicTemplate(string(temp))->frame;
1197  pushDynamicFrameOf(system->getDynamicTemplate(string(temp)),name);
1198 }
1199 
1201 {
1202  expression_t expr = fragments[0];
1205  fragments.pop(2);
1206 
1207  vector<expression_t> exprs;
1208  exprs.push_back(identifier);
1209  exprs.push_back(process);
1210  exprs.push_back(expr);
1211 
1213  popFrame();
1214  popDynamicFrameOf(name);
1215 }
1216 
1218 {
1219  if (!t->isDefined) {
1220  throw TypeException("Template referenced before used");
1221  }
1222  dynamicFrames[name] = t->frame;
1223 }
1224 
1226 {
1227  dynamicFrames.erase(name);
1228 }
static expression_t createDouble(double, position_t=position_t())
void exprSumBegin(const char *name) override
Constants::kind_t getKind() const
Returns the kind of the expression.
Definition: expression.cpp:182
Partial instance of a template.
Definition: system.h:329
void exprPostDecrement() override
struct template_t * templ
Definition: system.h:336
static expression_t createExit(position_t=position_t())
void exprMitlBox(int, int) override
bool isDefined
Definition: system.h:390
TimedAutomataSystem * system
Pointer to the system under construction.
void addPosition(uint32_t position, uint32_t offset, uint32_t line, const std::string &path)
Definition: system.cpp:1392
void exprBuiltinFunction2(Constants::kind_t) override
std::set< symbol_t > restricted
Restricted variables.
Definition: system.h:337
void exprTernary(Constants::kind_t ternaryop, bool firstMissing) override
expression_t clone() const
Make a shallow clone of the expression.
Definition: expression.cpp:81
void typeChannel(PREFIX) override
Called whenever a channel type is parsed.
void exprSumDynamicEnd(const char *name) override
size_t unbound
Definition: system.h:335
void exprForAllEnd(const char *name) override
void exprSumEnd(const char *name) override
void popFrame()
Pop the topmost frame.
void exprExistsDynamicBegin(const char *, const char *) override
bool isInteger() const
Shortcut for is(INT).
Definition: type.h:202
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.
static type_t createRange(type_t, expression_t, expression_t, position_t=position_t())
Definition: type.cpp:425
void exprId(const char *varName) override
A reference to a symbol.
Definition: symbols.h:107
std::string getName() const
Returns the name (identifier) of this symbol.
Definition: symbols.cpp:228
symbol_t getSymbol()
Returns the symbol of a variable reference.
Definition: expression.cpp:718
void exprNary(Constants::kind_t op, uint32_t num) override
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
void addError(position_t, const std::string &msg, const std::string &ctx="")
Definition: system.cpp:1403
void addWarning(position_t, const std::string &msg, const std::string &ctx="")
Definition: system.cpp:1411
void exprMitlRelease(int, int) override
void typeBoundedInt(PREFIX) override
Called whenever an integer type with a range is parsed.
void typeInt(PREFIX) override
Called whenever an integer type is parsed.
void exprBuiltinFunction1(Constants::kind_t) override
std::map< std::string, frame_t > dynamicFrames
frame_t parameters
The parameters.
Definition: system.h:332
void exprUnary(Constants::kind_t unaryop) override
void exprProbaExpected(const char *aggregatingOp) override
void typeScalar(PREFIX) override
Called whenever a scalar type is parsed.
static type_t createPrimitive(Constants::kind_t, position_t=position_t())
Create a primitive type.
Definition: type.cpp:527
void handleWarning(const std::string &) override
bool resolve(const std::string &, symbol_t &)
void exprAssignment(Constants::kind_t op) override
void exprPreIncrement() override
void typeName(PREFIX, const char *name) override
Called when a type name has been parsed.
void exprCallEnd(uint32_t n) override
bool isArray() const
Shortcut for is(ARRAY).
Definition: type.h:229
void process(const char *) override
ExpressionFragments & getExpressions()
void pushFrame(frame_t)
Push a new frame.
type_t rename(const std::string &from, const std::string &to) const
Replaces any LABEL labeled from occuring in the type with a LABEL to.
Definition: type.cpp:307
void exprProbaQuantitative(Constants::kind_t) override
static expression_t createDot(expression_t, int32_t=-1, position_t=position_t(), type_t=type_t())
Create a DOT expression.
void typeVoid() override
Called whenever a void type is parsed.
expression_t & get(uint32_t)
Returns the ith subexpression.
Definition: expression.cpp:659
expression_t toMITLAtom(expression_t e)
static expression_t createUnary(Constants::kind_t, expression_t, position_t=position_t(), type_t=type_t())
Create a unary expression.
static frame_t createFrame()
Creates and returns a new root-frame.
Definition: symbols.cpp:474
template_t * getDynamicTemplate(const std::string &name)
Definition: system.cpp:1026
void exprForAllDynamicBegin(const char *, const char *) override
void exprExistsDynamicEnd(const char *) override
void exprForAllDynamicEnd(const char *name) override
template_t * currentTemplate
The template currently being parsed.
void exprSumDynamicBegin(const char *, const char *) override
Base type for variables, clocks, etc.
Definition: system.h:43
type_t getSub() const
Returns the element type of an array.
Definition: type.cpp:193
ExpressionFragments fragments
Expression stack.
static string symbol(const char *str)
Extracts the alpha-numerical symbol used for variable/type identifiers.
Definition: xmlreader.cpp:107
std::string toString(bool old=false) const
Returns a string representation of the expression.
void typePop() override
Pop type at the topof the type stack.
std::stack< frame_t > frames
Frame stack.
static expression_t createTernary(Constants::kind_t, expression_t, expression_t, expression_t, position_t=position_t(), type_t=type_t())
Create a ternary expression.
void handleError(const std::string &) override
void typeBool(PREFIX) override
Called whenever a boolean type is parsed.
virtual void handleError(const std::string &)=0
void exprMitlUntil(int, int) override
Exception indicating a type error.
Definition: builder.h:39
type_t subst(symbol_t symbol, expression_t expr) const
Substitutes any occurence of symbol in any expression in the type (expressions that occur as ranges e...
Definition: type.cpp:323
void exprSpawn(int params) override
bool isMITL(expression_t e)
A reference to a frame.
Definition: symbols.h:183
expression_t expr
The initialiser.
Definition: system.h:46
void exprForAllBegin(const char *name) override
A reference to a type.
Definition: type.h:93
std::map< symbol_t, expression_t > mapping
The arguments.
Definition: system.h:333
type_t getType() const
Returns the type of this symbol.
Definition: symbols.cpp:205
static expression_t createDeadlock(position_t=position_t())
Create a DEADLOCK expression.
void exprProbaQualitative(Constants::kind_t, Constants::kind_t, double) override
void exprSimulate(int, bool=false, int=0) override
int32_t findIndexOf(const std::string &) const
Returns the index of the record or process field with the given label.
Definition: type.cpp:105
static void collectDependencies(std::set< symbol_t > &dependencies, expression_t expr)
void exprPostIncrement() override
type_t createLabel(const std::string &, position_t=position_t()) const
Creates a LABEL.
Definition: type.cpp:539
ExpressionBuilder(TimedAutomataSystem *)
bool isType(const char *) override
Must return true if and only if name is registered in the symbol table as a named type...
void exprBuiltinFunction3(Constants::kind_t) override
void exprNat(int32_t) override
A reference to an expression.
Definition: expression.h:70
#define defaultIntMax
void exprExistsBegin(const char *name) override
type_t getType() const
Returns the type of the expression.
Definition: expression.cpp:611
void * getData()
Returns the user data of this symbol.
Definition: symbols.cpp:216
void exprDouble(double) override
void exprForeachDynamicEnd(const char *name) override
void exprProbaCompare(Constants::kind_t, Constants::kind_t) override
void pushDynamicFrameOf(template_t *t, const std::string &name)
#define defaultIntMin
void exprExistsEnd(const char *name) 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
void exprBinary(Constants::kind_t binaryop) override
void exprDot(const char *) override
bool isLocation() const
Shortcut for is(LOCATION).
Definition: type.h:217
Definition: lexer.cc:817
static expression_t createConstant(int32_t, position_t=position_t())
Create a CONSTANT expression.
void typeDuplicate() override
Duplicate type at the top of the type stack.
void setType(type_t)
Sets the type of the expression.
Definition: expression.cpp:617
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 popDynamicFrameOf(const std::string &name)
static expression_t createBinary(Constants::kind_t, expression_t, expression_t, position_t=position_t(), type_t=type_t())
Create a binary expression.
void collectPossibleReads(std::set< symbol_t > &, bool collectRandom=false) const
void typeDouble(PREFIX) override
Called whenever a double type is parsed.
void typeClock(PREFIX) override
Called whenever a clock type is parsed.
declarations_t & getGlobals()
Returns the global declarations of the system.
Definition: system.cpp:961
TypeFragments typeFragments
Type stack.
static type_t createArray(type_t sub, type_t size, position_t=position_t())
Creates an array type.
Definition: type.cpp:467
void exprMitlDiamond(int, int) override
static type_t createProcess(frame_t, position_t=position_t())
Creates a new process type.
Definition: type.cpp:505
bool isRecord() const
Shortcut for is(RECORD).
Definition: type.h:238
static expression_t createIdentifier(symbol_t, position_t=position_t())
Create an IDENTIFIER expression.
Constants::kind_t getKind() const
Returns the kind of type object.
Definition: type.cpp:120
void exprForeachDynamicBegin(const char *, const char *) override
void exprPreDecrement() override
expression_t makeConstant(int value)
bool isProcess() const
Shortcut for is(PROCESS).
Definition: type.h:211
void addPosition(uint32_t position, uint32_t offset, uint32_t line, const std::string &path) override
Add mapping from an absolute position to a relative XML element.
symbol_t uid
The name.
Definition: system.h:331
int32_t scalar_count
Counter for creating unique scalarset names.