diff --git a/LANGUAGE.md b/LANGUAGE.md index 332cfed..18a17de 100644 --- a/LANGUAGE.md +++ b/LANGUAGE.md @@ -16,9 +16,9 @@ roadmap and milestone history. - file-local relative imports, import aliases, and qualified member access - transparent declaration aliases with `Name :: alias package.Member`; functions/type factories, named types, and globals retain their original declaration or storage identity -- bare `hide` and explicit `hide(package)` make a named top-level declaration package-local; - `hide(file)` makes it file-local; declarations are public by default, leading underscores - are ordinary identifier characters, and imports are always file-local +- bare `@hide` and explicit `@hide:package` make a named top-level declaration package-local; + `@hide:file` makes it file-local, and any qualifier may precede its declaration on a separate + line; the qualifier words remain valid identifiers, declarations are public by default, and imports are always file-local - relative `.h` imports as synthetic C header package namespaces - native `name test { ... }` declarations with fallible-void results inferred from `testing.Error` and errors propagated by `try`, plus anonymous diff --git a/README.md b/README.md index 50ec5ee..5207914 100644 --- a/README.md +++ b/README.md @@ -208,14 +208,18 @@ mem :: import "@std/mem" value :: math.sum(other_math.value, 1) ``` -Top-level declarations are public by default. Prefix a declaration with bare `hide` -to make it package-local, or spell the scope explicitly with `hide(package)` or -`hide(file)`. Leading underscores have no visibility meaning. Imports are always -file-local and cannot use visibility modifiers or be re-exported: +Top-level declarations are public by default. Prefix a declaration with bare `@hide` +to make it package-local, or spell the scope explicitly with `@hide:package` or +`@hide:file`. The qualifier is contextual, so `hide`, `package`, and `file` remain +available as identifiers. Imports are always file-local and cannot use visibility +qualifiers or be re-exported: ```bro -hide shared_helper func() i32 { return 42 } -hide(file) implementation_detail func() i32 { return shared_helper() } +@hide +shared_helper func() i32 { return 42 } + +@hide:file +implementation_detail func() i32 { return shared_helper() } ``` Current prototype features: diff --git a/compiler/checker/checker.odin b/compiler/checker/checker.odin index dadefb8..f125c72 100644 --- a/compiler/checker/checker.odin +++ b/compiler/checker/checker.odin @@ -1758,7 +1758,7 @@ configure_entry_point :: proc(checker: ^Checker) { checker.template_diagnostics[main_template] = source.add( checker.diagnostics, main.span, - "@std/io does not provide the required 'hide system func() Io' startup implementation", + "@std/io does not provide the required '@hide system func() Io' startup implementation", ) return } diff --git a/compiler/lexer/lexer.odin b/compiler/lexer/lexer.odin index 5ea2d0a..135a8ce 100644 --- a/compiler/lexer/lexer.odin +++ b/compiler/lexer/lexer.odin @@ -26,7 +26,6 @@ keyword_kind :: proc(text: string) -> token.Kind { case "distinct": return .Keyword_Distinct case "alias": return .Keyword_Alias case "import": return .Keyword_Import - case "hide": return .Keyword_Hide case "return": return .Keyword_Return case "try": return .Keyword_Try case "catch": return .Keyword_Catch diff --git a/compiler/parser/parser.odin b/compiler/parser/parser.odin index 801603a..584f8e7 100644 --- a/compiler/parser/parser.odin +++ b/compiler/parser/parser.odin @@ -65,20 +65,21 @@ collect_local_names :: proc(parser: ^Parser) { depth += 1 case .Right_Brace: depth = max(depth-1, 0) - case .Keyword_Hide: - if depth != 0 { + case .At: + if depth != 0 || index+1 >= len(parser.tokens.items) || + parser.tokens.items[index+1].kind != .Identifier || + token_text(parser, parser.tokens.items[index+1]) != "hide" { continue } visibility := types.Visibility.Package - name_index := index+1 + name_index := index+2 if name_index < len(parser.tokens.items) && - parser.tokens.items[name_index].kind == .Left_Paren { - if index+4 >= len(parser.tokens.items) || - parser.tokens.items[index+2].kind != .Identifier || - parser.tokens.items[index+3].kind != .Right_Paren { + parser.tokens.items[name_index].kind == .Colon { + if index+3 >= len(parser.tokens.items) || + parser.tokens.items[index+3].kind != .Identifier { continue } - scope := token_text(parser, parser.tokens.items[index+2]) + scope := token_text(parser, parser.tokens.items[index+3]) if scope == "file" { visibility = .File } else if scope != "package" { @@ -86,6 +87,10 @@ collect_local_names :: proc(parser: ^Parser) { } name_index = index+4 } + for name_index < len(parser.tokens.items) && + parser.tokens.items[name_index].kind == .Newline { + name_index += 1 + } if name_index < len(parser.tokens.items) && parser.tokens.items[name_index].kind == .Identifier { append(&parser.local_names, Local_Name{ @@ -3324,12 +3329,15 @@ parse_test :: proc(parser: ^Parser, name: token.Token) { parse_top_level :: proc(parser: ^Parser) { modifier := current(parser) + hide_name := peek(parser) visibility := types.Visibility.Public - has_modifier := modifier.kind == .Keyword_Hide + has_modifier := modifier.kind == .At && hide_name.kind == .Identifier && + token_text(parser, hide_name) == "hide" if has_modifier { visibility = .Package advance(parser) - if _, scoped := allow(parser, .Left_Paren); scoped { + advance(parser) + if _, scoped := allow(parser, .Colon); scoped { if current(parser).kind == .Identifier { scope := advance(parser) scope_text := token_text(parser, scope) @@ -3344,12 +3352,10 @@ parse_top_level :: proc(parser: ^Parser) { ) } } else { - source.add(parser.diagnostics, current(parser).span, "expected 'package' or 'file' in hide scope") - } - if _, closed := allow(parser, .Right_Paren); !closed { - source.add(parser.diagnostics, current(parser).span, "expected ')' after hide scope") + source.add(parser.diagnostics, current(parser).span, "expected 'package' or 'file' after '@hide:'") } } + skip_newlines(parser) } if current(parser).kind == .Keyword_Test && peek(parser).kind == .Keyword_Import { if has_modifier { diff --git a/compiler/testing.odin b/compiler/testing.odin index 88eba0b..1351ffa 100644 --- a/compiler/testing.odin +++ b/compiler/testing.odin @@ -175,7 +175,7 @@ append_runner :: proc( for entry, index in tests { test := module.functions[entry.function] alias := fmt.tprintf("__brolang_test_%d", index) - fmt.sbprintf(&builder, "hide __brolang_test_adapter_%d func() void ! __brolang_testing.Error ", index) + fmt.sbprintf(&builder, "@hide __brolang_test_adapter_%d func() void ! __brolang_testing.Error ", index) strings.write_string(&builder, "{\n\t") fmt.sbprintf(&builder, "%s.%s() catch |_| ", alias, symbol.resolve(symbols, test.name)) strings.write_string(&builder, "{\n\t\treturn .expectation_failed\n\t}\n}\n\n") diff --git a/compiler/token/token.odin b/compiler/token/token.odin index e228824..15b4ea2 100644 --- a/compiler/token/token.odin +++ b/compiler/token/token.odin @@ -72,7 +72,6 @@ Kind :: enum u8 { Keyword_Distinct, Keyword_Alias, Keyword_Import, - Keyword_Hide, Keyword_Return, Keyword_Try, Keyword_Catch, diff --git a/compiler_tests.odin b/compiler_tests.odin index 11a59e1..9c7ccbd 100644 --- a/compiler_tests.odin +++ b/compiler_tests.odin @@ -3194,7 +3194,7 @@ main func() void! { B :: enum { b } fail_a func() void ! A { return .a } fail_b func() void ! B { return .b } -hide dispatch func(selector i32) void! { +@hide dispatch func(selector i32) void! { if selector == 1 { try fail_a() return @@ -3265,7 +3265,7 @@ main func() void {} { source=`Error :: enum { failed } fail func() void ! Error { return .failed } -hide untyped func(flag bool) void! { +@hide untyped func(flag bool) void! { if flag { try fail() return @@ -3277,7 +3277,7 @@ main func() void { untyped(false) catch |_| {} } message="inferred error returns require a concretely typed error value", }, { - source=`hide empty func() void! {} + source=`@hide empty func() void! {} main func() void { empty() catch |_| {} } `, message="could not infer a named error channel for 'empty'", @@ -3577,11 +3577,11 @@ system func() Io { return Io {value = 0} } process_source=`io :: import "@std/io" Init :: struct { io io.Io } `, - message="does not provide the required 'hide system func() Io'", + message="does not provide the required '@hide system func() Io'", }, { io_source=`Io :: struct { value i32 } -hide system func() Io { return Io {value = 0} } +@hide system func() Io { return Io {value = 0} } `, process_source=`io :: import "@std/io" Init :: struct { io io.Io, extra i32 } @@ -10366,16 +10366,16 @@ imports_are_file_local :: proc(t: ^testing.T) { @(test) visibility_modifiers_are_rejected_outside_named_top_level_declarations :: proc(t: ^testing.T) { cases := [?]string{ - `hide import "../dep"`, - `hide(file) dep :: import "../dep"`, - `hide func() void {}`, - `main func(hide value i32) void {}`, - `Box :: struct { hide i32 }`, - `main func() void { hide value i32 := 1 }`, - `hide() value :: 1`, - `hide(module) value :: 1`, - `hide("file") value :: 1`, - `hide(file value :: 1`, + `@hide import "../dep"`, + `@hide:file dep :: import "../dep"`, + `@hide func() void {}`, + `main func(@hide value i32) void {}`, + `Box :: struct { @hide i32 }`, + `main func() void { @hide value i32 := 1 }`, + `@hide: value :: 1`, + `@hide:module value :: 1`, + `@hide:"file" value :: 1`, + `@hide(file) value :: 1`, } for text in cases { source_file := source.Source{path="test.bro", text=text} @@ -10568,7 +10568,7 @@ MaybePoint :: alias ?@dep.Point Concrete :: alias dep.Box(i32) ` hidden_text := `dep :: import "../dep" -hide local_answer_alias :: alias dep.answer +@hide local_answer_alias :: alias dep.answer ` top_text := `facade :: import "../facade" Box :: alias facade.RenamedBox @@ -10692,7 +10692,7 @@ declaration_aliases_diagnose_invalid_targets :: proc(t: ^testing.T) { testing.expect(t, os.make_directory(directory) == nil) } dep_text := `visible func() i32 { return 1 } -hide hidden_target func() i32 { return 2 } +@hide hidden_target func() i32 { return 2 } ambiguous func() i32 { return 3 } ambiguous i32 :: 4 ` @@ -14165,7 +14165,6 @@ main func() i32 { @(test) keywords_are_valid_enum_members_and_tagged_union_variants :: proc(t: ^testing.T) { testing.expect(t, token.is_keyword(.Keyword_Func)) - testing.expect(t, token.is_keyword(.Keyword_Hide)) testing.expect(t, token.is_keyword(.Keyword_C_Longdouble)) testing.expect(t, !token.is_keyword(.Identifier)) testing.expect(t, !token.is_keyword(.Underscore)) @@ -14180,6 +14179,9 @@ Token :: union(TokenKind) { else void return i32 } +hide func() i32 { return 0 } +package func() i32 { return 0 } +file func() i32 { return 0 } kind func(value bool) TokenKind { if value { return .if @@ -14192,7 +14194,7 @@ main func() i32 { a Token := Token{ if = 1 } b Token := Token{ else } c Token := .return{2} - total i32 := a.if + c.return + total i32 := a.if + c.return + hide() + package() + file() match first { .if: total = total + 1 .else: total = total + 2 diff --git a/examples/packages/hidden_invalid/app/a.bro b/examples/packages/hidden_invalid/app/a.bro index 85c7606..92df0e2 100644 --- a/examples/packages/hidden_invalid/app/a.bro +++ b/examples/packages/hidden_invalid/app/a.bro @@ -1,22 +1,22 @@ -hide sibling func() i32 { +@hide sibling func() i32 { return 1 } -hide Sibling :: struct { +@hide Sibling :: struct { value i32 } -hide sibling_value :: 1 +@hide sibling_value :: 1 -hide(file) file_sibling func() i32 { +@hide:file file_sibling func() i32 { return 1 } -hide(file) File_Sibling :: struct { +@hide:file File_Sibling :: struct { value i32 } -hide(file) file_sibling_value :: 1 +@hide:file file_sibling_value :: 1 collision c_func() i32 { return 1 diff --git a/examples/packages/hidden_invalid/app/b.bro b/examples/packages/hidden_invalid/app/b.bro index 95ed97d..651b376 100644 --- a/examples/packages/hidden_invalid/app/b.bro +++ b/examples/packages/hidden_invalid/app/b.bro @@ -1,6 +1,6 @@ import "../dep" -hide collision func() i32 { +@hide collision func() i32 { return 2 } diff --git a/examples/packages/hidden_invalid/dep/dep.bro b/examples/packages/hidden_invalid/dep/dep.bro index 50428f3..408c317 100644 --- a/examples/packages/hidden_invalid/dep/dep.bro +++ b/examples/packages/hidden_invalid/dep/dep.bro @@ -1,3 +1,3 @@ -hide(package) secret c_func() i32 { +@hide:package secret c_func() i32 { return 1 } diff --git a/examples/packages/hidden_valid/app/a.bro b/examples/packages/hidden_valid/app/a.bro index 3b0e93b..148434f 100644 --- a/examples/packages/hidden_valid/app/a.bro +++ b/examples/packages/hidden_valid/app/a.bro @@ -1,26 +1,28 @@ -hide(package) helper func() i32 { +@hide:package +helper func() i32 { thing Thing := Thing { value = value } return thing.value } -hide Thing :: struct { +@hide +Thing :: struct { value i32 } -hide Local_Union :: union { +@hide Local_Union :: union { value i32 } -hide Local_Enum :: enum { +@hide Local_Enum :: enum { value } -hide Local_Opaque :: opaque -hide Local_Distinct :: distinct i32 -hide Local_Alias :: alias i32 +@hide Local_Opaque :: opaque +@hide Local_Distinct :: distinct i32 +@hide Local_Alias :: alias i32 -hide value :: 1 -hide mutable_value i32 := 1 +@hide value :: 1 +@hide mutable_value i32 := 1 _foreign c_func() i32 { return 1 @@ -30,23 +32,24 @@ _C_Record :: c_struct { value c_int } -hide local_foreign c_func() i32 { +@hide local_foreign c_func() i32 { return 1 } -hide Local_C_Record :: c_struct { +@hide Local_C_Record :: c_struct { value c_int } -hide(file) file_helper func() i32 { +@hide:file +file_helper func() i32 { return 1 } -hide(file) File_Thing :: struct { +@hide:file File_Thing :: struct { value i32 } -hide(file) file_value :: 1 +@hide:file file_value :: 1 from_a func() i32 { record Local_C_Record := Local_C_Record { value = 0 } diff --git a/examples/packages/hidden_valid/app/b.bro b/examples/packages/hidden_valid/app/b.bro index 85ca4bc..efed640 100644 --- a/examples/packages/hidden_valid/app/b.bro +++ b/examples/packages/hidden_valid/app/b.bro @@ -5,15 +5,15 @@ Box :: struct { _value i32 } -hide(file) file_helper func() i32 { +@hide:file file_helper func() i32 { return 2 } -hide(file) File_Thing :: struct { +@hide:file File_Thing :: struct { value i32 } -hide(file) file_value :: 2 +@hide:file file_value :: 2 from_b func(_input i32) i32 { _local Box := Box { _value = _input } diff --git a/examples/programs/arraylist/main.bro b/examples/programs/arraylist/main.bro index 098decf..0694152 100644 --- a/examples/programs/arraylist/main.bro +++ b/examples/programs/arraylist/main.bro @@ -19,23 +19,23 @@ init func(allocator mem.Allocator) State { } } -hide fail_alloc func(_ ?@mut anyopaque, _ usize, _ usize) ?*mut u8 { +@hide fail_alloc func(_ ?@mut anyopaque, _ usize, _ usize) ?*mut u8 { return null } -hide fail_realloc func(_ ?@mut anyopaque, _ ?*mut u8, _ usize, _ usize, _ usize) ?*mut u8 { +@hide fail_realloc func(_ ?@mut anyopaque, _ ?*mut u8, _ usize, _ usize, _ usize) ?*mut u8 { return null } -hide fail_free func(_ ?@mut anyopaque, _ ?*mut u8, _ usize, _ usize) void {} +@hide fail_free func(_ ?@mut anyopaque, _ ?*mut u8, _ usize, _ usize) void {} -hide fail_vtable mem.AllocatorVTable :: mem.AllocatorVTable { +@hide fail_vtable mem.AllocatorVTable :: mem.AllocatorVTable { alloc = fail_alloc, realloc = fail_realloc, free = fail_free, } -hide fail_allocator mem.Allocator :: mem.Allocator { +@hide fail_allocator mem.Allocator :: mem.Allocator { context = null, vtable = &fail_vtable, } diff --git a/examples/programs/io/main.bro b/examples/programs/io/main.bro index 5e3ac35..7afda21 100644 --- a/examples/programs/io/main.bro +++ b/examples/programs/io/main.bro @@ -1,7 +1,7 @@ io :: import "@std/io" process :: import "@std/process" -hide read_ok func(_ ?@mut anyopaque, _ io.Handle, buffer []mut u8) usize ! io.ReadError { +@hide read_ok func(_ ?@mut anyopaque, _ io.Handle, buffer []mut u8) usize ! io.ReadError { if buffer.len == 0 { return 0 } @@ -13,26 +13,26 @@ hide read_ok func(_ ?@mut anyopaque, _ io.Handle, buffer []mut u8) usize ! io.Re return 2 } -hide read_too_much func(_ ?@mut anyopaque, _ io.Handle, buffer []mut u8) usize ! io.ReadError { +@hide read_too_much func(_ ?@mut anyopaque, _ io.Handle, buffer []mut u8) usize ! io.ReadError { return buffer.len + 1 } -hide read_eof func(_ ?@mut anyopaque, _ io.Handle, _ []mut u8) usize ! io.ReadError { +@hide read_eof func(_ ?@mut anyopaque, _ io.Handle, _ []mut u8) usize ! io.ReadError { return 0 } -hide write_short func(_ ?@mut anyopaque, _ io.Handle, bytes []u8) usize ! io.WriteError { +@hide write_short func(_ ?@mut anyopaque, _ io.Handle, bytes []u8) usize ! io.WriteError { if bytes.len > 2 { return 2 } return bytes.len } -hide write_none func(_ ?@mut anyopaque, _ io.Handle, _ []u8) usize ! io.WriteError { +@hide write_none func(_ ?@mut anyopaque, _ io.Handle, _ []u8) usize ! io.WriteError { return 0 } -hide write_too_much func(_ ?@mut anyopaque, _ io.Handle, bytes []u8) usize ! io.WriteError { +@hide write_too_much func(_ ?@mut anyopaque, _ io.Handle, bytes []u8) usize ! io.WriteError { return bytes.len + 1 } diff --git a/examples/programs/mem_allocator/typed_alloc.bro b/examples/programs/mem_allocator/typed_alloc.bro index 5a6aedc..d1cfd52 100644 --- a/examples/programs/mem_allocator/typed_alloc.bro +++ b/examples/programs/mem_allocator/typed_alloc.bro @@ -1,27 +1,27 @@ mem :: import "@std/mem" -hide probe_count func(context ?@mut anyopaque) void { +@hide probe_count func(context ?@mut anyopaque) void { if context |raw| { count @mut usize :: ptrcast!(usize, raw) count^ += 1 } } -hide probe_alloc func(context ?@mut anyopaque, _ usize, _ usize) ?*mut u8 { +@hide probe_alloc func(context ?@mut anyopaque, _ usize, _ usize) ?*mut u8 { probe_count(context) return null } -hide probe_realloc func(context ?@mut anyopaque, _ ?*mut u8, _ usize, _ usize, _ usize) ?*mut u8 { +@hide probe_realloc func(context ?@mut anyopaque, _ ?*mut u8, _ usize, _ usize, _ usize) ?*mut u8 { probe_count(context) return null } -hide probe_free func(context ?@mut anyopaque, _ ?*mut u8, _ usize, _ usize) void { +@hide probe_free func(context ?@mut anyopaque, _ ?*mut u8, _ usize, _ usize) void { probe_count(context) } -hide probe_vtable mem.AllocatorVTable :: mem.AllocatorVTable { +@hide probe_vtable mem.AllocatorVTable :: mem.AllocatorVTable { alloc = probe_alloc, realloc = probe_realloc, free = probe_free, diff --git a/std/debug/debug.hon b/std/debug/debug.hon index 78ddacb..9cf75f2 100644 --- a/std/debug/debug.hon +++ b/std/debug/debug.hon @@ -10,7 +10,7 @@ print func($format []u8, $Args type, args Args) void { io.print(writer, format, Args, args) catch |_| {} } -hide write func(_ ?@mut anyopaque, handle io.Handle, bytes []u8) usize ! io.WriteError { +@hide write func(_ ?@mut anyopaque, handle io.Handle, bytes []u8) usize ! io.WriteError { request usize := bytes.len maximum usize :: usize(maxval!(c_long)) if request > maximum { diff --git a/std/hashmap/hashmap.hon b/std/hashmap/hashmap.hon index 635b150..c7d7425 100644 --- a/std/hashmap/hashmap.hon +++ b/std/hashmap/hashmap.hon @@ -134,7 +134,7 @@ put func( } } -hide normalize func(hash usize) usize { +@hide normalize func(hash usize) usize { # mapping both 0 and 1 to 1 is safe because equality resolves # collisions (since hash and key must both be equal). if (hash == 0) return 1 @@ -143,7 +143,7 @@ hide normalize func(hash usize) usize { #! FNV-1a hash implementation. #! note: vulnerable to collision attacks. -hide str_hash func(key []u8) usize { +@hide str_hash func(key []u8) usize { hash u32 := 2166136261 # offset basis prime u32 := 16777619 @@ -155,6 +155,6 @@ hide str_hash func(key []u8) usize { return usize(hash) } -hide str_eql func(a, b []u8) bool { +@hide str_eql func(a, b []u8) bool { return mem.eql(a, b) } diff --git a/std/io/file.hon b/std/io/file.hon index 7ba39ef..353229f 100644 --- a/std/io/file.hon +++ b/std/io/file.hon @@ -46,7 +46,7 @@ writer func(file File) Writer { } } -hide system_read func(_ ?@mut anyopaque, handle Handle, buffer []mut u8) usize ! ReadError { +@hide system_read func(_ ?@mut anyopaque, handle Handle, buffer []mut u8) usize ! ReadError { request usize := buffer.len maximum usize :: usize(maxval!(c_long)) if request > maximum { @@ -68,7 +68,7 @@ hide system_read func(_ ?@mut anyopaque, handle Handle, buffer []mut u8) usize ! } } -hide system_write func(_ ?@mut anyopaque, handle Handle, bytes []u8) usize ! WriteError { +@hide system_write func(_ ?@mut anyopaque, handle Handle, bytes []u8) usize ! WriteError { request usize := bytes.len maximum usize :: usize(maxval!(c_long)) if request > maximum { @@ -90,7 +90,7 @@ hide system_write func(_ ?@mut anyopaque, handle Handle, bytes []u8) usize ! Wri } } -hide system_open func(_ ?@mut anyopaque, path [;0]u8, mode FileMode) Handle ! OpenError { +@hide system_open func(_ ?@mut anyopaque, path [;0]u8, mode FileMode) Handle ! OpenError { flags c_int := c.O_RDONLY match mode { .read_only: flags = c.O_RDONLY @@ -108,25 +108,25 @@ hide system_open func(_ ?@mut anyopaque, path [;0]u8, mode FileMode) Handle ! Op } } -hide system_close func(_ ?@mut anyopaque, handle Handle) void ! CloseError { +@hide system_close func(_ ?@mut anyopaque, handle Handle) void ! CloseError { if c.close(handle.file_desc) != 0 { return .close_failed } } -hide system_stdin func(_ ?@mut anyopaque) Handle { +@hide system_stdin func(_ ?@mut anyopaque) Handle { return Handle {file_desc = c_int(Stream.stdin)} } -hide system_stdout func(_ ?@mut anyopaque) Handle { +@hide system_stdout func(_ ?@mut anyopaque) Handle { return Handle {file_desc = c_int(Stream.stdout)} } -hide system_stderr func(_ ?@mut anyopaque) Handle { +@hide system_stderr func(_ ?@mut anyopaque) Handle { return Handle {file_desc = c_int(Stream.stderr)} } -hide system_vtable IoVTable :: IoVTable { +@hide system_vtable IoVTable :: IoVTable { read = system_read, write = system_write, open = system_open, @@ -136,7 +136,7 @@ hide system_vtable IoVTable :: IoVTable { stderr = system_stderr, } -hide system func() Io { +@hide system func() Io { return Io { context = null, vtable = &system_vtable, diff --git a/std/io/io.hon b/std/io/io.hon index 6fbb40c..dac7997 100644 --- a/std/io/io.hon +++ b/std/io/io.hon @@ -128,7 +128,7 @@ print func(output Writer, $format []u8, $Args type, args Args) void ! WriteError } } -hide write_integer_signed func(output Writer, value i64, base u64, uppercase bool) void ! WriteError { +@hide write_integer_signed func(output Writer, value i64, base u64, uppercase bool) void ! WriteError { buffer [65]mut u8 := undefined end usize := buffer.len current i64 := value @@ -161,7 +161,7 @@ hide write_integer_signed func(output Writer, value i64, base u64, uppercase boo return } -hide write_integer_unsigned func(output Writer, value u64, base u64, uppercase bool) void ! WriteError { +@hide write_integer_unsigned func(output Writer, value u64, base u64, uppercase bool) void ! WriteError { buffer [65]mut u8 := undefined end usize := buffer.len current u64 := value @@ -184,7 +184,7 @@ hide write_integer_unsigned func(output Writer, value u64, base u64, uppercase b return } -hide FormatTokenKind :: enum { +@hide FormatTokenKind :: enum { unused literal default @@ -198,14 +198,14 @@ hide FormatTokenKind :: enum { scientific } -hide FormatToken :: struct { +@hide FormatToken :: struct { kind FormatTokenKind start usize end usize field []u8 } -hide parse_format func($N usize, $format []u8, $Args type) [N]mut FormatToken { +@hide parse_format func($N usize, $format []u8, $Args type) [N]mut FormatToken { tokens [N]mut FormatToken := undefined for (usize(0))..format.len |index| { tokens[index] = FormatToken {kind = .unused, start = 0, end = 0, field = ""} @@ -310,17 +310,17 @@ hide parse_format func($N usize, $format []u8, $Args type) [N]mut FormatToken { return tokens } -hide format_field_name func($T type, index usize) []u8 { +@hide format_field_name func($T type, index usize) []u8 { match typeinfo!(T) { .record |record|: return record.fields[index].name else: compile_error!("io.print arguments must be a tuple") } } -hide distinct_value func($Backing, $Distinct type, value Distinct) Backing { +@hide distinct_value func($Backing, $Distinct type, value Distinct) Backing { return ptrcast!(Backing, &value)^ } -hide scalar_or_distinct_type func($T type) bool { +@hide scalar_or_distinct_type func($T type) bool { match typeinfo!(T) { .bool: return true .integer: return true @@ -332,7 +332,7 @@ hide scalar_or_distinct_type func($T type) bool { -hide write_integer func(output Writer, $T type, value T, base u64, uppercase bool) void ! WriteError { +@hide write_integer func(output Writer, $T type, value T, base u64, uppercase bool) void ! WriteError { match typeinfo!(T) { .integer: if minval!(T) < 0 { try write_integer_signed(output, i64(value), base, uppercase) @@ -350,7 +350,7 @@ hide write_integer func(output Writer, $T type, value T, base u64, uppercase boo } # note: libc keeps float formatting small; replace it with a native shortest-roundtrip writer if locale independence matters. -hide write_float func(output Writer, $T type, value T, scientific bool) void ! WriteError { +@hide write_float func(output Writer, $T type, value T, scientific bool) void ! WriteError { match typeinfo!(T) { .float: { buffer [64]mut u8 := undefined @@ -381,7 +381,7 @@ hide write_float func(output Writer, $T type, value T, scientific bool) void ! W return } -hide write_decimal func(output Writer, $T type, value T) void ! WriteError { +@hide write_decimal func(output Writer, $T type, value T) void ! WriteError { match typeinfo!(T) { .integer: try write_integer(output, value, 10, false) .float: try write_float(output, value, false) @@ -395,7 +395,7 @@ hide write_decimal func(output Writer, $T type, value T) void ! WriteError { return } -hide write_character func(output Writer, $T type, value T) void ! WriteError { +@hide write_character func(output Writer, $T type, value T) void ! WriteError { match typeinfo!(T) { .integer: { if minval!(T) < 0 or maxval!(T) > 255 { @@ -414,7 +414,7 @@ hide write_character func(output Writer, $T type, value T) void ! WriteError { return } -hide write_default func(output Writer, $T type, value T) void ! WriteError { +@hide write_default func(output Writer, $T type, value T) void ! WriteError { match typeinfo!(T) { .bool: if value { try write_all(output, "true") diff --git a/std/mem/mem.hon b/std/mem/mem.hon index a474caf..5879289 100644 --- a/std/mem/mem.hon +++ b/std/mem/mem.hon @@ -119,11 +119,11 @@ empty func($T type) []mut T { return empty_slice(T, 0) } -hide empty_storage [1]mut u64 := [0] +@hide empty_storage [1]mut u64 := [0] -hide malloc_alignment usize :: 16 # ponytail: aarch64-macos libc malloc alignment assumption. +@hide malloc_alignment usize :: 16 # ponytail: aarch64-macos libc malloc alignment assumption. -hide power_of_two func(value usize) bool { +@hide power_of_two func(value usize) bool { if (value == 0) return false current usize := value while current > 1 { @@ -134,7 +134,7 @@ hide power_of_two func(value usize) bool { return true } -hide c_alloc func(_ ?@mut anyopaque, size usize, alignment usize) ?*mut u8 { +@hide c_alloc func(_ ?@mut anyopaque, size usize, alignment usize) ?*mut u8 { if (power_of_two(alignment) == false) return null if alignment <= malloc_alignment { @@ -148,7 +148,7 @@ hide c_alloc func(_ ?@mut anyopaque, size usize, alignment usize) ?*mut u8 { return ptrcast!(u8, memory[0]) } -hide c_realloc func(_ ?@mut anyopaque, memory ?*mut u8, old_size usize, new_size usize, alignment usize) ?*mut u8 { +@hide c_realloc func(_ ?@mut anyopaque, memory ?*mut u8, old_size usize, new_size usize, alignment usize) ?*mut u8 { if (power_of_two(alignment) == false) return null if new_size == 0 { @@ -174,11 +174,11 @@ hide c_realloc func(_ ?@mut anyopaque, memory ?*mut u8, old_size usize, new_size return c_alloc(null, new_size, alignment) } -hide c_free func(_ ?@mut anyopaque, memory ?*mut u8, _ usize, _ usize) void { +@hide c_free func(_ ?@mut anyopaque, memory ?*mut u8, _ usize, _ usize) void { c.free(memory) } -hide c_vtable AllocatorVTable :: AllocatorVTable { +@hide c_vtable AllocatorVTable :: AllocatorVTable { alloc = c_alloc, realloc = c_realloc, free = c_free, diff --git a/std/meta/meta.test.hon b/std/meta/meta.test.hon index 0d45e02..a2aa4c4 100644 --- a/std/meta/meta.test.hon +++ b/std/meta/meta.test.hon @@ -13,13 +13,13 @@ TestOuter :: distinct TestInner TestOuterAlias :: alias TestOuter -hide array_info_matches func($Array, $Child type, $len usize) bool { +@hide array_info_matches func($Array, $Child type, $len usize) bool { match typeinfo!(Array) { .array |info|: return info.child == Child and info.len == len else: return false } } -hide distinct_info_matches func($Distinct, $Backing type) bool { +@hide distinct_info_matches func($Distinct, $Backing type) bool { match typeinfo!(Distinct) { .distinct |backing|: return backing == Backing else: return false diff --git a/std/static_string_map/static_string_map.hon b/std/static_string_map/static_string_map.hon index 0b0868d..c6757bb 100644 --- a/std/static_string_map/static_string_map.hon +++ b/std/static_string_map/static_string_map.hon @@ -10,7 +10,7 @@ StaticStringMap func($V type) type { } } -hide Pair func($V type) type { +@hide Pair func($V type) type { return struct { []u8, V } } diff --git a/testbed/lexer/main.bro b/testbed/lexer/main.bro index 0648bde..4988a9c 100644 --- a/testbed/lexer/main.bro +++ b/testbed/lexer/main.bro @@ -20,17 +20,17 @@ Token :: struct { kind Kind } -hide is_alpha func(value u8) bool { +@hide is_alpha func(value u8) bool { return value == '_' or value >= 'a' and value <= 'z' or value >= 'A' and value <= 'Z' } -hide is_digit func(value u8) bool { +@hide is_digit func(value u8) bool { return value >= '0' and value <= '9' } -hide word_kind func(word []u8) Kind { +@hide word_kind func(word []u8) Kind { # ponytail: enough keywords for the demo; add the full language set when a parser needs it. if mem.eql(word, "func") or mem.eql(word, "void") { return .keyword @@ -38,7 +38,7 @@ hide word_kind func(word []u8) Kind { return .identifier } -hide append_token func(tokens @mut std.ArrayList(Token), kind Kind, start, end usize) void ! mem.AllocError { +@hide append_token func(tokens @mut std.ArrayList(Token), kind Kind, start, end usize) void ! mem.AllocError { try arraylist.append(tokens, Token { start = start, length = end - start, @@ -95,7 +95,7 @@ lex func(source []u8, tokens @mut std.ArrayList(Token)) void ! mem.AllocError { return } -hide kind_name func(kind Kind) *c_char { +@hide kind_name func(kind Kind) *c_char { return match kind { .invalid: "invalid" .eof: "eof" @@ -108,7 +108,7 @@ hide kind_name func(kind Kind) *c_char { } } -hide print_token func(source []u8, token Token) void { +@hide print_token func(source []u8, token Token) void { _ = c.printf("%-11s", kind_name(token.kind)) if token.length != 0 { _ = c.printf(" `") diff --git a/testbed/lexer/std/io/io.bro b/testbed/lexer/std/io/io.bro index 07b8360..2040c18 100644 --- a/testbed/lexer/std/io/io.bro +++ b/testbed/lexer/std/io/io.bro @@ -74,7 +74,7 @@ write_all func(writer Writer, bytes []u8) void ! WriteError { return } -hide system_read func(_ ?*mut anyopaque, stream ReadStream, buffer []mut u8) usize ! ReadError { +@hide system_read func(_ ?*mut anyopaque, stream ReadStream, buffer []mut u8) usize ! ReadError { request usize := buffer.len maximum usize :: usize(maxval!(c_long)) if request > maximum { @@ -91,7 +91,7 @@ hide system_read func(_ ?*mut anyopaque, stream ReadStream, buffer []mut u8) usi } } -hide system_write func(_ ?*mut anyopaque, stream WriteStream, bytes []mut u8) usize ! WriteError { +@hide system_write func(_ ?*mut anyopaque, stream WriteStream, bytes []u8) usize ! WriteError { fd c_int :: c_int(stream) request usize := bytes.len maximum usize :: usize(maxval!(c_long)) @@ -109,12 +109,12 @@ hide system_write func(_ ?*mut anyopaque, stream WriteStream, bytes []mut u8) us } } -hide system_vtable IoVTable :: IoVTable { +@hide system_vtable IoVTable :: IoVTable { read = system_read, write = system_write, } -hide system func() Io { +@hide system func() Io { return Io { context = null, vtable = &system_vtable, diff --git a/testbed/lexer/std/mem/mem.bro b/testbed/lexer/std/mem/mem.bro index 2d91785..096bb98 100644 --- a/testbed/lexer/std/mem/mem.bro +++ b/testbed/lexer/std/mem/mem.bro @@ -41,9 +41,9 @@ eql func($T type, left, right []T) bool { return true } -hide empty_storage [1]mut u64 := [0] +@hide empty_storage [1]mut u64 := [0] -hide empty_slice func($T type, count usize) []mut T { +@hide empty_slice func($T type, count usize) []mut T { pointer *mut T :: ptrcast!(T, (&empty_storage).ptr) return pointer[..count] } @@ -116,9 +116,9 @@ free func($T type, allocator Allocator, memory []mut T) void { } } -hide malloc_alignment usize :: 16 # ponytail: aarch64-macos libc malloc alignment assumption. +@hide malloc_alignment usize :: 16 # ponytail: aarch64-macos libc malloc alignment assumption. -hide power_of_two func(value usize) bool { +@hide power_of_two func(value usize) bool { if value == 0 { return false } @@ -135,7 +135,7 @@ hide power_of_two func(value usize) bool { return true } -hide c_alloc func(_ ?*mut anyopaque, size usize, alignment usize) ?*mut u8 { +@hide c_alloc func(_ ?@mut anyopaque, size usize, alignment usize) ?*mut u8 { if power_of_two(alignment) == false { return null } @@ -153,7 +153,7 @@ hide c_alloc func(_ ?*mut anyopaque, size usize, alignment usize) ?*mut u8 { return ptrcast!(u8, memory[0]) } -hide c_realloc func(_ ?*mut anyopaque, memory ?*mut u8, old_size usize, new_size usize, alignment usize) ?*mut u8 { +@hide c_realloc func(_ ?@mut anyopaque, memory ?*mut u8, old_size usize, new_size usize, alignment usize) ?*mut u8 { if power_of_two(alignment) == false { return null } @@ -186,11 +186,11 @@ hide c_realloc func(_ ?*mut anyopaque, memory ?*mut u8, old_size usize, new_size return c_alloc(null, new_size, alignment) } -hide c_free func(_ ?*mut anyopaque, memory ?*mut u8, _ usize, _ usize) void { +@hide c_free func(_ ?@mut anyopaque, memory ?*mut u8, _ usize, _ usize) void { c.free(memory) } -hide c_vtable AllocatorVTable :: AllocatorVTable { +@hide c_vtable AllocatorVTable :: AllocatorVTable { alloc = c_alloc, realloc = c_realloc, free = c_free, diff --git a/testbed/mem_alloc/std/mem/mem.bro b/testbed/mem_alloc/std/mem/mem.bro index c7c6642..4e2f8e6 100644 --- a/testbed/mem_alloc/std/mem/mem.bro +++ b/testbed/mem_alloc/std/mem/mem.bro @@ -27,9 +27,9 @@ raw_free func(allocator Allocator, memory ?*mut u8, size usize, alignment usize) allocator.vtable.free(allocator.context, memory, size, alignment) } -hide empty_storage [1]mut u64 := [0] +@hide empty_storage [1]mut u64 := [0] -hide empty_slice func($T type, count usize) []mut T { +@hide empty_slice func($T type, count usize) []mut T { pointer *mut T :: ptrcast!(T, (&empty_storage).ptr) return pointer[..count] } @@ -61,9 +61,9 @@ free func($T type, allocator Allocator, memory []mut T) void { } } -hide malloc_alignment usize :: 16 # ponytail: aarch64-macos libc malloc alignment assumption. +@hide malloc_alignment usize :: 16 # ponytail: aarch64-macos libc malloc alignment assumption. -hide power_of_two func(value usize) bool { +@hide power_of_two func(value usize) bool { if value == 0 { return false } @@ -80,7 +80,7 @@ hide power_of_two func(value usize) bool { return true } -hide c_alloc func(_ ?@mut anyopaque, size usize, alignment usize) ?*mut u8 { +@hide c_alloc func(_ ?@mut anyopaque, size usize, alignment usize) ?*mut u8 { if power_of_two(alignment) == false { return null } @@ -98,7 +98,7 @@ hide c_alloc func(_ ?@mut anyopaque, size usize, alignment usize) ?*mut u8 { return ptrcast!(u8, memory[0]) } -hide c_realloc func(_ ?@mut anyopaque, memory ?*mut u8, old_size usize, new_size usize, alignment usize) ?*mut u8 { +@hide c_realloc func(_ ?@mut anyopaque, memory ?*mut u8, old_size usize, new_size usize, alignment usize) ?*mut u8 { if power_of_two(alignment) == false { return null } @@ -131,11 +131,11 @@ hide c_realloc func(_ ?@mut anyopaque, memory ?*mut u8, old_size usize, new_size return c_alloc(null, new_size, alignment) } -hide c_free func(_ ?*mut anyopaque, memory ?*mut u8, _ usize, _ usize) void { +@hide c_free func(_ ?@mut anyopaque, memory ?*mut u8, _ usize, _ usize) void { c.free(memory) } -hide c_vtable AllocatorVTable :: AllocatorVTable { +@hide c_vtable AllocatorVTable :: AllocatorVTable { alloc = c_alloc, realloc = c_realloc, free = c_free,