예제 #1
0
    def __init__(self, succgen, query):
        self.succgen = succgen
        self.query = query
        self.query_type = None

        #Short-circuit, if no query:
        if query == "":
            self.isGoal = lambda s: False
            return

        #Parse query, and compile goal status query XXX
        self.query_type = query.strip()[:3]

        if self.query_type == "E<>":
            #form: E<> some_expression
            query = (query.strip()[3:]).strip()
            query_ast = expressionParser.parse_expression(query)
            self.goal_func_python = util.expression_to_python(query_ast, self.succgen)
            logger.info('Goal func: %s', self.goal_func_python)
            self.goal_expr = compile(self.goal_func_python, "<goal func>", 'eval')
            self.isGoal = self.isGoal_reachability
        elif self.query_type == "sup":
            #form: sup: some_expression
            self.sup_val = None
            query = (query.strip()[4:]).strip()
            query_ast = expressionParser.parse_expression(query)
            self.sup_expr_python = util.expression_to_python(query_ast, self.succgen)
            logger.info('sup expr.: %s', self.sup_expr_python)
            self.sup_expr = compile(self.sup_expr_python, "<goal func>", 'eval')
            self.isGoal = self.isGoal_sup
        else:
            raise IllegalQueryException(
                'Sorry, only reachability ("E<>") and sup supported for now')
예제 #2
0
    def bounds_for_type(self, someType):    
        if someType.type == 'NodeTypedef':
            someType = someType.children[0]

        assert someType.type == 'TypeInt' #TODO other types
        lowerexpr = util.expression_to_python(someType.children[0].children[0])
        upperexpr = util.expression_to_python(someType.children[1].children[0])

        lower = eval(lowerexpr, {}, self.constants)
        upper = eval(upperexpr, {}, self.constants)

        return (lower, upper)
예제 #3
0
    def parse_and_calculate_constants(self):
        self.lex = lexer.lexer
        try:
            self.pars = parser.Parser(self.nta.declaration, self.lex)
        except Exception:
            opaal.util.emergencyExitUppaalCParser(
                "Error in parsing the model to calculation constants.")
        self.declvisitor = parser.DeclVisitor(self.pars)
        self.declvisitor.visit(self.pars.AST)

        self.constants = {}
        #constant overrides
        for (cident, cval) in self.constant_overrides.iteritems():
            #XXX assumes expression is already python
            self.constants[cident] = eval(cval, {}, self.constants)
        #evaluate constants to values
        for (cident, cval) in self.declvisitor.constants.iteritems():
            if not cident in self.constants:
                self.constants[cident] = eval(util.expression_to_python(cval),
                                              {}, self.constants)

        try:
            #evaluate VarDecl expressions
            for vdecl in self.declvisitor.variables:
                util.eval_vardecl_expressions(vdecl, self.constants)
        except Exception:
            opaal.util.emergencyExitUppaalCParser(
                "Error in evaluating variable properties (e.g. array dimensions), for '%s'."
                % (vdecl.identifier))
예제 #4
0
 def parse_and_calculate_constants(self):
     self.lex = lexer.lexer
     try:
         self.pars = parser.Parser(self.nta.declaration, self.lex)
     except Exception:
         opaal.util.emergencyExitUppaalCParser("Error parsing the model for calculating constants.")
     self.declvisitor = parser.DeclVisitor(self.pars)
     self.declvisitor.visit(self.pars.AST)
     
     self.constants = {}
     #constant overrides
     for (cident, cval) in self.constant_overrides.iteritems():
         #XXX assumes expression is already python
         self.constants[cident] = eval(cval, {}, self.constants)
     #evaluate constants to values
     for (cident, cval) in self.declvisitor.constants.iteritems():
         if not cident in self.constants:
             self.constants[cident] = eval(util.expression_to_python(cval), {}, self.constants)
예제 #5
0
    def _lu_collect_comparisons(self, node, t_idx, l_idx, lower_eq_graph,
                                upper_eq_graph):
        if node.type in ('Greater', 'GreaterEqual', 'Less', 'LessEqual',
                         'Equal', 'NotEqual'):
            idents = [n for n in node.children if n.type == 'Identifier']
            clockside = None
            #is left side clock?
            if node.children[0].type == 'Identifier' and \
                    node.children[1].type != 'Identifier':
                clockident = node.children[0]
                exprnode = node.children[1]
                clockside = "left"
            #is right side clock?
            elif node.children[1].type == 'Identifier' and \
                    node.children[0].type != 'Identifier':
                clockident = node.children[1]
                exprnode = node.children[0]
                clockside = "right"
                if clockident.children[0] in self._clocks:
                    assert False, "Clock on the right of comparison not supported (%s, %s)" % (
                        clockident, exprnode)
                else:
                    #not a clock
                    return True
            #comparing two clocks?
            elif node.children[0].type == 'Identifier' and \
                    node.children[1].type == 'Identifier':
                clockident1 = node.children[0]
                clockident2 = node.children[1]
                #comparing clocks do not affect the max constants
                if clockident1.children[
                        0] in self._clocks and clockident2.children[
                            0] in self._clocks:
                    return True
                elif clockident1.children[0] in self._clocks:
                    #left side clock, right side some expression
                    clockident = clockident1
                    exprnode = node.children[1]
                    clockside = "left"
                elif clockident2.children[0] in self._clocks:
                    #right side clock, left side some expression
                    clockident = clockident2
                    exprnode = node.children[0]
                    clockside = "right"
                    assert False, "Clock on the right of comparison not supported"
                else:
                    #comparing two non-clocks
                    return True
            else:
                #Some expression we don't know about
                logger.warning("Unknown expression: %s", node)
                return True

            if not clockident.children[0] in self._clocks:
                return True

            #try to calc expression, might be constant
            try:
                constant = eval(util.expression_to_python(exprnode), {},
                                self.constants)
            except:
                #variables in expression
                a = util.range_for_expression(exprnode, self.declvisitor,
                                              self.constants)
                constant = a[1]

            logger.debug("    found comparison of %s to %d",
                         clockident.children[0], constant)

            # lower bound
            if node.type in ('Greater', 'GreaterEqual', 'Equal',
                             'NotEqual') and clockside == "left":
                lower_eq_graph[self._calc_index(t_idx, l_idx, clockident.children[0])][0] = \
                        max(constant, lower_eq_graph[self._calc_index(t_idx, l_idx, clockident.children[0])][0])
            # upper bound -- not an elif!
            if node.type in ('Less', 'LessEqual', 'Equal',
                             'NotEqual') and clockside == "left":
                upper_eq_graph[self._calc_index(t_idx, l_idx, clockident.children[0])][0] = \
                        max(constant, upper_eq_graph[self._calc_index(t_idx, l_idx, clockident.children[0])][0])

        return True
