no :: in func decls

This commit is contained in:
2026-06-30 19:31:26 +02:00
parent ae5af37b85
commit 07c560b750
107 changed files with 580 additions and 520 deletions
+7 -7
View File
@@ -14,7 +14,7 @@ types. C primitives use atomic target-dependent names and remain semantically
distinct from exact-width Brolang primitives: distinct from exact-width Brolang primitives:
```bro ```bro
strlen :: c_func(value *c_char) c_ulong strlen c_func(value *c_char) c_ulong
``` ```
Additional native inputs and libraries are passed to the final `zig cc` Additional native inputs and libraries are passed to the final `zig cc`
@@ -35,7 +35,7 @@ Relative `.h` imports create synthetic package namespaces backed by libclang:
```bro ```bro
native :: import "../include/native.h" native :: import "../include/native.h"
main :: func() void { main func() void {
_ = native.imported_add(20, 22) _ = native.imported_add(20, 22)
} }
``` ```
@@ -63,11 +63,11 @@ from Brolang requires an explicit unwrap:
```bro ```bro
native :: import "../include/native.h" native :: import "../include/native.h"
double :: c_func(value c_int) c_int { double c_func(value c_int) c_int {
return value + value return value + value
} }
call_mapper :: func(mapper native.Imported_Mapper) c_int { call_mapper func(mapper native.Imported_Mapper) c_int {
return mapper?(21) return mapper?(21)
} }
``` ```
@@ -75,16 +75,16 @@ call_mapper :: func(mapper native.Imported_Mapper) c_int {
Bodyless manual and imported C functions may be variadic: Bodyless manual and imported C functions may be variadic:
```bro ```bro
log_values :: c_func(tag c_int, ...) c_int log_values c_func(tag c_int, ...) c_int
``` ```
Zero-terminated byte strings can be passed directly to immutable C character Zero-terminated byte strings can be passed directly to immutable C character
pointers without making `u8` and `c_char` generally interchangeable: pointers without making `u8` and `c_char` generally interchangeable:
```bro ```bro
printf :: c_func(format *c_char, ...) c_int printf c_func(format *c_char, ...) c_int
main :: func() void { main func() void {
_ = printf("answer: %d\n", 42) _ = printf("answer: %d\n", 42)
} }
``` ```
+17 -17
View File
@@ -223,7 +223,7 @@
14.5. backward type-demand propagation through call boundaries (DEFERRED) 14.5. backward type-demand propagation through call boundaries (DEFERRED)
- a callee's result/return demand flows back through the function body to constrain - a callee's result/return demand flows back through the function body to constrain
the caller's arguments, so `R u32 :: echo(A)` (with `echo :: func(p int) int`) the caller's arguments, so `R u32 :: echo(A)` (with `echo func(p int) int`)
resolves A to u32 instead of erroring at the call's result coercion resolves A to u32 instead of erroring at the call's result coercion
- requires reversing the per-call data flow: a specialization's argument types - requires reversing the per-call data flow: a specialization's argument types
(`spec.args`) become outputs to solve, not just inputs — a new back-edge threaded (`spec.args`) become outputs to solve, not just inputs — a new back-edge threaded
@@ -981,7 +981,7 @@ Milestone 23 v1 implements named error channels, native sum composition, `return
Functions that can fail declare their error type after `!`: Functions that can fail declare their error type after `!`:
``` ```
read_file :: func(path []u8) []u8 ! IoError { ... } read_file func(path []u8) []u8 ! IoError { ... }
``` ```
This reads as: "returns `[]u8` or fails with `IoError`." The space around `!` is idiomatic but not required. This reads as: "returns `[]u8` or fails with `IoError`." The space around `!` is idiomatic but not required.
@@ -1035,7 +1035,7 @@ Functions that can fail with multiple error types use `|` to compose a named err
``` ```
ProcessError :: alias IoError | ParseError ProcessError :: alias IoError | ParseError
process :: func(path []u8) Ast ! ProcessError { ... } process func(path []u8) Ast ! ProcessError { ... }
``` ```
Parentheses are optional in the composed type and can aid readability: Parentheses are optional in the composed type and can aid readability:
@@ -1053,7 +1053,7 @@ Inline error types are planned, but not part of milestone 23 v1. Use named enums
Fallible functions use ordinary `return` for both channels. If the returned expression coerces to the success type `T`, the function returns success with channel code `0`. If it coerces to the error type `E`, the function returns the error with that variant's global tag id: Fallible functions use ordinary `return` for both channels. If the returned expression coerces to the success type `T`, the function returns success with channel code `0`. If it coerces to the error type `E`, the function returns the error with that variant's global tag id:
``` ```
parse_section :: func(p: @mut Parser) void ! ParseError { parse_section func(p: @mut Parser) void ! ParseError {
start_line Line = p.line start_line Line = p.line
p.advance() p.advance()
@@ -1086,7 +1086,7 @@ The `try` keyword unwraps a successful result or returns early with the error:
``` ```
ProcessError :: alias IoError | ParseError ProcessError :: alias IoError | ParseError
process :: func(path []u8) Ast ! ProcessError { process func(path []u8) Ast ! ProcessError {
data :: try read_file(path) # read_file also returns []u8 ! ProcessError in v1 data :: try read_file(path) # read_file also returns []u8 ! ProcessError in v1
ast :: try parse(data) # parse also returns Ast ! ProcessError in v1 ast :: try parse(data) # parse also returns Ast ! ProcessError in v1
return ast return ast
@@ -1195,7 +1195,7 @@ Brolang provides a **thread-local global heap allocator** that is:
``` ```
import "std/mem/heap" import "std/mem/heap"
process :: func(input []u8) u64 { process func(input []u8) u64 {
# heap used for internal temporary work — does not escape # heap used for internal temporary work — does not escape
temp := heap.alloc(u8, size: input.len * 2) temp := heap.alloc(u8, size: input.len * 2)
defer heap.free(temp) defer heap.free(temp)
@@ -1227,20 +1227,20 @@ import "std/mem"
import "std/mem/heap" import "std/mem/heap"
# Allocation escapes via return value — requires allocator # Allocation escapes via return value — requires allocator
duplicate :: func(input []u8, allocator @mem.Allocator) []u8 { duplicate func(input []u8, allocator @mem.Allocator) []u8 {
result := allocator.alloc(u8, size: input.len) result := allocator.alloc(u8, size: input.len)
mem.copy(result, input) mem.copy(result, input)
return result # caller manages this memory return result # caller manages this memory
} }
# Allocation escapes via mutable parameter — requires allocator # Allocation escapes via mutable parameter — requires allocator
init :: func(obj: @mut MyStruct, allocator: @mem.Allocator) void { init func(obj: @mut MyStruct, allocator: @mem.Allocator) void {
obj.buffer = allocator.alloc(u8, size: 100) obj.buffer = allocator.alloc(u8, size: 100)
# caller now knows heap memory was written into obj # caller now knows heap memory was written into obj
} }
# No allocation escapes — no allocator needed # No allocation escapes — no allocator needed
process :: func(input: []u8) u64 { process func(input: []u8) u64 {
temp := heap.alloc(u8, size: input.len) temp := heap.alloc(u8, size: input.len)
defer heap.free(temp) defer heap.free(temp)
# ... work with temp ... # ... work with temp ...
@@ -1248,11 +1248,11 @@ process :: func(input: []u8) u64 {
} }
# No heap allocation at all — no allocator needed # No heap allocation at all — no allocator needed
reset :: func(obj: @mut MyStruct) void { reset func(obj: @mut MyStruct) void {
obj.count = 0 obj.count = 0
} }
main :: func() void { main func() void {
data := duplicate("hello", heap) data := duplicate("hello", heap)
defer heap.free(data) defer heap.free(data)
@@ -1302,7 +1302,7 @@ For specialized needs, you create explicit allocator instances. These are not gl
import "std/mem" import "std/mem"
import "std/mem/heap" import "std/mem/heap"
process_file :: func(path: []u8, allocator: @mem.Allocator) !Data { process_file func(path: []u8, allocator: @mem.Allocator) !Data {
# arena manages its own backing memory via heap # arena manages its own backing memory via heap
arena := mem.Arena.init(heap, capacity: mem.megabytes(1)) arena := mem.Arena.init(heap, capacity: mem.megabytes(1))
defer arena.deinit() defer arena.deinit()
@@ -1333,17 +1333,17 @@ EntitySystem :: struct {
pool: mem.Pool(Entity), pool: mem.Pool(Entity),
} }
init_entities :: func(allocator: @mem.Allocator) EntitySystem { init_entities func(allocator: @mem.Allocator) EntitySystem {
return EntitySystem{ return EntitySystem{
pool = mem.Pool(Entity).init(allocator, capacity: 10_000), pool = mem.Pool(Entity).init(allocator, capacity: 10_000),
} }
} }
spawn :: func(sys: @mut EntitySystem) @Entity { spawn func(sys: @mut EntitySystem) @Entity {
return sys.pool.alloc() # O(1), no fragmentation return sys.pool.alloc() # O(1), no fragmentation
} }
despawn :: func(sys: @mut EntitySystem, entity: @Entity) void { despawn func(sys: @mut EntitySystem, entity: @Entity) void {
sys.pool.free(entity) # returned to pool for reuse sys.pool.free(entity) # returned to pool for reuse
} }
``` ```
@@ -1356,7 +1356,7 @@ As described in the escaping allocation rule, when a function heap-allocates mem
import "std/mem" import "std/mem"
# Function that uses caller's allocator # Function that uses caller's allocator
parse :: func(input: []u8, allocator: @mem.Allocator) !ParseResult { parse func(input: []u8, allocator: @mem.Allocator) !ParseResult {
buffer := allocator.alloc(u8, size: input.len) buffer := allocator.alloc(u8, size: input.len)
defer allocator.free(buffer) defer allocator.free(buffer)
@@ -1367,7 +1367,7 @@ parse :: func(input: []u8, allocator: @mem.Allocator) !ParseResult {
} }
# Caller decides which allocator to use # Caller decides which allocator to use
main :: func() void { main func() void {
# use an arena for this parsing work # use an arena for this parsing work
arena := mem.Arena.init(heap, capacity: mem.kilobytes(64)) arena := mem.Arena.init(heap, capacity: mem.kilobytes(64))
defer arena.deinit() defer arena.deinit()
+2 -2
View File
@@ -24,8 +24,8 @@ Metrics :: struct {
make_source :: proc(repetitions: int, allocator := context.allocator) -> string { make_source :: proc(repetitions: int, allocator := context.allocator) -> string {
builder := strings.builder_make(allocator) builder := strings.builder_make(allocator)
defer strings.builder_destroy(&builder) defer strings.builder_destroy(&builder)
strings.write_string(&builder, "identity :: func(value int) int { return value }\n") strings.write_string(&builder, "identity func(value int) int { return value }\n")
strings.write_string(&builder, "main :: func() i32 {\n\tacc i32 = 0\n") strings.write_string(&builder, "main func() i32 {\n\tacc i32 = 0\n")
for _ in 0 ..< repetitions { for _ in 0 ..< repetitions {
strings.write_string(&builder, "\t_ = identity(acc)\n\tacc = acc + 1\n") strings.write_string(&builder, "\t_ = identity(acc)\n\tacc = acc + 1\n")
} }
+7
View File
@@ -2256,6 +2256,11 @@ parse_top_level :: proc(parser: ^Parser) {
} }
parser.cursor = saved parser.cursor = saved
} }
if current(parser).kind == .Keyword_Func || current(parser).kind == .Keyword_C_Func {
c_abi := current(parser).kind == .Keyword_C_Func
parse_function(parser, name, c_abi)
return
}
type_syntax := types.INVALID type_syntax := types.INVALID
if is_type_token(current(parser).kind) { if is_type_token(current(parser).kind) {
type_syntax = parse_type(parser) type_syntax = parse_type(parser)
@@ -2271,6 +2276,8 @@ parse_top_level :: proc(parser: ^Parser) {
if operator.kind == .Colon_Colon && if operator.kind == .Colon_Colon &&
(current(parser).kind == .Keyword_Func || current(parser).kind == .Keyword_C_Func) { (current(parser).kind == .Keyword_Func || current(parser).kind == .Keyword_C_Func) {
source.add(parser.diagnostics, span_from(name.span, current(parser).span),
"function declarations do not use '::'; write 'name func(...)' or 'name c_func(...)'")
c_abi := current(parser).kind == .Keyword_C_Func c_abi := current(parser).kind == .Keyword_C_Func
parse_function(parser, name, c_abi) parse_function(parser, name, c_abi)
return return
+1 -1
View File
@@ -279,7 +279,7 @@ emit_functions :: proc(b: ^strings.Builder, result: ^cimport.Result, record_name
wrote = true wrote = true
continue continue
} }
fmt.sbprintf(b, "%s :: ", function.name) fmt.sbprintf(b, "%s ", function.name)
render_c_func(b, result, function.params, function.param_names, function.result, function.variadic, record_names) render_c_func(b, result, function.params, function.param_names, function.result, function.variadic, record_names)
strings.write_byte(b, '\n') strings.write_byte(b, '\n')
wrote = true wrote = true
+365 -312
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -3,8 +3,8 @@ Buffer :: c_struct {
length c_ulong length c_ulong
} }
get_buffer :: c_func() @Buffer get_buffer c_func() @Buffer
verify :: c_func( verify c_func(
char_value c_char, char_value c_char,
schar_value c_schar, schar_value c_schar,
uchar_value c_uchar, uchar_value c_uchar,
@@ -21,7 +21,7 @@ verify :: c_func(
longdouble_value c_longdouble, longdouble_value c_longdouble,
) i32 ) i32
main :: func() i32 { main func() i32 {
buffer @Buffer :: get_buffer() buffer @Buffer :: get_buffer()
_ = buffer^.data _ = buffer^.data
_ = buffer^.length _ = buffer^.length
+5 -5
View File
@@ -1,22 +1,22 @@
native :: import "../include/native.h" native :: import "../include/native.h"
pass_alias :: func(value native.imported_int_alias) native.imported_int { pass_alias func(value native.imported_int_alias) native.imported_int {
return value return value
} }
double_value :: c_func(value c_int) c_int { double_value c_func(value c_int) c_int {
return value + value return value + value
} }
call_mapper :: func(mapper native.Imported_Mapper) c_int { call_mapper func(mapper native.Imported_Mapper) c_int {
return mapper?(21) return mapper?(21)
} }
enum_identity :: c_func(value native.Imported_Enum) native.Imported_Enum { enum_identity c_func(value native.Imported_Enum) native.Imported_Enum {
return value return value
} }
main :: func() void { main func() void {
_ = native.imported_add(pass_alias(20), 22) _ = native.imported_add(pass_alias(20), 22)
_ = native.imported_scalar(3, 4) _ = native.imported_scalar(3, 4)
_ = native.child_value(7) _ = native.child_value(7)
+1 -1
View File
@@ -1,4 +1,4 @@
first :: import "../header/include/native.h" first :: import "../header/include/native.h"
second :: import "../header/include/native.h" second :: import "../header/include/native.h"
main :: func() void {} main func() void {}
+1 -1
View File
@@ -1,7 +1,7 @@
first :: import "first.h" first :: import "first.h"
second :: import "second.h" second :: import "second.h"
main :: func() void { main func() void {
_ = first.conflict_global _ = first.conflict_global
_ = second.conflict_global _ = second.conflict_global
} }
+1 -1
View File
@@ -1,7 +1,7 @@
native :: import "../header/include/native.h" native :: import "../header/include/native.h"
child :: import "../header/include/child.h" child :: import "../header/include/child.h"
main :: func() void { main func() void {
_ = native.child_value(1) _ = native.child_value(1)
_ = child.child_value(2) _ = child.child_value(2)
native.child_shared_global = 7 native.child_shared_global = 7
@@ -1,5 +1,5 @@
native :: import "native.h" native :: import "native.h"
main :: func() void { main func() void {
_ = native.main _ = native.main
} }
@@ -1,7 +1,7 @@
variable :: import "variable.h" variable :: import "variable.h"
function :: import "function.h" function :: import "function.h"
main :: func() void { main func() void {
_ = variable.conflict_symbol _ = variable.conflict_symbol
_ = function.conflict_symbol() _ = function.conflict_symbol()
} }
+5 -5
View File
@@ -1,11 +1,11 @@
native :: import "../header/include/native.h" native :: import "../header/include/native.h"
use_callback :: c_func(value native.Imported_Callback) void use_callback c_func(value native.Imported_Callback) void
use_union :: c_func(value native.Imported_Union) void use_union c_func(value native.Imported_Union) void
use_enum :: c_func(value native.Imported_Enum) void use_enum c_func(value native.Imported_Enum) void
use_opaque :: c_func(value native.Imported_Handle) void use_opaque c_func(value native.Imported_Handle) void
main :: func() void { main func() void {
_ = native.IMPORTED_BAD_EXPR _ = native.IMPORTED_BAD_EXPR
_ = native.IMPORTED_REDEFINED_BAD _ = native.IMPORTED_REDEFINED_BAD
_ = native.IMPORTED_GONE _ = native.IMPORTED_GONE
@@ -1,5 +1,5 @@
native :: import "native.h" native :: import "native.h"
main :: func() void { main func() void {
_ = native.write _ = native.write
} }
+2 -2
View File
@@ -1,5 +1,5 @@
foreign_add :: c_func(a, b i32) i32 foreign_add c_func(a, b i32) i32
main :: func() i32 { main func() i32 {
return foreign_add(20, 22) return foreign_add(20, 22)
} }
+2 -2
View File
@@ -1,5 +1,5 @@
printf :: c_func(format *c_char, ...) c_int printf c_func(format *c_char, ...) c_int
main :: func() void { main func() void {
_ = printf("answer: %d\n", 42) _ = printf("answer: %d\n", 42)
} }
+4 -4
View File
@@ -4,21 +4,21 @@ Manual :: c_struct {
value c_int value c_int
} }
mirror_manual :: c_func(value Manual) Manual { mirror_manual c_func(value Manual) Manual {
return value return value
} }
mirror_large :: c_func(value native.Large) native.Large { mirror_large c_func(value native.Large) native.Large {
return value return value
} }
native_pair :: func(value native.Pair) native.Pair { native_pair func(value native.Pair) native.Pair {
return value return value
} }
global_pair native.Pair :: native.Pair { left = 1, right = 2 } global_pair native.Pair :: native.Pair { left = 1, right = 2 }
main :: func() i32 { main func() i32 {
pair native.Pair = native_pair(global_pair) pair native.Pair = native_pair(global_pair)
pair.left = 10 pair.left = 10
pair = native.echo_pair(pair) pair = native.echo_pair(pair)
+1 -1
View File
@@ -4,7 +4,7 @@ native :: import "../include/native.h"
# the importer must not recurse forever populating it, and the checker must accept the # the importer must not recurse forever populating it, and the checker must accept the
# self-referential `?*mut Node` field as C-layout-compatible. # self-referential `?*mut Node` field as C-layout-compatible.
main :: func() i32 { main func() i32 {
node native.Node = native.Node { next = none, value = 7 } node native.Node = native.Node { next = none, value = 7 }
if node.next |_| { if node.next |_| {
return 1 return 1
+1 -1
View File
@@ -1,3 +1,3 @@
import "/definitely/not/a/brolang/package" import "/definitely/not/a/brolang/package"
main :: func() void {} main func() void {}
@@ -1,6 +1,6 @@
math i32 :: 7 math i32 :: 7
import "../math" import "../math"
main :: func() i32 { main func() i32 {
return math return math
} }
+1 -1
View File
@@ -1,6 +1,6 @@
left :: import "../math" left :: import "../math"
right :: import "../math" right :: import "../math"
main :: func() i32 { main func() i32 {
return left.value + right.value return left.value + right.value
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "../math" import "../math"
main :: func() i32 { main func() i32 {
return math.sum(local_value, math.value) return math.sum(local_value, math.value)
} }
+1 -1
View File
@@ -1,5 +1,5 @@
value i32 :: 2 value i32 :: 2
sum :: func(a, b i32) i32 { sum func(a, b i32) i32 {
return a + b return a + b
} }
+1 -1
View File
@@ -1,7 +1,7 @@
import "../left" import "../left"
import "../right" import "../right"
main :: func() void { main func() void {
_ = left.same() _ = left.same()
_ = right.same() _ = right.same()
} }
+1 -1
View File
@@ -1,3 +1,3 @@
same :: c_func() int { same c_func() int {
return 1 return 1
} }
+1 -1
View File
@@ -1,3 +1,3 @@
same :: c_func() int { same c_func() int {
return 2 return 2
} }
+1 -1
View File
@@ -2,6 +2,6 @@ import "../b"
seed i32 :: 4 seed i32 :: 4
run :: func() i32 { run func() i32 {
return b.value return b.value
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "../a" import "../a"
main :: func() i32 { main func() i32 {
return a.run() return a.run()
} }
@@ -1,5 +1,5 @@
import "./level_three" import "./level_three"
value :: func() i32 { value func() i32 {
return level_three.value return level_three.value
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "./level_two" import "./level_two"
value :: func() i32 { value func() i32 {
return level_two.value() return level_two.value()
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "./level_one" import "./level_one"
main :: func() i32 { main func() i32 {
return level_one.value() return level_one.value()
} }
@@ -1,3 +1,3 @@
import "../bad-name" import "../bad-name"
main :: func() void {} main func() void {}
+1 -1
View File
@@ -1,6 +1,6 @@
math :: import "../math" math :: import "../math"
math :: import "../math" math :: import "../math"
main :: func() i32 { main func() i32 {
return math.value return math.value
} }
+1 -1
View File
@@ -1,3 +1,3 @@
import "../eager" import "../eager"
main :: func() void {} main func() void {}
+1 -1
View File
@@ -1,3 +1,3 @@
import "../empty" import "../empty"
main :: func() void {} main func() void {}
@@ -1,5 +1,5 @@
good :: import "../bad-name" good :: import "../bad-name"
main :: func() i32 { main func() i32 {
return good.value return good.value
} }
+1 -1
View File
@@ -1,3 +1,3 @@
import "../not_package.bro" import "../not_package.bro"
main :: func() void {} main func() void {}
@@ -1 +1 @@
main :: func() void {} main func() void {}
+1 -1
View File
@@ -1,5 +1,5 @@
import "../math" import "../math"
used_here :: func() int { used_here func() int {
return math.value return math.value
} }
+2 -2
View File
@@ -1,8 +1,8 @@
not_imported_here :: func() int { not_imported_here func() int {
return math.value return math.value
} }
main :: func() void { main func() void {
_ = used_here() _ = used_here()
_ = not_imported_here() _ = not_imported_here()
} }
@@ -1,7 +1,7 @@
import "../left" import "../left"
import "../right" import "../right"
main :: func() void { main func() void {
_ = left.same() _ = left.same()
_ = right.same() _ = right.same()
} }
@@ -1 +1 @@
same :: c_func() i32 same c_func() i32
@@ -1 +1 @@
same :: c_func() i32 same c_func() i32
+1 -1
View File
@@ -1,5 +1,5 @@
import "../math" import "../math"
main :: func() i32 { main func() i32 {
return math.identity(127 + 1) return math.identity(127 + 1)
} }
+1 -1
View File
@@ -1,3 +1,3 @@
identity :: func(value int) int { identity func(value int) int {
return value return value
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "../a" import "../a"
main :: func() void { main func() void {
_ = a.value _ = a.value
} }
+1 -1
View File
@@ -1,4 +1,4 @@
main :: func() i32 { main func() i32 {
return math.value return math.value
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "../dep" import "../dep"
main :: func() i32 { main func() i32 {
return dep.main() return dep.main()
} }
+1 -1
View File
@@ -1,3 +1,3 @@
main :: func() i32 { main func() i32 {
return 7 return 7
} }
+2 -2
View File
@@ -1,7 +1,7 @@
import "../math" import "../math"
unused :: func() int { unused func() int {
return math.missing return math.missing
} }
main :: func() void {} main func() void {}
@@ -1,3 +1,3 @@
main :: func() i32 { main func() i32 {
return 1 return 1
} }
@@ -1,3 +1,3 @@
import "../missing" import "../missing"
main :: func() void {} main func() void {}
+1 -1
View File
@@ -1,5 +1,5 @@
import "../missing" import "../missing"
main :: func() void { main func() void {
_ = missing.value _ = missing.value
} }
@@ -1,5 +1,5 @@
import "../bridge" import "../bridge"
main :: func() void { main func() void {
_ = bridge.value _ = bridge.value
} }
@@ -1,5 +1,5 @@
import "../math" import "../math"
read :: func() i32 { read func() i32 {
return math.value return math.value
} }
@@ -1,3 +1,3 @@
import "../broken" import "../broken"
main :: func() void {} main func() void {}
@@ -1,9 +1,9 @@
import "../math" import "../math"
read :: func(value i8) int { read func(value i8) int {
return math.value return math.value
} }
main :: func() i32 { main func() i32 {
return read(1) return read(1)
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "../b" import "../b"
one :: func(value int) i32 { one func(value int) i32 {
return b.two(value) return b.two(value)
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "../a" import "../a"
main :: func() i32 { main func() i32 {
return a.one(1) return a.one(1)
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "../a" import "../a"
two :: func(value int) i32 { two func(value int) i32 {
return a.one(value) return a.one(value)
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "../math" import "../math"
from_a :: func() i32 { from_a func() i32 {
return math.value return math.value
} }
+1 -1
View File
@@ -1,5 +1,5 @@
import "../math" import "../math"
main :: func() i32 { main func() i32 {
return from_a() + math.value return from_a() + math.value
} }
+1 -1
View File
@@ -2,6 +2,6 @@ self :: import "."
value i32 :: 5 value i32 :: 5
main :: func() i32 { main func() i32 {
return self.value return self.value
} }
+1 -1
View File
@@ -1,3 +1,3 @@
import "../math" import "../math"
main :: func() void {} main func() void {}
+1 -1
View File
@@ -5,7 +5,7 @@
# innermost enclosing loop. Each section returns a distinct code on failure so # innermost enclosing loop. Each section returns a distinct code on failure so
# a regression points at the broken behaviour; success falls through to 42. # a regression points at the broken behaviour; success falls through to 42.
main :: func() i32 { main func() i32 {
# 1. `break` out of a `while` once i reaches 5. # 1. `break` out of a `while` once i reaches 5.
i i32 = 0 i i32 = 0
a i32 = 0 a i32 = 0
@@ -1,7 +1,7 @@
# Milestone 6: compound assignment (`+=`, `-=`, `*=`, `/=`) and the binary # Milestone 6: compound assignment (`+=`, `-=`, `*=`, `/=`) and the binary
# arithmetic operators `-`, `*`, `/` with multiplicative precedence. # arithmetic operators `-`, `*`, `/` with multiplicative precedence.
check_float :: func() i32 { check_float func() i32 {
x f64 = 10.0 x f64 = 10.0
x /= 4.0 # 2.5 x /= 4.0 # 2.5
x *= 2.0 # 5.0 x *= 2.0 # 5.0
@@ -13,7 +13,7 @@ check_float :: func() i32 {
return 0 return 0
} }
check_unsigned :: func() i32 { check_unsigned func() i32 {
n u32 = 100 n u32 = 100
n /= 7 # 14 (truncating integer division) n /= 7 # 14 (truncating integer division)
n -= 4 # 10 n -= 4 # 10
@@ -23,7 +23,7 @@ check_unsigned :: func() i32 {
return 0 return 0
} }
main :: func() i32 { main func() i32 {
total i32 = 0 total i32 = 0
total += 10 # 10 total += 10 # 10
total -= 3 # 7 total -= 3 # 7
@@ -1,11 +1,11 @@
# Milestone 5: conditional optional unwrapping, guards, and multi-unwrap. # Milestone 5: conditional optional unwrapping, guards, and multi-unwrap.
observe :: func(counter @mut i32, value ?i32) ?i32 { observe func(counter @mut i32, value ?i32) ?i32 {
counter^ = counter^ + 1 counter^ = counter^ + 1
return value return value
} }
main :: func() i32 { main func() i32 {
total i32 = 0 total i32 = 0
# present optional scalar -> binds v to the unwrapped value # present optional scalar -> binds v to the unwrapped value
@@ -1,4 +1,4 @@
main :: func() void { main func() void {
value i8 :: 127 + 1 value i8 :: 127 + 1
_ = value _ = value
} }
+1 -1
View File
@@ -1,3 +1,3 @@
main :: func() void { main func() void {
_ = 127 + 1 _ = 127 + 1
} }
@@ -1,3 +1,3 @@
main :: func() void { main func() void {
_ = 9223372036854775807 + 1 _ = 9223372036854775807 + 1
} }
+4 -4
View File
@@ -1,9 +1,9 @@
# Milestone 5 foundation: booleans, comparisons, logical ops, if/else if/else. # Milestone 5 foundation: booleans, comparisons, logical ops, if/else if/else.
printf :: c_func(format *c_char, ...) c_int printf c_func(format *c_char, ...) c_int
# Returns a distinct code per range using if / else if / else and comparisons. # Returns a distinct code per range using if / else if / else and comparisons.
classify :: func(n i32) i32 { classify func(n i32) i32 {
if n < 0 { if n < 0 {
return 1 return 1
} else if n == 0 { } else if n == 0 {
@@ -17,12 +17,12 @@ classify :: func(n i32) i32 {
# A bool-returning function with a visible side effect, used to prove # A bool-returning function with a visible side effect, used to prove
# short-circuit evaluation: it must only print when actually evaluated. # short-circuit evaluation: it must only print when actually evaluated.
noisy :: func() bool { noisy func() bool {
_ = printf("rhs-evaluated\n") _ = printf("rhs-evaluated\n")
return true return true
} }
main :: func() i32 { main func() i32 {
total i32 = 0 total i32 = 0
# comparisons drive if / else if / else # comparisons drive if / else if / else
+1 -1
View File
@@ -1,6 +1,6 @@
a int :: b a int :: b
b int :: a b int :: a
main :: func() void { main func() void {
_ = 1 _ = 1
} }
+1 -1
View File
@@ -1,6 +1,6 @@
a int :: b a int :: b
b int :: a b int :: a
main :: func() void { main func() void {
_ = a _ = a
} }
+3 -3
View File
@@ -6,7 +6,7 @@
# The return value is captured before defers run, so the mutation here does not # The return value is captured before defers run, so the mutation here does not
# change what is returned (Zig semantics). # change what is returned (Zig semantics).
spill_check :: func() i32 { spill_check func() i32 {
x i32 = 5 x i32 = 5
defer x = 999 defer x = 999
return x return x
@@ -14,7 +14,7 @@ spill_check :: func() i32 {
# A function-scope defer runs only at function exit; a `break` runs the loop-body # A function-scope defer runs only at function exit; a `break` runs the loop-body
# defer but NOT the enclosing function-scope defer. # defer but NOT the enclosing function-scope defer.
enclosing_defer_check :: func() i32 { enclosing_defer_check func() i32 {
v i32 = 0 v i32 = 0
defer v = v + 100 defer v = v + 100
for 0..3 |i| { for 0..3 |i| {
@@ -24,7 +24,7 @@ enclosing_defer_check :: func() i32 {
return v # 0->1 (i=0 fall-through), ->2 (i=1 break); the +100 runs after capture return v # 0->1 (i=0 fall-through), ->2 (i=1 break); the +100 runs after capture
} }
main :: func() i32 { main func() i32 {
# 1. return value captured before defers run. # 1. return value captured before defers run.
if (spill_check() != 5) return 101 if (spill_check() != 5) return 101
+1 -1
View File
@@ -1,5 +1,5 @@
UserID :: distinct u32 UserID :: distinct u32
make :: func(value u32) UserID { make func(value u32) UserID {
return UserID(value) return UserID(value)
} }
+2 -2
View File
@@ -12,11 +12,11 @@ WrappedID :: distinct LocalID
static_id LocalID :: LocalID(42) static_id LocalID :: LocalID(42)
take :: func(value LocalID) LocalID { take func(value LocalID) LocalID {
return value return value
} }
main :: func() i32 { main func() i32 {
id LocalID :: LocalID(7) id LocalID :: LocalID(7)
copy LocalID = take(id) copy LocalID = take(id)
maybe ?LocalID = copy maybe ?LocalID = copy
+1 -1
View File
@@ -3,6 +3,6 @@ Animal :: enum {
cat cat
} }
favorite :: func() Animal { favorite func() Animal {
return .cat return .cat
} }
+3 -3
View File
@@ -8,15 +8,15 @@ State :: enum(u16) {
initial State :: State.started initial State :: State.started
same :: func(left State, right State) bool { same func(left State, right State) bool {
return left == right return left == right
} }
identity :: c_func(value State) State { identity c_func(value State) State {
return value return value
} }
main :: func() i32 { main func() i32 {
state State = identity(.running) state State = identity(.running)
values [2]State :: [.started, State.stopped] values [2]State :: [.started, State.stopped]
animal animals.Animal :: animals.Animal.dog animal animals.Animal :: animals.Animal.dog
+6 -6
View File
@@ -28,37 +28,37 @@ BoxB :: union(enum) {
Box :: alias BoxA | BoxB Box :: alias BoxA | BoxB
maybe :: func(value i32) i32 ! BasicError { maybe func(value i32) i32 ! BasicError {
if (value == 0) return .bad if (value == 0) return .bad
return value + 1 return value + 1
} }
via_try :: func(value i32) i32 ! BasicError { via_try func(value i32) i32 ! BasicError {
unwrapped :: try maybe(value) unwrapped :: try maybe(value)
return unwrapped + 1 return unwrapped + 1
} }
with_detail :: func(value i32) i32 ! DetailError { with_detail func(value i32) i32 ! DetailError {
if (value == 0) return DetailError{ code = 5 } if (value == 0) return DetailError{ code = 5 }
if (value == 1) return .empty if (value == 1) return .empty
return value return value
} }
pick :: func(value Both) i32 { pick func(value Both) i32 {
match value { match value {
.left: return 10 .left: return 10
.right: return 20 .right: return 20
} }
} }
payload :: func(value Box) i32 { payload func(value Box) i32 {
match value { match value {
.a |n|: return n .a |n|: return n
.b: return 3 .b: return 3
} }
} }
main :: func() i32 { main func() i32 {
acc i32 = 0 acc i32 = 0
a :: maybe(0) catch 7 a :: maybe(0) catch 7
+2 -2
View File
@@ -1,10 +1,10 @@
# Milestone 5: ranges and sequence for loops. # Milestone 5: ranges and sequence for loops.
pass :: func(value range) range { pass func(value range) range {
return value return value
} }
main :: func() i32 { main func() i32 {
total i32 = 0 total i32 = 0
items [3]mut i32 = [1, 2, 3] items [3]mut i32 = [1, 2, 3]
+2 -2
View File
@@ -1,11 +1,11 @@
make_range :: func(calls @mut i32, end usize) range { make_range func(calls @mut i32, end usize) range {
calls^ = calls^ + 1 calls^ = calls^ + 1
return 0..end return 0..end
} }
global_range :: 0..1 global_range :: 0..1
main :: func() i32 { main func() i32 {
total i32 = 0 total i32 = 0
first u8 = 254 first u8 = 254
@@ -1,9 +1,9 @@
bad int = 1 bad int = 1
read_bad :: func() int { read_bad func() int {
return bad return bad
} }
derived :: read_bad() derived :: read_bad()
main :: func() void {} main func() void {}
@@ -1,11 +1,11 @@
bad int = 1 bad int = 1
read_bad :: func() int { read_bad func() int {
return bad return bad
} }
derived :: read_bad() derived :: read_bad()
main :: func() void { main func() void {
_ = derived _ = derived
} }
@@ -1,11 +1,11 @@
bad int = 4 bad int = 4
read_bad :: func() int { read_bad func() int {
return bad return bad
} }
derived int :: read_bad() derived int :: read_bad()
main :: func() void { main func() void {
_ = 1 _ = 1
} }
@@ -1,11 +1,11 @@
bad int = 4 bad int = 4
read_bad :: func() int { read_bad func() int {
return bad return bad
} }
derived int :: read_bad() derived int :: read_bad()
main :: func() void { main func() void {
_ = derived _ = derived
} }
@@ -1,7 +1,7 @@
broken :: func(value int) int { broken func(value int) int {
return missing + value return missing + value
} }
main :: func() void { main func() void {
_ = 1 _ = 1
} }
@@ -1,5 +1,5 @@
bad int = 4 bad int = 4
main :: func() void { main func() void {
_ = 1 _ = 1
} }
@@ -1,7 +1,7 @@
broken :: func(value int) int { broken func(value int) int {
return missing + value return missing + value
} }
main :: func() void { main func() void {
_ = broken(1) _ = broken(1)
} }
@@ -1,5 +1,5 @@
bad int = 4 bad int = 4
main :: func() void { main func() void {
_ = bad _ = bad
} }
+1 -1
View File
@@ -1,3 +1,3 @@
main :: func() i32 { main func() i32 {
return 4 return 4
} }
+1 -1
View File
@@ -1,3 +1,3 @@
main :: func() int { main func() int {
return 3 return 3
} }
@@ -1,12 +1,12 @@
take :: func(value i8) i8 { take func(value i8) i8 {
return value return value
} }
bad_return :: func() i8 { bad_return func() i8 {
return missing return missing
} }
main :: func() void { main func() void {
_ = take(missing) _ = take(missing)
_ = bad_return() _ = bad_return()
} }
+5 -5
View File
@@ -30,7 +30,7 @@ Box :: union(enum) {
# Statement match with payload capture; every variant returns, so the function needs # Statement match with payload capture; every variant returns, so the function needs
# no trailing return (the desugared if/else chain covers all paths). # no trailing return (the desugared if/else chain covers all paths).
describe :: func(d Data) i32 { describe func(d Data) i32 {
match d { match d {
.dog |age|: return age + 1 .dog |age|: return age + 1
.bird |wingspan|: return wingspan + 2 .bird |wingspan|: return wingspan + 2
@@ -38,7 +38,7 @@ describe :: func(d Data) i32 {
} }
# Value match: single-expression arms yield implicitly, a block arm yields explicitly. # Value match: single-expression arms yield implicitly, a block arm yields explicitly.
area :: func(s Shape) i32 { area func(s Shape) i32 {
result :: match s { result :: match s {
.square |side|: side * side .square |side|: side * side
.circle |r|: { .circle |r|: {
@@ -51,18 +51,18 @@ area :: func(s Shape) i32 {
# Same-type multi-pattern capture: `.dog` and `.bird` are both i32, so one capture binds # Same-type multi-pattern capture: `.dog` and `.bird` are both i32, so one capture binds
# either payload (read once at the union's shared carrier offset). # either payload (read once at the union's shared carrier offset).
payload_of :: func(d Data) i32 { payload_of func(d Data) i32 {
v :: match d { v :: match d {
.dog, .bird |n|: n .dog, .bird |n|: n
} }
return v return v
} }
make_box :: func() Box { make_box func() Box {
return Box{ point = Point{ x = 4, y = 0 } } return Box{ point = Point{ x = 4, y = 0 } }
} }
main :: func() i32 { main func() i32 {
acc i32 = 0 acc i32 = 0
dog Data = Data{ dog = 9 } dog Data = Data{ dog = 9 }
+1 -1
View File
@@ -1,4 +1,4 @@
main :: func() i32 { main func() i32 {
value i32 = 1 value i32 = 1
value = value + 2 value = value + 2
return value return value
+2 -2
View File
@@ -1,7 +1,7 @@
take :: func(value i8) i8 { take func(value i8) i8 {
return value return value
} }
main :: func() void { main func() void {
_ = take(128) _ = take(128)
} }
+1 -1
View File
@@ -1 +1 @@
main :: func() i32 { return 7 } main func() i32 { return 7 }
+1 -1
View File
@@ -1,4 +1,4 @@
main :: func() void { main func() void {
value i8 = 127 value i8 = 127
_ = value + 1 _ = value + 1
} }
+3 -3
View File
@@ -2,15 +2,15 @@
x int :: 2 x int :: 2
sum_c :: c_func(a, b int) int { sum_c c_func(a, b int) int {
return a + b return a + b
} }
sum_brolang :: func(a, b int) int { sum_brolang func(a, b int) int {
return a + b return a + b
} }
main :: func() void { main func() void {
y int = 4 y int = 4
a_add_b_c :: sum_c(1, 2) a_add_b_c :: sum_c(1, 2)
a_add_b_brolang :: sum_brolang(1, 2) a_add_b_brolang :: sum_brolang(1, 2)
+2 -2
View File
@@ -1,10 +1,10 @@
make_value :: func() int { make_value func() int {
return 40 + 2 return 40 + 2
} }
answer int :: make_value() answer int :: make_value()
main :: func() i32 { main func() i32 {
_ = answer _ = answer
return 0 return 0
} }

Some files were not shown because too many files have changed in this diff Show More