# Raic / T-AST: inline tutorial for model authors

This preamble teaches **Raic** in its **T-AST (Tokenized AST)** form: a compact, tokenizer-friendly surface that compiles to **idiomatic Rust**. Treat it as a **serialization of intent**, not as free-form prose code.

---

## 1. What you are emitting

- **One file** (e.g. `main.rc`) containing **T-AST** source.
- T-AST is **line-oriented**. Items are separated by **blank lines** (double newlines) or single newlines between consecutive lines in the same “block” as defined by the reference compiler.
- Everything at **crate visibility** is **`pub` by default** in the emitted Rust unless marked private with a leading `_` on the item (where applicable).

The **reference compiler** (`raic compile`) maps T-AST → Rust **deterministically**. Unsupported opcode sequences are rejected with a clear error—so stay within the **supported opcode set** for the task, or emit **minimal** structs and the documented function patterns.

---

## 2. Type abbreviations (single-token types)

Use these **exact** spellings (they are designed to be **one BPE token** in many code models):

| T-AST | Rust |
|------|------|
| `I` | `i32` |
| `N` | `usize` |
| `b` | `bool` |
| `s` | `&str` in signatures (parameter type) |
| `S` | `String` |
| `[T]` | `Vec<T>` — bracket the inner type; e.g. `[S]` is `Vec<String>` |
| `[(S N)]` | `Vec<(String, usize)>` — vector of pairs (tuple inside parens) |
| `M<K V>` | `HashMap<K, V>` — **space** between `K` and `V` inside the angle brackets |

Full Rust type paths are **not** required in T-AST for this tutorial; stick to abbreviations above for portability.

---

## 3. Struct declarations

Form (one line):

```text
@ StructName field1:T1 field2:T2 …
```

Each field is `name:T` with **no space** around the colon inside the token (the line is still whitespace-separated between fields).

**Example:**

```text
@ Post slug:S title:S body:S
```

Emits a public struct with `pub` fields.

**Constraints:** at least **one** field; struct name follows `@` immediately.

---

## 4. Function declarations (signatures + postfix opcodes)

Form:

```text
name arg_ty … : ret_ty = opcode1 opcode2 …
```

- **Arguments:** T-AST types separated by spaces (each argument is one type; compound types like `[(S N)]` are a **single** token group—see below).
- **Separator:** a **top-level** ` : ` (space, colon, space) between the **argument list** and the **return type**. Do not rely on colons **inside** types at depth (the compiler tracks `[]` and `<>`).
- **Body:** after `=` , a **whitespace-separated** list of **opcode tokens** (no commas).

**Example (canonical, fully supported opcode chain):**

```text
top_words s N : [(S N)] = Ws Fm Vi Sd Tk
```

Meaning (conceptually):

- Arguments: `s` → `&str`, `N` → `usize`.
- Return: `[(S N)]` → `Vec<(String, usize)>`.
- Opcodes: `Ws` (split_whitespace pipeline), `Fm` (frequency map fold), `Vi` (into_iter / collect vector step), `Sd` (sort by second tuple field descending), `Tk` (take + collect tail).

The compiler expands this chain to a **fixed**, idiomatic Rust body (frequency counting, sort, take). Parameter names in Rust are synthesized (e.g. `text`, `n`)—you do **not** write `fn`/`let`/braces in T-AST.

---

## 5. Opcode vocabulary (reference)

**Documented opcodes** (the dictionary will grow):

| Opcode | Role |
|--------|------|
| `Ws` | Part of the `split_whitespace` / iterator pipeline for the canonical word-count example |
| `Fm` | Frequency map fold (HashMap count pattern) |
| `Vi` | Collect / vector transition step in the canonical chain |
| `Sd` | Sort `Vec` of pairs by **second element descending** |
| `Tk` | Take first *n* then collect (pairs with `N` argument) |
| `.` | (Planned) duplicate stack top — `.clone()` |
| `x` | (Planned) swap two stack values |
| `_` | (Planned) drop top |

**Combinators (planned / grammar-level):**

- `? [ A ] [ B ]` — conditional on boolean (two postfix blocks).
- `# [ block ]` — map over iterator.

For **maximum compatibility** with the **current** compiler, prefer:

1. **Structs** as in §3.
2. **Exactly one** function line using the **supported** chain `Ws Fm Vi Sd Tk` with signature `… s N : [(S N)]` when you need that behavior.
3. Avoid inventing new opcode tokens unless the specification explicitly allows them—they will **fail to compile** until added to the compiler.

