How HIL works

A deep dive into the system architecture, from LISP source to hardware execution.

System Overview

HIL is a Hardware-in-the-Loop language with three layers:

Architecture
┌─────────────────────────────────────────────┐ │ User LISP Program │ │ (main.hil or project.hil) │ └─────────────────┬───────────────────────────┘ │ ┌─────────────┼─────────────┐ ▼ ▼ ▼ ┌────────┐ ┌─────────┐ ┌──────────┐ │ Simulate│ │ Build │ │ CRUMB │ │ (headless)│ │(compile)│ │(simulate)│ └────┬───┘ └────┬────┘ └────┬─────┘ │ │ │ ▼ ▼ ▼ ┌────────┐ ┌─────────┐ ┌──────────┐ │ Host │ │ Arduino │ │ CRUMB │ │ Monitor│ │ .hex │ │ .cru │ └────────┘ └─────────┘ └──────────┘

The Three Targets

1. Headless Simulation

The host LISP interpreter runs your code directly on your computer. No Arduino, no simulator, no hardware needed. This is the fastest way to test logic, algorithms, and control flow.

Flow
.hil file → LISP parser → Host interpreter → Console output

The host monitor interprets every LISP expression in real-time. Serial commands like WRITE and TONE are logged instead of sent to hardware.

2. Arduino Hardware

Your LISP code is transpiled to Arduino C, compiled to a .hex firmware, and flashed to a real ATmega328P board.

Flow
.hil → LISP parser → C transpiler → Arduino C → avr-gcc → .hex → avrdude → Arduino

The transpiler converts each LISP S-expression into equivalent C code, including function wrappers for hardware calls.

3. CRUMB Simulator

Same as Arduino hardware, but the .hex is loaded into the CRUMB circuit simulator instead of real hardware.

Flow
.hil → LISP parser → C transpiler → .cru file → CRUMB simulator

Components

hil-cli (Go)

The command-line interface. Orchestrates all workflows, simulation, compilation, CRUMB generation, firmware flashing. Built in Go for single-binary distribution.

LISP Parser (Go)

Parses S-expressions into an AST. Handles hex literals, float literals, string concatenation, Arduino pin notation, and nested expressions. Unicode-safe with BOM stripping.

C Transpiler (Go)

Converts LISP AST to Arduino C source code. Generates complete .ino files with setup/loop, helper functions (servo, LCD, DHT, PID, NeoPixel), and proper Arduino API calls.

Host Interpreter (Go)

Real-time LISP evaluator for headless simulation. Maintains environment with variables, functions, and sensor state. Includes all 15+ operators, PID control, and event system.

CRUMB Generator (Go)

Creates .cru XML files compatible with the CRUMB Circuit Simulator. Injects transpiled Arduino C into the CRUMB template with proper component wiring.

VS Code Extension

TextMate grammar for syntax highlighting, 20+ code snippets, language configuration for bracket matching, and build tasks for simulation and CRUMB.

LISP → C Translation

Each LISP expression maps to specific Arduino C code:

LISPArduino C
(WRITE D 13 1)digitalWrite(13, HIGH);
(READ A 0)analogRead(A0);
(WRITE P 9 128)analogWrite(9, 128);
(DELAY 500)delay(500);
(TONE 11 440 200)tone(11, 440, 200);
(SERVO 9 90)myServo.write(90);
(SET x 10)int x = 10;
(IF (> x 5) ...)if (x > 5) { ... }
(WHILE 1 ...)while (true) { ... }
(FOR i 0 10 ...)for (int i = 0; i < 10; i++) { ... }
(DEFUN FOO (a b) ...)int FOO(int a, int b) { ... }

Data Flow

Every LISP expression returns a numeric value. Strings are stored as variables and passed through LOG. The environment is a flat key-value store — no scoping, no types.

Environment
Environment = { "led_pin": 13, "temp": 25.5, "counter": 0, "BLINK": Function(params, body), ... }

Error Handling

HIL is designed to be fault-tolerant:

This makes it safe for embedded use where crashing is not an option.