// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*- /* libutap - Uppaal Timed Automata Parser. Copyright (C) 2002-2006 Uppsala University and Aalborg University. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef UTAP_INTERMEDIATE_HH #define UTAP_INTERMEDIATE_HH #include #include #include #include #include "utap/symbols.h" #include "utap/expression.h" #include "utap/position.h" namespace UTAP { /** Base type for variables, clocks, etc. The user data of the corresponding symbol_t points to this structure, i.e. v.uid.getData() is a pointer to v. */ struct variable_t { symbol_t uid; /**< The symbol of the variables */ expression_t expr; /**< The initialiser */ }; /** Information about a location. The symbol's user data points to this structure, i.e. s.uid.getData() is a pointer to s. Notice that the rate list is generated by the type checker; until then the rate expressions are part of the invariant. */ struct state_t { symbol_t uid; /**< The symbol of the location */ expression_t invariant; /**< The invariant */ expression_t costrate; /**< Rate expression */ int32_t locNr; /**< Location number in template */ }; /** Information about an edge. Edges have a source (src) and a destination (dst) locations. The guard, synchronisation and assignment are stored as expressions. */ struct edge_t { int nr; /**< Placement in input file */ bool control; /**< Controllable (true/false) */ state_t *src; /**< Pointer to source location */ state_t *dst; /**< Pointer to destination location */ frame_t select; /**< Frame for non-deterministic select */ expression_t guard; /**< The guard */ expression_t assign; /**< The assignment */ expression_t sync; /**< The synchronisation */ }; class BlockStatement; // Forward declaration /** Information about a function. The symbol's user data points to this structure, i.e. f.uid.getData() is a pointer to f. */ struct function_t { symbol_t uid; /**< The symbol of the function. */ std::set changes; /**< Variables changed by this function. */ std::set depends; /**< Variables the function depends on. */ std::list variables; /**< Local variables. */ BlockStatement *body; /**< Pointer to the block. */ function_t() : body(NULL) {} ~function_t(); }; struct progress_t { expression_t guard; expression_t measure; }; /** * Structure holding declarations of various types. Used by * templates and block statements. */ struct declarations_t { frame_t frame; std::list variables; /**< Variables */ std::list functions; /**< Functions */ std::list progress; /**< Progress measures */ /** Add function declaration. */ bool addFunction(type_t type, std::string, function_t *&); }; /** * Partial instance of a template. Every template is also a * partial instance of itself and therefore template_t is derived * from instance_t. A complete instance is just a partial instance * without any parameters. * * Even though it is possible to make partial instances of partial * instances, they are not represented hierarchically: All * parameters and arguments are merged into this one * struct. Therefore \a parameters contains both bound and unbound * symbols: Unbound symbols are parameters of this instance. Bound * symbols are inherited from another instance. Symbols in \a * parameters are ordered such that unbound symbols are listed * first, i.e., uid.getType().size() == parameters.getSize(). * * \a mapping binds parameters to expressions. * * \a arguments is the number of arguments given by the partial * instance. The first \a arguments bound symbols of \a parameters * are the corresponding parameters. For templates, \a arguments * is obviously 0. * * Restricted variables are those that are used either directly or * indirectly in the definition of array sizes. Any restricted * parameters have restriction on the kind of arguments they * accept (they must not depend on any free process parameters). * * If i is an instance, then i.uid.getData() == i. */ struct instance_t { symbol_t uid; /**< The name */ frame_t parameters; /**< The parameters */ std::map mapping; /**< The arguments */ size_t arguments; size_t unbound; struct template_t *templ; std::set restricted; /**< Restricted variables */ }; /** * Information about a template. A template is a parameterised * automaton with local declarations of variables and functions. */ struct template_t : public instance_t, declarations_t { symbol_t init; /**< The initial location */ frame_t templateset; /**< Template set decls */ std::list states; /**< Locations */ std::list edges; /**< Edges */ /** Add another location to template. */ state_t &addLocation(std::string, expression_t inv); /** Add edge to template. */ edge_t &addEdge(symbol_t src, symbol_t dst, bool type); }; /** * Channel priority information. The expression must be a a * channel or an array of channels. */ struct chan_priority_t { expression_t chanElement; int chanPriority; }; class TimedAutomataSystem; class SystemVisitor { public: virtual ~SystemVisitor() {} virtual void visitSystemBefore(TimedAutomataSystem *) {} virtual void visitSystemAfter(TimedAutomataSystem *) {} virtual void visitVariable(variable_t &) {} virtual bool visitTemplateBefore(template_t &) { return true; } virtual void visitTemplateAfter(template_t &) {} virtual void visitState(state_t &) {} virtual void visitEdge(edge_t &) {} virtual void visitInstance(instance_t &) {} virtual void visitProcess(instance_t &) {} virtual void visitFunction(function_t &) {} virtual void visitTypeDef(symbol_t) {} virtual void visitProgressMeasure(progress_t &) {} }; class TimedAutomataSystem { public: TimedAutomataSystem(); virtual ~TimedAutomataSystem(); /** Returns the global declarations of the system. */ declarations_t &getGlobals(); /** Returns the templates of the system. */ std::list &getTemplates(); /** Returns the processes of the system. */ std::list &getProcesses(); void addPosition( uint32_t position, uint32_t offset, uint32_t line, std::string path); const Positions::line_t &findPosition(uint32_t position) const; variable_t *addVariableToFunction( function_t *, frame_t, type_t, std::string, expression_t initital); variable_t *addVariable( declarations_t *, type_t type, std::string, expression_t initial); void addProgressMeasure( declarations_t *, expression_t guard, expression_t measure); template_t &addTemplate(std::string, frame_t params); instance_t &addInstance( std::string name, instance_t &instance, frame_t params, const std::vector &arguments); void addProcess(instance_t &instance); void accept(SystemVisitor &); void setBeforeUpdate(expression_t); expression_t getBeforeUpdate(); void setAfterUpdate(expression_t); expression_t getAfterUpdate(); /* The default priority for channels is also used for 'tau * transitions' (i.e. non-synchronizing transitions). */ void setChanPriority(expression_t chan, int priority); const std::list& getChanPriorities() const; std::list& getMutableChanPriorities(); void setDefaultChanPriority(int priority); int getTauPriority() const; /** Sets process priority for process \a name. */ void setProcPriority(const char* name, int priority); /** Returns process priority for process \a name. */ int getProcPriority(const char* name) const; /** Returns true if system has some priority declaration. */ bool hasPriorityDeclaration() const; protected: bool hasPriorities; int defaultChanPriority; std::list chanPriorities; std::map procPriority; protected: // The list of templates. std::list templates; // The list of template instances. std::list instances; // List of processes. std::list processes; // Global declarations declarations_t global; expression_t beforeUpdate; expression_t afterUpdate; variable_t *addVariable( std::list &variables, frame_t frame, type_t type, std::string); public: void addError(position_t, std::string); void addWarning(position_t, std::string); bool hasErrors() const; bool hasWarnings() const; const std::vector &getErrors() const; const std::vector &getWarnings() const; void clearErrors(); void clearWarnings(); private: std::vector errors; std::vector warnings; Positions positions; }; } #endif