Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions LANGUAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ Anonymous structs with named fields:
user = { name = "Alice", age = 30 }
n = user.name
```
(See `examples/records.ql`.)
Fields may hold any type — `Text`, arrays, nested arrays, etc. — and read back at
their real type (no numeric-only restriction). (See `examples/records.ql` and
`examples/composites.ql`, which exercises a `Text` record field, an array of `Text`,
and a nested array together.)

### Named record types with methods
Methods take an implicit `it` (the receiver):
Expand Down Expand Up @@ -142,8 +145,8 @@ classify = v => v ?
| Ok(x) => x * 2
| NotOk(e) => 0
```
Numeric payloads work end-to-end. (See `examples/result.ql`. Non-numeric payloads in
some positions: see [Known limitations](#known-limitations).)
Payloads work end-to-end for `Num`, `Bool`, and `Text` (e.g. `Ok("done")` /
`NotOk("error")`). (See `examples/result.ql` and `examples/composites.ql`.)

#### `/` — sum-type separator vs. division
`/` is the division operator **and** the sum-type variant separator. They are told apart
Expand Down Expand Up @@ -498,11 +501,11 @@ message instead. Any compile error exits with status 1.
| Pattern matching (numbers, wildcard, identifiers, sum-type variants) | ✅ |
| User-defined sum types (`/` separator), exhaustive matching, payload binding | ✅ |
| `Result` as a normal predefined sum type (`Ok`/`NotOk`) | ✅ |
| Sum-type payloads: `Num` / `Bool` (and `Text`, see limitations) | ✅ |
| Sum-type payloads: `Num` / `Bool` / `Text` | ✅ |
| Modules: `<< core.io`, file-path imports, `>>` exports | ✅ |
| I/O: `print` / `eprint` / `write` | ✅ |
| Conservative GC (Boehm) | ✅ |
| `Text` in records/arrays, or as a sum-type payload (`Ok(text)`) | 🚧 |
| `Text` (and nested arrays) in records/arrays, or as a sum-type payload (`Ok(text)`) | |
| Command-line `argv` (argc works; argv is a placeholder) | 🚧 |
| Generics / type variables (overloading is the only polymorphism), closures, `while` loops | ❌ |
| Overloaded name passed as a value (higher-order); only direct call sites resolve | ❌ |
Expand All @@ -514,7 +517,7 @@ message instead. Any compile error exits with status 1.

0.9 is a stable **core**, not the whole language. Notably:

- **Non-numeric data in composites isn't sound yet.** `Text` inside a record or an array, and non-numeric sum-type payloads such as `Ok("x")` / `NotOk("error")`, do not type-check correctly in 0.9 — numeric payloads and numeric records/arrays work. Planned for a later release. A corollary for [overloading](#overloading): a `Result` payload is generic, so binding it (`Ok(x) => …`) and passing it to an [overload set](#overloading) resolves to the **`Num`** member (numeric payloads work end-to-end); a non-numeric `Result` payload (`Ok("x")`) routed through an overload is part of this same non-numeric-payload gap. A **user** sum type's payloads are concrete (`Circle(Num)`, `On(Bool)`), so they dispatch overloads correctly by their declared type.
- **A generic `Result` payload routed through an overload set resolves to the `Num` member.** `Text`/array fields and `Ok("x")`/`NotOk("e")` payloads now type-check and round-trip end-to-end (see [records](#records), [`Result`](#result-is-a-normal-sum-type)). But a `Result` payload is *generic*, so binding it (`Ok(x) => …`) and passing `x` to an [overload set](#overloading) still resolves to the **`Num`** member; a user sum type's payloads are concrete (`Circle(Num)`, `On(Bool)`), so they dispatch overloads correctly by their declared type.
- **Array `.size` works only on a named receiver** (`xs.size`), not on a literal/expression (`[1,2,3].size`).
- **No generics, closures, or `while` loops.** Overloading (ad-hoc, exact-type
dispatch) is the only polymorphism; there are no type variables. The module system is
Expand Down
19 changes: 19 additions & 0 deletions examples/composites.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
~ Text and other non-numeric values nested inside composites round-trip correctly:
~ a `Text` field of a record, an array of `Text`, and a nested array all read back
~ with their real type (no f64 corruption). Codegen recovers each element/field type
~ from the type oracle rather than assuming `Num`.
^ = () -> Num => <
~ Record with a Text field: read it back, count its graphemes.
user = { name = "Quilon", n = 7 }
nameLen = user.name.length ~ "Quilon" -> 6

~ Array of Text: index it, then take the byte length of the element.
words = ["a", "cde"]
wordLen = words[1].size ~ "cde" -> 3

~ Nested array (array of arrays): double-index it.
grid = [[1, 2], [3, 4]]
cell = grid[1][0] ~ 3

nameLen + wordLen + cell ~ exit 6 + 3 + 3 = 12
>
3 changes: 1 addition & 2 deletions examples/records.ql
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
~ Records are anonymous structs with named fields; access fields with `.`.
~ (Fields are numeric here — Text/array fields inside composites await richer
~ payload support; see LANGUAGE.md "Known limitations".)
~ (Fields can hold any type — Text, arrays, etc.; see examples/composites.ql.)
^ = () -> Num => <
rect = { width = 4, height = 7 }
rect.width * rect.height ~ exit 28
Expand Down
4 changes: 2 additions & 2 deletions examples/result.ql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
~ The built-in `Result` sum type: `Ok(value)` for success, `NotOk(error)` for
~ failure. Pattern-match to extract the payload. (Numeric payloads; richer payload
~ types await generics — see LANGUAGE.md.)
~ failure. Pattern-match to extract the payload. Payloads may be Num, Bool, or Text
~ (e.g. `Ok("done")`); see examples/composites.ql and LANGUAGE.md.
^ = () -> Num => <
outcome = Ok(42)
outcome ?
Expand Down
3 changes: 2 additions & 1 deletion src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ fn emit_object(program: &Program, obj_path: &Path) -> Result<(), String> {
.map_err(|e| format!("Failed to initialize native target: {e}"))?;

let context = Context::create();
let mut generator = CodeGenerator::new(&context, "main");
// Build the generator with the type oracle installed (precise composite read types).
let mut generator = CodeGenerator::with_oracle(&context, "main", program)?;
// Populates, verifies, and builds the C `main` wrapper around `^`.
generator.generate(program)?;
let module = generator.module();
Expand Down
Loading