HL

> [!INFO]
> **Syntactically**, [[HL]] is Turing Complete. It possesses the required isomorphism to #brainfuck (loops, math, memory traversal). However, the current C-based **HVM implementation** is technically a *Linear Bounded Automaton*. The fixed number of registers (6) and fixed program size (255) prevents the "infinite tape" requirement of a true Turing Machine. To make it fully Turing Complete, the VM would simply need to allow dynamic memory allocation.

[[HL]] (Halit's Language) is a project for learning how computers actually run logic. It has two parts: a high-level #esolang scripting language (HL) and its low-level backbone, the **HVM** (Halit's Virtual Machine). I wrote it in #c, and instead of targeting a real architecture like x86 or ARM it runs on a small hardware simulation I built myself.

The first version was a flat linear script. The current one adds branching, loops, and system calls, which makes HL **syntactically Turing Complete**.

## The Engine (HVM)

The core of the project is the virtual machine. It models a **register-based architecture**, using plain #c integers as its "electricity." It has a fixed block of program memory and a small set of registers.

* **Word Size:** 16-bit instruction format.
* **Memory:** 255 slots of fixed program memory.
* **Registers:** 6 total (1 Program Counter + 5 General Purpose).

The machine operates on a classic cycle. It fetches an integer from memory, decodes it into an Operation Code (OpCode), executes the logic, and increments the Program Counter.

```mermaid title="HVM Execution Cycle"
graph TD
Start((Start)) --> Fetch[Fetch Instruction]
Fetch --> Decode[Decode Bitmasks]

subgraph Execution Unit
Decode --> ALU{OpCode?}
ALU -->|ADD/SUB| Math[Arithmetic Logic]
ALU -->|MOV/LOAD| Reg[Register Ops]
ALU -->|JMP/JNE| Flow[Control Flow]
ALU -->|SYS| IO[System / IO]
end

Math --> UpdatePC[Update PC]
Reg --> UpdatePC
Flow --> UpdatePC
IO --> UpdatePC

UpdatePC -->|Status = True| Fetch
UpdatePC -->|Status = False| Stop((Halt))
```

Instructions are packed into single integers. The VM uses bitwise operators to "slice" the instruction. Crucially, while registers use 4-bit slots, immediate values (used in `LOAD` or `JMP`) utilize the lower 8 bits, overlapping with Reg 1 and Reg 2.

| Mask | Component | Description |
| :------- | :--------- | :-------------------------------------------------- |
| `0xF000` | **OpCode** | The operation command (e.g., ADD, MOV, SYS). |
| `0x0F00` | **Reg 0** | Destination Register. |
| `0x00F0` | **Reg 1** | Source Register A. |
| `0x000F` | **Reg 2** | Source Register B. |
| `0x00FF` | **Value** | **Immediate Value / Address** (Overlaps Reg 1 & 2). |

## The Language (HL)

**HL** sits on top of the HVM as a high-level wrapper. It combines **delta encoding** (using `+` and `-` to shift values) with stack-based control flow.

The language uses a minimal set of symbols to manipulate registers and control execution flow, plus a special initialization syntax.

| Symbol | Action | HVM Mapping |
| :--------- | :------------- | :------------------------------------------------------------- |
| `("c", r)` | **Init** | `LOAD` value 'c' into register 'r'. |
| `( ... )` | **Group** | Wraps arithmetic operations. |
| `+` / `-` | **Math** | Increment or Decrement the *Active Register*. |
| `>` / `<` | **Switch** | Move focus to the Next or Previous Register. |
| `[` | **Loop Start** | `JNZ` (Jump if Not Zero). Repeats block while Active Reg != 0. |
| `]` | **Loop End** | `JMP` (Jump back to start). |
| `.` | **Print** | `SYS 1` (Output Active Register as Char). |
| `,` | **Input** | `SYS 2` (Read Input to Active Register). |

The parsing logic acts as a hybrid state machine.

