Files
tricu/AGENTS.md

6.4 KiB
Raw Blame History

AGENTS.md — tricu Project Guide

For AI agents and contributors working in this repository.

1. Build & Test

nix build .# always runs tests. This is the primary and only way to build and validate.

# Full build + tests (this is the default)
nix build .#

# Build only (skip tests)
nix build .#package

# Build the test-specific variant with doCheck enforced
nix build .#test
nix flake check

# Dev shell (includes ghcid, cabal-install, ghc, upx)
nix develop .#

⚠️ Never call cabal directly

This project uses a Nix flake that wraps callCabal2nix to produce the cabal package. All compilation, linking, and test execution are driven through Nix. Running cabal build, cabal test, cabal repl, or cabal install directly will use the system GHC (or .stack-work) and can produce artifacts that differ from the Nix-built ones — especially regarding megaparsec which is a project dependency.

Rule of thumb: if it builds, links, or tests, it goes through nix.

2. Project Overview

tricu (pronounced "tree-shoe") is a programming-language experiment written in Haskell. It implements Triage Calculus, an extension of Barry Jay's Tree Calculus, with lambda-abstraction sugar that gets eliminated back to pure tree calculus terms.

tricu is Lojban for "tree".

Core types (in src/Research.hs)

Type Description
T = Leaf | Stem T | Fork T T Tree Calculus term (the runtime value)
TricuAST Parsed AST with SDef, SApp, SLambda, etc.
LToken Lexer tokens
Node / MerkleHash Content-addressed Merkle DAG nodes

Source modules

Module Purpose
Main.hs CLI entry point (cmdargs), three modes: repl, eval, decode
Eval.hs Interpreter: evalTricu, result, evalSingle
Parser.hs Megaparsec parser → TricuAST
Lexer.hs Megaparsec lexer → LToken
FileEval.hs File loading, module imports, !import
REPL.hs Interactive Read-Eval-Print Loop (haskeline)
Research.hs Core types, apply reduction, booleans, marshalling (ofString, ofNumber), output formatters (toAscii, toTernaryString, decodeResult)
ContentStore.hs SQLite-backed term persistence

File extensions

  • .hs — Haskell source
  • .tri — tricu language source (used in lib/, test/, demos/)

3. Test Suite

Tests live in test/Spec.hs and use Tasty + HUnit.

nix flake check   # or: nix build .#test

Test groups

Group What it covers
lexer Megaparsec lexer — identifiers, keywords, strings, escapes, invalid tokens
parser Parser — defs, lambda, applications, lists, comments, parentheses
simpleEvaluation Core apply reduction rules, variable substitution, immutability
lambdas Lambda elimination, SKI calculus, higher-order functions, currying, shadowing, free vars
providedLibraries lib/list.tri — triage, booleans, list ops (head, tail, map, emptyList?, append, equal?)
fileEval Loading .tri files, multi-file context, decode
modules !import, cyclic deps, namespacing, multi-level imports, unresolved vars, local namespaces
demos demos/*.tri — structural equality, toSource, size, level-order traversal
decoding decodeResult — Leaf, numbers, strings, lists, mixed
elimLambdaSingle Lambda elimination: eta reduction, SDef binding, semantics preservation
stressElimLambda Lambda elimination stress test: 200 vars, 800-body curried lambda

Suggesting tests

You do not write or modify tests. The user writes tests to constrain your outputs. You must adhere your code to tests or suggest modifications to tests.

4. tricu Language Quick Reference

t                      → Leaf (the base term)
t t                    → Stem Leaf
t t t                  → Fork Leaf Leaf

x = t                  → Define term x = Leaf
id = (a : a)           → Lambda identity (eliminates to tree calculus)
head (map f xs)        → From lib/list.tri

!import "./path.tri" NS  → Import file under namespace

-- line comment
|- block comment -|

5. Output Formats

The eval command accepts --form (shorthand -t):

Format Value Description
tree TreeCalculus Simple t form (default)
fsl FSL Full show representation
ast AST Parsed AST representation
ternary Ternary Ternary string encoding
ascii Ascii ASCII-art tree diagram
decode Decode Human-readable (strings, numbers, lists)

6. Content Addressing

Each T term is content-addressed via a Merkle DAG:

NLeaf       → 0x00
NStem(h)    → 0x01 || h (32 bytes)
NFork(l,r)  → 0x02 || l (32 bytes) || r (32 bytes)

hash = SHA256("tricu.merkle.node.v1" <> 0x00 <> serialized_node)

This is stored in SQLite via ContentStore.hs. Hash suffixes on identifiers (e.g., foo_abc123...) are validated: 1664 hex characters (SHA256).

7. Directory Layout

tricu/
├── flake.nix           # Nix flake: packages, tests, devShell
├── tricu.cabal         # Cabal package (used via callCabal2nix)
├── src/                # Haskell modules
│   ├── Main.hs
│   ├── Eval.hs
│   ├── Parser.hs
│   ├── Lexer.hs
│   ├── FileEval.hs
│   ├── REPL.hs
│   ├── Research.hs
│   └── ContentStore.hs
├── test/
│   ├── Spec.hs         # Tasty + HUnit tests
│   ├── *.tri           # tricu test programs
│   └── local-ns/       # Module namespace test files
├── lib/
│   ├── base.tri
│   ├── list.tri
│   └── patterns.tri
├── demos/
│   ├── equality.tri
│   ├── size.tri
│   ├── toSource.tri
│   ├── levelOrderTraversal.tri
│   └── patternMatching.tri
└── AGENTS.md           # This file

8. Development Tips

  • Quick iteration: nix develop then ghcid (provided in the devShell) watches files and re-runs.
  • REPL: nix run .# starts the interactive REPL.
  • Evaluate files: nix run .# -- eval -f demos/equality.tri
  • GHC options: -threaded -rtsopts -with-rtsopts=-N for parallel runtime. Use -N RTS flag for multi-core.
  • Upx is in the devShell for binary compression if needed.