Exemple #1
0
    def _condition(self, action, automaton):
        """
        Always translate a conditional action boolean expression or statement string into a corresponding boolean
        cnditional expression or C statement string correspondingly. Each such conditional expression or statement is
        parsed and all entries of labels and the other model expressions are replaced by particular C implementation.
        Note, that if a label with different interface matches is used than each string can be translated into several
        ones depending on the number of interfaces but keeping the original order with a respect to the other statements
        or boolean expressions.

        :param action: Action object.
        :param automaton: Automaton object which contains the condition.
        :return: [list of strings with lines of C code statements of the code block],
                 [list of strings with new local variable declarations required for the block],
                 [list of strings with boolean conditional expressions which guard code block entering],
                 [list of strings with model comments which embrace the code block]
        """
        code, v_code, conditions, comments = list(), list(), list(), list()

        # Make comments
        comment = action.comment
        comments.append(action_model_comment(action, comment, begin=True))
        comments.append(action_model_comment(action, None, begin=False))

        # Add additional conditions
        for stm in action.condition:
            conditions.extend(self._cmodel.text_processor(automaton, stm))

        for stm in action.statements:
            code.extend(self._cmodel.text_processor(automaton, stm))

        return code, v_code, conditions, comments
Exemple #2
0
    def _receive(self, action, automaton):
        """
        Generate code block for receive action. Require more detailed implementation in your translation.

        :param action: Action object.
        :param automaton: Automaton object.
        :return: [list of strings with lines of C code statements of the code block],
                 [list of strings with new local variable declarations required for the block],
                 [list of strings with boolean conditional expressions which guard code block entering],
                 [list of strings with model comments which embrace the code block]
        """
        code, v_code, conditions, comments = list(), list(), list(), list()

        # Make comments
        comment = action.comment.format(automaton.process.category.upper())
        comments.append(action_model_comment(action, comment, begin=True))
        comments.append(action_model_comment(action, None, begin=False))

        return code, v_code, conditions, comments
Exemple #3
0
    def _subprocess(self, action, automaton):
        """
        Generate reduction to a subprocess as a code block. Add your own logic in the corresponding implementation.

        :param action: Action object.
        :param automaton: Automaton object which contains the subprocess.
        :return: [list of strings with lines of C code statements of the code block],
                 [list of strings with new local variable declarations required for the block],
                 [list of strings with boolean conditional expressions which guard code block entering],
                 [list of strings with model comments which embrace the code block]
        """
        code, v_code, conditions, comments = list(), list(), list(), list()

        # Make comments
        comment = action.comment
        comments.append(action_model_comment(action, comment, begin=True))
        comments.append(action_model_comment(action, None, begin=False))

        # Add additional condition
        for stm in action.condition:
            conditions.extend(self._cmodel.text_processor(automaton, stm))

        return code, v_code, conditions, comments
Exemple #4
0
    def _art_action(self, action, automaton):
        """
        Generate a code block for an artificial node in FSA which does not correspond to any action.

        :param action: Action object.
        :param automaton: Automaton object which contains the artificial node.
        :return: [list of strings with lines of C code statements of the code block],
                 [list of strings with new local variable declarations required for the block],
                 [list of strings with boolean conditional expressions which guard code block entering],
                 [list of strings with model comments which embrace the code block]
        """
        # Make comments
        code, v_code, conditions, comments = list(), list(), list(), list()
        comments.append(
            action_model_comment(
                action,
                'Artificial state in scenario'.format(automaton.process.name)))

        return code, v_code, conditions, comments
