> **Documentation index**
>
> Fetch the complete documentation index at: https://circ-lang.org/llms.txt
> Use this file to discover all available pages before exploring further.


# A short tour

> A progressive walkthrough of `circ`. Each step adds one new idea on top of the previous one. By the end you'll have read enough to feel at home in the language reference.


## Step 1. A single NOT gate

The smallest possible circuit. One input pin `a`, one inverter, one output pin. Every program is a flat list of declarations: name a thing, then wire its ports. The `.out` suffix on a primitive's instance name is its single implicit output port.

### Source

```circ
input a
not n(in=a)
output out(in=n.out)
```

### `circ-compile --preview`

```
╭───╮     ╭───╮     ╭─────╮
│ a ├○───▶┤NOT├○───▶┤ out │
╰───╯     ╰───╯     ╰─────╯
```

## Step 2. AND of two inputs

Two inputs, named `a` and `b`, feed an AND gate. The gate has two input ports — `a` and `b` — that you bind by name in the parenthesised list. The output of the gate goes to a single output pin named `out`.

### Source

```circ
input a, b
and g(a=a, b=b)
output out(in=g.out)
```

### `circ-compile --preview`

```
╭───╮     ╭───╮     ╭─────╮
│ a ├○───▶┤   │ ╭──▶┤ out │
╰───╯     │AND├○╯   ╰─────╯
       ╭─▶┤   │
       │  ╰───╯
       │
╭───╮  │
│ b ├○─╯
╰───╯                      
```

## Step 3. Naming an intermediate signal

A `wire` is a one-port pass-through: the value on `in` is, after evaluation, exactly the value on `out`. It exists so you can give a derived signal a name. Without `clock_buf` here, `gate.a` would be wired directly to `clk` — same logic, less self-documenting.

### Source

```circ
input clk, data
wire clock_buf(in=clk)
and gate(a=clock_buf.out, b=data)
output out(in=gate.out)
```

### `circ-compile --preview`

```
╭─────╮      ╭───╮     ╭─────╮
│ clk ├○────▶┤   │ ╭──▶┤ out │
╰─────╯      │AND├○╯   ╰─────╯
         ╭──▶┤   │
         │   ╰───╯
         │
╭──────╮ │
│ data ├○╯
╰──────╯                    
```

## Step 4. Anonymous nested components

A component can be instantiated inline as the value of a port. The inverter here has no instance name; its `.out` is wired immediately into `gate1`'s `b` port. The same wiring rules apply — anonymous nesting is just syntactic sugar for declaring an unnamed component.

### Source

```circ
input a
input b
not inv(in=b)
and gate1(a=a, b=inv.out)
output out(in=gate1.out)
```

### `circ-compile --preview`

```
╭───╮     ╭───╮     ╭───╮     ╭─────╮
│ a ├○┬──▶┤NOT├○╮ ╭▶┤   │ ╭──▶┤ out │
╰───╯ │   ╰───╯ │ │ │AND├○╯   ╰─────╯
      ├─────────┴─┴▶┤   │
      │             ╰───╯
      │
╭───╮ │
│ b ├○╯
╰───╯                                
```

## Step 5. A half-adder

Two single-bit numbers `a` and `b` sum to `(carry, sum)` where `sum = a XOR b` and `carry = a AND b`. The `xor` keyword is a built-in macro that expands to primitives at compile time. In a single-file program you import macros explicitly; this is the classic Nand2Tetris milestone, eight lines of source.

### Source

```circ
// half_adder.circ
import xor "<builtin>/xor.circ"
input a, b
xor s(a=a, b=b)
and c(a=a, b=b)
output sum(in=s.out)
output carry(in=c.out)
```

### `circ-compile --preview`

```
╭───╮     ╭───╮         ╭───────╮
│ a ├○─●─▶┤   │ ╭──────▶┤ carry │
╰───╯  │  │AND├○╯       ╰───────╯
      ╭┼─▶┤   │
      ││  ╰───╯
      ││
╭───╮ ││  ╭───────╮     ╭─────╮
│ b ├○●╰─▶┤       │ ╭──▶┤ sum │
╰───╯ │   │[xor:s]├○╯   ╰─────╯
      ╰──▶┤       │
          ╰───────╯
```

## Step 6. A full-adder, by importing the half-adder

Imports glue files together. The root file declares a `half_adder` alias and uses it twice — once for the low-bit sum, once to fold in the carry-in. The carry-out is the OR of the two intermediate carries. The half-adder's ports (`a`, `b`, `sum`, `carry`) are exactly its `input` and `output` declarations. Notice in the preview how the half-adders show up as `[half_adder:ha1]` and `[half_adder:ha2]` boxes — opaque sub-circuits, just like the built-in macros.

### Source

```circ
// half_adder.circ
import xor "<builtin>/xor.circ"
input a, b
xor s(a=a, b=b)
and c(a=a, b=b)
output sum(in=s.out)
output carry(in=c.out)

// root.circ
import half_adder "half_adder.circ"
input a, b, cin
half_adder ha1(a=a, b=b)
half_adder ha2(a=ha1.sum, b=cin)
or cout_or(a=ha1.carry, b=ha2.carry)
output sum(in=ha2.sum)
output cout(in=cout_or.out)
```

### `circ-compile --preview`

```
╭───╮       ╭────────────────╮     ╭────────────────╮     ╭────────────╮     ╭─────╮
│ a ├○─────▶┤                │ ╭──▶┤                │   ╭▶┤            │   ╭▶┤ sum │
╰───╯       │[half_adder:ha1]├○●   │[half_adder:ha2]├○● │ │[or:cout_or]├○╮ │ ╰─────╯
       ╭───▶┤                │ │ ╭▶┤                │ ●─┼▶┤            │ │ │
       │    ╰────────────────╯ │ │ ╰────────────────╯ │ │ ╰────────────╯ │ │
       │                       ╰─┼────────────────────┼─╯                │ │
╭───╮  │                         │                    │                  │ │ ╭──────╮
│ b ├○─╯                         │                    ╰──────────────────┴─┴▶┤ cout │
╰───╯                            │                                           ╰──────╯
                                 │
╭─────╮                          │
│ cin ├○─────────────────────────╯
╰─────╯                                                                              
```

## Step 7. Stable feedback through wires

Combinational feedback is rejected at compile time — a chain of gates whose output drives its own input is a hard error (`E008`). But the validator looks at the signal graph, not the textual order. Here two `not` gates connect end to end through two `wire` pass-throughs; the chain has length four and no cycle, so it compiles cleanly. This is the substrate the language gives you for building latches and other feedback structures.

### Source

```circ
not n1(in=w2.out)
wire w1(in=n1.out)
not n2(in=w1.out)
wire w2(in=n2.out)
```

### `circ-compile --preview`

```
     ╭───╮     ╭───╮
   ╭▶┤NOT├○───▶┤NOT├○╮
   │ ╰───╯     ╰───╯ │
   ╰─────────────────╯
```

Done. The [language reference](https://circ-lang.org/reference.md) covers the full surface — every keyword, every diagnostic code, the rules the validator enforces. The [examples gallery](https://circ-lang.org/examples.md) has more circuits to read through.
