Pinochle - Core Library
Python implementation of the Nock 4K Combinator Calculus.
Components
noun.py:pynounfrom Urbitnock.py: Nock tree-walking interpreter
Installation
pip install pinochle
Or from source:
git clone https://github.com/sigilante/pinochle.git
cd pinochle/packages/pinochle
pip install .
Usage
from pinochle import nock, parse_noun
# Parse and evaluate Nock expressions
result = nock(42, parse_noun("[0 1]"))
print(result) # 42
# Increment
result = nock(41, parse_noun("[4 0 1]"))
print(result) # 42
Terms (%tas)
The parser accepts Hoon-style % constants alongside numbers. % before a
number is that number (an atom is already a constant); % before a term
(a-z, -, ., …) is the term's bytes as a little-endian atom — the @tas
cord. Number syntax (with . digit separators) is unchanged.
from pinochle import parse
parse('%dec') # 6514020 (little-endian cord for "dec")
parse('%42') # 42
parse('[%fast %dec]')# Cell(1953718630, 6514020)
parse('1.024') # 1024
Jets and hints
A jet is a native Python implementation of a Nock arm, matched by the mug of a core's battery — the register-then-match architecture Vere uses, minus parents and hooks.
A %fast opcode-11 hint wraps a core-producing formula:
*[a 11 [%fast name] core-formula] == *[a core-formula]
It is transparent — it just produces the core — but as a side effect it
warms the core's battery: it records mug(battery) → native in a run-time
table, where the native is looked up by name (a @tas cord such as %dec,
or an Urbit-style [name parent hooks] clue whose head is the name; the clue
is metadata, never evaluated as a formula).
Dispatch happens at arm invocation (Nock 9). Evaluating *[a 9 b c] builds
the core *[a c]; if its battery is warm, the native runs against the core
instead of the arm formula. A native receives the whole core
[battery payload]; for a gate the sample is at axis 6 and the context at
axis 7 (the standard Hoon calling convention). With jets disabled, or an
unregistered name/battery, nothing warms and nothing dispatches — results are
identical, so a jet only changes cost, never meaning.
from pinochle import nock, parse, to_noun, register_jet, jets, Cell
# A native reads the sample from the core at +6. The built-ins
# (dec/add/sub/mul/lte) follow the same convention; register your own by name.
register_jet('inc', lambda core: int(core.tail.head) + 1)
# A minimal inc gate: core = [battery [sample context]], battery [4 0 6].
core = to_noun(((4, 0, 6), (5, 0)))
# %fast warms the battery and returns the core (transparent)...
nock(0, Cell(11, Cell(Cell(jets.cord('fast'), jets.cord('inc')), Cell(1, core))))
# ...so invoking arm 2 now dispatches the native instead of the formula:
nock(core, parse('[9 2 0 1]')) # 6
# Certification: run BOTH native and arm formula on every dispatch, assert equal.
jets.VALIDATE = True
# Master switch (nothing warms, nothing dispatches — pure interpreter):
jets.ENABLED = False
jets.reset_warm() # clear the run-time warm table
pinochle is an interpreter, not a compiler: it emits no hints. Jets fire
only on cores warmed by [11 [%fast name] core] hints present in the noun
(for example those produced by
nockasm's (%hintd 'fast' 'dec' …)).
Dispatch keys on the battery mug alone, so it assumes one jet per battery
(true for gates, not multi-arm cores) and, being a 31-bit mug, could in
principle collide (astronomically unlikely).
A runnable end-to-end demo — the built-in %dec native accelerating the
genuine O(n) Nock decrement loop, with jets off, jets on, and VALIDATE all
agreeing — is in examples/jets_demo.py:
python examples/jets_demo.py
# dec 7
# jets off (formula) : 6
# jets on (native) : 6
# VALIDATE (both=) : 6
# ok: native and formula agree
Debug hints (%slog, %bout)
The dynamic hint [11 [%slog clue] body] prints its clue ([priority tank])
before producing body, the Nock analogue of Hoon's ~&. The static hint
[11 %bout body] times the evaluation of body and reports the elapsed time,
Urbit's ~>(%bout .). Both stay transparent — the body's value is unchanged
— and both write to stderr by default through a redirectable sink:
from pinochle import jets
# route ~& output into a Jupyter cell instead of the server's stderr
jets.SLOG = lambda clue: my_stream_writer(clue)
# collect timings instead of printing them (elapsed is in nanoseconds)
jets.BOUT = lambda elapsed_ns: timings.append(elapsed_ns)
API Reference
See full documentation in the repository.
License
MIT License
Metadata
Release files for pinochle 1.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pinochle-1.3.1.tar.gz | 20.3 kB | Without provenance | Details for pinochle-1.3.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pinochle-1.3.1-py3-none-any.whl | Python 3 | none | any | Details for pinochle-1.3.1-py3-none-any.whl |
Total release size: 41.1 kB
Release files / pinochle-1.3.1.tar.gz
| Download URL | pinochle-1.3.1.tar.gz |
|---|---|
| Size | 20.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
737fca35e350c088dda3ffa3e8bca11b4f44b83f5b27b0a9191ddd49d81b3a27
|
|
BLAKE2b-256 checksum How to use checksums |
4904bc50fbc9ccdd96cfadaa3abde8748ee24a42a0665e032b4d77721894047e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.7
|
Release files / pinochle-1.3.1-py3-none-any.whl
| Download URL | pinochle-1.3.1-py3-none-any.whl |
|---|---|
| Size | 20.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
029a3faf708d0aa7d1d8d59f5a9c4000c128a27a7b2001f519c6459928865cd0
|
|
BLAKE2b-256 checksum How to use checksums |
eca862c176ddbe0783ad9c94fdf36225ca139803e3806a0bca099857767d8be7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.7
|
Security for pinochle 1.3.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.