Verified Commit 3ac5bae0 authored by james's avatar james
Browse files

feat(compiler): add verified pixel compiler and templeos runner

parents
Loading
Loading
Loading
Loading

.gitignore

0 → 100644
+2 −0
Changes for .gitignore: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
/.build/
__pycache__/

Makefile

0 → 100644
+23 −0
Changes for Makefile: 23 added lines, 0 removed lines.
Original line number Diff line number Diff line
ISABELLE ?= isabelle

.PHONY: all check payload clean

all: .build/ready

.build/ready: ROOT $(wildcard src/*.thy) cli/driver.ML Makefile
	@test "$$('$(ISABELLE)' version)" = Isabelle2026
	"$(ISABELLE)" build -D . -j 1 -o threads=1 -o parallel_proofs=0
	"$(ISABELLE)" export -n -d . -O .build -x 'Remy.Export:code/remy.ML' Remy
	REMY_ROOT="$(CURDIR)" "$$('$(ISABELLE)' getenv -b POLYML_HOME)/$$('$(ISABELLE)' getenv -b ISABELLE_PLATFORM64)/polyc" -o .build/remy cli/driver.ML
	@touch $@

check: all
	python3 tests/native.py

payload: all
	@mkdir -p .build/payload
	@set -e; for name in Rings Weave Cells; do .build/remy examples/$$name.remy .build/payload/$$name.BIN; .build/remy vectors examples/$$name.remy .build/payload/$$name.DAT; cp examples/$$name.remy .build/payload/$$name.TXT; done
	cp guest/Remy.HC .build/payload/Remy.HC

clean:
	rm -rf .build

README.md

0 → 100644
+36 −0
Changes for README.md: 36 added lines, 0 removed lines.
Original line number Diff line number Diff line
Pixel expressions compile to native x86+64 for TempleOS through a compiler implemented in Isabelle/HOL with proofs of constant folding, lexical slot allocation, bounded stack execution and correspondence with a register and stack model

[![i like men](media/demo.gif)](media/demo.mp4)

## Build

```sh
make check
make payload
```

It uses:
- Isabelle2026 and its bundled Poly/ML toolchain 
- Python

Copy these files onto `C:/` in TempleOS and run:

```c
#include "C:/Remy.HC";
Verify;
Show(0);
```

## Correctness

Each `let` pushes a binding onto the evaluation stack. [Compilation](src/Compiler.thy) adjusts variable offsets as intermediate values accumulate above those bindings and proves that execution leaves the result followed by the original stack whereas accepted programs stay within 512 evaluation words at every instruction boundary

[Native lowering](src/Native.thy) puts the result in `rax` and preserves `r8`, `r9` and `rdx` which carry `x`, `y` and `t`. The temporary registers are `rax`, `rcx` and `rbx` while the [Encoding](src/Encoding.thy) proves decoder inversion and byte bounds for the emitted blocks including their immediate operands and stack displacements

![Source eval](media/correspondence.svg)

Arithmetic wraps modulo `2^64` and shifts mask their count to six bits

Both branches of a nonconstant conditional run before selection which preserves the result because expressions have no side effects. The HolyC runner masks each pixel result to four bits for the TempleOS palette

The execution theorem is relative to the instruction block model. Actual x86 execution + the HolyC calling bridge and the extracted runtime and the OS are outside its scope. Tests compare emitted code against an independent evaluator on Linux and against HOL results inside the recorded TempleOS guest

ROOT

0 → 100644
+18 −0
Changes for ROOT: 18 added lines, 0 removed lines.
Original line number Diff line number Diff line
session Remybase = HOL +
  options [document = false]
  sessions "HOL-Library"
  theories
    "HOL-Library.Word"
    "HOL-Library.Code_Target_Numeral"

session Remy in src = Remybase +
  options [document = false]
  sessions "HOL-Library"
  theories
    Model
    Compiler
    Native
    Encoding
    Frontend
    Examples
    Export

cli/driver.ML

0 → 100644
+40 −0
Changes for cli/driver.ML: 40 added lines, 0 removed lines.
Original line number Diff line number Diff line
val root = valOf (OS.Process.getEnv "REMY_ROOT");
val _ = use (root ^ "/.build/Remy.Export/code/remy.ML");

fun chars s = map (Remy.ascii o IntInf.fromInt o Char.ord) (String.explode s);
fun text cs = String.implode (map (Char.chr o IntInf.toInt o Remy.ordinal) cs);

fun read path =
  let
    val stream = TextIO.openIn path
    val input = TextIO.inputN (stream, 65537)
      handle exn => (TextIO.closeIn stream; raise exn)
    val _ = TextIO.closeIn stream
  in
    if size input > 65536 then raise Fail "source exceeds 64 KiB" else chars input
  end;

fun write path bytes =
  let
    val stream = BinIO.openOut path
  in
    (BinIO.output (stream, Byte.stringToBytes (text bytes)); BinIO.closeOut stream)
      handle exn => ((BinIO.closeOut stream handle _ => ()); raise exn)
  end;

fun output (ok, message) =
  (TextIO.output (if ok then TextIO.stdOut else TextIO.stdErr, text message);
   if ok then () else OS.Process.exit OS.Process.failure);

fun main () =
  (case CommandLine.arguments () of
    ["vectors", source, destination] =>
      (case Remy.vectors (read source) of (true, bytes) => write destination bytes | result => output result)
  | ["eval", source, x, y, t] => output (Remy.reference (read source) (chars x) (chars y) (chars t))
  | [source, destination] =>
      let val ((ok, bytes), report) = Remy.artifact (read source)
      in if ok then (write destination bytes; output (true,report)) else output (false,report) end
  | _ => raise Fail "usage: remy source binary | remy vectors source data | remy eval source x y t")
  handle exn =>
    (TextIO.output (TextIO.stdErr, "remy: " ^ General.exnMessage exn ^ "\n");
     OS.Process.exit OS.Process.failure);
Loading