Skip to content

Commit 0744ca4

Browse files
committed
Reorganize examples into per-demo folders, fix http_server, and stop committing generated C.
Each example now has its own ion.toml and target/ output; http_server serves until stdin quit with a correct 144-byte HTML body.
1 parent 1b4e317 commit 0744ca4

41 files changed

Lines changed: 273 additions & 2156 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cursor/skills/adding-ion-features/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ New builtins (channels, Vec, String, spawn) often need C runtime helpers. Keep h
111111

112112
## Debugging a failing stage
113113

114-
**Stale binaries:** Rebuild `target/release/ion-compiler` (and `ion-build` when touching build code) after cgen or tc changes before `test_runner.sh` or regenerating `examples/*.c`. The harness defaults to `../target/release/ion-compiler`. Agent shells may set `CARGO_TARGET_DIR` outside the repo; pin it to the repo `target/` when verifying locally, or override with `COMPILER=` / `ION_BUILD=` and confirm the binary mtime.
114+
**Stale binaries:** Rebuild `target/release/ion-compiler` (and `ion-build` when touching build code) after cgen or tc changes before `test_runner.sh` or rebuilding examples.
115115

116116
```bash
117117
# See parser/tc errors

.cursor/skills/ion-integration-tests/SKILL.md

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,9 @@ paths:
1515

1616
End-to-end tests: Ion → C → gcc → run executable → assert exit code (or assert compile failure).
1717

18-
The harness runs tests under `tests/` only. Files in `examples/` are documented demos; build and run them with `ion-build` and per-example manifests (see [README.md](../../../README.md#example-programs)). Regenerate committed `examples/*.c` snapshots with `ion-compiler` after codegen changes.
18+
The harness runs tests under `tests/` only. Files in `examples/` are documented demos; build and run them with `ion-build` from each example directory (see [README.md](../../../README.md#example-programs)).
1919

20-
**Example output policy:** Top-level single-file examples commit one merged `.c` next to the `.ion`. `text_summary/` commits one `.c` plus `sample.txt`. `data_lib/` and `todo_demo/` keep `.ion` and `ion.toml` only (see each directory's `README.md`).
21-
22-
After compiler codegen changes, regenerate committed example `.c` files:
23-
24-
```bash
25-
cargo build --release --bin ion-compiler
26-
for f in examples/*.ion; do ./target/release/ion-compiler "$f"; done
27-
./target/release/ion-compiler examples/text_summary/text_summary.ion
28-
```
29-
30-
Multi-file `examples/data_lib/` has no committed `.c`; see `examples/data_lib/README.md`. `examples/todo_demo/` is the same; see `examples/todo_demo/README.md`.
20+
**Example output policy:** Each demo is `examples/<name>/` with `ion.toml`. Generated `.c` and executables go under that directory's `target/` (not committed). `text_summary/` also ships `sample.txt`.
3121

3222
To build examples, use `ion-build` (see README). Manual `gcc` + `runtime/ion_runtime.c` is for the test harness and advanced debugging only.
3323

.cursor/skills/ion-lang/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ Read these when the task matches:
102102
1. **Spec first** - If semantics change, update `ION_SPEC.md` before or alongside code.
103103
2. **Minimal diff** - Match existing patterns in the module you're editing; don't refactor adjacent code.
104104
3. **Test both paths** - Positive compile+run tests and negative compile-error tests where applicable.
105-
4. **Rebuild release** - Integration harness defaults to `target/release/ion-compiler`. After codegen changes, rebuild before `test_runner.sh` or regenerating `examples/*.c`. Confirm the binary timestamp matches your build; a stale `target/release/ion-compiler` can pass an old harness run or fail on new tests. Cursor agent shells may set `CARGO_TARGET_DIR` outside the repo; point `COMPILER=` at the binary you just built, or unset `CARGO_TARGET_DIR` and rebuild into `target/release/`.
105+
4. **Rebuild release** - Integration harness defaults to `target/release/ion-compiler`. After codegen changes, rebuild before `test_runner.sh` or rebuilding examples.
106106

107107
## Common pitfalls
108108

.cursor/skills/writing-ion-code/SKILL.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ For syntax templates and anti-patterns, see [references/verified-patterns.md](re
4545

4646
## Minimal program (stdlib I/O)
4747

48-
From [examples/hello_world_safe.ion](../../../examples/hello_world_safe.ion):
48+
From [examples/hello_world_safe/hello_world_safe.ion](../../../examples/hello_world_safe/hello_world_safe.ion):
4949

5050
```ion
5151
import "stdlib/io.ion" as io;
@@ -100,7 +100,7 @@ Tuple values (flat only, no nesting): `let t: (int, int) = (1, 2);` then `t.0`,
100100

101101
**Channels and spawn**
102102

103-
From [examples/spawn_channel.ion](../../../examples/spawn_channel.ion):
103+
From [examples/spawn_channel/spawn_channel.ion](../../../examples/spawn_channel/spawn_channel.ion):
104104

105105
```ion
106106
let (tx, rx): (Sender<int>, Receiver<int>) = channel<int>();
@@ -154,12 +154,13 @@ Built-ins: `Vec<T>`, `String`, `Box<T>`, `Option<T>`, `Result<T, E>` (define enu
154154

155155
## Build and verify
156156

157-
With `ion.toml` in the project or example directory (or `examples/*.toml` with `--manifest`):
157+
With `ion.toml` in the example directory:
158158

159159
```powershell
160160
cargo build --release --bin ion-build
161-
cd examples # or example subdirectory with ion.toml
162-
..\target\release\ion-build.exe build --manifest spawn_channel.toml
161+
cd examples\spawn_channel
162+
..\..\target\release\ion-build.exe build
163+
.\target\spawn_channel.exe
163164
.\target\spawn_channel.exe
164165
echo $LASTEXITCODE
165166
```

.cursor/skills/writing-ion-code/references/verified-patterns.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ Manual codegen only (emits `.c`/`.h` in cwd):
130130
./target/release/ion-compiler --mode multi --output app path/to/main.ion
131131
```
132132

133-
Multi-file mode prefixes each module's C symbols (`io_print_int`, `fmt_print_int`) so stdlib modules can link together. The compiler walks up from the current directory to find `runtime/`. Spawn captures move by value even for `int`; use a helper function if the same constant is needed after `spawn` (see `examples/channel_worker.ion`).
133+
Multi-file mode prefixes each module's C symbols (`io_print_int`, `fmt_print_int`) so stdlib modules can link together. The compiler walks up from the current directory to find `runtime/`. Spawn captures move by value even for `int`; use a helper function if the same constant is needed after `spawn` (see `examples/channel_worker/channel_worker.ion`).
134134

135135
## Channel send expressions
136136

.gitignore

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,9 @@ target/
2323
# ------------------------------------
2424
# 4. Ion-Specific Generated Files
2525
# ------------------------------------
26-
# Ignore compiled binaries in examples
27-
examples/hello_world
28-
examples/hello_world_safe
29-
examples/http_server
30-
examples/minimal
31-
examples/showcase
32-
33-
# Ion-generated C and object files (Uncomment if you generate these files in your project root)
34-
# *.c
35-
# *.o
36-
37-
# Do NOT ignore .c or .ion source files in examples
38-
!examples/*.c
39-
!examples/**/*.c
40-
!examples/*.ion
26+
examples/**/target/
27+
examples/**/*.c
28+
examples/**/*.o
4129

