docstr: 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`
docstr_tok: ["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",",","can","not","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","`"]
code: 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 = []
  
      # 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()
  
      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()
  
imports: from collections import Counter, OrderedDict
  import copy
  import logging
  import numpy
  from six import string_types
  from .None import SPACES, types
  from .var import Var, InternalVar, ListVar
  from .visitors.dot_visitor import DotVisitor
  from .types.symbolic import k_used_symbols, k_num_internal_syms, any_symbolic, is_symbolic
  from .input_type import TupleInputType
label_desc: Use image node_id 2 to create a new Block object from inherited base classes: object with example: obj = Block(block_inputs, outer_op, name)