1635. gopy intrinsics
What we are porting
Python/intrinsics.c (~400 lines). Two opcodes, CALL_INTRINSIC_1
and CALL_INTRINSIC_2, are emitted by the compiler in places where
a runtime helper is cleaner than a dedicated opcode. The oparg
selects which helper to call.
This is a small, well-bounded surface. The helper set is closed: about 10 unary intrinsics and 4 binary intrinsics. CPython adds to it sparingly (one or two per release), so a hand-port plus a table is cheaper than codegen.
The unary intrinsic table
CALL_INTRINSIC_1 oparg: pop one value, push one.
| ID | Helper |
|---|---|
INTRINSIC_1_INVALID | guard; raises if reached |
INTRINSIC_PRINT | print expression result (REPL displayhook) |
INTRINSIC_IMPORT_STAR | implements from x import * |
INTRINSIC_STOPITERATION_ERROR | re-raise StopIteration as RuntimeError |
INTRINSIC_ASYNC_GEN_WRAP | wrap value for async generator yield |
INTRINSIC_UNARY_POSITIVE | +x (rare; usually inlined) |
INTRINSIC_LIST_TO_TUPLE | freeze a list comprehension into a tuple |
INTRINSIC_TYPEVAR | PEP 695 TypeVar(...) |
INTRINSIC_PARAMSPEC | PEP 695 ParamSpec(...) |
INTRINSIC_TYPEVARTUPLE | PEP 695 TypeVarTuple(...) |
INTRINSIC_SUBSCRIPT_GENERIC | PEP 695 Generic[T] subscription |
INTRINSIC_TYPEALIAS | PEP 695 type X = ... |
The binary intrinsic table
CALL_INTRINSIC_2 oparg: pop two, push one.
| ID | Helper |
|---|---|
INTRINSIC_2_INVALID | guard |
INTRINSIC_PREP_RERAISE_STAR | ExceptionGroup re-raise prep |
INTRINSIC_TYPEVAR_WITH_BOUND | TypeVar('T', bound=int) |
INTRINSIC_TYPEVAR_WITH_CONSTRAINTS | TypeVar('T', int, str) |
INTRINSIC_SET_FUNCTION_TYPE_PARAMS | wire generic type params onto a function |
(IDs come from Include/internal/pycore_intrinsics.h. Numeric
values must match CPython byte-for-byte so emitted bytecode loads
the right entry.)
Go shape
// Unary is the CALL_INTRINSIC_1 entry. The eval loop reads
// UnaryTable[oparg] and calls it.
type Unary func(ts *state.Thread, v object.Object) (object.Object, error)
// Binary is the CALL_INTRINSIC_2 entry.
type Binary func(ts *state.Thread, lhs, rhs object.Object) (object.Object, error)
// UnaryTable is the dispatch table for CALL_INTRINSIC_1.
// Indexed by INTRINSIC_* enum value; entries match
// _PyIntrinsics_UnaryFunctions from Python/intrinsics.c.
var UnaryTable = [...]Unary{
Unary1Invalid,
UnaryPrint,
UnaryImportStar,
UnaryStopIterationError,
UnaryAsyncGenWrap,
UnaryUnaryPositive,
UnaryListToTuple,
UnaryTypevar,
UnaryParamspec,
UnaryTypevartuple,
UnarySubscriptGeneric,
UnaryTypealias,
}
// BinaryTable is the dispatch table for CALL_INTRINSIC_2.
var BinaryTable = [...]Binary{
Binary2Invalid,
BinaryPrepReraiseStar,
BinaryTypevarWithBound,
BinaryTypevarWithConstraints,
BinarySetFunctionTypeParams,
}
The eval loop dispatch is one indexed call:
case opcode.CALL_INTRINSIC_1:
v := e.popObject()
res, err := intrinsics.UnaryTable[oparg](e.ts, v)
if err != nil {
return 0, err
}
e.pushObject(res)
return e.advance(1), nil
File mapping
| C source | Go target |
|---|---|
Python/intrinsics.c (unary table + helpers) | intrinsics/unary.go |
Python/intrinsics.c (binary table + helpers) | intrinsics/binary.go |
Include/internal/pycore_intrinsics.h (enum) | intrinsics/ids.go |
Checklist
Status legend: [x] shipped, [ ] pending, [~] partial / scaffold,
[n] deferred / not in scope this phase.
Files
-
intrinsics/ids.go:INTRINSIC_*constants matchingpycore_intrinsics.hnumerically (12 unary, 6 binary, MAX_INTRINSIC_*). -
intrinsics/unary.go:Unarytype,UnaryTable, every unary helper (UnaryPrint,UnaryImportStar, ...). Bodies stubbed with notImplementedError pending cross-block prereqs. -
intrinsics/binary.go:Binarytype,BinaryTable, every binary helper. Includes BinarySetTypeparamDefault (3.13+). -
intrinsics/intrinsics.go:notImplementedErrorshared between unary and binary stubs. -
intrinsics/intrinsics_test.go: ID-value pinning, table population, invalid-ID error path, every stub returns notImplementedError.
Unary panel
- [n]
UnaryPrint: callssys.displayhook. Defers to thesysmodule port (1651). Stub returnsnotImplementedError. - [n]
UnaryImportStar: walks__all__and copies into locals. Defers to the import system port (1683). Stub. - [n]
UnaryStopIterationError: wraps StopIteration in a RuntimeError (PEP 479). Defers to the exception module port (1686). Stub. - [n]
UnaryAsyncGenWrap: builds_PyAsyncGenWrappedValue. Defers to the async-generator object (1687). Stub. - [n]
UnaryUnaryPositive:+xvia__pos__. Defers to the number-protocol slot dispatch (1684). Stub. -
UnaryListToTuple: freezes a list comprehension into a tuple. Implemented inintrinsics/unary.go; consumed by theLIST_TO_TUPLElowering invm/eval_simple.go. - [n]
UnaryTypevar/UnaryParamspec/UnaryTypevartuple/UnarySubscriptGeneric/UnaryTypealias: PEP 695 type runtime objects. Defer to 1689. Stubs.
Binary panel
- [n]
BinaryPrepReraiseStar: reconstructs an ExceptionGroup forraise except*re-raise. Defers to the ExceptionGroup type (1686). Stub. - [n]
BinaryTypevarWithBound,BinaryTypevarWithConstraints,BinarySetFunctionTypeParams,BinarySetTypeparamDefault: PEP 695 helpers. Defer to 1689. Stubs.
Surface guarantees
- Numeric IDs match
Include/internal/pycore_intrinsics.hbyte-for-byte. Pinned byintrinsics_test.go::TestUnaryIDValuesandTestBinaryIDValues(every entry plusMaxUnary/MaxBinary). - Each stubbed helper returns
notImplementedError. Pinned byTestStubHelpersReturnNotImplemented(sweeps both tables, skips the implementedUnaryListToTuple). - [n] PEP 695 helpers (Typevar / Paramspec / Typevartuple /
Typealias) build runtime objects whose
reprmatches CPython's. Defers to 1689; stubs returnnotImplementedErrorin v0.6.
Out of scope for v0.6
- Specialized variants:
INSTRUMENTED_CALL_INTRINSIC_*. Falls back to base case until 1634 (monitoring) lands at v0.9.
Cross-references
- Eval loop dispatch: 1636.
- PEP 695 type runtime objects: 1689 (typevar, generic alias).
- ExceptionGroup type: 1686.
sys.displayhook: 1651 (sys module).