code: def _disassemble(self, preserve=False) -> None:
      assembly = []
      i = 0
      bytecode = getattr(self, "bytecode", [])
      numBytecode = len(bytecode)
      while i < numBytecode:
          op = bytecode[i]
          try:
              mnemonic, argBits, argoffset, name = opcodeDict[op]
          except KeyError:
              if op in streamOpcodeDict:
                  values = []
  
                  # Merge consecutive PUSH operations
                  while bytecode[i] in streamOpcodeDict:
                      op = bytecode[i]
                      (
                          mnemonic,
                          argBits,
                          argoffset,
                          name,
                      ) = streamOpcodeDict[op]
                      words = mnemonic[-1] == "W"
                      if argBits:
                          nValues = op - argoffset + 1
                      else:
                          i = i + 1
                          nValues = bytecode[i]
                      i = i + 1
                      assert nValues > 0
                      if not words:
                          for j in range(nValues):
                              value = bytecode[i]
                              values.append(repr(value))
                              i = i + 1
                      else:
                          for j in range(nValues):
                              # cast to signed int16
                              value = (bytecode[i] << 8) | bytecode[
                                  i + 1
                              ]
                              if value >= 0x8000:
                                  value = value - 0x10000
                              values.append(repr(value))
                              i = i + 2
                      if preserve:
                          break
  
                  if not preserve:
                      mnemonic = "PUSH"
                  nValues = len(values)
                  if nValues == 1:
                      assembly.append(
                          "%s[ ]	/* 1 value pushed */" % mnemonic
                      )
                  else:
                      assembly.append(
                          "%s[ ]	/* %s values pushed */"
                          % (mnemonic, nValues)
                      )
                  assembly.extend(values)
              else:
                  assembly.append("INSTR%d[ ]" % op)
                  i = i + 1
          else:
              if argBits:
                  assembly.append(
                      mnemonic
                      + "[%s]	/* %s */"
                      % (num2binary(op - argoffset, argBits), name)
                  )
              else:
                  assembly.append(mnemonic + "[ ]	/* %s */" % name)
              i = i + 1
      self.assembly = assembly
  
imports: from __future__ import annotations
  from fontTools.misc.textTools import num2binary, binary2num, readHex, strjoin
  import array
  from io import StringIO
  from typing import List
  import re
  import logging
label_desc: Use image node_id 9 for calling the Program obj's underlying member method code with example usage: obj._disassemble(preserve) without return types