Registry
The registry module mirrors the Lean-side LeanPy.TypeRepr data model
in Python. It describes the shape of every exported function and type so
the marshaller knows how to convert values across the FFI boundary.
Where the data comes from
On the Lean side, the command #export_python_registry "MyLib" emits
two C functions:
MyLib_funcs_json— JSON array of exported functionsMyLib_types_json— JSON array of registered inductive types
LeanLibrary calls these at load time and parses the result into a
LibraryRegistry.
TypeRepr — describing Lean types
Every parameter, return type, and constructor field is described by a
TypeRepr. It captures the structural shape of the type, not its
full Lean name:
>>> from lean_py.registry import TypeRepr
>>> TypeRepr(kind="int") # Lean Int
>>> TypeRepr(kind="array", elem=TypeRepr(kind="string")) # Array String
>>> TypeRepr(kind="named", name="Point") # a derive_python'd type
>>> TypeRepr(kind="io", elem=TypeRepr(kind="nat")) # IO Nat
The short() method produces a compact pseudo-Lean rendering:
>>> TypeRepr(kind="array", elem=TypeRepr(kind="int")).short()
'Array[Int]'
Supported kinds:
Primitives:
"unit","bool","nat","int","float","char","string"Fixed-width:
"uint"/"sint"with abitsfield (8, 16, 32, 64)Containers:
"array","list","option","prod"Wrappers:
"io"(unwrapped automatically),"pyobject"(rawPyObject*),"opaque"(untouchedlean_object*)Named:
"named"with anamefield pointing to aderive_pythontype
CtorInfo — constructor metadata
Each constructor of a derive_python’d inductive is described by a
CtorInfo:
>>> CtorInfo(name="circle", tag=0, fields=[TypeRepr(kind="int")])
>>> CtorInfo(name="rect", tag=2, fields=[TypeRepr(kind="int"), TypeRepr(kind="int")])
name: the constructor name (e.g."circle","mk")tag: the runtime tag valuefields: list ofTypeReprfor each field, in declaration order
TypeInfo — type metadata
A TypeInfo bundles all constructors for a registered type:
>>> TypeInfo(name="Shape", isStructure=False, isEnum=False,
... ctors=[circle_info, square_info, rect_info])
isStructure: true if the type has exactly one constructorisEnum: true if all constructors are nullary
FuncInfo — function metadata
Each @[python]-annotated function is described by a FuncInfo:
>>> FuncInfo(
... declName="increment",
... exportName="py_increment",
... params=[TypeRepr(kind="int")],
... returnType=TypeRepr(kind="int"),
... )
declName is the Lean name; exportName is the C symbol registered
with @[python "py_increment"].
LibraryRegistry — the full picture
LibraryRegistry holds all types and functions for a loaded library:
>>> reg = LibraryRegistry.from_json_strings(funcs_json, types_json)
>>> reg.types # list[TypeInfo]
>>> reg.funcs # list[FuncInfo]
>>> reg.find_type("Shape") # Optional[TypeInfo]
>>> reg.find_func("py_increment") # Optional[FuncInfo]
The registry handles deduplication — recursive inductives may register the same type multiple times, and the parser merges them.