mutable decl syntax change
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
- unsigned integers, floats, and target-dependent c scalar types
|
||||
- atomic `c_*` primitive types remain distinct until target-aware lowering
|
||||
- `c_func`, complete `c_struct`, and pointer-only `opaque`; `c` remains an ordinary identifier
|
||||
- keep binding mutability (`::` / `=`) separate from element or pointee mutability (`mut`)
|
||||
- keep binding mutability (`::` / `:=`) separate from element or pointee mutability (`mut`)
|
||||
- arrays and indexing
|
||||
- `[N]T`: array with `N` logical elements
|
||||
- `[N;S]T`: array with `N` logical elements followed by sentinel `S`
|
||||
@@ -184,7 +184,7 @@
|
||||
- undefined values are assigned a poison value (0xaa...)
|
||||
- allows for something like:
|
||||
```
|
||||
a int = undefined
|
||||
a int := undefined
|
||||
if (condition) {
|
||||
a = 42
|
||||
} else {
|
||||
@@ -323,7 +323,7 @@
|
||||
- a `{ ... }` on the right of a declaration or assignment is a *value block*: its final
|
||||
statement must be `yield <expr>`, which supplies the block's value (the block analogue
|
||||
of `return`). Supported: `x :: { ...; yield v }` (untyped — the local takes the yield's
|
||||
natural type), `x T = { ... }` (coerces to `T`), and `target = { ... }` (coerces to the
|
||||
natural type), `x T := { ... }` (coerces to `T`), and `target = { ... }` (coerces to the
|
||||
target's type, including complex targets like `a[i] = { ... }`)
|
||||
- the yielded value is captured *before* the block's defers run (a defer that mutates a
|
||||
block local can't change what is yielded), reusing the `return` spill-to-temp pattern
|
||||
@@ -695,9 +695,9 @@
|
||||
27.8 source-defined mutable runtime globals (implemented)
|
||||
- allow mutable global declarations in Brolang source for process-global runtime
|
||||
state, matching the writable-global support already needed for imported C globals
|
||||
- require source type syntax and an initializer; constraints (`int`/`float`/`range`)
|
||||
and inferred array counts may resolve through the existing inference fixpoint, but
|
||||
the final type must be concrete runtime storage
|
||||
- require an initializer and infer or explicitly declare a concrete runtime storage type;
|
||||
constraints (`int`/`float`/`range`) and inferred array counts resolve through the existing
|
||||
inference fixpoint
|
||||
- emit source-defined mutable globals as writable globals, not constants
|
||||
- allow `undefined` initializers for runtime storage initialized explicitly by a function
|
||||
- allow assignment, address-taking, field/index mutation, and pointer passing under
|
||||
@@ -774,7 +774,7 @@
|
||||
improving layout or specialization
|
||||
- the smallest fitting feature is call-local inference of omitted comptime type arguments:
|
||||
```
|
||||
values ArrayList(i32) = arraylist.init(mem.c_allocator)
|
||||
values ArrayList(i32) := arraylist.init(mem.c_allocator)
|
||||
defer arraylist.deinit(&values)
|
||||
try arraylist.append(&values, 42)
|
||||
```
|
||||
@@ -988,9 +988,9 @@ f: f32 = 3.14
|
||||
bits := bitcast(f, u32) # IEEE 754 representation
|
||||
|
||||
# pointer casts
|
||||
buf *u8 = get_buffer()
|
||||
ints *u32 = ptrcast!(u32, buf) # element type change, same pointer shape
|
||||
writable *mut u8 = constcast!(buf) # explicit unsafe mutability restoration
|
||||
buf *u8 := get_buffer()
|
||||
ints *u32 := ptrcast!(u32, buf) # element type change, same pointer shape
|
||||
writable *mut u8 := constcast!(buf) # explicit unsafe mutability restoration
|
||||
```
|
||||
|
||||
## A word on multi-unwrap
|
||||
@@ -1069,8 +1069,7 @@ layer:
|
||||
```bro
|
||||
UserID :: distinct u32
|
||||
OuterID :: distinct UserID
|
||||
|
||||
index usize = 42
|
||||
index usize := 42
|
||||
id UserID :: UserID(index)
|
||||
raw u32 :: u32(id)
|
||||
outer OuterID :: OuterID(id)
|
||||
@@ -1222,7 +1221,7 @@ data :: {
|
||||
}
|
||||
|
||||
# match arms
|
||||
label []u8 = match p {
|
||||
label []u8 := match p {
|
||||
.high: "HIGH", # single expression: implicit yield
|
||||
.low: {
|
||||
log("low priority")
|
||||
@@ -1231,7 +1230,7 @@ label []u8 = match p {
|
||||
}
|
||||
|
||||
# catch handlers (planned; block form deferred in milestone 23 v1)
|
||||
data []u8 = read(path) catch |e| {
|
||||
data []u8 := read(path) catch |e| {
|
||||
log(e)
|
||||
yield fallback_data # block: explicit yield
|
||||
}
|
||||
@@ -1252,7 +1251,7 @@ result :: if a {
|
||||
}
|
||||
|
||||
# yielding to a variable
|
||||
result int = if a {
|
||||
result int := if a {
|
||||
yield 1
|
||||
} else if b {
|
||||
yield 2
|
||||
@@ -1482,7 +1481,7 @@ Fallible functions use ordinary `return` for both channels. If the returned expr
|
||||
|
||||
```
|
||||
parse_section func(p: @mut Parser) void ! ParseError {
|
||||
start_line Line = p.line
|
||||
start_line Line := p.line
|
||||
p.advance()
|
||||
|
||||
# ... parsing logic ...
|
||||
@@ -1497,7 +1496,7 @@ Since errors are just union values, you can also construct them separately:
|
||||
|
||||
```
|
||||
# Construct error value (it's just a union)
|
||||
e ParseError = .timeout{500}
|
||||
e ParseError := .timeout{500}
|
||||
|
||||
# Return it via error channel later
|
||||
return e
|
||||
@@ -1647,7 +1646,7 @@ Brolang provides a libc-backed allocator value:
|
||||
mem :: import "@std/mem"
|
||||
|
||||
process func(input []u8) u64 {
|
||||
temp ?*mut u8 = mem.alloc(mem.c_allocator, input.len * 2, 1)
|
||||
temp ?*mut u8 := mem.alloc(mem.c_allocator, input.len * 2, 1)
|
||||
defer mem.free(mem.c_allocator, temp, input.len * 2, 1)
|
||||
|
||||
# ... work with temp ...
|
||||
@@ -1677,7 +1676,7 @@ mem :: import "@std/mem"
|
||||
|
||||
# Allocation escapes via return value — requires allocator
|
||||
duplicate func(input []u8, allocator mem.Allocator) ?*mut u8 {
|
||||
result ?*mut u8 = mem.alloc(allocator, input.len, 1)
|
||||
result ?*mut u8 := mem.alloc(allocator, input.len, 1)
|
||||
mem.copy(result, input)
|
||||
return result # caller manages this memory
|
||||
}
|
||||
@@ -1690,7 +1689,7 @@ init func(obj @mut MyStruct, allocator mem.Allocator) void {
|
||||
|
||||
# No allocation escapes — no allocator needed
|
||||
process func(input []u8) u64 {
|
||||
temp ?*mut u8 = mem.alloc(mem.c_allocator, input.len, 1)
|
||||
temp ?*mut u8 := mem.alloc(mem.c_allocator, input.len, 1)
|
||||
defer mem.free(mem.c_allocator, temp, input.len, 1)
|
||||
# ... work with temp ...
|
||||
return compute_hash(temp)
|
||||
|
||||
Reference in New Issue
Block a user