Pocket · Cup · Box

PCB
Language Reference

Forward  ·  Backward  ·  Container-first

130+
Keywords
6
Container Types
5
Pipeline Stages
Directions
Architecture

Interpreter Pipeline

Every PCB program passes through five stages before a single line executes. Click any stage for details.

Core Concept

Bidirectionality

A PCB program runs in both directions simultaneously — not as a mode but as two concurrent strands on shared data. KnotRunner uses an oscillation model: at each loop boundary the direction flips while the condition holds, so forward statements fire on forward passes and backward statements (tnirp, xob, rav, etc.) fire on backward passes — within the same loop body. Flow processing (tkp/pkt tick loops) runs independently on its own threads. Lexical reversal (keywords spelled backward, dot-chain mirrored) is the surface projection of directional traversal. The dot-chain is a directional composition operator — print.("x") and ("x").tnirp are the same execution graph node traversed from opposite ends.

↗ Forward Direction
MIRROR
↙ Reverse Direction
Language Reference

Keyword Explorer

Search and filter all PCB keywords. Click any card to see syntax, description, and examples. Cyan = forward form. Amber = reverse form.

0 keywords
Keyword Distribution by Category
Data Structures

Container Types

PCB has six container types in two mirrored hierarchies. Forward: box → cup → pkt. Backward mirror: xob → puc → tkp. Each pair is not merely a syntactic mirror — each backward type has distinct execution semantics: xob is structurally opaque (inspection ops blocked); puc inverts every operation in its body at execution time; tkp has an independent tick-based lifecycle that seam-crosses to pkt. knt/tnk stand apart — they act as container, orientation, and operator simultaneously. Everything in PCB is a box — every container implements IBox, and every primitive is automatically wrapped in a single-item BoxInstance at storage boundaries. Variables are containers all the way down.

Type System

Primitive Boxing

Primitives are never stored raw. At every storage boundary the runtime wraps them in a single-item BoxInstance. Computation may produce raw values, but storing them always boxes them. Reading them for arithmetic auto-unboxes transparently.

Storage Boundaries

Boxing happens automatically when a value crosses any of these boundaries:

Boundary Where it fires
Container body evaluationevaluateBody() in all six container types
Variable definitionvar / rav declaration
Assignment= (forward) and = (backward)
Routing injectionKnotRunner.injectIntoContainer() before addAll()
Bootstrap resultpkt/tkp tick() before inserting fn.call() result

Boxer Rules

Input to Boxer.box() Result
Double, Integer, String, BooleanBoxInstance([value]) — single-item body
nullBoxInstance([null]) — body size 1, distinct from empty BoxInstance
Any Instance (container)Passed through unchanged — containers are never re-wrapped
Non-boxable Java objectnull; error routed to NON/LIMBO sink

Auto-Unboxing

Binary operators (+ - * / % ^ and comparisons) automatically unwrap a BoxInstance on either operand before computing. The result is raw; it is re-boxed only at the next storage boundary. You never need to manually unbox for arithmetic.

Interface Type Hierarchy

Every container implements IBox. The marker interfaces form the runtime type tree:

IBox
 ├── ICup  extends IBox
 │    └── IPkt  extends ICup
 │         ├── ITkp  extends IPkt    →  TkpInstance
 │         ├── IKnt  extends IPkt    →  KnotInstance
 │         └── ITnk  extends IPkt    →  TonkInstance
 └── IXob  extends IBox
      └── IPuc  extends IXob, ICup

BoxInstance    implements IBox
CupInstance    implements ICup
PocketInstance implements IPkt
XobInstance    implements IXob  (also extends BoxInstance)
PucInstance    implements IPuc  (also extends CupInstance)

Pocket Ecosystem

pkt and tkp are self-contained execution ecosystems — they hold elements, run Flow tick loops on independent daemon threads, and manage their own lifecycle. They are the only containers with autonomous execution.

Flow Tick Loop

On each tick, every active Flow scans the body in its current direction. Priority order of what Flow acts on:

Item in body What Flow does
Flow objectScavenged — chain absorbed, item removed
String(".") — standalone periodFlips active flow direction (FORWARD↔BACKWARD), consumed. Syntax: ( . "hello")
Bare bracket string "(" "{" ")" "}"Synthesizes period → new independent Flow promoted to flows list (open=fwd, close=bwd), consumed
PocketOpen/CupOpen/PocketClosed/CupClosed exprSame as bare bracket — new independent Flow, label discarded, consumed (knotted pocket)
String with connectors "(." ".)" etc.Chain absorbed, string added as cargo
cup / puc — CupInstanceBootstrapped — re-executes originalBody, cup consumed, token spent
knt / tnk — KnotInstance/TonkInstanceBootstrapped — KnotRunner.runWithRouting() runs knot and routes output to named target container; token spent
Nested pkt / tkpIgnored — Flow does not enter nested ecosystems

Bootstrapping vs Routing

These are separate concerns. Flow bootstraps — it starts execution. Routing is where the output goes — handled entirely by KnotRunner using interp.environment to look up the target container by name. Flow does not participate in routing.

Period as Direction Signal

A standalone . flips the active flow's direction in place. When a . appears inside a knt/tnk body, it becomes a routed result — injected into the target container by runWithRouting(). If the target is a pkt/tkp, the tick loop flips that container's flow direction. A knot can remotely flip flow direction in another pocket. In box/cup targets, "." lands inertly.

Heat Death

Heat death is reached when all Flow chain tokens are spent and no actionable items remain — no dormant Flow objects, no unexecuted cups or knots, no bracket signals. tkp at heat death seam-crosses to pkt. pkt at heat death simply stops ticking.

Seam Crossing

Event pkt result tkp result
Heat deathStops ticking (stays pkt)→ seam-crosses to pkt
Natural lifetime expiry→ seam-crosses to tkp→ seam-crosses to pkt
User-kill (= null)Destroyed, no transformationDestroyed, no transformation
INDEFINITE lifetimeNever crosses naturallyNever crosses naturally

Lifetime budget transfers through every crossing. TRAVERSAL carries remaining count. Body and flows transfer; seam-crossed container starts its own tick loop if it has flows.

Execution Control

Control Flow

Loops and conditionals have bidirectional forms. Labeled loops allow complex nested structures to reference each other.

Symbols

Operators

PCB supports standard arithmetic, comparison, and logical operators plus two unique stream operators for direct file I/O.

Code Examples

Program Examples

Real programs from source files, plus authored examples demonstrating common patterns.

Math Subsystem

Math Examples

PCB has built-in trig, log, arithmetic, rounding, inverse trig, bitwise, and vector/matrix keywords. A separate symbolic math subsystem (BoxMath) with derivatives, integrals, and the Fresnel S/C integrals exists internally. The examples here cover all math keywords available in PCB programs.

Game Integration

FlatLand Commands

PCB includes first-class commands for interacting with the FlatLand 2D game engine. Scripts attached to game objects can create, move, and destroy entities in the world.

FlatLand integration example

  
← PCB