@staticmethod
  def find_classes_methods(bytecode):
    """
      Finds the indices of the classes and methods declared in the bytecode. This is done
      by matching code_object of the declaration and the ``MAKE_FUNCTION`` or ``BUILD_CLASS``
      opcode.
    """
    class_indices = set()
    method_indices = set()
    class_lines = set()
    method_lines = set()

    # code object -> (start, end)
    co_lines = {}
    classes_co = set()
    methods_co = set()

    i, length = 0, len(bytecode)
    while i < length:
      tpl = bytecode[i]
      lineno, op_code, co = tpl[1], tpl[2], tpl[5]
      if op_code == BUILD_CLASS:
        class_co = bytecode[i - 3][5]
        co_lines[class_co] = lineno
        classes_co.add(class_co)
        class_lines.add(lineno)
      elif op_code in (MAKE_FUNCTION, MAKE_CLOSURE):
        if i < length - 3 and bytecode[i + 1][2] == CALL_FUNCTION and bytecode[i + 2][2] == BUILD_CLASS:
          i += 1
          continue
        prev_co = bytecode[i - 1][5]
        method_lines.add(lineno)
        methods_co.add(prev_co)
        co_lines[prev_co] = lineno
      i += 1

    # This multi-pass should be refactored...
    for decl_co in co_lines:
      if decl_co not in methods_co and decl_co not in classes_co:
        continue
      dest_set = method_indices if decl_co in methods_co else class_indices
      i, length = 0, len(bytecode)
      start_index, end_index = 0, 0
      while i < length:
        co = bytecode[i][5]
        if co == decl_co:
          start_index = i
          j = i + 1
          while j < length:
            if bytecode[j][5] == decl_co:
              end_index = j
            j += 1
          break
        i += 1
      # logger.debug("decl_co(%d, %d) := %s", start_index, end_index, decl_co)
      dest_set.add((start_index, end_index))

    return class_indices, method_indices
dataset/ETHPy150Open neuroo/equip/equip/bytecode/code.py/BytecodeObject.find_classes_methods/original