optionals
This commit is contained in:
116
specs.md
116
specs.md
@@ -429,7 +429,7 @@ set_x :: (p: *Vec2, val: f32) {
|
||||
set_x(@v, 99.0);
|
||||
```
|
||||
|
||||
**Null**: All pointer types are nullable. `null` is the null pointer literal.
|
||||
**Null**: Pointer types are currently nullable by default. `null` is the null pointer literal.
|
||||
```sx
|
||||
np : *Vec2 = null;
|
||||
```
|
||||
@@ -451,6 +451,120 @@ val := mp[2]; // 30
|
||||
|
||||
**Fat pointer layout**: `[:0]u8`, `string`, and `[]T` are `{ptr, i64}` structs. The raw pointer is always the first field at offset 0. This means `*[:0]u8` works as C's `char**` — a C function dereferences through the outer pointer and reads the raw `char*` from offset 0.
|
||||
|
||||
### Optional Types
|
||||
|
||||
Optional types represent values that may or may not be present.
|
||||
|
||||
#### Type Syntax
|
||||
```sx
|
||||
x: ?s32 = 42; // optional s32, has value
|
||||
y: ?s32 = null; // optional s32, no value
|
||||
```
|
||||
|
||||
Any type `T` can be made optional: `?s32`, `?string`, `?Point`, `?*T`, `?[]T`.
|
||||
|
||||
#### LLVM Representation
|
||||
- Non-pointer optionals (`?s32`, `?Point`): `{ T, i1 }` struct — payload + has_value flag
|
||||
- Pointer optionals (`?*T`): bare pointer — null represents absence
|
||||
|
||||
#### Implicit Wrapping
|
||||
A value of type `T` implicitly converts to `?T`:
|
||||
```sx
|
||||
wrap :: (n: s32) -> ?s32 {
|
||||
if n > 0 { return n; } // s32 → ?s32 (wraps)
|
||||
return null; // null → ?s32
|
||||
}
|
||||
```
|
||||
|
||||
#### Force Unwrap (`!`)
|
||||
Extracts the payload, traps at runtime if null:
|
||||
```sx
|
||||
x: ?s32 = 42;
|
||||
val := x!; // val : s32 = 42
|
||||
```
|
||||
|
||||
#### Null Coalescing (`??`)
|
||||
Returns the payload if present, otherwise evaluates the right-hand side:
|
||||
```sx
|
||||
x: ?s32 = 42;
|
||||
y: ?s32 = null;
|
||||
a := x ?? 0; // 42
|
||||
b := y ?? 99; // 99
|
||||
```
|
||||
|
||||
#### Safe Unwrap (`if val := expr`)
|
||||
Binds the payload to a variable if present:
|
||||
```sx
|
||||
x: ?s32 = 42;
|
||||
if val := x {
|
||||
print("{}\n", val); // val : s32 = 42
|
||||
} else {
|
||||
print("none\n");
|
||||
}
|
||||
```
|
||||
|
||||
#### While-Optional Binding
|
||||
```sx
|
||||
while val := get_next() {
|
||||
// val is the unwrapped value
|
||||
}
|
||||
```
|
||||
|
||||
#### Pattern Matching
|
||||
Optionals support `.some` and `.none` virtual enum variants:
|
||||
```sx
|
||||
result := if opt == {
|
||||
case .some: (val) { val * 2; }
|
||||
case .none: { 0; }
|
||||
};
|
||||
```
|
||||
|
||||
#### Optional Chaining (`?.`)
|
||||
Short-circuits field access on optionals:
|
||||
```sx
|
||||
x: ?Point = Point.{ x = 1, y = 2 };
|
||||
y: ?Point = null;
|
||||
a := x?.x ?? 0; // 1
|
||||
b := y?.x ?? 0; // 0
|
||||
```
|
||||
|
||||
Result type of `x?.field` is always `?FieldType`.
|
||||
|
||||
#### Flow-Sensitive Narrowing
|
||||
The compiler narrows `?T` to `T` in control flow branches:
|
||||
```sx
|
||||
x: ?s32 = 42;
|
||||
if x != null {
|
||||
print("{}\n", x); // x is s32 here (narrowed)
|
||||
}
|
||||
if x == null { return; }
|
||||
print("{}\n", x); // x is s32 here (guard narrowing)
|
||||
```
|
||||
|
||||
Compound conditions:
|
||||
```sx
|
||||
if a != null and b != null {
|
||||
// both a and b are narrowed to their inner types
|
||||
}
|
||||
if a == null or b == null { return; }
|
||||
// both a and b are narrowed after the guard
|
||||
```
|
||||
|
||||
Reassignment kills narrowing.
|
||||
|
||||
#### Struct Field Defaults
|
||||
Optional fields in structs default to `null`:
|
||||
```sx
|
||||
Node :: struct { value: s32; next: ?s32; }
|
||||
n := Node.{ value = 10 }; // n.next is null
|
||||
```
|
||||
|
||||
#### Printing
|
||||
`print("{}", opt)` prints the payload value if present, or `"null"`.
|
||||
|
||||
#### Comptime
|
||||
Optionals work in `#run` blocks — `??`, `!`, `if val :=`, null checks all supported.
|
||||
|
||||
### Foreign Function Interface (C Interop)
|
||||
|
||||
To call C functions, declare a library constant with `#library` and bind functions with `#foreign`:
|
||||
|
||||
Reference in New Issue
Block a user