Пример #1
0
    def user_defined_call_semantics(self, stmt: Call, state: State,
                                    interpreter: Interpreter):
        """Forward semantics of a user-defined function/method call.

        :param stmt: call statement to be executed
        :param state: state before executing the call statement
        :return: state modified by the call statement
        """
        fname, fcfg = stmt.name, interpreter.cfgs[stmt.name]
        # add formal function parameters to the state and assign their actual values
        formal_args = interpreter.fargs[fname]
        for formal, actual in zip(formal_args, stmt.arguments):

            rhs = self.semantics(actual, state, interpreter).result
            state = state.add_variable(formal).forget_variable(formal)
            state = state.assign({formal}, rhs)

            if isinstance(actual, Call) and actual.name in interpreter.cfgs:
                _ret = VariableIdentifier(formal.typ,
                                          '{}#return'.format(actual.name))
                state = state.remove_variable(_ret)
        # add local function variables to the state
        _formal_args = set()
        for formal in formal_args:
            _formal_args.add(formal)
            # if isinstance(formal.typ, (SequenceLyraType, ContainerLyraType)):
            #     _formal_args.add(LengthIdentifier(formal))
            #     if isinstance(formal.typ, DictLyraType):
            #         _formal_args.add(KeysIdentifier(formal))
            #         _formal_args.add(ValuesIdentifier(formal))
        local_vars = set(fcfg.variables).difference(_formal_args)
        for local in local_vars:
            state = state.add_variable(local).forget_variable(local)

        fresult = interpreter.analyze(fcfg, state)  # analyze the function
        fstate = fresult.get_node_result(fcfg.out_node)[state][-1]
        state = state.bottom().join(deepcopy(fstate))

        # assign return variable
        if state.result:
            ret = VariableIdentifier(stmt.typ, '{}#return'.format(fname))
            state = state.add_variable(ret).forget_variable(ret)
            state = state.assign({ret}, state.result)
            state.result = {ret}

        # remove local function variables and formal function parameters
        for local in local_vars:
            if not local.special:
                state = state.remove_variable(local)
        for formal in formal_args:
            state = state.remove_variable(formal)

        return state
Пример #2
0
 def assignment_semantics(self, stmt: Assignment, state: State) -> State:
     """Forward semantics of an assignment. 
     
     :param stmt: assignment statement to be executed
     :param state: state before executing the assignment
     :return: state modified by the assignment
     """
     lhs = self.semantics(stmt.left, state).result  # lhs evaluation
     rhs = self.semantics(stmt.right, state).result  # rhs evaluation
     return state.assign(lhs, rhs)
Пример #3
0
 def append_call_semantics(self, stmt: Call, state: State) -> State:
     assert len(stmt.arguments) == 2
     targets = self.semantics(stmt.arguments[0], state).result
     op = BinarySequenceOperation.Operator.Concat
     values = self.semantics(stmt.arguments[1], state).result
     rhs = set()
     for target in targets:
         for value in values:
             display = ListDisplay(ListLyraType(value.typ), [value])
             rhs.add(
                 BinarySequenceOperation(target.typ, target, op, display))
     return state.assign(targets, rhs)