예제 #6
0
    def expand_system_declaration(self):
        """Expand the model according to the system declaration:
        * For each automaton in the system create a unique template, 
          converting parameters to local variables.
        * Promote local variables to uniquely named global vars.
        """
        nta = self.nta
        ret = pyuppaal.NTA(declaration=nta.declaration)

        try:
            parser = systemdec_parser.SystemDeclarationParser(nta.system)
            res = parser.AST
        except Exception:
            opaal.util.emergencyExitSytemDecl("In the simplyfication phase a parsing error occurred when the system declaration in your model was being parsed.")
        #res.visit()

        # Instantiate process assignments
        for c in res.children:
            if c.type == 'ProcessAssignment':
                ident = c.leaf.children[0]
                tname = c.children[0].leaf.children[0]
                try:
                    template = [t for t in nta.templates if t.name == tname][0]
                except IndexError:
                    raise util.PyuppaalError("Template '%s' for instantiating '%s' not found!" % (tname, ident))
                inst_parameters = c.children[0].children

                #XXX copy over logic for implicit instantiation below on when to inline and when to convert
                #(convert'ing will fail for e.g. train-gate because of mis-parsing the sync's)
                formal_parameters = [p.strip() for p in template.parameter.split(',')]
                formal_parameter_idents = []
                for p in formal_parameters:
                    if p:
                        pident = p.split(' ')[-1]
                        formal_parameter_idents += [pident]

                if len(inst_parameters) != len(formal_parameter_idents):
                    raise util.PyuppaalError("Incorrect number of parameters for template '%s' for instantiating '%s'" % (tname, ident))

                if len(inst_parameters) == 0:
                    instantiated_template = copy.deepcopy(template)
                else:
                    #make parameters local variables
                    instantiated_template = copy.deepcopy(template)
                    for (formal_param, pnode) in zip(formal_parameters, 
                            inst_parameters):
                        instantiated_template.declaration = formal_param + " = " + \
                            str(eval(util.expression_to_python(pnode), {}, self.constants)) + ";\n" + \
                                instantiated_template.declaration
                instantiated_template.parameter = ''
                instantiated_template.name = ident

                #add to templates
                nta.templates += [instantiated_template]


        systemsnode = [c for c in res.children if c.type == 'System'][0]
        #systemsnode.visit()
        #print nta.templates
        
        retsystems = []
        prevprio = -1
        for inst in systemsnode.children:
            prio = inst.priority
            ident = inst.leaf
            tname = ident.children[0]

            temp = [t for t in nta.templates if t.name == tname][0]
            if prevprio == -1: #first process
                separator = ""
            else:
                separator = (prio != prevprio) and " < " or ", "
            prevprio = prio
            #case with no pars
            if temp.parameter.strip() == '':
                self.add_template_promote_local_vars(ret, temp)
                retsystems += [separator, temp.name]
            #case where we instantiate based on possible parameter values
            else:
                comb_temps = [copy.deepcopy(temp)]
                comb_temps[0].parameter = ''
                for par in [p.strip() for p in temp.parameter.split(',')]:
                    par_parts = par.split(' ')
                    if len(par_parts) == 2:
                        (constness, typename, ident) = ("", par_parts[0], par_parts[1])
                    else:
                        (constness, typename, ident) = par_parts
                    someType = self.pars.getType(typename)
                    lower, upper = self.bounds_for_type(someType.children[0])
                    
                    new_temps = []
                    for oldtemp in comb_temps:
                        for x in range(lower, upper+1):
                            if constness:
                                #inline const parameters
                                new_temp = self.inline_var_in_temp(oldtemp, ident, x)
                                new_temp.name += '_' + str(x)
                                new_temps += [new_temp]
                            else:
                                #make variable parameters local vars
                                new_temp = copy.deepcopy(oldtemp)
                                new_temp.declaration = constness + " " + typename + " " + ident + " = " + str(x) + ";\n" + \
                                    new_temp.declaration
                                new_temp.name += '_' + str(x)
                                new_temps += [new_temp]
                    comb_temps = new_temps
                for temp in comb_temps:
                    self.add_template_promote_local_vars(ret, temp)
                    retsystems += [separator, temp.name]
                    separator = ", "
            #TODO other cases
        ret.system = "system " + "".join(retsystems) + ";"
        self.nta = ret