예제 #1
0
    def translate(self) -> List[Expr]:
        """Translate variables bound by IO operation call."""
        assert not self._equations, "translate is called twice."

        self._check()
        contexts = self._create_result_contexts()

        for result in contexts:
            if not isinstance(result.instance, ast.Name):
                raise_invalid_operation_use('not_variable_in_result_position',
                                            self._node)
            else:
                result.getter = self._translator.create_result_getter(
                    self._node, result.definition, self._ctx)
                self._set_variable(result)

                if self._io_ctx.contains_variable(result.var_name):
                    # Variable denotes a result of the operation being opened.
                    self._handle_opener_result_var(result)
                elif isinstance(result.var, PythonIOExistentialVar):
                    self._handle_existential_var(result)
                else:
                    # Normal variable, which is already defined.
                    self._handle_normal_var(result)

        return self._equations
예제 #2
0
 def _check(self) -> None:
     """Check that operation open is well-formed."""
     if self._operation.is_basic():
         raise_invalid_operation_use('open_basic_io_operation', self._node)
     if (len(self._operation_call.args) != len(
             self._operation.get_parameters())):
         raise_invalid_operation_use('result_used_argument', self._node)
예제 #3
0
def _get_opened_operation(node: ast.Call, ctx: Context) -> PythonIOOperation:
    """Get the operation that is being opened."""
    if (len(node.args) == 1 and isinstance(node.args[0], ast.Call)
            and isinstance(node.args[0].func, ast.Name)):
        containers = [ctx.module]
        containers.extend(ctx.module.get_included_modules())
        target = get_target(node.args[0], containers, None)
        if isinstance(target, PythonIOOperation):
            return target
    raise_invalid_operation_use('open_non_io_operation', node)
예제 #4
0
    def translate_get_ghost_output(self, node: ast.Assign,
                                   ctx: Context) -> List[Stmt]:
        """Translate ``GetGhostOutput``."""
        if len(node.targets) != 1:
            raise_invalid_get_ghost_output('multiple_targets', node)
        if not isinstance(node.targets[0], ast.Name):
            raise_invalid_get_ghost_output('target_not_variable', node)
        target_name = cast(ast.Name, node.targets[0]).id
        target = ctx.actual_function.get_variable(target_name)
        assert target

        operation_call, result_name_node = cast(ast.Call, node.value).args

        if not isinstance(result_name_node, ast.Str):
            raise_invalid_get_ghost_output('result_identifier_not_str', node)
        result_name = cast(ast.Str, result_name_node).s

        if not (isinstance(operation_call, ast.Call)
                and isinstance(operation_call.func, ast.Name)):
            raise_invalid_get_ghost_output('argument_not_io_operation', node)
        operation_call = cast(ast.Call, operation_call)
        operation_name = cast(ast.Name, operation_call.func).id

        if operation_name not in ctx.module.io_operations:
            raise_invalid_get_ghost_output('argument_not_io_operation', node)
        operation = ctx.module.io_operations[operation_name]

        result = None
        for result in operation.get_results():
            if result.name == result_name:
                break
        else:
            raise_invalid_get_ghost_output('invalid_result_identifier', node)
        assert result

        if result.type != target.type:
            raise_invalid_get_ghost_output('type_mismatch', node)

        if len(operation_call.args) != len(operation.get_parameters()):
            raise_invalid_operation_use('result_used_argument', node)
        getter = self.create_result_getter(operation_call, result, ctx)

        position = self.to_position(node, ctx)
        info = self.no_info(ctx)
        set_defined = self.set_var_defined(target, position, info)
        assignment = self.viper.LocalVarAssign(target.ref(), getter, position,
                                               info)

        return [assignment, set_defined]
예제 #5
0
 def _check(self) -> None:
     """Perform some well-formedness checks."""
     if len(self._result_definitions) != len(self._result_instances):
         raise_invalid_operation_use('result_mismatch', self._node)