* **Tokenizer:** Scans for groupings `()` or control characters `[]`.
* **Initialization:** If a token contains a comma and quotes (e.g., `("h", 1)`), it parses it as a literal and generates a `LOAD` opcode using the **Value** bitmask.
* **Deltas:** If the token contains operators (e.g., `(+++)`), it counts them and generates `ADD`/`SUB` opcodes.
* **Loop Handling:** When the parser encounters `[`, it pushes the current bytecode address to a **Stack**. When it finds `]`, it pops the address to resolve the jump target.

```mermaid title="Parser & Compilation Logic"
graph LR
Input["Source: (++) [ . (-) ]"] --> Tokenizer{Token Type}

Tokenizer -- "Math Group" --> Count[Count Deltas]
Count --> GenMath[Emit ADD/SUB]

Tokenizer -- "Loop Start '['" --> StackPush[Push Address to Stack]
StackPush --> GenJNZ[Emit Placeholder JNZ]

Tokenizer -- "Loop End ']'" --> StackPop[Pop Address from Stack]
StackPop --> Resolve[Resolve Jump Targets]
```

## Examples

These snippets show how the language grew. They go from a raw delta-encoded string to a structured loop.

### Linear "Hello World"

This shows the **delta encoding** side of [[HL]]. It starts at 'h' with the initialization syntax, then shifts the value up and down to reach each following ASCII character.

```hl
("h", 1)
(---)
(+++++++)
()
(+++)
(-------------------------------------------------------------------------------)
(+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++)
(--------)
(+++)
(------)
(--------)
(-------------------------------------------------------------------)
```

Here is how the HVM interprets that stream to produce the output. It maintains the state in **Register 1** and modifies it step-by-step.

| Instruction | Logic | Calculation | ASCII | Output |
| :------------ | :----------- | :-------------- | :---- | :-------- |
| `("h", 1)` | **LOAD** 'h' | `Reg1 = 104` | 104 | **h** |
| `(---)` | **SUB** 3 | `104 - 3 = 101` | 101 | **e** |
| `(+++++++)` | **ADD** 7 | `101 + 7 = 108` | 108 | **l** |
| `()` | **NOP** | `108 + 0 = 108` | 108 | **l** |
| `(+++)` | **ADD** 3 | `108 + 3 = 111` | 111 | **o** |
| `(---...x79)` | **SUB** 79 | `111 - 79 = 32` | 32 | **SPACE** |
| `(+++...x87)` | **ADD** 87 | `32 + 87 = 119` | 119 | **w** |
| `(--------)` | **SUB** 8 | `119 - 8 = 111` | 111 | **o** |
| `(+++)` | **ADD** 3 | `111 + 3 = 114` | 114 | **r** |
| `(------)` | **SUB** 6 | `114 - 6 = 108` | 108 | **l** |
| `(--------)` | **SUB** 8 | `108 - 8 = 100` | 100 | **d** |
| `(---...x67)` | **SUB** 67 | `100 - 67 = 33` | 33 | **!** |

### The "A-Z" Generator

This shows **control flow**. Instead of hardcoding every letter, a loop prints the alphabet automatically.

* **Reg 1:** Set to 26 (Loop Counter).
* **Reg 2:** Set to 65 ('A').
* **Loop:** Print Reg 2, Increment Reg 2, Decrement Reg 1.

```hl
// Setup: Reg 1 = 26
(++++++++++++++++++++++++++)

// Switch to Reg 2, Setup 'A' (65)
(>) (+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++) (<)

// While Reg 1 is not 0
[
(>) // Switch to Reg 2 ('A')
. // Print Char
(+) // Increment to 'B'
(<) // Switch to Reg 1 (Counter)
(-) // Decrement Counter
]
```

## HL vs. Brainfuck

HL has the same spirit as #brainfuck, but the two differ in architecture and philosophy.

| Feature | Brainfuck | HL |
| :--------------- | :-------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------- |
| **Architecture** | **Tape Based:** You move a pointer along an infinite array of memory cells. | **Register Based:** You switch focus between a limited set of high-speed registers (CPU simulation). |
| **Grouping** | **Individual:** `++++` executes as 4 separate increment instructions. | **Grouped:** `(++++)` is parsed as a single `ADD 4` instruction. This makes HL more efficient at runtime. |
| **Philosophy** | Minimalist Turing Machine. | Minimalist CPU Architecture. |