tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

README.md (4805B)


Four small SCP / tree-calculus lessons

Each lesson has its own equality/, patterns/, size/ or source/ directory, keeping its runner and SCP dependencies together. These are compiled SCP workers, not the reference IR interpreter. Start with each short .scp source; its .tri runner only reads and compiles source, supplies workers where needed, invokes it, and displays the result. From the repository root, after nix build .#:

result/bin/tricu arboricx import --store /tmp/scp-lessons \
  --file test/fixtures/support-library.arboricx --indexed
# Substitute equality, patterns or source for LESSON below.
result/bin/tricu arboricx run --store /tmp/scp-lessons --module support-library \
  --name demos_consumers_lessons_LESSON_LESSON.main --io \
  --allow-read demos/consumers/lessons --allow-read lib/consumer --format tree

size also has a stored entry with the same naming convention. Its logical self-size traversal can exceed short budgets; run it explicitly with a deadline, not as a required smoke test. The other three lesson runners have stored-execution coverage. This is native artifact loading, not Haskell source compilation.

The final t printed by --format tree is the IO program's return value, not part of a worker's output. These runners compile source at launch; they are not deployed-CAS startup measurements.

1. equality/structural-equality.scp — behavior is not representation

equal left right compares complete trees. The runner supplies two tricu identity functions: one returns its input; the other destructures and reconstructs every Leaf, Stem, and Fork. Their results agree on Leaf and Fork, but the functions' own trees differ:

same representation: same
two identities: different
result on Leaf: same
result on Fork: same

The shape-based definition is visibly identity for every reduced tree; merely checking two examples would not establish extensional equality in general. The older demos/equality.tri is another intensional comparison, but its particular two not definitions actually normalize to the same tree in the current compiler. Intensional equality is not a method for deciding arbitrary behavioral equivalence.

2. patterns/shape.scp — one tree, no declared datatype

Rule order distinguishes leaf, stem leaf, and a general Stem. A computed match child of (...) reuses the same structural patterns. Forks can be list cells, pairs, or executable code; the matcher sees shape, not a type label. Try t, t t, t (t t t), and t t t in patterns.tri. Unlike tricu-wide matchBool, SCP's choose matches only the two canonical Boolean trees; it is not used here to misclassify arbitrary non-Leaf trees.

3. size/tree-size.scp — size of code is still tree size

tree-size.scp structurally recurs over any tree. It calls two SCP workers, succ.scp and add.scp, on tricu's compact LSB natural-number trees; it does not use unary intermediate counts. The adder accepts two numbers as a pair, so there is no separate state adapter. call uses each worker's stored initial state, while recur preserves the pair of arithmetic descriptors. The runner prints 1, 2, and 3 for the smallest three tree shapes, then applies the compiled SCP size worker to its own worker descriptor. That last number depends on the compiler and descriptor representation (69382 on one checked build): it is not an intrinsic constant or the same term as the lambda implementation in demos/size.tri. showNumber merely renders the compact number already computed by SCP. This larger worker descriptor also exposes the cost of compiling nested SCP workers.

4. source/to-source.scp — inspect a value, not remembered source text

The renderer walks the tree and emits t, (t child), or (t left right); it works on executable functions too. source.tri renders a Leaf, Stem, Fork, the tricu identity function, and the tree behind a quoted string. The function's output reflects its eliminated tree, not the original x : x spelling; the quoted string is a list tree, not the characters "a" in source notation. This is the same intensional idea as demos/toSource.tri, written as an SCP program.

The renderer joins fragments through several calls to join.scp, which delegates to lib/consumer/append.scp with an explicit suffix. Each call uses the target's initial state.

Continue exploring

These lessons use input @ state, scoped captures, recursion, and calls to expose tree structure and worker relationships. Larger compositions and effects live one directory above.