Circuit File Format

The .circ language: declarations, ports, components, and built-ins.

.circ files describe a digital circuit as a set of named components and their connections. The format is a simple declarative DSL designed to map directly onto the simulation engine’s component and connection model.

Status: Parsing, semantic validation, and compilation to Zig/WASM exist for the supported surface below (zig build-produced WASM per sub-circuit and built-in macros).

Syntax Overview

A .circ file contains a sequence of top-level declarations. Each declaration either names input pins or instantiates a component with named port connections.

input <name> [, <name> ...]

<type> <name> (
    <port> = <signal> [,
    <port> = <signal> ...]
)

Comments

Line comments start with // and run to end of line (see Annotation in lib/grammar/proto-circ.peg). Hash (#) is not a comment starter in .circ.

Declarations

Input Pins

input pin1, pin2

Declares one or more named input pins for the circuit. Input pins are driven externally (by the JavaScript host) and have no input ports of their own.

Component Instances

<type> <instance-name> (
    <input-port> = <signal>,
    ...
)

<type> is the gate kind. Recognised types:

TypePortsDescription
anda, bAND gate
notinNOT gate (inverter)
ledinOutput indicator
wireinPass-through

Built-in macro gates expand at compile time to nested and / not (and optionally other macros). They use a and b as input ports and expose out. Unlike and/not, no import is required — the compiler behaves as if import … from "<builtin>/<name>.circ" were present.

TypePortsExpansion
ora, bOR from not/and
nanda, bNAND
nora, bNOR (uses internal or macro)
xora, bXOR
xnora, bXNOR (uses internal xor macro)

<input-port> is the name of the port being driven (e.g. a, b, in).

<signal> is one of:

  • <instance-name>.out — the output of a named component or primitive with a single implicit output .out.
  • <instance-name>.<port> — the output pin of an imported subcircuit that exposes <port> (sum, carry, etc.).
  • An inline component expression (see nested components below)

Signal References

A signal reference connects a port to the output of a previously declared name:

a = pin1.out

This wires port a to the output of the component named pin1.

Nested Component Expressions

Components may be defined inline as the value of a port connection. The nested component has no instance name but its .out output is wired immediately to the enclosing port:

and combine (
    a = pin1.out,
    b = not (
        in = pin2.out
    ).out
)

Here a not gate is instantiated anonymously; its output is connected to port b of combine.

Full Example

input pin1, pin2

and combine (
    a = pin1.out,
    b = not (
        in = pin2.out
    ).out
)

led result (
    in = combine.out
)

This circuit computes pin1 AND (NOT pin2) and displays the result on an LED.

Equivalent WASM API construction:

const pin1    = circuit.createComponent(ComponentKind.InputPinGate);
const pin2    = circuit.createComponent(ComponentKind.InputPinGate);
const notGate = circuit.createComponent(ComponentKind.NotGate);
const andGate = circuit.createComponent(ComponentKind.AndGate);
const led     = circuit.createComponent(ComponentKind.Led);

circuit.connect(pin2,    0, notGate, 1);  // pin2.out  → not.in
circuit.connect(pin1,    0, andGate, 2);  // pin1.out  → and.a
circuit.connect(notGate, 0, andGate, 3);  // not.out   → and.b
circuit.connect(andGate, 0, led,     1);  // and.out   → led.in

Grammar

The parser is generated from a PEG grammar at lib/grammar/proto-circ.peg using the langlang tool. The generated C parser is at lib/parser.c / lib/parser.h and is imported into Zig via lib/syntax/CParser.zig.

Parse tree node types used by lib/syntax/translate.zig:

Node typeMeaning
LL_NODE_SEQUENCEOrdered list of child nodes
LL_NODE_NODENamed grammar rule match
LL_NODE_STRINGMatched literal text (identifier, etc.)
LL_NODE_ERRORParse failure at this position

lib/syntax/nodes/declaration.zig handles Declaration rule nodes and recognises the sub-rules input, output, and component to determine declaration kind.