---

## 6. Multi-item files

Separate **top-level** items with a **blank line**:

```text
@ Config site_title:S base_url:S

top_words s N : [(S N)] = Ws Fm Vi Sd Tk
```

Order is preserved in emission. HashMap `use` is inserted automatically when `Fm` or `M<…>` types appear.

---

## 7. What T-AST is *not*

- Not **Rust** syntax: no `fn`, `let`, `;`, `{` `}` in the surface form for the opcode-driven subset.
- Not **arbitrary** Rust: you cannot embed raw Rust in T-AST files for the reference compiler today.
- Not **ambiguous**: one spelling → one expansion pattern per opcode entry.

---

## 8. Compiling and running

```bash
raic compile main.rc -o generated.rs
```

Place `generated.rs` into a Cargo project (`src/main.rs` or binary target) with `Cargo.toml` dependencies matching what the emitted Rust needs (e.g. `std::collections::HashMap` is already used; add crates if you later emit broader Rust).

---

## 9. Checklist before you answer

- [ ] File uses **only** T-AST lines you can justify with this document.
- [ ] Every function line has `name … : ret = …` with a **known-good** opcode list for this compiler version.
- [ ] Structs use `@ Name field:T …`.
- [ ] No extra prose outside the source file content.

You will now receive the **task** in the same message. Follow the **task** exactly, and emit **only** the requested filename’s contents.

---

## 10. More struct examples

```text
@ Page path:S title:S
```

```text
@ Site name:S url:S posts:N
```

Field names are identifiers before `:`. Types use the abbreviations from §2. Nested generics like `M<S N>` for a field are allowed when the compiler’s type parser supports them (HashMap inserts `use std::collections::HashMap` in the output when needed).

---

## 11. Signature parsing rules (precision)

- The **`=`** sign that separates **signature** from **opcode body** must appear at **depth zero** with respect to `[]`, `<>`, and `()` nesting. Do not put raw `=` inside a type.
- The **` : `** between **arguments** and **return type** is also parsed at depth zero: it must be **space-colon-space** so it is not confused with characters inside `M<K V>`.
- Argument types are parsed **left to right** with a greedy “one type per argument” rule: `s`, `N`, `[(S N)]` are three separate arguments if written as three tokens.

---

## 12. When you need behavior the opcodes do not cover

The reference compiler **version 1** ships a **small** opcode→Rust library. If your task needs I/O, HTTP, or a full Markdown pipeline, you have two honest options:

1. **Stay in T-AST** and implement only what maps to supported patterns (may be insufficient for large tasks).
2. **Ask the user for Rust** instead of Raic (outside this preamble’s scope).

Do **not** emit pseudo-opcodes that look plausible but are undefined—compilation will fail.

---

## 13. Worked mental model: stack shape for `top_words`

Think of the postfix chain as operating over **values** threaded by the emitter:

1. **Inputs** `text: &str` and `n: usize` are fixed by the signature order `s` then `N`.
2. **`Ws`** prepares the whitespace-split iterator pipeline from `text`.
3. **`Fm`** materializes the counting loop into a `HashMap<String, usize>`.
4. **`Vi`** moves to a `Vec` representation where needed for sorting.
5. **`Sd`** sorts by descending frequency (tuple `.1`).
6. **`Tk`** applies `take(n)` and final `collect()` into `Vec<(String, usize)>`.

You do not write these steps in Rust—you write the **opcode name** and the compiler expands **one** canonical Rust shape.

---

## 14. Formatting and whitespace

- **One statement per line** for each top-level item is typical.
- **Do not** indent T-AST with semantic meaning (unlike Python); the compiler is **not** indentation-sensitive for T-AST v1.
- **UTF-8** throughout; avoid smart quotes in source tokens.

---

## 15. Interoperability with Rust projects

After `raic compile`:

- You get a **single** Rust translation unit (or concatenated items) suitable for dropping into `src/main.rs`.
- Add **dependencies** in `Cargo.toml` for any **additional** Rust you hand-edit *after* generation. The T-AST emit for `Fm` already assumes `HashMap` import rules as implemented.

---

## 16. Glossary