4230
# ------------------------------------
4331
# 5. Editor / OS Files

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
- **Tooling**: GitHub Actions CI (Linux and Windows), pinned toolchain (1.96.0), `test_expectations.tsv` manifest, `--version`, line-numbered errors, Cursor agent skills. Split `tc` and `cgen` into submodules. `ion-build` driver and `ion.toml` manifests (`single`/`multi`, `out_dir`, `cflags`, `ldflags`, `stdlib_paths`, `emit_in_source`); per-example manifests and `build_hello`/`build_bad_main` harness smoke tests. Shared `discover_import_config` and stdlib search paths for `ion-compiler`, `ion-build`, and LSP. Integration harness precompiles `runtime/ion_runtime.c` once per run (`RUNTIME_OBJ`). `writing-ion-code` agent skill; `creating-ion-skills` examples index lists all eight project skills. Documented checked-in `examples/*.c` codegen snapshots in README and integration-test skill; regenerated example C output. Fixed `researching-pl-literature` skill `paper-seeds` reference formatting.
1111
- **Docs**: README, CONTRIBUTING, ION_SPEC, and agent skills aligned on project layout, `ion-build` workflow, `emit_in_source`, stdlib import order, LSP features and limitations, `src/build/` checklists, portable Git Bash paths for `test_runner.sh`, and rebuilding release binaries before harness or example C regen (stale `target/release/ion-compiler` note).
1212
- **Fixes**: match rvalue codegen, `Vec` struct drops, channel codegen, parser handling of `alias::call()`, scope-drop for moved-into-call bindings, HTTP server on Windows, integration harness on Windows. Cgen return-unwind: stop marking bindings dropped after inner-branch `return` (restores outer-path drops), dedupe `_`-prefixed unused silences, mark call arguments moved at emission to avoid double-free on unwind, and unify all function returns via `emit_function_return` (including diverging rvalue `match` arms). Cgen struct field move-out neutralizes owned fields after partial move, deferred to statement end when the move is a call argument; `Vec::push` passes address of struct lvalues; non-generic enums emit before structs; tuple IR uses resolved element types and `tuple_Vec_T` mangling with compound-zero `ret_val` for tuple returns (functions and fn literals). Integer indexing and `Vec<i32>` inference in the type checker. Match rvalue arms: reject diverging arms mixed with value arms; structural control-flow analysis for arm bodies (nested `if`/`else`, `loop` without `break`, `unsafe` blocks); reject mixed diverge and value-producing paths within one arm; cgen assigns through `if`/`else` value branches. `fmt::int_to_string` uses `String::push_byte` per digit instead of per-digit `push_str` branches; integration test asserts `0`, negatives, and `int::MIN`. `int::MIN`/`int::MAX` on integer primitives; `Vec::new()`/`with_capacity()` infer `T` from a `let` type annotation. Clippy fix in `portable_source_label`. `Vec::get`/`Vec::pop`: IR infers `Option<T>` from the vector argument; cgen dereferences `&mut Vec<T>` parameters, unpacks runtime `Option` via `ion_option_from_raw`, and uses a temp for struct-returning `Vec::push`/`Vec::set` call values. Grouped `match` switch arms: scope drops before the case `break` (GCC `-Wimplicit-fallthrough` under `-Werror`); guarded arms in a shared variant case break inside the guard `if` so fallback arms do not run.
13-
- **Examples**: `text_summary` (fixture file), `data_lib` (multi-module), `channel_worker` (flat single-file), `todo_demo` (interactive stdin, `Vec` of structs with `String`). Per-example `*.toml` manifests for `ion-build`. `http_server` accepts one client then exits (verifiable demo).
14-
- **Multi-file fixes**: merge private struct types for cross-module type checking; per-module C symbol prefixes in multi-file codegen (`io_print_int`); walk-up `runtime/` discovery for nested build directories. Integration tests `test_multi_struct`, `test_multi_fmt_io`. Example policy: single-file examples commit `.c` snapshots; `data_lib` multi-file keeps `.ion` only.
13+
- **Examples**: `text_summary` (fixture file), `data_lib` (multi-module), `channel_worker` (flat single-file), `todo_demo` (interactive stdin, `Vec` of structs with `String`). Per-example `*.toml` manifests for `ion-build`. `http_server` accepts clients until stdin `quit`.
14+
- **Multi-file fixes**: merge private struct types for cross-module type checking; per-module C symbol prefixes in multi-file codegen (`io_print_int`); walk-up `runtime/` discovery for nested build directories. Integration tests `test_multi_struct`, `test_multi_fmt_io`. Example policy: each demo under `examples/<name>/` with `ion.toml`; build output under `target/` only (no committed `.c`).
1515

1616
## 2025-12
1717

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
cargo build --release --bin ion-compiler --bin ion-build --bin ion-lsp
1313
```
1414

15-
After compiler codegen changes, rebuild before `tests/test_runner.sh` or regenerating committed `examples/*.c`. A stale `target/release/ion-compiler` can produce misleading harness results.
15+
After compiler codegen changes, rebuild before `tests/test_runner.sh` or rebuilding examples. A stale `target/release/ion-compiler` can produce misleading harness results.
1616

1717
Install CLI tools into your Cargo bin directory:
1818

ION_SPEC.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,7 @@ cargo build --release --bin ion-build
11961196
.\target\release\ion-build.exe build
11971197
```
11981198

1199-
Manifest discovery walks upward from the current directory for a file named `ion.toml`. To use another filename (for example `examples/http_server.toml`), pass `--manifest <path>`; the manifest's parent directory is the project root and `main` paths are relative to that directory.
1199+
Manifest discovery walks upward from the current directory for a file named `ion.toml`. Pass `--manifest <path>` when cwd is not the example directory; the manifest's parent directory is the project root and `main` paths are relative to that directory.
12001200

12011201
`ion-compiler` remains available for codegen inspection, LSP internals, and integration tests that grep `.c` output. It does not require `ion.toml`.
12021202

README.md

Lines changed: 25 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,15 @@ cargo build --release --bin ion-build
118118

119119
`ion build` transpiles, compiles generated C, links the runtime, and writes the executable under `target/` by default.
120120

121-
Source: [examples/hello_world_safe.ion](examples/hello_world_safe.ion). For a minimal FFI example without stdlib, see [examples/hello_world.ion](examples/hello_world.ion).
121+
Source: [examples/hello_world_safe/hello_world_safe.ion](examples/hello_world_safe/hello_world_safe.ion). For a minimal FFI example without stdlib, see [examples/hello_world/hello_world.ion](examples/hello_world/hello_world.ion).
122122

123123
### Advanced: Manual Transpile and Link
124124

125125
For codegen inspection, integration test workflows, or debugging generated C, use `ion-compiler` directly (see [ION_SPEC.md section 10.1](ION_SPEC.md#101-project-build-ion-build)):
126126

127127
```bash
128-
./target/release/ion-compiler examples/hello_world.ion
129-
gcc examples/hello_world.c runtime/ion_runtime.c -o hello_world \
128+
./target/release/ion-compiler examples/hello_world/hello_world.ion
129+
gcc examples/hello_world/target/hello_world.c runtime/ion_runtime.c -o hello_world \
130130
-I. -I.. -Iruntime -I../runtime -lpthread
131131
./hello_world
132132
```
@@ -137,15 +137,15 @@ The integration harness (`tests/test_runner.sh`) calls `ion-compiler` and `gcc`
137137

138138
`ion-build` discovers `ion.toml` by walking up from the current directory. Required fields: `name`, `main`, `output`. Common optional fields: `mode` (`single` or `multi`), `out_dir` (default `target`), `cflags`, `ldflags`, `stdlib_paths`, `emit_in_source`.
139139

140-
Root [ion.toml](ion.toml) builds [examples/hello_world_safe.ion](examples/hello_world_safe.ion). Per-example manifests live under [examples/](examples/) (for example `spawn_channel.toml`, `http_server.toml`, `examples/data_lib/ion.toml`). Use `--manifest path` when the file is not named `ion.toml`:
140+
Root [ion.toml](ion.toml) builds [examples/hello_world_safe/hello_world_safe.ion](examples/hello_world_safe/hello_world_safe.ion). Each example lives in its own directory under [examples/](examples/) with an `ion.toml` manifest. Use `--manifest path` when cwd is not the example directory:
141141

142142
```powershell
143-
cd examples
144-
..\target\release\ion-build.exe build --manifest http_server.toml
145-
.\target\http_server.exe
143+
cd examples\spawn_channel
144+
..\..\target\release\ion-build.exe build
145+
.\target\spawn_channel.exe
146146
```
147147

148-
FFI programs that rename C symbols (for example `recv_sys`) set compile-time `-D` flags in `cflags`, not `ldflags`. See [examples/http_server.toml](examples/http_server.toml).
148+
FFI programs that rename C symbols (for example `recv_sys`) set compile-time `-D` flags in `cflags`, not `ldflags`. See [examples/http_server/ion.toml](examples/http_server/ion.toml).
149149

150150
### Multi-file projects
151151

@@ -161,53 +161,31 @@ For manual multi-file codegen in the source directory (no `ion-build`), use `ion
161161

162162
## Example Programs
163163

164-
Top-level `examples/*.ion` files each have a checked-in merged `examples/*.c` codegen snapshot. Regenerate after compiler codegen changes (from repo root, relative paths keep portable banners):
165-
166-
```bash
167-
for f in examples/*.ion; do ./target/release/ion-compiler "$f"; done
168-
./target/release/ion-compiler examples/text_summary/text_summary.ion
169-
```
170-
171-
Committed `.c` snapshots are for review and `ion-compiler` regression; building and running examples uses `ion-build` and the manifests below.
164+
Each example is a subdirectory of [examples/](examples/) with `ion.toml`. Build with `ion-build` from that directory; generated C and executables go under `target/` (not committed).
172165

173-
**Build and run** (from `examples/` unless noted):
166+
**Build and run:**
174167

175168
```powershell
176-
# Single-file example with a manifest in examples/
177-
..\target\release\ion-build.exe build --manifest spawn_channel.toml
178-
.\target\spawn_channel.exe
179-
180-
# http_server (FFI cflags in http_server.toml)
181-
..\target\release\ion-build.exe build --manifest http_server.toml
182-
183-
# text_summary (has its own ion.toml; needs sample.txt in that directory)
184-
cd text_summary
169+
cd examples\spawn_channel
185170
..\..\target\release\ion-build.exe build
186-
.\target\text_summary.exe
187-
188-
# todo_demo (interactive stdin commands)
189-
cd todo_demo
190-
..\..\target\release\ion-build.exe build
191-
.\target\todo_demo.exe
171+
.\target\spawn_channel.exe
192172
```
193173

194174
On Linux or macOS, use `./target/release/ion-build` and drop `.exe`. Windows channel/spawn builds add `-lws2_32` automatically.
195175

196-
| File | Manifest | What it demonstrates |
197-
|------|----------|---------------------|
198-
| [examples/hello_world.ion](examples/hello_world.ion) | (use `ion-compiler` only; no stdlib) | Minimal FFI `write()` to stdout |
199-
| [examples/hello_world_safe.ion](examples/hello_world_safe.ion) | [hello_world_safe.toml](examples/hello_world_safe.toml) or root [ion.toml](ion.toml) | stdlib `io` module |
200-
| [examples/spawn_channel.ion](examples/spawn_channel.ion) | [spawn_channel.toml](examples/spawn_channel.toml) | `spawn` with cross-thread channels |
201-
| [examples/http_server.ion](examples/http_server.ion) | [http_server.toml](examples/http_server.toml) | Sockets, FFI, spawn per client (single accept, then exit) |
202-
| [examples/showcase.ion](examples/showcase.ion) | [showcase.toml](examples/showcase.toml) | Mixed language features |
203-
| [examples/access_log.ion](examples/access_log.ion) | [access_log.toml](examples/access_log.toml) | Log parsing, spawn, channels, fmt/io |
204-
| [examples/minimal.ion](examples/minimal.ion) | (transpile-only with `ion-compiler`) | Smallest valid program |
205-
| [examples/channel_worker.ion](examples/channel_worker.ion) | [channel_worker.toml](examples/channel_worker.toml) | Channel worker |
206-
| [examples/text_summary/text_summary.ion](examples/text_summary/text_summary.ion) | [text_summary/ion.toml](examples/text_summary/ion.toml) | `fs` read, string iteration, counts |
207-
| [examples/todo_demo/todo_demo.ion](examples/todo_demo/todo_demo.ion) | [todo_demo/ion.toml](examples/todo_demo/ion.toml) | Interactive todo list: `Vec` of structs with `String`, stdin via FFI `read`; see [todo_demo/README.md](examples/todo_demo/README.md) |
208-
| [examples/data_lib/main.ion](examples/data_lib/main.ion) | [data_lib/ion.toml](examples/data_lib/ion.toml) | Multi-module library; see [data_lib/README.md](examples/data_lib/README.md) |
209-
210-
`examples/data_lib/` and `examples/todo_demo/` keep `.ion` sources and manifests only; `ion-build` writes under each project's `target/` (not committed).
176+
| Directory | What it demonstrates |
177+
|-----------|---------------------|
178+
| [hello_world/](examples/hello_world/) | Minimal FFI `write()` to stdout (no stdlib) |
179+
| [hello_world_safe/](examples/hello_world_safe/) | stdlib `io` module; also built by root [ion.toml](ion.toml) |
180+
| [minimal/](examples/minimal/) | Smallest valid program |
181+
| [spawn_channel/](examples/spawn_channel/) | `spawn` with cross-thread channels |
182+
| [channel_worker/](examples/channel_worker/) | Channel worker |
183+
| [showcase/](examples/showcase/) | Mixed language features |
184+
| [access_log/](examples/access_log/) | Log parsing, spawn, channels, fmt/io |
185+
| [http_server/](examples/http_server/) | Sockets FFI, spawn per client, stdin `quit` to stop; see [http_server/README.md](examples/http_server/README.md) |
186+
| [text_summary/](examples/text_summary/) | `fs` read, string iteration, counts |
187+
| [todo_demo/](examples/todo_demo/) | Interactive todo list (`Vec` of structs, stdin); see [todo_demo/README.md](examples/todo_demo/README.md) |
188+
| [data_lib/](examples/data_lib/) | Multi-module library; see [data_lib/README.md](examples/data_lib/README.md) |
211189

212190
## Project Structure
213191

0 commit comments

Comments
 (0)