Skip to content

[RFC] Split oparg type from the opcode enum #6746

Open

Description

@ShaharNaveh

Summary

Introduce a new AnyOparg enum & make Instruction + PseudoInstruction enums to not hold the oparg type.

Detailed Explanation

The current Instruction enum couples the opcode and its oparg type together. In practice, this creates friction and many boilerplate code that can be avoided.

Suggested API

New pure Opcode enum that will have only the mapping between the opcode name and it's ID, like this:

enum Opcode {
   Nop = 0,
   IsOp = 1,
   BinaryOp = 2,
   ...
}

A new AnyOparg enum that will have all oparg types as it's variants:

enum AnyOparg {
    NameIdx(oparg::NameIdx),
    IntristicFunction1(oparg::IntristicFunction1),
    Invert(oparg::Invert),
    ...
}

An Instruction struct that is like a typed version of the CodeUnit struct:

struct Instruction {
  opcode: AnyOpcode,
  oparg: AnyOparg,
}

impl Instruction {
  pub fn new<T: Into<AnyOpcode>>(opcode: T, oparg: Option<i32>) -> Result<Self, MarshalError> {
    let oparg = match opcode.into() {
      AnyOpcode::Real(Opcode::Nop) => None,
      AnyOpcode::Real(Opcode::IsOp) => Some(oparg::Invert::try_from(oparg.unwrap())?),
      ...
    };

    Ok(Self { opcode: opcode.into(), oparg: oparg.map(Into::into) })
  }
}

Drawbacks, Rationale, and Alternatives

Drawbacks

  • Will require a serious refactoring to the code

Rational

  • Reduce boilerplate code (use num_enum crate for example).
  • Easier to auto-generate the opcodes (and their IDs) in the future.
  • Simplify opcode -> oparg mapping.

Unresolved Questions

Performance implifications?

  • Will probably increase performance because we will validate the oparg once instead of doing so every time we need to do an operation on the opcode.

Implementation & refactoring efforts?

Activity

  1. youknowone commented on Jan 16, 2026

    @youknowone
    Member

    @coolreader18 I'd like to listen what was the rational to made current layout. And how do you think about the changes.

    Python instruction changed a lot since 3.10. Probably this will be a good chance to research what's the best for next a few years

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

RFCRequest for comments

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions