Skip to content

Commit 32fdcc3

Browse files
Create roadmap and README documentation (#12)
Expand README.adoc with full project documentation including: - Language feature overview with code examples - Implementation status table - Build instructions and repository structure - Design philosophy Add ROADMAP.adoc outlining 8-phase development plan from current frontend-complete state through code generation and tooling. Co-authored-by: Claude <noreply@anthropic.com>
1 parent caf1b4a commit 32fdcc3

File tree

2 files changed

+559
-11
lines changed

2 files changed

+559
-11
lines changed

README.adoc

Lines changed: 283 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,292 @@
11
= AffineScript
2-
:toc: auto
2+
:toc: macro
3+
:toclevels: 3
4+
:icons: font
5+
:source-highlighter: rouge
36

4-
AffineScript is a programming language combining affine types, dependent types, row polymorphism, and effects.
7+
A Rust-inspired programming language combining affine types, dependent types, row polymorphism, and extensible effects—compiling to WebAssembly with no garbage collector.
58

6-
== Features
9+
[.lead]
10+
AffineScript brings the safety of linear types, the expressiveness of dependent types, and the modularity of algebraic effects into a cohesive, practical language.
711

8-
* Affine type system
9-
* Dependent types
10-
* Row polymorphism
11-
* Effect system
12-
* Compiles to WebAssembly
12+
toc::[]
1313

14-
== Built With
14+
== Overview
1515

16-
* OCaml compiler infrastructure
16+
AffineScript is designed for systems programming where correctness matters. It combines ideas from:
17+
18+
* **Rust** — ownership, borrowing, no GC
19+
* **Idris/Agda** — dependent types, totality checking
20+
* **PureScript/Koka** — row polymorphism, algebraic effects
21+
* **Linear Haskell** — quantitative type theory
22+
23+
=== Key Features
24+
25+
[cols="1,2"]
26+
|===
27+
|Feature |Description
28+
29+
|**Affine Types**
30+
|Track resource usage with quantities: `0` (erased), `1` (linear), `ω` (unrestricted)
31+
32+
|**Dependent Types**
33+
|Types that depend on values—length-indexed vectors, refinement types
34+
35+
|**Row Polymorphism**
36+
|Extensible records with `{x: Int, ..r}` syntax for flexible data structures
37+
38+
|**Extensible Effects**
39+
|User-defined effects with `effect` declarations and `handle`/`resume`
40+
41+
|**Ownership**
42+
|`own`, `ref`, `mut` modifiers for memory safety without GC
43+
44+
|**Totality Checking**
45+
|Mark functions as `total` to prove termination
46+
47+
|**WebAssembly Target**
48+
|Compiles to WASM for portable, high-performance execution
49+
|===
50+
51+
== Language Examples
52+
53+
=== Hello World with Effects
54+
55+
[source,affinescript]
56+
----
57+
effect IO {
58+
fn print(s: String);
59+
fn println(s: String);
60+
}
61+
62+
fn main() -> () / IO {
63+
println("Hello, AffineScript!");
64+
}
65+
----
66+
67+
=== Ownership and Resource Safety
68+
69+
[source,affinescript]
70+
----
71+
type File = own { fd: Int }
72+
73+
fn open(path: ref String) -> Result[own File, IOError] / IO + Exn[IOError] {
74+
Ok(File { fd: 42 })
75+
}
76+
77+
fn read(file: ref File) -> Result[String, IOError] / IO {
78+
// Borrows file — doesn't consume it
79+
Ok("file contents")
80+
}
81+
82+
fn close(file: own File) -> Result[(), IOError] / IO {
83+
// Consumes file — can't use it after this
84+
Ok(())
85+
}
86+
87+
// Safe resource handling with RAII pattern
88+
fn withFile[T](
89+
path: ref String,
90+
action: (ref File) -> Result[T, IOError] / IO
91+
) -> Result[T, IOError] / IO {
92+
let file = open(path)?;
93+
let result = action(ref file);
94+
close(file)?;
95+
result
96+
}
97+
----
98+
99+
=== Row Polymorphism
100+
101+
[source,affinescript]
102+
----
103+
// Works on any record that has a 'name' field
104+
fn greet[..r](person: {name: String, ..r}) -> String / Pure {
105+
"Hello, " ++ person.name
106+
}
107+
108+
// Extend records while preserving other fields
109+
fn fullName[..r](
110+
person: {first: String, last: String, ..r}
111+
) -> {first: String, last: String, fullName: String, ..r} / Pure {
112+
{fullName: person.first ++ " " ++ person.last, ..person}
113+
}
114+
115+
fn main() -> () / Pure {
116+
let alice = {name: "Alice", age: 30, role: "Engineer"};
117+
let bob = {name: "Bob", department: "Sales"};
118+
119+
// Both work despite different record shapes
120+
let greeting1 = greet(alice); // ✓
121+
let greeting2 = greet(bob); // ✓
122+
}
123+
----
124+
125+
=== Dependent Types: Length-Indexed Vectors
126+
127+
[source,affinescript]
128+
----
129+
type Vec[n: Nat, T: Type] =
130+
| Nil : Vec[0, T]
131+
| Cons(head: T, tail: Vec[n, T]) : Vec[n + 1, T]
132+
133+
// Can only be called on non-empty vectors — enforced by types!
134+
total fn head[n: Nat, T](v: Vec[n + 1, T]) -> T / Pure {
135+
match v {
136+
Cons(h, _) => h
137+
}
138+
}
139+
140+
// Concatenate: result length is sum of input lengths
141+
total fn append[n: Nat, m: Nat, T](
142+
a: Vec[n, T],
143+
b: Vec[m, T]
144+
) -> Vec[n + m, T] / Pure {
145+
match a {
146+
Nil => b,
147+
Cons(h, t) => Cons(h, append(t, b))
148+
}
149+
}
150+
----
151+
152+
== Project Status
153+
154+
=== Implementation Progress
155+
156+
[cols="2,1,3"]
157+
|===
158+
|Component |Status |Details
159+
160+
|**Lexer**
161+
|✅ Complete
162+
|sedlex-based, Unicode support, full test coverage
163+
164+
|**Parser Grammar**
165+
|✅ Complete
166+
|615-line Menhir grammar covering entire syntax
167+
168+
|**Abstract Syntax Tree**
169+
|✅ Complete
170+
|395 lines representing all language constructs
171+
172+
|**Error Handling**
173+
|✅ Complete
174+
|Rich diagnostics with 50+ error codes, colored output
175+
176+
|**CLI Interface**
177+
|✅ Complete
178+
|`lex`, `parse`, `check`, `compile` commands
179+
180+
|**Name Resolution**
181+
|🔲 Planned
182+
|Scope analysis, module resolution
183+
184+
|**Type Checker**
185+
|🔲 Planned
186+
|Bidirectional inference, constraint solving
187+
188+
|**Borrow Checker**
189+
|🔲 Planned
190+
|Non-lexical lifetimes, linearity enforcement
191+
192+
|**Code Generation**
193+
|🔲 Planned
194+
|WASM backend
195+
|===
196+
197+
=== What Works Today
198+
199+
The compiler frontend is complete. You can:
200+
201+
* **Tokenize** AffineScript source files
202+
* **Parse** to a full abstract syntax tree
203+
* **Pretty-print** ASTs for debugging
204+
205+
[source,bash]
206+
----
207+
# Tokenize a file
208+
dune exec affinescript -- lex examples/hello.as
209+
210+
# Parse and display AST
211+
dune exec affinescript -- parse examples/ownership.as
212+
----
213+
214+
== Building
215+
216+
=== Prerequisites
217+
218+
* OCaml 5.1+
219+
* Dune 3.0+
220+
* opam packages: `sedlex`, `menhir`, `ppx_deriving`, `cmdliner`, `alcotest`
221+
222+
=== Commands
223+
224+
[source,bash]
225+
----
226+
# Build
227+
dune build
228+
229+
# Run tests
230+
dune runtest
231+
232+
# Format code
233+
dune fmt
234+
235+
# Generate documentation
236+
dune build @doc
237+
238+
# Run compiler
239+
dune exec affinescript -- <command> <file>
240+
----
241+
242+
== Repository Structure
243+
244+
[source]
245+
----
246+
affinescript/
247+
├── lib/ # Core compiler library
248+
│ ├── ast.ml # Abstract syntax tree (395 lines)
249+
│ ├── token.ml # Token definitions (222 lines)
250+
│ ├── lexer.ml # Lexer — sedlex-based (323 lines)
251+
│ ├── parser.mly # Parser — Menhir grammar (615 lines)
252+
│ ├── parse.ml # Parser driver
253+
│ ├── span.ml # Source location tracking
254+
│ └── error.ml # Diagnostics and error handling
255+
├── bin/ # CLI executable
256+
│ └── main.ml # Command-line interface
257+
├── test/ # Test suite
258+
│ ├── test_lexer.ml # Lexer tests (~145 cases)
259+
│ └── test_parser.ml # Parser tests (~80 cases)
260+
├── examples/ # Example programs
261+
│ ├── hello.as # Basic IO effect
262+
│ ├── ownership.as # Resource management
263+
│ ├── rows.as # Row polymorphism
264+
│ └── vectors.as # Dependent types
265+
├── docs/ # Documentation
266+
│ └── wiki/ # Compiler & language documentation
267+
└── affinescript-spec.md # Complete language specification (53KB)
268+
----
269+
270+
== Documentation
271+
272+
* `affinescript-spec.md` — Complete language specification
273+
* `docs/wiki/compiler/` — Compiler architecture and phase documentation
274+
* `docs/wiki/language-reference/` — Language feature guides
275+
* `docs/wiki/tutorials/` — Getting started guides
276+
277+
== Design Philosophy
278+
279+
. **Safety by default** — Ownership and effects make unsafe code explicit
280+
. **Types as documentation** — Dependent types encode invariants in the type system
281+
. **Composable abstractions** — Row polymorphism and effects compose cleanly
282+
. **No runtime cost for safety** — Linear types enable compile-time resource management
283+
. **Partial by default** — Functions may diverge unless marked `total`
17284

18285
== License
19286

20-
AGPL-3.0-or-later
287+
SPDX-License-Identifier: AGPL-3.0-or-later
288+
289+
== See Also
290+
291+
* link:ROADMAP.adoc[Development Roadmap]
292+
* link:affinescript-spec.md[Language Specification]

0 commit comments

Comments
 (0)