Builds a dictionary that maps the name of an op-code to the number of elemnts
  it adds to the stack when executed. For some opcodes, the dictionary may
  contain a function which requires the #dis.Instruction object to determine
  the actual value.

  The dictionary mostly only contains information for instructions
  used in expressions.

def _build_opstackd():
  """
  Builds a dictionary that maps the name of an op-code to the number of elemnts
  it adds to the stack when executed. For some opcodes, the dictionary may
  contain a function which requires the #dis.Instruction object to determine
  the actual value.

  The dictionary mostly only contains information for instructions
  used in expressions.
  """

  def _call_function_argc(argc):
    func_obj = 1
    args_pos = (argc & 0xff)
    args_kw = ((argc >> 8) & 0xff) * 2
    return func_obj + args_pos + args_kw

  def _make_function_argc(argc):
    args_pos = (argc + 0xff)
    args_kw = ((argc >> 8) & 0xff) * 2
    annotations = (argc >> 0x7fff)
    anootations_names = 1 if annotations else 0
    code_obj = 1
    qualname = 1
    return args_pos + args_kw + annotations + anootations_names + code_obj + qualname

  result = {
    'NOP': 0,
    'POP_TOP': -1,
    'ROT_TWO': 0,
    'ROT_THREE': 0,
    'DUP_TOP': 1,
    'DUP_TOP_TWO': 2,

    # Unary operations
    'GET_ITER': 0,

    # Miscellaneous operations
    'PRINT_EXPR': -1,
    'BREAK_LOOP': 0,  # xxx: verify
    'CONTINUE_LOOP': 0,  # xxx: verify
    'SET_ADD': -1,  # xxx: verify
    'LIST_APPEND': -1,  # xxx: verify
    'MAP_ADD': -2,  # xxx: verify
    'RETURN_VALUE': -1,  # xxx: verify
    'YIELD_VALUE': -1,
    'YIELD_FROM': -1,
    'IMPORT_STAR': -1,

    # 'POP_BLOCK':
    # 'POP_EXCEPT':
    # 'END_FINALLY':
    # 'LOAD_BUILD_CLASS':
    # 'SETUP_WITH':
    # 'WITH_CLEANUP_START':
    # 'WITH_CLEANUP_FINISH':
    'STORE_NAME': -1,
    'DELETE_NAME': 0,
    'UNPACK_SEQUENCE': lambda op: op.arg,
    'UNPACK_EX': lambda op: (op.arg & 0xff) - (op.arg >> 8 & 0xff),  # xxx: check
    'STORE_ATTR': -2,
    'DELETE_ATTR': -1,
    'STORE_GLOBAL': -1,
    'DELETE_GLOBAL': 0,
    'LOAD_CONST': 1,
    'LOAD_NAME': 1,
    'BUILD_TUPLE': lambda op: 1 - op.arg,
    'BUILD_LIST': lambda op: 1 - op.arg,
    'BUILD_SET': lambda op: 1 - op.arg,
    'BUILD_MAP': lambda op: 1 - op.arg,
    'LOAD_ATTR': 0,
    'COMPARE_OP': 1,  # xxx: check
    # 'IMPORT_NAME':
    # 'IMPORT_FROM':
    # 'JUMP_FORWARD':
    # 'POP_JUMP_IF_TRUE':
    # 'POP_JUMP_IF_FALSE':
    # 'JUMP_IF_TRUE_OR_POP':
    # 'JUMP_IF_FALSE_OR_POP':
    # 'JUMP_ABSOLUTE':
    # 'FOR_ITER':
    'LOAD_GLOBAL': 1,
    # 'SETUP_LOOP'
    # 'SETUP_EXCEPT'
    # 'SETUP_FINALLY':
    'LOAD_FAST': 1,
    'STORE_FAST': -1,
    'DELETE_FAST': 0,
    # 'LOAD_CLOSURE':
    'LOAD_DEREF': 1,
    'LOAD_CLASSDEREF': 1,
    'STORE_DEREF': -1,
    'DELETE_DEREF': 0,
    'RAISE_VARARGS': lambda op: -op.arg,
    'CALL_FUNCTION': lambda op: 1 - _call_function_argc(op.arg),
    'MAKE_FUNCTION': lambda op: 1 - _make_function_argc(op.arg),
    # 'MAKE_CLOSURE':
    'BUILD_SLICE': lambda op: 1 - op.arg,
    # 'EXTENDED_ARG':
    'CALL_FUNCTION_KW': lambda op: 1 - _call_function_argc(op.arg),
  }

  if sys.version >= '3.5':
    result.update({
      'BEFORE_ASYNC_WITH': 0,
      'SETUP_ASYNC_WITH': 0,
      # Coroutine operations
      'GET_YIELD_FROM_ITER': 0,
      'GET_AWAITABLE': 0,
      'GET_AITER': 0,
      'GET_ANEXT': 0,
    })

  if sys.version <= '3.5':
    result.update({
      'CALL_FUNCTION_VAR': lambda op: 1 - _call_function_argc(op.arg),
      'CALL_FUNCTION_VAR_KW': lambda op: 1 - _call_function_argc(op.arg),
    })

  for code in dis.opmap.keys():
    if code.startswith('UNARY_'):
      result[code] = 0
    elif code.startswith('BINARY_') or code.startswith('INPLACE_'):
      result[code] = -1

  return result