def __init__(self, block_inputs=None, outer_op=None, name=None):
        """
        Inputs:

        block_inputs: python tuple[Var].

            block_inputs is None except when the block represents loop. By
            convention block_inputs should have name ending in '.x', and the
            Variable are not produced by any op (block_inputs[i]._op is None).

            Ex:

            #    main(%a: (1, 2, fp32),
            #         %b: (1, 2, fp32),
            #         %c: (1, 2, fp32)) {
            #      block0() {
            #        %const1: (1, fp32) = const(...)
            #        %loop:0: (1, 2, fp32), %loop:1: (1, 2, fp32) = \
            #        while_loop(loop_vars=(%a, %b))
            #          loop_cond(%a.x, %b.x) {
            #            %blah: (bool) = some_op(x=%a.x, y=%b.x)
            #            %cond_var: (bool) = some_op2(x=%a.x, y=%blah)
            #          } -> (%cond_var)
            #          loop_body(%a.x, %b.x) {
            #            %add_0: (1, 2, fp32) = add(x=%a.x, y=%b.x)
            #          } -> (%add_0, %b.x)
            #        %linear: (1, fp32) = linear(...)
            #      } -> (%loop:0, %loop:1)
            #    }

            %a.x, %b.x are block_inputs.

            `some_op` in `loop_cond` block can access %a, %b, %a.x, %b.x.
            `some_op`, however, cannot take %linear as input.

        outer_op: Operation
            The enclosing op. None iff this Block is an Function.

        function_inputs: tuple[Var]
            function_inputs are always visible for this block and all blocks
            nested within. If function_inputs is None, get it from
            `outer_op.block`
        """
        self.name = name
        if self.name is None:
            self.name = Block._get_new_name()

        # list[Operation]. Topologically sorted.
        self.operations = CacheDoublyLinkedList()

        # Must be set before self.validate()
        self.outer_op = outer_op

        self._block_inputs = block_inputs
        if self._block_inputs is None:
            self._block_inputs = tuple()

        # list[Var]. This is converted to str when generating MIL proto.
        self._outputs = []

        # If we create const, whose inputs (mode, val) cannot be const
        # (infinite recursion). They must be considered as always visible.
        self._internal_vars = set()

        # List[ScopeSource]. During graph pass, those scope source cannot be missed
        self._essential_scope_sources = []

        if self.outer_op is None and not isinstance(self, Function):
            msg = "Block {} is not Function and thus outer_op cannot be None"
            raise ValueError(msg.format(self.name))

        self.validate()

        Inputs:

        block_inputs: python tuple[Var].

            block_inputs is None except when the block represents loop. By
            convention block_inputs should have name ending in '.x', and the
            Variable are not produced by any op (block_inputs[i]._op is None).

            Ex:

            #    main(%a: (1, 2, fp32),
            #         %b: (1, 2, fp32),
            #         %c: (1, 2, fp32)) {
            #      block0() {
            #        %const1: (1, fp32) = const(...)
            #        %loop:0: (1, 2, fp32), %loop:1: (1, 2, fp32) =             #        while_loop(loop_vars=(%a, %b))
            #          loop_cond(%a.x, %b.x) {
            #            %blah: (bool) = some_op(x=%a.x, y=%b.x)
            #            %cond_var: (bool) = some_op2(x=%a.x, y=%blah)
            #          } -> (%cond_var)
            #          loop_body(%a.x, %b.x) {
            #            %add_0: (1, 2, fp32) = add(x=%a.x, y=%b.x)
            #          } -> (%add_0, %b.x)
            #        %linear: (1, fp32) = linear(...)
            #      } -> (%loop:0, %loop:1)
            #    }

            %a.x, %b.x are block_inputs.

            `some_op` in `loop_cond` block can access %a, %b, %a.x, %b.x.
            `some_op`, however, cannot take %linear as input.

        outer_op: Operation
            The enclosing op. None iff this Block is an Function.

        function_inputs: tuple[Var]
            function_inputs are always visible for this block and all blocks
            nested within. If function_inputs is None, get it from
            `outer_op.block`
        
coremltools/converters/mil/mil/block.py