> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# parse()

> Parse EVM bytecode into array of instructions with offsets and immediates

<Card title="Try it Live" icon="play" href="https://playground.tevm.sh?example=primitives/opcode.ts">
  Run Opcode examples in the interactive playground
</Card>

## Opcode.parse()

Parse bytecode into array of instructions with offsets and immediates.

<Tabs>
  <Tab title="Functional API">
    ```typescript theme={null}
    import { parse } from 'tevm/Opcode'

    const bytecode = new Uint8Array([
      0x60, 0x80,           // PUSH1 0x80
      0x60, 0x40,           // PUSH1 0x40
      0x52,                 // MSTORE
    ])

    const instructions = parse(bytecode)
    // [
    //   { offset: 0, opcode: 0x60, immediate: Uint8Array([0x80]) },
    //   { offset: 2, opcode: 0x60, immediate: Uint8Array([0x40]) },
    //   { offset: 4, opcode: 0x52 }
    // ]
    ```
  </Tab>
</Tabs>

## Parameters

* `bytecode: Uint8Array` - Raw contract bytecode to parse

## Returns

`Instruction[]` - Array of parsed instructions

```typescript theme={null}
type Instruction = {
  offset: number           // Program counter offset
  opcode: BrandedOpcode    // Opcode byte
  immediate?: Uint8Array   // Immediate data for PUSH instructions
}
```

## Behavior

* **Automatic PUSH skipping**: Correctly skips PUSH immediate bytes (1-32 bytes depending on PUSH opcode)
* **Incomplete data handling**: If bytecode ends mid-PUSH, returns instruction with partial immediate data
* **No validation**: Does not validate if opcodes are valid - use `isValid()` to check
* **Zero-copy**: Returns views into original bytecode for immediate data (efficient)

## Use Cases

### Disassemble Bytecode

```typescript theme={null}
import * as Opcode from 'tevm/Opcode'

function disassemble(bytecode: Uint8Array): string[] {
  const instructions = Opcode.parse(bytecode)
  const lines: string[] = []

  for (const inst of instructions) {
    const name = Opcode.name(inst.opcode)
    let line = `${inst.offset.toString(16).padStart(4, '0')}: ${name}`

    if (inst.immediate) {
      const hex = Array(inst.immediate)
        .map(b => b.toString(16).padStart(2, '0'))
        .join('')
      line += ` 0x${hex}`
    }

    lines.push(line)
  }

  return lines
}
```

### Count Instruction Types

```typescript theme={null}
function countInstructionTypes(bytecode: Uint8Array) {
  const instructions = Opcode.parse(bytecode)

  const counts = {
    push: 0,
    dup: 0,
    swap: 0,
    jump: 0,
    storage: 0,
    other: 0
  }

  for (const inst of instructions) {
    if (Opcode.isPush(inst.opcode)) counts.push++
    else if (Opcode.isDup(inst.opcode)) counts.dup++
    else if (Opcode.isSwap(inst.opcode)) counts.swap++
    else if (Opcode.isJump(inst.opcode)) counts.jump++
    else if (inst.opcode === Opcode.SLOAD || inst.opcode === Opcode.SSTORE) counts.storage++
    else counts.other++
  }

  return counts
}
```

### Extract All Constants

```typescript theme={null}
function extractConstants(bytecode: Uint8Array): bigint[] {
  const instructions = Opcode.parse(bytecode)
  const constants: bigint[] = []

  for (const inst of instructions) {
    if (Opcode.isPush(inst.opcode) && inst.immediate) {
      const hex = '0x' + Array(inst.immediate)
        .map(b => b.toString(16).padStart(2, '0'))
        .join('')
      constants.push(BigInt(hex))
    }
  }

  return constants
}
```

### Track Stack Depth

```typescript theme={null}
function trackStackDepth(bytecode: Uint8Array): { max: number, trace: number[] } {
  const instructions = Opcode.parse(bytecode)
  let depth = 0
  let max = 0
  const trace: number[] = []

  for (const inst of instructions) {
    const effect = Opcode.getStackEffect(inst.opcode) ?? 0
    depth += effect

    if (depth < 0) {
      throw new Error(`Stack underflow at offset ${inst.offset}`)
    }
    if (depth > 1024) {
      throw new Error(`Stack overflow at offset ${inst.offset}`)
    }

    max = Math.max(max, depth)
    trace.push(depth)
  }

  return { max, trace }
}
```

## Performance

* **O(n)** time complexity where n is bytecode length
* **Zero allocation** for non-PUSH opcodes (just offset tracking)
* **Single pass** through bytecode
* **No recursion** - simple linear scan

## Related

* [disassemble()](/primitives/opcode/disassemble) - Convert to human-readable strings
* [jumpDests()](/primitives/opcode/jump-dests) - Find all JUMPDEST positions
* [isValid()](/primitives/opcode/is-valid) - Validate opcode bytes
* [Bytecode](/primitives/bytecode) - Bytecode type