| Term | Meaning |
|------|---------|
| T-AST | Tokenized AST: postfix opcode + abbreviated types |
| Opcode | Token in the `= …` body naming an expansion pattern |
| Thick AST | Macro-level opcode that expands to many Rust lines |
| `s` | String slice parameter type (`&str`) in Rust position |

---

## 17. Duplicate copy of the canonical function (memorization aid)

```text
top_words s N : [(S N)] = Ws Fm Vi Sd Tk
```

This line is the **reference** integration test for the toolchain. If you only learn one function, learn this one.

---

## 18. Security and determinism

- **Deterministic:** same T-AST input → same Rust output (for a fixed compiler version).
- **No `unsafe`** in opcode expansions shipped by the reference compiler unless explicitly documented elsewhere.

---

## 19. Version note

This preamble matches **T-AST** in the project README and **`tests/integration.rs`**. Emit only the forms documented here unless the task explicitly allows something else.

---

## 20. Final reminder

Output **only** the source requested in the task (e.g. `main.rc`). No YAML front matter, no JSON wrapper, no explanation—unless the task explicitly allows it.

---

## 21. Extra examples (repetition for calibration)

The following blocks are **intentionally repetitive** so models internalize spelling. They are **not** additional requirements—just pattern reinforcement.

**Struct + function file:**

```text
@ Config title:S

top_words s N : [(S N)] = Ws Fm Vi Sd Tk
```

**Function only:**

```text
rank_terms s N : [(S N)] = Ws Fm Vi Sd Tk
```

**Struct only:**

```text
@ User id:N name:S
```

**Another struct:**

```text
@ NavItem label:S href:S
```

**Pair types inside vectors:**

- `[(S N)]` — pairs of `String` and `usize`.
- `[S]` — vector of strings.

**Map types:**

- `M<S N>` — keys `String`, values `usize`.

---

## 22. Anti-patterns (do not do)

- Do **not** emit Rust keywords (`fn`, `struct`, `let`) as if they were T-AST—unless the task switches language to Rust.
- Do **not** mix Markdown bullet lists **inside** `main.rc`—the file must be **pure** T-AST / comments are **not** part of v1 (no comment token yet).
- Do **not** use `#` at line start for headings inside `main.rc`—`#` may be reserved for combinators in future grammar.

---

## 23. Line endings

Use **Unix** `\n` line endings in emitted source for predictable hashing and tooling.

---

## 24. Filename convention

- **`main.rc`** — Raic / T-AST source for this evaluation harness.
- After compile, consumers may rename to `main.rs` inside Cargo.

---

## 25. Closing

You now have enough context to emit valid T-AST for tasks that fit the supported opcode surface. If a task is **too large** for opcode v1, acknowledge by producing the **smallest** valid T-AST program that still **compiles**, and rely on comments in Rust **after** compile—or request clarification in a setting that allows prose (not in this harness).

---

# Task

Produce a **complete, runnable** program (a single source file) that implements a **static blog generator** CLI—conceptually similar to Hugo (not full feature parity).

## Required behavior

1. **Templates**: If `templates/top.html` and/or `templates/bottom.html` exist, wrap each generated page: top HTML + rendered body + bottom HTML. If a template file is missing, emit the body alone.
2. **Content**: Read Markdown from `content/*.md` (recursive or top-level only—your choice, but be consistent). Render each file to HTML under an output directory (default `site/`). Preserve a sensible URL layout (e.g. `content/a/b.md` → `site/a/b/index.html` or `site/a/b.html`—pick one and document in a comment at the top of the file).
3. **CLI**:
   - **Default** (no subcommand): build the site from the current working directory (optional `--root <dir>` is allowed).
   - **`--init`**: create a **full** initial project tree: `templates/`, `content/`, default `templates/top.html`, `templates/bottom.html`, and **`content/home.html`** (plus anything else required) such that running the generator **without** `--init` on that tree produces a complete `site/` with at least a home page. Subsequent runs should allow adding more files under `content/`.
4. **Execution**: The program must be suitable for `cargo run` with dependencies you declare (use common crates: CLI parsing, Markdown → HTML, path walking, etc.).

## Output contract

- Emit **only** the full source code for **`main.rc`** (no prose before or after).
- No markdown code fences unless your answer would be ambiguous without them; prefer raw source.
- No `TODO` or placeholder logic: the program must be logically complete.

**Target language:** Raic **T-AST** exactly as defined in the **preamble above**. Emit only constructs the reference `raic compile` accepts for this compiler version.