Exemple #5
0
    def _dispatch(self, action, automaton):
        """
        Generate a code block for a dispatch action of the process for which the automaton is generated. A dispatch code
        block is always generated in a fixed form: as a function call of auxiliary function. Such a function contains
        switch or if operator to choose one of available optional receivers to send the signal. Implementation of
        particular dispatch to particular receiver is configurable and can be implemented differently in various
        translation.

        :param action: Action object.
        :param automaton: Automaton object which contains the dispatch.
        :return: [list of strings with lines of C code statements of the code block],
                 [list of strings with new local variable declarations required for the block],
                 [list of strings with boolean conditional expressions which guard code block entering],
                 [list of strings with model comments which embrace the code block]
        """
        code, v_code, conditions, comments = list(), list(), list(), list()

        # Determine peers to receive the signal
        automata_peers = sortedcontainers.SortedDict()
        if len(action.peers) > 0:
            # Do call only if model which can be called will not hang
            extract_relevant_automata(
                self._logger,
                self._event_fsa + self._model_fsa + [self._entry_fsa],
                automata_peers, action.peers, Receive)
        else:
            # Generate comment
            code.append(
                "/* Dispatch {!r} is not expected by any process, skipping the action */"
                .format(action.name))

        # Make comments
        if len(automata_peers) > 0:
            category = list(automata_peers.values()
                            )[0]['automaton'].process.category.upper()
            comment = action.comment.format(category)
        else:
            comment = 'Skip the action, since no peers has been found.'
        comments.append(action_model_comment(action, comment, begin=True))
        comments.append(action_model_comment(action, None, begin=False))

        # Add given conditions from a spec
        conditions = []
        if action.condition and len(action.condition) > 0:
            for statement in action.condition:
                cn = self._cmodel.text_processor(automaton, statement)
                conditions.extend(cn)

        if len(automata_peers) > 0:
            # Add conditions on base of dispatches
            checks = self._relevant_checks(automata_peers)
            if len(checks) > 0:
                if automaton in self._model_fsa:
                    conditions.append("({})".format(' || '.join(checks)))
                else:
                    # Convert conditions into assume, because according to signals semantics process could not proceed
                    # until it sends a signal and condition describes precondition to prevent signal sending to a
                    # wrong process.
                    if len(checks) > 0:
                        code.append('ldv_assume({});'.format(
                            ' || '.join(checks)))

            # Generate artificial function
            body = []

            if not self._conf.get('direct control functions calls'):
                body = ['int ret;']

            # Check dispatch type
            replicative = False
            for a_peer in automata_peers:
                for act in automata_peers[a_peer]['actions']:
                    if act.replicative:
                        replicative = True
                        break

            # Determine parameters
            df_parameters = []
            function_parameters = []

            # Add parameters
            for index in range(len(action.parameters)):
                # Determine dispatcher parameter
                # We expect strictly one
                dispatcher_access = automaton.process.resolve_access(
                    action.parameters[index])
                variable = automaton.determine_variable(
                    dispatcher_access.label)
                function_parameters.append(variable.declaration)
                df_parameters.append(variable.name)

            # Generate blocks on each receive to another process
            # You can implement your own translation with different implementations of the function
            pre, blocks, post = self._dispatch_blocks(action, automaton,
                                                      function_parameters,
                                                      automata_peers,
                                                      replicative)
            if len(blocks) > 0:
                body += pre

                # Print body of a dispatching function
                if action.broadcast:
                    for block in blocks:
                        body += block
                else:
                    imply_signals = self._conf.get('do not skip signals')
                    if len(blocks) > 2 or (len(blocks) == 2
                                           and not imply_signals):
                        body.append('switch (ldv_undef_int()) {')
                        for index in range(len(blocks)):
                            body.extend(
                                ['\tcase {}: '.format(index) + '{'] + \
                                ['\t\t' + stm for stm in blocks[index]] + \
                                ['\t\tbreak;',
                                 '\t};']
                            )
                        if imply_signals:
                            body.append('\tdefault: ldv_assume(0);')
                        body.append('};')
                    elif len(blocks) == 2 and imply_signals:
                        body.append('if (ldv_undef_int()) {')
                        body.extend(['\t' + stm for stm in blocks[0]])
                        body.extend(['}', 'else {'])
                        body.extend(['\t' + stm for stm in blocks[1]])
                        body.extend(['}'])
                    elif len(blocks) == 1 and not imply_signals:
                        body.append('if (ldv_undef_int()) {')
                        body.extend(['\t' + stm for stm in blocks[0]])
                        body.extend(['}'])
                    else:
                        body.extend(blocks[0])

                if len(function_parameters) > 0:
                    df = Function(
                        "emg_dispatch_{}_{}".format(str(action),
                                                    str(automaton)),
                        "void f({})".format(', '.join([
                            function_parameters[index].to_string(
                                'arg{}'.format(index),
                                typedef='complex_and_params')
                            for index in range(len(function_parameters))
                        ])))
                else:
                    df = Function(
                        "emg_dispatch_{}_{}".format(str(action),
                                                    str(automaton)),
                        "void f(void)")
                df.definition_file = automaton.process.file
                body.extend(post)
                body.append('return;')
                df.body.extend(body)

                # Add function definition
                self._cmodel.add_function_definition(df)

                code.extend(
                    ['{}({});'.format(df.name, ', '.join(df_parameters))])
            else:
                # This is becouse translation can have specific restrictions
                self._logger.debug(
                    f'No block to implement signal receive of actioon {str(action)} in {str(automaton)}'
                )
                code.append(
                    '/* Skip the dispatch because there is no process to receive the signal */'
                )
        else:
            self._logger.debug(
                f'No peers to implement signal receive of actioon {str(action)} in {str(automaton)}'
            )
            code.append(
                '/* Skip the dispatch because there is no process to receive the signal */'
            )

        return code, v_code, conditions, comments