| author | |
| committer | |
| log | 47be64af5add5c146541c16dbb043ddf97f97d34 |
| tree | 3fabcb50c94b254a71cdbf009f29ad1ece6b1f67 |
| parent | 4556f448060b19492d7b104ff01585241ba9c256 |
| parent | f7670882aff5fb3a943057edd9da34d053b5fe59 |
221 files changed, 5224 insertions(+), 5546 deletions(-)
README.md-10| ... | ... | @@ -5,8 +5,6 @@ clarity. |
| 5 | 5 | |
| 6 | 6 | [ziglang.org](http://ziglang.org) |
| 7 | 7 | |
| 8 | [Documentation](http://ziglang.org/documentation/master/) | |
| 9 | ||
| 10 | 8 | ## Feature Highlights |
| 11 | 9 | |
| 12 | 10 | * Small, simple language. Focus on debugging your application rather than |
| ... | ... | @@ -200,11 +198,3 @@ This is the actual compiler binary that we will install to the system. |
| 200 | 198 | ``` |
| 201 | 199 | ./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast |
| 202 | 200 | ``` |
| 203 | ||
| 204 | ### Related Projects | |
| 205 | ||
| 206 | * [zig-mode](https://github.com/AndreaOrru/zig-mode) - Emacs integration | |
| 207 | * [zig.vim](https://github.com/zig-lang/zig.vim) - Vim configuration files | |
| 208 | * [vscode-zig](https://github.com/zig-lang/vscode-zig) - Visual Studio Code extension | |
| 209 | * [zig-compiler-completions](https://github.com/tiehuis/zig-compiler-completions) - bash and zsh completions for the zig compiler | |
| 210 | * [NppExtension](https://github.com/ice1000/NppExtension) - Notepad++ syntax highlighting |
build.zig+9-8| ... | ... | @@ -10,7 +10,7 @@ const ArrayList = std.ArrayList; |
| 10 | 10 | const Buffer = std.Buffer; |
| 11 | 11 | const io = std.io; |
| 12 | 12 | |
| 13 | pub fn build(b: &Builder) -> %void { | |
| 13 | pub fn build(b: &Builder) %void { | |
| 14 | 14 | const mode = b.standardReleaseOptions(); |
| 15 | 15 | |
| 16 | 16 | var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig"); |
| ... | ... | @@ -116,11 +116,12 @@ pub fn build(b: &Builder) -> %void { |
| 116 | 116 | test_step.dependOn(tests.addBuildExampleTests(b, test_filter)); |
| 117 | 117 | test_step.dependOn(tests.addCompileErrorTests(b, test_filter)); |
| 118 | 118 | test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter)); |
| 119 | test_step.dependOn(tests.addDebugSafetyTests(b, test_filter)); | |
| 119 | test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter)); | |
| 120 | 120 | test_step.dependOn(tests.addTranslateCTests(b, test_filter)); |
| 121 | test_step.dependOn(tests.addGenHTests(b, test_filter)); | |
| 121 | 122 | } |
| 122 | 123 | |
| 123 | fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) { | |
| 124 | fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) void { | |
| 124 | 125 | for (dep.libdirs.toSliceConst()) |lib_dir| { |
| 125 | 126 | lib_exe_obj.addLibPath(lib_dir); |
| 126 | 127 | } |
| ... | ... | @@ -135,7 +136,7 @@ fn dependOnLib(lib_exe_obj: &std.build.LibExeObjStep, dep: &const LibraryDep) { |
| 135 | 136 | } |
| 136 | 137 | } |
| 137 | 138 | |
| 138 | fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) { | |
| 139 | fn addCppLib(b: &Builder, lib_exe_obj: &std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) void { | |
| 139 | 140 | const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib"; |
| 140 | 141 | lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", |
| 141 | 142 | b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable); |
| ... | ... | @@ -148,7 +149,7 @@ const LibraryDep = struct { |
| 148 | 149 | includes: ArrayList([]const u8), |
| 149 | 150 | }; |
| 150 | 151 | |
| 151 | fn findLLVM(b: &Builder, llvm_config_exe: []const u8) -> %LibraryDep { | |
| 152 | fn findLLVM(b: &Builder, llvm_config_exe: []const u8) %LibraryDep { | |
| 152 | 153 | const libs_output = try b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"}); |
| 153 | 154 | const includes_output = try b.exec([][]const u8{llvm_config_exe, "--includedir"}); |
| 154 | 155 | const libdir_output = try b.exec([][]const u8{llvm_config_exe, "--libdir"}); |
| ... | ... | @@ -196,7 +197,7 @@ fn findLLVM(b: &Builder, llvm_config_exe: []const u8) -> %LibraryDep { |
| 196 | 197 | return result; |
| 197 | 198 | } |
| 198 | 199 | |
| 199 | pub fn installStdLib(b: &Builder, stdlib_files: []const u8) { | |
| 200 | pub fn installStdLib(b: &Builder, stdlib_files: []const u8) void { | |
| 200 | 201 | var it = mem.split(stdlib_files, ";"); |
| 201 | 202 | while (it.next()) |stdlib_file| { |
| 202 | 203 | const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable; |
| ... | ... | @@ -205,7 +206,7 @@ pub fn installStdLib(b: &Builder, stdlib_files: []const u8) { |
| 205 | 206 | } |
| 206 | 207 | } |
| 207 | 208 | |
| 208 | pub fn installCHeaders(b: &Builder, c_header_files: []const u8) { | |
| 209 | pub fn installCHeaders(b: &Builder, c_header_files: []const u8) void { | |
| 209 | 210 | var it = mem.split(c_header_files, ";"); |
| 210 | 211 | while (it.next()) |c_header_file| { |
| 211 | 212 | const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable; |
| ... | ... | @@ -214,7 +215,7 @@ pub fn installCHeaders(b: &Builder, c_header_files: []const u8) { |
| 214 | 215 | } |
| 215 | 216 | } |
| 216 | 217 | |
| 217 | fn nextValue(index: &usize, build_info: []const u8) -> []const u8 { | |
| 218 | fn nextValue(index: &usize, build_info: []const u8) []const u8 { | |
| 218 | 219 | const start = *index; |
| 219 | 220 | while (true) : (*index += 1) { |
| 220 | 221 | switch (build_info[*index]) { |
ci/appveyor/after_build.bat+1| ... | ... | @@ -8,6 +8,7 @@ SET "RELEASEDIR=zig-%ZIGVERSION%" |
| 8 | 8 | mkdir "%RELEASEDIR%" |
| 9 | 9 | move build-msvc-release\bin\zig.exe "%RELEASEDIR%" |
| 10 | 10 | move build-msvc-release\lib "%RELEASEDIR%" |
| 11 | move zig-cache\langref.html "%RELEASEDIR%" | |
| 11 | 12 | |
| 12 | 13 | SET "RELEASEZIP=zig-%ZIGVERSION%.zip" |
| 13 | 14 |
doc/docgen.zig+490-59| ... | ... | @@ -1,14 +1,18 @@ |
| 1 | const builtin = @import("builtin"); | |
| 1 | 2 | const std = @import("std"); |
| 2 | 3 | const io = std.io; |
| 3 | 4 | const os = std.os; |
| 4 | 5 | const warn = std.debug.warn; |
| 5 | 6 | const mem = std.mem; |
| 7 | const assert = std.debug.assert; | |
| 6 | 8 | |
| 7 | 9 | const max_doc_file_size = 10 * 1024 * 1024; |
| 8 | 10 | |
| 9 | 11 | const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt(); |
| 12 | const obj_ext = std.build.Target(std.build.Target.Native).oFileExt(); | |
| 13 | const tmp_dir_name = "docgen_tmp"; | |
| 10 | 14 | |
| 11 | pub fn main() -> %void { | |
| 15 | pub fn main() %void { | |
| 12 | 16 | // TODO use a more general purpose allocator here |
| 13 | 17 | var inc_allocator = try std.heap.IncrementingAllocator.init(max_doc_file_size); |
| 14 | 18 | defer inc_allocator.deinit(); |
| ... | ... | @@ -43,6 +47,15 @@ pub fn main() -> %void { |
| 43 | 47 | var tokenizer = Tokenizer.init(in_file_name, input_file_bytes); |
| 44 | 48 | var toc = try genToc(allocator, &tokenizer); |
| 45 | 49 | |
| 50 | try os.makePath(allocator, tmp_dir_name); | |
| 51 | defer { | |
| 52 | // TODO issue #709 | |
| 53 | // disabled to pass CI tests, but obviously we want to implement this | |
| 54 | // and then remove this workaround | |
| 55 | if (builtin.os == builtin.Os.linux) { | |
| 56 | os.deleteTree(allocator, tmp_dir_name) catch {}; | |
| 57 | } | |
| 58 | } | |
| 46 | 59 | try genHtml(allocator, &tokenizer, &toc, &buffered_out_stream.stream, zig_exe); |
| 47 | 60 | try buffered_out_stream.flush(); |
| 48 | 61 | } |
| ... | ... | @@ -68,6 +81,7 @@ const Tokenizer = struct { |
| 68 | 81 | index: usize, |
| 69 | 82 | state: State, |
| 70 | 83 | source_file_name: []const u8, |
| 84 | code_node_count: usize, | |
| 71 | 85 | |
| 72 | 86 | const State = enum { |
| 73 | 87 | Start, |
| ... | ... | @@ -77,16 +91,17 @@ const Tokenizer = struct { |
| 77 | 91 | Eof, |
| 78 | 92 | }; |
| 79 | 93 | |
| 80 | fn init(source_file_name: []const u8, buffer: []const u8) -> Tokenizer { | |
| 94 | fn init(source_file_name: []const u8, buffer: []const u8) Tokenizer { | |
| 81 | 95 | return Tokenizer { |
| 82 | 96 | .buffer = buffer, |
| 83 | 97 | .index = 0, |
| 84 | 98 | .state = State.Start, |
| 85 | 99 | .source_file_name = source_file_name, |
| 100 | .code_node_count = 0, | |
| 86 | 101 | }; |
| 87 | 102 | } |
| 88 | 103 | |
| 89 | fn next(self: &Tokenizer) -> Token { | |
| 104 | fn next(self: &Tokenizer) Token { | |
| 90 | 105 | var result = Token { |
| 91 | 106 | .id = Token.Id.Eof, |
| 92 | 107 | .start = self.index, |
| ... | ... | @@ -178,7 +193,7 @@ const Tokenizer = struct { |
| 178 | 193 | line_end: usize, |
| 179 | 194 | }; |
| 180 | 195 | |
| 181 | fn getTokenLocation(self: &Tokenizer, token: &const Token) -> Location { | |
| 196 | fn getTokenLocation(self: &Tokenizer, token: &const Token) Location { | |
| 182 | 197 | var loc = Location { |
| 183 | 198 | .line = 0, |
| 184 | 199 | .column = 0, |
| ... | ... | @@ -205,7 +220,7 @@ const Tokenizer = struct { |
| 205 | 220 | |
| 206 | 221 | error ParseError; |
| 207 | 222 | |
| 208 | fn parseError(tokenizer: &Tokenizer, token: &const Token, comptime fmt: []const u8, args: ...) -> error { | |
| 223 | fn parseError(tokenizer: &Tokenizer, token: &const Token, comptime fmt: []const u8, args: ...) error { | |
| 209 | 224 | const loc = tokenizer.getTokenLocation(token); |
| 210 | 225 | warn("{}:{}:{}: error: " ++ fmt ++ "\n", tokenizer.source_file_name, loc.line + 1, loc.column + 1, args); |
| 211 | 226 | if (loc.line_start <= loc.line_end) { |
| ... | ... | @@ -228,13 +243,13 @@ fn parseError(tokenizer: &Tokenizer, token: &const Token, comptime fmt: []const |
| 228 | 243 | return error.ParseError; |
| 229 | 244 | } |
| 230 | 245 | |
| 231 | fn assertToken(tokenizer: &Tokenizer, token: &const Token, id: Token.Id) -> %void { | |
| 246 | fn assertToken(tokenizer: &Tokenizer, token: &const Token, id: Token.Id) %void { | |
| 232 | 247 | if (token.id != id) { |
| 233 | 248 | return parseError(tokenizer, token, "expected {}, found {}", @tagName(id), @tagName(token.id)); |
| 234 | 249 | } |
| 235 | 250 | } |
| 236 | 251 | |
| 237 | fn eatToken(tokenizer: &Tokenizer, id: Token.Id) -> %Token { | |
| 252 | fn eatToken(tokenizer: &Tokenizer, id: Token.Id) %Token { | |
| 238 | 253 | const token = tokenizer.next(); |
| 239 | 254 | try assertToken(tokenizer, token, id); |
| 240 | 255 | return token; |
| ... | ... | @@ -251,24 +266,43 @@ const SeeAlsoItem = struct { |
| 251 | 266 | token: Token, |
| 252 | 267 | }; |
| 253 | 268 | |
| 269 | const ExpectedOutcome = enum { | |
| 270 | Succeed, | |
| 271 | Fail, | |
| 272 | }; | |
| 273 | ||
| 254 | 274 | const Code = struct { |
| 255 | 275 | id: Id, |
| 256 | 276 | name: []const u8, |
| 257 | 277 | source_token: Token, |
| 278 | is_inline: bool, | |
| 279 | mode: builtin.Mode, | |
| 280 | link_objects: []const []const u8, | |
| 281 | target_windows: bool, | |
| 282 | link_libc: bool, | |
| 258 | 283 | |
| 259 | const Id = enum { | |
| 284 | const Id = union(enum) { | |
| 260 | 285 | Test, |
| 261 | Exe, | |
| 262 | Error, | |
| 286 | TestError: []const u8, | |
| 287 | TestSafety: []const u8, | |
| 288 | Exe: ExpectedOutcome, | |
| 289 | Obj: ?[]const u8, | |
| 263 | 290 | }; |
| 264 | 291 | }; |
| 265 | 292 | |
| 293 | const Link = struct { | |
| 294 | url: []const u8, | |
| 295 | name: []const u8, | |
| 296 | token: Token, | |
| 297 | }; | |
| 298 | ||
| 266 | 299 | const Node = union(enum) { |
| 267 | 300 | Content: []const u8, |
| 268 | 301 | Nav, |
| 269 | 302 | HeaderOpen: HeaderOpen, |
| 270 | 303 | SeeAlso: []const SeeAlsoItem, |
| 271 | 304 | Code: Code, |
| 305 | Link: Link, | |
| 272 | 306 | }; |
| 273 | 307 | |
| 274 | 308 | const Toc = struct { |
| ... | ... | @@ -282,9 +316,9 @@ const Action = enum { |
| 282 | 316 | Close, |
| 283 | 317 | }; |
| 284 | 318 | |
| 285 | fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc { | |
| 319 | fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) %Toc { | |
| 286 | 320 | var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator); |
| 287 | %defer urls.deinit(); | |
| 321 | errdefer urls.deinit(); | |
| 288 | 322 | |
| 289 | 323 | var header_stack_size: usize = 0; |
| 290 | 324 | var last_action = Action.Open; |
| ... | ... | @@ -365,7 +399,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc { |
| 365 | 399 | } |
| 366 | 400 | } else if (mem.eql(u8, tag_name, "see_also")) { |
| 367 | 401 | var list = std.ArrayList(SeeAlsoItem).init(allocator); |
| 368 | %defer list.deinit(); | |
| 402 | errdefer list.deinit(); | |
| 369 | 403 | |
| 370 | 404 | while (true) { |
| 371 | 405 | const see_also_tok = tokenizer.next(); |
| ... | ... | @@ -385,6 +419,31 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc { |
| 385 | 419 | else => return parseError(tokenizer, see_also_tok, "invalid see_also token"), |
| 386 | 420 | } |
| 387 | 421 | } |
| 422 | } else if (mem.eql(u8, tag_name, "link")) { | |
| 423 | _ = try eatToken(tokenizer, Token.Id.Separator); | |
| 424 | const name_tok = try eatToken(tokenizer, Token.Id.TagContent); | |
| 425 | const name = tokenizer.buffer[name_tok.start..name_tok.end]; | |
| 426 | ||
| 427 | const url_name = blk: { | |
| 428 | const tok = tokenizer.next(); | |
| 429 | switch (tok.id) { | |
| 430 | Token.Id.BracketClose => break :blk name, | |
| 431 | Token.Id.Separator => { | |
| 432 | const explicit_text = try eatToken(tokenizer, Token.Id.TagContent); | |
| 433 | _ = try eatToken(tokenizer, Token.Id.BracketClose); | |
| 434 | break :blk tokenizer.buffer[explicit_text.start..explicit_text.end]; | |
| 435 | }, | |
| 436 | else => return parseError(tokenizer, tok, "invalid link token"), | |
| 437 | } | |
| 438 | }; | |
| 439 | ||
| 440 | try nodes.append(Node { | |
| 441 | .Link = Link { | |
| 442 | .url = try urlize(allocator, url_name), | |
| 443 | .name = name, | |
| 444 | .token = name_tok, | |
| 445 | }, | |
| 446 | }); | |
| 388 | 447 | } else if (mem.eql(u8, tag_name, "code_begin")) { |
| 389 | 448 | _ = try eatToken(tokenizer, Token.Id.Separator); |
| 390 | 449 | const code_kind_tok = try eatToken(tokenizer, Token.Id.TagContent); |
| ... | ... | @@ -401,28 +460,71 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc { |
| 401 | 460 | } |
| 402 | 461 | const code_kind_str = tokenizer.buffer[code_kind_tok.start..code_kind_tok.end]; |
| 403 | 462 | var code_kind_id: Code.Id = undefined; |
| 463 | var is_inline = false; | |
| 404 | 464 | if (mem.eql(u8, code_kind_str, "exe")) { |
| 405 | code_kind_id = Code.Id.Exe; | |
| 465 | code_kind_id = Code.Id { .Exe = ExpectedOutcome.Succeed }; | |
| 466 | } else if (mem.eql(u8, code_kind_str, "exe_err")) { | |
| 467 | code_kind_id = Code.Id { .Exe = ExpectedOutcome.Fail }; | |
| 406 | 468 | } else if (mem.eql(u8, code_kind_str, "test")) { |
| 407 | 469 | code_kind_id = Code.Id.Test; |
| 408 | } else if (mem.eql(u8, code_kind_str, "error")) { | |
| 409 | code_kind_id = Code.Id.Error; | |
| 470 | } else if (mem.eql(u8, code_kind_str, "test_err")) { | |
| 471 | code_kind_id = Code.Id { .TestError = name}; | |
| 472 | name = "test"; | |
| 473 | } else if (mem.eql(u8, code_kind_str, "test_safety")) { | |
| 474 | code_kind_id = Code.Id { .TestSafety = name}; | |
| 475 | name = "test"; | |
| 476 | } else if (mem.eql(u8, code_kind_str, "obj")) { | |
| 477 | code_kind_id = Code.Id { .Obj = null }; | |
| 478 | } else if (mem.eql(u8, code_kind_str, "obj_err")) { | |
| 479 | code_kind_id = Code.Id { .Obj = name }; | |
| 480 | name = "test"; | |
| 481 | } else if (mem.eql(u8, code_kind_str, "syntax")) { | |
| 482 | code_kind_id = Code.Id { .Obj = null }; | |
| 483 | is_inline = true; | |
| 410 | 484 | } else { |
| 411 | 485 | return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {}", code_kind_str); |
| 412 | 486 | } |
| 413 | const source_token = try eatToken(tokenizer, Token.Id.Content); | |
| 414 | _ = try eatToken(tokenizer, Token.Id.BracketOpen); | |
| 415 | const end_code_tag = try eatToken(tokenizer, Token.Id.TagContent); | |
| 416 | const end_tag_name = tokenizer.buffer[end_code_tag.start..end_code_tag.end]; | |
| 417 | if (!mem.eql(u8, end_tag_name, "code_end")) { | |
| 418 | return parseError(tokenizer, end_code_tag, "expected code_end token"); | |
| 419 | } | |
| 420 | _ = try eatToken(tokenizer, Token.Id.BracketClose); | |
| 421 | try nodes.append(Node {.Code = Code{ | |
| 487 | ||
| 488 | var mode = builtin.Mode.Debug; | |
| 489 | var link_objects = std.ArrayList([]const u8).init(allocator); | |
| 490 | defer link_objects.deinit(); | |
| 491 | var target_windows = false; | |
| 492 | var link_libc = false; | |
| 493 | ||
| 494 | const source_token = while (true) { | |
| 495 | const content_tok = try eatToken(tokenizer, Token.Id.Content); | |
| 496 | _ = try eatToken(tokenizer, Token.Id.BracketOpen); | |
| 497 | const end_code_tag = try eatToken(tokenizer, Token.Id.TagContent); | |
| 498 | const end_tag_name = tokenizer.buffer[end_code_tag.start..end_code_tag.end]; | |
| 499 | if (mem.eql(u8, end_tag_name, "code_release_fast")) { | |
| 500 | mode = builtin.Mode.ReleaseFast; | |
| 501 | } else if (mem.eql(u8, end_tag_name, "code_link_object")) { | |
| 502 | _ = try eatToken(tokenizer, Token.Id.Separator); | |
| 503 | const obj_tok = try eatToken(tokenizer, Token.Id.TagContent); | |
| 504 | try link_objects.append(tokenizer.buffer[obj_tok.start..obj_tok.end]); | |
| 505 | } else if (mem.eql(u8, end_tag_name, "target_windows")) { | |
| 506 | target_windows = true; | |
| 507 | } else if (mem.eql(u8, end_tag_name, "link_libc")) { | |
| 508 | link_libc = true; | |
| 509 | } else if (mem.eql(u8, end_tag_name, "code_end")) { | |
| 510 | _ = try eatToken(tokenizer, Token.Id.BracketClose); | |
| 511 | break content_tok; | |
| 512 | } else { | |
| 513 | return parseError(tokenizer, end_code_tag, "invalid token inside code_begin: {}", end_tag_name); | |
| 514 | } | |
| 515 | _ = try eatToken(tokenizer, Token.Id.BracketClose); | |
| 516 | } else unreachable; // TODO issue #707 | |
| 517 | try nodes.append(Node {.Code = Code { | |
| 422 | 518 | .id = code_kind_id, |
| 423 | 519 | .name = name, |
| 424 | 520 | .source_token = source_token, |
| 521 | .is_inline = is_inline, | |
| 522 | .mode = mode, | |
| 523 | .link_objects = link_objects.toOwnedSlice(), | |
| 524 | .target_windows = target_windows, | |
| 525 | .link_libc = link_libc, | |
| 425 | 526 | }}); |
| 527 | tokenizer.code_node_count += 1; | |
| 426 | 528 | } else { |
| 427 | 529 | return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name); |
| 428 | 530 | } |
| ... | ... | @@ -438,7 +540,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc { |
| 438 | 540 | }; |
| 439 | 541 | } |
| 440 | 542 | |
| 441 | fn urlize(allocator: &mem.Allocator, input: []const u8) -> %[]u8 { | |
| 543 | fn urlize(allocator: &mem.Allocator, input: []const u8) %[]u8 { | |
| 442 | 544 | var buf = try std.Buffer.initSize(allocator, 0); |
| 443 | 545 | defer buf.deinit(); |
| 444 | 546 | |
| ... | ... | @@ -458,7 +560,7 @@ fn urlize(allocator: &mem.Allocator, input: []const u8) -> %[]u8 { |
| 458 | 560 | return buf.toOwnedSlice(); |
| 459 | 561 | } |
| 460 | 562 | |
| 461 | fn escapeHtml(allocator: &mem.Allocator, input: []const u8) -> %[]u8 { | |
| 563 | fn escapeHtml(allocator: &mem.Allocator, input: []const u8) %[]u8 { | |
| 462 | 564 | var buf = try std.Buffer.initSize(allocator, 0); |
| 463 | 565 | defer buf.deinit(); |
| 464 | 566 | |
| ... | ... | @@ -476,14 +578,127 @@ fn escapeHtml(allocator: &mem.Allocator, input: []const u8) -> %[]u8 { |
| 476 | 578 | return buf.toOwnedSlice(); |
| 477 | 579 | } |
| 478 | 580 | |
| 581 | //#define VT_RED "\x1b[31;1m" | |
| 582 | //#define VT_GREEN "\x1b[32;1m" | |
| 583 | //#define VT_CYAN "\x1b[36;1m" | |
| 584 | //#define VT_WHITE "\x1b[37;1m" | |
| 585 | //#define VT_BOLD "\x1b[0;1m" | |
| 586 | //#define VT_RESET "\x1b[0m" | |
| 587 | ||
| 588 | const TermState = enum { | |
| 589 | Start, | |
| 590 | Escape, | |
| 591 | LBracket, | |
| 592 | Number, | |
| 593 | AfterNumber, | |
| 594 | Arg, | |
| 595 | ArgNumber, | |
| 596 | ExpectEnd, | |
| 597 | }; | |
| 598 | ||
| 599 | error UnsupportedEscape; | |
| 600 | ||
| 601 | test "term color" { | |
| 602 | const input_bytes = "A\x1b[32;1mgreen\x1b[0mB"; | |
| 603 | const result = try termColor(std.debug.global_allocator, input_bytes); | |
| 604 | assert(mem.eql(u8, result, "A<span class=\"t32\">green</span>B")); | |
| 605 | } | |
| 606 | ||
| 607 | fn termColor(allocator: &mem.Allocator, input: []const u8) %[]u8 { | |
| 608 | var buf = try std.Buffer.initSize(allocator, 0); | |
| 609 | defer buf.deinit(); | |
| 610 | ||
| 611 | var buf_adapter = io.BufferOutStream.init(&buf); | |
| 612 | var out = &buf_adapter.stream; | |
| 613 | var number_start_index: usize = undefined; | |
| 614 | var first_number: usize = undefined; | |
| 615 | var second_number: usize = undefined; | |
| 616 | var i: usize = 0; | |
| 617 | var state = TermState.Start; | |
| 618 | var open_span_count: usize = 0; | |
| 619 | while (i < input.len) : (i += 1) { | |
| 620 | const c = input[i]; | |
| 621 | switch (state) { | |
| 622 | TermState.Start => switch (c) { | |
| 623 | '\x1b' => state = TermState.Escape, | |
| 624 | else => try out.writeByte(c), | |
| 625 | }, | |
| 626 | TermState.Escape => switch (c) { | |
| 627 | '[' => state = TermState.LBracket, | |
| 628 | else => return error.UnsupportedEscape, | |
| 629 | }, | |
| 630 | TermState.LBracket => switch (c) { | |
| 631 | '0'...'9' => { | |
| 632 | number_start_index = i; | |
| 633 | state = TermState.Number; | |
| 634 | }, | |
| 635 | else => return error.UnsupportedEscape, | |
| 636 | }, | |
| 637 | TermState.Number => switch (c) { | |
| 638 | '0'...'9' => {}, | |
| 639 | else => { | |
| 640 | first_number = std.fmt.parseInt(usize, input[number_start_index..i], 10) catch unreachable; | |
| 641 | second_number = 0; | |
| 642 | state = TermState.AfterNumber; | |
| 643 | i -= 1; | |
| 644 | }, | |
| 645 | }, | |
| 646 | ||
| 647 | TermState.AfterNumber => switch (c) { | |
| 648 | ';' => state = TermState.Arg, | |
| 649 | else => { | |
| 650 | state = TermState.ExpectEnd; | |
| 651 | i -= 1; | |
| 652 | }, | |
| 653 | }, | |
| 654 | TermState.Arg => switch (c) { | |
| 655 | '0'...'9' => { | |
| 656 | number_start_index = i; | |
| 657 | state = TermState.ArgNumber; | |
| 658 | }, | |
| 659 | else => return error.UnsupportedEscape, | |
| 660 | }, | |
| 661 | TermState.ArgNumber => switch (c) { | |
| 662 | '0'...'9' => {}, | |
| 663 | else => { | |
| 664 | second_number = std.fmt.parseInt(usize, input[number_start_index..i], 10) catch unreachable; | |
| 665 | state = TermState.ExpectEnd; | |
| 666 | i -= 1; | |
| 667 | }, | |
| 668 | }, | |
| 669 | TermState.ExpectEnd => switch (c) { | |
| 670 | 'm' => { | |
| 671 | state = TermState.Start; | |
| 672 | while (open_span_count != 0) : (open_span_count -= 1) { | |
| 673 | try out.write("</span>"); | |
| 674 | } | |
| 675 | if (first_number != 0 or second_number != 0) { | |
| 676 | try out.print("<span class=\"t{}_{}\">", first_number, second_number); | |
| 677 | open_span_count += 1; | |
| 678 | } | |
| 679 | }, | |
| 680 | else => return error.UnsupportedEscape, | |
| 681 | }, | |
| 682 | } | |
| 683 | } | |
| 684 | return buf.toOwnedSlice(); | |
| 685 | } | |
| 686 | ||
| 479 | 687 | error ExampleFailedToCompile; |
| 480 | 688 | |
| 481 | fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: &io.OutStream, zig_exe: []const u8) -> %void { | |
| 689 | fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: &io.OutStream, zig_exe: []const u8) %void { | |
| 690 | var code_progress_index: usize = 0; | |
| 482 | 691 | for (toc.nodes) |node| { |
| 483 | 692 | switch (node) { |
| 484 | 693 | Node.Content => |data| { |
| 485 | 694 | try out.write(data); |
| 486 | 695 | }, |
| 696 | Node.Link => |info| { | |
| 697 | if (!toc.urls.contains(info.url)) { | |
| 698 | return parseError(tokenizer, info.token, "url not found: {}", info.url); | |
| 699 | } | |
| 700 | try out.print("<a href=\"#{}\">{}</a>", info.url, info.name); | |
| 701 | }, | |
| 487 | 702 | Node.Nav => { |
| 488 | 703 | try out.write(toc.toc); |
| 489 | 704 | }, |
| ... | ... | @@ -502,65 +717,281 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: &io |
| 502 | 717 | try out.write("</ul>\n"); |
| 503 | 718 | }, |
| 504 | 719 | Node.Code => |code| { |
| 720 | code_progress_index += 1; | |
| 721 | warn("docgen example code {}/{}...", code_progress_index, tokenizer.code_node_count); | |
| 722 | ||
| 505 | 723 | const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end]; |
| 506 | 724 | const trimmed_raw_source = mem.trim(u8, raw_source, " \n"); |
| 507 | 725 | const escaped_source = try escapeHtml(allocator, trimmed_raw_source); |
| 726 | if (!code.is_inline) { | |
| 727 | try out.print("<p class=\"file\">{}.zig</p>", code.name); | |
| 728 | } | |
| 508 | 729 | try out.print("<pre><code class=\"zig\">{}</code></pre>", escaped_source); |
| 509 | const tmp_dir_name = "docgen_tmp"; | |
| 510 | try os.makePath(allocator, tmp_dir_name); | |
| 511 | 730 | const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name); |
| 512 | const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext); | |
| 513 | 731 | const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext); |
| 514 | const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext); | |
| 515 | 732 | try io.writeFile(tmp_source_file_name, trimmed_raw_source, null); |
| 516 | 733 | |
| 517 | 734 | switch (code.id) { |
| 518 | Code.Id.Exe => { | |
| 519 | { | |
| 520 | const args = [][]const u8 {zig_exe, "build-exe", tmp_source_file_name, "--output", tmp_bin_file_name}; | |
| 521 | const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size); | |
| 735 | Code.Id.Exe => |expected_outcome| { | |
| 736 | const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext); | |
| 737 | const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext); | |
| 738 | var build_args = std.ArrayList([]const u8).init(allocator); | |
| 739 | defer build_args.deinit(); | |
| 740 | try build_args.appendSlice([][]const u8 {zig_exe, | |
| 741 | "build-exe", tmp_source_file_name, | |
| 742 | "--output", tmp_bin_file_name, | |
| 743 | }); | |
| 744 | try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name); | |
| 745 | switch (code.mode) { | |
| 746 | builtin.Mode.Debug => {}, | |
| 747 | builtin.Mode.ReleaseSafe => { | |
| 748 | try build_args.append("--release-safe"); | |
| 749 | try out.print(" --release-safe"); | |
| 750 | }, | |
| 751 | builtin.Mode.ReleaseFast => { | |
| 752 | try build_args.append("--release-fast"); | |
| 753 | try out.print(" --release-fast"); | |
| 754 | }, | |
| 755 | } | |
| 756 | for (code.link_objects) |link_object| { | |
| 757 | const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext); | |
| 758 | const full_path_object = try os.path.join(allocator, tmp_dir_name, name_with_ext); | |
| 759 | try build_args.append("--object"); | |
| 760 | try build_args.append(full_path_object); | |
| 761 | try out.print(" --object {}", name_with_ext); | |
| 762 | } | |
| 763 | if (code.link_libc) { | |
| 764 | try build_args.append("--library"); | |
| 765 | try build_args.append("c"); | |
| 766 | try out.print(" --library c"); | |
| 767 | } | |
| 768 | _ = exec(allocator, build_args.toSliceConst()) catch return parseError( | |
| 769 | tokenizer, code.source_token, "example failed to compile"); | |
| 770 | ||
| 771 | const run_args = [][]const u8 {tmp_bin_file_name}; | |
| 772 | ||
| 773 | const result = if (expected_outcome == ExpectedOutcome.Fail) blk: { | |
| 774 | const result = try os.ChildProcess.exec(allocator, run_args, null, null, max_doc_file_size); | |
| 522 | 775 | switch (result.term) { |
| 523 | 776 | os.ChildProcess.Term.Exited => |exit_code| { |
| 524 | if (exit_code != 0) { | |
| 525 | warn("{}\nThe following command exited with code {}:\n", result.stderr, exit_code); | |
| 526 | for (args) |arg| warn("{} ", arg) else warn("\n"); | |
| 527 | return parseError(tokenizer, code.source_token, "example failed to compile"); | |
| 777 | if (exit_code == 0) { | |
| 778 | warn("{}\nThe following command incorrectly succeeded:\n", result.stderr); | |
| 779 | for (run_args) |arg| warn("{} ", arg) else warn("\n"); | |
| 780 | return parseError(tokenizer, code.source_token, "example incorrectly compiled"); | |
| 528 | 781 | } |
| 529 | 782 | }, |
| 530 | else => { | |
| 531 | warn("{}\nThe following command crashed:\n", result.stderr); | |
| 532 | for (args) |arg| warn("{} ", arg) else warn("\n"); | |
| 533 | return parseError(tokenizer, code.source_token, "example failed to compile"); | |
| 534 | }, | |
| 783 | else => {}, | |
| 535 | 784 | } |
| 785 | break :blk result; | |
| 786 | } else blk: { | |
| 787 | break :blk exec(allocator, run_args) catch return parseError( | |
| 788 | tokenizer, code.source_token, "example crashed"); | |
| 789 | }; | |
| 790 | ||
| 791 | ||
| 792 | const escaped_stderr = try escapeHtml(allocator, result.stderr); | |
| 793 | const escaped_stdout = try escapeHtml(allocator, result.stdout); | |
| 794 | ||
| 795 | const colored_stderr = try termColor(allocator, escaped_stderr); | |
| 796 | const colored_stdout = try termColor(allocator, escaped_stdout); | |
| 797 | ||
| 798 | try out.print("\n$ ./{}\n{}{}</code></pre>\n", code.name, colored_stdout, colored_stderr); | |
| 799 | }, | |
| 800 | Code.Id.Test => { | |
| 801 | var test_args = std.ArrayList([]const u8).init(allocator); | |
| 802 | defer test_args.deinit(); | |
| 803 | ||
| 804 | try test_args.appendSlice([][]const u8 {zig_exe, "test", tmp_source_file_name}); | |
| 805 | try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name); | |
| 806 | switch (code.mode) { | |
| 807 | builtin.Mode.Debug => {}, | |
| 808 | builtin.Mode.ReleaseSafe => { | |
| 809 | try test_args.append("--release-safe"); | |
| 810 | try out.print(" --release-safe"); | |
| 811 | }, | |
| 812 | builtin.Mode.ReleaseFast => { | |
| 813 | try test_args.append("--release-fast"); | |
| 814 | try out.print(" --release-fast"); | |
| 815 | }, | |
| 816 | } | |
| 817 | if (code.target_windows) { | |
| 818 | try test_args.appendSlice([][]const u8{ | |
| 819 | "--target-os", "windows", | |
| 820 | "--target-arch", "x86_64", | |
| 821 | "--target-environ", "msvc", | |
| 822 | }); | |
| 823 | } | |
| 824 | const result = exec(allocator, test_args.toSliceConst()) catch return parseError( | |
| 825 | tokenizer, code.source_token, "test failed"); | |
| 826 | const escaped_stderr = try escapeHtml(allocator, result.stderr); | |
| 827 | const escaped_stdout = try escapeHtml(allocator, result.stdout); | |
| 828 | try out.print("\n{}{}</code></pre>\n", escaped_stderr, escaped_stdout); | |
| 829 | }, | |
| 830 | Code.Id.TestError => |error_match| { | |
| 831 | var test_args = std.ArrayList([]const u8).init(allocator); | |
| 832 | defer test_args.deinit(); | |
| 833 | ||
| 834 | try test_args.appendSlice([][]const u8 {zig_exe, "test", "--color", "on", tmp_source_file_name}); | |
| 835 | try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name); | |
| 836 | switch (code.mode) { | |
| 837 | builtin.Mode.Debug => {}, | |
| 838 | builtin.Mode.ReleaseSafe => { | |
| 839 | try test_args.append("--release-safe"); | |
| 840 | try out.print(" --release-safe"); | |
| 841 | }, | |
| 842 | builtin.Mode.ReleaseFast => { | |
| 843 | try test_args.append("--release-fast"); | |
| 844 | try out.print(" --release-fast"); | |
| 845 | }, | |
| 536 | 846 | } |
| 537 | const args = [][]const u8 {tmp_bin_file_name}; | |
| 538 | const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size); | |
| 847 | const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, null, max_doc_file_size); | |
| 539 | 848 | switch (result.term) { |
| 540 | 849 | os.ChildProcess.Term.Exited => |exit_code| { |
| 541 | if (exit_code != 0) { | |
| 542 | warn("The following command exited with code {}:\n", exit_code); | |
| 543 | for (args) |arg| warn("{} ", arg) else warn("\n"); | |
| 544 | return parseError(tokenizer, code.source_token, "example exited with code {}", exit_code); | |
| 850 | if (exit_code == 0) { | |
| 851 | warn("{}\nThe following command incorrectly succeeded:\n", result.stderr); | |
| 852 | for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n"); | |
| 853 | return parseError(tokenizer, code.source_token, "example incorrectly compiled"); | |
| 545 | 854 | } |
| 546 | 855 | }, |
| 547 | 856 | else => { |
| 548 | warn("The following command crashed:\n"); | |
| 549 | for (args) |arg| warn("{} ", arg) else warn("\n"); | |
| 550 | return parseError(tokenizer, code.source_token, "example crashed"); | |
| 857 | warn("{}\nThe following command crashed:\n", result.stderr); | |
| 858 | for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n"); | |
| 859 | return parseError(tokenizer, code.source_token, "example compile crashed"); | |
| 551 | 860 | }, |
| 552 | 861 | } |
| 553 | try out.print("<pre><code class=\"sh\">$ zig build-exe {}.zig\n$ ./{}\n{}{}</code></pre>\n", code.name, code.name, result.stderr, result.stdout); | |
| 862 | if (mem.indexOf(u8, result.stderr, error_match) == null) { | |
| 863 | warn("{}\nExpected to find '{}' in stderr", result.stderr, error_match); | |
| 864 | return parseError(tokenizer, code.source_token, "example did not have expected compile error"); | |
| 865 | } | |
| 866 | const escaped_stderr = try escapeHtml(allocator, result.stderr); | |
| 867 | const colored_stderr = try termColor(allocator, escaped_stderr); | |
| 868 | try out.print("\n{}</code></pre>\n", colored_stderr); | |
| 554 | 869 | }, |
| 555 | Code.Id.Test => { | |
| 556 | @panic("TODO"); | |
| 870 | ||
| 871 | Code.Id.TestSafety => |error_match| { | |
| 872 | var test_args = std.ArrayList([]const u8).init(allocator); | |
| 873 | defer test_args.deinit(); | |
| 874 | ||
| 875 | try test_args.appendSlice([][]const u8 {zig_exe, "test", tmp_source_file_name}); | |
| 876 | switch (code.mode) { | |
| 877 | builtin.Mode.Debug => {}, | |
| 878 | builtin.Mode.ReleaseSafe => try test_args.append("--release-safe"), | |
| 879 | builtin.Mode.ReleaseFast => try test_args.append("--release-fast"), | |
| 880 | } | |
| 881 | ||
| 882 | const result = try os.ChildProcess.exec(allocator, test_args.toSliceConst(), null, null, max_doc_file_size); | |
| 883 | switch (result.term) { | |
| 884 | os.ChildProcess.Term.Exited => |exit_code| { | |
| 885 | if (exit_code == 0) { | |
| 886 | warn("{}\nThe following command incorrectly succeeded:\n", result.stderr); | |
| 887 | for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n"); | |
| 888 | return parseError(tokenizer, code.source_token, "example test incorrectly succeeded"); | |
| 889 | } | |
| 890 | }, | |
| 891 | else => { | |
| 892 | warn("{}\nThe following command crashed:\n", result.stderr); | |
| 893 | for (test_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n"); | |
| 894 | return parseError(tokenizer, code.source_token, "example compile crashed"); | |
| 895 | }, | |
| 896 | } | |
| 897 | if (mem.indexOf(u8, result.stderr, error_match) == null) { | |
| 898 | warn("{}\nExpected to find '{}' in stderr", result.stderr, error_match); | |
| 899 | return parseError(tokenizer, code.source_token, "example did not have expected runtime safety error message"); | |
| 900 | } | |
| 901 | const escaped_stderr = try escapeHtml(allocator, result.stderr); | |
| 902 | const colored_stderr = try termColor(allocator, escaped_stderr); | |
| 903 | try out.print("<pre><code class=\"shell\">$ zig test {}.zig\n{}</code></pre>\n", code.name, colored_stderr); | |
| 557 | 904 | }, |
| 558 | Code.Id.Error => { | |
| 559 | @panic("TODO"); | |
| 905 | Code.Id.Obj => |maybe_error_match| { | |
| 906 | const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext); | |
| 907 | const tmp_obj_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_obj_ext); | |
| 908 | var build_args = std.ArrayList([]const u8).init(allocator); | |
| 909 | defer build_args.deinit(); | |
| 910 | ||
| 911 | try build_args.appendSlice([][]const u8 {zig_exe, "build-obj", tmp_source_file_name, | |
| 912 | "--color", "on", | |
| 913 | "--output", tmp_obj_file_name}); | |
| 914 | ||
| 915 | if (!code.is_inline) { | |
| 916 | try out.print("<pre><code class=\"shell\">$ zig build-obj {}.zig", code.name); | |
| 917 | } | |
| 918 | ||
| 919 | switch (code.mode) { | |
| 920 | builtin.Mode.Debug => {}, | |
| 921 | builtin.Mode.ReleaseSafe => { | |
| 922 | try build_args.append("--release-safe"); | |
| 923 | if (!code.is_inline) { | |
| 924 | try out.print(" --release-safe"); | |
| 925 | } | |
| 926 | }, | |
| 927 | builtin.Mode.ReleaseFast => { | |
| 928 | try build_args.append("--release-fast"); | |
| 929 | if (!code.is_inline) { | |
| 930 | try out.print(" --release-fast"); | |
| 931 | } | |
| 932 | }, | |
| 933 | } | |
| 934 | ||
| 935 | if (maybe_error_match) |error_match| { | |
| 936 | const result = try os.ChildProcess.exec(allocator, build_args.toSliceConst(), null, null, max_doc_file_size); | |
| 937 | switch (result.term) { | |
| 938 | os.ChildProcess.Term.Exited => |exit_code| { | |
| 939 | if (exit_code == 0) { | |
| 940 | warn("{}\nThe following command incorrectly succeeded:\n", result.stderr); | |
| 941 | for (build_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n"); | |
| 942 | return parseError(tokenizer, code.source_token, "example build incorrectly succeeded"); | |
| 943 | } | |
| 944 | }, | |
| 945 | else => { | |
| 946 | warn("{}\nThe following command crashed:\n", result.stderr); | |
| 947 | for (build_args.toSliceConst()) |arg| warn("{} ", arg) else warn("\n"); | |
| 948 | return parseError(tokenizer, code.source_token, "example compile crashed"); | |
| 949 | }, | |
| 950 | } | |
| 951 | if (mem.indexOf(u8, result.stderr, error_match) == null) { | |
| 952 | warn("{}\nExpected to find '{}' in stderr", result.stderr, error_match); | |
| 953 | return parseError(tokenizer, code.source_token, "example did not have expected compile error message"); | |
| 954 | } | |
| 955 | const escaped_stderr = try escapeHtml(allocator, result.stderr); | |
| 956 | const colored_stderr = try termColor(allocator, escaped_stderr); | |
| 957 | try out.print("\n{}\n", colored_stderr); | |
| 958 | if (!code.is_inline) { | |
| 959 | try out.print("</code></pre>\n"); | |
| 960 | } | |
| 961 | } else { | |
| 962 | _ = exec(allocator, build_args.toSliceConst()) catch return parseError( | |
| 963 | tokenizer, code.source_token, "example failed to compile"); | |
| 964 | } | |
| 965 | if (!code.is_inline) { | |
| 966 | try out.print("</code></pre>\n"); | |
| 967 | } | |
| 560 | 968 | }, |
| 561 | 969 | } |
| 970 | warn("OK\n"); | |
| 562 | 971 | }, |
| 563 | 972 | } |
| 564 | 973 | } |
| 565 | 974 | |
| 566 | 975 | } |
| 976 | ||
| 977 | error ChildCrashed; | |
| 978 | error ChildExitError; | |
| 979 | ||
| 980 | fn exec(allocator: &mem.Allocator, args: []const []const u8) %os.ChildProcess.ExecResult { | |
| 981 | const result = try os.ChildProcess.exec(allocator, args, null, null, max_doc_file_size); | |
| 982 | switch (result.term) { | |
| 983 | os.ChildProcess.Term.Exited => |exit_code| { | |
| 984 | if (exit_code != 0) { | |
| 985 | warn("{}\nThe following command exited with code {}:\n", result.stderr, exit_code); | |
| 986 | for (args) |arg| warn("{} ", arg) else warn("\n"); | |
| 987 | return error.ChildExitError; | |
| 988 | } | |
| 989 | }, | |
| 990 | else => { | |
| 991 | warn("{}\nThe following command crashed:\n", result.stderr); | |
| 992 | for (args) |arg| warn("{} ", arg) else warn("\n"); | |
| 993 | return error.ChildCrashed; | |
| 994 | }, | |
| 995 | } | |
| 996 | return result; | |
| 997 | } |
doc/langref.html.in+1134-1028| ... | ... | @@ -4,7 +4,9 @@ |
| 4 | 4 | <meta charset="utf-8"> |
| 5 | 5 | <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> |
| 6 | 6 | <title>Documentation - The Zig Programming Language</title> |
| 7 | <link rel="stylesheet" type="text/css" href="highlight/styles/default.css"> | |
| 7 | <style type="text/css"> | |
| 8 | .hljs{display:block;overflow-x:auto;padding:0.5em;color:#333;background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:bold}.hljs-number,.hljs-literal,.hljs-variable,.hljs-template-variable,.hljs-tag .hljs-attr{color:#008080}.hljs-string,.hljs-doctag{color:#d14}.hljs-title,.hljs-section,.hljs-selector-id{color:#900;font-weight:bold}.hljs-subst{font-weight:normal}.hljs-type,.hljs-class .hljs-title{color:#458;font-weight:bold}.hljs-tag,.hljs-name,.hljs-attribute{color:#000080;font-weight:normal}.hljs-regexp,.hljs-link{color:#009926}.hljs-symbol,.hljs-bullet{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:bold}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold} | |
| 9 | </style> | |
| 8 | 10 | <style type="text/css"> |
| 9 | 11 | table, th, td { |
| 10 | 12 | border-collapse: collapse; |
| ... | ... | @@ -13,6 +15,27 @@ |
| 13 | 15 | th, td { |
| 14 | 16 | padding: 0.1em; |
| 15 | 17 | } |
| 18 | .t0_1, .t37, .t37_1 { | |
| 19 | font-weight: bold; | |
| 20 | } | |
| 21 | .t2_0 { | |
| 22 | color: grey; | |
| 23 | } | |
| 24 | .t31_1 { | |
| 25 | color: red; | |
| 26 | } | |
| 27 | .t32_1 { | |
| 28 | color: green; | |
| 29 | } | |
| 30 | .t36_1 { | |
| 31 | color: #0086b3; | |
| 32 | } | |
| 33 | .file { | |
| 34 | text-decoration: underline; | |
| 35 | } | |
| 36 | code { | |
| 37 | font-size: 12pt; | |
| 38 | } | |
| 16 | 39 | @media screen and (min-width: 28.75em) { |
| 17 | 40 | #nav { |
| 18 | 41 | width: 20em; |
| ... | ... | @@ -53,13 +76,17 @@ |
| 53 | 76 | If you search for something specific in this documentation and do not find it, |
| 54 | 77 | please <a href="https://github.com/zig-lang/www.ziglang.org/issues/new?title=I%20searched%20for%20___%20in%20the%20docs%20and%20didn%27t%20find%20it">file an issue</a> or <a href="https://webchat.freenode.net/?channels=%23zig">say something on IRC</a>. |
| 55 | 78 | </p> |
| 79 | <p> | |
| 80 | The code samples in this document are compiled and tested as part of the main test suite of Zig. | |
| 81 | This HTML document depends on no external files, so you can use it offline. | |
| 82 | </p> | |
| 56 | 83 | {#header_close#} |
| 57 | 84 | {#header_open|Hello World#} |
| 58 | 85 | |
| 59 | 86 | {#code_begin|exe|hello#} |
| 60 | 87 | const std = @import("std"); |
| 61 | 88 | |
| 62 | pub fn main() -> %void { | |
| 89 | pub fn main() %void { | |
| 63 | 90 | // If this program is run without stdout attached, exit with an error. |
| 64 | 91 | var stdout_file = try std.io.getStdOut(); |
| 65 | 92 | // If this program encounters pipe failure when printing to stdout, exit |
| ... | ... | @@ -75,10 +102,14 @@ pub fn main() -> %void { |
| 75 | 102 | {#code_begin|exe|hello#} |
| 76 | 103 | const warn = @import("std").debug.warn; |
| 77 | 104 | |
| 78 | pub fn main() -> %void { | |
| 105 | pub fn main() void { | |
| 79 | 106 | warn("Hello, world!\n"); |
| 80 | 107 | } |
| 81 | 108 | {#code_end#} |
| 109 | <p> | |
| 110 | Note that we also left off the <code class="zig">%</code> from the return type. | |
| 111 | In Zig, if your main function cannot fail, you may use the <code class="zig">void</code> return type. | |
| 112 | </p> | |
| 82 | 113 | {#see_also|Values|@import|Errors|Root Source File#} |
| 83 | 114 | {#header_close#} |
| 84 | 115 | {#header_open|Source Encoding#} |
| ... | ... | @@ -101,7 +132,7 @@ const assert = std.debug.assert; |
| 101 | 132 | // error declaration, makes `error.ArgNotFound` available |
| 102 | 133 | error ArgNotFound; |
| 103 | 134 | |
| 104 | pub fn main() -> %void { | |
| 135 | pub fn main() %void { | |
| 105 | 136 | // integers |
| 106 | 137 | const one_plus_one: i32 = 1 + 1; |
| 107 | 138 | warn("1 + 1 = {}\n", one_plus_one); |
| ... | ... | @@ -354,7 +385,7 @@ pub fn main() -> %void { |
| 354 | 385 | <tr> |
| 355 | 386 | <td><code>noreturn</code></td> |
| 356 | 387 | <td>(none)</td> |
| 357 | <td>the type of <code>break</code>, <code>continue</code>, <code>goto</code>, <code>return</code>, <code>unreachable</code>, and <code>while (true) {}</code></td> | |
| 388 | <td>the type of <code>break</code>, <code>continue</code>, <code>return</code>, <code>unreachable</code>, and <code>while (true) {}</code></td> | |
| 358 | 389 | </tr> |
| 359 | 390 | <tr> |
| 360 | 391 | <td><code>type</code></td> |
| ... | ... | @@ -399,7 +430,8 @@ pub fn main() -> %void { |
| 399 | 430 | {#see_also|Nullables|this#} |
| 400 | 431 | {#header_close#} |
| 401 | 432 | {#header_open|String Literals#} |
| 402 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 433 | {#code_begin|test#} | |
| 434 | const assert = @import("std").debug.assert; | |
| 403 | 435 | const mem = @import("std").mem; |
| 404 | 436 | |
| 405 | 437 | test "string literals" { |
| ... | ... | @@ -413,11 +445,10 @@ test "string literals" { |
| 413 | 445 | |
| 414 | 446 | // A C string literal is a null terminated pointer. |
| 415 | 447 | const null_terminated_bytes = c"hello"; |
| 416 | assert(@typeOf(null_terminated_bytes) == &amp;const u8); | |
| 448 | assert(@typeOf(null_terminated_bytes) == &const u8); | |
| 417 | 449 | assert(null_terminated_bytes[5] == 0); |
| 418 | }</code></pre> | |
| 419 | <pre><code class="sh">$ zig test string_literals.zig | |
| 420 | Test 1/1 string literals...OK</code></pre> | |
| 450 | } | |
| 451 | {#code_end#} | |
| 421 | 452 | {#see_also|Arrays|Zig Test#} |
| 422 | 453 | {#header_open|Escape Sequences#} |
| 423 | 454 | <table> |
| ... | ... | @@ -477,25 +508,29 @@ Test 1/1 string literals...OK</code></pre> |
| 477 | 508 | However, if the next line begins with <code>\\</code> then a newline is appended and |
| 478 | 509 | the string literal continues. |
| 479 | 510 | </p> |
| 480 | <pre><code class="zig">const hello_world_in_c = | |
| 481 | \\#include &lt;stdio.h&gt; | |
| 511 | {#code_begin|syntax#} | |
| 512 | const hello_world_in_c = | |
| 513 | \\#include <stdio.h> | |
| 482 | 514 | \\ |
| 483 | 515 | \\int main(int argc, char **argv) { |
| 484 | 516 | \\ printf("hello world\n"); |
| 485 | 517 | \\ return 0; |
| 486 | 518 | \\} |
| 487 | ;</code></pre> | |
| 519 | ; | |
| 520 | {#code_end#} | |
| 488 | 521 | <p> |
| 489 | 522 | For a multiline C string literal, prepend <code>c</code> to each <code>\\</code>: |
| 490 | 523 | </p> |
| 491 | <pre><code class="zig">const c_string_literal = | |
| 492 | c\\#include &lt;stdio.h&gt; | |
| 524 | {#code_begin|syntax#} | |
| 525 | const c_string_literal = | |
| 526 | c\\#include <stdio.h> | |
| 493 | 527 | c\\ |
| 494 | 528 | c\\int main(int argc, char **argv) { |
| 495 | 529 | c\\ printf("hello world\n"); |
| 496 | 530 | c\\ return 0; |
| 497 | 531 | c\\} |
| 498 | ;</code></pre> | |
| 532 | ; | |
| 533 | {#code_end#} | |
| 499 | 534 | <p> |
| 500 | 535 | In this example the variable <code>c_string_literal</code> has type <code>&amp;const char</code> and |
| 501 | 536 | has a terminating null byte. |
| ... | ... | @@ -505,9 +540,10 @@ Test 1/1 string literals...OK</code></pre> |
| 505 | 540 | {#header_close#} |
| 506 | 541 | {#header_open|Assignment#} |
| 507 | 542 | <p>Use <code>const</code> to assign a value to an identifier:</p> |
| 508 | <pre><code class="zig">const x = 1234; | |
| 543 | {#code_begin|test_err|cannot assign to constant#} | |
| 544 | const x = 1234; | |
| 509 | 545 | |
| 510 | fn foo() { | |
| 546 | fn foo() void { | |
| 511 | 547 | // It works at global scope as well as inside functions. |
| 512 | 548 | const y = 5678; |
| 513 | 549 | |
| ... | ... | @@ -517,13 +553,11 @@ fn foo() { |
| 517 | 553 | |
| 518 | 554 | test "assignment" { |
| 519 | 555 | foo(); |
| 520 | }</code></pre> | |
| 521 | <pre><code class="sh">$ zig test test.zig | |
| 522 | test.zig:8:7: error: cannot assign to constant | |
| 523 | y += 1; | |
| 524 | ^</code></pre> | |
| 556 | } | |
| 557 | {#code_end#} | |
| 525 | 558 | <p>If you need a variable that you can modify, use <code>var</code>:</p> |
| 526 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 559 | {#code_begin|test#} | |
| 560 | const assert = @import("std").debug.assert; | |
| 527 | 561 | |
| 528 | 562 | test "var" { |
| 529 | 563 | var y: i32 = 5678; |
| ... | ... | @@ -531,38 +565,37 @@ test "var" { |
| 531 | 565 | y += 1; |
| 532 | 566 | |
| 533 | 567 | assert(y == 5679); |
| 534 | }</code></pre> | |
| 535 | <pre><code class="sh">$ zig test test.zig | |
| 536 | Test 1/1 assignment...OK</code></pre> | |
| 568 | } | |
| 569 | {#code_end#} | |
| 537 | 570 | <p>Variables must be initialized:</p> |
| 538 | <pre><code class="zig">test "initialization" { | |
| 571 | {#code_begin|test_err#} | |
| 572 | test "initialization" { | |
| 539 | 573 | var x: i32; |
| 540 | 574 | |
| 541 | 575 | x = 1; |
| 542 | }</code></pre> | |
| 543 | <pre><code class="sh">$ zig test test.zig | |
| 544 | test.zig:3:5: error: variables must be initialized | |
| 545 | var x: i32; | |
| 546 | ^</code></pre> | |
| 576 | } | |
| 577 | {#code_end#} | |
| 547 | 578 | <p>Use <code>undefined</code> to leave variables uninitialized:</p> |
| 548 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 579 | {#code_begin|test#} | |
| 580 | const assert = @import("std").debug.assert; | |
| 549 | 581 | |
| 550 | 582 | test "init with undefined" { |
| 551 | 583 | var x: i32 = undefined; |
| 552 | 584 | x = 1; |
| 553 | 585 | assert(x == 1); |
| 554 | }</code></pre> | |
| 555 | <pre><code class="sh">$ zig test test.zig | |
| 556 | Test 1/1 init with undefined...OK</code></pre> | |
| 586 | } | |
| 587 | {#code_end#} | |
| 557 | 588 | {#header_close#} |
| 558 | 589 | {#header_close#} |
| 559 | 590 | {#header_open|Integers#} |
| 560 | 591 | {#header_open|Integer Literals#} |
| 561 | <pre><code class="zig">const decimal_int = 98222; | |
| 592 | {#code_begin|syntax#} | |
| 593 | const decimal_int = 98222; | |
| 562 | 594 | const hex_int = 0xff; |
| 563 | 595 | const another_hex_int = 0xFF; |
| 564 | 596 | const octal_int = 0o755; |
| 565 | const binary_int = 0b11110000;</code></pre> | |
| 597 | const binary_int = 0b11110000; | |
| 598 | {#code_end#} | |
| 566 | 599 | {#header_close#} |
| 567 | 600 | {#header_open|Runtime Integer Values#} |
| 568 | 601 | <p> |
| ... | ... | @@ -573,9 +606,11 @@ const binary_int = 0b11110000;</code></pre> |
| 573 | 606 | However, once an integer value is no longer known at compile-time, it must have a |
| 574 | 607 | known size, and is vulnerable to undefined behavior. |
| 575 | 608 | </p> |
| 576 | <pre><code class="zig">fn divide(a: i32, b: i32) -&gt; i32 { | |
| 609 | {#code_begin|syntax#} | |
| 610 | fn divide(a: i32, b: i32) i32 { | |
| 577 | 611 | return a / b; |
| 578 | }</code></pre> | |
| 612 | } | |
| 613 | {#code_end#} | |
| 579 | 614 | <p> |
| 580 | 615 | In this function, values <code>a</code> and <code>b</code> are known only at runtime, |
| 581 | 616 | and thus this division operation is vulnerable to both integer overflow and |
| ... | ... | @@ -590,52 +625,53 @@ const binary_int = 0b11110000;</code></pre> |
| 590 | 625 | {#header_close#} |
| 591 | 626 | {#header_close#} |
| 592 | 627 | {#header_open|Floats#} |
| 593 | {#header_close#} | |
| 594 | 628 | {#header_open|Float Literals#} |
| 595 | <pre><code class="zig">const floating_point = 123.0E+77; | |
| 629 | {#code_begin|syntax#} | |
| 630 | const floating_point = 123.0E+77; | |
| 596 | 631 | const another_float = 123.0; |
| 597 | 632 | const yet_another = 123.0e+77; |
| 598 | 633 | |
| 599 | 634 | const hex_floating_point = 0x103.70p-5; |
| 600 | 635 | const another_hex_float = 0x103.70; |
| 601 | const yet_another_hex_float = 0x103.70P-5;</code></pre> | |
| 636 | const yet_another_hex_float = 0x103.70P-5; | |
| 637 | {#code_end#} | |
| 602 | 638 | {#header_close#} |
| 603 | 639 | {#header_open|Floating Point Operations#} |
| 604 | 640 | <p>By default floating point operations use <code>Optimized</code> mode, |
| 605 | 641 | but you can switch to <code>Strict</code> mode on a per-block basis:</p> |
| 606 | <p>foo.zig</p> | |
| 607 | <pre><code class="zig">const builtin = @import("builtin"); | |
| 608 | const big = f64(1 &lt;&lt; 40); | |
| 642 | {#code_begin|obj|foo#} | |
| 643 | {#code_release_fast#} | |
| 644 | const builtin = @import("builtin"); | |
| 645 | const big = f64(1 << 40); | |
| 609 | 646 | |
| 610 | export fn foo_strict(x: f64) -&gt; f64 { | |
| 647 | export fn foo_strict(x: f64) f64 { | |
| 611 | 648 | @setFloatMode(this, builtin.FloatMode.Strict); |
| 612 | 649 | return x + big - big; |
| 613 | 650 | } |
| 614 | 651 | |
| 615 | export fn foo_optimized(x: f64) -&gt; f64 { | |
| 652 | export fn foo_optimized(x: f64) f64 { | |
| 616 | 653 | return x + big - big; |
| 617 | }</code></pre> | |
| 618 | <p>test.zig</p> | |
| 619 | <pre><code class="zig">const warn = @import("std").debug.warn; | |
| 654 | } | |
| 655 | {#code_end#} | |
| 656 | <p>For this test we have to separate code into two object files - | |
| 657 | otherwise the optimizer figures out all the values at compile-time, | |
| 658 | which operates in strict mode.</p> | |
| 659 | {#code_begin|exe|float_mode#} | |
| 660 | {#code_link_object|foo#} | |
| 661 | const warn = @import("std").debug.warn; | |
| 620 | 662 | |
| 621 | extern fn foo_strict(x: f64) -&gt; f64; | |
| 622 | extern fn foo_optimized(x: f64) -&gt; f64; | |
| 663 | extern fn foo_strict(x: f64) f64; | |
| 664 | extern fn foo_optimized(x: f64) f64; | |
| 623 | 665 | |
| 624 | pub fn main() -&gt; %void { | |
| 666 | pub fn main() %void { | |
| 625 | 667 | const x = 0.001; |
| 626 | 668 | warn("optimized = {}\n", foo_optimized(x)); |
| 627 | 669 | warn("strict = {}\n", foo_strict(x)); |
| 628 | }</code></pre> | |
| 629 | <p>For this test we have to separate code into two object files - | |
| 630 | otherwise the optimizer figures out all the values at compile-time, | |
| 631 | which operates in strict mode.</p> | |
| 632 | <pre><code class="sh">$ zig build-obj foo.zig --release-fast | |
| 633 | $ zig build-exe test.zig --object foo.o | |
| 634 | $ ./test | |
| 635 | optimized = 1.0e-2 | |
| 636 | strict = 9.765625e-3</code></pre> | |
| 670 | } | |
| 671 | {#code_end#} | |
| 637 | 672 | {#see_also|@setFloatMode|Division by Zero#} |
| 638 | 673 | {#header_close#} |
| 674 | {#header_close#} | |
| 639 | 675 | {#header_open|Operators#} |
| 640 | 676 | {#header_open|Table of Operators#} |
| 641 | 677 | <table> |
| ... | ... | @@ -658,13 +694,13 @@ strict = 9.765625e-3</code></pre> |
| 658 | 694 | a += b</code></pre></td> |
| 659 | 695 | <td> |
| 660 | 696 | <ul> |
| 661 | <li><a href="#integers">Integers</a></li> | |
| 662 | <li><a href="#floats">Floats</a></li> | |
| 697 | <li>{#link|Integers#}</li> | |
| 698 | <li>{#link|Floats#}</li> | |
| 663 | 699 | </ul> |
| 664 | 700 | </td> |
| 665 | 701 | <td>Addition. |
| 666 | 702 | <ul> |
| 667 | <li>Can cause <a href="#undef-integer-overflow">overflow</a> for integers.</li> | |
| 703 | <li>Can cause {#link|overflow|Default Operations#} for integers.</li> | |
| 668 | 704 | </ul> |
| 669 | 705 | </td> |
| 670 | 706 | <td> |
| ... | ... | @@ -676,7 +712,7 @@ a += b</code></pre></td> |
| 676 | 712 | a +%= b</code></pre></td> |
| 677 | 713 | <td> |
| 678 | 714 | <ul> |
| 679 | <li><a href="#integers">Integers</a></li> | |
| 715 | <li>{#link|Integers#}</li> | |
| 680 | 716 | </ul> |
| 681 | 717 | </td> |
| 682 | 718 | <td>Wrapping Addition. |
| ... | ... | @@ -693,13 +729,13 @@ a +%= b</code></pre></td> |
| 693 | 729 | a -= b</code></pre></td> |
| 694 | 730 | <td> |
| 695 | 731 | <ul> |
| 696 | <li><a href="#integers">Integers</a></li> | |
| 697 | <li><a href="#floats">Floats</a></li> | |
| 732 | <li>{#link|Integers#}</li> | |
| 733 | <li>{#link|Floats#}</li> | |
| 698 | 734 | </ul> |
| 699 | 735 | </td> |
| 700 | 736 | <td>Subtraction. |
| 701 | 737 | <ul> |
| 702 | <li>Can cause <a href="#undef-integer-overflow">overflow</a> for integers.</li> | |
| 738 | <li>Can cause {#link|overflow|Default Operations#} for integers.</li> | |
| 703 | 739 | </ul> |
| 704 | 740 | </td> |
| 705 | 741 | <td> |
| ... | ... | @@ -711,7 +747,7 @@ a -= b</code></pre></td> |
| 711 | 747 | a -%= b</code></pre></td> |
| 712 | 748 | <td> |
| 713 | 749 | <ul> |
| 714 | <li><a href="#integers">Integers</a></li> | |
| 750 | <li>{#link|Integers#}</li> | |
| 715 | 751 | </ul> |
| 716 | 752 | </td> |
| 717 | 753 | <td>Wrapping Subtraction. |
| ... | ... | @@ -727,14 +763,14 @@ a -%= b</code></pre></td> |
| 727 | 763 | <td><pre><code class="zig">-a<code></pre></td> |
| 728 | 764 | <td> |
| 729 | 765 | <ul> |
| 730 | <li><a href="#integers">Integers</a></li> | |
| 731 | <li><a href="#floats">Floats</a></li> | |
| 766 | <li>{#link|Integers#}</li> | |
| 767 | <li>{#link|Floats#}</li> | |
| 732 | 768 | </ul> |
| 733 | 769 | </td> |
| 734 | 770 | <td> |
| 735 | 771 | Negation. |
| 736 | 772 | <ul> |
| 737 | <li>Can cause <a href="#undef-integer-overflow">overflow</a> for integers.</li> | |
| 773 | <li>Can cause {#link|overflow|Default Operations#} for integers.</li> | |
| 738 | 774 | </ul> |
| 739 | 775 | </td> |
| 740 | 776 | <td> |
| ... | ... | @@ -745,7 +781,7 @@ a -%= b</code></pre></td> |
| 745 | 781 | <td><pre><code class="zig">-%a<code></pre></td> |
| 746 | 782 | <td> |
| 747 | 783 | <ul> |
| 748 | <li><a href="#integers">Integers</a></li> | |
| 784 | <li>{#link|Integers#}</li> | |
| 749 | 785 | </ul> |
| 750 | 786 | </td> |
| 751 | 787 | <td> |
| ... | ... | @@ -763,13 +799,13 @@ a -%= b</code></pre></td> |
| 763 | 799 | a *= b</code></pre></td> |
| 764 | 800 | <td> |
| 765 | 801 | <ul> |
| 766 | <li><a href="#integers">Integers</a></li> | |
| 767 | <li><a href="#floats">Floats</a></li> | |
| 802 | <li>{#link|Integers#}</li> | |
| 803 | <li>{#link|Floats#}</li> | |
| 768 | 804 | </ul> |
| 769 | 805 | </td> |
| 770 | 806 | <td>Multiplication. |
| 771 | 807 | <ul> |
| 772 | <li>Can cause <a href="#undef-integer-overflow">overflow</a> for integers.</li> | |
| 808 | <li>Can cause {#link|overflow|Default Operations#} for integers.</li> | |
| 773 | 809 | </ul> |
| 774 | 810 | </td> |
| 775 | 811 | <td> |
| ... | ... | @@ -781,7 +817,7 @@ a *= b</code></pre></td> |
| 781 | 817 | a *%= b</code></pre></td> |
| 782 | 818 | <td> |
| 783 | 819 | <ul> |
| 784 | <li><a href="#integers">Integers</a></li> | |
| 820 | <li>{#link|Integers#}</li> | |
| 785 | 821 | </ul> |
| 786 | 822 | </td> |
| 787 | 823 | <td>Wrapping Multiplication. |
| ... | ... | @@ -798,19 +834,19 @@ a *%= b</code></pre></td> |
| 798 | 834 | a /= b</code></pre></td> |
| 799 | 835 | <td> |
| 800 | 836 | <ul> |
| 801 | <li><a href="#integers">Integers</a></li> | |
| 802 | <li><a href="#floats">Floats</a></li> | |
| 837 | <li>{#link|Integers#}</li> | |
| 838 | <li>{#link|Floats#}</li> | |
| 803 | 839 | </ul> |
| 804 | 840 | </td> |
| 805 | 841 | <td>Divison. |
| 806 | 842 | <ul> |
| 807 | <li>Can cause <a href="#undef-integer-overflow">overflow</a> for integers.</li> | |
| 808 | <li>Can cause <a href="#undef-division-by-zero">division by zero</a> for integers.</li> | |
| 809 | <li>Can cause <a href="#undef-division-by-zero">division by zero</a> for floats in <a href="#float-operations">FloatMode.Optimized Mode</a>.</li> | |
| 843 | <li>Can cause {#link|overflow|Default Operations#} for integers.</li> | |
| 844 | <li>Can cause {#link|Division by Zero#} for integers.</li> | |
| 845 | <li>Can cause {#link|Division by Zero#} for floats in {#link|FloatMode.Optimized Mode|Floating Point Operations#}.</li> | |
| 810 | 846 | <li>For non-compile-time-known signed integers, must use |
| 811 | <a href="#builtin-divTrunc">@divTrunc</a>, | |
| 812 | <a href="#builtin-divFloor">@divFloor</a>, or | |
| 813 | <a href="#builtin-divExact">@divExact</a> instead of <code>/</code>. | |
| 847 | {#link|@divTrunc#}, | |
| 848 | {#link|@divFloor#}, or | |
| 849 | {#link|@divExact#} instead of <code>/</code>. | |
| 814 | 850 | </li> |
| 815 | 851 | </ul> |
| 816 | 852 | </td> |
| ... | ... | @@ -823,17 +859,17 @@ a /= b</code></pre></td> |
| 823 | 859 | a %= b</code></pre></td> |
| 824 | 860 | <td> |
| 825 | 861 | <ul> |
| 826 | <li><a href="#integers">Integers</a></li> | |
| 827 | <li><a href="#floats">Floats</a></li> | |
| 862 | <li>{#link|Integers#}</li> | |
| 863 | <li>{#link|Floats#}</li> | |
| 828 | 864 | </ul> |
| 829 | 865 | </td> |
| 830 | 866 | <td>Remainder Division. |
| 831 | 867 | <ul> |
| 832 | <li>Can cause <a href="#undef-division-by-zero">division by zero</a> for integers.</li> | |
| 833 | <li>Can cause <a href="#undef-division-by-zero">division by zero</a> for floats in <a href="#float-operations">FloatMode.Optimized Mode</a>.</li> | |
| 868 | <li>Can cause {#link|Division by Zero#} for integers.</li> | |
| 869 | <li>Can cause {#link|Division by Zero#} for floats in {#link|FloatMode.Optimized Mode|Floating Point Operations#}.</li> | |
| 834 | 870 | <li>For non-compile-time-known signed integers, must use |
| 835 | <a href="#builtin-rem">@rem</a> or | |
| 836 | <a href="#builtin-mod">@mod</a> instead of <code>%</code>. | |
| 871 | {#link|@rem#} or | |
| 872 | {#link|@mod#} instead of <code>%</code>. | |
| 837 | 873 | </li> |
| 838 | 874 | </ul> |
| 839 | 875 | </td> |
| ... | ... | @@ -846,13 +882,13 @@ a %= b</code></pre></td> |
| 846 | 882 | a &lt;&lt;= b</code></pre></td> |
| 847 | 883 | <td> |
| 848 | 884 | <ul> |
| 849 | <li><a href="#integers">Integers</a></li> | |
| 885 | <li>{#link|Integers#}</li> | |
| 850 | 886 | </ul> |
| 851 | 887 | </td> |
| 852 | 888 | <td>Bit Shift Left. |
| 853 | 889 | <ul> |
| 854 | <li>See also <a href="#builtin-shlExact">@shlExact</a>.</li> | |
| 855 | <li>See also <a href="#builtin-shlWithOverflow">@shlWithOverflow</a>.</li> | |
| 890 | <li>See also {#link|@shlExact#}.</li> | |
| 891 | <li>See also {#link|@shlWithOverflow#}.</li> | |
| 856 | 892 | </ul> |
| 857 | 893 | </td> |
| 858 | 894 | <td> |
| ... | ... | @@ -864,12 +900,12 @@ a &lt;&lt;= b</code></pre></td> |
| 864 | 900 | a &gt;&gt;= b</code></pre></td> |
| 865 | 901 | <td> |
| 866 | 902 | <ul> |
| 867 | <li><a href="#integers">Integers</a></li> | |
| 903 | <li>{#link|Integers#}</li> | |
| 868 | 904 | </ul> |
| 869 | 905 | </td> |
| 870 | 906 | <td>Bit Shift Right. |
| 871 | 907 | <ul> |
| 872 | <li>See also <a href="#builtin-shrExact">@shrExact</a>.</li> | |
| 908 | <li>See also {#link|@shrExact#}.</li> | |
| 873 | 909 | </ul> |
| 874 | 910 | </td> |
| 875 | 911 | <td> |
| ... | ... | @@ -881,7 +917,7 @@ a &gt;&gt;= b</code></pre></td> |
| 881 | 917 | a &amp;= b</code></pre></td> |
| 882 | 918 | <td> |
| 883 | 919 | <ul> |
| 884 | <li><a href="#integers">Integers</a></li> | |
| 920 | <li>{#link|Integers#}</li> | |
| 885 | 921 | </ul> |
| 886 | 922 | </td> |
| 887 | 923 | <td>Bitwise AND. |
| ... | ... | @@ -895,7 +931,7 @@ a &amp;= b</code></pre></td> |
| 895 | 931 | a |= b</code></pre></td> |
| 896 | 932 | <td> |
| 897 | 933 | <ul> |
| 898 | <li><a href="#integers">Integers</a></li> | |
| 934 | <li>{#link|Integers#}</li> | |
| 899 | 935 | </ul> |
| 900 | 936 | </td> |
| 901 | 937 | <td>Bitwise OR. |
| ... | ... | @@ -909,7 +945,7 @@ a |= b</code></pre></td> |
| 909 | 945 | a ^= b</code></pre></td> |
| 910 | 946 | <td> |
| 911 | 947 | <ul> |
| 912 | <li><a href="#integers">Integers</a></li> | |
| 948 | <li>{#link|Integers#}</li> | |
| 913 | 949 | </ul> |
| 914 | 950 | </td> |
| 915 | 951 | <td>Bitwise XOR. |
| ... | ... | @@ -922,7 +958,7 @@ a ^= b</code></pre></td> |
| 922 | 958 | <td><pre><code class="zig">~a<code></pre></td> |
| 923 | 959 | <td> |
| 924 | 960 | <ul> |
| 925 | <li><a href="#integers">Integers</a></li> | |
| 961 | <li>{#link|Integers#}</li> | |
| 926 | 962 | </ul> |
| 927 | 963 | </td> |
| 928 | 964 | <td> |
| ... | ... | @@ -936,13 +972,13 @@ a ^= b</code></pre></td> |
| 936 | 972 | <td><pre><code class="zig">a ?? b</code></pre></td> |
| 937 | 973 | <td> |
| 938 | 974 | <ul> |
| 939 | <li><a href="#nullables">Nullables</a></li> | |
| 975 | <li>{#link|Nullables#}</li> | |
| 940 | 976 | </ul> |
| 941 | 977 | </td> |
| 942 | 978 | <td>If <code>a</code> is <code>null</code>, |
| 943 | 979 | returns <code>b</code> ("default value"), |
| 944 | 980 | otherwise returns the unwrapped value of <code>a</code>. |
| 945 | Note that <code>b</code> may be a value of type <a href="#noreturn">noreturn</a>. | |
| 981 | Note that <code>b</code> may be a value of type {#link|noreturn#}. | |
| 946 | 982 | </td> |
| 947 | 983 | <td> |
| 948 | 984 | <pre><code class="zig">const value: ?u32 = null; |
| ... | ... | @@ -954,7 +990,7 @@ unwrapped == 1234</code></pre> |
| 954 | 990 | <td><pre><code class="zig">??a</code></pre></td> |
| 955 | 991 | <td> |
| 956 | 992 | <ul> |
| 957 | <li><a href="#nullables">Nullables</a></li> | |
| 993 | <li>{#link|Nullables#}</li> | |
| 958 | 994 | </ul> |
| 959 | 995 | </td> |
| 960 | 996 | <td> |
| ... | ... | @@ -971,13 +1007,13 @@ unwrapped == 1234</code></pre> |
| 971 | 1007 | a catch |err| b</code></pre></td> |
| 972 | 1008 | <td> |
| 973 | 1009 | <ul> |
| 974 | <li><a href="#errors">Error Unions</a></li> | |
| 1010 | <li>{#link|Error Unions|Errors#}</li> | |
| 975 | 1011 | </ul> |
| 976 | 1012 | </td> |
| 977 | 1013 | <td>If <code>a</code> is an <code>error</code>, |
| 978 | 1014 | returns <code>b</code> ("default value"), |
| 979 | 1015 | otherwise returns the unwrapped value of <code>a</code>. |
| 980 | Note that <code>b</code> may be a value of type <a href="#noreturn">noreturn</a>. | |
| 1016 | Note that <code>b</code> may be a value of type {#link|noreturn#}. | |
| 981 | 1017 | <code>err</code> is the <code>error</code> and is in scope of the expression <code>b</code>. |
| 982 | 1018 | </td> |
| 983 | 1019 | <td> |
| ... | ... | @@ -986,26 +1022,11 @@ const unwrapped = value catch 1234; |
| 986 | 1022 | unwrapped == 1234</code></pre> |
| 987 | 1023 | </td> |
| 988 | 1024 | </tr> |
| 989 | <tr> | |
| 990 | <td><pre><code class="zig">%%a</code></pre></td> | |
| 991 | <td> | |
| 992 | <ul> | |
| 993 | <li><a href="#errors">Error Unions</a></li> | |
| 994 | </ul> | |
| 995 | </td> | |
| 996 | <td>Equivalent to: | |
| 997 | <pre><code class="zig">a catch unreachable</code></pre> | |
| 998 | </td> | |
| 999 | <td> | |
| 1000 | <pre><code class="zig">const value: %u32 = 5678; | |
| 1001 | %%value == 5678</code></pre> | |
| 1002 | </td> | |
| 1003 | </tr> | |
| 1004 | 1025 | <tr> |
| 1005 | 1026 | <td><pre><code class="zig">a and b<code></pre></td> |
| 1006 | 1027 | <td> |
| 1007 | 1028 | <ul> |
| 1008 | <li><a href="#primitive-types">bool</a></li> | |
| 1029 | <li>{#link|bool|Primitive Types#}</li> | |
| 1009 | 1030 | </ul> |
| 1010 | 1031 | </td> |
| 1011 | 1032 | <td> |
| ... | ... | @@ -1020,7 +1041,7 @@ unwrapped == 1234</code></pre> |
| 1020 | 1041 | <td><pre><code class="zig">a or b<code></pre></td> |
| 1021 | 1042 | <td> |
| 1022 | 1043 | <ul> |
| 1023 | <li><a href="#primitive-types">bool</a></li> | |
| 1044 | <li>{#link|bool|Primitive Types#}</li> | |
| 1024 | 1045 | </ul> |
| 1025 | 1046 | </td> |
| 1026 | 1047 | <td> |
| ... | ... | @@ -1035,7 +1056,7 @@ unwrapped == 1234</code></pre> |
| 1035 | 1056 | <td><pre><code class="zig">!a<code></pre></td> |
| 1036 | 1057 | <td> |
| 1037 | 1058 | <ul> |
| 1038 | <li><a href="#primitive-types">bool</a></li> | |
| 1059 | <li>{#link|bool|Primitive Types#}</li> | |
| 1039 | 1060 | </ul> |
| 1040 | 1061 | </td> |
| 1041 | 1062 | <td> |
| ... | ... | @@ -1049,10 +1070,10 @@ unwrapped == 1234</code></pre> |
| 1049 | 1070 | <td><pre><code class="zig">a == b<code></pre></td> |
| 1050 | 1071 | <td> |
| 1051 | 1072 | <ul> |
| 1052 | <li><a href="#integers">Integers</a></li> | |
| 1053 | <li><a href="#floats">Floats</a></li> | |
| 1054 | <li><a href="#primitive-types">bool</a></li> | |
| 1055 | <li><a href="#primitive-types">type</a></li> | |
| 1073 | <li>{#link|Integers#}</li> | |
| 1074 | <li>{#link|Floats#}</li> | |
| 1075 | <li>{#link|bool|Primitive Types#}</li> | |
| 1076 | <li>{#link|type|Primitive Types#}</li> | |
| 1056 | 1077 | </ul> |
| 1057 | 1078 | </td> |
| 1058 | 1079 | <td> |
| ... | ... | @@ -1066,7 +1087,7 @@ unwrapped == 1234</code></pre> |
| 1066 | 1087 | <td><pre><code class="zig">a == null<code></pre></td> |
| 1067 | 1088 | <td> |
| 1068 | 1089 | <ul> |
| 1069 | <li><a href="#nullables">Nullables</a></li> | |
| 1090 | <li>{#link|Nullables#}</li> | |
| 1070 | 1091 | </ul> |
| 1071 | 1092 | </td> |
| 1072 | 1093 | <td> |
| ... | ... | @@ -1081,10 +1102,10 @@ value == null</code></pre> |
| 1081 | 1102 | <td><pre><code class="zig">a != b<code></pre></td> |
| 1082 | 1103 | <td> |
| 1083 | 1104 | <ul> |
| 1084 | <li><a href="#integers">Integers</a></li> | |
| 1085 | <li><a href="#floats">Floats</a></li> | |
| 1086 | <li><a href="#primitive-types">bool</a></li> | |
| 1087 | <li><a href="#primitive-types">type</a></li> | |
| 1105 | <li>{#link|Integers#}</li> | |
| 1106 | <li>{#link|Floats#}</li> | |
| 1107 | <li>{#link|bool|Primitive Types#}</li> | |
| 1108 | <li>{#link|type|Primitive Types#}</li> | |
| 1088 | 1109 | </ul> |
| 1089 | 1110 | </td> |
| 1090 | 1111 | <td> |
| ... | ... | @@ -1098,8 +1119,8 @@ value == null</code></pre> |
| 1098 | 1119 | <td><pre><code class="zig">a &gt; b<code></pre></td> |
| 1099 | 1120 | <td> |
| 1100 | 1121 | <ul> |
| 1101 | <li><a href="#integers">Integers</a></li> | |
| 1102 | <li><a href="#floats">Floats</a></li> | |
| 1122 | <li>{#link|Integers#}</li> | |
| 1123 | <li>{#link|Floats#}</li> | |
| 1103 | 1124 | </ul> |
| 1104 | 1125 | </td> |
| 1105 | 1126 | <td> |
| ... | ... | @@ -1113,8 +1134,8 @@ value == null</code></pre> |
| 1113 | 1134 | <td><pre><code class="zig">a &gt;= b<code></pre></td> |
| 1114 | 1135 | <td> |
| 1115 | 1136 | <ul> |
| 1116 | <li><a href="#integers">Integers</a></li> | |
| 1117 | <li><a href="#floats">Floats</a></li> | |
| 1137 | <li>{#link|Integers#}</li> | |
| 1138 | <li>{#link|Floats#}</li> | |
| 1118 | 1139 | </ul> |
| 1119 | 1140 | </td> |
| 1120 | 1141 | <td> |
| ... | ... | @@ -1128,8 +1149,8 @@ value == null</code></pre> |
| 1128 | 1149 | <td><pre><code class="zig">a &lt; b<code></pre></td> |
| 1129 | 1150 | <td> |
| 1130 | 1151 | <ul> |
| 1131 | <li><a href="#integers">Integers</a></li> | |
| 1132 | <li><a href="#floats">Floats</a></li> | |
| 1152 | <li>{#link|Integers#}</li> | |
| 1153 | <li>{#link|Floats#}</li> | |
| 1133 | 1154 | </ul> |
| 1134 | 1155 | </td> |
| 1135 | 1156 | <td> |
| ... | ... | @@ -1143,8 +1164,8 @@ value == null</code></pre> |
| 1143 | 1164 | <td><pre><code class="zig">a &lt;= b<code></pre></td> |
| 1144 | 1165 | <td> |
| 1145 | 1166 | <ul> |
| 1146 | <li><a href="#integers">Integers</a></li> | |
| 1147 | <li><a href="#floats">Floats</a></li> | |
| 1167 | <li>{#link|Integers#}</li> | |
| 1168 | <li>{#link|Floats#}</li> | |
| 1148 | 1169 | </ul> |
| 1149 | 1170 | </td> |
| 1150 | 1171 | <td> |
| ... | ... | @@ -1158,13 +1179,13 @@ value == null</code></pre> |
| 1158 | 1179 | <td><pre><code class="zig">a ++ b<code></pre></td> |
| 1159 | 1180 | <td> |
| 1160 | 1181 | <ul> |
| 1161 | <li><a href="#arrays">Arrays</a></li> | |
| 1182 | <li>{#link|Arrays#}</li> | |
| 1162 | 1183 | </ul> |
| 1163 | 1184 | </td> |
| 1164 | 1185 | <td> |
| 1165 | 1186 | Array concatenation. |
| 1166 | 1187 | <ul> |
| 1167 | <li>Only available when <code>a</code> and <code>b</code> are <a href="#comptime">compile-time known</a>. | |
| 1188 | <li>Only available when <code>a</code> and <code>b</code> are {#link|compile-time known|comptime#}. | |
| 1168 | 1189 | </ul> |
| 1169 | 1190 | </td> |
| 1170 | 1191 | <td> |
| ... | ... | @@ -1179,13 +1200,13 @@ mem.eql(u32, together, []u32{1,2,3,4})</code></pre> |
| 1179 | 1200 | <td><pre><code class="zig">a ** b<code></pre></td> |
| 1180 | 1201 | <td> |
| 1181 | 1202 | <ul> |
| 1182 | <li><a href="#arrays">Arrays</a></li> | |
| 1203 | <li>{#link|Arrays#}</li> | |
| 1183 | 1204 | </ul> |
| 1184 | 1205 | </td> |
| 1185 | 1206 | <td> |
| 1186 | 1207 | Array multiplication. |
| 1187 | 1208 | <ul> |
| 1188 | <li>Only available when <code>a</code> and <code>b</code> are <a href="#comptime">compile-time known</a>. | |
| 1209 | <li>Only available when <code>a</code> and <code>b</code> are {#link|compile-time known|comptime#}. | |
| 1189 | 1210 | </ul> |
| 1190 | 1211 | </td> |
| 1191 | 1212 | <td> |
| ... | ... | @@ -1198,7 +1219,7 @@ mem.eql(u8, pattern, "ababab")</code></pre> |
| 1198 | 1219 | <td><pre><code class="zig">*a<code></pre></td> |
| 1199 | 1220 | <td> |
| 1200 | 1221 | <ul> |
| 1201 | <li><a href="#pointers">Pointers</a></li> | |
| 1222 | <li>{#link|Pointers#}</li> | |
| 1202 | 1223 | </ul> |
| 1203 | 1224 | </td> |
| 1204 | 1225 | <td> |
| ... | ... | @@ -1228,7 +1249,7 @@ const ptr = &amp;x; |
| 1228 | 1249 | {#header_close#} |
| 1229 | 1250 | {#header_open|Precedence#} |
| 1230 | 1251 | <pre><code>x() x[] x.y |
| 1231 | !x -x -%x ~x *x &amp;x ?x %x %%x ??x | |
| 1252 | !x -x -%x ~x *x &amp;x ?x %x ??x | |
| 1232 | 1253 | x{} |
| 1233 | 1254 | * / % ** *% |
| 1234 | 1255 | + - ++ +% -% |
| ... | ... | @@ -1244,7 +1265,8 @@ or |
| 1244 | 1265 | {#header_close#} |
| 1245 | 1266 | {#header_close#} |
| 1246 | 1267 | {#header_open|Arrays#} |
| 1247 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 1268 | {#code_begin|test|arrays#} | |
| 1269 | const assert = @import("std").debug.assert; | |
| 1248 | 1270 | const mem = @import("std").mem; |
| 1249 | 1271 | |
| 1250 | 1272 | // array literal |
| ... | ... | @@ -1314,7 +1336,7 @@ comptime { |
| 1314 | 1336 | } |
| 1315 | 1337 | |
| 1316 | 1338 | // use compile-time code to initialize an array |
| 1317 | var fancy_array = { | |
| 1339 | var fancy_array = init: { | |
| 1318 | 1340 | var initial_value: [10]Point = undefined; |
| 1319 | 1341 | for (initial_value) |*pt, i| { |
| 1320 | 1342 | *pt = Point { |
| ... | ... | @@ -1322,7 +1344,7 @@ var fancy_array = { |
| 1322 | 1344 | .y = i32(i) * 2, |
| 1323 | 1345 | }; |
| 1324 | 1346 | } |
| 1325 | initial_value | |
| 1347 | break :init initial_value; | |
| 1326 | 1348 | }; |
| 1327 | 1349 | const Point = struct { |
| 1328 | 1350 | x: i32, |
| ... | ... | @@ -1336,26 +1358,23 @@ test "compile-time array initalization" { |
| 1336 | 1358 | |
| 1337 | 1359 | // call a function to initialize an array |
| 1338 | 1360 | var more_points = []Point{makePoint(3)} ** 10; |
| 1339 | fn makePoint(x: i32) -&gt; Point { | |
| 1340 | Point { | |
| 1361 | fn makePoint(x: i32) Point { | |
| 1362 | return Point { | |
| 1341 | 1363 | .x = x, |
| 1342 | 1364 | .y = x * 2, |
| 1343 | } | |
| 1365 | }; | |
| 1344 | 1366 | } |
| 1345 | 1367 | test "array initialization with function calls" { |
| 1346 | 1368 | assert(more_points[4].x == 3); |
| 1347 | 1369 | assert(more_points[4].y == 6); |
| 1348 | 1370 | assert(more_points.len == 10); |
| 1349 | }</code></pre> | |
| 1350 | <pre><code class="sh">$ zig test arrays.zig | |
| 1351 | Test 1/4 iterate over an array...OK | |
| 1352 | Test 2/4 modify an array...OK | |
| 1353 | Test 3/4 compile-time array initalization...OK | |
| 1354 | Test 4/4 array initialization with function calls...OK</code></pre> | |
| 1371 | } | |
| 1372 | {#code_end#} | |
| 1355 | 1373 | {#see_also|for|Slices#} |
| 1356 | 1374 | {#header_close#} |
| 1357 | 1375 | {#header_open|Pointers#} |
| 1358 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 1376 | {#code_begin|test#} | |
| 1377 | const assert = @import("std").debug.assert; | |
| 1359 | 1378 | |
| 1360 | 1379 | test "address of syntax" { |
| 1361 | 1380 | // Get the address of a variable: |
| ... | ... | @@ -1366,12 +1385,12 @@ test "address of syntax" { |
| 1366 | 1385 | assert(*x_ptr == 1234); |
| 1367 | 1386 | |
| 1368 | 1387 | // When you get the address of a const variable, you get a const pointer. |
| 1369 | assert(@typeOf(x_ptr) == &amp;const i32); | |
| 1388 | assert(@typeOf(x_ptr) == &const i32); | |
| 1370 | 1389 | |
| 1371 | 1390 | // If you want to mutate the value, you'd need an address of a mutable variable: |
| 1372 | 1391 | var y: i32 = 5678; |
| 1373 | 1392 | const y_ptr = &y; |
| 1374 | assert(@typeOf(y_ptr) == &amp;i32); | |
| 1393 | assert(@typeOf(y_ptr) == &i32); | |
| 1375 | 1394 | *y_ptr += 1; |
| 1376 | 1395 | assert(*y_ptr == 5679); |
| 1377 | 1396 | } |
| ... | ... | @@ -1381,7 +1400,7 @@ test "pointer array access" { |
| 1381 | 1400 | // need such a thing, use array index syntax: |
| 1382 | 1401 | |
| 1383 | 1402 | var array = []u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; |
| 1384 | const ptr = &amp;array[1]; | |
| 1403 | const ptr = &array[1]; | |
| 1385 | 1404 | |
| 1386 | 1405 | assert(array[2] == 3); |
| 1387 | 1406 | ptr[1] += 1; |
| ... | ... | @@ -1392,10 +1411,10 @@ test "pointer slicing" { |
| 1392 | 1411 | // In Zig, we prefer using slices over null-terminated pointers. |
| 1393 | 1412 | // You can turn a pointer into a slice using slice syntax: |
| 1394 | 1413 | var array = []u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; |
| 1395 | const ptr = &amp;array[1]; | |
| 1414 | const ptr = &array[1]; | |
| 1396 | 1415 | const slice = ptr[1..3]; |
| 1397 | 1416 | |
| 1398 | assert(slice.ptr == &amp;ptr[1]); | |
| 1417 | assert(slice.ptr == &ptr[1]); | |
| 1399 | 1418 | assert(slice.len == 2); |
| 1400 | 1419 | |
| 1401 | 1420 | // Slices have bounds checking and are therefore protected |
| ... | ... | @@ -1410,7 +1429,7 @@ comptime { |
| 1410 | 1429 | // Pointers work at compile-time too, as long as you don't use |
| 1411 | 1430 | // @ptrCast. |
| 1412 | 1431 | var x: i32 = 1; |
| 1413 | const ptr = &amp;x; | |
| 1432 | const ptr = &x; | |
| 1414 | 1433 | *ptr += 1; |
| 1415 | 1434 | x += 1; |
| 1416 | 1435 | assert(*ptr == 3); |
| ... | ... | @@ -1418,7 +1437,7 @@ comptime { |
| 1418 | 1437 | |
| 1419 | 1438 | test "@ptrToInt and @intToPtr" { |
| 1420 | 1439 | // To convert an integer address into a pointer, use @intToPtr: |
| 1421 | const ptr = @intToPtr(&amp;i32, 0xdeadbeef); | |
| 1440 | const ptr = @intToPtr(&i32, 0xdeadbeef); | |
| 1422 | 1441 | |
| 1423 | 1442 | // To convert a pointer to an integer, use @ptrToInt: |
| 1424 | 1443 | const addr = @ptrToInt(ptr); |
| ... | ... | @@ -1430,7 +1449,7 @@ test "@ptrToInt and @intToPtr" { |
| 1430 | 1449 | comptime { |
| 1431 | 1450 | // Zig is able to do this at compile-time, as long as |
| 1432 | 1451 | // ptr is never dereferenced. |
| 1433 | const ptr = @intToPtr(&amp;i32, 0xdeadbeef); | |
| 1452 | const ptr = @intToPtr(&i32, 0xdeadbeef); | |
| 1434 | 1453 | const addr = @ptrToInt(ptr); |
| 1435 | 1454 | assert(@typeOf(addr) == usize); |
| 1436 | 1455 | assert(addr == 0xdeadbeef); |
| ... | ... | @@ -1440,34 +1459,34 @@ test "volatile" { |
| 1440 | 1459 | // In Zig, loads and stores are assumed to not have side effects. |
| 1441 | 1460 | // If a given load or store should have side effects, such as |
| 1442 | 1461 | // Memory Mapped Input/Output (MMIO), use `volatile`: |
| 1443 | const mmio_ptr = @intToPtr(&amp;volatile u8, 0x12345678); | |
| 1462 | const mmio_ptr = @intToPtr(&volatile u8, 0x12345678); | |
| 1444 | 1463 | |
| 1445 | 1464 | // Now loads and stores with mmio_ptr are guaranteed to all happen |
| 1446 | 1465 | // and in the same order as in source code. |
| 1447 | assert(@typeOf(mmio_ptr) == &amp;volatile u8); | |
| 1466 | assert(@typeOf(mmio_ptr) == &volatile u8); | |
| 1448 | 1467 | } |
| 1449 | 1468 | |
| 1450 | 1469 | test "nullable pointers" { |
| 1451 | 1470 | // Pointers cannot be null. If you want a null pointer, use the nullable |
| 1452 | 1471 | // prefix `?` to make the pointer type nullable. |
| 1453 | var ptr: ?&amp;i32 = null; | |
| 1472 | var ptr: ?&i32 = null; | |
| 1454 | 1473 | |
| 1455 | 1474 | var x: i32 = 1; |
| 1456 | ptr = &amp;x; | |
| 1475 | ptr = &x; | |
| 1457 | 1476 | |
| 1458 | 1477 | assert(*??ptr == 1); |
| 1459 | 1478 | |
| 1460 | 1479 | // Nullable pointers are the same size as normal pointers, because pointer |
| 1461 | 1480 | // value 0 is used as the null value. |
| 1462 | assert(@sizeOf(?&amp;i32) == @sizeOf(&amp;i32)); | |
| 1481 | assert(@sizeOf(?&i32) == @sizeOf(&i32)); | |
| 1463 | 1482 | } |
| 1464 | 1483 | |
| 1465 | 1484 | test "pointer casting" { |
| 1466 | 1485 | // To convert one pointer type to another, use @ptrCast. This is an unsafe |
| 1467 | 1486 | // operation that Zig cannot protect you against. Use @ptrCast only when other |
| 1468 | 1487 | // conversions are not possible. |
| 1469 | const bytes = []u8{0x12, 0x12, 0x12, 0x12}; | |
| 1470 | const u32_ptr = @ptrCast(&amp;const u32, &amp;bytes[0]); | |
| 1488 | const bytes align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12}; | |
| 1489 | const u32_ptr = @ptrCast(&const u32, &bytes[0]); | |
| 1471 | 1490 | assert(*u32_ptr == 0x12121212); |
| 1472 | 1491 | |
| 1473 | 1492 | // Even this example is contrived - there are better ways to do the above than |
| ... | ... | @@ -1481,23 +1500,15 @@ test "pointer casting" { |
| 1481 | 1500 | |
| 1482 | 1501 | test "pointer child type" { |
| 1483 | 1502 | // pointer types have a `child` field which tells you the type they point to. |
| 1484 | assert((&amp;u32).child == u32); | |
| 1485 | }</code></pre> | |
| 1486 | <pre><code class="sh">$ zig test test.zig | |
| 1487 | Test 1/8 address of syntax...OK | |
| 1488 | Test 2/8 pointer array access...OK | |
| 1489 | Test 3/8 pointer slicing...OK | |
| 1490 | Test 4/8 @ptrToInt and @intToPtr...OK | |
| 1491 | Test 5/8 volatile...OK | |
| 1492 | Test 6/8 nullable pointers...OK | |
| 1493 | Test 7/8 pointer casting...OK | |
| 1494 | Test 8/8 pointer child type...OK</code></pre> | |
| 1503 | assert((&u32).Child == u32); | |
| 1504 | } | |
| 1505 | {#code_end#} | |
| 1495 | 1506 | {#header_open|Alignment#} |
| 1496 | 1507 | <p> |
| 1497 | 1508 | Each type has an <strong>alignment</strong> - a number of bytes such that, |
| 1498 | 1509 | when a value of the type is loaded from or stored to memory, |
| 1499 | 1510 | the memory address must be evenly divisible by this number. You can use |
| 1500 | <a href="#builtin-alignOf">@alignOf</a> to find out this value for any type. | |
| 1511 | {#link|@alignOf#} to find out this value for any type. | |
| 1501 | 1512 | </p> |
| 1502 | 1513 | <p> |
| 1503 | 1514 | Alignment depends on the CPU architecture, but is always a power of two, and |
| ... | ... | @@ -1507,18 +1518,20 @@ Test 8/8 pointer child type...OK</code></pre> |
| 1507 | 1518 | In Zig, a pointer type has an alignment value. If the value is equal to the |
| 1508 | 1519 | alignment of the underlying type, it can be omitted from the type: |
| 1509 | 1520 | </p> |
| 1510 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 1521 | {#code_begin|test#} | |
| 1522 | const assert = @import("std").debug.assert; | |
| 1511 | 1523 | const builtin = @import("builtin"); |
| 1512 | 1524 | |
| 1513 | 1525 | test "variable alignment" { |
| 1514 | 1526 | var x: i32 = 1234; |
| 1515 | 1527 | const align_of_i32 = @alignOf(@typeOf(x)); |
| 1516 | assert(@typeOf(&amp;x) == &amp;i32); | |
| 1517 | assert(&amp;i32 == &amp;align(align_of_i32) i32); | |
| 1528 | assert(@typeOf(&x) == &i32); | |
| 1529 | assert(&i32 == &align(align_of_i32) i32); | |
| 1518 | 1530 | if (builtin.arch == builtin.Arch.x86_64) { |
| 1519 | assert((&amp;i32).alignment == 4); | |
| 1531 | assert((&i32).alignment == 4); | |
| 1520 | 1532 | } |
| 1521 | }</code></pre> | |
| 1533 | } | |
| 1534 | {#code_end#} | |
| 1522 | 1535 | <p>In the same way that a <code>&amp;i32</code> can be implicitly cast to a |
| 1523 | 1536 | <code>&amp;const i32</code>, a pointer with a larger alignment can be implicitly |
| 1524 | 1537 | cast to a pointer with a smaller alignment, but not vice versa. |
| ... | ... | @@ -1527,72 +1540,50 @@ test "variable alignment" { |
| 1527 | 1540 | You can specify alignment on variables and functions. If you do this, then |
| 1528 | 1541 | pointers to them get the specified alignment: |
| 1529 | 1542 | </p> |
| 1530 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 1543 | {#code_begin|test#} | |
| 1544 | const assert = @import("std").debug.assert; | |
| 1531 | 1545 | |
| 1532 | 1546 | var foo: u8 align(4) = 100; |
| 1533 | 1547 | |
| 1534 | 1548 | test "global variable alignment" { |
| 1535 | assert(@typeOf(&amp;foo).alignment == 4); | |
| 1536 | assert(@typeOf(&amp;foo) == &amp;align(4) u8); | |
| 1537 | const slice = (&amp;foo)[0..1]; | |
| 1549 | assert(@typeOf(&foo).alignment == 4); | |
| 1550 | assert(@typeOf(&foo) == &align(4) u8); | |
| 1551 | const slice = (&foo)[0..1]; | |
| 1538 | 1552 | assert(@typeOf(slice) == []align(4) u8); |
| 1539 | 1553 | } |
| 1540 | 1554 | |
| 1541 | fn derp() align(@sizeOf(usize) * 2) -&gt; i32 { 1234 } | |
| 1542 | fn noop1() align(1) {} | |
| 1543 | fn noop4() align(4) {} | |
| 1555 | fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; } | |
| 1556 | fn noop1() align(1) void {} | |
| 1557 | fn noop4() align(4) void {} | |
| 1544 | 1558 | |
| 1545 | 1559 | test "function alignment" { |
| 1546 | 1560 | assert(derp() == 1234); |
| 1547 | assert(@typeOf(noop1) == fn() align(1)); | |
| 1548 | assert(@typeOf(noop4) == fn() align(4)); | |
| 1561 | assert(@typeOf(noop1) == fn() align(1) void); | |
| 1562 | assert(@typeOf(noop4) == fn() align(4) void); | |
| 1549 | 1563 | noop1(); |
| 1550 | 1564 | noop4(); |
| 1551 | }</code></pre> | |
| 1565 | } | |
| 1566 | {#code_end#} | |
| 1552 | 1567 | <p> |
| 1553 | 1568 | If you have a pointer or a slice that has a small alignment, but you know that it actually |
| 1554 | has a bigger alignment, use <a href="#builtin-alignCast">@alignCast</a> to change the | |
| 1569 | has a bigger alignment, use {#link|@alignCast#} to change the | |
| 1555 | 1570 | pointer into a more aligned pointer. This is a no-op at runtime, but inserts a |
| 1556 | <a href="#undef-incorrect-pointer-alignment">safety check</a>: | |
| 1571 | {#link|safety check|Incorrect Pointer Alignment#}: | |
| 1557 | 1572 | </p> |
| 1558 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 1573 | {#code_begin|test_safety|incorrect alignment#} | |
| 1574 | const assert = @import("std").debug.assert; | |
| 1559 | 1575 | |
| 1560 | 1576 | test "pointer alignment safety" { |
| 1561 | 1577 | var array align(4) = []u32{0x11111111, 0x11111111}; |
| 1562 | 1578 | const bytes = ([]u8)(array[0..]); |
| 1563 | 1579 | assert(foo(bytes) == 0x11111111); |
| 1564 | 1580 | } |
| 1565 | fn foo(bytes: []u8) -&gt; u32 { | |
| 1581 | fn foo(bytes: []u8) u32 { | |
| 1566 | 1582 | const slice4 = bytes[1..5]; |
| 1567 | 1583 | const int_slice = ([]u32)(@alignCast(4, slice4)); |
| 1568 | 1584 | return int_slice[0]; |
| 1569 | }</code></pre> | |
| 1570 | <pre><code class="sh">$ zig test test.zig | |
| 1571 | Test 1/1 pointer alignment safety...incorrect alignment | |
| 1572 | /home/andy/dev/zig/build/lib/zig/std/special/zigrt.zig:16:35: 0x0000000000203525 in ??? (test) | |
| 1573 | @import("std").debug.panic("{}", message_ptr[0..message_len]); | |
| 1574 | ^ | |
| 1575 | /home/andy/dev/zig/build/test.zig:10:45: 0x00000000002035ec in ??? (test) | |
| 1576 | const int_slice = ([]u32)(@alignCast(4, slice4)); | |
| 1577 | ^ | |
| 1578 | /home/andy/dev/zig/build/test.zig:6:15: 0x0000000000203439 in ??? (test) | |
| 1579 | assert(foo(bytes) == 0x11111111); | |
| 1580 | ^ | |
| 1581 | /home/andy/dev/zig/build/lib/zig/std/special/test_runner.zig:9:21: 0x00000000002162d8 in ??? (test) | |
| 1582 | test_fn.func(); | |
| 1583 | ^ | |
| 1584 | /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:60:21: 0x0000000000216197 in ??? (test) | |
| 1585 | return root.main(); | |
| 1586 | ^ | |
| 1587 | /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:47:13: 0x0000000000216050 in ??? (test) | |
| 1588 | callMain(argc, argv, envp) catch std.os.posix.exit(1); | |
| 1589 | ^ | |
| 1590 | /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:34:25: 0x0000000000215fa0 in ??? (test) | |
| 1591 | posixCallMainAndExit() | |
| 1592 | ^ | |
| 1593 | ||
| 1594 | Tests failed. Use the following command to reproduce the failure: | |
| 1595 | ./test</code></pre> | |
| 1585 | } | |
| 1586 | {#code_end#} | |
| 1596 | 1587 | {#header_close#} |
| 1597 | 1588 | {#header_open|Type Based Alias Analysis#} |
| 1598 | 1589 | <p>Zig uses Type Based Alias Analysis (also known as Strict Aliasing) to |
| ... | ... | @@ -1602,14 +1593,15 @@ Tests failed. Use the following command to reproduce the failure: |
| 1602 | 1593 | </p> |
| 1603 | 1594 | <p>As an example, this code produces undefined behavior:</p> |
| 1604 | 1595 | <pre><code class="zig">*@ptrCast(&amp;u32, f32(12.34))</code></pre> |
| 1605 | <p>Instead, use <a href="#builtin-bitCast">@bitCast</a>: | |
| 1596 | <p>Instead, use {#link|@bitCast#}: | |
| 1606 | 1597 | <pre><code class="zig">@bitCast(u32, f32(12.34))</code></pre> |
| 1607 | 1598 | <p>As an added benefit, the <code>@bitcast</code> version works at compile-time.</p> |
| 1608 | 1599 | {#see_also|Slices|Memory#} |
| 1609 | 1600 | {#header_close#} |
| 1610 | 1601 | {#header_close#} |
| 1611 | 1602 | {#header_open|Slices#} |
| 1612 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 1603 | {#code_begin|test_safety|index out of bounds#} | |
| 1604 | const assert = @import("std").debug.assert; | |
| 1613 | 1605 | |
| 1614 | 1606 | test "basic slices" { |
| 1615 | 1607 | var array = []i32{1, 2, 3, 4}; |
| ... | ... | @@ -1618,38 +1610,17 @@ test "basic slices" { |
| 1618 | 1610 | // compile-time, whereas the slice's length is known at runtime. |
| 1619 | 1611 | // Both can be accessed with the `len` field. |
| 1620 | 1612 | const slice = array[0..array.len]; |
| 1621 | assert(slice.ptr == &amp;array[0]); | |
| 1613 | assert(slice.ptr == &array[0]); | |
| 1622 | 1614 | assert(slice.len == array.len); |
| 1623 | 1615 | |
| 1624 | 1616 | // Slices have array bounds checking. If you try to access something out |
| 1625 | 1617 | // of bounds, you'll get a safety check failure: |
| 1626 | 1618 | slice[10] += 1; |
| 1627 | }</code></pre> | |
| 1628 | <pre><code class="sh">$ zig test test.zig | |
| 1629 | Test 1/1 basic slices...index out of bounds | |
| 1630 | lib/zig/std/special/zigrt.zig:16:35: 0x0000000000203455 in ??? (test) | |
| 1631 | @import("std").debug.panic("{}", message_ptr[0..message_len]); | |
| 1632 | ^ | |
| 1633 | test.zig:15:10: 0x0000000000203334 in ??? (test) | |
| 1634 | slice[10] += 1; | |
| 1635 | ^ | |
| 1636 | lib/zig/std/special/test_runner.zig:9:21: 0x0000000000214b1a in ??? (test) | |
| 1637 | test_fn.func(); | |
| 1638 | ^ | |
| 1639 | lib/zig/std/special/bootstrap.zig:60:21: 0x00000000002149e7 in ??? (test) | |
| 1640 | return root.main(); | |
| 1641 | ^ | |
| 1642 | lib/zig/std/special/bootstrap.zig:47:13: 0x00000000002148a0 in ??? (test) | |
| 1643 | callMain(argc, argv, envp) catch std.os.posix.exit(1); | |
| 1644 | ^ | |
| 1645 | lib/zig/std/special/bootstrap.zig:34:25: 0x00000000002147f0 in ??? (test) | |
| 1646 | posixCallMainAndExit() | |
| 1647 | ^ | |
| 1648 | ||
| 1649 | Tests failed. Use the following command to reproduce the failure: | |
| 1650 | ./test</code></pre> | |
| 1619 | } | |
| 1620 | {#code_end#} | |
| 1651 | 1621 | <p>This is one reason we prefer slices to pointers.</p> |
| 1652 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 1622 | {#code_begin|test|slices#} | |
| 1623 | const assert = @import("std").debug.assert; | |
| 1653 | 1624 | const mem = @import("std").mem; |
| 1654 | 1625 | const fmt = @import("std").fmt; |
| 1655 | 1626 | |
| ... | ... | @@ -1663,8 +1634,8 @@ test "using slices for strings" { |
| 1663 | 1634 | var all_together: [100]u8 = undefined; |
| 1664 | 1635 | // You can use slice syntax on an array to convert an array into a slice. |
| 1665 | 1636 | const all_together_slice = all_together[0..]; |
| 1666 | // String concatenation example: | |
| 1667 | const hello_world = fmt.bufPrint(all_together_slice, "{} {}", hello, world); | |
| 1637 | // String concatenation example. | |
| 1638 | const hello_world = try fmt.bufPrint(all_together_slice, "{} {}", hello, world); | |
| 1668 | 1639 | |
| 1669 | 1640 | // Generally, you can use UTF-8 and not worry about whether something is a |
| 1670 | 1641 | // string. If you don't need to deal with individual characters, no need |
| ... | ... | @@ -1674,7 +1645,7 @@ test "using slices for strings" { |
| 1674 | 1645 | |
| 1675 | 1646 | test "slice pointer" { |
| 1676 | 1647 | var array: [10]u8 = undefined; |
| 1677 | const ptr = &amp;array[0]; | |
| 1648 | const ptr = &array[0]; | |
| 1678 | 1649 | |
| 1679 | 1650 | // You can use slicing syntax to convert a pointer into a slice: |
| 1680 | 1651 | const slice = ptr[0..5]; |
| ... | ... | @@ -1692,20 +1663,18 @@ test "slice pointer" { |
| 1692 | 1663 | test "slice widening" { |
| 1693 | 1664 | // Zig supports slice widening and slice narrowing. Cast a slice of u8 |
| 1694 | 1665 | // to a slice of anything else, and Zig will perform the length conversion. |
| 1695 | const array = []u8{0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13}; | |
| 1666 | const array align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13}; | |
| 1696 | 1667 | const slice = ([]const u32)(array[0..]); |
| 1697 | 1668 | assert(slice.len == 2); |
| 1698 | 1669 | assert(slice[0] == 0x12121212); |
| 1699 | 1670 | assert(slice[1] == 0x13131313); |
| 1700 | }</code></pre> | |
| 1701 | <pre><code class="sh">$ zig test test.zig | |
| 1702 | Test 1/3 using slices for strings...OK | |
| 1703 | Test 2/3 slice pointer...OK | |
| 1704 | Test 3/3 slice widening...OK</code></pre> | |
| 1671 | } | |
| 1672 | {#code_end#} | |
| 1705 | 1673 | {#see_also|Pointers|for|Arrays#} |
| 1706 | 1674 | {#header_close#} |
| 1707 | 1675 | {#header_open|struct#} |
| 1708 | <pre><code class="zig">// Declare a struct. | |
| 1676 | {#code_begin|test|structs#} | |
| 1677 | // Declare a struct. | |
| 1709 | 1678 | // Zig gives no guarantees about the order of fields and whether or |
| 1710 | 1679 | // not there will be padding. |
| 1711 | 1680 | const Point = struct { |
| ... | ... | @@ -1741,7 +1710,7 @@ const Vec3 = struct { |
| 1741 | 1710 | y: f32, |
| 1742 | 1711 | z: f32, |
| 1743 | 1712 | |
| 1744 | pub fn init(x: f32, y: f32, z: f32) -&gt; Vec3 { | |
| 1713 | pub fn init(x: f32, y: f32, z: f32) Vec3 { | |
| 1745 | 1714 | return Vec3 { |
| 1746 | 1715 | .x = x, |
| 1747 | 1716 | .y = y, |
| ... | ... | @@ -1749,7 +1718,7 @@ const Vec3 = struct { |
| 1749 | 1718 | }; |
| 1750 | 1719 | } |
| 1751 | 1720 | |
| 1752 | pub fn dot(self: &amp;const Vec3, other: &amp;const Vec3) -&gt; f32 { | |
| 1721 | pub fn dot(self: &const Vec3, other: &const Vec3) f32 { | |
| 1753 | 1722 | return self.x * other.x + self.y * other.y + self.z * other.z; |
| 1754 | 1723 | } |
| 1755 | 1724 | }; |
| ... | ... | @@ -1781,7 +1750,7 @@ test "struct namespaced variable" { |
| 1781 | 1750 | |
| 1782 | 1751 | // struct field order is determined by the compiler for optimal performance. |
| 1783 | 1752 | // however, you can still calculate a struct base pointer given a field pointer: |
| 1784 | fn setYBasedOnX(x: &amp;f32, y: f32) { | |
| 1753 | fn setYBasedOnX(x: &f32, y: f32) void { | |
| 1785 | 1754 | const point = @fieldParentPtr(Point, "x", x); |
| 1786 | 1755 | point.y = y; |
| 1787 | 1756 | } |
| ... | ... | @@ -1790,22 +1759,22 @@ test "field parent pointer" { |
| 1790 | 1759 | .x = 0.1234, |
| 1791 | 1760 | .y = 0.5678, |
| 1792 | 1761 | }; |
| 1793 | setYBasedOnX(&amp;point.x, 0.9); | |
| 1762 | setYBasedOnX(&point.x, 0.9); | |
| 1794 | 1763 | assert(point.y == 0.9); |
| 1795 | 1764 | } |
| 1796 | 1765 | |
| 1797 | 1766 | // You can return a struct from a function. This is how we do generics |
| 1798 | 1767 | // in Zig: |
| 1799 | fn LinkedList(comptime T: type) -&gt; type { | |
| 1768 | fn LinkedList(comptime T: type) type { | |
| 1800 | 1769 | return struct { |
| 1801 | 1770 | pub const Node = struct { |
| 1802 | prev: ?&amp;Node, | |
| 1803 | next: ?&amp;Node, | |
| 1771 | prev: ?&Node, | |
| 1772 | next: ?&Node, | |
| 1804 | 1773 | data: T, |
| 1805 | 1774 | }; |
| 1806 | 1775 | |
| 1807 | first: ?&amp;Node, | |
| 1808 | last: ?&amp;Node, | |
| 1776 | first: ?&Node, | |
| 1777 | last: ?&Node, | |
| 1809 | 1778 | len: usize, |
| 1810 | 1779 | }; |
| 1811 | 1780 | } |
| ... | ... | @@ -1833,21 +1802,18 @@ test "linked list" { |
| 1833 | 1802 | .data = 1234, |
| 1834 | 1803 | }; |
| 1835 | 1804 | var list2 = LinkedList(i32) { |
| 1836 | .first = &amp;node, | |
| 1837 | .last = &amp;node, | |
| 1805 | .first = &node, | |
| 1806 | .last = &node, | |
| 1838 | 1807 | .len = 1, |
| 1839 | 1808 | }; |
| 1840 | 1809 | assert((??list2.first).data == 1234); |
| 1841 | }</code></pre> | |
| 1842 | <pre><code class="sh">$ zig test structs.zig | |
| 1843 | Test 1/4 dot product...OK | |
| 1844 | Test 2/4 struct namespaced variable...OK | |
| 1845 | Test 3/4 field parent pointer...OK | |
| 1846 | Test 4/4 linked list...OK</code></pre> | |
| 1810 | } | |
| 1811 | {#code_end#} | |
| 1847 | 1812 | {#see_also|comptime|@fieldParentPtr#} |
| 1848 | 1813 | {#header_close#} |
| 1849 | 1814 | {#header_open|enum#} |
| 1850 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 1815 | {#code_begin|test|enums#} | |
| 1816 | const assert = @import("std").debug.assert; | |
| 1851 | 1817 | const mem = @import("std").mem; |
| 1852 | 1818 | |
| 1853 | 1819 | // Declare an enum. |
| ... | ... | @@ -1896,7 +1862,7 @@ const Suit = enum { |
| 1896 | 1862 | Diamonds, |
| 1897 | 1863 | Hearts, |
| 1898 | 1864 | |
| 1899 | pub fn isClubs(self: Suit) -&gt; bool { | |
| 1865 | pub fn isClubs(self: Suit) bool { | |
| 1900 | 1866 | return self == Suit.Clubs; |
| 1901 | 1867 | } |
| 1902 | 1868 | }; |
| ... | ... | @@ -1914,9 +1880,9 @@ const Foo = enum { |
| 1914 | 1880 | test "enum variant switch" { |
| 1915 | 1881 | const p = Foo.Number; |
| 1916 | 1882 | const what_is_it = switch (p) { |
| 1917 | Foo.String =&gt; "this is a string", | |
| 1918 | Foo.Number =&gt; "this is a number", | |
| 1919 | Foo.None =&gt; "this is a none", | |
| 1883 | Foo.String => "this is a string", | |
| 1884 | Foo.Number => "this is a number", | |
| 1885 | Foo.None => "this is a none", | |
| 1920 | 1886 | }; |
| 1921 | 1887 | assert(mem.eql(u8, what_is_it, "this is a number")); |
| 1922 | 1888 | } |
| ... | ... | @@ -1945,22 +1911,30 @@ test "@memberName" { |
| 1945 | 1911 | // @tagName gives a []const u8 representation of an enum value: |
| 1946 | 1912 | test "@tagName" { |
| 1947 | 1913 | assert(mem.eql(u8, @tagName(Small.Three), "Three")); |
| 1948 | }</code></pre> | |
| 1949 | <p>TODO extern enum</p> | |
| 1914 | } | |
| 1915 | {#code_end#} | |
| 1916 | {#header_open|extern enum#} | |
| 1917 | <p> | |
| 1918 | By default, enums are not guaranteed to be compatible with the C ABI: | |
| 1919 | </p> | |
| 1920 | {#code_begin|obj_err|parameter of type 'Foo' not allowed in function with calling convention 'ccc'#} | |
| 1921 | const Foo = enum { A, B, C }; | |
| 1922 | export fn entry(foo: Foo) void { } | |
| 1923 | {#code_end#} | |
| 1924 | <p> | |
| 1925 | For a C-ABI-compatible enum, use <code class="zig">extern enum</code>: | |
| 1926 | </p> | |
| 1927 | {#code_begin|obj#} | |
| 1928 | const Foo = extern enum { A, B, C }; | |
| 1929 | export fn entry(foo: Foo) void { } | |
| 1930 | {#code_end#} | |
| 1931 | {#header_close#} | |
| 1950 | 1932 | <p>TODO packed enum</p> |
| 1951 | <pre><code class="sh">$ zig test enum.zig | |
| 1952 | Test 1/8 enum ordinal value...OK | |
| 1953 | Test 2/8 set enum ordinal value...OK | |
| 1954 | Test 3/8 enum method...OK | |
| 1955 | Test 4/8 enum variant switch...OK | |
| 1956 | Test 5/8 @TagType...OK | |
| 1957 | Test 6/8 @memberCount...OK | |
| 1958 | Test 7/8 @memberName...OK | |
| 1959 | Test 8/8 @tagName...OK</code></pre> | |
| 1960 | 1933 | {#see_also|@memberName|@memberCount|@tagName#} |
| 1961 | 1934 | {#header_close#} |
| 1962 | 1935 | {#header_open|union#} |
| 1963 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 1936 | {#code_begin|test|union#} | |
| 1937 | const assert = @import("std").debug.assert; | |
| 1964 | 1938 | const mem = @import("std").mem; |
| 1965 | 1939 | |
| 1966 | 1940 | // A union has only 1 active field at a time. |
| ... | ... | @@ -2008,19 +1982,19 @@ test "union variant switch" { |
| 2008 | 1982 | const p = Foo { .Number = 54 }; |
| 2009 | 1983 | const what_is_it = switch (p) { |
| 2010 | 1984 | // Capture by reference |
| 2011 | Foo.String =&gt; |*x| { | |
| 2012 | "this is a string" | |
| 1985 | Foo.String => |*x| blk: { | |
| 1986 | break :blk "this is a string"; | |
| 2013 | 1987 | }, |
| 2014 | 1988 | |
| 2015 | 1989 | // Capture by value |
| 2016 | Foo.Number =&gt; |x| { | |
| 1990 | Foo.Number => |x| blk: { | |
| 2017 | 1991 | assert(x == 54); |
| 2018 | "this is a number" | |
| 1992 | break :blk "this is a number"; | |
| 2019 | 1993 | }, |
| 2020 | 1994 | |
| 2021 | Foo.None =&gt; { | |
| 2022 | "this is a none" | |
| 2023 | } | |
| 1995 | Foo.None => blk: { | |
| 1996 | break :blk "this is a none"; | |
| 1997 | }, | |
| 2024 | 1998 | }; |
| 2025 | 1999 | assert(mem.eql(u8, what_is_it, "this is a number")); |
| 2026 | 2000 | } |
| ... | ... | @@ -2053,22 +2027,16 @@ const Small2 = union(enum) { |
| 2053 | 2027 | }; |
| 2054 | 2028 | test "@tagName" { |
| 2055 | 2029 | assert(mem.eql(u8, @tagName(Small2.C), "C")); |
| 2056 | }</code></pre> | |
| 2057 | <pre><code class="sh">$ zig test union.zig | |
| 2058 | Test 1/7 simple union...OK | |
| 2059 | Test 2/7 declare union value...OK | |
| 2060 | Test 3/7 @TagType...OK | |
| 2061 | Test 4/7 union variant switch...OK | |
| 2062 | Test 5/7 @memberCount...OK | |
| 2063 | Test 6/7 @memberName...OK | |
| 2064 | Test 7/7 @tagName...OK</code></pre> | |
| 2030 | } | |
| 2031 | {#code_end#} | |
| 2065 | 2032 | <p> |
| 2066 | 2033 | Unions with an enum tag are generated as a struct with a tag field and union field. Zig |
| 2067 | 2034 | sorts the order of the tag and union field by the largest alignment. |
| 2068 | 2035 | </p> |
| 2069 | 2036 | {#header_close#} |
| 2070 | 2037 | {#header_open|switch#} |
| 2071 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 2038 | {#code_begin|test|switch#} | |
| 2039 | const assert = @import("std").debug.assert; | |
| 2072 | 2040 | const builtin = @import("builtin"); |
| 2073 | 2041 | |
| 2074 | 2042 | test "switch simple" { |
| ... | ... | @@ -2082,59 +2050,59 @@ test "switch simple" { |
| 2082 | 2050 | // the cases and use an if. |
| 2083 | 2051 | const b = switch (a) { |
| 2084 | 2052 | // Multiple cases can be combined via a ',' |
| 2085 | 1, 2, 3 =&gt; 0, | |
| 2053 | 1, 2, 3 => 0, | |
| 2086 | 2054 | |
| 2087 | 2055 | // Ranges can be specified using the ... syntax. These are inclusive |
| 2088 | 2056 | // both ends. |
| 2089 | 5 ... 100 =&gt; 1, | |
| 2057 | 5 ... 100 => 1, | |
| 2090 | 2058 | |
| 2091 | 2059 | // Branches can be arbitrarily complex. |
| 2092 | 101 =&gt; { | |
| 2060 | 101 => blk: { | |
| 2093 | 2061 | const c: u64 = 5; |
| 2094 | c * 2 + 1 | |
| 2062 | break :blk c * 2 + 1; | |
| 2095 | 2063 | }, |
| 2096 | 2064 | |
| 2097 | 2065 | // Switching on arbitrary expressions is allowed as long as the |
| 2098 | 2066 | // expression is known at compile-time. |
| 2099 | zz =&gt; zz, | |
| 2100 | comptime { | |
| 2067 | zz => zz, | |
| 2068 | comptime blk: { | |
| 2101 | 2069 | const d: u32 = 5; |
| 2102 | 2070 | const e: u32 = 100; |
| 2103 | d + e | |
| 2104 | } =&gt; 107, | |
| 2071 | break :blk d + e; | |
| 2072 | } => 107, | |
| 2105 | 2073 | |
| 2106 | 2074 | // The else branch catches everything not already captured. |
| 2107 | 2075 | // Else branches are mandatory unless the entire range of values |
| 2108 | 2076 | // is handled. |
| 2109 | else =&gt; 9, | |
| 2077 | else => 9, | |
| 2110 | 2078 | }; |
| 2111 | 2079 | |
| 2112 | 2080 | assert(b == 1); |
| 2113 | 2081 | } |
| 2114 | 2082 | |
| 2115 | 2083 | test "switch enum" { |
| 2116 | const Item = enum { | |
| 2084 | const Item = union(enum) { | |
| 2117 | 2085 | A: u32, |
| 2118 | 2086 | C: struct { x: u8, y: u8 }, |
| 2119 | 2087 | D, |
| 2120 | 2088 | }; |
| 2121 | 2089 | |
| 2122 | var a = Item.A { 3 }; | |
| 2090 | var a = Item { .A = 3 }; | |
| 2123 | 2091 | |
| 2124 | 2092 | // Switching on more complex enums is allowed. |
| 2125 | 2093 | const b = switch (a) { |
| 2126 | 2094 | // A capture group is allowed on a match, and will return the enum |
| 2127 | 2095 | // value matched. |
| 2128 | Item.A =&gt; |item| item, | |
| 2096 | Item.A => |item| item, | |
| 2129 | 2097 | |
| 2130 | 2098 | // A reference to the matched value can be obtained using `*` syntax. |
| 2131 | Item.C =&gt; |*item| { | |
| 2099 | Item.C => |*item| blk: { | |
| 2132 | 2100 | (*item).x += 1; |
| 2133 | 6 | |
| 2101 | break :blk 6; | |
| 2134 | 2102 | }, |
| 2135 | 2103 | |
| 2136 | 2104 | // No else is required if the types cases was exhaustively handled |
| 2137 | Item.D =&gt; 8, | |
| 2105 | Item.D => 8, | |
| 2138 | 2106 | }; |
| 2139 | 2107 | |
| 2140 | 2108 | assert(b == 3); |
| ... | ... | @@ -2142,37 +2110,35 @@ test "switch enum" { |
| 2142 | 2110 | |
| 2143 | 2111 | // Switch expressions can be used outside a function: |
| 2144 | 2112 | const os_msg = switch (builtin.os) { |
| 2145 | builtin.Os.linux =&gt; "we found a linux user", | |
| 2146 | else =&gt; "not a linux user", | |
| 2113 | builtin.Os.linux => "we found a linux user", | |
| 2114 | else => "not a linux user", | |
| 2147 | 2115 | }; |
| 2148 | 2116 | |
| 2149 | 2117 | // Inside a function, switch statements implicitly are compile-time |
| 2150 | 2118 | // evaluated if the target expression is compile-time known. |
| 2151 | 2119 | test "switch inside function" { |
| 2152 | 2120 | switch (builtin.os) { |
| 2153 | builtin.Os.windows =&gt; { | |
| 2154 | // On an OS other than windows, block is not even analyzed, | |
| 2121 | builtin.Os.fuchsia => { | |
| 2122 | // On an OS other than fuchsia, block is not even analyzed, | |
| 2155 | 2123 | // so this compile error is not triggered. |
| 2156 | // On windows this compile error would be triggered. | |
| 2124 | // On fuchsia this compile error would be triggered. | |
| 2157 | 2125 | @compileError("windows not supported"); |
| 2158 | 2126 | }, |
| 2159 | else =&gt; {}, | |
| 2160 | }; | |
| 2161 | }</code></pre> | |
| 2162 | <pre><code class="sh">$ zig test switch.zig | |
| 2163 | Test 1/2 switch simple...OK | |
| 2164 | Test 2/2 switch enum...OK | |
| 2165 | Test 3/3 switch inside function...OK</code></pre> | |
| 2127 | else => {}, | |
| 2128 | } | |
| 2129 | } | |
| 2130 | {#code_end#} | |
| 2166 | 2131 | {#see_also|comptime|enum|@compileError|Compile Variables#} |
| 2167 | 2132 | {#header_close#} |
| 2168 | 2133 | {#header_open|while#} |
| 2169 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 2134 | {#code_begin|test|while#} | |
| 2135 | const assert = @import("std").debug.assert; | |
| 2170 | 2136 | |
| 2171 | 2137 | test "while basic" { |
| 2172 | 2138 | // A while loop is used to repeatedly execute an expression until |
| 2173 | 2139 | // some condition is no longer true. |
| 2174 | 2140 | var i: usize = 0; |
| 2175 | while (i &lt; 10) { | |
| 2141 | while (i < 10) { | |
| 2176 | 2142 | i += 1; |
| 2177 | 2143 | } |
| 2178 | 2144 | assert(i == 10); |
| ... | ... | @@ -2194,7 +2160,7 @@ test "while continue" { |
| 2194 | 2160 | var i: usize = 0; |
| 2195 | 2161 | while (true) { |
| 2196 | 2162 | i += 1; |
| 2197 | if (i &lt; 10) | |
| 2163 | if (i < 10) | |
| 2198 | 2164 | continue; |
| 2199 | 2165 | break; |
| 2200 | 2166 | } |
| ... | ... | @@ -2205,7 +2171,7 @@ test "while loop continuation expression" { |
| 2205 | 2171 | // You can give an expression to the while loop to execute when |
| 2206 | 2172 | // the loop is continued. This is respected by the continue control flow. |
| 2207 | 2173 | var i: usize = 0; |
| 2208 | while (i &lt; 10) : (i += 1) {} | |
| 2174 | while (i < 10) : (i += 1) {} | |
| 2209 | 2175 | assert(i == 10); |
| 2210 | 2176 | } |
| 2211 | 2177 | |
| ... | ... | @@ -2214,9 +2180,9 @@ test "while loop continuation expression, more complicated" { |
| 2214 | 2180 | // expression. |
| 2215 | 2181 | var i1: usize = 1; |
| 2216 | 2182 | var j1: usize = 1; |
| 2217 | while (i1 * j1 &lt; 2000) : ({ i1 *= 2; j1 *= 3; }) { | |
| 2183 | while (i1 * j1 < 2000) : ({ i1 *= 2; j1 *= 3; }) { | |
| 2218 | 2184 | const my_ij1 = i1 * j1; |
| 2219 | assert(my_ij1 &lt; 2000); | |
| 2185 | assert(my_ij1 < 2000); | |
| 2220 | 2186 | } |
| 2221 | 2187 | } |
| 2222 | 2188 | |
| ... | ... | @@ -2225,12 +2191,12 @@ test "while else" { |
| 2225 | 2191 | assert(!rangeHasNumber(0, 10, 15)); |
| 2226 | 2192 | } |
| 2227 | 2193 | |
| 2228 | fn rangeHasNumber(begin: usize, end: usize, number: usize) -&gt; bool { | |
| 2194 | fn rangeHasNumber(begin: usize, end: usize, number: usize) bool { | |
| 2229 | 2195 | var i = begin; |
| 2230 | 2196 | // While loops are expressions. The result of the expression is the |
| 2231 | 2197 | // result of the else clause of a while loop, which is executed when |
| 2232 | 2198 | // the condition of the while loop is tested as false. |
| 2233 | return while (i &lt; end) : (i += 1) { | |
| 2199 | return while (i < end) : (i += 1) { | |
| 2234 | 2200 | if (i == number) { |
| 2235 | 2201 | // break expressions, like return expressions, accept a value |
| 2236 | 2202 | // parameter. This is the result of the while expression. |
| ... | ... | @@ -2238,9 +2204,7 @@ fn rangeHasNumber(begin: usize, end: usize, number: usize) -&gt; bool { |
| 2238 | 2204 | // evaluated. |
| 2239 | 2205 | break true; |
| 2240 | 2206 | } |
| 2241 | } else { | |
| 2242 | false | |
| 2243 | } | |
| 2207 | } else false; | |
| 2244 | 2208 | } |
| 2245 | 2209 | |
| 2246 | 2210 | test "while null capture" { |
| ... | ... | @@ -2278,22 +2242,18 @@ test "while null capture" { |
| 2278 | 2242 | } |
| 2279 | 2243 | |
| 2280 | 2244 | var numbers_left: u32 = undefined; |
| 2281 | fn eventuallyNullSequence() -&gt; ?u32 { | |
| 2282 | return if (numbers_left == 0) { | |
| 2283 | null | |
| 2284 | } else { | |
| 2245 | fn eventuallyNullSequence() ?u32 { | |
| 2246 | return if (numbers_left == 0) null else blk: { | |
| 2285 | 2247 | numbers_left -= 1; |
| 2286 | numbers_left | |
| 2287 | } | |
| 2248 | break :blk numbers_left; | |
| 2249 | }; | |
| 2288 | 2250 | } |
| 2289 | 2251 | error ReachedZero; |
| 2290 | fn eventuallyErrorSequence() -&gt; %u32 { | |
| 2291 | return if (numbers_left == 0) { | |
| 2292 | error.ReachedZero | |
| 2293 | } else { | |
| 2252 | fn eventuallyErrorSequence() %u32 { | |
| 2253 | return if (numbers_left == 0) error.ReachedZero else blk: { | |
| 2294 | 2254 | numbers_left -= 1; |
| 2295 | numbers_left | |
| 2296 | } | |
| 2255 | break :blk numbers_left; | |
| 2256 | }; | |
| 2297 | 2257 | } |
| 2298 | 2258 | |
| 2299 | 2259 | test "inline while loop" { |
| ... | ... | @@ -2302,34 +2262,27 @@ test "inline while loop" { |
| 2302 | 2262 | // such as use types as first class values. |
| 2303 | 2263 | comptime var i = 0; |
| 2304 | 2264 | var sum: usize = 0; |
| 2305 | inline while (i &lt; 3) : (i += 1) { | |
| 2265 | inline while (i < 3) : (i += 1) { | |
| 2306 | 2266 | const T = switch (i) { |
| 2307 | 0 =&gt; f32, | |
| 2308 | 1 =&gt; i8, | |
| 2309 | 2 =&gt; bool, | |
| 2310 | else =&gt; unreachable, | |
| 2267 | 0 => f32, | |
| 2268 | 1 => i8, | |
| 2269 | 2 => bool, | |
| 2270 | else => unreachable, | |
| 2311 | 2271 | }; |
| 2312 | 2272 | sum += typeNameLength(T); |
| 2313 | 2273 | } |
| 2314 | 2274 | assert(sum == 9); |
| 2315 | 2275 | } |
| 2316 | 2276 | |
| 2317 | fn typeNameLength(comptime T: type) -&gt; usize { | |
| 2277 | fn typeNameLength(comptime T: type) usize { | |
| 2318 | 2278 | return @typeName(T).len; |
| 2319 | }</code></pre> | |
| 2320 | <pre><code class="sh">$ zig while.zig | |
| 2321 | Test 1/8 while basic...OK | |
| 2322 | Test 2/8 while break...OK | |
| 2323 | Test 3/8 while continue...OK | |
| 2324 | Test 4/8 while loop continuation expression...OK | |
| 2325 | Test 5/8 while loop continuation expression, more complicated...OK | |
| 2326 | Test 6/8 while else...OK | |
| 2327 | Test 7/8 while null capture...OK | |
| 2328 | Test 8/8 inline while loop...OK</code></pre> | |
| 2279 | } | |
| 2280 | {#code_end#} | |
| 2329 | 2281 | {#see_also|if|Nullables|Errors|comptime|unreachable#} |
| 2330 | 2282 | {#header_close#} |
| 2331 | 2283 | {#header_open|for#} |
| 2332 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 2284 | {#code_begin|test|for#} | |
| 2285 | const assert = @import("std").debug.assert; | |
| 2333 | 2286 | |
| 2334 | 2287 | test "for basics" { |
| 2335 | 2288 | const items = []i32 { 4, 5, 3, 4, 0 }; |
| ... | ... | @@ -2387,9 +2340,9 @@ test "for else" { |
| 2387 | 2340 | } else { |
| 2388 | 2341 | sum += ??value; |
| 2389 | 2342 | } |
| 2390 | } else { | |
| 2343 | } else blk: { | |
| 2391 | 2344 | assert(sum == 7); |
| 2392 | sum | |
| 2345 | break :blk sum; | |
| 2393 | 2346 | }; |
| 2394 | 2347 | } |
| 2395 | 2348 | |
| ... | ... | @@ -2404,28 +2357,25 @@ test "inline for loop" { |
| 2404 | 2357 | var sum: usize = 0; |
| 2405 | 2358 | inline for (nums) |i| { |
| 2406 | 2359 | const T = switch (i) { |
| 2407 | 2 =&gt; f32, | |
| 2408 | 4 =&gt; i8, | |
| 2409 | 6 =&gt; bool, | |
| 2410 | else =&gt; unreachable, | |
| 2360 | 2 => f32, | |
| 2361 | 4 => i8, | |
| 2362 | 6 => bool, | |
| 2363 | else => unreachable, | |
| 2411 | 2364 | }; |
| 2412 | 2365 | sum += typeNameLength(T); |
| 2413 | 2366 | } |
| 2414 | 2367 | assert(sum == 9); |
| 2415 | 2368 | } |
| 2416 | 2369 | |
| 2417 | fn typeNameLength(comptime T: type) -&gt; usize { | |
| 2370 | fn typeNameLength(comptime T: type) usize { | |
| 2418 | 2371 | return @typeName(T).len; |
| 2419 | }</code></pre> | |
| 2420 | <pre><code class="sh">$ zig test for.zig | |
| 2421 | Test 1/4 for basics...OK | |
| 2422 | Test 2/4 for reference...OK | |
| 2423 | Test 3/4 for else...OK | |
| 2424 | Test 4/4 inline for loop...OK</code></pre> | |
| 2372 | } | |
| 2373 | {#code_end#} | |
| 2425 | 2374 | {#see_also|while|comptime|Arrays|Slices#} |
| 2426 | 2375 | {#header_close#} |
| 2427 | 2376 | {#header_open|if#} |
| 2428 | <pre><code class="zig">// If expressions have three uses, corresponding to the three types: | |
| 2377 | {#code_begin|test|if#} | |
| 2378 | // If expressions have three uses, corresponding to the three types: | |
| 2429 | 2379 | // * bool |
| 2430 | 2380 | // * ?T |
| 2431 | 2381 | // * %T |
| ... | ... | @@ -2439,9 +2389,9 @@ test "if boolean" { |
| 2439 | 2389 | if (a != b) { |
| 2440 | 2390 | assert(true); |
| 2441 | 2391 | } else if (a == 9) { |
| 2442 | unreachable | |
| 2392 | unreachable; | |
| 2443 | 2393 | } else { |
| 2444 | unreachable | |
| 2394 | unreachable; | |
| 2445 | 2395 | } |
| 2446 | 2396 | |
| 2447 | 2397 | // If expressions are used instead of a ternary expression. |
| ... | ... | @@ -2499,12 +2449,12 @@ test "if error union" { |
| 2499 | 2449 | if (a) |value| { |
| 2500 | 2450 | assert(value == 0); |
| 2501 | 2451 | } else |err| { |
| 2502 | unreachable | |
| 2452 | unreachable; | |
| 2503 | 2453 | } |
| 2504 | 2454 | |
| 2505 | 2455 | const b: %u32 = error.BadValue; |
| 2506 | 2456 | if (b) |value| { |
| 2507 | unreachable | |
| 2457 | unreachable; | |
| 2508 | 2458 | } else |err| { |
| 2509 | 2459 | assert(err == error.BadValue); |
| 2510 | 2460 | } |
| ... | ... | @@ -2524,27 +2474,26 @@ test "if error union" { |
| 2524 | 2474 | if (c) |*value| { |
| 2525 | 2475 | *value = 9; |
| 2526 | 2476 | } else |err| { |
| 2527 | unreachable | |
| 2477 | unreachable; | |
| 2528 | 2478 | } |
| 2529 | 2479 | |
| 2530 | 2480 | if (c) |value| { |
| 2531 | 2481 | assert(value == 9); |
| 2532 | 2482 | } else |err| { |
| 2533 | unreachable | |
| 2483 | unreachable; | |
| 2534 | 2484 | } |
| 2535 | }</code></pre> | |
| 2536 | <pre><code class="sh">$ zig test if.zig | |
| 2537 | Test 1/3 if boolean...OK | |
| 2538 | Test 2/3 if nullable...OK | |
| 2539 | Test 3/3 if error union...OK</code></pre> | |
| 2485 | } | |
| 2486 | {#code_end#} | |
| 2540 | 2487 | {#see_also|Nullables|Errors#} |
| 2541 | 2488 | {#header_close#} |
| 2542 | 2489 | {#header_open|defer#} |
| 2543 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 2544 | const printf = @import("std").io.stdout.printf; | |
| 2490 | {#code_begin|test|defer#} | |
| 2491 | const std = @import("std"); | |
| 2492 | const assert = std.debug.assert; | |
| 2493 | const warn = std.debug.warn; | |
| 2545 | 2494 | |
| 2546 | 2495 | // defer will execute an expression at the end of the current scope. |
| 2547 | fn deferExample() -&gt; usize { | |
| 2496 | fn deferExample() usize { | |
| 2548 | 2497 | var a: usize = 1; |
| 2549 | 2498 | |
| 2550 | 2499 | { |
| ... | ... | @@ -2554,7 +2503,7 @@ fn deferExample() -&gt; usize { |
| 2554 | 2503 | assert(a == 2); |
| 2555 | 2504 | |
| 2556 | 2505 | a = 5; |
| 2557 | a | |
| 2506 | return a; | |
| 2558 | 2507 | } |
| 2559 | 2508 | |
| 2560 | 2509 | test "defer basics" { |
| ... | ... | @@ -2563,43 +2512,43 @@ test "defer basics" { |
| 2563 | 2512 | |
| 2564 | 2513 | // If multiple defer statements are specified, they will be executed in |
| 2565 | 2514 | // the reverse order they were run. |
| 2566 | fn deferUnwindExample() { | |
| 2567 | %%printf("\n"); | |
| 2515 | fn deferUnwindExample() void { | |
| 2516 | warn("\n"); | |
| 2568 | 2517 | |
| 2569 | 2518 | defer { |
| 2570 | %%printf("1 "); | |
| 2519 | warn("1 "); | |
| 2571 | 2520 | } |
| 2572 | 2521 | defer { |
| 2573 | %%printf("2 "); | |
| 2522 | warn("2 "); | |
| 2574 | 2523 | } |
| 2575 | 2524 | if (false) { |
| 2576 | 2525 | // defers are not run if they are never executed. |
| 2577 | 2526 | defer { |
| 2578 | %%printf("3 "); | |
| 2527 | warn("3 "); | |
| 2579 | 2528 | } |
| 2580 | 2529 | } |
| 2581 | 2530 | } |
| 2582 | 2531 | |
| 2583 | 2532 | test "defer unwinding" { |
| 2584 | deferUnwindExample() | |
| 2533 | deferUnwindExample(); | |
| 2585 | 2534 | } |
| 2586 | 2535 | |
| 2587 | // The %defer keyword is similar to defer, but will only execute if the | |
| 2536 | // The errdefer keyword is similar to defer, but will only execute if the | |
| 2588 | 2537 | // scope returns with an error. |
| 2589 | 2538 | // |
| 2590 | 2539 | // This is especially useful in allowing a function to clean up properly |
| 2591 | 2540 | // on error, and replaces goto error handling tactics as seen in c. |
| 2592 | 2541 | error DeferError; |
| 2593 | fn deferErrorExample(is_error: bool) -&gt; %void { | |
| 2594 | %%printf("\nstart of function\n"); | |
| 2542 | fn deferErrorExample(is_error: bool) %void { | |
| 2543 | warn("\nstart of function\n"); | |
| 2595 | 2544 | |
| 2596 | 2545 | // This will always be executed on exit |
| 2597 | 2546 | defer { |
| 2598 | %%printf("end of function\n"); | |
| 2547 | warn("end of function\n"); | |
| 2599 | 2548 | } |
| 2600 | 2549 | |
| 2601 | %defer { | |
| 2602 | %%printf("encountered an error!\n"); | |
| 2550 | errdefer { | |
| 2551 | warn("encountered an error!\n"); | |
| 2603 | 2552 | } |
| 2604 | 2553 | |
| 2605 | 2554 | if (is_error) { |
| ... | ... | @@ -2607,24 +2556,11 @@ fn deferErrorExample(is_error: bool) -&gt; %void { |
| 2607 | 2556 | } |
| 2608 | 2557 | } |
| 2609 | 2558 | |
| 2610 | test "%defer unwinding" { | |
| 2559 | test "errdefer unwinding" { | |
| 2611 | 2560 | _ = deferErrorExample(false); |
| 2612 | 2561 | _ = deferErrorExample(true); |
| 2613 | 2562 | } |
| 2614 | </code></pre> | |
| 2615 | <pre><code class="sh">$ zig test defer.zig | |
| 2616 | Test 1/3 defer basics...OK | |
| 2617 | Test 2/3 defer unwinding... | |
| 2618 | 2 1 OK | |
| 2619 | Test 3/3 %defer unwinding... | |
| 2620 | start of function | |
| 2621 | end of function | |
| 2622 | ||
| 2623 | start of function | |
| 2624 | encountered an error! | |
| 2625 | end of function | |
| 2626 | OK | |
| 2627 | </code></pre> | |
| 2563 | {#code_end#} | |
| 2628 | 2564 | {#see_also|Errors#} |
| 2629 | 2565 | {#header_close#} |
| 2630 | 2566 | {#header_open|unreachable#} |
| ... | ... | @@ -2638,7 +2574,8 @@ OK |
| 2638 | 2574 | still emits <code>unreachable</code> as calls to <code>panic</code>. |
| 2639 | 2575 | </p> |
| 2640 | 2576 | {#header_open|Basics#} |
| 2641 | <pre><code class="zig">// unreachable is used to assert that control flow will never happen upon a | |
| 2577 | {#code_begin|test#} | |
| 2578 | // unreachable is used to assert that control flow will never happen upon a | |
| 2642 | 2579 | // particular location: |
| 2643 | 2580 | test "basic math" { |
| 2644 | 2581 | const x = 1; |
| ... | ... | @@ -2647,56 +2584,34 @@ test "basic math" { |
| 2647 | 2584 | unreachable; |
| 2648 | 2585 | } |
| 2649 | 2586 | } |
| 2650 | ||
| 2651 | // in fact, this is how assert is implemented: | |
| 2652 | fn assert(ok: bool) { | |
| 2587 | {#code_end#} | |
| 2588 | <p>In fact, this is how assert is implemented:</p> | |
| 2589 | {#code_begin|test_err#} | |
| 2590 | fn assert(ok: bool) void { | |
| 2653 | 2591 | if (!ok) unreachable; // assertion failure |
| 2654 | 2592 | } |
| 2655 | 2593 | |
| 2656 | 2594 | // This test will fail because we hit unreachable. |
| 2657 | 2595 | test "this will fail" { |
| 2658 | 2596 | assert(false); |
| 2659 | }</code></pre> | |
| 2660 | <pre><code class="sh">$ zig test test.zig | |
| 2661 | Test 1/2 basic math...OK | |
| 2662 | Test 2/2 this will fail...reached unreachable code | |
| 2663 | test.zig:13:14: 0x00000000002033ac in ??? (test) | |
| 2664 | if (!ok) unreachable; // assertion failure | |
| 2665 | ^ | |
| 2666 | test.zig:18:11: 0x000000000020329b in ??? (test) | |
| 2667 | assert(false); | |
| 2668 | ^ | |
| 2669 | lib/zig/std/special/test_runner.zig:9:21: 0x0000000000214a7a in ??? (test) | |
| 2670 | test_fn.func(); | |
| 2671 | ^ | |
| 2672 | lib/zig/std/special/bootstrap.zig:60:21: 0x0000000000214947 in ??? (test) | |
| 2673 | return root.main(); | |
| 2674 | ^ | |
| 2675 | lib/zig/std/special/bootstrap.zig:47:13: 0x0000000000214800 in ??? (test) | |
| 2676 | callMain(argc, argv, envp) catch std.os.posix.exit(1); | |
| 2677 | ^ | |
| 2678 | lib/zig/std/special/bootstrap.zig:34:25: 0x0000000000214750 in ??? (test) | |
| 2679 | posixCallMainAndExit() | |
| 2680 | ^ | |
| 2681 | ||
| 2682 | Tests failed. Use the following command to reproduce the failure: | |
| 2683 | ./test</code></pre> | |
| 2597 | } | |
| 2598 | {#code_end#} | |
| 2684 | 2599 | {#header_close#} |
| 2685 | 2600 | {#header_open|At Compile-Time#} |
| 2686 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 2601 | {#code_begin|test_err|unreachable code#} | |
| 2602 | const assert = @import("std").debug.assert; | |
| 2687 | 2603 | |
| 2688 | comptime { | |
| 2689 | // The type of unreachable is noreturn. | |
| 2604 | test "type of unreachable" { | |
| 2605 | comptime { | |
| 2606 | // The type of unreachable is noreturn. | |
| 2690 | 2607 | |
| 2691 | // However this assertion will still fail because | |
| 2692 | // evaluating unreachable at compile-time is a compile error. | |
| 2608 | // However this assertion will still fail because | |
| 2609 | // evaluating unreachable at compile-time is a compile error. | |
| 2693 | 2610 | |
| 2694 | assert(@typeOf(unreachable) == noreturn); | |
| 2695 | }</code></pre> | |
| 2696 | <pre><code class="sh">$ zig build-obj test.zig | |
| 2697 | test.zig:9:12: error: unreachable code | |
| 2698 | assert(@typeOf(unreachable) == noreturn); | |
| 2699 | ^</code></pre> | |
| 2611 | assert(@typeOf(unreachable) == noreturn); | |
| 2612 | } | |
| 2613 | } | |
| 2614 | {#code_end#} | |
| 2700 | 2615 | {#see_also|Zig Test|Build Mode|comptime#} |
| 2701 | 2616 | {#header_close#} |
| 2702 | 2617 | {#header_close#} |
| ... | ... | @@ -2707,7 +2622,6 @@ test.zig:9:12: error: unreachable code |
| 2707 | 2622 | <ul> |
| 2708 | 2623 | <li><code>break</code></li> |
| 2709 | 2624 | <li><code>continue</code></li> |
| 2710 | <li><code>goto</code></li> | |
| 2711 | 2625 | <li><code>return</code></li> |
| 2712 | 2626 | <li><code>unreachable</code></li> |
| 2713 | 2627 | <li><code>while (true) {}</code></li> |
| ... | ... | @@ -2715,31 +2629,38 @@ test.zig:9:12: error: unreachable code |
| 2715 | 2629 | <p>When resolving types together, such as <code>if</code> clauses or <code>switch</code> prongs, |
| 2716 | 2630 | the <code>noreturn</code> type is compatible with every other type. Consider: |
| 2717 | 2631 | </p> |
| 2718 | <pre><code class="zig">fn foo(condition: bool, b: u32) { | |
| 2632 | {#code_begin|test#} | |
| 2633 | fn foo(condition: bool, b: u32) void { | |
| 2719 | 2634 | const a = if (condition) b else return; |
| 2720 | bar(a); | |
| 2635 | @panic("do something with a"); | |
| 2721 | 2636 | } |
| 2722 | ||
| 2723 | extern fn bar(value: u32);</code></pre> | |
| 2637 | test "noreturn" { | |
| 2638 | foo(false, 1); | |
| 2639 | } | |
| 2640 | {#code_end#} | |
| 2724 | 2641 | <p>Another use case for <code>noreturn</code> is the <code>exit</code> function:</p> |
| 2725 | <pre><code class="zig">pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: c_uint) -&gt; noreturn; | |
| 2642 | {#code_begin|test#} | |
| 2643 | {#target_windows#} | |
| 2644 | pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: c_uint) noreturn; | |
| 2726 | 2645 | |
| 2727 | fn foo() { | |
| 2646 | test "foo" { | |
| 2728 | 2647 | const value = bar() catch ExitProcess(1); |
| 2729 | 2648 | assert(value == 1234); |
| 2730 | 2649 | } |
| 2731 | 2650 | |
| 2732 | fn bar() -&gt; %u32 { | |
| 2651 | fn bar() %u32 { | |
| 2733 | 2652 | return 1234; |
| 2734 | 2653 | } |
| 2735 | 2654 | |
| 2736 | const assert = @import("std").debug.assert;</code></pre> | |
| 2655 | const assert = @import("std").debug.assert; | |
| 2656 | {#code_end#} | |
| 2737 | 2657 | {#header_close#} |
| 2738 | 2658 | {#header_open|Functions#} |
| 2739 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 2659 | {#code_begin|test|functions#} | |
| 2660 | const assert = @import("std").debug.assert; | |
| 2740 | 2661 | |
| 2741 | 2662 | // Functions are declared like this |
| 2742 | fn add(a: i8, b: i8) -&gt; i8 { | |
| 2663 | fn add(a: i8, b: i8) i8 { | |
| 2743 | 2664 | if (a == 0) { |
| 2744 | 2665 | // You can still return manually if needed. |
| 2745 | 2666 | return b; |
| ... | ... | @@ -2750,84 +2671,84 @@ fn add(a: i8, b: i8) -&gt; i8 { |
| 2750 | 2671 | |
| 2751 | 2672 | // The export specifier makes a function externally visible in the generated |
| 2752 | 2673 | // object file, and makes it use the C ABI. |
| 2753 | export fn sub(a: i8, b: i8) -&gt; i8 { a - b } | |
| 2674 | export fn sub(a: i8, b: i8) i8 { return a - b; } | |
| 2754 | 2675 | |
| 2755 | 2676 | // The extern specifier is used to declare a function that will be resolved |
| 2756 | 2677 | // at link time, when linking statically, or at runtime, when linking |
| 2757 | 2678 | // dynamically. |
| 2758 | 2679 | // The stdcallcc specifier changes the calling convention of the function. |
| 2759 | extern "kernel32" stdcallcc fn ExitProcess(exit_code: u32) -&gt; noreturn; | |
| 2760 | extern "c" fn atan2(a: f64, b: f64) -&gt; f64; | |
| 2680 | extern "kernel32" stdcallcc fn ExitProcess(exit_code: u32) noreturn; | |
| 2681 | extern "c" fn atan2(a: f64, b: f64) f64; | |
| 2761 | 2682 | |
| 2762 | // coldcc makes a function use the cold calling convention. | |
| 2763 | coldcc fn abort() -&gt; noreturn { | |
| 2683 | // The @setCold builtin tells the optimizer that a function is rarely called. | |
| 2684 | fn abort() noreturn { | |
| 2685 | @setCold(true); | |
| 2764 | 2686 | while (true) {} |
| 2765 | 2687 | } |
| 2766 | 2688 | |
| 2767 | 2689 | // nakedcc makes a function not have any function prologue or epilogue. |
| 2768 | 2690 | // This can be useful when integrating with assembly. |
| 2769 | nakedcc fn _start() -&gt; noreturn { | |
| 2691 | nakedcc fn _start() noreturn { | |
| 2770 | 2692 | abort(); |
| 2771 | 2693 | } |
| 2772 | 2694 | |
| 2773 | 2695 | // The pub specifier allows the function to be visible when importing. |
| 2774 | 2696 | // Another file can use @import and call sub2 |
| 2775 | pub fn sub2(a: i8, b: i8) -&gt; i8 { a - b } | |
| 2697 | pub fn sub2(a: i8, b: i8) i8 { return a - b; } | |
| 2776 | 2698 | |
| 2777 | 2699 | // Functions can be used as values and are equivalent to pointers. |
| 2778 | const call2_op = fn (a: i8, b: i8) -&gt; i8; | |
| 2779 | fn do_op(fn_call: call2_op, op1: i8, op2: i8) -&gt; i8 { | |
| 2780 | fn_call(op1, op2) | |
| 2700 | const call2_op = fn (a: i8, b: i8) i8; | |
| 2701 | fn do_op(fn_call: call2_op, op1: i8, op2: i8) i8 { | |
| 2702 | return fn_call(op1, op2); | |
| 2781 | 2703 | } |
| 2782 | 2704 | |
| 2783 | 2705 | test "function" { |
| 2784 | 2706 | assert(do_op(add, 5, 6) == 11); |
| 2785 | 2707 | assert(do_op(sub2, 5, 6) == -1); |
| 2786 | }</code></pre> | |
| 2787 | <pre><code class="sh">$ zig test function.zig | |
| 2788 | Test 1/1 function...OK | |
| 2789 | </code></pre> | |
| 2708 | } | |
| 2709 | {#code_end#} | |
| 2790 | 2710 | <p>Function values are like pointers:</p> |
| 2791 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 2711 | {#code_begin|obj#} | |
| 2712 | const assert = @import("std").debug.assert; | |
| 2792 | 2713 | |
| 2793 | 2714 | comptime { |
| 2794 | assert(@typeOf(foo) == fn()); | |
| 2795 | assert(@sizeOf(fn()) == @sizeOf(?fn())); | |
| 2715 | assert(@typeOf(foo) == fn()void); | |
| 2716 | assert(@sizeOf(fn()void) == @sizeOf(?fn()void)); | |
| 2796 | 2717 | } |
| 2797 | 2718 | |
| 2798 | fn foo() { }</code></pre> | |
| 2799 | <pre><code class="sh">$ zig build-obj test.zig</code></pre> | |
| 2719 | fn foo() void { } | |
| 2720 | {#code_end#} | |
| 2800 | 2721 | {#header_open|Pass-by-value Parameters#} |
| 2801 | 2722 | <p> |
| 2802 | 2723 | In Zig, structs, unions, and enums with payloads cannot be passed by value |
| 2803 | 2724 | to a function. |
| 2804 | 2725 | </p> |
| 2805 | <pre><code class="zig">const Foo = struct { | |
| 2726 | {#code_begin|test_err|not copyable; cannot pass by value#} | |
| 2727 | const Foo = struct { | |
| 2806 | 2728 | x: i32, |
| 2807 | 2729 | }; |
| 2808 | 2730 | |
| 2809 | fn bar(foo: Foo) {} | |
| 2731 | fn bar(foo: Foo) void {} | |
| 2810 | 2732 | |
| 2811 | export fn entry() { | |
| 2733 | test "pass aggregate type by value to function" { | |
| 2812 | 2734 | bar(Foo {.x = 12,}); |
| 2813 | }</code></pre> | |
| 2814 | <pre><code class="sh">$ ./zig build-obj test.zig | |
| 2815 | /home/andy/dev/zig/build/test.zig:5:13: error: type 'Foo' is not copyable; cannot pass by value | |
| 2816 | fn bar(foo: Foo) {} | |
| 2817 | ^</code></pre> | |
| 2735 | } | |
| 2736 | {#code_end#} | |
| 2818 | 2737 | <p> |
| 2819 | 2738 | Instead, one must use <code>&amp;const</code>. Zig allows implicitly casting something |
| 2820 | 2739 | to a const pointer to it: |
| 2821 | 2740 | </p> |
| 2822 | <pre><code class="zig">const Foo = struct { | |
| 2741 | {#code_begin|test#} | |
| 2742 | const Foo = struct { | |
| 2823 | 2743 | x: i32, |
| 2824 | 2744 | }; |
| 2825 | 2745 | |
| 2826 | fn bar(foo: &amp;const Foo) {} | |
| 2746 | fn bar(foo: &const Foo) void {} | |
| 2827 | 2747 | |
| 2828 | export fn entry() { | |
| 2748 | test "implicitly cast to const pointer" { | |
| 2829 | 2749 | bar(Foo {.x = 12,}); |
| 2830 | }</code></pre> | |
| 2750 | } | |
| 2751 | {#code_end#} | |
| 2831 | 2752 | <p> |
| 2832 | 2753 | However, |
| 2833 | 2754 | the C ABI does allow passing structs and unions by value. So functions which |
| ... | ... | @@ -2842,9 +2763,11 @@ export fn entry() { |
| 2842 | 2763 | <p> |
| 2843 | 2764 | Among the top level declarations available is the error value declaration: |
| 2844 | 2765 | </p> |
| 2845 | <pre><code class="zig">error FileNotFound; | |
| 2766 | {#code_begin|syntax#} | |
| 2767 | error FileNotFound; | |
| 2846 | 2768 | error OutOfMemory; |
| 2847 | error UnexpectedToken;</code></pre> | |
| 2769 | error UnexpectedToken; | |
| 2770 | {#code_end#} | |
| 2848 | 2771 | <p> |
| 2849 | 2772 | These error values are assigned an unsigned integer value greater than 0 at |
| 2850 | 2773 | compile time. You are allowed to declare the same error value more than once, |
| ... | ... | @@ -2862,7 +2785,7 @@ error UnexpectedToken;</code></pre> |
| 2862 | 2785 | The pure error type is one of the error values, and in the same way that pointers |
| 2863 | 2786 | cannot be null, a pure error is always an error. |
| 2864 | 2787 | </p> |
| 2865 | <pre><code class="zig">const pure_error = error.FileNotFound;</code></pre> | |
| 2788 | {#code_begin|syntax#}const pure_error = error.FileNotFound;{#code_end#} | |
| 2866 | 2789 | <p> |
| 2867 | 2790 | Most of the time you will not find yourself using a pure error type. Instead, |
| 2868 | 2791 | likely you will be using the error union type. This is when you take a normal type, |
| ... | ... | @@ -2871,32 +2794,48 @@ error UnexpectedToken;</code></pre> |
| 2871 | 2794 | <p> |
| 2872 | 2795 | Here is a function to parse a string into a 64-bit integer: |
| 2873 | 2796 | </p> |
| 2874 | <pre><code class="zig">error InvalidChar; | |
| 2797 | {#code_begin|test#} | |
| 2798 | error InvalidChar; | |
| 2875 | 2799 | error Overflow; |
| 2876 | 2800 | |
| 2877 | pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 { | |
| 2801 | pub fn parseU64(buf: []const u8, radix: u8) %u64 { | |
| 2878 | 2802 | var x: u64 = 0; |
| 2879 | 2803 | |
| 2880 | 2804 | for (buf) |c| { |
| 2881 | 2805 | const digit = charToDigit(c); |
| 2882 | 2806 | |
| 2883 | if (digit &gt;= radix) { | |
| 2807 | if (digit >= radix) { | |
| 2884 | 2808 | return error.InvalidChar; |
| 2885 | 2809 | } |
| 2886 | 2810 | |
| 2887 | 2811 | // x *= radix |
| 2888 | if (@mulWithOverflow(u64, x, radix, &amp;x)) { | |
| 2812 | if (@mulWithOverflow(u64, x, radix, &x)) { | |
| 2889 | 2813 | return error.Overflow; |
| 2890 | 2814 | } |
| 2891 | 2815 | |
| 2892 | 2816 | // x += digit |
| 2893 | if (@addWithOverflow(u64, x, digit, &amp;x)) { | |
| 2817 | if (@addWithOverflow(u64, x, digit, &x)) { | |
| 2894 | 2818 | return error.Overflow; |
| 2895 | 2819 | } |
| 2896 | 2820 | } |
| 2897 | 2821 | |
| 2898 | 2822 | return x; |
| 2899 | }</code></pre> | |
| 2823 | } | |
| 2824 | ||
| 2825 | fn charToDigit(c: u8) u8 { | |
| 2826 | return switch (c) { | |
| 2827 | '0' ... '9' => c - '0', | |
| 2828 | 'A' ... 'Z' => c - 'A' + 10, | |
| 2829 | 'a' ... 'z' => c - 'a' + 10, | |
| 2830 | else => @maxValue(u8), | |
| 2831 | }; | |
| 2832 | } | |
| 2833 | ||
| 2834 | test "parse u64" { | |
| 2835 | const result = try parseU64("1234", 10); | |
| 2836 | @import("std").debug.assert(result == 1234); | |
| 2837 | } | |
| 2838 | {#code_end#} | |
| 2900 | 2839 | <p> |
| 2901 | 2840 | Notice the return type is <code>%u64</code>. This means that the function |
| 2902 | 2841 | either returns an unsigned 64 bit integer, or an error. |
| ... | ... | @@ -2916,29 +2855,35 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 { |
| 2916 | 2855 | <li>You know with complete certainty it will not return an error, so want to unconditionally unwrap it.</li> |
| 2917 | 2856 | <li>You want to take a different action for each possible error.</li> |
| 2918 | 2857 | </ul> |
| 2919 | <p>If you want to provide a default value, you can use the <code>%%</code> binary operator:</p> | |
| 2920 | <pre><code class="zig">fn doAThing(str: []u8) { | |
| 2858 | <p>If you want to provide a default value, you can use the <code>catch</code> binary operator:</p> | |
| 2859 | {#code_begin|syntax#} | |
| 2860 | fn doAThing(str: []u8) void { | |
| 2921 | 2861 | const number = parseU64(str, 10) catch 13; |
| 2922 | 2862 | // ... |
| 2923 | }</code></pre> | |
| 2863 | } | |
| 2864 | {#code_end#} | |
| 2924 | 2865 | <p> |
| 2925 | 2866 | In this code, <code>number</code> will be equal to the successfully parsed string, or |
| 2926 | a default value of 13. The type of the right hand side of the binary <code>%%</code> operator must | |
| 2867 | a default value of 13. The type of the right hand side of the binary <code>catch</code> operator must | |
| 2927 | 2868 | match the unwrapped error union type, or be of type <code>noreturn</code>. |
| 2928 | 2869 | </p> |
| 2929 | 2870 | <p>Let's say you wanted to return the error if you got one, otherwise continue with the |
| 2930 | 2871 | function logic:</p> |
| 2931 | <pre><code class="zig">fn doAThing(str: []u8) -&gt; %void { | |
| 2872 | {#code_begin|syntax#} | |
| 2873 | fn doAThing(str: []u8) %void { | |
| 2932 | 2874 | const number = parseU64(str, 10) catch |err| return err; |
| 2933 | 2875 | // ... |
| 2934 | }</code></pre> | |
| 2876 | } | |
| 2877 | {#code_end#} | |
| 2935 | 2878 | <p> |
| 2936 | 2879 | There is a shortcut for this. The <code>try</code> expression: |
| 2937 | 2880 | </p> |
| 2938 | <pre><code class="zig">fn doAThing(str: []u8) -&gt; %void { | |
| 2881 | {#code_begin|syntax#} | |
| 2882 | fn doAThing(str: []u8) %void { | |
| 2939 | 2883 | const number = try parseU64(str, 10); |
| 2940 | 2884 | // ... |
| 2941 | }</code></pre> | |
| 2885 | } | |
| 2886 | {#code_end#} | |
| 2942 | 2887 | <p> |
| 2943 | 2888 | <code>try</code> evaluates an error union expression. If it is an error, it returns |
| 2944 | 2889 | from the current function with the same error. Otherwise, the expression results in |
| ... | ... | @@ -2948,61 +2893,60 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 { |
| 2948 | 2893 | Maybe you know with complete certainty that an expression will never be an error. |
| 2949 | 2894 | In this case you can do this: |
| 2950 | 2895 | </p> |
| 2951 | <pre><code class="zig">const number = parseU64("1234", 10) catch unreachable;</code></pre> | |
| 2896 | {#code_begin|syntax#}const number = parseU64("1234", 10) catch unreachable;{#code_end#} | |
| 2952 | 2897 | <p> |
| 2953 | 2898 | Here we know for sure that "1234" will parse successfully. So we put the |
| 2954 | 2899 | <code>unreachable</code> value on the right hand side. <code>unreachable</code> generates |
| 2955 | 2900 | a panic in Debug and ReleaseSafe modes and undefined behavior in ReleaseFast mode. So, while we're debugging the |
| 2956 | 2901 | application, if there <em>was</em> a surprise error here, the application would crash |
| 2957 | 2902 | appropriately. |
| 2958 | </p> | |
| 2959 | <p>Again there is a syntactic shortcut for this:</p> | |
| 2960 | <pre><code class="zig">const number = %%parseU64("1234", 10);</code></pre> | |
| 2961 | <p> | |
| 2962 | The <code>%%</code> <em>prefix</em> operator is equivalent to <code class="zig">expression catch unreachable</code>. It unwraps an error union type, | |
| 2963 | and panics in debug mode if the value was an error. | |
| 2903 | TODO: mention error return traces | |
| 2964 | 2904 | </p> |
| 2965 | 2905 | <p> |
| 2966 | 2906 | Finally, you may want to take a different action for every situation. For that, we combine |
| 2967 | 2907 | the <code>if</code> and <code>switch</code> expression: |
| 2968 | 2908 | </p> |
| 2969 | <pre><code class="zig">fn doAThing(str: []u8) { | |
| 2909 | {#code_begin|syntax#} | |
| 2910 | fn doAThing(str: []u8) void { | |
| 2970 | 2911 | if (parseU64(str, 10)) |number| { |
| 2971 | 2912 | doSomethingWithNumber(number); |
| 2972 | 2913 | } else |err| switch (err) { |
| 2973 | error.Overflow =&gt; { | |
| 2914 | error.Overflow => { | |
| 2974 | 2915 | // handle overflow... |
| 2975 | 2916 | }, |
| 2976 | 2917 | // we promise that InvalidChar won't happen (or crash in debug mode if it does) |
| 2977 | error.InvalidChar =&gt; unreachable, | |
| 2918 | error.InvalidChar => unreachable, | |
| 2978 | 2919 | } |
| 2979 | }</code></pre> | |
| 2920 | } | |
| 2921 | {#code_end#} | |
| 2980 | 2922 | <p> |
| 2981 | 2923 | The other component to error handling is defer statements. |
| 2982 | In addition to an unconditional <code>defer</code>, Zig has <code>%defer</code>, | |
| 2924 | In addition to an unconditional <code>defer</code>, Zig has <code>errdefer</code>, | |
| 2983 | 2925 | which evaluates the deferred expression on block exit path if and only if |
| 2984 | 2926 | the function returned with an error from the block. |
| 2985 | 2927 | </p> |
| 2986 | 2928 | <p> |
| 2987 | 2929 | Example: |
| 2988 | 2930 | </p> |
| 2989 | <pre><code class="zig">fn createFoo(param: i32) -&gt; %Foo { | |
| 2931 | {#code_begin|syntax#} | |
| 2932 | fn createFoo(param: i32) %Foo { | |
| 2990 | 2933 | const foo = try tryToAllocateFoo(); |
| 2991 | 2934 | // now we have allocated foo. we need to free it if the function fails. |
| 2992 | 2935 | // but we want to return it if the function succeeds. |
| 2993 | %defer deallocateFoo(foo); | |
| 2936 | errdefer deallocateFoo(foo); | |
| 2994 | 2937 | |
| 2995 | 2938 | const tmp_buf = allocateTmpBuffer() ?? return error.OutOfMemory; |
| 2996 | 2939 | // tmp_buf is truly a temporary resource, and we for sure want to clean it up |
| 2997 | 2940 | // before this block leaves scope |
| 2998 | 2941 | defer deallocateTmpBuffer(tmp_buf); |
| 2999 | 2942 | |
| 3000 | if (param &gt; 1337) return error.InvalidParam; | |
| 2943 | if (param > 1337) return error.InvalidParam; | |
| 3001 | 2944 | |
| 3002 | // here the %defer will not run since we're returning success from the function. | |
| 2945 | // here the errdefer will not run since we're returning success from the function. | |
| 3003 | 2946 | // but the defer will run! |
| 3004 | 2947 | return foo; |
| 3005 | }</code></pre> | |
| 2948 | } | |
| 2949 | {#code_end#} | |
| 3006 | 2950 | <p> |
| 3007 | 2951 | The neat thing about this is that you get robust error handling without |
| 3008 | 2952 | the verbosity and cognitive overhead of trying to make sure every exit path |
| ... | ... | @@ -3014,7 +2958,7 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 { |
| 3014 | 2958 | <ul> |
| 3015 | 2959 | <li>These primitives give enough expressiveness that it's completely practical |
| 3016 | 2960 | to have failing to check for an error be a compile error. If you really want |
| 3017 | to ignore the error, you can use the <code>%%</code> prefix operator and | |
| 2961 | to ignore the error, you can add <code>catch unreachable</code> and | |
| 3018 | 2962 | get the added benefit of crashing in Debug and ReleaseSafe modes if your assumption was wrong. |
| 3019 | 2963 | </li> |
| 3020 | 2964 | <li> |
| ... | ... | @@ -3034,11 +2978,13 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 { |
| 3034 | 2978 | The question mark symbolizes the nullable type. You can convert a type to a nullable |
| 3035 | 2979 | type by putting a question mark in front of it, like this: |
| 3036 | 2980 | </p> |
| 3037 | <pre><code class="zig">// normal integer | |
| 2981 | {#code_begin|syntax#} | |
| 2982 | // normal integer | |
| 3038 | 2983 | const normal_int: i32 = 1234; |
| 3039 | 2984 | |
| 3040 | 2985 | // nullable integer |
| 3041 | const nullable_int: ?i32 = 5678;</code></pre> | |
| 2986 | const nullable_int: ?i32 = 5678; | |
| 2987 | {#code_end#} | |
| 3042 | 2988 | <p> |
| 3043 | 2989 | Now the variable <code>nullable_int</code> could be an <code>i32</code>, or <code>null</code>. |
| 3044 | 2990 | </p> |
| ... | ... | @@ -3061,7 +3007,7 @@ const nullable_int: ?i32 = 5678;</code></pre> |
| 3061 | 3007 | Task: call malloc, if the result is null, return null. |
| 3062 | 3008 | </p> |
| 3063 | 3009 | <p>C code</p> |
| 3064 | <pre><code class="c">// malloc prototype included for reference | |
| 3010 | <pre><code class="cpp">// malloc prototype included for reference | |
| 3065 | 3011 | void *malloc(size_t size); |
| 3066 | 3012 | |
| 3067 | 3013 | struct Foo *do_a_thing(void) { |
| ... | ... | @@ -3070,23 +3016,25 @@ struct Foo *do_a_thing(void) { |
| 3070 | 3016 | // ... |
| 3071 | 3017 | }</code></pre> |
| 3072 | 3018 | <p>Zig code</p> |
| 3073 | <pre><code class="zig">// malloc prototype included for reference | |
| 3074 | extern fn malloc(size: size_t) -&gt; ?&amp;u8; | |
| 3019 | {#code_begin|syntax#} | |
| 3020 | // malloc prototype included for reference | |
| 3021 | extern fn malloc(size: size_t) ?&u8; | |
| 3075 | 3022 | |
| 3076 | fn doAThing() -&gt; ?&amp;Foo { | |
| 3023 | fn doAThing() ?&Foo { | |
| 3077 | 3024 | const ptr = malloc(1234) ?? return null; |
| 3078 | 3025 | // ... |
| 3079 | }</code></pre> | |
| 3026 | } | |
| 3027 | {#code_end#} | |
| 3080 | 3028 | <p> |
| 3081 | 3029 | Here, Zig is at least as convenient, if not more, than C. And, the type of "ptr" |
| 3082 | is <code>&amp;u8</code> <em>not</em> <code>?&amp;u8</code>. The <code>??</code> operator | |
| 3030 | is <code>&u8</code> <em>not</em> <code>?&u8</code>. The <code>??</code> operator | |
| 3083 | 3031 | unwrapped the nullable type and therefore <code>ptr</code> is guaranteed to be non-null everywhere |
| 3084 | 3032 | it is used in the function. |
| 3085 | 3033 | </p> |
| 3086 | 3034 | <p> |
| 3087 | 3035 | The other form of checking against NULL you might see looks like this: |
| 3088 | 3036 | </p> |
| 3089 | <pre><code class="c">void do_a_thing(struct Foo *foo) { | |
| 3037 | <pre><code class="cpp">void do_a_thing(struct Foo *foo) { | |
| 3090 | 3038 | // do some stuff |
| 3091 | 3039 | |
| 3092 | 3040 | if (foo) { |
| ... | ... | @@ -3098,7 +3046,8 @@ fn doAThing() -&gt; ?&amp;Foo { |
| 3098 | 3046 | <p> |
| 3099 | 3047 | In Zig you can accomplish the same thing: |
| 3100 | 3048 | </p> |
| 3101 | <pre><code class="zig">fn doAThing(nullable_foo: ?&amp;Foo) { | |
| 3049 | {#code_begin|syntax#} | |
| 3050 | fn doAThing(nullable_foo: ?&Foo) void { | |
| 3102 | 3051 | // do some stuff |
| 3103 | 3052 | |
| 3104 | 3053 | if (nullable_foo) |foo| { |
| ... | ... | @@ -3106,7 +3055,8 @@ fn doAThing() -&gt; ?&amp;Foo { |
| 3106 | 3055 | } |
| 3107 | 3056 | |
| 3108 | 3057 | // do some stuff |
| 3109 | }</code></pre> | |
| 3058 | } | |
| 3059 | {#code_end#} | |
| 3110 | 3060 | <p> |
| 3111 | 3061 | Once again, the notable thing here is that inside the if block, |
| 3112 | 3062 | <code>foo</code> is no longer a nullable pointer, it is a pointer, which |
| ... | ... | @@ -3140,7 +3090,7 @@ fn doAThing() -&gt; ?&amp;Foo { |
| 3140 | 3090 | {#header_open|this#} |
| 3141 | 3091 | <p>TODO: example of this referring to Self struct</p> |
| 3142 | 3092 | <p>TODO: example of this referring to recursion function</p> |
| 3143 | <p>TODO: example of this referring to basic block for @setDebugSafety</p> | |
| 3093 | <p>TODO: example of this referring to basic block for @setRuntimeSafety</p> | |
| 3144 | 3094 | {#header_close#} |
| 3145 | 3095 | {#header_open|comptime#} |
| 3146 | 3096 | <p> |
| ... | ... | @@ -3153,15 +3103,17 @@ fn doAThing() -&gt; ?&amp;Foo { |
| 3153 | 3103 | <p> |
| 3154 | 3104 | Compile-time parameters is how Zig implements generics. It is compile-time duck typing. |
| 3155 | 3105 | </p> |
| 3156 | <pre><code class="zig">fn max(comptime T: type, a: T, b: T) -&gt; T { | |
| 3157 | if (a &gt; b) a else b | |
| 3106 | {#code_begin|syntax#} | |
| 3107 | fn max(comptime T: type, a: T, b: T) T { | |
| 3108 | return if (a > b) a else b; | |
| 3158 | 3109 | } |
| 3159 | fn gimmeTheBiggerFloat(a: f32, b: f32) -&gt; f32 { | |
| 3160 | max(f32, a, b) | |
| 3110 | fn gimmeTheBiggerFloat(a: f32, b: f32) f32 { | |
| 3111 | return max(f32, a, b); | |
| 3161 | 3112 | } |
| 3162 | fn gimmeTheBiggerInteger(a: u64, b: u64) -&gt; u64 { | |
| 3163 | max(u64, a, b) | |
| 3164 | }</code></pre> | |
| 3113 | fn gimmeTheBiggerInteger(a: u64, b: u64) u64 { | |
| 3114 | return max(u64, a, b); | |
| 3115 | } | |
| 3116 | {#code_end#} | |
| 3165 | 3117 | <p> |
| 3166 | 3118 | In Zig, types are first-class citizens. They can be assigned to variables, passed as parameters to functions, |
| 3167 | 3119 | and returned from functions. However, they can only be used in expressions which are known at <em>compile-time</em>, |
| ... | ... | @@ -3179,21 +3131,20 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) -&gt; u64 { |
| 3179 | 3131 | <p> |
| 3180 | 3132 | For example, if we were to introduce another function to the above snippet: |
| 3181 | 3133 | </p> |
| 3182 | <pre><code class="zig">fn max(comptime T: type, a: T, b: T) -&gt; T { | |
| 3183 | if (a &gt; b) a else b | |
| 3134 | {#code_begin|test_err|unable to evaluate constant expression#} | |
| 3135 | fn max(comptime T: type, a: T, b: T) T { | |
| 3136 | return if (a > b) a else b; | |
| 3137 | } | |
| 3138 | test "try to pass a runtime type" { | |
| 3139 | foo(false); | |
| 3184 | 3140 | } |
| 3185 | fn letsTryToPassARuntimeType(condition: bool) { | |
| 3141 | fn foo(condition: bool) void { | |
| 3186 | 3142 | const result = max( |
| 3187 | 3143 | if (condition) f32 else u64, |
| 3188 | 3144 | 1234, |
| 3189 | 3145 | 5678); |
| 3190 | }</code></pre> | |
| 3191 | <p> | |
| 3192 | Then we get this result from the compiler: | |
| 3193 | </p> | |
| 3194 | <pre><code class="sh">./test.zig:6:9: error: unable to evaluate constant expression | |
| 3195 | if (condition) f32 else u64, | |
| 3196 | ^</code></pre> | |
| 3146 | } | |
| 3147 | {#code_end#} | |
| 3197 | 3148 | <p> |
| 3198 | 3149 | This is an error because the programmer attempted to pass a value only known at run-time |
| 3199 | 3150 | to a function which expects a value known at compile-time. |
| ... | ... | @@ -3205,38 +3156,33 @@ fn letsTryToPassARuntimeType(condition: bool) { |
| 3205 | 3156 | <p> |
| 3206 | 3157 | For example: |
| 3207 | 3158 | </p> |
| 3208 | <pre><code class="zig">fn max(comptime T: type, a: T, b: T) -&gt; T { | |
| 3209 | if (a &gt; b) a else b | |
| 3159 | {#code_begin|test_err|operator not allowed for type 'bool'#} | |
| 3160 | fn max(comptime T: type, a: T, b: T) T { | |
| 3161 | return if (a > b) a else b; | |
| 3210 | 3162 | } |
| 3211 | fn letsTryToCompareBools(a: bool, b: bool) -&gt; bool { | |
| 3212 | max(bool, a, b) | |
| 3213 | }</code></pre> | |
| 3214 | <p> | |
| 3215 | The code produces this error message: | |
| 3216 | </p> | |
| 3217 | <pre><code>./test.zig:2:11: error: operator not allowed for type 'bool' | |
| 3218 | if (a &gt; b) a else b | |
| 3219 | ^ | |
| 3220 | ./test.zig:5:8: note: called from here | |
| 3221 | max(bool, a, b) | |
| 3222 | ^</code></pre> | |
| 3163 | test "try to compare bools" { | |
| 3164 | _ = max(bool, true, false); | |
| 3165 | } | |
| 3166 | {#code_end#} | |
| 3223 | 3167 | <p> |
| 3224 | 3168 | On the flip side, inside the function definition with the <code>comptime</code> parameter, the |
| 3225 | 3169 | value is known at compile-time. This means that we actually could make this work for the bool type |
| 3226 | 3170 | if we wanted to: |
| 3227 | 3171 | </p> |
| 3228 | <pre><code class="zig">fn max(comptime T: type, a: T, b: T) -&gt; T { | |
| 3172 | {#code_begin|test#} | |
| 3173 | fn max(comptime T: type, a: T, b: T) T { | |
| 3229 | 3174 | if (T == bool) { |
| 3230 | 3175 | return a or b; |
| 3231 | } else if (a &gt; b) { | |
| 3176 | } else if (a > b) { | |
| 3232 | 3177 | return a; |
| 3233 | 3178 | } else { |
| 3234 | 3179 | return b; |
| 3235 | 3180 | } |
| 3236 | 3181 | } |
| 3237 | fn letsTryToCompareBools(a: bool, b: bool) -&gt; bool { | |
| 3238 | max(bool, a, b) | |
| 3239 | }</code></pre> | |
| 3182 | test "try to compare bools" { | |
| 3183 | @import("std").debug.assert(max(bool, false, true) == true); | |
| 3184 | } | |
| 3185 | {#code_end#} | |
| 3240 | 3186 | <p> |
| 3241 | 3187 | This works because Zig implicitly inlines <code>if</code> expressions when the condition |
| 3242 | 3188 | is known at compile-time, and the compiler guarantees that it will skip analysis of |
| ... | ... | @@ -3246,9 +3192,11 @@ fn letsTryToCompareBools(a: bool, b: bool) -&gt; bool { |
| 3246 | 3192 | This means that the actual function generated for <code>max</code> in this situation looks like |
| 3247 | 3193 | this: |
| 3248 | 3194 | </p> |
| 3249 | <pre><code class="zig">fn max(a: bool, b: bool) -&gt; bool { | |
| 3195 | {#code_begin|syntax#} | |
| 3196 | fn max(a: bool, b: bool) bool { | |
| 3250 | 3197 | return a or b; |
| 3251 | }</code></pre> | |
| 3198 | } | |
| 3199 | {#code_end#} | |
| 3252 | 3200 | <p> |
| 3253 | 3201 | All the code that dealt with compile-time known values is eliminated and we are left with only |
| 3254 | 3202 | the necessary run-time code to accomplish the task. |
| ... | ... | @@ -3271,11 +3219,12 @@ fn letsTryToCompareBools(a: bool, b: bool) -&gt; bool { |
| 3271 | 3219 | <p> |
| 3272 | 3220 | For example: |
| 3273 | 3221 | </p> |
| 3274 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 3222 | {#code_begin|test|comptime_vars#} | |
| 3223 | const assert = @import("std").debug.assert; | |
| 3275 | 3224 | |
| 3276 | 3225 | const CmdFn = struct { |
| 3277 | 3226 | name: []const u8, |
| 3278 | func: fn(i32) -&gt; i32, | |
| 3227 | func: fn(i32) i32, | |
| 3279 | 3228 | }; |
| 3280 | 3229 | |
| 3281 | 3230 | const cmd_fns = []CmdFn{ |
| ... | ... | @@ -3283,14 +3232,14 @@ const cmd_fns = []CmdFn{ |
| 3283 | 3232 | CmdFn {.name = "two", .func = two}, |
| 3284 | 3233 | CmdFn {.name = "three", .func = three}, |
| 3285 | 3234 | }; |
| 3286 | fn one(value: i32) -&gt; i32 { value + 1 } | |
| 3287 | fn two(value: i32) -&gt; i32 { value + 2 } | |
| 3288 | fn three(value: i32) -&gt; i32 { value + 3 } | |
| 3235 | fn one(value: i32) i32 { return value + 1; } | |
| 3236 | fn two(value: i32) i32 { return value + 2; } | |
| 3237 | fn three(value: i32) i32 { return value + 3; } | |
| 3289 | 3238 | |
| 3290 | fn performFn(comptime prefix_char: u8, start_value: i32) -&gt; i32 { | |
| 3239 | fn performFn(comptime prefix_char: u8, start_value: i32) i32 { | |
| 3291 | 3240 | var result: i32 = start_value; |
| 3292 | 3241 | comptime var i = 0; |
| 3293 | inline while (i &lt; cmd_fns.len) : (i += 1) { | |
| 3242 | inline while (i < cmd_fns.len) : (i += 1) { | |
| 3294 | 3243 | if (cmd_fns[i].name[0] == prefix_char) { |
| 3295 | 3244 | result = cmd_fns[i].func(result); |
| 3296 | 3245 | } |
| ... | ... | @@ -3302,36 +3251,41 @@ test "perform fn" { |
| 3302 | 3251 | assert(performFn('t', 1) == 6); |
| 3303 | 3252 | assert(performFn('o', 0) == 1); |
| 3304 | 3253 | assert(performFn('w', 99) == 99); |
| 3305 | }</code></pre> | |
| 3254 | } | |
| 3255 | {#code_end#} | |
| 3306 | 3256 | <p> |
| 3307 | 3257 | This example is a bit contrived, because the compile-time evaluation component is unnecessary; |
| 3308 | 3258 | this code would work fine if it was all done at run-time. But it does end up generating |
| 3309 | 3259 | different code. In this example, the function <code>performFn</code> is generated three different times, |
| 3310 | 3260 | for the different values of <code>prefix_char</code> provided: |
| 3311 | 3261 | </p> |
| 3312 | <pre><code class="zig">// From the line: | |
| 3262 | {#code_begin|syntax#} | |
| 3263 | // From the line: | |
| 3313 | 3264 | // assert(performFn('t', 1) == 6); |
| 3314 | fn performFn(start_value: i32) -&gt; i32 { | |
| 3265 | fn performFn(start_value: i32) i32 { | |
| 3315 | 3266 | var result: i32 = start_value; |
| 3316 | 3267 | result = two(result); |
| 3317 | 3268 | result = three(result); |
| 3318 | 3269 | return result; |
| 3319 | 3270 | } |
| 3320 | ||
| 3271 | {#code_end#} | |
| 3272 | {#code_begin|syntax#} | |
| 3321 | 3273 | // From the line: |
| 3322 | 3274 | // assert(performFn('o', 0) == 1); |
| 3323 | fn performFn(start_value: i32) -&gt; i32 { | |
| 3275 | fn performFn(start_value: i32) i32 { | |
| 3324 | 3276 | var result: i32 = start_value; |
| 3325 | 3277 | result = one(result); |
| 3326 | 3278 | return result; |
| 3327 | 3279 | } |
| 3328 | ||
| 3280 | {#code_end#} | |
| 3281 | {#code_begin|syntax#} | |
| 3329 | 3282 | // From the line: |
| 3330 | 3283 | // assert(performFn('w', 99) == 99); |
| 3331 | fn performFn(start_value: i32) -&gt; i32 { | |
| 3284 | fn performFn(start_value: i32) i32 { | |
| 3332 | 3285 | var result: i32 = start_value; |
| 3333 | 3286 | return result; |
| 3334 | }</code></pre> | |
| 3287 | } | |
| 3288 | {#code_end#} | |
| 3335 | 3289 | <p> |
| 3336 | 3290 | Note that this happens even in a debug build; in a release build these generated functions still |
| 3337 | 3291 | pass through rigorous LLVM optimizations. The important thing to note, however, is not that this |
| ... | ... | @@ -3347,16 +3301,15 @@ fn performFn(start_value: i32) -&gt; i32 { |
| 3347 | 3301 | use a <code>comptime</code> expression to guarantee that the expression will be evaluated at compile-time. |
| 3348 | 3302 | If this cannot be accomplished, the compiler will emit an error. For example: |
| 3349 | 3303 | </p> |
| 3350 | <pre><code class="zig">extern fn exit() -&gt; unreachable; | |
| 3304 | {#code_begin|test_err|unable to evaluate constant expression#} | |
| 3305 | extern fn exit() noreturn; | |
| 3351 | 3306 | |
| 3352 | fn foo() { | |
| 3307 | test "foo" { | |
| 3353 | 3308 | comptime { |
| 3354 | 3309 | exit(); |
| 3355 | 3310 | } |
| 3356 | }</code></pre> | |
| 3357 | <pre><code>./test.zig:5:9: error: unable to evaluate constant expression | |
| 3358 | exit(); | |
| 3359 | ^</code></pre> | |
| 3311 | } | |
| 3312 | {#code_end#} | |
| 3360 | 3313 | <p> |
| 3361 | 3314 | It doesn't make sense that a program could call <code>exit()</code> (or any other external function) |
| 3362 | 3315 | at compile-time, so this is a compile error. However, a <code>comptime</code> expression does much |
| ... | ... | @@ -3367,7 +3320,7 @@ fn foo() { |
| 3367 | 3320 | </p> |
| 3368 | 3321 | <ul> |
| 3369 | 3322 | <li>All variables are <code>comptime</code> variables.</li> |
| 3370 | <li>All <code>if</code>, <code>while</code>, <code>for</code>, <code>switch</code>, and <code>goto</code> | |
| 3323 | <li>All <code>if</code>, <code>while</code>, <code>for</code>, and <code>switch</code> | |
| 3371 | 3324 | expressions are evaluated at compile-time, or emit a compile error if this is not possible.</li> |
| 3372 | 3325 | <li>All function calls cause the compiler to interpret the function at compile-time, emitting a |
| 3373 | 3326 | compile error if the function tries to do something that has global run-time side effects.</li> |
| ... | ... | @@ -3379,10 +3332,11 @@ fn foo() { |
| 3379 | 3332 | <p> |
| 3380 | 3333 | Let's look at an example: |
| 3381 | 3334 | </p> |
| 3382 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 3335 | {#code_begin|test#} | |
| 3336 | const assert = @import("std").debug.assert; | |
| 3383 | 3337 | |
| 3384 | fn fibonacci(index: u32) -&gt; u32 { | |
| 3385 | if (index &lt; 2) return index; | |
| 3338 | fn fibonacci(index: u32) u32 { | |
| 3339 | if (index < 2) return index; | |
| 3386 | 3340 | return fibonacci(index - 1) + fibonacci(index - 2); |
| 3387 | 3341 | } |
| 3388 | 3342 | |
| ... | ... | @@ -3394,16 +3348,16 @@ test "fibonacci" { |
| 3394 | 3348 | comptime { |
| 3395 | 3349 | assert(fibonacci(7) == 13); |
| 3396 | 3350 | } |
| 3397 | }</code></pre> | |
| 3398 | <pre><code>$ zig test test.zig | |
| 3399 | Test 1/1 testFibonacci...OK</code></pre> | |
| 3351 | } | |
| 3352 | {#code_end#} | |
| 3400 | 3353 | <p> |
| 3401 | 3354 | Imagine if we had forgotten the base case of the recursive function and tried to run the tests: |
| 3402 | 3355 | </p> |
| 3403 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 3356 | {#code_begin|test_err|operation caused overflow#} | |
| 3357 | const assert = @import("std").debug.assert; | |
| 3404 | 3358 | |
| 3405 | fn fibonacci(index: u32) -&gt; u32 { | |
| 3406 | //if (index &lt; 2) return index; | |
| 3359 | fn fibonacci(index: u32) u32 { | |
| 3360 | //if (index < 2) return index; | |
| 3407 | 3361 | return fibonacci(index - 1) + fibonacci(index - 2); |
| 3408 | 3362 | } |
| 3409 | 3363 | |
| ... | ... | @@ -3411,35 +3365,8 @@ test "fibonacci" { |
| 3411 | 3365 | comptime { |
| 3412 | 3366 | assert(fibonacci(7) == 13); |
| 3413 | 3367 | } |
| 3414 | }</code></pre> | |
| 3415 | <pre><code>$ zig test test.zig | |
| 3416 | ./test.zig:3:28: error: operation caused overflow | |
| 3417 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3418 | ^ | |
| 3419 | ./test.zig:3:21: note: called from here | |
| 3420 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3421 | ^ | |
| 3422 | ./test.zig:3:21: note: called from here | |
| 3423 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3424 | ^ | |
| 3425 | ./test.zig:3:21: note: called from here | |
| 3426 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3427 | ^ | |
| 3428 | ./test.zig:3:21: note: called from here | |
| 3429 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3430 | ^ | |
| 3431 | ./test.zig:3:21: note: called from here | |
| 3432 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3433 | ^ | |
| 3434 | ./test.zig:3:21: note: called from here | |
| 3435 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3436 | ^ | |
| 3437 | ./test.zig:3:21: note: called from here | |
| 3438 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3439 | ^ | |
| 3440 | ./test.zig:14:25: note: called from here | |
| 3441 | assert(fibonacci(7) == 13); | |
| 3442 | ^</code></pre> | |
| 3368 | } | |
| 3369 | {#code_end#} | |
| 3443 | 3370 | <p> |
| 3444 | 3371 | The compiler produces an error which is a stack trace from trying to evaluate the |
| 3445 | 3372 | function at compile-time. |
| ... | ... | @@ -3449,10 +3376,11 @@ test "fibonacci" { |
| 3449 | 3376 | undefined behavior, which is always a compile error if the compiler knows it happened. |
| 3450 | 3377 | But what would have happened if we used a signed integer? |
| 3451 | 3378 | </p> |
| 3452 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 3379 | {#code_begin|test_err|evaluation exceeded 1000 backwards branches#} | |
| 3380 | const assert = @import("std").debug.assert; | |
| 3453 | 3381 | |
| 3454 | fn fibonacci(index: i32) -&gt; i32 { | |
| 3455 | //if (index &lt; 2) return index; | |
| 3382 | fn fibonacci(index: i32) i32 { | |
| 3383 | //if (index < 2) return index; | |
| 3456 | 3384 | return fibonacci(index - 1) + fibonacci(index - 2); |
| 3457 | 3385 | } |
| 3458 | 3386 | |
| ... | ... | @@ -3460,61 +3388,31 @@ test "fibonacci" { |
| 3460 | 3388 | comptime { |
| 3461 | 3389 | assert(fibonacci(7) == 13); |
| 3462 | 3390 | } |
| 3463 | }</code></pre> | |
| 3464 | <pre><code>./test.zig:3:21: error: evaluation exceeded 1000 backwards branches | |
| 3465 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3466 | ^ | |
| 3467 | ./test.zig:3:21: note: called from here | |
| 3468 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3469 | ^ | |
| 3470 | ./test.zig:3:21: note: called from here | |
| 3471 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3472 | ^ | |
| 3473 | ./test.zig:3:21: note: called from here | |
| 3474 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3475 | ^ | |
| 3476 | ./test.zig:3:21: note: called from here | |
| 3477 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3478 | ^ | |
| 3479 | ./test.zig:3:21: note: called from here | |
| 3480 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3481 | ^ | |
| 3482 | ./test.zig:3:21: note: called from here | |
| 3483 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3484 | ^ | |
| 3485 | ./test.zig:3:21: note: called from here | |
| 3486 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3487 | ^ | |
| 3488 | ./test.zig:3:21: note: called from here | |
| 3489 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3490 | ^ | |
| 3491 | ./test.zig:3:21: note: called from here | |
| 3492 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3493 | ^ | |
| 3494 | ./test.zig:3:21: note: called from here | |
| 3495 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3496 | ^ | |
| 3497 | ./test.zig:3:21: note: called from here | |
| 3498 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3499 | ^</code></pre> | |
| 3391 | } | |
| 3392 | {#code_end#} | |
| 3500 | 3393 | <p> |
| 3501 | 3394 | The compiler noticed that evaluating this function at compile-time took a long time, |
| 3502 | 3395 | and thus emitted a compile error and gave up. If the programmer wants to increase |
| 3503 | 3396 | the budget for compile-time computation, they can use a built-in function called |
| 3504 | <a href="#builtin-setEvalBranchQuota">@setEvalBranchQuota</a> to change the default number 1000 to something else. | |
| 3397 | {#link|@setEvalBranchQuota#} to change the default number 1000 to something else. | |
| 3505 | 3398 | </p> |
| 3506 | 3399 | <p> |
| 3507 | 3400 | What if we fix the base case, but put the wrong value in the <code>assert</code> line? |
| 3508 | 3401 | </p> |
| 3509 | <pre><code class="zig">comptime { | |
| 3510 | assert(fibonacci(7) == 99999); | |
| 3511 | }</code></pre> | |
| 3512 | <pre><code>./test.zig:15:14: error: unable to evaluate constant expression | |
| 3513 | if (!ok) unreachable; | |
| 3514 | ^ | |
| 3515 | ./test.zig:10:15: note: called from here | |
| 3402 | {#code_begin|test_err|encountered @panic at compile-time#} | |
| 3403 | const assert = @import("std").debug.assert; | |
| 3404 | ||
| 3405 | fn fibonacci(index: i32) i32 { | |
| 3406 | if (index < 2) return index; | |
| 3407 | return fibonacci(index - 1) + fibonacci(index - 2); | |
| 3408 | } | |
| 3409 | ||
| 3410 | test "fibonacci" { | |
| 3411 | comptime { | |
| 3516 | 3412 | assert(fibonacci(7) == 99999); |
| 3517 | ^</code></pre> | |
| 3413 | } | |
| 3414 | } | |
| 3415 | {#code_end#} | |
| 3518 | 3416 | <p> |
| 3519 | 3417 | What happened is Zig started interpreting the <code>assert</code> function with the |
| 3520 | 3418 | parameter <code>ok</code> set to <code>false</code>. When the interpreter hit |
| ... | ... | @@ -3528,17 +3426,18 @@ test "fibonacci" { |
| 3528 | 3426 | <code>comptime</code> expressions. This means that we can use functions to |
| 3529 | 3427 | initialize complex static data. For example: |
| 3530 | 3428 | </p> |
| 3531 | <pre><code class="zig">const first_25_primes = firstNPrimes(25); | |
| 3429 | {#code_begin|test#} | |
| 3430 | const first_25_primes = firstNPrimes(25); | |
| 3532 | 3431 | const sum_of_first_25_primes = sum(first_25_primes); |
| 3533 | 3432 | |
| 3534 | fn firstNPrimes(comptime n: usize) -&gt; [n]i32 { | |
| 3433 | fn firstNPrimes(comptime n: usize) [n]i32 { | |
| 3535 | 3434 | var prime_list: [n]i32 = undefined; |
| 3536 | 3435 | var next_index: usize = 0; |
| 3537 | 3436 | var test_number: i32 = 2; |
| 3538 | while (next_index &lt; prime_list.len) : (test_number += 1) { | |
| 3437 | while (next_index < prime_list.len) : (test_number += 1) { | |
| 3539 | 3438 | var test_prime_index: usize = 0; |
| 3540 | 3439 | var is_prime = true; |
| 3541 | while (test_prime_index &lt; next_index) : (test_prime_index += 1) { | |
| 3440 | while (test_prime_index < next_index) : (test_prime_index += 1) { | |
| 3542 | 3441 | if (test_number % prime_list[test_prime_index] == 0) { |
| 3543 | 3442 | is_prime = false; |
| 3544 | 3443 | break; |
| ... | ... | @@ -3552,19 +3451,24 @@ fn firstNPrimes(comptime n: usize) -&gt; [n]i32 { |
| 3552 | 3451 | return prime_list; |
| 3553 | 3452 | } |
| 3554 | 3453 | |
| 3555 | fn sum(numbers: []i32) -&gt; i32 { | |
| 3454 | fn sum(numbers: []const i32) i32 { | |
| 3556 | 3455 | var result: i32 = 0; |
| 3557 | 3456 | for (numbers) |x| { |
| 3558 | 3457 | result += x; |
| 3559 | 3458 | } |
| 3560 | 3459 | return result; |
| 3561 | }</code></pre> | |
| 3460 | } | |
| 3461 | ||
| 3462 | test "variable values" { | |
| 3463 | @import("std").debug.assert(sum_of_first_25_primes == 1060); | |
| 3464 | } | |
| 3465 | {#code_end#} | |
| 3562 | 3466 | <p> |
| 3563 | 3467 | When we compile this program, Zig generates the constants |
| 3564 | 3468 | with the answer pre-computed. Here are the lines from the generated LLVM IR: |
| 3565 | 3469 | </p> |
| 3566 | <pre><code>@0 = internal unnamed_addr constant [25 x i32] [i32 2, i32 3, i32 5, i32 7, i32 11, i32 13, i32 17, i32 19, i32 23, i32 29, i32 31, i32 37, i32 41, i32 43, i32 47, i32 53, i32 59, i32 61, i32 67, i32 71, i32 73, i32 79, i32 83, i32 89, i32 97] | |
| 3567 | @1 = internal unnamed_addr constant i32 1060</code></pre> | |
| 3470 | <pre><code class="llvm">@0 = internal unnamed_addr constant [25 x i32] [i32 2, i32 3, i32 5, i32 7, i32 11, i32 13, i32 17, i32 19, i32 23, i32 29, i32 31, i32 37, i32 41, i32 43, i32 47, i32 53, i32 59, i32 61, i32 67, i32 71, i32 73, i32 79, i32 83, i32 89, i32 97] | |
| 3471 | @1 = internal unnamed_addr constant i32 1060</code></pre> | |
| 3568 | 3472 | <p> |
| 3569 | 3473 | Note that we did not have to do anything special with the syntax of these functions. For example, |
| 3570 | 3474 | we could call the <code>sum</code> function as is with a slice of numbers whose length and values were |
| ... | ... | @@ -3582,12 +3486,14 @@ fn sum(numbers: []i32) -&gt; i32 { |
| 3582 | 3486 | Here is an example of a generic <code>List</code> data structure, that we will instantiate with |
| 3583 | 3487 | the type <code>i32</code>. In Zig we refer to the type as <code>List(i32)</code>. |
| 3584 | 3488 | </p> |
| 3585 | <pre><code class="zig">fn List(comptime T: type) -&gt; type { | |
| 3586 | struct { | |
| 3489 | {#code_begin|syntax#} | |
| 3490 | fn List(comptime T: type) type { | |
| 3491 | return struct { | |
| 3587 | 3492 | items: []T, |
| 3588 | 3493 | len: usize, |
| 3589 | } | |
| 3590 | }</code></pre> | |
| 3494 | }; | |
| 3495 | } | |
| 3496 | {#code_end#} | |
| 3591 | 3497 | <p> |
| 3592 | 3498 | That's it. It's a function that returns an anonymous <code>struct</code>. For the purposes of error messages |
| 3593 | 3499 | and debugging, Zig infers the name <code>"List(i32)"</code> from the function name and parameters invoked when creating |
| ... | ... | @@ -3597,10 +3503,12 @@ fn sum(numbers: []i32) -&gt; i32 { |
| 3597 | 3503 | To keep the language small and uniform, all aggregate types in Zig are anonymous. To give a type |
| 3598 | 3504 | a name, we assign it to a constant: |
| 3599 | 3505 | </p> |
| 3600 | <pre><code class="zig">const Node = struct { | |
| 3601 | next: &amp;Node, | |
| 3506 | {#code_begin|syntax#} | |
| 3507 | const Node = struct { | |
| 3508 | next: &Node, | |
| 3602 | 3509 | name: []u8, |
| 3603 | };</code></pre> | |
| 3510 | }; | |
| 3511 | {#code_end#} | |
| 3604 | 3512 | <p> |
| 3605 | 3513 | This works because all top level declarations are order-independent, and as long as there isn't |
| 3606 | 3514 | an actual infinite regression, values can refer to themselves, directly or indirectly. In this case, |
| ... | ... | @@ -3618,7 +3526,7 @@ const warn = @import("std").debug.warn; |
| 3618 | 3526 | const a_number: i32 = 1234; |
| 3619 | 3527 | const a_string = "foobar"; |
| 3620 | 3528 | |
| 3621 | pub fn main() { | |
| 3529 | pub fn main() void { | |
| 3622 | 3530 | warn("here is a string: '{}' here is a number: {}\n", a_string, a_number); |
| 3623 | 3531 | } |
| 3624 | 3532 | {#code_end#} |
| ... | ... | @@ -3627,8 +3535,9 @@ pub fn main() { |
| 3627 | 3535 | Let's crack open the implementation of this and see how it works: |
| 3628 | 3536 | </p> |
| 3629 | 3537 | |
| 3630 | <pre><code class="zig">/// Calls print and then flushes the buffer. | |
| 3631 | pub fn printf(self: &amp;OutStream, comptime format: []const u8, args: ...) -&gt; %void { | |
| 3538 | {#code_begin|syntax#} | |
| 3539 | /// Calls print and then flushes the buffer. | |
| 3540 | pub fn printf(self: &OutStream, comptime format: []const u8, args: ...) %void { | |
| 3632 | 3541 | const State = enum { |
| 3633 | 3542 | Start, |
| 3634 | 3543 | OpenBrace, |
| ... | ... | @@ -3641,36 +3550,36 @@ pub fn printf(self: &amp;OutStream, comptime format: []const u8, args: ...) -&gt |
| 3641 | 3550 | |
| 3642 | 3551 | inline for (format) |c, i| { |
| 3643 | 3552 | switch (state) { |
| 3644 | State.Start =&gt; switch (c) { | |
| 3645 | '{' =&gt; { | |
| 3646 | if (start_index &lt; i) try self.write(format[start_index...i]); | |
| 3553 | State.Start => switch (c) { | |
| 3554 | '{' => { | |
| 3555 | if (start_index < i) try self.write(format[start_index..i]); | |
| 3647 | 3556 | state = State.OpenBrace; |
| 3648 | 3557 | }, |
| 3649 | '}' =&gt; { | |
| 3650 | if (start_index &lt; i) try self.write(format[start_index...i]); | |
| 3558 | '}' => { | |
| 3559 | if (start_index < i) try self.write(format[start_index..i]); | |
| 3651 | 3560 | state = State.CloseBrace; |
| 3652 | 3561 | }, |
| 3653 | else =&gt; {}, | |
| 3562 | else => {}, | |
| 3654 | 3563 | }, |
| 3655 | State.OpenBrace =&gt; switch (c) { | |
| 3656 | '{' =&gt; { | |
| 3564 | State.OpenBrace => switch (c) { | |
| 3565 | '{' => { | |
| 3657 | 3566 | state = State.Start; |
| 3658 | 3567 | start_index = i; |
| 3659 | 3568 | }, |
| 3660 | '}' =&gt; { | |
| 3569 | '}' => { | |
| 3661 | 3570 | try self.printValue(args[next_arg]); |
| 3662 | 3571 | next_arg += 1; |
| 3663 | 3572 | state = State.Start; |
| 3664 | 3573 | start_index = i + 1; |
| 3665 | 3574 | }, |
| 3666 | else =&gt; @compileError("Unknown format character: " ++ c), | |
| 3575 | else => @compileError("Unknown format character: " ++ c), | |
| 3667 | 3576 | }, |
| 3668 | State.CloseBrace =&gt; switch (c) { | |
| 3669 | '}' =&gt; { | |
| 3577 | State.CloseBrace => switch (c) { | |
| 3578 | '}' => { | |
| 3670 | 3579 | state = State.Start; |
| 3671 | 3580 | start_index = i; |
| 3672 | 3581 | }, |
| 3673 | else =&gt; @compileError("Single '}' encountered in format string"), | |
| 3582 | else => @compileError("Single '}' encountered in format string"), | |
| 3674 | 3583 | }, |
| 3675 | 3584 | } |
| 3676 | 3585 | } |
| ... | ... | @@ -3682,11 +3591,12 @@ pub fn printf(self: &amp;OutStream, comptime format: []const u8, args: ...) -&gt |
| 3682 | 3591 | @compileError("Incomplete format string: " ++ format); |
| 3683 | 3592 | } |
| 3684 | 3593 | } |
| 3685 | if (start_index &lt; format.len) { | |
| 3686 | try self.write(format[start_index...format.len]); | |
| 3594 | if (start_index < format.len) { | |
| 3595 | try self.write(format[start_index..format.len]); | |
| 3687 | 3596 | } |
| 3688 | 3597 | try self.flush(); |
| 3689 | }</code></pre> | |
| 3598 | } | |
| 3599 | {#code_end#} | |
| 3690 | 3600 | <p> |
| 3691 | 3601 | This is a proof of concept implementation; the actual function in the standard library has more |
| 3692 | 3602 | formatting capabilities. |
| ... | ... | @@ -3698,19 +3608,22 @@ pub fn printf(self: &amp;OutStream, comptime format: []const u8, args: ...) -&gt |
| 3698 | 3608 | When this function is analyzed from our example code above, Zig partially evaluates the function |
| 3699 | 3609 | and emits a function that actually looks like this: |
| 3700 | 3610 | </p> |
| 3701 | <pre><code class="zig">pub fn printf(self: &amp;OutStream, arg0: i32, arg1: []const u8) -&gt; %void { | |
| 3611 | {#code_begin|syntax#} | |
| 3612 | pub fn printf(self: &OutStream, arg0: i32, arg1: []const u8) %void { | |
| 3702 | 3613 | try self.write("here is a string: '"); |
| 3703 | 3614 | try self.printValue(arg0); |
| 3704 | 3615 | try self.write("' here is a number: "); |
| 3705 | 3616 | try self.printValue(arg1); |
| 3706 | 3617 | try self.write("\n"); |
| 3707 | 3618 | try self.flush(); |
| 3708 | }</code></pre> | |
| 3619 | } | |
| 3620 | {#code_end#} | |
| 3709 | 3621 | <p> |
| 3710 | 3622 | <code>printValue</code> is a function that takes a parameter of any type, and does different things depending |
| 3711 | 3623 | on the type: |
| 3712 | 3624 | </p> |
| 3713 | <pre><code class="zig">pub fn printValue(self: &amp;OutStream, value: var) -&gt; %void { | |
| 3625 | {#code_begin|syntax#} | |
| 3626 | pub fn printValue(self: &OutStream, value: var) %void { | |
| 3714 | 3627 | const T = @typeOf(value); |
| 3715 | 3628 | if (@isInteger(T)) { |
| 3716 | 3629 | return self.printInt(T, value); |
| ... | ... | @@ -3722,18 +3635,22 @@ pub fn printf(self: &amp;OutStream, comptime format: []const u8, args: ...) -&gt |
| 3722 | 3635 | } else { |
| 3723 | 3636 | @compileError("Unable to print type '" ++ @typeName(T) ++ "'"); |
| 3724 | 3637 | } |
| 3725 | }</code></pre> | |
| 3638 | } | |
| 3639 | {#code_end#} | |
| 3726 | 3640 | <p> |
| 3727 | 3641 | And now, what happens if we give too many arguments to <code>printf</code>? |
| 3728 | 3642 | </p> |
| 3729 | <pre><code class="zig">warn("here is a string: '{}' here is a number: {}\n", | |
| 3730 | a_string, a_number, a_number);</code></pre> | |
| 3731 | <pre><code>.../std/io.zig:147:17: error: Unused arguments | |
| 3732 | @compileError("Unused arguments"); | |
| 3733 | ^ | |
| 3734 | ./test.zig:7:23: note: called from here | |
| 3735 | warn("here is a number: {} and here is a string: {}\n", | |
| 3736 | ^</code></pre> | |
| 3643 | {#code_begin|test_err|Unused arguments#} | |
| 3644 | const warn = @import("std").debug.warn; | |
| 3645 | ||
| 3646 | const a_number: i32 = 1234; | |
| 3647 | const a_string = "foobar"; | |
| 3648 | ||
| 3649 | test "printf too many arguments" { | |
| 3650 | warn("here is a string: '{}' here is a number: {}\n", | |
| 3651 | a_string, a_number, a_number); | |
| 3652 | } | |
| 3653 | {#code_end#} | |
| 3737 | 3654 | <p> |
| 3738 | 3655 | Zig gives programmers the tools needed to protect themselves against their own mistakes. |
| 3739 | 3656 | </p> |
| ... | ... | @@ -3748,7 +3665,7 @@ const a_number: i32 = 1234; |
| 3748 | 3665 | const a_string = "foobar"; |
| 3749 | 3666 | const fmt = "here is a string: '{}' here is a number: {}\n"; |
| 3750 | 3667 | |
| 3751 | pub fn main() { | |
| 3668 | pub fn main() void { | |
| 3752 | 3669 | warn(fmt, a_string, a_number); |
| 3753 | 3670 | } |
| 3754 | 3671 | {#code_end#} |
| ... | ... | @@ -3786,7 +3703,7 @@ pub fn main() { |
| 3786 | 3703 | at compile time. |
| 3787 | 3704 | </p> |
| 3788 | 3705 | {#header_open|@addWithOverflow#} |
| 3789 | <pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre> | |
| 3706 | <pre><code class="zig">@addWithOverflow(comptime T: type, a: T, b: T, result: &T) -&gt; bool</code></pre> | |
| 3790 | 3707 | <p> |
| 3791 | 3708 | Performs <code>*result = a + b</code>. If overflow or underflow occurs, |
| 3792 | 3709 | stores the overflowed bits in <code>result</code> and returns <code>true</code>. |
| ... | ... | @@ -3836,7 +3753,7 @@ pub fn main() { |
| 3836 | 3753 | <code>?fn()</code>, or <code>[]T</code>. It returns the same type as <code>ptr</code> |
| 3837 | 3754 | except with the alignment adjusted to the new value. |
| 3838 | 3755 | </p> |
| 3839 | <p>A <a href="#undef-incorrect-pointer-alignment">pointer alignment safety check</a> is added | |
| 3756 | <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added | |
| 3840 | 3757 | to the generated code to make sure the pointer is aligned as promised.</p> |
| 3841 | 3758 | |
| 3842 | 3759 | {#header_close#} |
| ... | ... | @@ -3849,11 +3766,11 @@ pub fn main() { |
| 3849 | 3766 | </p> |
| 3850 | 3767 | <pre><code class="zig">const assert = @import("std").debug.assert; |
| 3851 | 3768 | comptime { |
| 3852 | assert(&amp;u32 == &amp;align(@alignOf(u32)) u32); | |
| 3769 | assert(&u32 == &align(@alignOf(u32)) u32); | |
| 3853 | 3770 | }</code></pre> |
| 3854 | 3771 | <p> |
| 3855 | 3772 | The result is a target-specific compile time constant. It is guaranteed to be |
| 3856 | less than or equal to <a href="#builtin-sizeOf">@sizeOf(T)</a>. | |
| 3773 | less than or equal to {#link|@sizeOf(T)|@sizeOf#}. | |
| 3857 | 3774 | </p> |
| 3858 | 3775 | {#see_also|Alignment#} |
| 3859 | 3776 | {#header_close#} |
| ... | ... | @@ -3933,7 +3850,7 @@ comptime { |
| 3933 | 3850 | |
| 3934 | 3851 | {#header_close#} |
| 3935 | 3852 | {#header_open|@cmpxchg#} |
| 3936 | <pre><code class="zig">@cmpxchg(ptr: &amp;T, cmp: T, new: T, success_order: AtomicOrder, fail_order: AtomicOrder) -&gt; bool</code></pre> | |
| 3853 | <pre><code class="zig">@cmpxchg(ptr: &T, cmp: T, new: T, success_order: AtomicOrder, fail_order: AtomicOrder) -&gt; bool</code></pre> | |
| 3937 | 3854 | <p> |
| 3938 | 3855 | This function performs an atomic compare exchange operation. |
| 3939 | 3856 | </p> |
| ... | ... | @@ -3970,42 +3887,46 @@ comptime { |
| 3970 | 3887 | This function can be used to do "printf debugging" on |
| 3971 | 3888 | compile-time executing code. |
| 3972 | 3889 | </p> |
| 3973 | <pre><code class="zig">const warn = @import("std").debug.warn; | |
| 3890 | {#code_begin|test_err|found compile log statement#} | |
| 3891 | const warn = @import("std").debug.warn; | |
| 3974 | 3892 | |
| 3975 | const num1 = { | |
| 3893 | const num1 = blk: { | |
| 3976 | 3894 | var val1: i32 = 99; |
| 3977 | 3895 | @compileLog("comptime val1 = ", val1); |
| 3978 | 3896 | val1 = val1 + 1; |
| 3979 | val1 | |
| 3897 | break :blk val1; | |
| 3980 | 3898 | }; |
| 3981 | 3899 | |
| 3982 | pub fn main() -&gt; %void { | |
| 3900 | test "main" { | |
| 3983 | 3901 | @compileLog("comptime in main"); |
| 3984 | 3902 | |
| 3985 | 3903 | warn("Runtime in main, num1 = {}.\n", num1); |
| 3986 | }</code></pre> | |
| 3987 | ||
| 3904 | } | |
| 3905 | {#code_end#} | |
| 3988 | 3906 | </p> |
| 3989 | 3907 | <p> |
| 3990 | 3908 | will ouput: |
| 3991 | 3909 | </p> |
| 3992 | ||
| 3993 | <pre><code class="sh">$ zig build-exe test.zig | |
| 3994 | | "comptime in main" | |
| 3995 | | "comptime val1 = ", 99 | |
| 3996 | test.zig:14:5: error: found compile log statement | |
| 3997 | @compileLog("comptime in main"); | |
| 3998 | ^ | |
| 3999 | test.zig:6:2: error: found compile log statement | |
| 4000 | @compileLog("comptime val1 = ", val1); | |
| 4001 | ^</code></pre> | |
| 4002 | 3910 | <p> |
| 4003 | 3911 | If all <code>@compileLog</code> calls are removed or |
| 4004 | 3912 | not encountered by analysis, the |
| 4005 | 3913 | program compiles successfully and the generated executable prints: |
| 4006 | 3914 | </p> |
| 4007 | <pre><code class="sh">Runtime in main, num1 = 100.</code></pre> | |
| 4008 | {{@ctheader_open:z}} | |
| 3915 | {#code_begin|test#} | |
| 3916 | const warn = @import("std").debug.warn; | |
| 3917 | ||
| 3918 | const num1 = blk: { | |
| 3919 | var val1: i32 = 99; | |
| 3920 | val1 = val1 + 1; | |
| 3921 | break :blk val1; | |
| 3922 | }; | |
| 3923 | ||
| 3924 | test "main" { | |
| 3925 | warn("Runtime in main, num1 = {}.\n", num1); | |
| 3926 | } | |
| 3927 | {#code_end#} | |
| 3928 | {#header_close#} | |
| 3929 | {#header_open|@ctz#} | |
| 4009 | 3930 | <pre><code class="zig">@ctz(x: T) -&gt; U</code></pre> |
| 4010 | 3931 | <p> |
| 4011 | 3932 | This function counts the number of trailing zeroes in <code>x</code> which is an integer |
| ... | ... | @@ -4110,7 +4031,7 @@ test.zig:6:2: error: found compile log statement |
| 4110 | 4031 | </p> |
| 4111 | 4032 | {#header_close#} |
| 4112 | 4033 | {#header_open|@errorReturnTrace#} |
| 4113 | <pre><code class="zig">@errorReturnTrace() -&gt; ?&amp;builtin.StackTrace</code></pre> | |
| 4034 | <pre><code class="zig">@errorReturnTrace() -&gt; ?&builtin.StackTrace</code></pre> | |
| 4114 | 4035 | <p> |
| 4115 | 4036 | If the binary is built with error return tracing, and this function is invoked in a |
| 4116 | 4037 | function that calls a function with an error or error union return type, returns a |
| ... | ... | @@ -4129,7 +4050,7 @@ test.zig:6:2: error: found compile log statement |
| 4129 | 4050 | {#header_close#} |
| 4130 | 4051 | {#header_open|@fieldParentPtr#} |
| 4131 | 4052 | <pre><code class="zig">@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8, |
| 4132 | field_ptr: &amp;T) -&gt; &amp;ParentType</code></pre> | |
| 4053 | field_ptr: &T) -&gt; &ParentType</code></pre> | |
| 4133 | 4054 | <p> |
| 4134 | 4055 | Given a pointer to a field, returns the base pointer of a struct. |
| 4135 | 4056 | </p> |
| ... | ... | @@ -4173,12 +4094,15 @@ test.zig:6:2: error: found compile log statement |
| 4173 | 4094 | <p> |
| 4174 | 4095 | This calls a function, in the same way that invoking an expression with parentheses does: |
| 4175 | 4096 | </p> |
| 4176 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 4097 | {#code_begin|test#} | |
| 4098 | const assert = @import("std").debug.assert; | |
| 4099 | ||
| 4177 | 4100 | test "inline function call" { |
| 4178 | 4101 | assert(@inlineCall(add, 3, 9) == 12); |
| 4179 | 4102 | } |
| 4180 | 4103 | |
| 4181 | fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre> | |
| 4104 | fn add(a: i32, b: i32) i32 { return a + b; } | |
| 4105 | {#code_end#} | |
| 4182 | 4106 | <p> |
| 4183 | 4107 | Unlike a normal function call, however, <code>@inlineCall</code> guarantees that the call |
| 4184 | 4108 | will be inlined. If the call cannot be inlined, a compile error is emitted. |
| ... | ... | @@ -4188,7 +4112,7 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre> |
| 4188 | 4112 | {#header_open|@intToPtr#} |
| 4189 | 4113 | <pre><code class="zig">@intToPtr(comptime DestType: type, int: usize) -&gt; DestType</code></pre> |
| 4190 | 4114 | <p> |
| 4191 | Converts an integer to a pointer. To convert the other way, use <a href="#builtin-ptrToInt">@ptrToInt</a>. | |
| 4115 | Converts an integer to a pointer. To convert the other way, use {#link|@ptrToInt#}. | |
| 4192 | 4116 | </p> |
| 4193 | 4117 | {#header_close#} |
| 4194 | 4118 | {#header_open|@IntType#} |
| ... | ... | @@ -4222,7 +4146,7 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre> |
| 4222 | 4146 | <p>TODO</p> |
| 4223 | 4147 | {#header_close#} |
| 4224 | 4148 | {#header_open|@memcpy#} |
| 4225 | <pre><code class="zig">@memcpy(noalias dest: &amp;u8, noalias source: &amp;const u8, byte_count: usize)</code></pre> | |
| 4149 | <pre><code class="zig">@memcpy(noalias dest: &u8, noalias source: &const u8, byte_count: usize)</code></pre> | |
| 4226 | 4150 | <p> |
| 4227 | 4151 | This function copies bytes from one region of memory to another. <code>dest</code> and |
| 4228 | 4152 | <code>source</code> are both pointers and must not overlap. |
| ... | ... | @@ -4240,7 +4164,7 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre> |
| 4240 | 4164 | mem.copy(u8, dest[0...byte_count], source[0...byte_count]);</code></pre> |
| 4241 | 4165 | {#header_close#} |
| 4242 | 4166 | {#header_open|@memset#} |
| 4243 | <pre><code class="zig">@memset(dest: &amp;u8, c: u8, byte_count: usize)</code></pre> | |
| 4167 | <pre><code class="zig">@memset(dest: &u8, c: u8, byte_count: usize)</code></pre> | |
| 4244 | 4168 | <p> |
| 4245 | 4169 | This function sets a region of memory to <code>c</code>. <code>dest</code> is a pointer. |
| 4246 | 4170 | </p> |
| ... | ... | @@ -4279,7 +4203,7 @@ mem.set(u8, dest, c);</code></pre> |
| 4279 | 4203 | {#see_also|@rem#} |
| 4280 | 4204 | {#header_close#} |
| 4281 | 4205 | {#header_open|@mulWithOverflow#} |
| 4282 | <pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre> | |
| 4206 | <pre><code class="zig">@mulWithOverflow(comptime T: type, a: T, b: T, result: &T) -&gt; bool</code></pre> | |
| 4283 | 4207 | <p> |
| 4284 | 4208 | Performs <code>*result = a * b</code>. If overflow or underflow occurs, |
| 4285 | 4209 | stores the overflowed bits in <code>result</code> and returns <code>true</code>. |
| ... | ... | @@ -4318,17 +4242,19 @@ fn add(a: i32, b: i32) -&gt; i32 { a + b }</code></pre> |
| 4318 | 4242 | This is typically used for type safety when interacting with C code that does not expose struct details. |
| 4319 | 4243 | Example: |
| 4320 | 4244 | </p> |
| 4321 | <pre><code class="zig">const Derp = @OpaqueType(); | |
| 4245 | {#code_begin|test_err|expected type '&Derp', found '&Wat'#} | |
| 4246 | const Derp = @OpaqueType(); | |
| 4322 | 4247 | const Wat = @OpaqueType(); |
| 4323 | 4248 | |
| 4324 | extern fn bar(d: &amp;Derp); | |
| 4325 | export fn foo(w: &amp;Wat) { | |
| 4249 | extern fn bar(d: &Derp) void; | |
| 4250 | export fn foo(w: &Wat) void { | |
| 4326 | 4251 | bar(w); |
| 4327 | }</code></pre> | |
| 4328 | <pre><code class="sh">$ ./zig build-obj test.zig | |
| 4329 | test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat' | |
| 4330 | bar(w); | |
| 4331 | ^</code></pre> | |
| 4252 | } | |
| 4253 | ||
| 4254 | test "call foo" { | |
| 4255 | foo(undefined); | |
| 4256 | } | |
| 4257 | {#code_end#} | |
| 4332 | 4258 | {#header_close#} |
| 4333 | 4259 | {#header_open|@panic#} |
| 4334 | 4260 | <pre><code class="zig">@panic(message: []const u8) -&gt; noreturn</code></pre> |
| ... | ... | @@ -4363,7 +4289,7 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat' |
| 4363 | 4289 | <li><code>fn()</code></li> |
| 4364 | 4290 | <li><code>?fn()</code></li> |
| 4365 | 4291 | </ul> |
| 4366 | <p>To convert the other way, use <a href="#builtin-intToPtr">@intToPtr</a></p> | |
| 4292 | <p>To convert the other way, use {#link|@intToPtr#}</p> | |
| 4367 | 4293 | |
| 4368 | 4294 | {#header_close#} |
| 4369 | 4295 | {#header_open|@rem#} |
| ... | ... | @@ -4393,10 +4319,16 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat' |
| 4393 | 4319 | This function is only valid within function scope. |
| 4394 | 4320 | </p> |
| 4395 | 4321 | {#header_close#} |
| 4396 | {#header_open|@setDebugSafety#} | |
| 4397 | <pre><code class="zig">@setDebugSafety(scope, safety_on: bool)</code></pre> | |
| 4322 | {#header_open|@setCold#} | |
| 4323 | <pre><code class="zig">@setCold(is_cold: bool)</code></pre> | |
| 4324 | <p> | |
| 4325 | Tells the optimizer that a function is rarely called. | |
| 4326 | </p> | |
| 4327 | {#header_close#} | |
| 4328 | {#header_open|@setRuntimeSafety#} | |
| 4329 | <pre><code class="zig">@setRuntimeSafety(safety_on: bool)</code></pre> | |
| 4398 | 4330 | <p> |
| 4399 | Sets whether debug safety checks are on for a given scope. | |
| 4331 | Sets whether runtime safety checks are on for the scope that contains the function call. | |
| 4400 | 4332 | </p> |
| 4401 | 4333 | |
| 4402 | 4334 | {#header_close#} |
| ... | ... | @@ -4413,22 +4345,24 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat' |
| 4413 | 4345 | <p> |
| 4414 | 4346 | Example: |
| 4415 | 4347 | </p> |
| 4416 | <pre><code class="zig">comptime { | |
| 4417 | var i = 0; | |
| 4418 | while (i &lt; 1001) : (i += 1) {} | |
| 4419 | }</code></pre> | |
| 4420 | <pre><code class="sh">$ ./zig build-obj test.zig | |
| 4421 | /home/andy/dev/zig/build/test.zig:3:5: error: evaluation exceeded 1000 backwards branches | |
| 4422 | while (i &lt; 1001) : (i += 1) {} | |
| 4423 | ^</code></pre> | |
| 4424 | <p>Now we use <code>@setEvalBranchQuota</code>:</p> | |
| 4425 | <pre><code class="zig">comptime { | |
| 4426 | @setEvalBranchQuota(1001); | |
| 4427 | var i = 0; | |
| 4428 | while (i &lt; 1001) : (i += 1) {} | |
| 4429 | }</code></pre> | |
| 4430 | <pre><code class="sh">$ ./zig build-obj test.zig</code></pre> | |
| 4431 | <p>(no output because it worked fine)</p> | |
| 4348 | {#code_begin|test_err|evaluation exceeded 1000 backwards branches#} | |
| 4349 | test "foo" { | |
| 4350 | comptime { | |
| 4351 | var i = 0; | |
| 4352 | while (i < 1001) : (i += 1) {} | |
| 4353 | } | |
| 4354 | } | |
| 4355 | {#code_end#} | |
| 4356 | <p>Now we use <code class="zig">@setEvalBranchQuota</code>:</p> | |
| 4357 | {#code_begin|test#} | |
| 4358 | test "foo" { | |
| 4359 | comptime { | |
| 4360 | @setEvalBranchQuota(1001); | |
| 4361 | var i = 0; | |
| 4362 | while (i < 1001) : (i += 1) {} | |
| 4363 | } | |
| 4364 | } | |
| 4365 | {#code_end#} | |
| 4432 | 4366 | |
| 4433 | 4367 | {#see_also|comptime#} |
| 4434 | 4368 | {#header_close#} |
| ... | ... | @@ -4437,10 +4371,12 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat' |
| 4437 | 4371 | <p> |
| 4438 | 4372 | Sets the floating point mode for a given scope. Possible values are: |
| 4439 | 4373 | </p> |
| 4440 | <pre><code class="zig">pub const FloatMode = enum { | |
| 4374 | {#code_begin|syntax#} | |
| 4375 | pub const FloatMode = enum { | |
| 4441 | 4376 | Optimized, |
| 4442 | 4377 | Strict, |
| 4443 | };</code></pre> | |
| 4378 | }; | |
| 4379 | {#code_end#} | |
| 4444 | 4380 | <ul> |
| 4445 | 4381 | <li> |
| 4446 | 4382 | <code>Optimized</code> (default) - Floating point operations may do all of the following: |
| ... | ... | @@ -4486,7 +4422,7 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat' |
| 4486 | 4422 | {#see_also|@shrExact|@shlWithOverflow#} |
| 4487 | 4423 | {#header_close#} |
| 4488 | 4424 | {#header_open|@shlWithOverflow#} |
| 4489 | <pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &amp;T) -&gt; bool</code></pre> | |
| 4425 | <pre><code class="zig">@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: &T) -&gt; bool</code></pre> | |
| 4490 | 4426 | <p> |
| 4491 | 4427 | Performs <code>*result = a &lt;&lt; b</code>. If overflow or underflow occurs, |
| 4492 | 4428 | stores the overflowed bits in <code>result</code> and returns <code>true</code>. |
| ... | ... | @@ -4520,7 +4456,7 @@ test.zig:5:9: error: expected type '&amp;Derp', found '&amp;Wat' |
| 4520 | 4456 | </p> |
| 4521 | 4457 | {#header_close#} |
| 4522 | 4458 | {#header_open|@subWithOverflow#} |
| 4523 | <pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: &amp;T) -&gt; bool</code></pre> | |
| 4459 | <pre><code class="zig">@subWithOverflow(comptime T: type, a: T, b: T, result: &T) -&gt; bool</code></pre> | |
| 4524 | 4460 | <p> |
| 4525 | 4461 | Performs <code>*result = a - b</code>. If overflow or underflow occurs, |
| 4526 | 4462 | stores the overflowed bits in <code>result</code> and returns <code>true</code>. |
| ... | ... | @@ -4556,7 +4492,8 @@ const b: u8 = @truncate(u8, a); |
| 4556 | 4492 | <p> |
| 4557 | 4493 | Returns which kind of type something is. Possible values: |
| 4558 | 4494 | </p> |
| 4559 | <pre><code class="zig">pub const TypeId = enum { | |
| 4495 | {#code_begin|syntax#} | |
| 4496 | pub const TypeId = enum { | |
| 4560 | 4497 | Type, |
| 4561 | 4498 | Void, |
| 4562 | 4499 | Bool, |
| ... | ... | @@ -4574,7 +4511,6 @@ const b: u8 = @truncate(u8, a); |
| 4574 | 4511 | ErrorUnion, |
| 4575 | 4512 | Error, |
| 4576 | 4513 | Enum, |
| 4577 | EnumTag, | |
| 4578 | 4514 | Union, |
| 4579 | 4515 | Fn, |
| 4580 | 4516 | Namespace, |
| ... | ... | @@ -4582,8 +4518,8 @@ const b: u8 = @truncate(u8, a); |
| 4582 | 4518 | BoundFn, |
| 4583 | 4519 | ArgTuple, |
| 4584 | 4520 | Opaque, |
| 4585 | };</code></pre> | |
| 4586 | ||
| 4521 | }; | |
| 4522 | {#code_end#} | |
| 4587 | 4523 | {#header_close#} |
| 4588 | 4524 | {#header_open|@typeName#} |
| 4589 | 4525 | <pre><code class="zig">@typeName(T: type) -&gt; []u8</code></pre> |
| ... | ... | @@ -4606,27 +4542,29 @@ const b: u8 = @truncate(u8, a); |
| 4606 | 4542 | Zig has three build modes: |
| 4607 | 4543 | </p> |
| 4608 | 4544 | <ul> |
| 4609 | <li><a href="#build-mode-debug">Debug</a> (default)</li> | |
| 4610 | <li><a href="#build-mode-release-fast">ReleaseFast</a></li> | |
| 4611 | <li><a href="#build-mode-release-safe">ReleaseSafe</a></li> | |
| 4545 | <li>{#link|Debug#} (default)</li> | |
| 4546 | <li>{#link|ReleaseFast#}</li> | |
| 4547 | <li>{#link|ReleaseSafe#}</li> | |
| 4612 | 4548 | </ul> |
| 4613 | 4549 | <p> |
| 4614 | 4550 | To add standard build options to a <code>build.zig</code> file: |
| 4615 | 4551 | </p> |
| 4616 | <pre><code class="sh">const Builder = @import("std").build.Builder; | |
| 4552 | {#code_begin|syntax#} | |
| 4553 | const Builder = @import("std").build.Builder; | |
| 4617 | 4554 | |
| 4618 | pub fn build(b: &amp;Builder) { | |
| 4555 | pub fn build(b: &Builder) %void { | |
| 4619 | 4556 | const exe = b.addExecutable("example", "example.zig"); |
| 4620 | 4557 | exe.setBuildMode(b.standardReleaseOptions()); |
| 4621 | b.default_step.dependOn(&amp;exe.step); | |
| 4622 | }</code></pre> | |
| 4558 | b.default_step.dependOn(&exe.step); | |
| 4559 | } | |
| 4560 | {#code_end#} | |
| 4623 | 4561 | <p> |
| 4624 | 4562 | This causes these options to be available: |
| 4625 | 4563 | </p> |
| 4626 | <pre><code class="sh"> -Drelease-safe=(bool) optimizations on and safety on | |
| 4564 | <pre><code class="shell"> -Drelease-safe=(bool) optimizations on and safety on | |
| 4627 | 4565 | -Drelease-fast=(bool) optimizations on and safety off</code></pre> |
| 4628 | 4566 | {#header_open|Debug#} |
| 4629 | <pre><code class="sh">$ zig build-exe example.zig</code></pre> | |
| 4567 | <pre><code class="shell">$ zig build-exe example.zig</code></pre> | |
| 4630 | 4568 | <ul> |
| 4631 | 4569 | <li>Fast compilation speed</li> |
| 4632 | 4570 | <li>Safety checks enabled</li> |
| ... | ... | @@ -4634,7 +4572,7 @@ pub fn build(b: &amp;Builder) { |
| 4634 | 4572 | </ul> |
| 4635 | 4573 | {#header_close#} |
| 4636 | 4574 | {#header_open|ReleaseFast#} |
| 4637 | <pre><code class="sh">$ zig build-exe example.zig --release-fast</code></pre> | |
| 4575 | <pre><code class="shell">$ zig build-exe example.zig --release-fast</code></pre> | |
| 4638 | 4576 | <ul> |
| 4639 | 4577 | <li>Fast runtime performance</li> |
| 4640 | 4578 | <li>Safety checks disabled</li> |
| ... | ... | @@ -4642,7 +4580,7 @@ pub fn build(b: &amp;Builder) { |
| 4642 | 4580 | </ul> |
| 4643 | 4581 | {#header_close#} |
| 4644 | 4582 | {#header_open|ReleaseSafe#} |
| 4645 | <pre><code class="sh">$ zig build-exe example.zig --release-safe</code></pre> | |
| 4583 | <pre><code class="shell">$ zig build-exe example.zig --release-safe</code></pre> | |
| 4646 | 4584 | <ul> |
| 4647 | 4585 | <li>Medium runtime performance</li> |
| 4648 | 4586 | <li>Safety checks enabled</li> |
| ... | ... | @@ -4657,79 +4595,47 @@ pub fn build(b: &amp;Builder) { |
| 4657 | 4595 | detected at compile-time, Zig emits an error. Most undefined behavior that |
| 4658 | 4596 | cannot be detected at compile-time can be detected at runtime. In these cases, |
| 4659 | 4597 | Zig has safety checks. Safety checks can be disabled on a per-block basis |
| 4660 | with <code>@setDebugSafety</code>. The <a href="#build-mode-release-fast">ReleaseFast</a> | |
| 4598 | with <code>@setRuntimeSafety</code>. The {#link|ReleaseFast#} | |
| 4661 | 4599 | build mode disables all safety checks in order to facilitate optimizations. |
| 4662 | 4600 | </p> |
| 4663 | 4601 | <p> |
| 4664 | 4602 | When a safety check fails, Zig crashes with a stack trace, like this: |
| 4665 | 4603 | </p> |
| 4666 | <pre><code class="zig">test "safety check" { | |
| 4604 | {#code_begin|test_err|reached unreachable code#} | |
| 4605 | test "safety check" { | |
| 4667 | 4606 | unreachable; |
| 4668 | }</code></pre> | |
| 4669 | <pre><code class="sh">$ zig test test.zig | |
| 4670 | Test 1/1 safety check...reached unreachable code | |
| 4671 | /home/andy/dev/zig/build/lib/zig/std/special/zigrt.zig:16:35: 0x000000000020331c in ??? (test) | |
| 4672 | @import("std").debug.panic("{}", message_ptr[0...message_len]); | |
| 4673 | ^ | |
| 4674 | /home/andy/dev/zig/build/test.zig:2:5: 0x0000000000203297 in ??? (test) | |
| 4675 | unreachable; | |
| 4676 | ^ | |
| 4677 | /home/andy/dev/zig/build/lib/zig/std/special/test_runner.zig:9:21: 0x0000000000214b0a in ??? (test) | |
| 4678 | test_fn.func(); | |
| 4679 | ^ | |
| 4680 | /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:50:21: 0x0000000000214a17 in ??? (test) | |
| 4681 | return root.main(); | |
| 4682 | ^ | |
| 4683 | /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:37:13: 0x00000000002148d0 in ??? (test) | |
| 4684 | callMain(argc, argv, envp) catch exit(1); | |
| 4685 | ^ | |
| 4686 | /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:30:20: 0x0000000000214820 in ??? (test) | |
| 4687 | callMainAndExit() | |
| 4688 | ^ | |
| 4689 | ||
| 4690 | Tests failed. Use the following command to reproduce the failure: | |
| 4691 | ./test</code></pre> | |
| 4607 | } | |
| 4608 | {#code_end#} | |
| 4692 | 4609 | {#header_open|Reaching Unreachable Code#} |
| 4693 | 4610 | <p>At compile-time:</p> |
| 4694 | <pre><code class="zig">comptime { | |
| 4611 | {#code_begin|test_err|unable to evaluate constant expression#} | |
| 4612 | comptime { | |
| 4695 | 4613 | assert(false); |
| 4696 | 4614 | } |
| 4697 | fn assert(ok: bool) { | |
| 4615 | fn assert(ok: bool) void { | |
| 4698 | 4616 | if (!ok) unreachable; // assertion failure |
| 4699 | }</code></pre> | |
| 4700 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4701 | /home/andy/dev/zig/build/test.zig:5:14: error: unable to evaluate constant expression | |
| 4702 | if (!ok) unreachable; // assertion failure | |
| 4703 | ^ | |
| 4704 | /home/andy/dev/zig/build/test.zig:2:11: note: called from here | |
| 4705 | assert(false); | |
| 4706 | ^ | |
| 4707 | /home/andy/dev/zig/build/test.zig:1:10: note: called from here | |
| 4708 | comptime { | |
| 4709 | ^</code></pre> | |
| 4617 | } | |
| 4618 | {#code_end#} | |
| 4710 | 4619 | <p>At runtime crashes with the message <code>reached unreachable code</code> and a stack trace.</p> |
| 4711 | 4620 | {#header_close#} |
| 4712 | 4621 | {#header_open|Index out of Bounds#} |
| 4713 | 4622 | <p>At compile-time:</p> |
| 4714 | <pre><code class="zig">comptime { | |
| 4623 | {#code_begin|test_err|index 5 outside array of size 5#} | |
| 4624 | comptime { | |
| 4715 | 4625 | const array = "hello"; |
| 4716 | 4626 | const garbage = array[5]; |
| 4717 | }</code></pre> | |
| 4718 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4719 | /home/andy/dev/zig/build/test.zig:3:26: error: index 5 outside array of size 5 | |
| 4720 | const garbage = array[5]; | |
| 4721 | ^</code></pre> | |
| 4627 | } | |
| 4628 | {#code_end#} | |
| 4722 | 4629 | <p>At runtime crashes with the message <code>index out of bounds</code> and a stack trace.</p> |
| 4723 | 4630 | {#header_close#} |
| 4724 | 4631 | {#header_open|Cast Negative Number to Unsigned Integer#} |
| 4725 | 4632 | <p>At compile-time:</p> |
| 4726 | <pre><code class="zig">comptime { | |
| 4633 | {#code_begin|test_err|attempt to cast negative value to unsigned integer#} | |
| 4634 | comptime { | |
| 4727 | 4635 | const value: i32 = -1; |
| 4728 | 4636 | const unsigned = u32(value); |
| 4729 | }</code></pre> | |
| 4730 | <pre><code class="sh">$ zig build-obj test.zig test.zig:3:25: error: attempt to cast negative value to unsigned integer | |
| 4731 | const unsigned = u32(value); | |
| 4732 | ^</code></pre> | |
| 4637 | } | |
| 4638 | {#code_end#} | |
| 4733 | 4639 | <p>At runtime crashes with the message <code>attempt to cast negative value to unsigned integer</code> and a stack trace.</p> |
| 4734 | 4640 | <p> |
| 4735 | 4641 | If you are trying to obtain the maximum value of an unsigned integer, use <code>@maxValue(T)</code>, |
| ... | ... | @@ -4738,14 +4644,12 @@ comptime { |
| 4738 | 4644 | {#header_close#} |
| 4739 | 4645 | {#header_open|Cast Truncates Data#} |
| 4740 | 4646 | <p>At compile-time:</p> |
| 4741 | <pre><code class="zig">comptime { | |
| 4647 | {#code_begin|test_err|cast from 'u16' to 'u8' truncates bits#} | |
| 4648 | comptime { | |
| 4742 | 4649 | const spartan_count: u16 = 300; |
| 4743 | 4650 | const byte = u8(spartan_count); |
| 4744 | }</code></pre> | |
| 4745 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4746 | test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits | |
| 4747 | const byte = u8(spartan_count); | |
| 4748 | ^</code></pre> | |
| 4651 | } | |
| 4652 | {#code_end#} | |
| 4749 | 4653 | <p>At runtime crashes with the message <code>integer cast truncated bits</code> and a stack trace.</p> |
| 4750 | 4654 | <p> |
| 4751 | 4655 | If you are trying to truncate bits, use <code>@truncate(T, value)</code>, |
| ... | ... | @@ -4767,14 +4671,12 @@ test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits |
| 4767 | 4671 | <li><code>@divExact</code> (division)</li> |
| 4768 | 4672 | </ul> |
| 4769 | 4673 | <p>Example with addition at compile-time:</p> |
| 4770 | <pre><code class="zig">comptime { | |
| 4674 | {#code_begin|test_err|operation caused overflow#} | |
| 4675 | comptime { | |
| 4771 | 4676 | var byte: u8 = 255; |
| 4772 | 4677 | byte += 1; |
| 4773 | }</code></pre> | |
| 4774 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4775 | /home/andy/dev/zig/build/test.zig:3:10: error: operation caused overflow | |
| 4776 | byte += 1; | |
| 4777 | ^</code></pre> | |
| 4678 | } | |
| 4679 | {#code_end#} | |
| 4778 | 4680 | <p>At runtime crashes with the message <code>integer overflow</code> and a stack trace.</p> |
| 4779 | 4681 | {#header_close#} |
| 4780 | 4682 | {#header_open|Standard Library Math Functions#} |
| ... | ... | @@ -4789,23 +4691,20 @@ test.zig:3:20: error: cast from 'u16' to 'u8' truncates bits |
| 4789 | 4691 | <li><code>@import("std").math.shl</code></li> |
| 4790 | 4692 | </ul> |
| 4791 | 4693 | <p>Example of catching an overflow for addition:</p> |
| 4792 | <pre><code class="zig">const math = @import("std").math; | |
| 4694 | {#code_begin|exe_err#} | |
| 4695 | const math = @import("std").math; | |
| 4793 | 4696 | const warn = @import("std").debug.warn; |
| 4794 | pub fn main() -&gt; %void { | |
| 4697 | pub fn main() %void { | |
| 4795 | 4698 | var byte: u8 = 255; |
| 4796 | 4699 | |
| 4797 | byte = if (math.add(u8, byte, 1)) |result| { | |
| 4798 | result | |
| 4799 | } else |err| { | |
| 4700 | byte = if (math.add(u8, byte, 1)) |result| result else |err| { | |
| 4800 | 4701 | warn("unable to add one: {}\n", @errorName(err)); |
| 4801 | 4702 | return err; |
| 4802 | 4703 | }; |
| 4803 | 4704 | |
| 4804 | 4705 | warn("result: {}\n", byte); |
| 4805 | }</code></pre> | |
| 4806 | <pre><code class="sh">$ zig build-exe test.zig | |
| 4807 | $ ./test | |
| 4808 | unable to add one: Overflow</code></pre> | |
| 4706 | } | |
| 4707 | {#code_end#} | |
| 4809 | 4708 | {#header_close#} |
| 4810 | 4709 | {#header_open|Builtin Overflow Functions#} |
| 4811 | 4710 | <p> |
| ... | ... | @@ -4821,20 +4720,19 @@ unable to add one: Overflow</code></pre> |
| 4821 | 4720 | <p> |
| 4822 | 4721 | Example of <code>@addWithOverflow</code>: |
| 4823 | 4722 | </p> |
| 4824 | <pre><code class="zig">const warn = @import("std").debug.warn; | |
| 4825 | pub fn main() -&gt; %void { | |
| 4723 | {#code_begin|exe#} | |
| 4724 | const warn = @import("std").debug.warn; | |
| 4725 | pub fn main() %void { | |
| 4826 | 4726 | var byte: u8 = 255; |
| 4827 | 4727 | |
| 4828 | 4728 | var result: u8 = undefined; |
| 4829 | if (@addWithOverflow(u8, byte, 10, &amp;result)) { | |
| 4729 | if (@addWithOverflow(u8, byte, 10, &result)) { | |
| 4830 | 4730 | warn("overflowed result: {}\n", result); |
| 4831 | 4731 | } else { |
| 4832 | 4732 | warn("result: {}\n", result); |
| 4833 | 4733 | } |
| 4834 | }</code></pre> | |
| 4835 | <pre><code class="sh">$ zig build-exe test.zig | |
| 4836 | $ ./test | |
| 4837 | overflowed result: 9</code></pre> | |
| 4734 | } | |
| 4735 | {#code_end#} | |
| 4838 | 4736 | {#header_close#} |
| 4839 | 4737 | {#header_open|Wrapping Operations#} |
| 4840 | 4738 | <p> |
| ... | ... | @@ -4846,7 +4744,8 @@ overflowed result: 9</code></pre> |
| 4846 | 4744 | <li><code>-%</code> (wraparound negation)</li> |
| 4847 | 4745 | <li><code>*%</code> (wraparound multiplication)</li> |
| 4848 | 4746 | </ul> |
| 4849 | <pre><code class="zig">const assert = @import("std").debug.assert; | |
| 4747 | {#code_begin|test#} | |
| 4748 | const assert = @import("std").debug.assert; | |
| 4850 | 4749 | |
| 4851 | 4750 | test "wraparound addition and subtraction" { |
| 4852 | 4751 | const x: i32 = @maxValue(i32); |
| ... | ... | @@ -4854,56 +4753,49 @@ test "wraparound addition and subtraction" { |
| 4854 | 4753 | assert(min_val == @minValue(i32)); |
| 4855 | 4754 | const max_val = min_val -% 1; |
| 4856 | 4755 | assert(max_val == @maxValue(i32)); |
| 4857 | }</code></pre> | |
| 4756 | } | |
| 4757 | {#code_end#} | |
| 4858 | 4758 | {#header_close#} |
| 4859 | 4759 | {#header_close#} |
| 4860 | 4760 | {#header_open|Exact Left Shift Overflow#} |
| 4861 | 4761 | <p>At compile-time:</p> |
| 4862 | <pre><code class="zig">comptime { | |
| 4863 | const x = @shlExact(u8(0b01010101), 2); | |
| 4864 | }</code></pre> | |
| 4865 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4866 | /home/andy/dev/zig/build/test.zig:2:15: error: operation caused overflow | |
| 4762 | {#code_begin|test_err|operation caused overflow#} | |
| 4763 | comptime { | |
| 4867 | 4764 | const x = @shlExact(u8(0b01010101), 2); |
| 4868 | ^</code></pre> | |
| 4765 | } | |
| 4766 | {#code_end#} | |
| 4869 | 4767 | <p>At runtime crashes with the message <code>left shift overflowed bits</code> and a stack trace.</p> |
| 4870 | 4768 | {#header_close#} |
| 4871 | 4769 | {#header_open|Exact Right Shift Overflow#} |
| 4872 | 4770 | <p>At compile-time:</p> |
| 4873 | <pre><code class="zig">comptime { | |
| 4874 | const x = @shrExact(u8(0b10101010), 2); | |
| 4875 | }</code></pre> | |
| 4876 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4877 | /home/andy/dev/zig/build/test.zig:2:15: error: exact shift shifted out 1 bits | |
| 4771 | {#code_begin|test_err|exact shift shifted out 1 bits#} | |
| 4772 | comptime { | |
| 4878 | 4773 | const x = @shrExact(u8(0b10101010), 2); |
| 4879 | ^</code></pre> | |
| 4774 | } | |
| 4775 | {#code_end#} | |
| 4880 | 4776 | <p>At runtime crashes with the message <code>right shift overflowed bits</code> and a stack trace.</p> |
| 4881 | 4777 | {#header_close#} |
| 4882 | 4778 | {#header_open|Division by Zero#} |
| 4883 | 4779 | <p>At compile-time:</p> |
| 4884 | <pre><code class="zig">comptime { | |
| 4780 | {#code_begin|test_err|division by zero#} | |
| 4781 | comptime { | |
| 4885 | 4782 | const a: i32 = 1; |
| 4886 | 4783 | const b: i32 = 0; |
| 4887 | 4784 | const c = a / b; |
| 4888 | }</code></pre> | |
| 4889 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4890 | /home/andy/dev/zig/build/test.zig:4:17: error: division by zero is undefined | |
| 4891 | const c = a / b; | |
| 4892 | ^</code></pre> | |
| 4785 | } | |
| 4786 | {#code_end#} | |
| 4893 | 4787 | <p>At runtime crashes with the message <code>division by zero</code> and a stack trace.</p> |
| 4894 | 4788 | |
| 4895 | 4789 | {#header_close#} |
| 4896 | 4790 | {#header_open|Remainder Division by Zero#} |
| 4897 | 4791 | <p>At compile-time:</p> |
| 4898 | <pre><code class="zig">comptime { | |
| 4792 | {#code_begin|test_err|division by zero#} | |
| 4793 | comptime { | |
| 4899 | 4794 | const a: i32 = 10; |
| 4900 | 4795 | const b: i32 = 0; |
| 4901 | 4796 | const c = a % b; |
| 4902 | }</code></pre> | |
| 4903 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4904 | /home/andy/dev/zig/build/test.zig:4:17: error: division by zero is undefined | |
| 4905 | const c = a % b; | |
| 4906 | ^</code></pre> | |
| 4797 | } | |
| 4798 | {#code_end#} | |
| 4907 | 4799 | <p>At runtime crashes with the message <code>remainder division by zero</code> and a stack trace.</p> |
| 4908 | 4800 | |
| 4909 | 4801 | {#header_close#} |
| ... | ... | @@ -4915,20 +4807,18 @@ test "wraparound addition and subtraction" { |
| 4915 | 4807 | {#header_close#} |
| 4916 | 4808 | {#header_open|Attempt to Unwrap Null#} |
| 4917 | 4809 | <p>At compile-time:</p> |
| 4918 | <pre><code class="zig">comptime { | |
| 4810 | {#code_begin|test_err|unable to unwrap null#} | |
| 4811 | comptime { | |
| 4919 | 4812 | const nullable_number: ?i32 = null; |
| 4920 | 4813 | const number = ??nullable_number; |
| 4921 | }</code></pre> | |
| 4922 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4923 | /home/andy/dev/zig/build/test.zig:3:20: error: unable to unwrap null | |
| 4924 | const number = ??nullable_number; | |
| 4925 | ^</code></pre> | |
| 4814 | } | |
| 4815 | {#code_end#} | |
| 4926 | 4816 | <p>At runtime crashes with the message <code>attempt to unwrap null</code> and a stack trace.</p> |
| 4927 | 4817 | <p>One way to avoid this crash is to test for null instead of assuming non-null, with |
| 4928 | 4818 | the <code>if</code> expression:</p> |
| 4929 | 4819 | {#code_begin|exe|test#} |
| 4930 | 4820 | const warn = @import("std").debug.warn; |
| 4931 | pub fn main() { | |
| 4821 | pub fn main() void { | |
| 4932 | 4822 | const nullable_number: ?i32 = null; |
| 4933 | 4823 | |
| 4934 | 4824 | if (nullable_number) |number| { |
| ... | ... | @@ -4941,26 +4831,24 @@ pub fn main() { |
| 4941 | 4831 | {#header_close#} |
| 4942 | 4832 | {#header_open|Attempt to Unwrap Error#} |
| 4943 | 4833 | <p>At compile-time:</p> |
| 4944 | <pre><code class="zig">comptime { | |
| 4945 | const number = %%getNumberOrFail(); | |
| 4834 | {#code_begin|test_err|unable to unwrap error 'UnableToReturnNumber'#} | |
| 4835 | comptime { | |
| 4836 | const number = getNumberOrFail() catch unreachable; | |
| 4946 | 4837 | } |
| 4947 | 4838 | |
| 4948 | 4839 | error UnableToReturnNumber; |
| 4949 | 4840 | |
| 4950 | fn getNumberOrFail() -&gt; %i32 { | |
| 4841 | fn getNumberOrFail() %i32 { | |
| 4951 | 4842 | return error.UnableToReturnNumber; |
| 4952 | }</code></pre> | |
| 4953 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4954 | /home/andy/dev/zig/build/test.zig:2:20: error: unable to unwrap error 'UnableToReturnNumber' | |
| 4955 | const number = %%getNumberOrFail(); | |
| 4956 | ^</code></pre> | |
| 4843 | } | |
| 4844 | {#code_end#} | |
| 4957 | 4845 | <p>At runtime crashes with the message <code>attempt to unwrap error: ErrorCode</code> and a stack trace.</p> |
| 4958 | 4846 | <p>One way to avoid this crash is to test for an error instead of assuming a successful result, with |
| 4959 | 4847 | the <code>if</code> expression:</p> |
| 4960 | {#code_begin|exe|test#} | |
| 4848 | {#code_begin|exe#} | |
| 4961 | 4849 | const warn = @import("std").debug.warn; |
| 4962 | 4850 | |
| 4963 | pub fn main() { | |
| 4851 | pub fn main() void { | |
| 4964 | 4852 | const result = getNumberOrFail(); |
| 4965 | 4853 | |
| 4966 | 4854 | if (result) |number| { |
| ... | ... | @@ -4972,23 +4860,21 @@ pub fn main() { |
| 4972 | 4860 | |
| 4973 | 4861 | error UnableToReturnNumber; |
| 4974 | 4862 | |
| 4975 | fn getNumberOrFail() -> %i32 { | |
| 4863 | fn getNumberOrFail() %i32 { | |
| 4976 | 4864 | return error.UnableToReturnNumber; |
| 4977 | 4865 | } |
| 4978 | 4866 | {#code_end#} |
| 4979 | 4867 | {#header_close#} |
| 4980 | 4868 | {#header_open|Invalid Error Code#} |
| 4981 | 4869 | <p>At compile-time:</p> |
| 4982 | <pre><code class="zig">error AnError; | |
| 4870 | {#code_begin|test_err|integer value 11 represents no error#} | |
| 4871 | error AnError; | |
| 4983 | 4872 | comptime { |
| 4984 | 4873 | const err = error.AnError; |
| 4985 | 4874 | const number = u32(err) + 10; |
| 4986 | 4875 | const invalid_err = error(number); |
| 4987 | }</code></pre> | |
| 4988 | <pre><code class="sh">$ zig build-obj test.zig | |
| 4989 | /home/andy/dev/zig/build/test.zig:5:30: error: integer value 11 represents no error | |
| 4990 | const invalid_err = error(number); | |
| 4991 | ^</code></pre> | |
| 4876 | } | |
| 4877 | {#code_end#} | |
| 4992 | 4878 | <p>At runtime crashes with the message <code>invalid error code</code> and a stack trace.</p> |
| 4993 | 4879 | {#header_close#} |
| 4994 | 4880 | {#header_open|Invalid Enum Cast#} |
| ... | ... | @@ -5020,17 +4906,26 @@ comptime { |
| 5020 | 4906 | which the compiler makes available to every Zig source file. It contains |
| 5021 | 4907 | compile-time constants such as the current target, endianness, and release mode. |
| 5022 | 4908 | </p> |
| 5023 | <pre><code class="zig">const builtin = @import("builtin"); | |
| 5024 | const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';</code></pre> | |
| 4909 | {#code_begin|syntax#} | |
| 4910 | const builtin = @import("builtin"); | |
| 4911 | const separator = if (builtin.os == builtin.Os.windows) '\\' else '/'; | |
| 4912 | {#code_end#} | |
| 5025 | 4913 | <p> |
| 5026 | 4914 | Example of what is imported with <code>@import("builtin")</code>: |
| 5027 | 4915 | </p> |
| 5028 | <pre><code class="zig">pub const Os = enum { | |
| 4916 | {#code_begin|syntax#} | |
| 4917 | pub const StackTrace = struct { | |
| 4918 | index: usize, | |
| 4919 | instruction_addresses: []usize, | |
| 4920 | }; | |
| 4921 | ||
| 4922 | pub const Os = enum { | |
| 5029 | 4923 | freestanding, |
| 4924 | ananas, | |
| 5030 | 4925 | cloudabi, |
| 5031 | darwin, | |
| 5032 | 4926 | dragonfly, |
| 5033 | 4927 | freebsd, |
| 4928 | fuchsia, | |
| 5034 | 4929 | ios, |
| 5035 | 4930 | kfreebsd, |
| 5036 | 4931 | linux, |
| ... | ... | @@ -5055,12 +4950,15 @@ const separator = if (builtin.os == builtin.Os.windows) '\\' else '/';</code></p |
| 5055 | 4950 | tvos, |
| 5056 | 4951 | watchos, |
| 5057 | 4952 | mesa3d, |
| 4953 | contiki, | |
| 4954 | zen, | |
| 5058 | 4955 | }; |
| 5059 | 4956 | |
| 5060 | 4957 | pub const Arch = enum { |
| 5061 | 4958 | armv8_2a, |
| 5062 | 4959 | armv8_1a, |
| 5063 | 4960 | armv8, |
| 4961 | armv8r, | |
| 5064 | 4962 | armv8m_baseline, |
| 5065 | 4963 | armv8m_mainline, |
| 5066 | 4964 | armv7, |
| ... | ... | @@ -5068,6 +4966,7 @@ pub const Arch = enum { |
| 5068 | 4966 | armv7m, |
| 5069 | 4967 | armv7s, |
| 5070 | 4968 | armv7k, |
| 4969 | armv7ve, | |
| 5071 | 4970 | armv6, |
| 5072 | 4971 | armv6m, |
| 5073 | 4972 | armv6k, |
| ... | ... | @@ -5087,16 +4986,20 @@ pub const Arch = enum { |
| 5087 | 4986 | mips64, |
| 5088 | 4987 | mips64el, |
| 5089 | 4988 | msp430, |
| 4989 | nios2, | |
| 5090 | 4990 | powerpc, |
| 5091 | 4991 | powerpc64, |
| 5092 | 4992 | powerpc64le, |
| 5093 | 4993 | r600, |
| 5094 | 4994 | amdgcn, |
| 4995 | riscv32, | |
| 4996 | riscv64, | |
| 5095 | 4997 | sparc, |
| 5096 | 4998 | sparcv9, |
| 5097 | 4999 | sparcel, |
| 5098 | 5000 | s390x, |
| 5099 | 5001 | tce, |
| 5002 | tcele, | |
| 5100 | 5003 | thumb, |
| 5101 | 5004 | thumbeb, |
| 5102 | 5005 | i386, |
| ... | ... | @@ -5122,7 +5025,9 @@ pub const Arch = enum { |
| 5122 | 5025 | renderscript32, |
| 5123 | 5026 | renderscript64, |
| 5124 | 5027 | }; |
| 5028 | ||
| 5125 | 5029 | pub const Environ = enum { |
| 5030 | unknown, | |
| 5126 | 5031 | gnu, |
| 5127 | 5032 | gnuabi64, |
| 5128 | 5033 | gnueabi, |
| ... | ... | @@ -5140,6 +5045,7 @@ pub const Environ = enum { |
| 5140 | 5045 | cygnus, |
| 5141 | 5046 | amdopencl, |
| 5142 | 5047 | coreclr, |
| 5048 | opencl, | |
| 5143 | 5049 | }; |
| 5144 | 5050 | |
| 5145 | 5051 | pub const ObjectFormat = enum { |
| ... | ... | @@ -5147,6 +5053,7 @@ pub const ObjectFormat = enum { |
| 5147 | 5053 | coff, |
| 5148 | 5054 | elf, |
| 5149 | 5055 | macho, |
| 5056 | wasm, | |
| 5150 | 5057 | }; |
| 5151 | 5058 | |
| 5152 | 5059 | pub const GlobalLinkage = enum { |
| ... | ... | @@ -5171,15 +5078,53 @@ pub const Mode = enum { |
| 5171 | 5078 | ReleaseFast, |
| 5172 | 5079 | }; |
| 5173 | 5080 | |
| 5174 | pub const is_big_endian = false; | |
| 5081 | pub const TypeId = enum { | |
| 5082 | Type, | |
| 5083 | Void, | |
| 5084 | Bool, | |
| 5085 | NoReturn, | |
| 5086 | Int, | |
| 5087 | Float, | |
| 5088 | Pointer, | |
| 5089 | Array, | |
| 5090 | Struct, | |
| 5091 | FloatLiteral, | |
| 5092 | IntLiteral, | |
| 5093 | UndefinedLiteral, | |
| 5094 | NullLiteral, | |
| 5095 | Nullable, | |
| 5096 | ErrorUnion, | |
| 5097 | Error, | |
| 5098 | Enum, | |
| 5099 | Union, | |
| 5100 | Fn, | |
| 5101 | Namespace, | |
| 5102 | Block, | |
| 5103 | BoundFn, | |
| 5104 | ArgTuple, | |
| 5105 | Opaque, | |
| 5106 | }; | |
| 5107 | ||
| 5108 | pub const FloatMode = enum { | |
| 5109 | Optimized, | |
| 5110 | Strict, | |
| 5111 | }; | |
| 5112 | ||
| 5113 | pub const Endian = enum { | |
| 5114 | Big, | |
| 5115 | Little, | |
| 5116 | }; | |
| 5117 | ||
| 5118 | pub const endian = Endian.Little; | |
| 5175 | 5119 | pub const is_test = false; |
| 5176 | 5120 | pub const os = Os.linux; |
| 5177 | 5121 | pub const arch = Arch.x86_64; |
| 5178 | 5122 | pub const environ = Environ.gnu; |
| 5179 | 5123 | pub const object_format = ObjectFormat.elf; |
| 5180 | pub const mode = Mode.ReleaseFast; | |
| 5181 | pub const link_libs = [][]const u8 { | |
| 5182 | };</code></pre> | |
| 5124 | pub const mode = Mode.Debug; | |
| 5125 | pub const link_libc = false; | |
| 5126 | pub const have_error_return_tracing = true; | |
| 5127 | {#code_end#} | |
| 5183 | 5128 | {#see_also|Build Mode#} |
| 5184 | 5129 | {#header_close#} |
| 5185 | 5130 | {#header_open|Root Source File#} |
| ... | ... | @@ -5230,16 +5175,19 @@ pub const link_libs = [][]const u8 { |
| 5230 | 5175 | {#see_also|Primitive Types#} |
| 5231 | 5176 | {#header_close#} |
| 5232 | 5177 | {#header_open|C String Literals#} |
| 5233 | <pre><code class="zig">extern fn puts(&amp;const u8); | |
| 5178 | {#code_begin|exe#} | |
| 5179 | {#link_libc#} | |
| 5180 | extern fn puts(&const u8) void; | |
| 5234 | 5181 | |
| 5235 | pub fn main() -&gt; %void { | |
| 5182 | pub fn main() void { | |
| 5236 | 5183 | puts(c"this has a null terminator"); |
| 5237 | 5184 | puts( |
| 5238 | 5185 | c\\and so |
| 5239 | 5186 | c\\does this |
| 5240 | 5187 | c\\multiline C string literal |
| 5241 | 5188 | ); |
| 5242 | }</code></pre> | |
| 5189 | } | |
| 5190 | {#code_end#} | |
| 5243 | 5191 | {#see_also|String Literals#} |
| 5244 | 5192 | {#header_close#} |
| 5245 | 5193 | {#header_open|Import from C Header File#} |
| ... | ... | @@ -5247,40 +5195,49 @@ pub fn main() -&gt; %void { |
| 5247 | 5195 | The <code>@cImport</code> builtin function can be used |
| 5248 | 5196 | to directly import symbols from .h files: |
| 5249 | 5197 | </p> |
| 5250 | <pre><code class="zig">const c = @cImport(@cInclude("stdio.h")); | |
| 5251 | pub fn main() -&gt; %void { | |
| 5252 | c.printf("hello\n"); | |
| 5253 | }</code></pre> | |
| 5198 | {#code_begin|exe#} | |
| 5199 | {#link_libc#} | |
| 5200 | const c = @cImport({ | |
| 5201 | // See https://github.com/zig-lang/zig/issues/515 | |
| 5202 | @cDefine("_NO_CRT_STDIO_INLINE", "1"); | |
| 5203 | @cInclude("stdio.h"); | |
| 5204 | }); | |
| 5205 | pub fn main() void { | |
| 5206 | _ = c.printf(c"hello\n"); | |
| 5207 | } | |
| 5208 | {#code_end#} | |
| 5254 | 5209 | <p> |
| 5255 | 5210 | The <code>@cImport</code> function takes an expression as a parameter. |
| 5256 | 5211 | This expression is evaluated at compile-time and is used to control |
| 5257 | 5212 | preprocessor directives and include multiple .h files: |
| 5258 | 5213 | </p> |
| 5259 | <pre><code class="zig">const builtin = @import("builtin"); | |
| 5214 | {#code_begin|syntax#} | |
| 5215 | const builtin = @import("builtin"); | |
| 5260 | 5216 | |
| 5261 | 5217 | const c = @cImport({ |
| 5262 | 5218 | @cDefine("NDEBUG", builtin.mode == builtin.Mode.ReleaseFast); |
| 5263 | 5219 | if (something) { |
| 5264 | 5220 | @cDefine("_GNU_SOURCE", {}); |
| 5265 | 5221 | } |
| 5266 | @cInclude("stdlib.h") | |
| 5222 | @cInclude("stdlib.h"); | |
| 5267 | 5223 | if (something) { |
| 5268 | 5224 | @cUndef("_GNU_SOURCE"); |
| 5269 | 5225 | } |
| 5270 | 5226 | @cInclude("soundio.h"); |
| 5271 | });</code></pre> | |
| 5227 | }); | |
| 5228 | {#code_end#} | |
| 5272 | 5229 | {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#} |
| 5273 | 5230 | {#header_close#} |
| 5274 | 5231 | {#header_open|Mixing Object Files#} |
| 5275 | 5232 | <p> |
| 5276 | 5233 | You can mix Zig object files with any other object files that respect the C ABI. Example: |
| 5277 | 5234 | </p> |
| 5278 | {#header_close#} | |
| 5279 | {#header_open|base64.zig#} | |
| 5280 | <pre><code class="zig">const base64 = @import("std").base64; | |
| 5235 | <p class="file">base64.zig</p> | |
| 5236 | {#code_begin|syntax#} | |
| 5237 | const base64 = @import("std").base64; | |
| 5281 | 5238 | |
| 5282 | export fn decode_base_64(dest_ptr: &amp;u8, dest_len: usize, | |
| 5283 | source_ptr: &amp;const u8, source_len: usize) -&gt; usize | |
| 5239 | export fn decode_base_64(dest_ptr: &u8, dest_len: usize, | |
| 5240 | source_ptr: &const u8, source_len: usize) usize | |
| 5284 | 5241 | { |
| 5285 | 5242 | const src = source_ptr[0..source_len]; |
| 5286 | 5243 | const dest = dest_ptr[0..dest_len]; |
| ... | ... | @@ -5289,9 +5246,9 @@ export fn decode_base_64(dest_ptr: &amp;u8, dest_len: usize, |
| 5289 | 5246 | base64_decoder.decode(dest[0..decoded_size], src); |
| 5290 | 5247 | return decoded_size; |
| 5291 | 5248 | } |
| 5292 | </code></pre> | |
| 5293 | {{teheader_open:st.c}} | |
| 5294 | <pre><code class="c">// This header is generated by zig from base64.zig | |
| 5249 | {#code_end#} | |
| 5250 | <p class="file">test.c</p> | |
| 5251 | <pre><code class="cpp">// This header is generated by zig from base64.zig | |
| 5295 | 5252 | #include "base64.h" |
| 5296 | 5253 | |
| 5297 | 5254 | #include &lt;string.h&gt; |
| ... | ... | @@ -5307,11 +5264,11 @@ int main(int argc, char **argv) { |
| 5307 | 5264 | |
| 5308 | 5265 | return 0; |
| 5309 | 5266 | }</code></pre> |
| 5310 | {#header_close#} | |
| 5311 | {#header_open|build.zig#} | |
| 5312 | <pre><code class="zig">const Builder = @import("std").build.Builder; | |
| 5267 | <p class="file">build.zig</p> | |
| 5268 | {#code_begin|syntax#} | |
| 5269 | const Builder = @import("std").build.Builder; | |
| 5313 | 5270 | |
| 5314 | pub fn build(b: &amp;Builder) { | |
| 5271 | pub fn build(b: &Builder) %void { | |
| 5315 | 5272 | const obj = b.addObject("base64", "base64.zig"); |
| 5316 | 5273 | |
| 5317 | 5274 | const exe = b.addCExecutable("test"); |
| ... | ... | @@ -5322,11 +5279,12 @@ pub fn build(b: &amp;Builder) { |
| 5322 | 5279 | exe.addObject(obj); |
| 5323 | 5280 | exe.setOutputPath("."); |
| 5324 | 5281 | |
| 5325 | b.default_step.dependOn(&amp;exe.step); | |
| 5326 | }</code></pre> | |
| 5282 | b.default_step.dependOn(&exe.step); | |
| 5283 | } | |
| 5284 | {#code_end#} | |
| 5327 | 5285 | {#header_close#} |
| 5328 | 5286 | {#header_open|Terminal#} |
| 5329 | <pre><code class="sh">$ zig build | |
| 5287 | <pre><code class="shell">$ zig build | |
| 5330 | 5288 | $ ./test |
| 5331 | 5289 | all your base are belong to us</code></pre> |
| 5332 | 5290 | {#see_also|Targets|Zig Build System#} |
| ... | ... | @@ -5338,11 +5296,12 @@ all your base are belong to us</code></pre> |
| 5338 | 5296 | what it looks like to execute <code>zig targets</code> on a Linux x86_64 |
| 5339 | 5297 | computer: |
| 5340 | 5298 | </p> |
| 5341 | <pre><code class="sh">$ zig targets | |
| 5299 | <pre><code class="shell">$ zig targets | |
| 5342 | 5300 | Architectures: |
| 5343 | 5301 | armv8_2a |
| 5344 | 5302 | armv8_1a |
| 5345 | 5303 | armv8 |
| 5304 | armv8r | |
| 5346 | 5305 | armv8m_baseline |
| 5347 | 5306 | armv8m_mainline |
| 5348 | 5307 | armv7 |
| ... | ... | @@ -5350,6 +5309,7 @@ Architectures: |
| 5350 | 5309 | armv7m |
| 5351 | 5310 | armv7s |
| 5352 | 5311 | armv7k |
| 5312 | armv7ve | |
| 5353 | 5313 | armv6 |
| 5354 | 5314 | armv6m |
| 5355 | 5315 | armv6k |
| ... | ... | @@ -5369,16 +5329,20 @@ Architectures: |
| 5369 | 5329 | mips64 |
| 5370 | 5330 | mips64el |
| 5371 | 5331 | msp430 |
| 5332 | nios2 | |
| 5372 | 5333 | powerpc |
| 5373 | 5334 | powerpc64 |
| 5374 | 5335 | powerpc64le |
| 5375 | 5336 | r600 |
| 5376 | 5337 | amdgcn |
| 5338 | riscv32 | |
| 5339 | riscv64 | |
| 5377 | 5340 | sparc |
| 5378 | 5341 | sparcv9 |
| 5379 | 5342 | sparcel |
| 5380 | 5343 | s390x |
| 5381 | 5344 | tce |
| 5345 | tcele | |
| 5382 | 5346 | thumb |
| 5383 | 5347 | thumbeb |
| 5384 | 5348 | i386 |
| ... | ... | @@ -5392,6 +5356,7 @@ Architectures: |
| 5392 | 5356 | amdil64 |
| 5393 | 5357 | hsail |
| 5394 | 5358 | hsail64 |
| 5359 | spir | |
| 5395 | 5360 | spir64 |
| 5396 | 5361 | kalimbav3 |
| 5397 | 5362 | kalimbav4 |
| ... | ... | @@ -5405,10 +5370,11 @@ Architectures: |
| 5405 | 5370 | |
| 5406 | 5371 | Operating Systems: |
| 5407 | 5372 | freestanding |
| 5373 | ananas | |
| 5408 | 5374 | cloudabi |
| 5409 | darwin | |
| 5410 | 5375 | dragonfly |
| 5411 | 5376 | freebsd |
| 5377 | fuchsia | |
| 5412 | 5378 | ios |
| 5413 | 5379 | kfreebsd |
| 5414 | 5380 | linux (native) |
| ... | ... | @@ -5433,8 +5399,11 @@ Operating Systems: |
| 5433 | 5399 | tvos |
| 5434 | 5400 | watchos |
| 5435 | 5401 | mesa3d |
| 5402 | contiki | |
| 5403 | zen | |
| 5436 | 5404 | |
| 5437 | 5405 | Environments: |
| 5406 | unknown | |
| 5438 | 5407 | gnu (native) |
| 5439 | 5408 | gnuabi64 |
| 5440 | 5409 | gnueabi |
| ... | ... | @@ -5451,7 +5420,8 @@ Environments: |
| 5451 | 5420 | itanium |
| 5452 | 5421 | cygnus |
| 5453 | 5422 | amdopencl |
| 5454 | coreclr</code></pre> | |
| 5423 | coreclr | |
| 5424 | opencl</code></pre> | |
| 5455 | 5425 | <p> |
| 5456 | 5426 | The Zig Standard Library (<code>@import("std")</code>) has architecture, environment, and operating sytsem |
| 5457 | 5427 | abstractions, and thus takes additional work to support more platforms. It currently supports |
| ... | ... | @@ -5518,7 +5488,8 @@ coding style. |
| 5518 | 5488 | </p> |
| 5519 | 5489 | {#header_close#} |
| 5520 | 5490 | {#header_open|Examples#} |
| 5521 | <pre><code class="zig">const namespace_name = @import("dir_name/file_name.zig"); | |
| 5491 | {#code_begin|syntax#} | |
| 5492 | const namespace_name = @import("dir_name/file_name.zig"); | |
| 5522 | 5493 | var global_var: i32 = undefined; |
| 5523 | 5494 | const const_name = 42; |
| 5524 | 5495 | const primitive_type_alias = f32; |
| ... | ... | @@ -5527,7 +5498,7 @@ const string_alias = []u8; |
| 5527 | 5498 | const StructName = struct {}; |
| 5528 | 5499 | const StructAlias = StructName; |
| 5529 | 5500 | |
| 5530 | fn functionName(param_name: TypeName) { | |
| 5501 | fn functionName(param_name: TypeName) void { | |
| 5531 | 5502 | var functionPointer = functionName; |
| 5532 | 5503 | functionPointer(); |
| 5533 | 5504 | functionPointer = otherFunction; |
| ... | ... | @@ -5535,34 +5506,35 @@ fn functionName(param_name: TypeName) { |
| 5535 | 5506 | } |
| 5536 | 5507 | const functionAlias = functionName; |
| 5537 | 5508 | |
| 5538 | fn ListTemplateFunction(comptime ChildType: type, comptime fixed_size: usize) -&gt; type { | |
| 5509 | fn ListTemplateFunction(comptime ChildType: type, comptime fixed_size: usize) type { | |
| 5539 | 5510 | return List(ChildType, fixed_size); |
| 5540 | 5511 | } |
| 5541 | 5512 | |
| 5542 | fn ShortList(comptime T: type, comptime n: usize) -&gt; type { | |
| 5543 | struct { | |
| 5513 | fn ShortList(comptime T: type, comptime n: usize) type { | |
| 5514 | return struct { | |
| 5544 | 5515 | field_name: [n]T, |
| 5545 | fn methodName() {} | |
| 5546 | } | |
| 5516 | fn methodName() void {} | |
| 5517 | }; | |
| 5547 | 5518 | } |
| 5548 | 5519 | |
| 5549 | 5520 | // The word XML loses its casing when used in Zig identifiers. |
| 5550 | 5521 | const xml_document = |
| 5551 | \\&lt;?xml version="1.0" encoding="UTF-8"?&gt; | |
| 5552 | \\&lt;document&gt; | |
| 5553 | \\&lt;/document&gt; | |
| 5522 | \\<?xml version="1.0" encoding="UTF-8"?> | |
| 5523 | \\<document> | |
| 5524 | \\</document> | |
| 5554 | 5525 | ; |
| 5555 | 5526 | const XmlParser = struct {}; |
| 5556 | 5527 | |
| 5557 | 5528 | // The initials BE (Big Endian) are just another word in Zig identifier names. |
| 5558 | fn readU32Be() -&gt; u32 {}</code></pre> | |
| 5529 | fn readU32Be() u32 {} | |
| 5530 | {#code_end#} | |
| 5559 | 5531 | <p> |
| 5560 | 5532 | See the Zig Standard Library for more examples. |
| 5561 | 5533 | </p> |
| 5562 | 5534 | {#header_close#} |
| 5563 | 5535 | {#header_close#} |
| 5564 | 5536 | {#header_open|Grammar#} |
| 5565 | <pre><code>Root = many(TopLevelItem) EOF | |
| 5537 | <pre><code class="nohighlight">Root = many(TopLevelItem) EOF | |
| 5566 | 5538 | |
| 5567 | 5539 | TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl |
| 5568 | 5540 | |
| ... | ... | @@ -5586,7 +5558,7 @@ UseDecl = "use" Expression ";" |
| 5586 | 5558 | |
| 5587 | 5559 | ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";" |
| 5588 | 5560 | |
| 5589 | FnProto = option("coldcc" | "nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("-&gt;" TypeExpr) | |
| 5561 | FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") TypeExpr | |
| 5590 | 5562 | |
| 5591 | 5563 | FnDef = option("inline" | "export") FnProto Block |
| 5592 | 5564 | |
| ... | ... | @@ -5646,7 +5618,7 @@ TryExpression = "try" Expression |
| 5646 | 5618 | |
| 5647 | 5619 | BreakExpression = "break" option(":" Symbol) option(Expression) |
| 5648 | 5620 | |
| 5649 | Defer(body) = option("%") "defer" body | |
| 5621 | Defer(body) = ("defer" | "deferror") body | |
| 5650 | 5622 | |
| 5651 | 5623 | IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body)) |
| 5652 | 5624 | |
| ... | ... | @@ -5733,8 +5705,142 @@ ContainerDecl = option("extern" | "packed") |
| 5733 | 5705 | <p>TODO: document changes from a31b23c46ba2a8c28df01adc1aa0b4d878b9a5cf (compile time reflection additions)</p> |
| 5734 | 5706 | {#header_close#} |
| 5735 | 5707 | </div> |
| 5736 | <script src="highlight/highlight.pack.js"></script> | |
| 5737 | <script>hljs.initHighlightingOnLoad();</script> | |
| 5708 | <script> | |
| 5709 | /*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */ | |
| 5710 | !function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset<r[0].offset?e:r:"start"===r[0].event?e:r:e.length?e:r}function o(e){function r(e){return" "+e.nodeName+'="'+n(e.value).replace('"',"&quot;")+'"'}s+="<"+t(e)+E.map.call(e.attributes,r).join("")+">"}function u(e){s+="</"+t(e)+">"}function c(e){("start"===e.event?o:u)(e.node)}for(var l=0,s="",f=[];e.length||r.length;){var g=i();if(s+=n(a.substring(l,g[0].offset)),l=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===l);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return s+n(a.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return l("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function l(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='<span class="'+a,o=t?"":C;return i+=e+'">',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=l(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!y[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=null!=E.sL?d():h(),k=""}function v(e){L+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(L+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"<unnamed>")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,E=i||N,x={},L="";for(R=E;R!==N;R=R.parent)R.cN&&(L=p(R.cN,"",!0)+L);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(L+=C);return{r:B,value:L,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"<br>":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):n=e,l=n.textContent,r=s?f(s,l,!0):g(l),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),l)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,s,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function R(){return x(y)}function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}var E=[],x=Object.keys,y={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="</span>",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[{b:'(u8?|U)?L?"',e:'"',i:"\\n",c:[t.BE]},{b:'(u8?|U)?R"',e:'"',c:[t.BE]},{b:"'\\\\?.",e:"'",i:"."}]},s={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},i={cN:"meta",b:/#\s*[a-z]+\b/,e:/$/,k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},c:[{b:/\\\n/,r:0},t.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:/<[^\n>]*>/,e:/$/,i:"\\n"},t.CLCM,t.CBCM]},a=t.IR+"\\s*\\(",c={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},n=[e,t.CLCM,t.CBCM,s,r];return{aliases:["c","cc","h","c++","h++","hpp"],k:c,i:"</",c:n.concat([i,{b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:c,c:["self",e]},{b:t.IR+"::",k:c},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:c,c:n.concat([{b:/\(/,e:/\)/,k:c,c:n.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+t.IR+"[\\*&\\s]+)+"+a,rB:!0,e:/[{;=]/,eE:!0,k:c,i:/[^\w\s\*&]/,c:[{b:a,rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:c,r:0,c:[t.CLCM,t.CBCM,r,s,e]},t.CLCM,t.CBCM,i]},{cN:"class",bK:"class struct",e:/[{;:]/,c:[{b:/</,e:/>/,c:["self"]},t.TM]}]),exports:{preprocessor:i,strings:r,k:c}}});hljs.registerLanguage("llvm",function(e){var n="([-a-zA-Z$._][\\w\\-$.]*)";return{k:"begin end true false declare define global constant private linker_private internal available_externally linkonce linkonce_odr weak weak_odr appending dllimport dllexport common default hidden protected extern_weak external thread_local zeroinitializer undef null to tail target triple datalayout volatile nuw nsw nnan ninf nsz arcp fast exact inbounds align addrspace section alias module asm sideeffect gc dbg linker_private_weak attributes blockaddress initialexec localdynamic localexec prefix unnamed_addr ccc fastcc coldcc x86_stdcallcc x86_fastcallcc arm_apcscc arm_aapcscc arm_aapcs_vfpcc ptx_device ptx_kernel intel_ocl_bicc msp430_intrcc spir_func spir_kernel x86_64_sysvcc x86_64_win64cc x86_thiscallcc cc c signext zeroext inreg sret nounwind noreturn noalias nocapture byval nest readnone readonly inlinehint noinline alwaysinline optsize ssp sspreq noredzone noimplicitfloat naked builtin cold nobuiltin noduplicate nonlazybind optnone returns_twice sanitize_address sanitize_memory sanitize_thread sspstrong uwtable returned type opaque eq ne slt sgt sle sge ult ugt ule uge oeq one olt ogt ole oge ord uno ueq une x acq_rel acquire alignstack atomic catch cleanup filter inteldialect max min monotonic nand personality release seq_cst singlethread umax umin unordered xchg add fadd sub fsub mul fmul udiv sdiv fdiv urem srem frem shl lshr ashr and or xor icmp fcmp phi call trunc zext sext fptrunc fpext uitofp sitofp fptoui fptosi inttoptr ptrtoint bitcast addrspacecast select va_arg ret br switch invoke unwind unreachable indirectbr landingpad resume malloc alloca free load store getelementptr extractelement insertelement shufflevector getresult extractvalue insertvalue atomicrmw cmpxchg fence argmemonly double",c:[{cN:"keyword",b:"i\\d+"},e.C(";","\\n",{r:0}),e.QSM,{cN:"string",v:[{b:'"',e:'[^\\\\]"'}],r:0},{cN:"title",v:[{b:"@"+n},{b:"@\\d+"},{b:"!"+n},{b:"!\\d+"+n}]},{cN:"symbol",v:[{b:"%"+n},{b:"%\\d+"},{b:"#\\d+"}]},{cN:"number",v:[{b:"0[xX][a-fA-F0-9]+"},{b:"-?\\d+(?:[.]\\d+)?(?:[eE][-+]?\\d+(?:[.]\\d+)?)?"}],r:0}]}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}});hljs.registerLanguage("shell",function(s){return{aliases:["console"],c:[{cN:"meta",b:"^\\s{0,3}[\\w\\d\\[\\]()@-]*[>%$#]",starts:{e:"$",sL:"bash"}}]}}); | |
| 5711 | </script> | |
| 5712 | <script> | |
| 5713 | hljs.registerLanguage("zig", function(t) { | |
| 5714 | var e = { | |
| 5715 | cN: "keyword", | |
| 5716 | b: "\\b[a-z\\d_]*_t\\b" | |
| 5717 | }, | |
| 5718 | r = { | |
| 5719 | cN: "string", | |
| 5720 | v: [{ | |
| 5721 | b: '(u8?|U)?L?"', | |
| 5722 | e: '"', | |
| 5723 | i: "\\n", | |
| 5724 | c: [t.BE] | |
| 5725 | }, { | |
| 5726 | b: '(u8?|U)?R"', | |
| 5727 | e: '"', | |
| 5728 | c: [t.BE] | |
| 5729 | }, { | |
| 5730 | b: "'\\\\?.", | |
| 5731 | e: "'", | |
| 5732 | i: "." | |
| 5733 | }] | |
| 5734 | }, | |
| 5735 | s = { | |
| 5736 | cN: "number", | |
| 5737 | v: [{ | |
| 5738 | b: "\\b(0b[01']+)" | |
| 5739 | }, { | |
| 5740 | b: "(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)" | |
| 5741 | }, { | |
| 5742 | b: "(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" | |
| 5743 | }], | |
| 5744 | r: 0 | |
| 5745 | }, | |
| 5746 | i = { | |
| 5747 | cN: "meta", | |
| 5748 | b: /#\s*[a-z]+\b/, | |
| 5749 | e: /$/, | |
| 5750 | k: { | |
| 5751 | "meta-keyword": "zzzzzzdisable" | |
| 5752 | }, | |
| 5753 | c: [{ | |
| 5754 | b: /\\\n/, | |
| 5755 | r: 0 | |
| 5756 | }, t.inherit(r, { | |
| 5757 | cN: "meta-string" | |
| 5758 | }), { | |
| 5759 | cN: "meta-string", | |
| 5760 | b: /<[^\n>]*>/, | |
| 5761 | e: /$/, | |
| 5762 | i: "\\n" | |
| 5763 | }, t.CLCM, t.CBCM] | |
| 5764 | }, | |
| 5765 | a = t.IR + "\\s*\\(", | |
| 5766 | c = { | |
| 5767 | keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong", | |
| 5768 | built_in: "breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchg fence divExact truncate", | |
| 5769 | literal: "true false null undefined" | |
| 5770 | }, | |
| 5771 | n = [e, t.CLCM, t.CBCM, s, r]; | |
| 5772 | return { | |
| 5773 | aliases: ["c", "cc", "h", "c++", "h++", "hpp"], | |
| 5774 | k: c, | |
| 5775 | i: "</", | |
| 5776 | c: n.concat([i, { | |
| 5777 | b: "\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<", | |
| 5778 | e: ">", | |
| 5779 | k: c, | |
| 5780 | c: ["self", e] | |
| 5781 | }, { | |
| 5782 | b: t.IR + "::", | |
| 5783 | k: c | |
| 5784 | }, { | |
| 5785 | v: [{ | |
| 5786 | b: /=/, | |
| 5787 | e: /;/ | |
| 5788 | }, { | |
| 5789 | b: /\(/, | |
| 5790 | e: /\)/ | |
| 5791 | }, { | |
| 5792 | bK: "new throw return else", | |
| 5793 | e: /;/ | |
| 5794 | }], | |
| 5795 | k: c, | |
| 5796 | c: n.concat([{ | |
| 5797 | b: /\(/, | |
| 5798 | e: /\)/, | |
| 5799 | k: c, | |
| 5800 | c: n.concat(["self"]), | |
| 5801 | r: 0 | |
| 5802 | }]), | |
| 5803 | r: 0 | |
| 5804 | }, { | |
| 5805 | cN: "function", | |
| 5806 | b: "(" + t.IR + "[\\*&\\s]+)+" + a, | |
| 5807 | rB: !0, | |
| 5808 | e: /[{;=]/, | |
| 5809 | eE: !0, | |
| 5810 | k: c, | |
| 5811 | i: /[^\w\s\*&]/, | |
| 5812 | c: [{ | |
| 5813 | b: a, | |
| 5814 | rB: !0, | |
| 5815 | c: [t.TM], | |
| 5816 | r: 0 | |
| 5817 | }, { | |
| 5818 | cN: "params", | |
| 5819 | b: /\(/, | |
| 5820 | e: /\)/, | |
| 5821 | k: c, | |
| 5822 | r: 0, | |
| 5823 | c: [t.CLCM, t.CBCM, r, s, e] | |
| 5824 | }, t.CLCM, t.CBCM, i] | |
| 5825 | }, { | |
| 5826 | cN: "class", | |
| 5827 | bK: "class struct", | |
| 5828 | e: /[{;:]/, | |
| 5829 | c: [{ | |
| 5830 | b: /</, | |
| 5831 | e: />/, | |
| 5832 | c: ["self"] | |
| 5833 | }, t.TM] | |
| 5834 | }]), | |
| 5835 | exports: { | |
| 5836 | preprocessor: i, | |
| 5837 | strings: r, | |
| 5838 | k: c | |
| 5839 | } | |
| 5840 | } | |
| 5841 | }); | |
| 5842 | hljs.initHighlightingOnLoad(); | |
| 5843 | </script> | |
| 5738 | 5844 | </body> |
| 5739 | 5845 | </html> |
| 5740 | 5846 |
example/cat/main.zig+4-4| ... | ... | @@ -5,7 +5,7 @@ const os = std.os; |
| 5 | 5 | const warn = std.debug.warn; |
| 6 | 6 | const allocator = std.debug.global_allocator; |
| 7 | 7 | |
| 8 | pub fn main() -> %void { | |
| 8 | pub fn main() %void { | |
| 9 | 9 | var args_it = os.args(); |
| 10 | 10 | const exe = try unwrapArg(??args_it.next(allocator)); |
| 11 | 11 | var catted_anything = false; |
| ... | ... | @@ -36,12 +36,12 @@ pub fn main() -> %void { |
| 36 | 36 | } |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | fn usage(exe: []const u8) -> %void { | |
| 39 | fn usage(exe: []const u8) %void { | |
| 40 | 40 | warn("Usage: {} [FILE]...\n", exe); |
| 41 | 41 | return error.Invalid; |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | fn cat_file(stdout: &io.File, file: &io.File) -> %void { | |
| 44 | fn cat_file(stdout: &io.File, file: &io.File) %void { | |
| 45 | 45 | var buf: [1024 * 4]u8 = undefined; |
| 46 | 46 | |
| 47 | 47 | while (true) { |
| ... | ... | @@ -61,7 +61,7 @@ fn cat_file(stdout: &io.File, file: &io.File) -> %void { |
| 61 | 61 | } |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | fn unwrapArg(arg: %[]u8) -> %[]u8 { | |
| 64 | fn unwrapArg(arg: %[]u8) %[]u8 { | |
| 65 | 65 | return arg catch |err| { |
| 66 | 66 | warn("Unable to parse command line: {}\n", err); |
| 67 | 67 | return err; |
example/guess_number/main.zig+1-1| ... | ... | @@ -5,7 +5,7 @@ const fmt = std.fmt; |
| 5 | 5 | const Rand = std.rand.Rand; |
| 6 | 6 | const os = std.os; |
| 7 | 7 | |
| 8 | pub fn main() -> %void { | |
| 8 | pub fn main() %void { | |
| 9 | 9 | var stdout_file = try io.getStdOut(); |
| 10 | 10 | var stdout_file_stream = io.FileOutStream.init(&stdout_file); |
| 11 | 11 | const stdout = &stdout_file_stream.stream; |
example/hello_world/hello.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | pub fn main() -> %void { | |
| 3 | pub fn main() %void { | |
| 4 | 4 | // If this program is run without stdout attached, exit with an error. |
| 5 | 5 | var stdout_file = try std.io.getStdOut(); |
| 6 | 6 | // If this program encounters pipe failure when printing to stdout, exit |
example/hello_world/hello_libc.zig+1-1| ... | ... | @@ -7,7 +7,7 @@ const c = @cImport({ |
| 7 | 7 | |
| 8 | 8 | const msg = c"Hello, world!\n"; |
| 9 | 9 | |
| 10 | export fn main(argc: c_int, argv: &&u8) -> c_int { | |
| 10 | export fn main(argc: c_int, argv: &&u8) c_int { | |
| 11 | 11 | if (c.printf(msg) != c_int(c.strlen(msg))) |
| 12 | 12 | return -1; |
| 13 | 13 |
example/hello_world/hello_windows.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | use @import("std").os.windows; |
| 2 | 2 | |
| 3 | export fn WinMain(hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: PWSTR, nCmdShow: INT) -> INT { | |
| 3 | export fn WinMain(hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: PWSTR, nCmdShow: INT) INT { | |
| 4 | 4 | _ = MessageBoxA(null, c"hello", c"title", 0); |
| 5 | 5 | return 0; |
| 6 | 6 | } |
example/mix_o_files/base64.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const base64 = @import("std").base64; |
| 2 | 2 | |
| 3 | export fn decode_base_64(dest_ptr: &u8, dest_len: usize, source_ptr: &const u8, source_len: usize) -> usize { | |
| 3 | export fn decode_base_64(dest_ptr: &u8, dest_len: usize, source_ptr: &const u8, source_len: usize) usize { | |
| 4 | 4 | const src = source_ptr[0..source_len]; |
| 5 | 5 | const dest = dest_ptr[0..dest_len]; |
| 6 | 6 | const base64_decoder = base64.standard_decoder_unsafe; |
example/mix_o_files/build.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | |
| 3 | pub fn build(b: &Builder) -> %void { | |
| 3 | pub fn build(b: &Builder) %void { | |
| 4 | 4 | const obj = b.addObject("base64", "base64.zig"); |
| 5 | 5 | |
| 6 | 6 | const exe = b.addCExecutable("test"); |
example/shared_library/build.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | |
| 3 | pub fn build(b: &Builder) -> %void { | |
| 3 | pub fn build(b: &Builder) %void { | |
| 4 | 4 | const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0)); |
| 5 | 5 | |
| 6 | 6 | const exe = b.addCExecutable("test"); |
example/shared_library/mathtest.zig+1-1| ... | ... | @@ -1,3 +1,3 @@ |
| 1 | export fn add(a: i32, b: i32) -> i32 { | |
| 1 | export fn add(a: i32, b: i32) i32 { | |
| 2 | 2 | return a + b; |
| 3 | 3 | } |
src-self-hosted/ast.zig+15-17| ... | ... | @@ -20,7 +20,7 @@ pub const Node = struct { |
| 20 | 20 | FloatLiteral, |
| 21 | 21 | }; |
| 22 | 22 | |
| 23 | pub fn iterate(base: &Node, index: usize) -> ?&Node { | |
| 23 | pub fn iterate(base: &Node, index: usize) ?&Node { | |
| 24 | 24 | return switch (base.id) { |
| 25 | 25 | Id.Root => @fieldParentPtr(NodeRoot, "base", base).iterate(index), |
| 26 | 26 | Id.VarDecl => @fieldParentPtr(NodeVarDecl, "base", base).iterate(index), |
| ... | ... | @@ -35,7 +35,7 @@ pub const Node = struct { |
| 35 | 35 | }; |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | pub fn destroy(base: &Node, allocator: &mem.Allocator) { | |
| 38 | pub fn destroy(base: &Node, allocator: &mem.Allocator) void { | |
| 39 | 39 | return switch (base.id) { |
| 40 | 40 | Id.Root => allocator.destroy(@fieldParentPtr(NodeRoot, "base", base)), |
| 41 | 41 | Id.VarDecl => allocator.destroy(@fieldParentPtr(NodeVarDecl, "base", base)), |
| ... | ... | @@ -55,7 +55,7 @@ pub const NodeRoot = struct { |
| 55 | 55 | base: Node, |
| 56 | 56 | decls: ArrayList(&Node), |
| 57 | 57 | |
| 58 | pub fn iterate(self: &NodeRoot, index: usize) -> ?&Node { | |
| 58 | pub fn iterate(self: &NodeRoot, index: usize) ?&Node { | |
| 59 | 59 | if (index < self.decls.len) { |
| 60 | 60 | return self.decls.items[self.decls.len - index - 1]; |
| 61 | 61 | } |
| ... | ... | @@ -76,7 +76,7 @@ pub const NodeVarDecl = struct { |
| 76 | 76 | align_node: ?&Node, |
| 77 | 77 | init_node: ?&Node, |
| 78 | 78 | |
| 79 | pub fn iterate(self: &NodeVarDecl, index: usize) -> ?&Node { | |
| 79 | pub fn iterate(self: &NodeVarDecl, index: usize) ?&Node { | |
| 80 | 80 | var i = index; |
| 81 | 81 | |
| 82 | 82 | if (self.type_node) |type_node| { |
| ... | ... | @@ -102,7 +102,7 @@ pub const NodeIdentifier = struct { |
| 102 | 102 | base: Node, |
| 103 | 103 | name_token: Token, |
| 104 | 104 | |
| 105 | pub fn iterate(self: &NodeIdentifier, index: usize) -> ?&Node { | |
| 105 | pub fn iterate(self: &NodeIdentifier, index: usize) ?&Node { | |
| 106 | 106 | return null; |
| 107 | 107 | } |
| 108 | 108 | }; |
| ... | ... | @@ -113,7 +113,7 @@ pub const NodeFnProto = struct { |
| 113 | 113 | fn_token: Token, |
| 114 | 114 | name_token: ?Token, |
| 115 | 115 | params: ArrayList(&Node), |
| 116 | return_type: ?&Node, | |
| 116 | return_type: &Node, | |
| 117 | 117 | var_args_token: ?Token, |
| 118 | 118 | extern_token: ?Token, |
| 119 | 119 | inline_token: ?Token, |
| ... | ... | @@ -122,7 +122,7 @@ pub const NodeFnProto = struct { |
| 122 | 122 | lib_name: ?&Node, // populated if this is an extern declaration |
| 123 | 123 | align_expr: ?&Node, // populated if align(A) is present |
| 124 | 124 | |
| 125 | pub fn iterate(self: &NodeFnProto, index: usize) -> ?&Node { | |
| 125 | pub fn iterate(self: &NodeFnProto, index: usize) ?&Node { | |
| 126 | 126 | var i = index; |
| 127 | 127 | |
| 128 | 128 | if (self.body_node) |body_node| { |
| ... | ... | @@ -130,10 +130,8 @@ pub const NodeFnProto = struct { |
| 130 | 130 | i -= 1; |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | if (self.return_type) |return_type| { | |
| 134 | if (i < 1) return return_type; | |
| 135 | i -= 1; | |
| 136 | } | |
| 133 | if (i < 1) return self.return_type; | |
| 134 | i -= 1; | |
| 137 | 135 | |
| 138 | 136 | if (self.align_expr) |align_expr| { |
| 139 | 137 | if (i < 1) return align_expr; |
| ... | ... | @@ -160,7 +158,7 @@ pub const NodeParamDecl = struct { |
| 160 | 158 | type_node: &Node, |
| 161 | 159 | var_args_token: ?Token, |
| 162 | 160 | |
| 163 | pub fn iterate(self: &NodeParamDecl, index: usize) -> ?&Node { | |
| 161 | pub fn iterate(self: &NodeParamDecl, index: usize) ?&Node { | |
| 164 | 162 | var i = index; |
| 165 | 163 | |
| 166 | 164 | if (i < 1) return self.type_node; |
| ... | ... | @@ -176,7 +174,7 @@ pub const NodeBlock = struct { |
| 176 | 174 | end_token: Token, |
| 177 | 175 | statements: ArrayList(&Node), |
| 178 | 176 | |
| 179 | pub fn iterate(self: &NodeBlock, index: usize) -> ?&Node { | |
| 177 | pub fn iterate(self: &NodeBlock, index: usize) ?&Node { | |
| 180 | 178 | var i = index; |
| 181 | 179 | |
| 182 | 180 | if (i < self.statements.len) return self.statements.items[i]; |
| ... | ... | @@ -198,7 +196,7 @@ pub const NodeInfixOp = struct { |
| 198 | 196 | BangEqual, |
| 199 | 197 | }; |
| 200 | 198 | |
| 201 | pub fn iterate(self: &NodeInfixOp, index: usize) -> ?&Node { | |
| 199 | pub fn iterate(self: &NodeInfixOp, index: usize) ?&Node { | |
| 202 | 200 | var i = index; |
| 203 | 201 | |
| 204 | 202 | if (i < 1) return self.lhs; |
| ... | ... | @@ -234,7 +232,7 @@ pub const NodePrefixOp = struct { |
| 234 | 232 | volatile_token: ?Token, |
| 235 | 233 | }; |
| 236 | 234 | |
| 237 | pub fn iterate(self: &NodePrefixOp, index: usize) -> ?&Node { | |
| 235 | pub fn iterate(self: &NodePrefixOp, index: usize) ?&Node { | |
| 238 | 236 | var i = index; |
| 239 | 237 | |
| 240 | 238 | switch (self.op) { |
| ... | ... | @@ -258,7 +256,7 @@ pub const NodeIntegerLiteral = struct { |
| 258 | 256 | base: Node, |
| 259 | 257 | token: Token, |
| 260 | 258 | |
| 261 | pub fn iterate(self: &NodeIntegerLiteral, index: usize) -> ?&Node { | |
| 259 | pub fn iterate(self: &NodeIntegerLiteral, index: usize) ?&Node { | |
| 262 | 260 | return null; |
| 263 | 261 | } |
| 264 | 262 | }; |
| ... | ... | @@ -267,7 +265,7 @@ pub const NodeFloatLiteral = struct { |
| 267 | 265 | base: Node, |
| 268 | 266 | token: Token, |
| 269 | 267 | |
| 270 | pub fn iterate(self: &NodeFloatLiteral, index: usize) -> ?&Node { | |
| 268 | pub fn iterate(self: &NodeFloatLiteral, index: usize) ?&Node { | |
| 271 | 269 | return null; |
| 272 | 270 | } |
| 273 | 271 | }; |
src-self-hosted/ir.zig+1-1| ... | ... | @@ -33,7 +33,7 @@ pub const Instruction = struct { |
| 33 | 33 | TypeOf, |
| 34 | 34 | ToPtrType, |
| 35 | 35 | PtrTypeChild, |
| 36 | SetDebugSafety, | |
| 36 | SetRuntimeSafety, | |
| 37 | 37 | SetFloatMode, |
| 38 | 38 | ArrayType, |
| 39 | 39 | SliceType, |
src-self-hosted/llvm.zig+1-1| ... | ... | @@ -7,7 +7,7 @@ pub const ModuleRef = removeNullability(c.LLVMModuleRef); |
| 7 | 7 | pub const ContextRef = removeNullability(c.LLVMContextRef); |
| 8 | 8 | pub const BuilderRef = removeNullability(c.LLVMBuilderRef); |
| 9 | 9 | |
| 10 | fn removeNullability(comptime T: type) -> type { | |
| 10 | fn removeNullability(comptime T: type) type { | |
| 11 | 11 | comptime assert(@typeId(T) == builtin.TypeId.Nullable); |
| 12 | 12 | return T.Child; |
| 13 | 13 | } |
src-self-hosted/main.zig+10-10| ... | ... | @@ -20,7 +20,7 @@ error ZigInstallationNotFound; |
| 20 | 20 | |
| 21 | 21 | const default_zig_cache_name = "zig-cache"; |
| 22 | 22 | |
| 23 | pub fn main() -> %void { | |
| 23 | pub fn main() %void { | |
| 24 | 24 | main2() catch |err| { |
| 25 | 25 | if (err != error.InvalidCommandLineArguments) { |
| 26 | 26 | warn("{}\n", @errorName(err)); |
| ... | ... | @@ -39,7 +39,7 @@ const Cmd = enum { |
| 39 | 39 | Targets, |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | fn badArgs(comptime format: []const u8, args: ...) -> error { | |
| 42 | fn badArgs(comptime format: []const u8, args: ...) error { | |
| 43 | 43 | var stderr = try io.getStdErr(); |
| 44 | 44 | var stderr_stream_adapter = io.FileOutStream.init(&stderr); |
| 45 | 45 | const stderr_stream = &stderr_stream_adapter.stream; |
| ... | ... | @@ -48,7 +48,7 @@ fn badArgs(comptime format: []const u8, args: ...) -> error { |
| 48 | 48 | return error.InvalidCommandLineArguments; |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | pub fn main2() -> %void { | |
| 51 | pub fn main2() %void { | |
| 52 | 52 | const allocator = std.heap.c_allocator; |
| 53 | 53 | |
| 54 | 54 | const args = try os.argsAlloc(allocator); |
| ... | ... | @@ -371,7 +371,7 @@ pub fn main2() -> %void { |
| 371 | 371 | defer allocator.free(full_cache_dir); |
| 372 | 372 | |
| 373 | 373 | const zig_lib_dir = try resolveZigLibDir(allocator, zig_install_prefix); |
| 374 | %defer allocator.free(zig_lib_dir); | |
| 374 | errdefer allocator.free(zig_lib_dir); | |
| 375 | 375 | |
| 376 | 376 | const module = try Module.create(allocator, root_name, zig_root_source_file, |
| 377 | 377 | Target.Native, build_kind, build_mode, zig_lib_dir, full_cache_dir); |
| ... | ... | @@ -472,7 +472,7 @@ pub fn main2() -> %void { |
| 472 | 472 | } |
| 473 | 473 | } |
| 474 | 474 | |
| 475 | fn printUsage(stream: &io.OutStream) -> %void { | |
| 475 | fn printUsage(stream: &io.OutStream) %void { | |
| 476 | 476 | try stream.write( |
| 477 | 477 | \\Usage: zig [command] [options] |
| 478 | 478 | \\ |
| ... | ... | @@ -548,7 +548,7 @@ fn printUsage(stream: &io.OutStream) -> %void { |
| 548 | 548 | ); |
| 549 | 549 | } |
| 550 | 550 | |
| 551 | fn printZen() -> %void { | |
| 551 | fn printZen() %void { | |
| 552 | 552 | var stdout_file = try io.getStdErr(); |
| 553 | 553 | try stdout_file.write( |
| 554 | 554 | \\ |
| ... | ... | @@ -569,7 +569,7 @@ fn printZen() -> %void { |
| 569 | 569 | } |
| 570 | 570 | |
| 571 | 571 | /// Caller must free result |
| 572 | fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) -> %[]u8 { | |
| 572 | fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) %[]u8 { | |
| 573 | 573 | if (zig_install_prefix_arg) |zig_install_prefix| { |
| 574 | 574 | return testZigInstallPrefix(allocator, zig_install_prefix) catch |err| { |
| 575 | 575 | warn("No Zig installation found at prefix {}: {}\n", zig_install_prefix_arg, @errorName(err)); |
| ... | ... | @@ -585,9 +585,9 @@ fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const |
| 585 | 585 | } |
| 586 | 586 | |
| 587 | 587 | /// Caller must free result |
| 588 | fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) -> %[]u8 { | |
| 588 | fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) %[]u8 { | |
| 589 | 589 | const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig"); |
| 590 | %defer allocator.free(test_zig_dir); | |
| 590 | errdefer allocator.free(test_zig_dir); | |
| 591 | 591 | |
| 592 | 592 | const test_index_file = try os.path.join(allocator, test_zig_dir, "std", "index.zig"); |
| 593 | 593 | defer allocator.free(test_index_file); |
| ... | ... | @@ -599,7 +599,7 @@ fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) -> %[] |
| 599 | 599 | } |
| 600 | 600 | |
| 601 | 601 | /// Caller must free result |
| 602 | fn findZigLibDir(allocator: &mem.Allocator) -> %[]u8 { | |
| 602 | fn findZigLibDir(allocator: &mem.Allocator) %[]u8 { | |
| 603 | 603 | const self_exe_path = try os.selfExeDirPath(allocator); |
| 604 | 604 | defer allocator.free(self_exe_path); |
| 605 | 605 |
src-self-hosted/module.zig+18-18| ... | ... | @@ -110,22 +110,22 @@ pub const Module = struct { |
| 110 | 110 | }; |
| 111 | 111 | |
| 112 | 112 | pub fn create(allocator: &mem.Allocator, name: []const u8, root_src_path: ?[]const u8, target: &const Target, |
| 113 | kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) -> %&Module | |
| 113 | kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) %&Module | |
| 114 | 114 | { |
| 115 | 115 | var name_buffer = try Buffer.init(allocator, name); |
| 116 | %defer name_buffer.deinit(); | |
| 116 | errdefer name_buffer.deinit(); | |
| 117 | 117 | |
| 118 | 118 | const context = c.LLVMContextCreate() ?? return error.OutOfMemory; |
| 119 | %defer c.LLVMContextDispose(context); | |
| 119 | errdefer c.LLVMContextDispose(context); | |
| 120 | 120 | |
| 121 | 121 | const module = c.LLVMModuleCreateWithNameInContext(name_buffer.ptr(), context) ?? return error.OutOfMemory; |
| 122 | %defer c.LLVMDisposeModule(module); | |
| 122 | errdefer c.LLVMDisposeModule(module); | |
| 123 | 123 | |
| 124 | 124 | const builder = c.LLVMCreateBuilderInContext(context) ?? return error.OutOfMemory; |
| 125 | %defer c.LLVMDisposeBuilder(builder); | |
| 125 | errdefer c.LLVMDisposeBuilder(builder); | |
| 126 | 126 | |
| 127 | 127 | const module_ptr = try allocator.create(Module); |
| 128 | %defer allocator.destroy(module_ptr); | |
| 128 | errdefer allocator.destroy(module_ptr); | |
| 129 | 129 | |
| 130 | 130 | *module_ptr = Module { |
| 131 | 131 | .allocator = allocator, |
| ... | ... | @@ -185,11 +185,11 @@ pub const Module = struct { |
| 185 | 185 | return module_ptr; |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | fn dump(self: &Module) { | |
| 188 | fn dump(self: &Module) void { | |
| 189 | 189 | c.LLVMDumpModule(self.module); |
| 190 | 190 | } |
| 191 | 191 | |
| 192 | pub fn destroy(self: &Module) { | |
| 192 | pub fn destroy(self: &Module) void { | |
| 193 | 193 | c.LLVMDisposeBuilder(self.builder); |
| 194 | 194 | c.LLVMDisposeModule(self.module); |
| 195 | 195 | c.LLVMContextDispose(self.context); |
| ... | ... | @@ -198,7 +198,7 @@ pub const Module = struct { |
| 198 | 198 | self.allocator.destroy(self); |
| 199 | 199 | } |
| 200 | 200 | |
| 201 | pub fn build(self: &Module) -> %void { | |
| 201 | pub fn build(self: &Module) %void { | |
| 202 | 202 | if (self.llvm_argv.len != 0) { |
| 203 | 203 | var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.allocator, |
| 204 | 204 | [][]const []const u8 { [][]const u8{"zig (LLVM option parsing)"}, self.llvm_argv, }); |
| ... | ... | @@ -211,13 +211,13 @@ pub const Module = struct { |
| 211 | 211 | try printError("unable to get real path '{}': {}", root_src_path, err); |
| 212 | 212 | return err; |
| 213 | 213 | }; |
| 214 | %defer self.allocator.free(root_src_real_path); | |
| 214 | errdefer self.allocator.free(root_src_real_path); | |
| 215 | 215 | |
| 216 | 216 | const source_code = io.readFileAllocExtra(root_src_real_path, self.allocator, 3) catch |err| { |
| 217 | 217 | try printError("unable to open '{}': {}", root_src_real_path, err); |
| 218 | 218 | return err; |
| 219 | 219 | }; |
| 220 | %defer self.allocator.free(source_code); | |
| 220 | errdefer self.allocator.free(source_code); | |
| 221 | 221 | source_code[source_code.len - 3] = '\n'; |
| 222 | 222 | source_code[source_code.len - 2] = '\n'; |
| 223 | 223 | source_code[source_code.len - 1] = '\n'; |
| ... | ... | @@ -244,16 +244,16 @@ pub const Module = struct { |
| 244 | 244 | var parser = Parser.init(&tokenizer, self.allocator, root_src_real_path); |
| 245 | 245 | defer parser.deinit(); |
| 246 | 246 | |
| 247 | const root_node = try parser.parse(); | |
| 248 | defer parser.freeAst(root_node); | |
| 247 | const tree = try parser.parse(); | |
| 248 | defer tree.deinit(); | |
| 249 | 249 | |
| 250 | 250 | var stderr_file = try std.io.getStdErr(); |
| 251 | 251 | var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file); |
| 252 | 252 | const out_stream = &stderr_file_out_stream.stream; |
| 253 | try parser.renderAst(out_stream, root_node); | |
| 253 | try parser.renderAst(out_stream, tree.root_node); | |
| 254 | 254 | |
| 255 | 255 | warn("====fmt:====\n"); |
| 256 | try parser.renderSource(out_stream, root_node); | |
| 256 | try parser.renderSource(out_stream, tree.root_node); | |
| 257 | 257 | |
| 258 | 258 | warn("====ir:====\n"); |
| 259 | 259 | warn("TODO\n\n"); |
| ... | ... | @@ -263,11 +263,11 @@ pub const Module = struct { |
| 263 | 263 | |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | pub fn link(self: &Module, out_file: ?[]const u8) -> %void { | |
| 266 | pub fn link(self: &Module, out_file: ?[]const u8) %void { | |
| 267 | 267 | warn("TODO link"); |
| 268 | 268 | } |
| 269 | 269 | |
| 270 | pub fn addLinkLib(self: &Module, name: []const u8, provided_explicitly: bool) -> %&LinkLib { | |
| 270 | pub fn addLinkLib(self: &Module, name: []const u8, provided_explicitly: bool) %&LinkLib { | |
| 271 | 271 | const is_libc = mem.eql(u8, name, "c"); |
| 272 | 272 | |
| 273 | 273 | if (is_libc) { |
| ... | ... | @@ -297,7 +297,7 @@ pub const Module = struct { |
| 297 | 297 | } |
| 298 | 298 | }; |
| 299 | 299 | |
| 300 | fn printError(comptime format: []const u8, args: ...) -> %void { | |
| 300 | fn printError(comptime format: []const u8, args: ...) %void { | |
| 301 | 301 | var stderr_file = try std.io.getStdErr(); |
| 302 | 302 | var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file); |
| 303 | 303 | const out_stream = &stderr_file_out_stream.stream; |
src-self-hosted/parser.zig+89-132| ... | ... | @@ -20,14 +20,25 @@ pub const Parser = struct { |
| 20 | 20 | put_back_tokens: [2]Token, |
| 21 | 21 | put_back_count: usize, |
| 22 | 22 | source_file_name: []const u8, |
| 23 | cleanup_root_node: ?&ast.NodeRoot, | |
| 23 | ||
| 24 | pub const Tree = struct { | |
| 25 | root_node: &ast.NodeRoot, | |
| 26 | ||
| 27 | pub fn deinit(self: &const Tree) void { | |
| 28 | // TODO free the whole arena | |
| 29 | } | |
| 30 | }; | |
| 24 | 31 | |
| 25 | 32 | // This memory contents are used only during a function call. It's used to repurpose memory; |
| 26 | // specifically so that freeAst can be guaranteed to succeed. | |
| 33 | // we reuse the same bytes for the stack data structure used by parsing, tree rendering, and | |
| 34 | // source rendering. | |
| 27 | 35 | const utility_bytes_align = @alignOf( union { a: RenderAstFrame, b: State, c: RenderState } ); |
| 28 | 36 | utility_bytes: []align(utility_bytes_align) u8, |
| 29 | 37 | |
| 30 | pub fn init(tokenizer: &Tokenizer, allocator: &mem.Allocator, source_file_name: []const u8) -> Parser { | |
| 38 | /// `allocator` should be an arena allocator. Parser never calls free on anything. After you're | |
| 39 | /// done with a Parser, free the arena. After the arena is freed, no member functions of Parser | |
| 40 | /// may be called. | |
| 41 | pub fn init(tokenizer: &Tokenizer, allocator: &mem.Allocator, source_file_name: []const u8) Parser { | |
| 31 | 42 | return Parser { |
| 32 | 43 | .allocator = allocator, |
| 33 | 44 | .tokenizer = tokenizer, |
| ... | ... | @@ -35,12 +46,10 @@ pub const Parser = struct { |
| 35 | 46 | .put_back_count = 0, |
| 36 | 47 | .source_file_name = source_file_name, |
| 37 | 48 | .utility_bytes = []align(utility_bytes_align) u8{}, |
| 38 | .cleanup_root_node = null, | |
| 39 | 49 | }; |
| 40 | 50 | } |
| 41 | 51 | |
| 42 | pub fn deinit(self: &Parser) { | |
| 43 | assert(self.cleanup_root_node == null); | |
| 52 | pub fn deinit(self: &Parser) void { | |
| 44 | 53 | self.allocator.free(self.utility_bytes); |
| 45 | 54 | } |
| 46 | 55 | |
| ... | ... | @@ -54,7 +63,7 @@ pub const Parser = struct { |
| 54 | 63 | NullableField: &?&ast.Node, |
| 55 | 64 | List: &ArrayList(&ast.Node), |
| 56 | 65 | |
| 57 | pub fn store(self: &const DestPtr, value: &ast.Node) -> %void { | |
| 66 | pub fn store(self: &const DestPtr, value: &ast.Node) %void { | |
| 58 | 67 | switch (*self) { |
| 59 | 68 | DestPtr.Field => |ptr| *ptr = value, |
| 60 | 69 | DestPtr.NullableField => |ptr| *ptr = value, |
| ... | ... | @@ -88,52 +97,16 @@ pub const Parser = struct { |
| 88 | 97 | Statement: &ast.NodeBlock, |
| 89 | 98 | }; |
| 90 | 99 | |
| 91 | pub fn freeAst(self: &Parser, root_node: &ast.NodeRoot) { | |
| 92 | // utility_bytes is big enough to do this iteration since we were able to do | |
| 93 | // the parsing in the first place | |
| 94 | comptime assert(@sizeOf(State) >= @sizeOf(&ast.Node)); | |
| 95 | ||
| 96 | var stack = self.initUtilityArrayList(&ast.Node); | |
| 97 | defer self.deinitUtilityArrayList(stack); | |
| 98 | ||
| 99 | stack.append(&root_node.base) catch unreachable; | |
| 100 | while (stack.popOrNull()) |node| { | |
| 101 | var i: usize = 0; | |
| 102 | while (node.iterate(i)) |child| : (i += 1) { | |
| 103 | if (child.iterate(0) != null) { | |
| 104 | stack.append(child) catch unreachable; | |
| 105 | } else { | |
| 106 | child.destroy(self.allocator); | |
| 107 | } | |
| 108 | } | |
| 109 | node.destroy(self.allocator); | |
| 110 | } | |
| 111 | } | |
| 112 | ||
| 113 | pub fn parse(self: &Parser) -> %&ast.NodeRoot { | |
| 114 | const result = self.parseInner() catch |err| x: { | |
| 115 | if (self.cleanup_root_node) |root_node| { | |
| 116 | self.freeAst(root_node); | |
| 117 | } | |
| 118 | break :x err; | |
| 119 | }; | |
| 120 | self.cleanup_root_node = null; | |
| 121 | return result; | |
| 122 | } | |
| 123 | ||
| 124 | pub fn parseInner(self: &Parser) -> %&ast.NodeRoot { | |
| 100 | /// Returns an AST tree, allocated with the parser's allocator. | |
| 101 | /// Result should be freed with `freeAst` when done. | |
| 102 | pub fn parse(self: &Parser) %Tree { | |
| 125 | 103 | var stack = self.initUtilityArrayList(State); |
| 126 | 104 | defer self.deinitUtilityArrayList(stack); |
| 127 | 105 | |
| 128 | const root_node = x: { | |
| 129 | const root_node = try self.createRoot(); | |
| 130 | %defer self.allocator.destroy(root_node); | |
| 131 | // This stack append has to succeed for freeAst to work | |
| 132 | try stack.append(State.TopLevel); | |
| 133 | break :x root_node; | |
| 134 | }; | |
| 135 | assert(self.cleanup_root_node == null); | |
| 136 | self.cleanup_root_node = root_node; | |
| 106 | const root_node = try self.createRoot(); | |
| 107 | // TODO errdefer arena free root node | |
| 108 | ||
| 109 | try stack.append(State.TopLevel); | |
| 137 | 110 | |
| 138 | 111 | while (true) { |
| 139 | 112 | //{ |
| ... | ... | @@ -159,7 +132,7 @@ pub const Parser = struct { |
| 159 | 132 | stack.append(State { .TopLevelExtern = token }) catch unreachable; |
| 160 | 133 | continue; |
| 161 | 134 | }, |
| 162 | Token.Id.Eof => return root_node, | |
| 135 | Token.Id.Eof => return Tree {.root_node = root_node}, | |
| 163 | 136 | else => { |
| 164 | 137 | self.putBackToken(token); |
| 165 | 138 | // TODO shouldn't need this cast |
| ... | ... | @@ -211,7 +184,7 @@ pub const Parser = struct { |
| 211 | 184 | Token.Id.StringLiteral => { |
| 212 | 185 | @panic("TODO extern with string literal"); |
| 213 | 186 | }, |
| 214 | Token.Id.Keyword_coldcc, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { | |
| 187 | Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { | |
| 215 | 188 | stack.append(State.TopLevel) catch unreachable; |
| 216 | 189 | const fn_token = try self.eatToken(Token.Id.Keyword_fn); |
| 217 | 190 | // TODO shouldn't need this cast |
| ... | ... | @@ -439,15 +412,11 @@ pub const Parser = struct { |
| 439 | 412 | if (token.id == Token.Id.Keyword_align) { |
| 440 | 413 | @panic("TODO fn proto align"); |
| 441 | 414 | } |
| 442 | if (token.id == Token.Id.Arrow) { | |
| 443 | stack.append(State { | |
| 444 | .TypeExpr = DestPtr {.NullableField = &fn_proto.return_type}, | |
| 445 | }) catch unreachable; | |
| 446 | continue; | |
| 447 | } else { | |
| 448 | self.putBackToken(token); | |
| 449 | continue; | |
| 450 | } | |
| 415 | self.putBackToken(token); | |
| 416 | stack.append(State { | |
| 417 | .TypeExpr = DestPtr {.Field = &fn_proto.return_type}, | |
| 418 | }) catch unreachable; | |
| 419 | continue; | |
| 451 | 420 | }, |
| 452 | 421 | |
| 453 | 422 | State.ParamDecl => |fn_proto| { |
| ... | ... | @@ -575,9 +544,8 @@ pub const Parser = struct { |
| 575 | 544 | } |
| 576 | 545 | } |
| 577 | 546 | |
| 578 | fn createRoot(self: &Parser) -> %&ast.NodeRoot { | |
| 547 | fn createRoot(self: &Parser) %&ast.NodeRoot { | |
| 579 | 548 | const node = try self.allocator.create(ast.NodeRoot); |
| 580 | %defer self.allocator.destroy(node); | |
| 581 | 549 | |
| 582 | 550 | *node = ast.NodeRoot { |
| 583 | 551 | .base = ast.Node {.id = ast.Node.Id.Root}, |
| ... | ... | @@ -587,10 +555,9 @@ pub const Parser = struct { |
| 587 | 555 | } |
| 588 | 556 | |
| 589 | 557 | fn createVarDecl(self: &Parser, visib_token: &const ?Token, mut_token: &const Token, comptime_token: &const ?Token, |
| 590 | extern_token: &const ?Token) -> %&ast.NodeVarDecl | |
| 558 | extern_token: &const ?Token) %&ast.NodeVarDecl | |
| 591 | 559 | { |
| 592 | 560 | const node = try self.allocator.create(ast.NodeVarDecl); |
| 593 | %defer self.allocator.destroy(node); | |
| 594 | 561 | |
| 595 | 562 | *node = ast.NodeVarDecl { |
| 596 | 563 | .base = ast.Node {.id = ast.Node.Id.VarDecl}, |
| ... | ... | @@ -610,10 +577,9 @@ pub const Parser = struct { |
| 610 | 577 | } |
| 611 | 578 | |
| 612 | 579 | fn createFnProto(self: &Parser, fn_token: &const Token, extern_token: &const ?Token, |
| 613 | cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) -> %&ast.NodeFnProto | |
| 580 | cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) %&ast.NodeFnProto | |
| 614 | 581 | { |
| 615 | 582 | const node = try self.allocator.create(ast.NodeFnProto); |
| 616 | %defer self.allocator.destroy(node); | |
| 617 | 583 | |
| 618 | 584 | *node = ast.NodeFnProto { |
| 619 | 585 | .base = ast.Node {.id = ast.Node.Id.FnProto}, |
| ... | ... | @@ -621,7 +587,7 @@ pub const Parser = struct { |
| 621 | 587 | .name_token = null, |
| 622 | 588 | .fn_token = *fn_token, |
| 623 | 589 | .params = ArrayList(&ast.Node).init(self.allocator), |
| 624 | .return_type = null, | |
| 590 | .return_type = undefined, | |
| 625 | 591 | .var_args_token = null, |
| 626 | 592 | .extern_token = *extern_token, |
| 627 | 593 | .inline_token = *inline_token, |
| ... | ... | @@ -633,9 +599,8 @@ pub const Parser = struct { |
| 633 | 599 | return node; |
| 634 | 600 | } |
| 635 | 601 | |
| 636 | fn createParamDecl(self: &Parser) -> %&ast.NodeParamDecl { | |
| 602 | fn createParamDecl(self: &Parser) %&ast.NodeParamDecl { | |
| 637 | 603 | const node = try self.allocator.create(ast.NodeParamDecl); |
| 638 | %defer self.allocator.destroy(node); | |
| 639 | 604 | |
| 640 | 605 | *node = ast.NodeParamDecl { |
| 641 | 606 | .base = ast.Node {.id = ast.Node.Id.ParamDecl}, |
| ... | ... | @@ -648,9 +613,8 @@ pub const Parser = struct { |
| 648 | 613 | return node; |
| 649 | 614 | } |
| 650 | 615 | |
| 651 | fn createBlock(self: &Parser, begin_token: &const Token) -> %&ast.NodeBlock { | |
| 616 | fn createBlock(self: &Parser, begin_token: &const Token) %&ast.NodeBlock { | |
| 652 | 617 | const node = try self.allocator.create(ast.NodeBlock); |
| 653 | %defer self.allocator.destroy(node); | |
| 654 | 618 | |
| 655 | 619 | *node = ast.NodeBlock { |
| 656 | 620 | .base = ast.Node {.id = ast.Node.Id.Block}, |
| ... | ... | @@ -661,9 +625,8 @@ pub const Parser = struct { |
| 661 | 625 | return node; |
| 662 | 626 | } |
| 663 | 627 | |
| 664 | fn createInfixOp(self: &Parser, op_token: &const Token, op: &const ast.NodeInfixOp.InfixOp) -> %&ast.NodeInfixOp { | |
| 628 | fn createInfixOp(self: &Parser, op_token: &const Token, op: &const ast.NodeInfixOp.InfixOp) %&ast.NodeInfixOp { | |
| 665 | 629 | const node = try self.allocator.create(ast.NodeInfixOp); |
| 666 | %defer self.allocator.destroy(node); | |
| 667 | 630 | |
| 668 | 631 | *node = ast.NodeInfixOp { |
| 669 | 632 | .base = ast.Node {.id = ast.Node.Id.InfixOp}, |
| ... | ... | @@ -675,9 +638,8 @@ pub const Parser = struct { |
| 675 | 638 | return node; |
| 676 | 639 | } |
| 677 | 640 | |
| 678 | fn createPrefixOp(self: &Parser, op_token: &const Token, op: &const ast.NodePrefixOp.PrefixOp) -> %&ast.NodePrefixOp { | |
| 641 | fn createPrefixOp(self: &Parser, op_token: &const Token, op: &const ast.NodePrefixOp.PrefixOp) %&ast.NodePrefixOp { | |
| 679 | 642 | const node = try self.allocator.create(ast.NodePrefixOp); |
| 680 | %defer self.allocator.destroy(node); | |
| 681 | 643 | |
| 682 | 644 | *node = ast.NodePrefixOp { |
| 683 | 645 | .base = ast.Node {.id = ast.Node.Id.PrefixOp}, |
| ... | ... | @@ -688,9 +650,8 @@ pub const Parser = struct { |
| 688 | 650 | return node; |
| 689 | 651 | } |
| 690 | 652 | |
| 691 | fn createIdentifier(self: &Parser, name_token: &const Token) -> %&ast.NodeIdentifier { | |
| 653 | fn createIdentifier(self: &Parser, name_token: &const Token) %&ast.NodeIdentifier { | |
| 692 | 654 | const node = try self.allocator.create(ast.NodeIdentifier); |
| 693 | %defer self.allocator.destroy(node); | |
| 694 | 655 | |
| 695 | 656 | *node = ast.NodeIdentifier { |
| 696 | 657 | .base = ast.Node {.id = ast.Node.Id.Identifier}, |
| ... | ... | @@ -699,9 +660,8 @@ pub const Parser = struct { |
| 699 | 660 | return node; |
| 700 | 661 | } |
| 701 | 662 | |
| 702 | fn createIntegerLiteral(self: &Parser, token: &const Token) -> %&ast.NodeIntegerLiteral { | |
| 663 | fn createIntegerLiteral(self: &Parser, token: &const Token) %&ast.NodeIntegerLiteral { | |
| 703 | 664 | const node = try self.allocator.create(ast.NodeIntegerLiteral); |
| 704 | %defer self.allocator.destroy(node); | |
| 705 | 665 | |
| 706 | 666 | *node = ast.NodeIntegerLiteral { |
| 707 | 667 | .base = ast.Node {.id = ast.Node.Id.IntegerLiteral}, |
| ... | ... | @@ -710,9 +670,8 @@ pub const Parser = struct { |
| 710 | 670 | return node; |
| 711 | 671 | } |
| 712 | 672 | |
| 713 | fn createFloatLiteral(self: &Parser, token: &const Token) -> %&ast.NodeFloatLiteral { | |
| 673 | fn createFloatLiteral(self: &Parser, token: &const Token) %&ast.NodeFloatLiteral { | |
| 714 | 674 | const node = try self.allocator.create(ast.NodeFloatLiteral); |
| 715 | %defer self.allocator.destroy(node); | |
| 716 | 675 | |
| 717 | 676 | *node = ast.NodeFloatLiteral { |
| 718 | 677 | .base = ast.Node {.id = ast.Node.Id.FloatLiteral}, |
| ... | ... | @@ -721,40 +680,36 @@ pub const Parser = struct { |
| 721 | 680 | return node; |
| 722 | 681 | } |
| 723 | 682 | |
| 724 | fn createAttachIdentifier(self: &Parser, dest_ptr: &const DestPtr, name_token: &const Token) -> %&ast.NodeIdentifier { | |
| 683 | fn createAttachIdentifier(self: &Parser, dest_ptr: &const DestPtr, name_token: &const Token) %&ast.NodeIdentifier { | |
| 725 | 684 | const node = try self.createIdentifier(name_token); |
| 726 | %defer self.allocator.destroy(node); | |
| 727 | 685 | try dest_ptr.store(&node.base); |
| 728 | 686 | return node; |
| 729 | 687 | } |
| 730 | 688 | |
| 731 | fn createAttachParamDecl(self: &Parser, list: &ArrayList(&ast.Node)) -> %&ast.NodeParamDecl { | |
| 689 | fn createAttachParamDecl(self: &Parser, list: &ArrayList(&ast.Node)) %&ast.NodeParamDecl { | |
| 732 | 690 | const node = try self.createParamDecl(); |
| 733 | %defer self.allocator.destroy(node); | |
| 734 | 691 | try list.append(&node.base); |
| 735 | 692 | return node; |
| 736 | 693 | } |
| 737 | 694 | |
| 738 | 695 | fn createAttachFnProto(self: &Parser, list: &ArrayList(&ast.Node), fn_token: &const Token, |
| 739 | 696 | extern_token: &const ?Token, cc_token: &const ?Token, visib_token: &const ?Token, |
| 740 | inline_token: &const ?Token) -> %&ast.NodeFnProto | |
| 697 | inline_token: &const ?Token) %&ast.NodeFnProto | |
| 741 | 698 | { |
| 742 | 699 | const node = try self.createFnProto(fn_token, extern_token, cc_token, visib_token, inline_token); |
| 743 | %defer self.allocator.destroy(node); | |
| 744 | 700 | try list.append(&node.base); |
| 745 | 701 | return node; |
| 746 | 702 | } |
| 747 | 703 | |
| 748 | 704 | fn createAttachVarDecl(self: &Parser, list: &ArrayList(&ast.Node), visib_token: &const ?Token, |
| 749 | mut_token: &const Token, comptime_token: &const ?Token, extern_token: &const ?Token) -> %&ast.NodeVarDecl | |
| 705 | mut_token: &const Token, comptime_token: &const ?Token, extern_token: &const ?Token) %&ast.NodeVarDecl | |
| 750 | 706 | { |
| 751 | 707 | const node = try self.createVarDecl(visib_token, mut_token, comptime_token, extern_token); |
| 752 | %defer self.allocator.destroy(node); | |
| 753 | 708 | try list.append(&node.base); |
| 754 | 709 | return node; |
| 755 | 710 | } |
| 756 | 711 | |
| 757 | fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) -> error { | |
| 712 | fn parseError(self: &Parser, token: &const Token, comptime fmt: []const u8, args: ...) error { | |
| 758 | 713 | const loc = self.tokenizer.getTokenLocation(token); |
| 759 | 714 | warn("{}:{}:{}: error: " ++ fmt ++ "\n", self.source_file_name, loc.line + 1, loc.column + 1, args); |
| 760 | 715 | warn("{}\n", self.tokenizer.buffer[loc.line_start..loc.line_end]); |
| ... | ... | @@ -775,24 +730,24 @@ pub const Parser = struct { |
| 775 | 730 | return error.ParseError; |
| 776 | 731 | } |
| 777 | 732 | |
| 778 | fn expectToken(self: &Parser, token: &const Token, id: @TagType(Token.Id)) -> %void { | |
| 733 | fn expectToken(self: &Parser, token: &const Token, id: @TagType(Token.Id)) %void { | |
| 779 | 734 | if (token.id != id) { |
| 780 | 735 | return self.parseError(token, "expected {}, found {}", @tagName(id), @tagName(token.id)); |
| 781 | 736 | } |
| 782 | 737 | } |
| 783 | 738 | |
| 784 | fn eatToken(self: &Parser, id: @TagType(Token.Id)) -> %Token { | |
| 739 | fn eatToken(self: &Parser, id: @TagType(Token.Id)) %Token { | |
| 785 | 740 | const token = self.getNextToken(); |
| 786 | 741 | try self.expectToken(token, id); |
| 787 | 742 | return token; |
| 788 | 743 | } |
| 789 | 744 | |
| 790 | fn putBackToken(self: &Parser, token: &const Token) { | |
| 745 | fn putBackToken(self: &Parser, token: &const Token) void { | |
| 791 | 746 | self.put_back_tokens[self.put_back_count] = *token; |
| 792 | 747 | self.put_back_count += 1; |
| 793 | 748 | } |
| 794 | 749 | |
| 795 | fn getNextToken(self: &Parser) -> Token { | |
| 750 | fn getNextToken(self: &Parser) Token { | |
| 796 | 751 | if (self.put_back_count != 0) { |
| 797 | 752 | const put_back_index = self.put_back_count - 1; |
| 798 | 753 | const put_back_token = self.put_back_tokens[put_back_index]; |
| ... | ... | @@ -808,7 +763,7 @@ pub const Parser = struct { |
| 808 | 763 | indent: usize, |
| 809 | 764 | }; |
| 810 | 765 | |
| 811 | pub fn renderAst(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) -> %void { | |
| 766 | pub fn renderAst(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) %void { | |
| 812 | 767 | var stack = self.initUtilityArrayList(RenderAstFrame); |
| 813 | 768 | defer self.deinitUtilityArrayList(stack); |
| 814 | 769 | |
| ... | ... | @@ -847,7 +802,7 @@ pub const Parser = struct { |
| 847 | 802 | Indent: usize, |
| 848 | 803 | }; |
| 849 | 804 | |
| 850 | pub fn renderSource(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) -> %void { | |
| 805 | pub fn renderSource(self: &Parser, stream: &std.io.OutStream, root_node: &ast.NodeRoot) %void { | |
| 851 | 806 | var stack = self.initUtilityArrayList(RenderState); |
| 852 | 807 | defer self.deinitUtilityArrayList(stack); |
| 853 | 808 | |
| ... | ... | @@ -1039,14 +994,12 @@ pub const Parser = struct { |
| 1039 | 994 | if (fn_proto.align_expr != null) { |
| 1040 | 995 | @panic("TODO"); |
| 1041 | 996 | } |
| 1042 | if (fn_proto.return_type) |return_type| { | |
| 1043 | try stream.print(" -> "); | |
| 1044 | if (fn_proto.body_node) |body_node| { | |
| 1045 | try stack.append(RenderState { .Expression = body_node}); | |
| 1046 | try stack.append(RenderState { .Text = " "}); | |
| 1047 | } | |
| 1048 | try stack.append(RenderState { .Expression = return_type}); | |
| 997 | try stream.print(" "); | |
| 998 | if (fn_proto.body_node) |body_node| { | |
| 999 | try stack.append(RenderState { .Expression = body_node}); | |
| 1000 | try stack.append(RenderState { .Text = " "}); | |
| 1049 | 1001 | } |
| 1002 | try stack.append(RenderState { .Expression = fn_proto.return_type}); | |
| 1050 | 1003 | }, |
| 1051 | 1004 | RenderState.Statement => |base| { |
| 1052 | 1005 | switch (base.id) { |
| ... | ... | @@ -1066,7 +1019,7 @@ pub const Parser = struct { |
| 1066 | 1019 | } |
| 1067 | 1020 | } |
| 1068 | 1021 | |
| 1069 | fn initUtilityArrayList(self: &Parser, comptime T: type) -> ArrayList(T) { | |
| 1022 | fn initUtilityArrayList(self: &Parser, comptime T: type) ArrayList(T) { | |
| 1070 | 1023 | const new_byte_count = self.utility_bytes.len - self.utility_bytes.len % @sizeOf(T); |
| 1071 | 1024 | self.utility_bytes = self.allocator.alignedShrink(u8, utility_bytes_align, self.utility_bytes, new_byte_count); |
| 1072 | 1025 | const typed_slice = ([]T)(self.utility_bytes); |
| ... | ... | @@ -1077,7 +1030,7 @@ pub const Parser = struct { |
| 1077 | 1030 | }; |
| 1078 | 1031 | } |
| 1079 | 1032 | |
| 1080 | fn deinitUtilityArrayList(self: &Parser, list: var) { | |
| 1033 | fn deinitUtilityArrayList(self: &Parser, list: var) void { | |
| 1081 | 1034 | self.utility_bytes = ([]align(utility_bytes_align) u8)(list.items); |
| 1082 | 1035 | } |
| 1083 | 1036 | |
| ... | ... | @@ -1085,7 +1038,7 @@ pub const Parser = struct { |
| 1085 | 1038 | |
| 1086 | 1039 | var fixed_buffer_mem: [100 * 1024]u8 = undefined; |
| 1087 | 1040 | |
| 1088 | fn testParse(source: []const u8, allocator: &mem.Allocator) -> %[]u8 { | |
| 1041 | fn testParse(source: []const u8, allocator: &mem.Allocator) %[]u8 { | |
| 1089 | 1042 | var padded_source: [0x100]u8 = undefined; |
| 1090 | 1043 | std.mem.copy(u8, padded_source[0..source.len], source); |
| 1091 | 1044 | padded_source[source.len + 0] = '\n'; |
| ... | ... | @@ -1096,30 +1049,34 @@ fn testParse(source: []const u8, allocator: &mem.Allocator) -> %[]u8 { |
| 1096 | 1049 | var parser = Parser.init(&tokenizer, allocator, "(memory buffer)"); |
| 1097 | 1050 | defer parser.deinit(); |
| 1098 | 1051 | |
| 1099 | const root_node = try parser.parse(); | |
| 1100 | defer parser.freeAst(root_node); | |
| 1052 | const tree = try parser.parse(); | |
| 1053 | defer tree.deinit(); | |
| 1101 | 1054 | |
| 1102 | 1055 | var buffer = try std.Buffer.initSize(allocator, 0); |
| 1103 | 1056 | var buffer_out_stream = io.BufferOutStream.init(&buffer); |
| 1104 | try parser.renderSource(&buffer_out_stream.stream, root_node); | |
| 1057 | try parser.renderSource(&buffer_out_stream.stream, tree.root_node); | |
| 1105 | 1058 | return buffer.toOwnedSlice(); |
| 1106 | 1059 | } |
| 1107 | 1060 | |
| 1061 | error TestFailed; | |
| 1062 | error NondeterministicMemoryUsage; | |
| 1063 | error MemoryLeakDetected; | |
| 1064 | ||
| 1108 | 1065 | // TODO test for memory leaks |
| 1109 | 1066 | // TODO test for valid frees |
| 1110 | fn testCanonical(source: []const u8) { | |
| 1067 | fn testCanonical(source: []const u8) %void { | |
| 1111 | 1068 | const needed_alloc_count = x: { |
| 1112 | 1069 | // Try it once with unlimited memory, make sure it works |
| 1113 | 1070 | var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]); |
| 1114 | 1071 | var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, @maxValue(usize)); |
| 1115 | const result_source = testParse(source, &failing_allocator.allocator) catch @panic("test failed"); | |
| 1072 | const result_source = try testParse(source, &failing_allocator.allocator); | |
| 1116 | 1073 | if (!mem.eql(u8, result_source, source)) { |
| 1117 | 1074 | warn("\n====== expected this output: =========\n"); |
| 1118 | 1075 | warn("{}", source); |
| 1119 | 1076 | warn("\n======== instead found this: =========\n"); |
| 1120 | 1077 | warn("{}", result_source); |
| 1121 | 1078 | warn("\n======================================\n"); |
| 1122 | @panic("test failed"); | |
| 1079 | return error.TestFailed; | |
| 1123 | 1080 | } |
| 1124 | 1081 | failing_allocator.allocator.free(result_source); |
| 1125 | 1082 | break :x failing_allocator.index; |
| ... | ... | @@ -1130,7 +1087,7 @@ fn testCanonical(source: []const u8) { |
| 1130 | 1087 | var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]); |
| 1131 | 1088 | var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, fail_index); |
| 1132 | 1089 | if (testParse(source, &failing_allocator.allocator)) |_| { |
| 1133 | @panic("non-deterministic memory usage"); | |
| 1090 | return error.NondeterministicMemoryUsage; | |
| 1134 | 1091 | } else |err| { |
| 1135 | 1092 | assert(err == error.OutOfMemory); |
| 1136 | 1093 | // TODO make this pass |
| ... | ... | @@ -1139,19 +1096,19 @@ fn testCanonical(source: []const u8) { |
| 1139 | 1096 | // fail_index, needed_alloc_count, |
| 1140 | 1097 | // failing_allocator.allocated_bytes, failing_allocator.freed_bytes, |
| 1141 | 1098 | // failing_allocator.index, failing_allocator.deallocations); |
| 1142 | // @panic("memory leak detected"); | |
| 1099 | // return error.MemoryLeakDetected; | |
| 1143 | 1100 | //} |
| 1144 | 1101 | } |
| 1145 | 1102 | } |
| 1146 | 1103 | } |
| 1147 | 1104 | |
| 1148 | 1105 | test "zig fmt" { |
| 1149 | testCanonical( | |
| 1150 | \\extern fn puts(s: &const u8) -> c_int; | |
| 1106 | try testCanonical( | |
| 1107 | \\extern fn puts(s: &const u8) c_int; | |
| 1151 | 1108 | \\ |
| 1152 | 1109 | ); |
| 1153 | 1110 | |
| 1154 | testCanonical( | |
| 1111 | try testCanonical( | |
| 1155 | 1112 | \\const a = b; |
| 1156 | 1113 | \\pub const a = b; |
| 1157 | 1114 | \\var a = b; |
| ... | ... | @@ -1163,44 +1120,44 @@ test "zig fmt" { |
| 1163 | 1120 | \\ |
| 1164 | 1121 | ); |
| 1165 | 1122 | |
| 1166 | testCanonical( | |
| 1123 | try testCanonical( | |
| 1167 | 1124 | \\extern var foo: c_int; |
| 1168 | 1125 | \\ |
| 1169 | 1126 | ); |
| 1170 | 1127 | |
| 1171 | testCanonical( | |
| 1128 | try testCanonical( | |
| 1172 | 1129 | \\var foo: c_int align(1); |
| 1173 | 1130 | \\ |
| 1174 | 1131 | ); |
| 1175 | 1132 | |
| 1176 | testCanonical( | |
| 1177 | \\fn main(argc: c_int, argv: &&u8) -> c_int { | |
| 1133 | try testCanonical( | |
| 1134 | \\fn main(argc: c_int, argv: &&u8) c_int { | |
| 1178 | 1135 | \\ const a = b; |
| 1179 | 1136 | \\} |
| 1180 | 1137 | \\ |
| 1181 | 1138 | ); |
| 1182 | 1139 | |
| 1183 | testCanonical( | |
| 1184 | \\fn foo(argc: c_int, argv: &&u8) -> c_int { | |
| 1140 | try testCanonical( | |
| 1141 | \\fn foo(argc: c_int, argv: &&u8) c_int { | |
| 1185 | 1142 | \\ return 0; |
| 1186 | 1143 | \\} |
| 1187 | 1144 | \\ |
| 1188 | 1145 | ); |
| 1189 | 1146 | |
| 1190 | testCanonical( | |
| 1191 | \\extern fn f1(s: &align(&u8) u8) -> c_int; | |
| 1147 | try testCanonical( | |
| 1148 | \\extern fn f1(s: &align(&u8) u8) c_int; | |
| 1192 | 1149 | \\ |
| 1193 | 1150 | ); |
| 1194 | 1151 | |
| 1195 | testCanonical( | |
| 1196 | \\extern fn f1(s: &&align(1) &const &volatile u8) -> c_int; | |
| 1197 | \\extern fn f2(s: &align(1) const &align(1) volatile &const volatile u8) -> c_int; | |
| 1198 | \\extern fn f3(s: &align(1) const volatile u8) -> c_int; | |
| 1152 | try testCanonical( | |
| 1153 | \\extern fn f1(s: &&align(1) &const &volatile u8) c_int; | |
| 1154 | \\extern fn f2(s: &align(1) const &align(1) volatile &const volatile u8) c_int; | |
| 1155 | \\extern fn f3(s: &align(1) const volatile u8) c_int; | |
| 1199 | 1156 | \\ |
| 1200 | 1157 | ); |
| 1201 | 1158 | |
| 1202 | testCanonical( | |
| 1203 | \\fn f1(a: bool, b: bool) -> bool { | |
| 1159 | try testCanonical( | |
| 1160 | \\fn f1(a: bool, b: bool) bool { | |
| 1204 | 1161 | \\ a != b; |
| 1205 | 1162 | \\ return a == b; |
| 1206 | 1163 | \\} |
src-self-hosted/target.zig+6-6| ... | ... | @@ -11,7 +11,7 @@ pub const Target = union(enum) { |
| 11 | 11 | Native, |
| 12 | 12 | Cross: CrossTarget, |
| 13 | 13 | |
| 14 | pub fn oFileExt(self: &const Target) -> []const u8 { | |
| 14 | pub fn oFileExt(self: &const Target) []const u8 { | |
| 15 | 15 | const environ = switch (*self) { |
| 16 | 16 | Target.Native => builtin.environ, |
| 17 | 17 | Target.Cross => |t| t.environ, |
| ... | ... | @@ -22,28 +22,28 @@ pub const Target = union(enum) { |
| 22 | 22 | }; |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | pub fn exeFileExt(self: &const Target) -> []const u8 { | |
| 25 | pub fn exeFileExt(self: &const Target) []const u8 { | |
| 26 | 26 | return switch (self.getOs()) { |
| 27 | 27 | builtin.Os.windows => ".exe", |
| 28 | 28 | else => "", |
| 29 | 29 | }; |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | pub fn getOs(self: &const Target) -> builtin.Os { | |
| 32 | pub fn getOs(self: &const Target) builtin.Os { | |
| 33 | 33 | return switch (*self) { |
| 34 | 34 | Target.Native => builtin.os, |
| 35 | 35 | Target.Cross => |t| t.os, |
| 36 | 36 | }; |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | pub fn isDarwin(self: &const Target) -> bool { | |
| 39 | pub fn isDarwin(self: &const Target) bool { | |
| 40 | 40 | return switch (self.getOs()) { |
| 41 | 41 | builtin.Os.ios, builtin.Os.macosx => true, |
| 42 | 42 | else => false, |
| 43 | 43 | }; |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | pub fn isWindows(self: &const Target) -> bool { | |
| 46 | pub fn isWindows(self: &const Target) bool { | |
| 47 | 47 | return switch (self.getOs()) { |
| 48 | 48 | builtin.Os.windows => true, |
| 49 | 49 | else => false, |
| ... | ... | @@ -51,7 +51,7 @@ pub const Target = union(enum) { |
| 51 | 51 | } |
| 52 | 52 | }; |
| 53 | 53 | |
| 54 | pub fn initializeAll() { | |
| 54 | pub fn initializeAll() void { | |
| 55 | 55 | c.LLVMInitializeAllTargets(); |
| 56 | 56 | c.LLVMInitializeAllTargetInfos(); |
| 57 | 57 | c.LLVMInitializeAllTargetMCs(); |
src-self-hosted/tokenizer.zig+9-11| ... | ... | @@ -16,7 +16,6 @@ pub const Token = struct { |
| 16 | 16 | KeywordId{.bytes="and", .id = Id.Keyword_and}, |
| 17 | 17 | KeywordId{.bytes="asm", .id = Id.Keyword_asm}, |
| 18 | 18 | KeywordId{.bytes="break", .id = Id.Keyword_break}, |
| 19 | KeywordId{.bytes="coldcc", .id = Id.Keyword_coldcc}, | |
| 20 | 19 | KeywordId{.bytes="comptime", .id = Id.Keyword_comptime}, |
| 21 | 20 | KeywordId{.bytes="const", .id = Id.Keyword_const}, |
| 22 | 21 | KeywordId{.bytes="continue", .id = Id.Keyword_continue}, |
| ... | ... | @@ -54,7 +53,7 @@ pub const Token = struct { |
| 54 | 53 | KeywordId{.bytes="while", .id = Id.Keyword_while}, |
| 55 | 54 | }; |
| 56 | 55 | |
| 57 | fn getKeyword(bytes: []const u8) -> ?Id { | |
| 56 | fn getKeyword(bytes: []const u8) ?Id { | |
| 58 | 57 | for (keywords) |kw| { |
| 59 | 58 | if (mem.eql(u8, kw.bytes, bytes)) { |
| 60 | 59 | return kw.id; |
| ... | ... | @@ -97,7 +96,6 @@ pub const Token = struct { |
| 97 | 96 | Keyword_and, |
| 98 | 97 | Keyword_asm, |
| 99 | 98 | Keyword_break, |
| 100 | Keyword_coldcc, | |
| 101 | 99 | Keyword_comptime, |
| 102 | 100 | Keyword_const, |
| 103 | 101 | Keyword_continue, |
| ... | ... | @@ -148,7 +146,7 @@ pub const Tokenizer = struct { |
| 148 | 146 | line_end: usize, |
| 149 | 147 | }; |
| 150 | 148 | |
| 151 | pub fn getTokenLocation(self: &Tokenizer, token: &const Token) -> Location { | |
| 149 | pub fn getTokenLocation(self: &Tokenizer, token: &const Token) Location { | |
| 152 | 150 | var loc = Location { |
| 153 | 151 | .line = 0, |
| 154 | 152 | .column = 0, |
| ... | ... | @@ -173,13 +171,13 @@ pub const Tokenizer = struct { |
| 173 | 171 | } |
| 174 | 172 | |
| 175 | 173 | /// For debugging purposes |
| 176 | pub fn dump(self: &Tokenizer, token: &const Token) { | |
| 174 | pub fn dump(self: &Tokenizer, token: &const Token) void { | |
| 177 | 175 | std.debug.warn("{} \"{}\"\n", @tagName(token.id), self.buffer[token.start..token.end]); |
| 178 | 176 | } |
| 179 | 177 | |
| 180 | 178 | /// buffer must end with "\n\n\n". This is so that attempting to decode |
| 181 | 179 | /// a the 3 trailing bytes of a 4-byte utf8 sequence is never a buffer overflow. |
| 182 | pub fn init(buffer: []const u8) -> Tokenizer { | |
| 180 | pub fn init(buffer: []const u8) Tokenizer { | |
| 183 | 181 | std.debug.assert(buffer[buffer.len - 1] == '\n'); |
| 184 | 182 | std.debug.assert(buffer[buffer.len - 2] == '\n'); |
| 185 | 183 | std.debug.assert(buffer[buffer.len - 3] == '\n'); |
| ... | ... | @@ -214,7 +212,7 @@ pub const Tokenizer = struct { |
| 214 | 212 | Period2, |
| 215 | 213 | }; |
| 216 | 214 | |
| 217 | pub fn next(self: &Tokenizer) -> Token { | |
| 215 | pub fn next(self: &Tokenizer) Token { | |
| 218 | 216 | if (self.pending_invalid_token) |token| { |
| 219 | 217 | self.pending_invalid_token = null; |
| 220 | 218 | return token; |
| ... | ... | @@ -530,11 +528,11 @@ pub const Tokenizer = struct { |
| 530 | 528 | return result; |
| 531 | 529 | } |
| 532 | 530 | |
| 533 | pub fn getTokenSlice(self: &const Tokenizer, token: &const Token) -> []const u8 { | |
| 531 | pub fn getTokenSlice(self: &const Tokenizer, token: &const Token) []const u8 { | |
| 534 | 532 | return self.buffer[token.start..token.end]; |
| 535 | 533 | } |
| 536 | 534 | |
| 537 | fn checkLiteralCharacter(self: &Tokenizer) { | |
| 535 | fn checkLiteralCharacter(self: &Tokenizer) void { | |
| 538 | 536 | if (self.pending_invalid_token != null) return; |
| 539 | 537 | const invalid_length = self.getInvalidCharacterLength(); |
| 540 | 538 | if (invalid_length == 0) return; |
| ... | ... | @@ -545,7 +543,7 @@ pub const Tokenizer = struct { |
| 545 | 543 | }; |
| 546 | 544 | } |
| 547 | 545 | |
| 548 | fn getInvalidCharacterLength(self: &Tokenizer) -> u3 { | |
| 546 | fn getInvalidCharacterLength(self: &Tokenizer) u3 { | |
| 549 | 547 | const c0 = self.buffer[self.index]; |
| 550 | 548 | if (c0 < 0x80) { |
| 551 | 549 | if (c0 < 0x20 or c0 == 0x7f) { |
| ... | ... | @@ -638,7 +636,7 @@ test "tokenizer - illegal unicode codepoints" { |
| 638 | 636 | testTokenize("//\xe2\x80\xaa", []Token.Id{}); |
| 639 | 637 | } |
| 640 | 638 | |
| 641 | fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) { | |
| 639 | fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void { | |
| 642 | 640 | // (test authors, just make this bigger if you need it) |
| 643 | 641 | var padded_source: [0x100]u8 = undefined; |
| 644 | 642 | std.mem.copy(u8, padded_source[0..source.len], source); |
src/all_types.hpp+16-5| ... | ... | @@ -1108,6 +1108,7 @@ struct TypeTableEntry { |
| 1108 | 1108 | |
| 1109 | 1109 | bool zero_bits; |
| 1110 | 1110 | bool is_copyable; |
| 1111 | bool gen_h_loop_flag; | |
| 1111 | 1112 | |
| 1112 | 1113 | union { |
| 1113 | 1114 | TypeTableEntryPointer pointer; |
| ... | ... | @@ -1204,6 +1205,9 @@ struct FnTableEntry { |
| 1204 | 1205 | AstNode *set_alignstack_node; |
| 1205 | 1206 | uint32_t alignstack_value; |
| 1206 | 1207 | |
| 1208 | AstNode *set_cold_node; | |
| 1209 | bool is_cold; | |
| 1210 | ||
| 1207 | 1211 | ZigList<FnExport> export_list; |
| 1208 | 1212 | bool calls_errorable_function; |
| 1209 | 1213 | }; |
| ... | ... | @@ -1250,7 +1254,8 @@ enum BuiltinFnId { |
| 1250 | 1254 | BuiltinFnIdMod, |
| 1251 | 1255 | BuiltinFnIdTruncate, |
| 1252 | 1256 | BuiltinFnIdIntType, |
| 1253 | BuiltinFnIdSetDebugSafety, | |
| 1257 | BuiltinFnIdSetCold, | |
| 1258 | BuiltinFnIdSetRuntimeSafety, | |
| 1254 | 1259 | BuiltinFnIdSetFloatMode, |
| 1255 | 1260 | BuiltinFnIdTypeName, |
| 1256 | 1261 | BuiltinFnIdCanImplicitCast, |
| ... | ... | @@ -1830,7 +1835,8 @@ enum IrInstructionId { |
| 1830 | 1835 | IrInstructionIdTypeOf, |
| 1831 | 1836 | IrInstructionIdToPtrType, |
| 1832 | 1837 | IrInstructionIdPtrTypeChild, |
| 1833 | IrInstructionIdSetDebugSafety, | |
| 1838 | IrInstructionIdSetCold, | |
| 1839 | IrInstructionIdSetRuntimeSafety, | |
| 1834 | 1840 | IrInstructionIdSetFloatMode, |
| 1835 | 1841 | IrInstructionIdArrayType, |
| 1836 | 1842 | IrInstructionIdSliceType, |
| ... | ... | @@ -2202,11 +2208,16 @@ struct IrInstructionPtrTypeChild { |
| 2202 | 2208 | IrInstruction *value; |
| 2203 | 2209 | }; |
| 2204 | 2210 | |
| 2205 | struct IrInstructionSetDebugSafety { | |
| 2211 | struct IrInstructionSetCold { | |
| 2206 | 2212 | IrInstruction base; |
| 2207 | 2213 | |
| 2208 | IrInstruction *scope_value; | |
| 2209 | IrInstruction *debug_safety_on; | |
| 2214 | IrInstruction *is_cold; | |
| 2215 | }; | |
| 2216 | ||
| 2217 | struct IrInstructionSetRuntimeSafety { | |
| 2218 | IrInstruction base; | |
| 2219 | ||
| 2220 | IrInstruction *safety_on; | |
| 2210 | 2221 | }; |
| 2211 | 2222 | |
| 2212 | 2223 | struct IrInstructionSetFloatMode { |
src/analyze.cpp+126-50| ... | ... | @@ -609,7 +609,10 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t |
| 609 | 609 | buf_resize(&entry->name, 0); |
| 610 | 610 | buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name)); |
| 611 | 611 | |
| 612 | if (!entry->zero_bits) { | |
| 612 | if (entry->zero_bits) { | |
| 613 | entry->di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, 0, | |
| 614 | 0, child_type->di_type, 0); | |
| 615 | } else { | |
| 613 | 616 | entry->type_ref = child_type->type_ref ? LLVMArrayType(child_type->type_ref, |
| 614 | 617 | (unsigned int)array_size) : nullptr; |
| 615 | 618 | |
| ... | ... | @@ -915,9 +918,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 915 | 918 | if (fn_type_id->alignment != 0) { |
| 916 | 919 | buf_appendf(&fn_type->name, " align(%" PRIu32 ")", fn_type_id->alignment); |
| 917 | 920 | } |
| 918 | if (fn_type_id->return_type->id != TypeTableEntryIdVoid) { | |
| 919 | buf_appendf(&fn_type->name, " -> %s", buf_ptr(&fn_type_id->return_type->name)); | |
| 920 | } | |
| 921 | buf_appendf(&fn_type->name, " %s", buf_ptr(&fn_type_id->return_type->name)); | |
| 921 | 922 | skip_debug_info = skip_debug_info || !fn_type_id->return_type->di_type; |
| 922 | 923 | |
| 923 | 924 | // next, loop over the parameters again and compute debug information |
| ... | ... | @@ -1079,7 +1080,7 @@ TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 1079 | 1080 | const char *comma_str = (i == 0) ? "" : ","; |
| 1080 | 1081 | buf_appendf(&fn_type->name, "%svar", comma_str); |
| 1081 | 1082 | } |
| 1082 | buf_appendf(&fn_type->name, ")->var"); | |
| 1083 | buf_appendf(&fn_type->name, ")var"); | |
| 1083 | 1084 | |
| 1084 | 1085 | fn_type->data.fn.fn_type_id = *fn_type_id; |
| 1085 | 1086 | fn_type->data.fn.is_generic = true; |
| ... | ... | @@ -1155,6 +1156,104 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** |
| 1155 | 1156 | return true; |
| 1156 | 1157 | } |
| 1157 | 1158 | |
| 1159 | static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { | |
| 1160 | switch (type_entry->id) { | |
| 1161 | case TypeTableEntryIdInvalid: | |
| 1162 | case TypeTableEntryIdVar: | |
| 1163 | zig_unreachable(); | |
| 1164 | case TypeTableEntryIdMetaType: | |
| 1165 | case TypeTableEntryIdUnreachable: | |
| 1166 | case TypeTableEntryIdNumLitFloat: | |
| 1167 | case TypeTableEntryIdNumLitInt: | |
| 1168 | case TypeTableEntryIdUndefLit: | |
| 1169 | case TypeTableEntryIdNullLit: | |
| 1170 | case TypeTableEntryIdErrorUnion: | |
| 1171 | case TypeTableEntryIdPureError: | |
| 1172 | case TypeTableEntryIdNamespace: | |
| 1173 | case TypeTableEntryIdBlock: | |
| 1174 | case TypeTableEntryIdBoundFn: | |
| 1175 | case TypeTableEntryIdArgTuple: | |
| 1176 | case TypeTableEntryIdOpaque: | |
| 1177 | return false; | |
| 1178 | case TypeTableEntryIdVoid: | |
| 1179 | case TypeTableEntryIdBool: | |
| 1180 | case TypeTableEntryIdInt: | |
| 1181 | case TypeTableEntryIdFloat: | |
| 1182 | case TypeTableEntryIdPointer: | |
| 1183 | case TypeTableEntryIdArray: | |
| 1184 | case TypeTableEntryIdFn: | |
| 1185 | return true; | |
| 1186 | case TypeTableEntryIdStruct: | |
| 1187 | return type_entry->data.structure.layout == ContainerLayoutPacked; | |
| 1188 | case TypeTableEntryIdUnion: | |
| 1189 | return type_entry->data.unionation.layout == ContainerLayoutPacked; | |
| 1190 | case TypeTableEntryIdMaybe: | |
| 1191 | { | |
| 1192 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; | |
| 1193 | return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; | |
| 1194 | } | |
| 1195 | case TypeTableEntryIdEnum: | |
| 1196 | return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr; | |
| 1197 | } | |
| 1198 | zig_unreachable(); | |
| 1199 | } | |
| 1200 | ||
| 1201 | static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) { | |
| 1202 | switch (type_entry->id) { | |
| 1203 | case TypeTableEntryIdInvalid: | |
| 1204 | case TypeTableEntryIdVar: | |
| 1205 | zig_unreachable(); | |
| 1206 | case TypeTableEntryIdMetaType: | |
| 1207 | case TypeTableEntryIdNumLitFloat: | |
| 1208 | case TypeTableEntryIdNumLitInt: | |
| 1209 | case TypeTableEntryIdUndefLit: | |
| 1210 | case TypeTableEntryIdNullLit: | |
| 1211 | case TypeTableEntryIdErrorUnion: | |
| 1212 | case TypeTableEntryIdPureError: | |
| 1213 | case TypeTableEntryIdNamespace: | |
| 1214 | case TypeTableEntryIdBlock: | |
| 1215 | case TypeTableEntryIdBoundFn: | |
| 1216 | case TypeTableEntryIdArgTuple: | |
| 1217 | return false; | |
| 1218 | case TypeTableEntryIdOpaque: | |
| 1219 | case TypeTableEntryIdUnreachable: | |
| 1220 | case TypeTableEntryIdVoid: | |
| 1221 | case TypeTableEntryIdBool: | |
| 1222 | return true; | |
| 1223 | case TypeTableEntryIdInt: | |
| 1224 | switch (type_entry->data.integral.bit_count) { | |
| 1225 | case 8: | |
| 1226 | case 16: | |
| 1227 | case 32: | |
| 1228 | case 64: | |
| 1229 | case 128: | |
| 1230 | return true; | |
| 1231 | default: | |
| 1232 | return false; | |
| 1233 | } | |
| 1234 | case TypeTableEntryIdFloat: | |
| 1235 | return true; | |
| 1236 | case TypeTableEntryIdArray: | |
| 1237 | return type_allowed_in_extern(g, type_entry->data.array.child_type); | |
| 1238 | case TypeTableEntryIdFn: | |
| 1239 | return type_entry->data.fn.fn_type_id.cc == CallingConventionC; | |
| 1240 | case TypeTableEntryIdPointer: | |
| 1241 | return type_allowed_in_extern(g, type_entry->data.pointer.child_type); | |
| 1242 | case TypeTableEntryIdStruct: | |
| 1243 | return type_entry->data.structure.layout == ContainerLayoutExtern; | |
| 1244 | case TypeTableEntryIdMaybe: | |
| 1245 | { | |
| 1246 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; | |
| 1247 | return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; | |
| 1248 | } | |
| 1249 | case TypeTableEntryIdEnum: | |
| 1250 | return type_entry->data.enumeration.layout == ContainerLayoutExtern; | |
| 1251 | case TypeTableEntryIdUnion: | |
| 1252 | return type_entry->data.unionation.layout == ContainerLayoutExtern; | |
| 1253 | } | |
| 1254 | zig_unreachable(); | |
| 1255 | } | |
| 1256 | ||
| 1158 | 1257 | static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope) { |
| 1159 | 1258 | assert(proto_node->type == NodeTypeFnProto); |
| 1160 | 1259 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| ... | ... | @@ -1205,6 +1304,14 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1205 | 1304 | } |
| 1206 | 1305 | } |
| 1207 | 1306 | |
| 1307 | if (fn_type_id.cc != CallingConventionUnspecified && !type_allowed_in_extern(g, type_entry)) { | |
| 1308 | add_node_error(g, param_node->data.param_decl.type, | |
| 1309 | buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", | |
| 1310 | buf_ptr(&type_entry->name), | |
| 1311 | calling_convention_name(fn_type_id.cc))); | |
| 1312 | return g->builtin_types.entry_invalid; | |
| 1313 | } | |
| 1314 | ||
| 1208 | 1315 | switch (type_entry->id) { |
| 1209 | 1316 | case TypeTableEntryIdInvalid: |
| 1210 | 1317 | return g->builtin_types.entry_invalid; |
| ... | ... | @@ -1269,6 +1376,14 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1269 | 1376 | fn_type_id.return_type = (fn_proto->return_type == nullptr) ? |
| 1270 | 1377 | g->builtin_types.entry_void : analyze_type_expr(g, child_scope, fn_proto->return_type); |
| 1271 | 1378 | |
| 1379 | if (fn_type_id.cc != CallingConventionUnspecified && !type_allowed_in_extern(g, fn_type_id.return_type)) { | |
| 1380 | add_node_error(g, fn_proto->return_type, | |
| 1381 | buf_sprintf("return type '%s' not allowed in function with calling convention '%s'", | |
| 1382 | buf_ptr(&fn_type_id.return_type->name), | |
| 1383 | calling_convention_name(fn_type_id.cc))); | |
| 1384 | return g->builtin_types.entry_invalid; | |
| 1385 | } | |
| 1386 | ||
| 1272 | 1387 | switch (fn_type_id.return_type->id) { |
| 1273 | 1388 | case TypeTableEntryIdInvalid: |
| 1274 | 1389 | return g->builtin_types.entry_invalid; |
| ... | ... | @@ -1421,46 +1536,6 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1421 | 1536 | enum_type->di_type = tag_di_type; |
| 1422 | 1537 | } |
| 1423 | 1538 | |
| 1424 | static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { | |
| 1425 | switch (type_entry->id) { | |
| 1426 | case TypeTableEntryIdInvalid: | |
| 1427 | case TypeTableEntryIdVar: | |
| 1428 | zig_unreachable(); | |
| 1429 | case TypeTableEntryIdMetaType: | |
| 1430 | case TypeTableEntryIdUnreachable: | |
| 1431 | case TypeTableEntryIdNumLitFloat: | |
| 1432 | case TypeTableEntryIdNumLitInt: | |
| 1433 | case TypeTableEntryIdUndefLit: | |
| 1434 | case TypeTableEntryIdNullLit: | |
| 1435 | case TypeTableEntryIdErrorUnion: | |
| 1436 | case TypeTableEntryIdPureError: | |
| 1437 | case TypeTableEntryIdNamespace: | |
| 1438 | case TypeTableEntryIdBlock: | |
| 1439 | case TypeTableEntryIdBoundFn: | |
| 1440 | case TypeTableEntryIdArgTuple: | |
| 1441 | case TypeTableEntryIdOpaque: | |
| 1442 | return false; | |
| 1443 | case TypeTableEntryIdVoid: | |
| 1444 | case TypeTableEntryIdBool: | |
| 1445 | case TypeTableEntryIdInt: | |
| 1446 | case TypeTableEntryIdFloat: | |
| 1447 | case TypeTableEntryIdPointer: | |
| 1448 | case TypeTableEntryIdArray: | |
| 1449 | case TypeTableEntryIdUnion: | |
| 1450 | case TypeTableEntryIdFn: | |
| 1451 | return true; | |
| 1452 | case TypeTableEntryIdStruct: | |
| 1453 | return type_entry->data.structure.layout == ContainerLayoutPacked; | |
| 1454 | case TypeTableEntryIdMaybe: | |
| 1455 | { | |
| 1456 | TypeTableEntry *child_type = type_entry->data.maybe.child_type; | |
| 1457 | return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; | |
| 1458 | } | |
| 1459 | case TypeTableEntryIdEnum: | |
| 1460 | return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr; | |
| 1461 | } | |
| 1462 | zig_unreachable(); | |
| 1463 | } | |
| 1464 | 1539 | |
| 1465 | 1540 | TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], |
| 1466 | 1541 | TypeTableEntry *field_types[], size_t field_count) |
| ... | ... | @@ -1864,7 +1939,7 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) { |
| 1864 | 1939 | uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; |
| 1865 | 1940 | |
| 1866 | 1941 | TypeTableEntry *tag_type = union_type->data.unionation.tag_type; |
| 1867 | if (tag_type == nullptr) { | |
| 1942 | if (tag_type == nullptr || tag_type->zero_bits) { | |
| 1868 | 1943 | assert(most_aligned_union_member != nullptr); |
| 1869 | 1944 | |
| 1870 | 1945 | if (padding_in_bits > 0) { |
| ... | ... | @@ -2506,8 +2581,10 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2506 | 2581 | |
| 2507 | 2582 | if (create_enum_type) { |
| 2508 | 2583 | ImportTableEntry *import = get_scope_import(scope); |
| 2509 | uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref); | |
| 2510 | uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref); | |
| 2584 | uint64_t tag_debug_size_in_bits = tag_type->zero_bits ? 0 : | |
| 2585 | 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref); | |
| 2586 | uint64_t tag_debug_align_in_bits = tag_type->zero_bits ? 0 : | |
| 2587 | 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref); | |
| 2511 | 2588 | // TODO get a more accurate debug scope |
| 2512 | 2589 | ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, |
| 2513 | 2590 | ZigLLVMFileToScope(import->di_file), buf_ptr(&tag_type->name), |
| ... | ... | @@ -2586,7 +2663,7 @@ static bool scope_is_root_decls(Scope *scope) { |
| 2586 | 2663 | |
| 2587 | 2664 | static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, TypeTableEntry *fn_type) { |
| 2588 | 2665 | add_node_error(g, proto_node, |
| 2589 | buf_sprintf("expected 'fn([]const u8, ?&builtin.StackTrace) -> unreachable', found '%s'", | |
| 2666 | buf_sprintf("expected 'fn([]const u8, ?&builtin.StackTrace) unreachable', found '%s'", | |
| 2590 | 2667 | buf_ptr(&fn_type->name))); |
| 2591 | 2668 | } |
| 2592 | 2669 | |
| ... | ... | @@ -3448,7 +3525,6 @@ TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name) { |
| 3448 | 3525 | TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag) { |
| 3449 | 3526 | assert(type_entry->id == TypeTableEntryIdUnion); |
| 3450 | 3527 | assert(type_entry->data.unionation.zero_bits_known); |
| 3451 | assert(type_entry->data.unionation.gen_tag_index != SIZE_MAX); | |
| 3452 | 3528 | for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { |
| 3453 | 3529 | TypeUnionField *field = &type_entry->data.unionation.fields[i]; |
| 3454 | 3530 | if (bigint_cmp(&field->enum_field->value, tag) == CmpEQ) { |
src/ast_render.cpp+4-5| ... | ... | @@ -92,7 +92,7 @@ static const char *return_string(ReturnKind kind) { |
| 92 | 92 | static const char *defer_string(ReturnKind kind) { |
| 93 | 93 | switch (kind) { |
| 94 | 94 | case ReturnKindUnconditional: return "defer"; |
| 95 | case ReturnKindError: return "%defer"; | |
| 95 | case ReturnKindError: return "errdefer"; | |
| 96 | 96 | } |
| 97 | 97 | zig_unreachable(); |
| 98 | 98 | } |
| ... | ... | @@ -450,10 +450,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 450 | 450 | } |
| 451 | 451 | |
| 452 | 452 | AstNode *return_type_node = node->data.fn_proto.return_type; |
| 453 | if (return_type_node != nullptr) { | |
| 454 | fprintf(ar->f, " -> "); | |
| 455 | render_node_grouped(ar, return_type_node); | |
| 456 | } | |
| 453 | assert(return_type_node != nullptr); | |
| 454 | fprintf(ar->f, " "); | |
| 455 | render_node_grouped(ar, return_type_node); | |
| 457 | 456 | break; |
| 458 | 457 | } |
| 459 | 458 | case NodeTypeFnDef: |
src/codegen.cpp+270-81| ... | ... | @@ -485,11 +485,14 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 485 | 485 | addLLVMFnAttr(fn_table_entry->llvm_value, "naked"); |
| 486 | 486 | } else { |
| 487 | 487 | LLVMSetFunctionCallConv(fn_table_entry->llvm_value, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc)); |
| 488 | if (fn_type->data.fn.fn_type_id.cc == CallingConventionCold) { | |
| 489 | ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value); | |
| 490 | } | |
| 491 | 488 | } |
| 492 | 489 | |
| 490 | bool want_cold = fn_table_entry->is_cold || fn_type->data.fn.fn_type_id.cc == CallingConventionCold; | |
| 491 | if (want_cold) { | |
| 492 | ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value); | |
| 493 | } | |
| 494 | ||
| 495 | ||
| 493 | 496 | LLVMSetLinkage(fn_table_entry->llvm_value, to_llvm_linkage(linkage)); |
| 494 | 497 | |
| 495 | 498 | if (linkage == GlobalLinkageIdInternal) { |
| ... | ... | @@ -803,7 +806,7 @@ static bool ir_want_fast_math(CodeGen *g, IrInstruction *instruction) { |
| 803 | 806 | return true; |
| 804 | 807 | } |
| 805 | 808 | |
| 806 | static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) { | |
| 809 | static bool ir_want_runtime_safety(CodeGen *g, IrInstruction *instruction) { | |
| 807 | 810 | if (g->build_mode == BuildModeFastRelease) |
| 808 | 811 | return false; |
| 809 | 812 | |
| ... | ... | @@ -898,7 +901,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace |
| 898 | 901 | LLVMBuildUnreachable(g->builder); |
| 899 | 902 | } |
| 900 | 903 | |
| 901 | static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) { | |
| 904 | static void gen_safety_crash(CodeGen *g, PanicMsgId msg_id) { | |
| 902 | 905 | gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr); |
| 903 | 906 | } |
| 904 | 907 | |
| ... | ... | @@ -1137,7 +1140,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 1137 | 1140 | return fn_val; |
| 1138 | 1141 | } |
| 1139 | 1142 | |
| 1140 | static void gen_debug_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) { | |
| 1143 | static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) { | |
| 1141 | 1144 | LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g); |
| 1142 | 1145 | LLVMValueRef err_ret_trace_val = g->cur_err_ret_trace_val; |
| 1143 | 1146 | if (err_ret_trace_val == nullptr) { |
| ... | ... | @@ -1176,7 +1179,7 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val, |
| 1176 | 1179 | LLVMBuildCondBr(g->builder, lower_ok_val, lower_ok_block, bounds_check_fail_block); |
| 1177 | 1180 | |
| 1178 | 1181 | LLVMPositionBuilderAtEnd(g->builder, bounds_check_fail_block); |
| 1179 | gen_debug_safety_crash(g, PanicMsgIdBoundsCheckFailure); | |
| 1182 | gen_safety_crash(g, PanicMsgIdBoundsCheckFailure); | |
| 1180 | 1183 | |
| 1181 | 1184 | if (upper_value) { |
| 1182 | 1185 | LLVMPositionBuilderAtEnd(g->builder, lower_ok_block); |
| ... | ... | @@ -1187,7 +1190,7 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val, |
| 1187 | 1190 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1188 | 1191 | } |
| 1189 | 1192 | |
| 1190 | static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, TypeTableEntry *actual_type, | |
| 1193 | static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, TypeTableEntry *actual_type, | |
| 1191 | 1194 | TypeTableEntry *wanted_type, LLVMValueRef expr_val) |
| 1192 | 1195 | { |
| 1193 | 1196 | assert(actual_type->id == wanted_type->id); |
| ... | ... | @@ -1206,7 +1209,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, Typ |
| 1206 | 1209 | |
| 1207 | 1210 | if (actual_bits >= wanted_bits && actual_type->id == TypeTableEntryIdInt && |
| 1208 | 1211 | !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed && |
| 1209 | want_debug_safety) | |
| 1212 | want_runtime_safety) | |
| 1210 | 1213 | { |
| 1211 | 1214 | LLVMValueRef zero = LLVMConstNull(actual_type->type_ref); |
| 1212 | 1215 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, ""); |
| ... | ... | @@ -1216,7 +1219,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, Typ |
| 1216 | 1219 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 1217 | 1220 | |
| 1218 | 1221 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 1219 | gen_debug_safety_crash(g, PanicMsgIdCastNegativeToUnsigned); | |
| 1222 | gen_safety_crash(g, PanicMsgIdCastNegativeToUnsigned); | |
| 1220 | 1223 | |
| 1221 | 1224 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1222 | 1225 | } |
| ... | ... | @@ -1240,7 +1243,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, Typ |
| 1240 | 1243 | return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1241 | 1244 | } else if (actual_type->id == TypeTableEntryIdInt) { |
| 1242 | 1245 | LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1243 | if (!want_debug_safety) { | |
| 1246 | if (!want_runtime_safety) { | |
| 1244 | 1247 | return trunc_val; |
| 1245 | 1248 | } |
| 1246 | 1249 | LLVMValueRef orig_val; |
| ... | ... | @@ -1255,7 +1258,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, Typ |
| 1255 | 1258 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 1256 | 1259 | |
| 1257 | 1260 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 1258 | gen_debug_safety_crash(g, PanicMsgIdCastTruncatedData); | |
| 1261 | gen_safety_crash(g, PanicMsgIdCastTruncatedData); | |
| 1259 | 1262 | |
| 1260 | 1263 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1261 | 1264 | return trunc_val; |
| ... | ... | @@ -1283,7 +1286,7 @@ static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddS |
| 1283 | 1286 | LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block); |
| 1284 | 1287 | |
| 1285 | 1288 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 1286 | gen_debug_safety_crash(g, PanicMsgIdIntegerOverflow); | |
| 1289 | gen_safety_crash(g, PanicMsgIdIntegerOverflow); | |
| 1287 | 1290 | |
| 1288 | 1291 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1289 | 1292 | return result; |
| ... | ... | @@ -1491,7 +1494,7 @@ static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry, |
| 1491 | 1494 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 1492 | 1495 | |
| 1493 | 1496 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 1494 | gen_debug_safety_crash(g, PanicMsgIdShlOverflowedBits); | |
| 1497 | gen_safety_crash(g, PanicMsgIdShlOverflowedBits); | |
| 1495 | 1498 | |
| 1496 | 1499 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1497 | 1500 | return result; |
| ... | ... | @@ -1516,7 +1519,7 @@ static LLVMValueRef gen_overflow_shr_op(CodeGen *g, TypeTableEntry *type_entry, |
| 1516 | 1519 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 1517 | 1520 | |
| 1518 | 1521 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 1519 | gen_debug_safety_crash(g, PanicMsgIdShrOverflowedBits); | |
| 1522 | gen_safety_crash(g, PanicMsgIdShrOverflowedBits); | |
| 1520 | 1523 | |
| 1521 | 1524 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1522 | 1525 | return result; |
| ... | ... | @@ -1562,14 +1565,14 @@ static LLVMValueRef bigint_to_llvm_const(LLVMTypeRef type_ref, BigInt *bigint) { |
| 1562 | 1565 | } |
| 1563 | 1566 | } |
| 1564 | 1567 | |
| 1565 | static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_math, | |
| 1568 | static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast_math, | |
| 1566 | 1569 | LLVMValueRef val1, LLVMValueRef val2, |
| 1567 | 1570 | TypeTableEntry *type_entry, DivKind div_kind) |
| 1568 | 1571 | { |
| 1569 | 1572 | ZigLLVMSetFastMath(g->builder, want_fast_math); |
| 1570 | 1573 | |
| 1571 | 1574 | LLVMValueRef zero = LLVMConstNull(type_entry->type_ref); |
| 1572 | if (want_debug_safety && (want_fast_math || type_entry->id != TypeTableEntryIdFloat)) { | |
| 1575 | if (want_runtime_safety && (want_fast_math || type_entry->id != TypeTableEntryIdFloat)) { | |
| 1573 | 1576 | LLVMValueRef is_zero_bit; |
| 1574 | 1577 | if (type_entry->id == TypeTableEntryIdInt) { |
| 1575 | 1578 | is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, ""); |
| ... | ... | @@ -1583,7 +1586,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_m |
| 1583 | 1586 | LLVMBuildCondBr(g->builder, is_zero_bit, div_zero_fail_block, div_zero_ok_block); |
| 1584 | 1587 | |
| 1585 | 1588 | LLVMPositionBuilderAtEnd(g->builder, div_zero_fail_block); |
| 1586 | gen_debug_safety_crash(g, PanicMsgIdDivisionByZero); | |
| 1589 | gen_safety_crash(g, PanicMsgIdDivisionByZero); | |
| 1587 | 1590 | |
| 1588 | 1591 | LLVMPositionBuilderAtEnd(g->builder, div_zero_ok_block); |
| 1589 | 1592 | |
| ... | ... | @@ -1600,7 +1603,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_m |
| 1600 | 1603 | LLVMBuildCondBr(g->builder, overflow_fail_bit, overflow_fail_block, overflow_ok_block); |
| 1601 | 1604 | |
| 1602 | 1605 | LLVMPositionBuilderAtEnd(g->builder, overflow_fail_block); |
| 1603 | gen_debug_safety_crash(g, PanicMsgIdIntegerOverflow); | |
| 1606 | gen_safety_crash(g, PanicMsgIdIntegerOverflow); | |
| 1604 | 1607 | |
| 1605 | 1608 | LLVMPositionBuilderAtEnd(g->builder, overflow_ok_block); |
| 1606 | 1609 | } |
| ... | ... | @@ -1612,7 +1615,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_m |
| 1612 | 1615 | case DivKindFloat: |
| 1613 | 1616 | return result; |
| 1614 | 1617 | case DivKindExact: |
| 1615 | if (want_debug_safety) { | |
| 1618 | if (want_runtime_safety) { | |
| 1616 | 1619 | LLVMValueRef floored = gen_floor(g, result, type_entry); |
| 1617 | 1620 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactOk"); |
| 1618 | 1621 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivExactFail"); |
| ... | ... | @@ -1621,7 +1624,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_m |
| 1621 | 1624 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 1622 | 1625 | |
| 1623 | 1626 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 1624 | gen_debug_safety_crash(g, PanicMsgIdExactDivisionRemainder); | |
| 1627 | gen_safety_crash(g, PanicMsgIdExactDivisionRemainder); | |
| 1625 | 1628 | |
| 1626 | 1629 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1627 | 1630 | } |
| ... | ... | @@ -1669,7 +1672,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_m |
| 1669 | 1672 | return LLVMBuildUDiv(g->builder, val1, val2, ""); |
| 1670 | 1673 | } |
| 1671 | 1674 | case DivKindExact: |
| 1672 | if (want_debug_safety) { | |
| 1675 | if (want_runtime_safety) { | |
| 1673 | 1676 | LLVMValueRef remainder_val; |
| 1674 | 1677 | if (type_entry->data.integral.is_signed) { |
| 1675 | 1678 | remainder_val = LLVMBuildSRem(g->builder, val1, val2, ""); |
| ... | ... | @@ -1683,7 +1686,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, bool want_fast_m |
| 1683 | 1686 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 1684 | 1687 | |
| 1685 | 1688 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 1686 | gen_debug_safety_crash(g, PanicMsgIdExactDivisionRemainder); | |
| 1689 | gen_safety_crash(g, PanicMsgIdExactDivisionRemainder); | |
| 1687 | 1690 | |
| 1688 | 1691 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 1689 | 1692 | } |
| ... | ... | @@ -1721,14 +1724,14 @@ enum RemKind { |
| 1721 | 1724 | RemKindMod, |
| 1722 | 1725 | }; |
| 1723 | 1726 | |
| 1724 | static LLVMValueRef gen_rem(CodeGen *g, bool want_debug_safety, bool want_fast_math, | |
| 1727 | static LLVMValueRef gen_rem(CodeGen *g, bool want_runtime_safety, bool want_fast_math, | |
| 1725 | 1728 | LLVMValueRef val1, LLVMValueRef val2, |
| 1726 | 1729 | TypeTableEntry *type_entry, RemKind rem_kind) |
| 1727 | 1730 | { |
| 1728 | 1731 | ZigLLVMSetFastMath(g->builder, want_fast_math); |
| 1729 | 1732 | |
| 1730 | 1733 | LLVMValueRef zero = LLVMConstNull(type_entry->type_ref); |
| 1731 | if (want_debug_safety) { | |
| 1734 | if (want_runtime_safety) { | |
| 1732 | 1735 | LLVMValueRef is_zero_bit; |
| 1733 | 1736 | if (type_entry->id == TypeTableEntryIdInt) { |
| 1734 | 1737 | LLVMIntPredicate pred = type_entry->data.integral.is_signed ? LLVMIntSLE : LLVMIntEQ; |
| ... | ... | @@ -1743,7 +1746,7 @@ static LLVMValueRef gen_rem(CodeGen *g, bool want_debug_safety, bool want_fast_m |
| 1743 | 1746 | LLVMBuildCondBr(g->builder, is_zero_bit, rem_zero_fail_block, rem_zero_ok_block); |
| 1744 | 1747 | |
| 1745 | 1748 | LLVMPositionBuilderAtEnd(g->builder, rem_zero_fail_block); |
| 1746 | gen_debug_safety_crash(g, PanicMsgIdRemainderDivisionByZero); | |
| 1749 | gen_safety_crash(g, PanicMsgIdRemainderDivisionByZero); | |
| 1747 | 1750 | |
| 1748 | 1751 | LLVMPositionBuilderAtEnd(g->builder, rem_zero_ok_block); |
| 1749 | 1752 | } |
| ... | ... | @@ -1789,8 +1792,8 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 1789 | 1792 | op_id == IrBinOpBitShiftRightExact); |
| 1790 | 1793 | TypeTableEntry *type_entry = op1->value.type; |
| 1791 | 1794 | |
| 1792 | bool want_debug_safety = bin_op_instruction->safety_check_on && | |
| 1793 | ir_want_debug_safety(g, &bin_op_instruction->base); | |
| 1795 | bool want_runtime_safety = bin_op_instruction->safety_check_on && | |
| 1796 | ir_want_runtime_safety(g, &bin_op_instruction->base); | |
| 1794 | 1797 | |
| 1795 | 1798 | LLVMValueRef op1_value = ir_llvm_value(g, op1); |
| 1796 | 1799 | LLVMValueRef op2_value = ir_llvm_value(g, op2); |
| ... | ... | @@ -1838,7 +1841,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 1838 | 1841 | bool is_wrapping = (op_id == IrBinOpAddWrap); |
| 1839 | 1842 | if (is_wrapping) { |
| 1840 | 1843 | return LLVMBuildAdd(g->builder, op1_value, op2_value, ""); |
| 1841 | } else if (want_debug_safety) { | |
| 1844 | } else if (want_runtime_safety) { | |
| 1842 | 1845 | return gen_overflow_op(g, type_entry, AddSubMulAdd, op1_value, op2_value); |
| 1843 | 1846 | } else if (type_entry->data.integral.is_signed) { |
| 1844 | 1847 | return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, ""); |
| ... | ... | @@ -1863,7 +1866,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 1863 | 1866 | bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy); |
| 1864 | 1867 | if (is_sloppy) { |
| 1865 | 1868 | return LLVMBuildShl(g->builder, op1_value, op2_casted, ""); |
| 1866 | } else if (want_debug_safety) { | |
| 1869 | } else if (want_runtime_safety) { | |
| 1867 | 1870 | return gen_overflow_shl_op(g, type_entry, op1_value, op2_casted); |
| 1868 | 1871 | } else if (type_entry->data.integral.is_signed) { |
| 1869 | 1872 | return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_casted, ""); |
| ... | ... | @@ -1884,7 +1887,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 1884 | 1887 | } else { |
| 1885 | 1888 | return LLVMBuildLShr(g->builder, op1_value, op2_casted, ""); |
| 1886 | 1889 | } |
| 1887 | } else if (want_debug_safety) { | |
| 1890 | } else if (want_runtime_safety) { | |
| 1888 | 1891 | return gen_overflow_shr_op(g, type_entry, op1_value, op2_casted); |
| 1889 | 1892 | } else if (type_entry->data.integral.is_signed) { |
| 1890 | 1893 | return ZigLLVMBuildAShrExact(g->builder, op1_value, op2_casted, ""); |
| ... | ... | @@ -1901,7 +1904,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 1901 | 1904 | bool is_wrapping = (op_id == IrBinOpSubWrap); |
| 1902 | 1905 | if (is_wrapping) { |
| 1903 | 1906 | return LLVMBuildSub(g->builder, op1_value, op2_value, ""); |
| 1904 | } else if (want_debug_safety) { | |
| 1907 | } else if (want_runtime_safety) { | |
| 1905 | 1908 | return gen_overflow_op(g, type_entry, AddSubMulSub, op1_value, op2_value); |
| 1906 | 1909 | } else if (type_entry->data.integral.is_signed) { |
| 1907 | 1910 | return LLVMBuildNSWSub(g->builder, op1_value, op2_value, ""); |
| ... | ... | @@ -1920,7 +1923,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 1920 | 1923 | bool is_wrapping = (op_id == IrBinOpMultWrap); |
| 1921 | 1924 | if (is_wrapping) { |
| 1922 | 1925 | return LLVMBuildMul(g->builder, op1_value, op2_value, ""); |
| 1923 | } else if (want_debug_safety) { | |
| 1926 | } else if (want_runtime_safety) { | |
| 1924 | 1927 | return gen_overflow_op(g, type_entry, AddSubMulMul, op1_value, op2_value); |
| 1925 | 1928 | } else if (type_entry->data.integral.is_signed) { |
| 1926 | 1929 | return LLVMBuildNSWMul(g->builder, op1_value, op2_value, ""); |
| ... | ... | @@ -1931,22 +1934,22 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 1931 | 1934 | zig_unreachable(); |
| 1932 | 1935 | } |
| 1933 | 1936 | case IrBinOpDivUnspecified: |
| 1934 | return gen_div(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1937 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1935 | 1938 | op1_value, op2_value, type_entry, DivKindFloat); |
| 1936 | 1939 | case IrBinOpDivExact: |
| 1937 | return gen_div(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1940 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1938 | 1941 | op1_value, op2_value, type_entry, DivKindExact); |
| 1939 | 1942 | case IrBinOpDivTrunc: |
| 1940 | return gen_div(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1943 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1941 | 1944 | op1_value, op2_value, type_entry, DivKindTrunc); |
| 1942 | 1945 | case IrBinOpDivFloor: |
| 1943 | return gen_div(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1946 | return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1944 | 1947 | op1_value, op2_value, type_entry, DivKindFloor); |
| 1945 | 1948 | case IrBinOpRemRem: |
| 1946 | return gen_rem(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1949 | return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1947 | 1950 | op1_value, op2_value, type_entry, RemKindRem); |
| 1948 | 1951 | case IrBinOpRemMod: |
| 1949 | return gen_rem(g, want_debug_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1952 | return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base), | |
| 1950 | 1953 | op1_value, op2_value, type_entry, RemKindMod); |
| 1951 | 1954 | } |
| 1952 | 1955 | zig_unreachable(); |
| ... | ... | @@ -2004,7 +2007,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2004 | 2007 | new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); |
| 2005 | 2008 | } else if (src_size == 1) { |
| 2006 | 2009 | LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false); |
| 2007 | if (ir_want_debug_safety(g, &cast_instruction->base)) { | |
| 2010 | if (ir_want_runtime_safety(g, &cast_instruction->base)) { | |
| 2008 | 2011 | LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); |
| 2009 | 2012 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref); |
| 2010 | 2013 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); |
| ... | ... | @@ -2013,7 +2016,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2013 | 2016 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 2014 | 2017 | |
| 2015 | 2018 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 2016 | gen_debug_safety_crash(g, PanicMsgIdSliceWidenRemainder); | |
| 2019 | gen_safety_crash(g, PanicMsgIdSliceWidenRemainder); | |
| 2017 | 2020 | |
| 2018 | 2021 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 2019 | 2022 | } |
| ... | ... | @@ -2108,7 +2111,7 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executa |
| 2108 | 2111 | int_type = actual_type; |
| 2109 | 2112 | } |
| 2110 | 2113 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 2111 | return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base), int_type, | |
| 2114 | return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), int_type, | |
| 2112 | 2115 | instruction->base.value.type, target_val); |
| 2113 | 2116 | } |
| 2114 | 2117 | |
| ... | ... | @@ -2130,7 +2133,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, |
| 2130 | 2133 | TypeTableEntry *tag_int_type = wanted_type->data.enumeration.tag_int_type; |
| 2131 | 2134 | |
| 2132 | 2135 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 2133 | return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base), | |
| 2136 | return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), | |
| 2134 | 2137 | instruction->target->value.type, tag_int_type, target_val); |
| 2135 | 2138 | } |
| 2136 | 2139 | |
| ... | ... | @@ -2144,7 +2147,7 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, I |
| 2144 | 2147 | |
| 2145 | 2148 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 2146 | 2149 | |
| 2147 | if (ir_want_debug_safety(g, &instruction->base)) { | |
| 2150 | if (ir_want_runtime_safety(g, &instruction->base)) { | |
| 2148 | 2151 | LLVMValueRef zero = LLVMConstNull(actual_type->type_ref); |
| 2149 | 2152 | LLVMValueRef neq_zero_bit = LLVMBuildICmp(g->builder, LLVMIntNE, target_val, zero, ""); |
| 2150 | 2153 | LLVMValueRef ok_bit; |
| ... | ... | @@ -2168,7 +2171,7 @@ static LLVMValueRef ir_render_int_to_err(CodeGen *g, IrExecutable *executable, I |
| 2168 | 2171 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 2169 | 2172 | |
| 2170 | 2173 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 2171 | gen_debug_safety_crash(g, PanicMsgIdInvalidErrorCode); | |
| 2174 | gen_safety_crash(g, PanicMsgIdInvalidErrorCode); | |
| 2172 | 2175 | |
| 2173 | 2176 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 2174 | 2177 | } |
| ... | ... | @@ -2185,11 +2188,11 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutable *executable, I |
| 2185 | 2188 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 2186 | 2189 | |
| 2187 | 2190 | if (actual_type->id == TypeTableEntryIdPureError) { |
| 2188 | return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base), | |
| 2191 | return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), | |
| 2189 | 2192 | g->err_tag_type, wanted_type, target_val); |
| 2190 | 2193 | } else if (actual_type->id == TypeTableEntryIdErrorUnion) { |
| 2191 | 2194 | if (!type_has_bits(actual_type->data.error.child_type)) { |
| 2192 | return gen_widen_or_shorten(g, ir_want_debug_safety(g, &instruction->base), | |
| 2195 | return gen_widen_or_shorten(g, ir_want_runtime_safety(g, &instruction->base), | |
| 2193 | 2196 | g->err_tag_type, wanted_type, target_val); |
| 2194 | 2197 | } else { |
| 2195 | 2198 | zig_panic("TODO"); |
| ... | ... | @@ -2202,8 +2205,8 @@ static LLVMValueRef ir_render_err_to_int(CodeGen *g, IrExecutable *executable, I |
| 2202 | 2205 | static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable, |
| 2203 | 2206 | IrInstructionUnreachable *unreachable_instruction) |
| 2204 | 2207 | { |
| 2205 | if (ir_want_debug_safety(g, &unreachable_instruction->base)) { | |
| 2206 | gen_debug_safety_crash(g, PanicMsgIdUnreachable); | |
| 2208 | if (ir_want_runtime_safety(g, &unreachable_instruction->base)) { | |
| 2209 | gen_safety_crash(g, PanicMsgIdUnreachable); | |
| 2207 | 2210 | } else { |
| 2208 | 2211 | LLVMBuildUnreachable(g->builder); |
| 2209 | 2212 | } |
| ... | ... | @@ -2245,7 +2248,7 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst |
| 2245 | 2248 | } else if (expr_type->id == TypeTableEntryIdInt) { |
| 2246 | 2249 | if (op_id == IrUnOpNegationWrap) { |
| 2247 | 2250 | return LLVMBuildNeg(g->builder, expr, ""); |
| 2248 | } else if (ir_want_debug_safety(g, &un_op_instruction->base)) { | |
| 2251 | } else if (ir_want_runtime_safety(g, &un_op_instruction->base)) { | |
| 2249 | 2252 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr)); |
| 2250 | 2253 | return gen_overflow_op(g, expr_type, AddSubMulSub, zero, expr); |
| 2251 | 2254 | } else if (expr_type->data.integral.is_signed) { |
| ... | ... | @@ -2314,7 +2317,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 2314 | 2317 | var->align_bytes, 0, 0); |
| 2315 | 2318 | gen_assign_raw(g, var->value_ref, var_ptr_type, ir_llvm_value(g, init_value)); |
| 2316 | 2319 | } else { |
| 2317 | bool want_safe = ir_want_debug_safety(g, &decl_var_instruction->base); | |
| 2320 | bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base); | |
| 2318 | 2321 | if (want_safe) { |
| 2319 | 2322 | TypeTableEntry *usize = g->builtin_types.entry_usize; |
| 2320 | 2323 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref); |
| ... | ... | @@ -2406,7 +2409,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 2406 | 2409 | if (!type_has_bits(array_type)) |
| 2407 | 2410 | return nullptr; |
| 2408 | 2411 | |
| 2409 | bool safety_check_on = ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on; | |
| 2412 | bool safety_check_on = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on; | |
| 2410 | 2413 | |
| 2411 | 2414 | if (array_type->id == TypeTableEntryIdArray) { |
| 2412 | 2415 | if (safety_check_on) { |
| ... | ... | @@ -2590,7 +2593,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab |
| 2590 | 2593 | return bitcasted_union_field_ptr; |
| 2591 | 2594 | } |
| 2592 | 2595 | |
| 2593 | if (ir_want_debug_safety(g, &instruction->base)) { | |
| 2596 | if (ir_want_runtime_safety(g, &instruction->base)) { | |
| 2594 | 2597 | LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, ""); |
| 2595 | 2598 | LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, ""); |
| 2596 | 2599 | |
| ... | ... | @@ -2603,7 +2606,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab |
| 2603 | 2606 | LLVMBuildCondBr(g->builder, ok_val, ok_block, bad_block); |
| 2604 | 2607 | |
| 2605 | 2608 | LLVMPositionBuilderAtEnd(g->builder, bad_block); |
| 2606 | gen_debug_safety_crash(g, PanicMsgIdBadUnionField); | |
| 2609 | gen_safety_crash(g, PanicMsgIdBadUnionField); | |
| 2607 | 2610 | |
| 2608 | 2611 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 2609 | 2612 | } |
| ... | ... | @@ -2773,14 +2776,14 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 2773 | 2776 | TypeTableEntry *child_type = maybe_type->data.maybe.child_type; |
| 2774 | 2777 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); |
| 2775 | 2778 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); |
| 2776 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { | |
| 2779 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) { | |
| 2777 | 2780 | LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle); |
| 2778 | 2781 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeOk"); |
| 2779 | 2782 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapMaybeFail"); |
| 2780 | 2783 | LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block); |
| 2781 | 2784 | |
| 2782 | 2785 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 2783 | gen_debug_safety_crash(g, PanicMsgIdUnwrapMaybeFail); | |
| 2786 | gen_safety_crash(g, PanicMsgIdUnwrapMaybeFail); | |
| 2784 | 2787 | |
| 2785 | 2788 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 2786 | 2789 | } |
| ... | ... | @@ -2910,7 +2913,7 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI |
| 2910 | 2913 | } |
| 2911 | 2914 | |
| 2912 | 2915 | LLVMValueRef err_val = ir_llvm_value(g, instruction->value); |
| 2913 | if (ir_want_debug_safety(g, &instruction->base)) { | |
| 2916 | if (ir_want_runtime_safety(g, &instruction->base)) { | |
| 2914 | 2917 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val)); |
| 2915 | 2918 | LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false); |
| 2916 | 2919 | add_bounds_check(g, err_val, LLVMIntNE, zero, LLVMIntULT, end_val); |
| ... | ... | @@ -2932,7 +2935,7 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable |
| 2932 | 2935 | |
| 2933 | 2936 | TypeTableEntry *tag_int_type = enum_type->data.enumeration.tag_int_type; |
| 2934 | 2937 | LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target); |
| 2935 | if (ir_want_debug_safety(g, &instruction->base)) { | |
| 2938 | if (ir_want_runtime_safety(g, &instruction->base)) { | |
| 2936 | 2939 | size_t field_count = enum_type->data.enumeration.src_field_count; |
| 2937 | 2940 | |
| 2938 | 2941 | // if the field_count can't fit in the bits of the enum_type, then it can't possibly |
| ... | ... | @@ -2985,8 +2988,8 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I |
| 2985 | 2988 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 2986 | 2989 | assert(target_val); |
| 2987 | 2990 | |
| 2988 | bool want_debug_safety = ir_want_debug_safety(g, &instruction->base); | |
| 2989 | if (!want_debug_safety) { | |
| 2991 | bool want_runtime_safety = ir_want_runtime_safety(g, &instruction->base); | |
| 2992 | if (!want_runtime_safety) { | |
| 2990 | 2993 | return target_val; |
| 2991 | 2994 | } |
| 2992 | 2995 | |
| ... | ... | @@ -3035,7 +3038,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I |
| 3035 | 3038 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| 3036 | 3039 | |
| 3037 | 3040 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 3038 | gen_debug_safety_crash(g, PanicMsgIdIncorrectAlignment); | |
| 3041 | gen_safety_crash(g, PanicMsgIdIncorrectAlignment); | |
| 3039 | 3042 | |
| 3040 | 3043 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 3041 | 3044 | |
| ... | ... | @@ -3173,7 +3176,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 3173 | 3176 | |
| 3174 | 3177 | LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr; |
| 3175 | 3178 | |
| 3176 | bool want_debug_safety = instruction->safety_check_on && ir_want_debug_safety(g, &instruction->base); | |
| 3179 | bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base); | |
| 3177 | 3180 | |
| 3178 | 3181 | if (array_type->id == TypeTableEntryIdArray) { |
| 3179 | 3182 | LLVMValueRef start_val = ir_llvm_value(g, instruction->start); |
| ... | ... | @@ -3184,7 +3187,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 3184 | 3187 | end_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, array_type->data.array.len, false); |
| 3185 | 3188 | } |
| 3186 | 3189 | |
| 3187 | if (want_debug_safety) { | |
| 3190 | if (want_runtime_safety) { | |
| 3188 | 3191 | add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val); |
| 3189 | 3192 | if (instruction->end) { |
| 3190 | 3193 | LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| ... | ... | @@ -3195,7 +3198,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 3195 | 3198 | if (!type_has_bits(array_type)) { |
| 3196 | 3199 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, ""); |
| 3197 | 3200 | |
| 3198 | // TODO if debug safety is on, store 0xaaaaaaa in ptr field | |
| 3201 | // TODO if runtime safety is on, store 0xaaaaaaa in ptr field | |
| 3199 | 3202 | LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, ""); |
| 3200 | 3203 | gen_store_untyped(g, len_value, len_field_ptr, 0, false); |
| 3201 | 3204 | return tmp_struct_ptr; |
| ... | ... | @@ -3219,7 +3222,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 3219 | 3222 | LLVMValueRef start_val = ir_llvm_value(g, instruction->start); |
| 3220 | 3223 | LLVMValueRef end_val = ir_llvm_value(g, instruction->end); |
| 3221 | 3224 | |
| 3222 | if (want_debug_safety) { | |
| 3225 | if (want_runtime_safety) { | |
| 3223 | 3226 | add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val); |
| 3224 | 3227 | } |
| 3225 | 3228 | |
| ... | ... | @@ -3243,7 +3246,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 3243 | 3246 | assert(len_index != SIZE_MAX); |
| 3244 | 3247 | |
| 3245 | 3248 | LLVMValueRef prev_end = nullptr; |
| 3246 | if (!instruction->end || want_debug_safety) { | |
| 3249 | if (!instruction->end || want_runtime_safety) { | |
| 3247 | 3250 | LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, ""); |
| 3248 | 3251 | prev_end = gen_load_untyped(g, src_len_ptr, 0, false, ""); |
| 3249 | 3252 | } |
| ... | ... | @@ -3256,7 +3259,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 3256 | 3259 | end_val = prev_end; |
| 3257 | 3260 | } |
| 3258 | 3261 | |
| 3259 | if (want_debug_safety) { | |
| 3262 | if (want_runtime_safety) { | |
| 3260 | 3263 | assert(prev_end); |
| 3261 | 3264 | add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val); |
| 3262 | 3265 | if (instruction->end) { |
| ... | ... | @@ -3429,7 +3432,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu |
| 3429 | 3432 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); |
| 3430 | 3433 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); |
| 3431 | 3434 | |
| 3432 | if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on && g->error_decls.length > 1) { | |
| 3435 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->error_decls.length > 1) { | |
| 3433 | 3436 | LLVMValueRef err_val; |
| 3434 | 3437 | if (type_has_bits(child_type)) { |
| 3435 | 3438 | LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); |
| ... | ... | @@ -3444,7 +3447,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu |
| 3444 | 3447 | LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block); |
| 3445 | 3448 | |
| 3446 | 3449 | LLVMPositionBuilderAtEnd(g->builder, err_block); |
| 3447 | gen_debug_safety_crash_for_err(g, err_val); | |
| 3450 | gen_safety_crash_for_err(g, err_val); | |
| 3448 | 3451 | |
| 3449 | 3452 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 3450 | 3453 | } |
| ... | ... | @@ -3656,7 +3659,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3656 | 3659 | case IrInstructionIdToPtrType: |
| 3657 | 3660 | case IrInstructionIdPtrTypeChild: |
| 3658 | 3661 | case IrInstructionIdFieldPtr: |
| 3659 | case IrInstructionIdSetDebugSafety: | |
| 3662 | case IrInstructionIdSetCold: | |
| 3663 | case IrInstructionIdSetRuntimeSafety: | |
| 3660 | 3664 | case IrInstructionIdSetFloatMode: |
| 3661 | 3665 | case IrInstructionIdArrayType: |
| 3662 | 3666 | case IrInstructionIdSliceType: |
| ... | ... | @@ -5233,7 +5237,8 @@ static void define_builtin_fns(CodeGen *g) { |
| 5233 | 5237 | create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1); |
| 5234 | 5238 | create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX); |
| 5235 | 5239 | create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int |
| 5236 | create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); | |
| 5240 | create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1); | |
| 5241 | create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1); | |
| 5237 | 5242 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2); |
| 5238 | 5243 | create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); |
| 5239 | 5244 | create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrCast", 2); |
| ... | ... | @@ -5788,7 +5793,76 @@ static const char *c_int_type_names[] = { |
| 5788 | 5793 | "unsigned long long", |
| 5789 | 5794 | }; |
| 5790 | 5795 | |
| 5791 | static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { | |
| 5796 | struct GenH { | |
| 5797 | ZigList<TypeTableEntry *> types_to_declare; | |
| 5798 | }; | |
| 5799 | ||
| 5800 | static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry) { | |
| 5801 | if (type_entry->gen_h_loop_flag) | |
| 5802 | return; | |
| 5803 | type_entry->gen_h_loop_flag = true; | |
| 5804 | ||
| 5805 | switch (type_entry->id) { | |
| 5806 | case TypeTableEntryIdInvalid: | |
| 5807 | case TypeTableEntryIdVar: | |
| 5808 | case TypeTableEntryIdMetaType: | |
| 5809 | case TypeTableEntryIdNumLitFloat: | |
| 5810 | case TypeTableEntryIdNumLitInt: | |
| 5811 | case TypeTableEntryIdUndefLit: | |
| 5812 | case TypeTableEntryIdNullLit: | |
| 5813 | case TypeTableEntryIdNamespace: | |
| 5814 | case TypeTableEntryIdBlock: | |
| 5815 | case TypeTableEntryIdBoundFn: | |
| 5816 | case TypeTableEntryIdArgTuple: | |
| 5817 | case TypeTableEntryIdErrorUnion: | |
| 5818 | case TypeTableEntryIdPureError: | |
| 5819 | zig_unreachable(); | |
| 5820 | case TypeTableEntryIdVoid: | |
| 5821 | case TypeTableEntryIdUnreachable: | |
| 5822 | case TypeTableEntryIdBool: | |
| 5823 | case TypeTableEntryIdInt: | |
| 5824 | case TypeTableEntryIdFloat: | |
| 5825 | return; | |
| 5826 | case TypeTableEntryIdOpaque: | |
| 5827 | gen_h->types_to_declare.append(type_entry); | |
| 5828 | return; | |
| 5829 | case TypeTableEntryIdStruct: | |
| 5830 | for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { | |
| 5831 | TypeStructField *field = &type_entry->data.structure.fields[i]; | |
| 5832 | prepend_c_type_to_decl_list(g, gen_h, field->type_entry); | |
| 5833 | } | |
| 5834 | gen_h->types_to_declare.append(type_entry); | |
| 5835 | return; | |
| 5836 | case TypeTableEntryIdUnion: | |
| 5837 | for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { | |
| 5838 | TypeUnionField *field = &type_entry->data.unionation.fields[i]; | |
| 5839 | prepend_c_type_to_decl_list(g, gen_h, field->type_entry); | |
| 5840 | } | |
| 5841 | gen_h->types_to_declare.append(type_entry); | |
| 5842 | return; | |
| 5843 | case TypeTableEntryIdEnum: | |
| 5844 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.enumeration.tag_int_type); | |
| 5845 | gen_h->types_to_declare.append(type_entry); | |
| 5846 | return; | |
| 5847 | case TypeTableEntryIdPointer: | |
| 5848 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.pointer.child_type); | |
| 5849 | return; | |
| 5850 | case TypeTableEntryIdArray: | |
| 5851 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type); | |
| 5852 | return; | |
| 5853 | case TypeTableEntryIdMaybe: | |
| 5854 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type); | |
| 5855 | return; | |
| 5856 | case TypeTableEntryIdFn: | |
| 5857 | for (size_t i = 0; i < type_entry->data.fn.fn_type_id.param_count; i += 1) { | |
| 5858 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.fn.fn_type_id.param_info[i].type); | |
| 5859 | } | |
| 5860 | prepend_c_type_to_decl_list(g, gen_h, type_entry->data.fn.fn_type_id.return_type); | |
| 5861 | return; | |
| 5862 | } | |
| 5863 | } | |
| 5864 | ||
| 5865 | static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf *out_buf) { | |
| 5792 | 5866 | assert(type_entry); |
| 5793 | 5867 | |
| 5794 | 5868 | for (size_t i = 0; i < array_length(c_int_type_names); i += 1) { |
| ... | ... | @@ -5816,6 +5890,8 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { |
| 5816 | 5890 | return; |
| 5817 | 5891 | } |
| 5818 | 5892 | |
| 5893 | prepend_c_type_to_decl_list(g, gen_h, type_entry); | |
| 5894 | ||
| 5819 | 5895 | switch (type_entry->id) { |
| 5820 | 5896 | case TypeTableEntryIdVoid: |
| 5821 | 5897 | buf_init_from_str(out_buf, "void"); |
| ... | ... | @@ -5856,7 +5932,7 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { |
| 5856 | 5932 | { |
| 5857 | 5933 | Buf child_buf = BUF_INIT; |
| 5858 | 5934 | TypeTableEntry *child_type = type_entry->data.pointer.child_type; |
| 5859 | get_c_type(g, child_type, &child_buf); | |
| 5935 | get_c_type(g, gen_h, child_type, &child_buf); | |
| 5860 | 5936 | |
| 5861 | 5937 | const char *const_str = type_entry->data.pointer.is_const ? "const " : ""; |
| 5862 | 5938 | buf_resize(out_buf, 0); |
| ... | ... | @@ -5872,23 +5948,47 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { |
| 5872 | 5948 | } else if (child_type->id == TypeTableEntryIdPointer || |
| 5873 | 5949 | child_type->id == TypeTableEntryIdFn) |
| 5874 | 5950 | { |
| 5875 | return get_c_type(g, child_type, out_buf); | |
| 5951 | return get_c_type(g, gen_h, child_type, out_buf); | |
| 5876 | 5952 | } else { |
| 5877 | 5953 | zig_unreachable(); |
| 5878 | 5954 | } |
| 5879 | 5955 | } |
| 5880 | 5956 | case TypeTableEntryIdStruct: |
| 5957 | { | |
| 5958 | buf_init_from_str(out_buf, "struct "); | |
| 5959 | buf_append_buf(out_buf, &type_entry->name); | |
| 5960 | return; | |
| 5961 | } | |
| 5962 | case TypeTableEntryIdUnion: | |
| 5963 | { | |
| 5964 | buf_init_from_str(out_buf, "union "); | |
| 5965 | buf_append_buf(out_buf, &type_entry->name); | |
| 5966 | return; | |
| 5967 | } | |
| 5968 | case TypeTableEntryIdEnum: | |
| 5969 | { | |
| 5970 | buf_init_from_str(out_buf, "enum "); | |
| 5971 | buf_append_buf(out_buf, &type_entry->name); | |
| 5972 | return; | |
| 5973 | } | |
| 5881 | 5974 | case TypeTableEntryIdOpaque: |
| 5882 | 5975 | { |
| 5883 | // TODO add to table of structs we need to declare | |
| 5884 | 5976 | buf_init_from_buf(out_buf, &type_entry->name); |
| 5885 | 5977 | return; |
| 5886 | 5978 | } |
| 5887 | 5979 | case TypeTableEntryIdArray: |
| 5980 | { | |
| 5981 | TypeTableEntryArray *array_data = &type_entry->data.array; | |
| 5982 | ||
| 5983 | Buf *child_buf = buf_alloc(); | |
| 5984 | get_c_type(g, gen_h, array_data->child_type, child_buf); | |
| 5985 | ||
| 5986 | buf_resize(out_buf, 0); | |
| 5987 | buf_appendf(out_buf, "%s", buf_ptr(child_buf)); | |
| 5988 | return; | |
| 5989 | } | |
| 5888 | 5990 | case TypeTableEntryIdErrorUnion: |
| 5889 | 5991 | case TypeTableEntryIdPureError: |
| 5890 | case TypeTableEntryIdEnum: | |
| 5891 | case TypeTableEntryIdUnion: | |
| 5892 | 5992 | case TypeTableEntryIdFn: |
| 5893 | 5993 | zig_panic("TODO implement get_c_type for more types"); |
| 5894 | 5994 | case TypeTableEntryIdInvalid: |
| ... | ... | @@ -5942,6 +6042,9 @@ static void gen_h_file(CodeGen *g) { |
| 5942 | 6042 | if (!g->want_h_file) |
| 5943 | 6043 | return; |
| 5944 | 6044 | |
| 6045 | GenH gen_h_data = {0}; | |
| 6046 | GenH *gen_h = &gen_h_data; | |
| 6047 | ||
| 5945 | 6048 | codegen_add_time_event(g, "Generate .h"); |
| 5946 | 6049 | |
| 5947 | 6050 | assert(!g->is_test_build); |
| ... | ... | @@ -5971,7 +6074,7 @@ static void gen_h_file(CodeGen *g) { |
| 5971 | 6074 | FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id; |
| 5972 | 6075 | |
| 5973 | 6076 | Buf return_type_c = BUF_INIT; |
| 5974 | get_c_type(g, fn_type_id->return_type, &return_type_c); | |
| 6077 | get_c_type(g, gen_h, fn_type_id->return_type, &return_type_c); | |
| 5975 | 6078 | |
| 5976 | 6079 | buf_appendf(&h_buf, "%s %s %s(", |
| 5977 | 6080 | buf_ptr(export_macro), |
| ... | ... | @@ -5987,9 +6090,16 @@ static void gen_h_file(CodeGen *g) { |
| 5987 | 6090 | |
| 5988 | 6091 | const char *comma_str = (param_i == 0) ? "" : ", "; |
| 5989 | 6092 | const char *restrict_str = param_info->is_noalias ? "restrict" : ""; |
| 5990 | get_c_type(g, param_info->type, &param_type_c); | |
| 5991 | buf_appendf(&h_buf, "%s%s%s %s", comma_str, buf_ptr(&param_type_c), | |
| 5992 | restrict_str, buf_ptr(param_name)); | |
| 6093 | get_c_type(g, gen_h, param_info->type, &param_type_c); | |
| 6094 | ||
| 6095 | if (param_info->type->id == TypeTableEntryIdArray) { | |
| 6096 | // Arrays decay to pointers | |
| 6097 | buf_appendf(&h_buf, "%s%s%s %s[]", comma_str, buf_ptr(&param_type_c), | |
| 6098 | restrict_str, buf_ptr(param_name)); | |
| 6099 | } else { | |
| 6100 | buf_appendf(&h_buf, "%s%s%s %s", comma_str, buf_ptr(&param_type_c), | |
| 6101 | restrict_str, buf_ptr(param_name)); | |
| 6102 | } | |
| 5993 | 6103 | } |
| 5994 | 6104 | buf_appendf(&h_buf, ")"); |
| 5995 | 6105 | } else { |
| ... | ... | @@ -6027,6 +6137,85 @@ static void gen_h_file(CodeGen *g) { |
| 6027 | 6137 | fprintf(out_h, "#endif\n"); |
| 6028 | 6138 | fprintf(out_h, "\n"); |
| 6029 | 6139 | |
| 6140 | for (size_t type_i = 0; type_i < gen_h->types_to_declare.length; type_i += 1) { | |
| 6141 | TypeTableEntry *type_entry = gen_h->types_to_declare.at(type_i); | |
| 6142 | switch (type_entry->id) { | |
| 6143 | case TypeTableEntryIdInvalid: | |
| 6144 | case TypeTableEntryIdVar: | |
| 6145 | case TypeTableEntryIdMetaType: | |
| 6146 | case TypeTableEntryIdVoid: | |
| 6147 | case TypeTableEntryIdBool: | |
| 6148 | case TypeTableEntryIdUnreachable: | |
| 6149 | case TypeTableEntryIdInt: | |
| 6150 | case TypeTableEntryIdFloat: | |
| 6151 | case TypeTableEntryIdPointer: | |
| 6152 | case TypeTableEntryIdNumLitFloat: | |
| 6153 | case TypeTableEntryIdNumLitInt: | |
| 6154 | case TypeTableEntryIdArray: | |
| 6155 | case TypeTableEntryIdUndefLit: | |
| 6156 | case TypeTableEntryIdNullLit: | |
| 6157 | case TypeTableEntryIdErrorUnion: | |
| 6158 | case TypeTableEntryIdPureError: | |
| 6159 | case TypeTableEntryIdNamespace: | |
| 6160 | case TypeTableEntryIdBlock: | |
| 6161 | case TypeTableEntryIdBoundFn: | |
| 6162 | case TypeTableEntryIdArgTuple: | |
| 6163 | case TypeTableEntryIdMaybe: | |
| 6164 | case TypeTableEntryIdFn: | |
| 6165 | zig_unreachable(); | |
| 6166 | case TypeTableEntryIdEnum: | |
| 6167 | assert(type_entry->data.enumeration.layout == ContainerLayoutExtern); | |
| 6168 | fprintf(out_h, "enum %s {\n", buf_ptr(&type_entry->name)); | |
| 6169 | for (uint32_t field_i = 0; field_i < type_entry->data.enumeration.src_field_count; field_i += 1) { | |
| 6170 | TypeEnumField *enum_field = &type_entry->data.enumeration.fields[field_i]; | |
| 6171 | Buf *value_buf = buf_alloc(); | |
| 6172 | bigint_append_buf(value_buf, &enum_field->value, 10); | |
| 6173 | fprintf(out_h, " %s = %s", buf_ptr(enum_field->name), buf_ptr(value_buf)); | |
| 6174 | if (field_i != type_entry->data.enumeration.src_field_count - 1) { | |
| 6175 | fprintf(out_h, ","); | |
| 6176 | } | |
| 6177 | fprintf(out_h, "\n"); | |
| 6178 | } | |
| 6179 | fprintf(out_h, "};\n\n"); | |
| 6180 | break; | |
| 6181 | case TypeTableEntryIdStruct: | |
| 6182 | assert(type_entry->data.structure.layout == ContainerLayoutExtern); | |
| 6183 | fprintf(out_h, "struct %s {\n", buf_ptr(&type_entry->name)); | |
| 6184 | for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) { | |
| 6185 | TypeStructField *struct_field = &type_entry->data.structure.fields[field_i]; | |
| 6186 | ||
| 6187 | Buf *type_name_buf = buf_alloc(); | |
| 6188 | get_c_type(g, gen_h, struct_field->type_entry, type_name_buf); | |
| 6189 | ||
| 6190 | if (struct_field->type_entry->id == TypeTableEntryIdArray) { | |
| 6191 | fprintf(out_h, " %s %s[%" ZIG_PRI_u64 "];\n", buf_ptr(type_name_buf), | |
| 6192 | buf_ptr(struct_field->name), | |
| 6193 | struct_field->type_entry->data.array.len); | |
| 6194 | } else { | |
| 6195 | fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(struct_field->name)); | |
| 6196 | } | |
| 6197 | ||
| 6198 | } | |
| 6199 | fprintf(out_h, "};\n\n"); | |
| 6200 | break; | |
| 6201 | case TypeTableEntryIdUnion: | |
| 6202 | assert(type_entry->data.unionation.layout == ContainerLayoutExtern); | |
| 6203 | fprintf(out_h, "union %s {\n", buf_ptr(&type_entry->name)); | |
| 6204 | for (uint32_t field_i = 0; field_i < type_entry->data.unionation.src_field_count; field_i += 1) { | |
| 6205 | TypeUnionField *union_field = &type_entry->data.unionation.fields[field_i]; | |
| 6206 | ||
| 6207 | Buf *type_name_buf = buf_alloc(); | |
| 6208 | get_c_type(g, gen_h, union_field->type_entry, type_name_buf); | |
| 6209 | fprintf(out_h, " %s %s;\n", buf_ptr(type_name_buf), buf_ptr(union_field->name)); | |
| 6210 | } | |
| 6211 | fprintf(out_h, "};\n\n"); | |
| 6212 | break; | |
| 6213 | case TypeTableEntryIdOpaque: | |
| 6214 | fprintf(out_h, "struct %s;\n\n", buf_ptr(&type_entry->name)); | |
| 6215 | break; | |
| 6216 | } | |
| 6217 | } | |
| 6218 | ||
| 6030 | 6219 | fprintf(out_h, "%s", buf_ptr(&h_buf)); |
| 6031 | 6220 | |
| 6032 | 6221 | fprintf(out_h, "\n#endif\n"); |
src/ir.cpp+132-69| ... | ... | @@ -272,8 +272,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *) |
| 272 | 272 | return IrInstructionIdPtrTypeChild; |
| 273 | 273 | } |
| 274 | 274 | |
| 275 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety *) { | |
| 276 | return IrInstructionIdSetDebugSafety; | |
| 275 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetCold *) { | |
| 276 | return IrInstructionIdSetCold; | |
| 277 | } | |
| 278 | ||
| 279 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetRuntimeSafety *) { | |
| 280 | return IrInstructionIdSetRuntimeSafety; | |
| 277 | 281 | } |
| 278 | 282 | |
| 279 | 283 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFloatMode *) { |
| ... | ... | @@ -1262,15 +1266,22 @@ static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstN |
| 1262 | 1266 | return &instruction->base; |
| 1263 | 1267 | } |
| 1264 | 1268 | |
| 1265 | static IrInstruction *ir_build_set_debug_safety(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1266 | IrInstruction *scope_value, IrInstruction *debug_safety_on) | |
| 1269 | static IrInstruction *ir_build_set_cold(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *is_cold) { | |
| 1270 | IrInstructionSetCold *instruction = ir_build_instruction<IrInstructionSetCold>(irb, scope, source_node); | |
| 1271 | instruction->is_cold = is_cold; | |
| 1272 | ||
| 1273 | ir_ref_instruction(is_cold, irb->current_basic_block); | |
| 1274 | ||
| 1275 | return &instruction->base; | |
| 1276 | } | |
| 1277 | ||
| 1278 | static IrInstruction *ir_build_set_runtime_safety(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1279 | IrInstruction *safety_on) | |
| 1267 | 1280 | { |
| 1268 | IrInstructionSetDebugSafety *instruction = ir_build_instruction<IrInstructionSetDebugSafety>(irb, scope, source_node); | |
| 1269 | instruction->scope_value = scope_value; | |
| 1270 | instruction->debug_safety_on = debug_safety_on; | |
| 1281 | IrInstructionSetRuntimeSafety *instruction = ir_build_instruction<IrInstructionSetRuntimeSafety>(irb, scope, source_node); | |
| 1282 | instruction->safety_on = safety_on; | |
| 1271 | 1283 | |
| 1272 | ir_ref_instruction(scope_value, irb->current_basic_block); | |
| 1273 | ir_ref_instruction(debug_safety_on, irb->current_basic_block); | |
| 1284 | ir_ref_instruction(safety_on, irb->current_basic_block); | |
| 1274 | 1285 | |
| 1275 | 1286 | return &instruction->base; |
| 1276 | 1287 | } |
| ... | ... | @@ -3065,19 +3076,23 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 3065 | 3076 | return arg; |
| 3066 | 3077 | return ir_build_typeof(irb, scope, node, arg); |
| 3067 | 3078 | } |
| 3068 | case BuiltinFnIdSetDebugSafety: | |
| 3079 | case BuiltinFnIdSetCold: | |
| 3069 | 3080 | { |
| 3070 | 3081 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 3071 | 3082 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| 3072 | 3083 | if (arg0_value == irb->codegen->invalid_instruction) |
| 3073 | 3084 | return arg0_value; |
| 3074 | 3085 | |
| 3075 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | |
| 3076 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | |
| 3077 | if (arg1_value == irb->codegen->invalid_instruction) | |
| 3078 | return arg1_value; | |
| 3086 | return ir_build_set_cold(irb, scope, node, arg0_value); | |
| 3087 | } | |
| 3088 | case BuiltinFnIdSetRuntimeSafety: | |
| 3089 | { | |
| 3090 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 3091 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | |
| 3092 | if (arg0_value == irb->codegen->invalid_instruction) | |
| 3093 | return arg0_value; | |
| 3079 | 3094 | |
| 3080 | return ir_build_set_debug_safety(irb, scope, node, arg0_value, arg1_value); | |
| 3095 | return ir_build_set_runtime_safety(irb, scope, node, arg0_value); | |
| 3081 | 3096 | } |
| 3082 | 3097 | case BuiltinFnIdSetFloatMode: |
| 3083 | 3098 | { |
| ... | ... | @@ -4769,7 +4784,8 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4769 | 4784 | } |
| 4770 | 4785 | |
| 4771 | 4786 | static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *switch_node, AstNode *prong_node, |
| 4772 | IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *target_value_ptr, IrInstruction *prong_value, | |
| 4787 | IrBasicBlock *end_block, IrInstruction *is_comptime, IrInstruction *var_is_comptime, | |
| 4788 | IrInstruction *target_value_ptr, IrInstruction *prong_value, | |
| 4773 | 4789 | ZigList<IrBasicBlock *> *incoming_blocks, ZigList<IrInstruction *> *incoming_values) |
| 4774 | 4790 | { |
| 4775 | 4791 | assert(switch_node->type == NodeTypeSwitchExpr); |
| ... | ... | @@ -4786,7 +4802,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit |
| 4786 | 4802 | bool is_shadowable = false; |
| 4787 | 4803 | bool is_const = true; |
| 4788 | 4804 | VariableTableEntry *var = ir_create_var(irb, var_symbol_node, scope, |
| 4789 | var_name, is_const, is_const, is_shadowable, is_comptime); | |
| 4805 | var_name, is_const, is_const, is_shadowable, var_is_comptime); | |
| 4790 | 4806 | child_scope = var->child_scope; |
| 4791 | 4807 | IrInstruction *var_value; |
| 4792 | 4808 | if (prong_value) { |
| ... | ... | @@ -4827,10 +4843,13 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4827 | 4843 | ZigList<IrInstructionSwitchBrCase> cases = {0}; |
| 4828 | 4844 | |
| 4829 | 4845 | IrInstruction *is_comptime; |
| 4846 | IrInstruction *var_is_comptime; | |
| 4830 | 4847 | if (ir_should_inline(irb->exec, scope)) { |
| 4831 | 4848 | is_comptime = ir_build_const_bool(irb, scope, node, true); |
| 4849 | var_is_comptime = is_comptime; | |
| 4832 | 4850 | } else { |
| 4833 | 4851 | is_comptime = ir_build_test_comptime(irb, scope, node, target_value); |
| 4852 | var_is_comptime = ir_build_test_comptime(irb, scope, node, target_value_ptr); | |
| 4834 | 4853 | } |
| 4835 | 4854 | |
| 4836 | 4855 | ZigList<IrInstruction *> incoming_values = {0}; |
| ... | ... | @@ -4856,7 +4875,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4856 | 4875 | IrBasicBlock *prev_block = irb->current_basic_block; |
| 4857 | 4876 | ir_set_cursor_at_end_and_append_block(irb, else_block); |
| 4858 | 4877 | if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block, |
| 4859 | is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values)) | |
| 4878 | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values)) | |
| 4860 | 4879 | { |
| 4861 | 4880 | return irb->codegen->invalid_instruction; |
| 4862 | 4881 | } |
| ... | ... | @@ -4923,7 +4942,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4923 | 4942 | |
| 4924 | 4943 | ir_set_cursor_at_end_and_append_block(irb, range_block_yes); |
| 4925 | 4944 | if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block, |
| 4926 | is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values)) | |
| 4945 | is_comptime, var_is_comptime, target_value_ptr, nullptr, &incoming_blocks, &incoming_values)) | |
| 4927 | 4946 | { |
| 4928 | 4947 | return irb->codegen->invalid_instruction; |
| 4929 | 4948 | } |
| ... | ... | @@ -4967,7 +4986,7 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4967 | 4986 | IrBasicBlock *prev_block = irb->current_basic_block; |
| 4968 | 4987 | ir_set_cursor_at_end_and_append_block(irb, prong_block); |
| 4969 | 4988 | if (!ir_gen_switch_prong_expr(irb, scope, node, prong_node, end_block, |
| 4970 | is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values)) | |
| 4989 | is_comptime, var_is_comptime, target_value_ptr, only_item_value, &incoming_blocks, &incoming_values)) | |
| 4971 | 4990 | { |
| 4972 | 4991 | return irb->codegen->invalid_instruction; |
| 4973 | 4992 | } |
| ... | ... | @@ -4992,7 +5011,11 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 4992 | 5011 | |
| 4993 | 5012 | ir_set_cursor_at_end_and_append_block(irb, end_block); |
| 4994 | 5013 | assert(incoming_blocks.length == incoming_values.length); |
| 4995 | return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items); | |
| 5014 | if (incoming_blocks.length == 0) { | |
| 5015 | return ir_build_const_void(irb, scope, node); | |
| 5016 | } else { | |
| 5017 | return ir_build_phi(irb, scope, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items); | |
| 5018 | } | |
| 4996 | 5019 | } |
| 4997 | 5020 | |
| 4998 | 5021 | static IrInstruction *ir_gen_comptime(IrBuilder *irb, Scope *parent_scope, AstNode *node, LVal lval) { |
| ... | ... | @@ -8816,6 +8839,13 @@ static TypeTableEntry *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp * |
| 8816 | 8839 | if (op_id == IrBinOpBitShiftLeftLossy) { |
| 8817 | 8840 | op_id = IrBinOpBitShiftLeftExact; |
| 8818 | 8841 | } |
| 8842 | ||
| 8843 | if (casted_op2->value.data.x_bigint.is_negative) { | |
| 8844 | Buf *val_buf = buf_alloc(); | |
| 8845 | bigint_append_buf(val_buf, &casted_op2->value.data.x_bigint, 10); | |
| 8846 | ir_add_error(ira, casted_op2, buf_sprintf("shift by negative value %s", buf_ptr(val_buf))); | |
| 8847 | return ira->codegen->builtin_types.entry_invalid; | |
| 8848 | } | |
| 8819 | 8849 | } else { |
| 8820 | 8850 | TypeTableEntry *shift_amt_type = get_smallest_unsigned_int_type(ira->codegen, |
| 8821 | 8851 | op1->value.type->data.integral.bit_count - 1); |
| ... | ... | @@ -9002,7 +9032,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 9002 | 9032 | int err; |
| 9003 | 9033 | if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, out_val))) { |
| 9004 | 9034 | if (err == ErrorDivByZero) { |
| 9005 | ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("division by zero is undefined")); | |
| 9035 | ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("division by zero")); | |
| 9006 | 9036 | return ira->codegen->builtin_types.entry_invalid; |
| 9007 | 9037 | } else if (err == ErrorOverflow) { |
| 9008 | 9038 | ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("operation caused overflow")); |
| ... | ... | @@ -11540,72 +11570,90 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 11540 | 11570 | return ira->codegen->builtin_types.entry_type; |
| 11541 | 11571 | } |
| 11542 | 11572 | |
| 11543 | static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, | |
| 11544 | IrInstructionSetDebugSafety *set_debug_safety_instruction) | |
| 11545 | { | |
| 11546 | IrInstruction *target_instruction = set_debug_safety_instruction->scope_value->other; | |
| 11547 | TypeTableEntry *target_type = target_instruction->value.type; | |
| 11548 | if (type_is_invalid(target_type)) | |
| 11573 | static TypeTableEntry *ir_analyze_instruction_set_cold(IrAnalyze *ira, IrInstructionSetCold *instruction) { | |
| 11574 | if (ira->new_irb.exec->is_inline) { | |
| 11575 | // ignore setCold when running functions at compile time | |
| 11576 | ir_build_const_from(ira, &instruction->base); | |
| 11577 | return ira->codegen->builtin_types.entry_void; | |
| 11578 | } | |
| 11579 | ||
| 11580 | IrInstruction *is_cold_value = instruction->is_cold->other; | |
| 11581 | bool want_cold; | |
| 11582 | if (!ir_resolve_bool(ira, is_cold_value, &want_cold)) | |
| 11549 | 11583 | return ira->codegen->builtin_types.entry_invalid; |
| 11550 | ConstExprValue *target_val = ir_resolve_const(ira, target_instruction, UndefBad); | |
| 11551 | if (!target_val) | |
| 11584 | ||
| 11585 | FnTableEntry *fn_entry = scope_fn_entry(instruction->base.scope); | |
| 11586 | if (fn_entry == nullptr) { | |
| 11587 | ir_add_error(ira, &instruction->base, buf_sprintf("@setCold outside function")); | |
| 11552 | 11588 | return ira->codegen->builtin_types.entry_invalid; |
| 11589 | } | |
| 11553 | 11590 | |
| 11591 | if (fn_entry->set_cold_node != nullptr) { | |
| 11592 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cold set twice in same function")); | |
| 11593 | add_error_note(ira->codegen, msg, fn_entry->set_cold_node, buf_sprintf("first set here")); | |
| 11594 | return ira->codegen->builtin_types.entry_invalid; | |
| 11595 | } | |
| 11596 | ||
| 11597 | fn_entry->set_cold_node = instruction->base.source_node; | |
| 11598 | fn_entry->is_cold = want_cold; | |
| 11599 | ||
| 11600 | ir_build_const_from(ira, &instruction->base); | |
| 11601 | return ira->codegen->builtin_types.entry_void; | |
| 11602 | } | |
| 11603 | static TypeTableEntry *ir_analyze_instruction_set_runtime_safety(IrAnalyze *ira, | |
| 11604 | IrInstructionSetRuntimeSafety *set_runtime_safety_instruction) | |
| 11605 | { | |
| 11554 | 11606 | if (ira->new_irb.exec->is_inline) { |
| 11555 | // ignore setDebugSafety when running functions at compile time | |
| 11556 | ir_build_const_from(ira, &set_debug_safety_instruction->base); | |
| 11607 | // ignore setRuntimeSafety when running functions at compile time | |
| 11608 | ir_build_const_from(ira, &set_runtime_safety_instruction->base); | |
| 11557 | 11609 | return ira->codegen->builtin_types.entry_void; |
| 11558 | 11610 | } |
| 11559 | 11611 | |
| 11560 | 11612 | bool *safety_off_ptr; |
| 11561 | 11613 | AstNode **safety_set_node_ptr; |
| 11562 | if (target_type->id == TypeTableEntryIdBlock) { | |
| 11563 | ScopeBlock *block_scope = (ScopeBlock *)target_val->data.x_block; | |
| 11564 | safety_off_ptr = &block_scope->safety_off; | |
| 11565 | safety_set_node_ptr = &block_scope->safety_set_node; | |
| 11566 | } else if (target_type->id == TypeTableEntryIdFn) { | |
| 11567 | FnTableEntry *target_fn = target_val->data.x_fn.fn_entry; | |
| 11568 | assert(target_fn->def_scope); | |
| 11569 | safety_off_ptr = &target_fn->def_scope->safety_off; | |
| 11570 | safety_set_node_ptr = &target_fn->def_scope->safety_set_node; | |
| 11571 | } else if (target_type->id == TypeTableEntryIdMetaType) { | |
| 11572 | ScopeDecls *decls_scope; | |
| 11573 | TypeTableEntry *type_arg = target_val->data.x_type; | |
| 11574 | if (type_arg->id == TypeTableEntryIdStruct) { | |
| 11575 | decls_scope = type_arg->data.structure.decls_scope; | |
| 11576 | } else if (type_arg->id == TypeTableEntryIdEnum) { | |
| 11577 | decls_scope = type_arg->data.enumeration.decls_scope; | |
| 11578 | } else if (type_arg->id == TypeTableEntryIdUnion) { | |
| 11579 | decls_scope = type_arg->data.unionation.decls_scope; | |
| 11614 | ||
| 11615 | Scope *scope = set_runtime_safety_instruction->base.scope; | |
| 11616 | while (scope != nullptr) { | |
| 11617 | if (scope->id == ScopeIdBlock) { | |
| 11618 | ScopeBlock *block_scope = (ScopeBlock *)scope; | |
| 11619 | safety_off_ptr = &block_scope->safety_off; | |
| 11620 | safety_set_node_ptr = &block_scope->safety_set_node; | |
| 11621 | break; | |
| 11622 | } else if (scope->id == ScopeIdFnDef) { | |
| 11623 | ScopeFnDef *def_scope = (ScopeFnDef *)scope; | |
| 11624 | FnTableEntry *target_fn = def_scope->fn_entry; | |
| 11625 | assert(target_fn->def_scope != nullptr); | |
| 11626 | safety_off_ptr = &target_fn->def_scope->safety_off; | |
| 11627 | safety_set_node_ptr = &target_fn->def_scope->safety_set_node; | |
| 11628 | break; | |
| 11629 | } else if (scope->id == ScopeIdDecls) { | |
| 11630 | ScopeDecls *decls_scope = (ScopeDecls *)scope; | |
| 11631 | safety_off_ptr = &decls_scope->safety_off; | |
| 11632 | safety_set_node_ptr = &decls_scope->safety_set_node; | |
| 11633 | break; | |
| 11580 | 11634 | } else { |
| 11581 | ir_add_error_node(ira, target_instruction->source_node, | |
| 11582 | buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&type_arg->name))); | |
| 11583 | return ira->codegen->builtin_types.entry_invalid; | |
| 11635 | scope = scope->parent; | |
| 11636 | continue; | |
| 11584 | 11637 | } |
| 11585 | safety_off_ptr = &decls_scope->safety_off; | |
| 11586 | safety_set_node_ptr = &decls_scope->safety_set_node; | |
| 11587 | } else { | |
| 11588 | ir_add_error_node(ira, target_instruction->source_node, | |
| 11589 | buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&target_type->name))); | |
| 11590 | return ira->codegen->builtin_types.entry_invalid; | |
| 11591 | 11638 | } |
| 11639 | assert(scope != nullptr); | |
| 11592 | 11640 | |
| 11593 | IrInstruction *debug_safety_on_value = set_debug_safety_instruction->debug_safety_on->other; | |
| 11594 | bool want_debug_safety; | |
| 11595 | if (!ir_resolve_bool(ira, debug_safety_on_value, &want_debug_safety)) | |
| 11641 | IrInstruction *safety_on_value = set_runtime_safety_instruction->safety_on->other; | |
| 11642 | bool want_runtime_safety; | |
| 11643 | if (!ir_resolve_bool(ira, safety_on_value, &want_runtime_safety)) | |
| 11596 | 11644 | return ira->codegen->builtin_types.entry_invalid; |
| 11597 | 11645 | |
| 11598 | AstNode *source_node = set_debug_safety_instruction->base.source_node; | |
| 11646 | AstNode *source_node = set_runtime_safety_instruction->base.source_node; | |
| 11599 | 11647 | if (*safety_set_node_ptr) { |
| 11600 | 11648 | ErrorMsg *msg = ir_add_error_node(ira, source_node, |
| 11601 | buf_sprintf("debug safety set twice for same scope")); | |
| 11649 | buf_sprintf("runtime safety set twice for same scope")); | |
| 11602 | 11650 | add_error_note(ira->codegen, msg, *safety_set_node_ptr, buf_sprintf("first set here")); |
| 11603 | 11651 | return ira->codegen->builtin_types.entry_invalid; |
| 11604 | 11652 | } |
| 11605 | 11653 | *safety_set_node_ptr = source_node; |
| 11606 | *safety_off_ptr = !want_debug_safety; | |
| 11654 | *safety_off_ptr = !want_runtime_safety; | |
| 11607 | 11655 | |
| 11608 | ir_build_const_from(ira, &set_debug_safety_instruction->base); | |
| 11656 | ir_build_const_from(ira, &set_runtime_safety_instruction->base); | |
| 11609 | 11657 | return ira->codegen->builtin_types.entry_void; |
| 11610 | 11658 | } |
| 11611 | 11659 | |
| ... | ... | @@ -12243,11 +12291,18 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 12243 | 12291 | } |
| 12244 | 12292 | TypeTableEntry *tag_type = target_type->data.unionation.tag_type; |
| 12245 | 12293 | assert(tag_type != nullptr); |
| 12294 | assert(tag_type->id == TypeTableEntryIdEnum); | |
| 12246 | 12295 | if (pointee_val) { |
| 12247 | 12296 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); |
| 12248 | 12297 | bigint_init_bigint(&out_val->data.x_enum_tag, &pointee_val->data.x_union.tag); |
| 12249 | 12298 | return tag_type; |
| 12250 | 12299 | } |
| 12300 | if (tag_type->data.enumeration.src_field_count == 1) { | |
| 12301 | ConstExprValue *out_val = ir_build_const_from(ira, &switch_target_instruction->base); | |
| 12302 | TypeEnumField *only_field = &tag_type->data.enumeration.fields[0]; | |
| 12303 | bigint_init_bigint(&out_val->data.x_enum_tag, &only_field->value); | |
| 12304 | return tag_type; | |
| 12305 | } | |
| 12251 | 12306 | |
| 12252 | 12307 | IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, |
| 12253 | 12308 | switch_target_instruction->base.source_node, target_value_ptr); |
| ... | ... | @@ -14499,6 +14554,11 @@ static TypeTableEntry *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructio |
| 14499 | 14554 | if (type_is_invalid(msg->value.type)) |
| 14500 | 14555 | return ira->codegen->builtin_types.entry_invalid; |
| 14501 | 14556 | |
| 14557 | if (ir_should_inline(ira->new_irb.exec, instruction->base.scope)) { | |
| 14558 | ir_add_error(ira, &instruction->base, buf_sprintf("encountered @panic at compile-time")); | |
| 14559 | return ira->codegen->builtin_types.entry_invalid; | |
| 14560 | } | |
| 14561 | ||
| 14502 | 14562 | TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); |
| 14503 | 14563 | TypeTableEntry *str_type = get_slice_type(ira->codegen, u8_ptr_type); |
| 14504 | 14564 | IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type); |
| ... | ... | @@ -15212,8 +15272,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 15212 | 15272 | return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); |
| 15213 | 15273 | case IrInstructionIdPtrTypeChild: |
| 15214 | 15274 | return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); |
| 15215 | case IrInstructionIdSetDebugSafety: | |
| 15216 | return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction); | |
| 15275 | case IrInstructionIdSetCold: | |
| 15276 | return ir_analyze_instruction_set_cold(ira, (IrInstructionSetCold *)instruction); | |
| 15277 | case IrInstructionIdSetRuntimeSafety: | |
| 15278 | return ir_analyze_instruction_set_runtime_safety(ira, (IrInstructionSetRuntimeSafety *)instruction); | |
| 15217 | 15279 | case IrInstructionIdSetFloatMode: |
| 15218 | 15280 | return ir_analyze_instruction_set_float_mode(ira, (IrInstructionSetFloatMode *)instruction); |
| 15219 | 15281 | case IrInstructionIdSliceType: |
| ... | ... | @@ -15448,7 +15510,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15448 | 15510 | case IrInstructionIdCall: |
| 15449 | 15511 | case IrInstructionIdReturn: |
| 15450 | 15512 | case IrInstructionIdUnreachable: |
| 15451 | case IrInstructionIdSetDebugSafety: | |
| 15513 | case IrInstructionIdSetCold: | |
| 15514 | case IrInstructionIdSetRuntimeSafety: | |
| 15452 | 15515 | case IrInstructionIdSetFloatMode: |
| 15453 | 15516 | case IrInstructionIdImport: |
| 15454 | 15517 | case IrInstructionIdCompileErr: |
src/ir_print.cpp+14-7| ... | ... | @@ -368,11 +368,15 @@ static void ir_print_union_field_ptr(IrPrint *irp, IrInstructionUnionFieldPtr *i |
| 368 | 368 | fprintf(irp->f, ")"); |
| 369 | 369 | } |
| 370 | 370 | |
| 371 | static void ir_print_set_debug_safety(IrPrint *irp, IrInstructionSetDebugSafety *instruction) { | |
| 372 | fprintf(irp->f, "@setDebugSafety("); | |
| 373 | ir_print_other_instruction(irp, instruction->scope_value); | |
| 374 | fprintf(irp->f, ", "); | |
| 375 | ir_print_other_instruction(irp, instruction->debug_safety_on); | |
| 371 | static void ir_print_set_cold(IrPrint *irp, IrInstructionSetCold *instruction) { | |
| 372 | fprintf(irp->f, "@setCold("); | |
| 373 | ir_print_other_instruction(irp, instruction->is_cold); | |
| 374 | fprintf(irp->f, ")"); | |
| 375 | } | |
| 376 | ||
| 377 | static void ir_print_set_runtime_safety(IrPrint *irp, IrInstructionSetRuntimeSafety *instruction) { | |
| 378 | fprintf(irp->f, "@setRuntimeSafety("); | |
| 379 | ir_print_other_instruction(irp, instruction->safety_on); | |
| 376 | 380 | fprintf(irp->f, ")"); |
| 377 | 381 | } |
| 378 | 382 | |
| ... | ... | @@ -1081,8 +1085,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1081 | 1085 | case IrInstructionIdUnionFieldPtr: |
| 1082 | 1086 | ir_print_union_field_ptr(irp, (IrInstructionUnionFieldPtr *)instruction); |
| 1083 | 1087 | break; |
| 1084 | case IrInstructionIdSetDebugSafety: | |
| 1085 | ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction); | |
| 1088 | case IrInstructionIdSetCold: | |
| 1089 | ir_print_set_cold(irp, (IrInstructionSetCold *)instruction); | |
| 1090 | break; | |
| 1091 | case IrInstructionIdSetRuntimeSafety: | |
| 1092 | ir_print_set_runtime_safety(irp, (IrInstructionSetRuntimeSafety *)instruction); | |
| 1086 | 1093 | break; |
| 1087 | 1094 | case IrInstructionIdSetFloatMode: |
| 1088 | 1095 | ir_print_set_float_mode(irp, (IrInstructionSetFloatMode *)instruction); |
src/main.cpp+1-1| ... | ... | @@ -462,7 +462,7 @@ int main(int argc, char **argv) { |
| 462 | 462 | Termination term; |
| 463 | 463 | os_spawn_process(buf_ptr(path_to_build_exe), args, &term); |
| 464 | 464 | if (term.how != TerminationIdClean || term.code != 0) { |
| 465 | fprintf(stderr, "\nBuild failed. Use the following command to reproduce the failure:\n"); | |
| 465 | fprintf(stderr, "\nBuild failed. The following command failed:\n"); | |
| 466 | 466 | fprintf(stderr, "%s", buf_ptr(path_to_build_exe)); |
| 467 | 467 | for (size_t i = 0; i < args.length; i += 1) { |
| 468 | 468 | fprintf(stderr, " %s", args.at(i)); |
src/os.cpp+18-11| ... | ... | @@ -390,17 +390,15 @@ static int os_exec_process_posix(const char *exe, ZigList<const char *> &args, |
| 390 | 390 | |
| 391 | 391 | #if defined(ZIG_OS_WINDOWS) |
| 392 | 392 | |
| 393 | /* | |
| 394 | static void win32_panic(const char *str) { | |
| 395 | DWORD err = GetLastError(); | |
| 396 | LPSTR messageBuffer = nullptr; | |
| 397 | FormatMessageA( | |
| 398 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, | |
| 399 | NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); | |
| 400 | zig_panic(str, messageBuffer); | |
| 401 | LocalFree(messageBuffer); | |
| 402 | } | |
| 403 | */ | |
| 393 | //static void win32_panic(const char *str) { | |
| 394 | // DWORD err = GetLastError(); | |
| 395 | // LPSTR messageBuffer = nullptr; | |
| 396 | // FormatMessageA( | |
| 397 | // FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, | |
| 398 | // NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); | |
| 399 | // zig_panic(str, messageBuffer); | |
| 400 | // LocalFree(messageBuffer); | |
| 401 | //} | |
| 404 | 402 | |
| 405 | 403 | static int os_exec_process_windows(const char *exe, ZigList<const char *> &args, |
| 406 | 404 | Termination *term, Buf *out_stderr, Buf *out_stdout) |
| ... | ... | @@ -794,9 +792,18 @@ int os_delete_file(Buf *path) { |
| 794 | 792 | } |
| 795 | 793 | |
| 796 | 794 | int os_rename(Buf *src_path, Buf *dest_path) { |
| 795 | if (buf_eql_buf(src_path, dest_path)) { | |
| 796 | return 0; | |
| 797 | } | |
| 798 | #if defined(ZIG_OS_WINDOWS) | |
| 799 | if (!MoveFileExA(buf_ptr(src_path), buf_ptr(dest_path), MOVEFILE_REPLACE_EXISTING)) { | |
| 800 | return ErrorFileSystem; | |
| 801 | } | |
| 802 | #else | |
| 797 | 803 | if (rename(buf_ptr(src_path), buf_ptr(dest_path)) == -1) { |
| 798 | 804 | return ErrorFileSystem; |
| 799 | 805 | } |
| 806 | #endif | |
| 800 | 807 | return 0; |
| 801 | 808 | } |
| 802 | 809 |
src/parser.cpp+8-27| ... | ... | @@ -84,11 +84,6 @@ static AstNode *ast_create_node(ParseContext *pc, NodeType type, Token *first_to |
| 84 | 84 | return node; |
| 85 | 85 | } |
| 86 | 86 | |
| 87 | static AstNode *ast_create_void_type_node(ParseContext *pc, Token *token) { | |
| 88 | AstNode *node = ast_create_node(pc, NodeTypeSymbol, token); | |
| 89 | node->data.symbol_expr.symbol = pc->void_buf; | |
| 90 | return node; | |
| 91 | } | |
| 92 | 87 | |
| 93 | 88 | static void parse_asm_template(ParseContext *pc, AstNode *node) { |
| 94 | 89 | Buf *asm_template = node->data.asm_expr.asm_template; |
| ... | ... | @@ -1495,7 +1490,7 @@ static AstNode *ast_parse_break_expr(ParseContext *pc, size_t *token_index) { |
| 1495 | 1490 | } |
| 1496 | 1491 | |
| 1497 | 1492 | /* |
| 1498 | Defer(body) = option("%") "defer" body | |
| 1493 | Defer(body) = ("defer" | "errdefer") body | |
| 1499 | 1494 | */ |
| 1500 | 1495 | static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { |
| 1501 | 1496 | Token *token = &pc->tokens->at(*token_index); |
| ... | ... | @@ -1503,15 +1498,10 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { |
| 1503 | 1498 | NodeType node_type; |
| 1504 | 1499 | ReturnKind kind; |
| 1505 | 1500 | |
| 1506 | if (token->id == TokenIdPercent) { | |
| 1507 | Token *next_token = &pc->tokens->at(*token_index + 1); | |
| 1508 | if (next_token->id == TokenIdKeywordDefer) { | |
| 1509 | kind = ReturnKindError; | |
| 1510 | node_type = NodeTypeDefer; | |
| 1511 | *token_index += 2; | |
| 1512 | } else { | |
| 1513 | return nullptr; | |
| 1514 | } | |
| 1501 | if (token->id == TokenIdKeywordErrdefer) { | |
| 1502 | kind = ReturnKindError; | |
| 1503 | node_type = NodeTypeDefer; | |
| 1504 | *token_index += 1; | |
| 1515 | 1505 | } else if (token->id == TokenIdKeywordDefer) { |
| 1516 | 1506 | kind = ReturnKindUnconditional; |
| 1517 | 1507 | node_type = NodeTypeDefer; |
| ... | ... | @@ -2250,7 +2240,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2250 | 2240 | } |
| 2251 | 2241 | |
| 2252 | 2242 | /* |
| 2253 | FnProto = option("coldcc" | "nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("-&gt;" TypeExpr) | |
| 2243 | FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") TypeExpr | |
| 2254 | 2244 | */ |
| 2255 | 2245 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { |
| 2256 | 2246 | Token *first_token = &pc->tokens->at(*token_index); |
| ... | ... | @@ -2258,11 +2248,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2258 | 2248 | |
| 2259 | 2249 | CallingConvention cc; |
| 2260 | 2250 | bool is_extern = false; |
| 2261 | if (first_token->id == TokenIdKeywordColdCC) { | |
| 2262 | *token_index += 1; | |
| 2263 | fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); | |
| 2264 | cc = CallingConventionCold; | |
| 2265 | } else if (first_token->id == TokenIdKeywordNakedCC) { | |
| 2251 | if (first_token->id == TokenIdKeywordNakedCC) { | |
| 2266 | 2252 | *token_index += 1; |
| 2267 | 2253 | fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); |
| 2268 | 2254 | cc = CallingConventionNaked; |
| ... | ... | @@ -2329,12 +2315,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2329 | 2315 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 2330 | 2316 | next_token = &pc->tokens->at(*token_index); |
| 2331 | 2317 | } |
| 2332 | if (next_token->id == TokenIdArrow) { | |
| 2333 | *token_index += 1; | |
| 2334 | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, false); | |
| 2335 | } else { | |
| 2336 | node->data.fn_proto.return_type = ast_create_void_type_node(pc, next_token); | |
| 2337 | } | |
| 2318 | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, true); | |
| 2338 | 2319 | |
| 2339 | 2320 | return node; |
| 2340 | 2321 | } |
src/tokenizer.cpp+2-2| ... | ... | @@ -112,13 +112,13 @@ static const struct ZigKeyword zig_keywords[] = { |
| 112 | 112 | {"asm", TokenIdKeywordAsm}, |
| 113 | 113 | {"break", TokenIdKeywordBreak}, |
| 114 | 114 | {"catch", TokenIdKeywordCatch}, |
| 115 | {"coldcc", TokenIdKeywordColdCC}, | |
| 116 | 115 | {"comptime", TokenIdKeywordCompTime}, |
| 117 | 116 | {"const", TokenIdKeywordConst}, |
| 118 | 117 | {"continue", TokenIdKeywordContinue}, |
| 119 | 118 | {"defer", TokenIdKeywordDefer}, |
| 120 | 119 | {"else", TokenIdKeywordElse}, |
| 121 | 120 | {"enum", TokenIdKeywordEnum}, |
| 121 | {"errdefer", TokenIdKeywordErrdefer}, | |
| 122 | 122 | {"error", TokenIdKeywordError}, |
| 123 | 123 | {"export", TokenIdKeywordExport}, |
| 124 | 124 | {"extern", TokenIdKeywordExtern}, |
| ... | ... | @@ -1509,13 +1509,13 @@ const char * token_name(TokenId id) { |
| 1509 | 1509 | case TokenIdKeywordAsm: return "asm"; |
| 1510 | 1510 | case TokenIdKeywordBreak: return "break"; |
| 1511 | 1511 | case TokenIdKeywordCatch: return "catch"; |
| 1512 | case TokenIdKeywordColdCC: return "coldcc"; | |
| 1513 | 1512 | case TokenIdKeywordCompTime: return "comptime"; |
| 1514 | 1513 | case TokenIdKeywordConst: return "const"; |
| 1515 | 1514 | case TokenIdKeywordContinue: return "continue"; |
| 1516 | 1515 | case TokenIdKeywordDefer: return "defer"; |
| 1517 | 1516 | case TokenIdKeywordElse: return "else"; |
| 1518 | 1517 | case TokenIdKeywordEnum: return "enum"; |
| 1518 | case TokenIdKeywordErrdefer: return "errdefer"; | |
| 1519 | 1519 | case TokenIdKeywordError: return "error"; |
| 1520 | 1520 | case TokenIdKeywordExport: return "export"; |
| 1521 | 1521 | case TokenIdKeywordExtern: return "extern"; |
src/tokenizer.hpp+1-1| ... | ... | @@ -51,13 +51,13 @@ enum TokenId { |
| 51 | 51 | TokenIdKeywordAsm, |
| 52 | 52 | TokenIdKeywordBreak, |
| 53 | 53 | TokenIdKeywordCatch, |
| 54 | TokenIdKeywordColdCC, | |
| 55 | 54 | TokenIdKeywordCompTime, |
| 56 | 55 | TokenIdKeywordConst, |
| 57 | 56 | TokenIdKeywordContinue, |
| 58 | 57 | TokenIdKeywordDefer, |
| 59 | 58 | TokenIdKeywordElse, |
| 60 | 59 | TokenIdKeywordEnum, |
| 60 | TokenIdKeywordErrdefer, | |
| 61 | 61 | TokenIdKeywordError, |
| 62 | 62 | TokenIdKeywordExport, |
| 63 | 63 | TokenIdKeywordExtern, |
src/translate_c.cpp+1-1| ... | ... | @@ -922,7 +922,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou |
| 922 | 922 | // void foo(void) -> Foo; |
| 923 | 923 | // we want to keep the return type AST node. |
| 924 | 924 | if (is_c_void_type(proto_node->data.fn_proto.return_type)) { |
| 925 | proto_node->data.fn_proto.return_type = nullptr; | |
| 925 | proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "void"); | |
| 926 | 926 | } |
| 927 | 927 | } |
| 928 | 928 |
std/array_list.zig+16-16| ... | ... | @@ -4,11 +4,11 @@ const assert = debug.assert; |
| 4 | 4 | const mem = std.mem; |
| 5 | 5 | const Allocator = mem.Allocator; |
| 6 | 6 | |
| 7 | pub fn ArrayList(comptime T: type) -> type { | |
| 7 | pub fn ArrayList(comptime T: type) type { | |
| 8 | 8 | return AlignedArrayList(T, @alignOf(T)); |
| 9 | 9 | } |
| 10 | 10 | |
| 11 | pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{ | |
| 11 | pub fn AlignedArrayList(comptime T: type, comptime A: u29) type{ | |
| 12 | 12 | return struct { |
| 13 | 13 | const Self = this; |
| 14 | 14 | |
| ... | ... | @@ -20,7 +20,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{ |
| 20 | 20 | allocator: &Allocator, |
| 21 | 21 | |
| 22 | 22 | /// Deinitialize with `deinit` or use `toOwnedSlice`. |
| 23 | pub fn init(allocator: &Allocator) -> Self { | |
| 23 | pub fn init(allocator: &Allocator) Self { | |
| 24 | 24 | return Self { |
| 25 | 25 | .items = []align(A) T{}, |
| 26 | 26 | .len = 0, |
| ... | ... | @@ -28,22 +28,22 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{ |
| 28 | 28 | }; |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | pub fn deinit(l: &Self) { | |
| 31 | pub fn deinit(l: &Self) void { | |
| 32 | 32 | l.allocator.free(l.items); |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | pub fn toSlice(l: &Self) -> []align(A) T { | |
| 35 | pub fn toSlice(l: &Self) []align(A) T { | |
| 36 | 36 | return l.items[0..l.len]; |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | pub fn toSliceConst(l: &const Self) -> []align(A) const T { | |
| 39 | pub fn toSliceConst(l: &const Self) []align(A) const T { | |
| 40 | 40 | return l.items[0..l.len]; |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | 43 | /// ArrayList takes ownership of the passed in slice. The slice must have been |
| 44 | 44 | /// allocated with `allocator`. |
| 45 | 45 | /// Deinitialize with `deinit` or use `toOwnedSlice`. |
| 46 | pub fn fromOwnedSlice(allocator: &Allocator, slice: []align(A) T) -> Self { | |
| 46 | pub fn fromOwnedSlice(allocator: &Allocator, slice: []align(A) T) Self { | |
| 47 | 47 | return Self { |
| 48 | 48 | .items = slice, |
| 49 | 49 | .len = slice.len, |
| ... | ... | @@ -52,35 +52,35 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{ |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | /// The caller owns the returned memory. ArrayList becomes empty. |
| 55 | pub fn toOwnedSlice(self: &Self) -> []align(A) T { | |
| 55 | pub fn toOwnedSlice(self: &Self) []align(A) T { | |
| 56 | 56 | const allocator = self.allocator; |
| 57 | 57 | const result = allocator.alignedShrink(T, A, self.items, self.len); |
| 58 | 58 | *self = init(allocator); |
| 59 | 59 | return result; |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | pub fn append(l: &Self, item: &const T) -> %void { | |
| 62 | pub fn append(l: &Self, item: &const T) %void { | |
| 63 | 63 | const new_item_ptr = try l.addOne(); |
| 64 | 64 | *new_item_ptr = *item; |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | pub fn appendSlice(l: &Self, items: []align(A) const T) -> %void { | |
| 67 | pub fn appendSlice(l: &Self, items: []align(A) const T) %void { | |
| 68 | 68 | try l.ensureCapacity(l.len + items.len); |
| 69 | 69 | mem.copy(T, l.items[l.len..], items); |
| 70 | 70 | l.len += items.len; |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | pub fn resize(l: &Self, new_len: usize) -> %void { | |
| 73 | pub fn resize(l: &Self, new_len: usize) %void { | |
| 74 | 74 | try l.ensureCapacity(new_len); |
| 75 | 75 | l.len = new_len; |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | pub fn shrink(l: &Self, new_len: usize) { | |
| 78 | pub fn shrink(l: &Self, new_len: usize) void { | |
| 79 | 79 | assert(new_len <= l.len); |
| 80 | 80 | l.len = new_len; |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | pub fn ensureCapacity(l: &Self, new_capacity: usize) -> %void { | |
| 83 | pub fn ensureCapacity(l: &Self, new_capacity: usize) %void { | |
| 84 | 84 | var better_capacity = l.items.len; |
| 85 | 85 | if (better_capacity >= new_capacity) return; |
| 86 | 86 | while (true) { |
| ... | ... | @@ -90,7 +90,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{ |
| 90 | 90 | l.items = try l.allocator.alignedRealloc(T, A, l.items, better_capacity); |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | pub fn addOne(l: &Self) -> %&T { | |
| 93 | pub fn addOne(l: &Self) %&T { | |
| 94 | 94 | const new_length = l.len + 1; |
| 95 | 95 | try l.ensureCapacity(new_length); |
| 96 | 96 | const result = &l.items[l.len]; |
| ... | ... | @@ -98,12 +98,12 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) -> type{ |
| 98 | 98 | return result; |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | pub fn pop(self: &Self) -> T { | |
| 101 | pub fn pop(self: &Self) T { | |
| 102 | 102 | self.len -= 1; |
| 103 | 103 | return self.items[self.len]; |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | pub fn popOrNull(self: &Self) -> ?T { | |
| 106 | pub fn popOrNull(self: &Self) ?T { | |
| 107 | 107 | if (self.len == 0) |
| 108 | 108 | return null; |
| 109 | 109 | return self.pop(); |
std/base64.zig+18-18| ... | ... | @@ -11,7 +11,7 @@ pub const Base64Encoder = struct { |
| 11 | 11 | pad_char: u8, |
| 12 | 12 | |
| 13 | 13 | /// a bunch of assertions, then simply pass the data right through. |
| 14 | pub fn init(alphabet_chars: []const u8, pad_char: u8) -> Base64Encoder { | |
| 14 | pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64Encoder { | |
| 15 | 15 | assert(alphabet_chars.len == 64); |
| 16 | 16 | var char_in_alphabet = []bool{false} ** 256; |
| 17 | 17 | for (alphabet_chars) |c| { |
| ... | ... | @@ -27,12 +27,12 @@ pub const Base64Encoder = struct { |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | /// ceil(source_len * 4/3) |
| 30 | pub fn calcSize(source_len: usize) -> usize { | |
| 30 | pub fn calcSize(source_len: usize) usize { | |
| 31 | 31 | return @divTrunc(source_len + 2, 3) * 4; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | 34 | /// dest.len must be what you get from ::calcSize. |
| 35 | pub fn encode(encoder: &const Base64Encoder, dest: []u8, source: []const u8) { | |
| 35 | pub fn encode(encoder: &const Base64Encoder, dest: []u8, source: []const u8) void { | |
| 36 | 36 | assert(dest.len == Base64Encoder.calcSize(source.len)); |
| 37 | 37 | |
| 38 | 38 | var i: usize = 0; |
| ... | ... | @@ -90,7 +90,7 @@ pub const Base64Decoder = struct { |
| 90 | 90 | char_in_alphabet: [256]bool, |
| 91 | 91 | pad_char: u8, |
| 92 | 92 | |
| 93 | pub fn init(alphabet_chars: []const u8, pad_char: u8) -> Base64Decoder { | |
| 93 | pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64Decoder { | |
| 94 | 94 | assert(alphabet_chars.len == 64); |
| 95 | 95 | |
| 96 | 96 | var result = Base64Decoder{ |
| ... | ... | @@ -111,7 +111,7 @@ pub const Base64Decoder = struct { |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | 113 | /// If the encoded buffer is detected to be invalid, returns error.InvalidPadding. |
| 114 | pub fn calcSize(decoder: &const Base64Decoder, source: []const u8) -> %usize { | |
| 114 | pub fn calcSize(decoder: &const Base64Decoder, source: []const u8) %usize { | |
| 115 | 115 | if (source.len % 4 != 0) return error.InvalidPadding; |
| 116 | 116 | return calcDecodedSizeExactUnsafe(source, decoder.pad_char); |
| 117 | 117 | } |
| ... | ... | @@ -119,7 +119,7 @@ pub const Base64Decoder = struct { |
| 119 | 119 | /// dest.len must be what you get from ::calcSize. |
| 120 | 120 | /// invalid characters result in error.InvalidCharacter. |
| 121 | 121 | /// invalid padding results in error.InvalidPadding. |
| 122 | pub fn decode(decoder: &const Base64Decoder, dest: []u8, source: []const u8) -> %void { | |
| 122 | pub fn decode(decoder: &const Base64Decoder, dest: []u8, source: []const u8) %void { | |
| 123 | 123 | assert(dest.len == (decoder.calcSize(source) catch unreachable)); |
| 124 | 124 | assert(source.len % 4 == 0); |
| 125 | 125 | |
| ... | ... | @@ -168,7 +168,7 @@ error OutputTooSmall; |
| 168 | 168 | pub const Base64DecoderWithIgnore = struct { |
| 169 | 169 | decoder: Base64Decoder, |
| 170 | 170 | char_is_ignored: [256]bool, |
| 171 | pub fn init(alphabet_chars: []const u8, pad_char: u8, ignore_chars: []const u8) -> Base64DecoderWithIgnore { | |
| 171 | pub fn init(alphabet_chars: []const u8, pad_char: u8, ignore_chars: []const u8) Base64DecoderWithIgnore { | |
| 172 | 172 | var result = Base64DecoderWithIgnore { |
| 173 | 173 | .decoder = Base64Decoder.init(alphabet_chars, pad_char), |
| 174 | 174 | .char_is_ignored = []bool{false} ** 256, |
| ... | ... | @@ -185,7 +185,7 @@ pub const Base64DecoderWithIgnore = struct { |
| 185 | 185 | } |
| 186 | 186 | |
| 187 | 187 | /// If no characters end up being ignored or padding, this will be the exact decoded size. |
| 188 | pub fn calcSizeUpperBound(encoded_len: usize) -> %usize { | |
| 188 | pub fn calcSizeUpperBound(encoded_len: usize) %usize { | |
| 189 | 189 | return @divTrunc(encoded_len, 4) * 3; |
| 190 | 190 | } |
| 191 | 191 | |
| ... | ... | @@ -193,7 +193,7 @@ pub const Base64DecoderWithIgnore = struct { |
| 193 | 193 | /// Invalid padding results in error.InvalidPadding. |
| 194 | 194 | /// Decoding more data than can fit in dest results in error.OutputTooSmall. See also ::calcSizeUpperBound. |
| 195 | 195 | /// Returns the number of bytes writen to dest. |
| 196 | pub fn decode(decoder_with_ignore: &const Base64DecoderWithIgnore, dest: []u8, source: []const u8) -> %usize { | |
| 196 | pub fn decode(decoder_with_ignore: &const Base64DecoderWithIgnore, dest: []u8, source: []const u8) %usize { | |
| 197 | 197 | const decoder = &decoder_with_ignore.decoder; |
| 198 | 198 | |
| 199 | 199 | var src_cursor: usize = 0; |
| ... | ... | @@ -293,7 +293,7 @@ pub const Base64DecoderUnsafe = struct { |
| 293 | 293 | char_to_index: [256]u8, |
| 294 | 294 | pad_char: u8, |
| 295 | 295 | |
| 296 | pub fn init(alphabet_chars: []const u8, pad_char: u8) -> Base64DecoderUnsafe { | |
| 296 | pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64DecoderUnsafe { | |
| 297 | 297 | assert(alphabet_chars.len == 64); |
| 298 | 298 | var result = Base64DecoderUnsafe { |
| 299 | 299 | .char_to_index = undefined, |
| ... | ... | @@ -307,13 +307,13 @@ pub const Base64DecoderUnsafe = struct { |
| 307 | 307 | } |
| 308 | 308 | |
| 309 | 309 | /// The source buffer must be valid. |
| 310 | pub fn calcSize(decoder: &const Base64DecoderUnsafe, source: []const u8) -> usize { | |
| 310 | pub fn calcSize(decoder: &const Base64DecoderUnsafe, source: []const u8) usize { | |
| 311 | 311 | return calcDecodedSizeExactUnsafe(source, decoder.pad_char); |
| 312 | 312 | } |
| 313 | 313 | |
| 314 | 314 | /// dest.len must be what you get from ::calcDecodedSizeExactUnsafe. |
| 315 | 315 | /// invalid characters or padding will result in undefined values. |
| 316 | pub fn decode(decoder: &const Base64DecoderUnsafe, dest: []u8, source: []const u8) { | |
| 316 | pub fn decode(decoder: &const Base64DecoderUnsafe, dest: []u8, source: []const u8) void { | |
| 317 | 317 | assert(dest.len == decoder.calcSize(source)); |
| 318 | 318 | |
| 319 | 319 | var src_index: usize = 0; |
| ... | ... | @@ -359,7 +359,7 @@ pub const Base64DecoderUnsafe = struct { |
| 359 | 359 | } |
| 360 | 360 | }; |
| 361 | 361 | |
| 362 | fn calcDecodedSizeExactUnsafe(source: []const u8, pad_char: u8) -> usize { | |
| 362 | fn calcDecodedSizeExactUnsafe(source: []const u8, pad_char: u8) usize { | |
| 363 | 363 | if (source.len == 0) return 0; |
| 364 | 364 | var result = @divExact(source.len, 4) * 3; |
| 365 | 365 | if (source[source.len - 1] == pad_char) { |
| ... | ... | @@ -378,7 +378,7 @@ test "base64" { |
| 378 | 378 | comptime (testBase64() catch unreachable); |
| 379 | 379 | } |
| 380 | 380 | |
| 381 | fn testBase64() -> %void { | |
| 381 | fn testBase64() %void { | |
| 382 | 382 | try testAllApis("", ""); |
| 383 | 383 | try testAllApis("f", "Zg=="); |
| 384 | 384 | try testAllApis("fo", "Zm8="); |
| ... | ... | @@ -412,7 +412,7 @@ fn testBase64() -> %void { |
| 412 | 412 | try testOutputTooSmallError("AAAAAA=="); |
| 413 | 413 | } |
| 414 | 414 | |
| 415 | fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) -> %void { | |
| 415 | fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) %void { | |
| 416 | 416 | // Base64Encoder |
| 417 | 417 | { |
| 418 | 418 | var buffer: [0x100]u8 = undefined; |
| ... | ... | @@ -449,7 +449,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) -> %v |
| 449 | 449 | } |
| 450 | 450 | } |
| 451 | 451 | |
| 452 | fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) -> %void { | |
| 452 | fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) %void { | |
| 453 | 453 | const standard_decoder_ignore_space = Base64DecoderWithIgnore.init( |
| 454 | 454 | standard_alphabet_chars, standard_pad_char, " "); |
| 455 | 455 | var buffer: [0x100]u8 = undefined; |
| ... | ... | @@ -459,7 +459,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) -> % |
| 459 | 459 | } |
| 460 | 460 | |
| 461 | 461 | error ExpectedError; |
| 462 | fn testError(encoded: []const u8, expected_err: error) -> %void { | |
| 462 | fn testError(encoded: []const u8, expected_err: error) %void { | |
| 463 | 463 | const standard_decoder_ignore_space = Base64DecoderWithIgnore.init( |
| 464 | 464 | standard_alphabet_chars, standard_pad_char, " "); |
| 465 | 465 | var buffer: [0x100]u8 = undefined; |
| ... | ... | @@ -475,7 +475,7 @@ fn testError(encoded: []const u8, expected_err: error) -> %void { |
| 475 | 475 | } else |err| if (err != expected_err) return err; |
| 476 | 476 | } |
| 477 | 477 | |
| 478 | fn testOutputTooSmallError(encoded: []const u8) -> %void { | |
| 478 | fn testOutputTooSmallError(encoded: []const u8) %void { | |
| 479 | 479 | const standard_decoder_ignore_space = Base64DecoderWithIgnore.init( |
| 480 | 480 | standard_alphabet_chars, standard_pad_char, " "); |
| 481 | 481 | var buffer: [0x100]u8 = undefined; |
std/buf_map.zig+12-12| ... | ... | @@ -9,14 +9,14 @@ pub const BufMap = struct { |
| 9 | 9 | |
| 10 | 10 | const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8); |
| 11 | 11 | |
| 12 | pub fn init(allocator: &Allocator) -> BufMap { | |
| 12 | pub fn init(allocator: &Allocator) BufMap { | |
| 13 | 13 | var self = BufMap { |
| 14 | 14 | .hash_map = BufMapHashMap.init(allocator), |
| 15 | 15 | }; |
| 16 | 16 | return self; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | pub fn deinit(self: &BufMap) { | |
| 19 | pub fn deinit(self: &BufMap) void { | |
| 20 | 20 | var it = self.hash_map.iterator(); |
| 21 | 21 | while (true) { |
| 22 | 22 | const entry = it.next() ?? break; |
| ... | ... | @@ -27,47 +27,47 @@ pub const BufMap = struct { |
| 27 | 27 | self.hash_map.deinit(); |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | pub fn set(self: &BufMap, key: []const u8, value: []const u8) -> %void { | |
| 30 | pub fn set(self: &BufMap, key: []const u8, value: []const u8) %void { | |
| 31 | 31 | if (self.hash_map.get(key)) |entry| { |
| 32 | 32 | const value_copy = try self.copy(value); |
| 33 | %defer self.free(value_copy); | |
| 33 | errdefer self.free(value_copy); | |
| 34 | 34 | _ = try self.hash_map.put(key, value_copy); |
| 35 | 35 | self.free(entry.value); |
| 36 | 36 | } else { |
| 37 | 37 | const key_copy = try self.copy(key); |
| 38 | %defer self.free(key_copy); | |
| 38 | errdefer self.free(key_copy); | |
| 39 | 39 | const value_copy = try self.copy(value); |
| 40 | %defer self.free(value_copy); | |
| 40 | errdefer self.free(value_copy); | |
| 41 | 41 | _ = try self.hash_map.put(key_copy, value_copy); |
| 42 | 42 | } |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | pub fn get(self: &BufMap, key: []const u8) -> ?[]const u8 { | |
| 45 | pub fn get(self: &BufMap, key: []const u8) ?[]const u8 { | |
| 46 | 46 | const entry = self.hash_map.get(key) ?? return null; |
| 47 | 47 | return entry.value; |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | pub fn delete(self: &BufMap, key: []const u8) { | |
| 50 | pub fn delete(self: &BufMap, key: []const u8) void { | |
| 51 | 51 | const entry = self.hash_map.remove(key) ?? return; |
| 52 | 52 | self.free(entry.key); |
| 53 | 53 | self.free(entry.value); |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | pub fn count(self: &const BufMap) -> usize { | |
| 56 | pub fn count(self: &const BufMap) usize { | |
| 57 | 57 | return self.hash_map.size; |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | pub fn iterator(self: &const BufMap) -> BufMapHashMap.Iterator { | |
| 60 | pub fn iterator(self: &const BufMap) BufMapHashMap.Iterator { | |
| 61 | 61 | return self.hash_map.iterator(); |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | fn free(self: &BufMap, value: []const u8) { | |
| 64 | fn free(self: &BufMap, value: []const u8) void { | |
| 65 | 65 | // remove the const |
| 66 | 66 | const mut_value = @ptrCast(&u8, value.ptr)[0..value.len]; |
| 67 | 67 | self.hash_map.allocator.free(mut_value); |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | fn copy(self: &BufMap, value: []const u8) -> %[]const u8 { | |
| 70 | fn copy(self: &BufMap, value: []const u8) %[]const u8 { | |
| 71 | 71 | const result = try self.hash_map.allocator.alloc(u8, value.len); |
| 72 | 72 | mem.copy(u8, result, value); |
| 73 | 73 | return result; |
std/buf_set.zig+10-10| ... | ... | @@ -7,14 +7,14 @@ pub const BufSet = struct { |
| 7 | 7 | |
| 8 | 8 | const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); |
| 9 | 9 | |
| 10 | pub fn init(a: &Allocator) -> BufSet { | |
| 10 | pub fn init(a: &Allocator) BufSet { | |
| 11 | 11 | var self = BufSet { |
| 12 | 12 | .hash_map = BufSetHashMap.init(a), |
| 13 | 13 | }; |
| 14 | 14 | return self; |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | pub fn deinit(self: &BufSet) { | |
| 17 | pub fn deinit(self: &BufSet) void { | |
| 18 | 18 | var it = self.hash_map.iterator(); |
| 19 | 19 | while (true) { |
| 20 | 20 | const entry = it.next() ?? break; |
| ... | ... | @@ -24,38 +24,38 @@ pub const BufSet = struct { |
| 24 | 24 | self.hash_map.deinit(); |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | pub fn put(self: &BufSet, key: []const u8) -> %void { | |
| 27 | pub fn put(self: &BufSet, key: []const u8) %void { | |
| 28 | 28 | if (self.hash_map.get(key) == null) { |
| 29 | 29 | const key_copy = try self.copy(key); |
| 30 | %defer self.free(key_copy); | |
| 30 | errdefer self.free(key_copy); | |
| 31 | 31 | _ = try self.hash_map.put(key_copy, {}); |
| 32 | 32 | } |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | pub fn delete(self: &BufSet, key: []const u8) { | |
| 35 | pub fn delete(self: &BufSet, key: []const u8) void { | |
| 36 | 36 | const entry = self.hash_map.remove(key) ?? return; |
| 37 | 37 | self.free(entry.key); |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | pub fn count(self: &const BufSet) -> usize { | |
| 40 | pub fn count(self: &const BufSet) usize { | |
| 41 | 41 | return self.hash_map.size; |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | pub fn iterator(self: &const BufSet) -> BufSetHashMap.Iterator { | |
| 44 | pub fn iterator(self: &const BufSet) BufSetHashMap.Iterator { | |
| 45 | 45 | return self.hash_map.iterator(); |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | pub fn allocator(self: &const BufSet) -> &Allocator { | |
| 48 | pub fn allocator(self: &const BufSet) &Allocator { | |
| 49 | 49 | return self.hash_map.allocator; |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | fn free(self: &BufSet, value: []const u8) { | |
| 52 | fn free(self: &BufSet, value: []const u8) void { | |
| 53 | 53 | // remove the const |
| 54 | 54 | const mut_value = @ptrCast(&u8, value.ptr)[0..value.len]; |
| 55 | 55 | self.hash_map.allocator.free(mut_value); |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | fn copy(self: &BufSet, value: []const u8) -> %[]const u8 { | |
| 58 | fn copy(self: &BufSet, value: []const u8) %[]const u8 { | |
| 59 | 59 | const result = try self.hash_map.allocator.alloc(u8, value.len); |
| 60 | 60 | mem.copy(u8, result, value); |
| 61 | 61 | return result; |
std/buffer.zig+22-22| ... | ... | @@ -12,14 +12,14 @@ pub const Buffer = struct { |
| 12 | 12 | list: ArrayList(u8), |
| 13 | 13 | |
| 14 | 14 | /// Must deinitialize with deinit. |
| 15 | pub fn init(allocator: &Allocator, m: []const u8) -> %Buffer { | |
| 15 | pub fn init(allocator: &Allocator, m: []const u8) %Buffer { | |
| 16 | 16 | var self = try initSize(allocator, m.len); |
| 17 | 17 | mem.copy(u8, self.list.items, m); |
| 18 | 18 | return self; |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | /// Must deinitialize with deinit. |
| 22 | pub fn initSize(allocator: &Allocator, size: usize) -> %Buffer { | |
| 22 | pub fn initSize(allocator: &Allocator, size: usize) %Buffer { | |
| 23 | 23 | var self = initNull(allocator); |
| 24 | 24 | try self.resize(size); |
| 25 | 25 | return self; |
| ... | ... | @@ -30,21 +30,21 @@ pub const Buffer = struct { |
| 30 | 30 | /// * ::replaceContents |
| 31 | 31 | /// * ::replaceContentsBuffer |
| 32 | 32 | /// * ::resize |
| 33 | pub fn initNull(allocator: &Allocator) -> Buffer { | |
| 33 | pub fn initNull(allocator: &Allocator) Buffer { | |
| 34 | 34 | return Buffer { |
| 35 | 35 | .list = ArrayList(u8).init(allocator), |
| 36 | 36 | }; |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | 39 | /// Must deinitialize with deinit. |
| 40 | pub fn initFromBuffer(buffer: &const Buffer) -> %Buffer { | |
| 40 | pub fn initFromBuffer(buffer: &const Buffer) %Buffer { | |
| 41 | 41 | return Buffer.init(buffer.list.allocator, buffer.toSliceConst()); |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | /// Buffer takes ownership of the passed in slice. The slice must have been |
| 45 | 45 | /// allocated with `allocator`. |
| 46 | 46 | /// Must deinitialize with deinit. |
| 47 | pub fn fromOwnedSlice(allocator: &Allocator, slice: []u8) -> Buffer { | |
| 47 | pub fn fromOwnedSlice(allocator: &Allocator, slice: []u8) Buffer { | |
| 48 | 48 | var self = Buffer { |
| 49 | 49 | .list = ArrayList(u8).fromOwnedSlice(allocator, slice), |
| 50 | 50 | }; |
| ... | ... | @@ -54,7 +54,7 @@ pub const Buffer = struct { |
| 54 | 54 | |
| 55 | 55 | /// The caller owns the returned memory. The Buffer becomes null and |
| 56 | 56 | /// is safe to `deinit`. |
| 57 | pub fn toOwnedSlice(self: &Buffer) -> []u8 { | |
| 57 | pub fn toOwnedSlice(self: &Buffer) []u8 { | |
| 58 | 58 | const allocator = self.list.allocator; |
| 59 | 59 | const result = allocator.shrink(u8, self.list.items, self.len()); |
| 60 | 60 | *self = initNull(allocator); |
| ... | ... | @@ -62,55 +62,55 @@ pub const Buffer = struct { |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | |
| 65 | pub fn deinit(self: &Buffer) { | |
| 65 | pub fn deinit(self: &Buffer) void { | |
| 66 | 66 | self.list.deinit(); |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | pub fn toSlice(self: &Buffer) -> []u8 { | |
| 69 | pub fn toSlice(self: &Buffer) []u8 { | |
| 70 | 70 | return self.list.toSlice()[0..self.len()]; |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | pub fn toSliceConst(self: &const Buffer) -> []const u8 { | |
| 73 | pub fn toSliceConst(self: &const Buffer) []const u8 { | |
| 74 | 74 | return self.list.toSliceConst()[0..self.len()]; |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | pub fn shrink(self: &Buffer, new_len: usize) { | |
| 77 | pub fn shrink(self: &Buffer, new_len: usize) void { | |
| 78 | 78 | assert(new_len <= self.len()); |
| 79 | 79 | self.list.shrink(new_len + 1); |
| 80 | 80 | self.list.items[self.len()] = 0; |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | pub fn resize(self: &Buffer, new_len: usize) -> %void { | |
| 83 | pub fn resize(self: &Buffer, new_len: usize) %void { | |
| 84 | 84 | try self.list.resize(new_len + 1); |
| 85 | 85 | self.list.items[self.len()] = 0; |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | pub fn isNull(self: &const Buffer) -> bool { | |
| 88 | pub fn isNull(self: &const Buffer) bool { | |
| 89 | 89 | return self.list.len == 0; |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | pub fn len(self: &const Buffer) -> usize { | |
| 92 | pub fn len(self: &const Buffer) usize { | |
| 93 | 93 | return self.list.len - 1; |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | pub fn append(self: &Buffer, m: []const u8) -> %void { | |
| 96 | pub fn append(self: &Buffer, m: []const u8) %void { | |
| 97 | 97 | const old_len = self.len(); |
| 98 | 98 | try self.resize(old_len + m.len); |
| 99 | 99 | mem.copy(u8, self.list.toSlice()[old_len..], m); |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | 102 | // TODO: remove, use OutStream for this |
| 103 | pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) -> %void { | |
| 103 | pub fn appendFormat(self: &Buffer, comptime format: []const u8, args: ...) %void { | |
| 104 | 104 | return fmt.format(self, append, format, args); |
| 105 | 105 | } |
| 106 | 106 | |
| 107 | 107 | // TODO: remove, use OutStream for this |
| 108 | pub fn appendByte(self: &Buffer, byte: u8) -> %void { | |
| 108 | pub fn appendByte(self: &Buffer, byte: u8) %void { | |
| 109 | 109 | return self.appendByteNTimes(byte, 1); |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | 112 | // TODO: remove, use OutStream for this |
| 113 | pub fn appendByteNTimes(self: &Buffer, byte: u8, count: usize) -> %void { | |
| 113 | pub fn appendByteNTimes(self: &Buffer, byte: u8, count: usize) %void { | |
| 114 | 114 | var prev_size: usize = self.len(); |
| 115 | 115 | const new_size = prev_size + count; |
| 116 | 116 | try self.resize(new_size); |
| ... | ... | @@ -121,29 +121,29 @@ pub const Buffer = struct { |
| 121 | 121 | } |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | pub fn eql(self: &const Buffer, m: []const u8) -> bool { | |
| 124 | pub fn eql(self: &const Buffer, m: []const u8) bool { | |
| 125 | 125 | return mem.eql(u8, self.toSliceConst(), m); |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | pub fn startsWith(self: &const Buffer, m: []const u8) -> bool { | |
| 128 | pub fn startsWith(self: &const Buffer, m: []const u8) bool { | |
| 129 | 129 | if (self.len() < m.len) return false; |
| 130 | 130 | return mem.eql(u8, self.list.items[0..m.len], m); |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | pub fn endsWith(self: &const Buffer, m: []const u8) -> bool { | |
| 133 | pub fn endsWith(self: &const Buffer, m: []const u8) bool { | |
| 134 | 134 | const l = self.len(); |
| 135 | 135 | if (l < m.len) return false; |
| 136 | 136 | const start = l - m.len; |
| 137 | 137 | return mem.eql(u8, self.list.items[start..l], m); |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | pub fn replaceContents(self: &const Buffer, m: []const u8) -> %void { | |
| 140 | pub fn replaceContents(self: &const Buffer, m: []const u8) %void { | |
| 141 | 141 | try self.resize(m.len); |
| 142 | 142 | mem.copy(u8, self.list.toSlice(), m); |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | 145 | /// For passing to C functions. |
| 146 | pub fn ptr(self: &const Buffer) -> &u8 { | |
| 146 | pub fn ptr(self: &const Buffer) &u8 { | |
| 147 | 147 | return self.list.items.ptr; |
| 148 | 148 | } |
| 149 | 149 | }; |
std/build.zig+124-124| ... | ... | @@ -90,7 +90,7 @@ pub const Builder = struct { |
| 90 | 90 | }; |
| 91 | 91 | |
| 92 | 92 | pub fn init(allocator: &Allocator, zig_exe: []const u8, build_root: []const u8, |
| 93 | cache_root: []const u8) -> Builder | |
| 93 | cache_root: []const u8) Builder | |
| 94 | 94 | { |
| 95 | 95 | var self = Builder { |
| 96 | 96 | .zig_exe = zig_exe, |
| ... | ... | @@ -136,7 +136,7 @@ pub const Builder = struct { |
| 136 | 136 | return self; |
| 137 | 137 | } |
| 138 | 138 | |
| 139 | pub fn deinit(self: &Builder) { | |
| 139 | pub fn deinit(self: &Builder) void { | |
| 140 | 140 | self.lib_paths.deinit(); |
| 141 | 141 | self.include_paths.deinit(); |
| 142 | 142 | self.rpaths.deinit(); |
| ... | ... | @@ -144,85 +144,85 @@ pub const Builder = struct { |
| 144 | 144 | self.top_level_steps.deinit(); |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | pub fn setInstallPrefix(self: &Builder, maybe_prefix: ?[]const u8) { | |
| 147 | pub fn setInstallPrefix(self: &Builder, maybe_prefix: ?[]const u8) void { | |
| 148 | 148 | self.prefix = maybe_prefix ?? "/usr/local"; // TODO better default |
| 149 | 149 | self.lib_dir = os.path.join(self.allocator, self.prefix, "lib") catch unreachable; |
| 150 | 150 | self.exe_dir = os.path.join(self.allocator, self.prefix, "bin") catch unreachable; |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | pub fn addExecutable(self: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep { | |
| 153 | pub fn addExecutable(self: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep { | |
| 154 | 154 | return LibExeObjStep.createExecutable(self, name, root_src); |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | pub fn addObject(self: &Builder, name: []const u8, root_src: []const u8) -> &LibExeObjStep { | |
| 157 | pub fn addObject(self: &Builder, name: []const u8, root_src: []const u8) &LibExeObjStep { | |
| 158 | 158 | return LibExeObjStep.createObject(self, name, root_src); |
| 159 | 159 | } |
| 160 | 160 | |
| 161 | 161 | pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8, |
| 162 | ver: &const Version) -> &LibExeObjStep | |
| 162 | ver: &const Version) &LibExeObjStep | |
| 163 | 163 | { |
| 164 | 164 | return LibExeObjStep.createSharedLibrary(self, name, root_src, ver); |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | pub fn addStaticLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep { | |
| 167 | pub fn addStaticLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep { | |
| 168 | 168 | return LibExeObjStep.createStaticLibrary(self, name, root_src); |
| 169 | 169 | } |
| 170 | 170 | |
| 171 | pub fn addTest(self: &Builder, root_src: []const u8) -> &TestStep { | |
| 171 | pub fn addTest(self: &Builder, root_src: []const u8) &TestStep { | |
| 172 | 172 | const test_step = self.allocator.create(TestStep) catch unreachable; |
| 173 | 173 | *test_step = TestStep.init(self, root_src); |
| 174 | 174 | return test_step; |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | pub fn addAssemble(self: &Builder, name: []const u8, src: []const u8) -> &LibExeObjStep { | |
| 177 | pub fn addAssemble(self: &Builder, name: []const u8, src: []const u8) &LibExeObjStep { | |
| 178 | 178 | const obj_step = LibExeObjStep.createObject(self, name, null); |
| 179 | 179 | obj_step.addAssemblyFile(src); |
| 180 | 180 | return obj_step; |
| 181 | 181 | } |
| 182 | 182 | |
| 183 | pub fn addCStaticLibrary(self: &Builder, name: []const u8) -> &LibExeObjStep { | |
| 183 | pub fn addCStaticLibrary(self: &Builder, name: []const u8) &LibExeObjStep { | |
| 184 | 184 | return LibExeObjStep.createCStaticLibrary(self, name); |
| 185 | 185 | } |
| 186 | 186 | |
| 187 | pub fn addCSharedLibrary(self: &Builder, name: []const u8, ver: &const Version) -> &LibExeObjStep { | |
| 187 | pub fn addCSharedLibrary(self: &Builder, name: []const u8, ver: &const Version) &LibExeObjStep { | |
| 188 | 188 | return LibExeObjStep.createCSharedLibrary(self, name, ver); |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | pub fn addCExecutable(self: &Builder, name: []const u8) -> &LibExeObjStep { | |
| 191 | pub fn addCExecutable(self: &Builder, name: []const u8) &LibExeObjStep { | |
| 192 | 192 | return LibExeObjStep.createCExecutable(self, name); |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | pub fn addCObject(self: &Builder, name: []const u8, src: []const u8) -> &LibExeObjStep { | |
| 195 | pub fn addCObject(self: &Builder, name: []const u8, src: []const u8) &LibExeObjStep { | |
| 196 | 196 | return LibExeObjStep.createCObject(self, name, src); |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | 199 | /// ::argv is copied. |
| 200 | 200 | pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, |
| 201 | argv: []const []const u8) -> &CommandStep | |
| 201 | argv: []const []const u8) &CommandStep | |
| 202 | 202 | { |
| 203 | 203 | return CommandStep.create(self, cwd, env_map, argv); |
| 204 | 204 | } |
| 205 | 205 | |
| 206 | pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) -> &WriteFileStep { | |
| 206 | pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) &WriteFileStep { | |
| 207 | 207 | const write_file_step = self.allocator.create(WriteFileStep) catch unreachable; |
| 208 | 208 | *write_file_step = WriteFileStep.init(self, file_path, data); |
| 209 | 209 | return write_file_step; |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | pub fn addLog(self: &Builder, comptime format: []const u8, args: ...) -> &LogStep { | |
| 212 | pub fn addLog(self: &Builder, comptime format: []const u8, args: ...) &LogStep { | |
| 213 | 213 | const data = self.fmt(format, args); |
| 214 | 214 | const log_step = self.allocator.create(LogStep) catch unreachable; |
| 215 | 215 | *log_step = LogStep.init(self, data); |
| 216 | 216 | return log_step; |
| 217 | 217 | } |
| 218 | 218 | |
| 219 | pub fn addRemoveDirTree(self: &Builder, dir_path: []const u8) -> &RemoveDirStep { | |
| 219 | pub fn addRemoveDirTree(self: &Builder, dir_path: []const u8) &RemoveDirStep { | |
| 220 | 220 | const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable; |
| 221 | 221 | *remove_dir_step = RemoveDirStep.init(self, dir_path); |
| 222 | 222 | return remove_dir_step; |
| 223 | 223 | } |
| 224 | 224 | |
| 225 | pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) -> Version { | |
| 225 | pub fn version(self: &const Builder, major: u32, minor: u32, patch: u32) Version { | |
| 226 | 226 | return Version { |
| 227 | 227 | .major = major, |
| 228 | 228 | .minor = minor, |
| ... | ... | @@ -230,19 +230,19 @@ pub const Builder = struct { |
| 230 | 230 | }; |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | pub fn addCIncludePath(self: &Builder, path: []const u8) { | |
| 233 | pub fn addCIncludePath(self: &Builder, path: []const u8) void { | |
| 234 | 234 | self.include_paths.append(path) catch unreachable; |
| 235 | 235 | } |
| 236 | 236 | |
| 237 | pub fn addRPath(self: &Builder, path: []const u8) { | |
| 237 | pub fn addRPath(self: &Builder, path: []const u8) void { | |
| 238 | 238 | self.rpaths.append(path) catch unreachable; |
| 239 | 239 | } |
| 240 | 240 | |
| 241 | pub fn addLibPath(self: &Builder, path: []const u8) { | |
| 241 | pub fn addLibPath(self: &Builder, path: []const u8) void { | |
| 242 | 242 | self.lib_paths.append(path) catch unreachable; |
| 243 | 243 | } |
| 244 | 244 | |
| 245 | pub fn make(self: &Builder, step_names: []const []const u8) -> %void { | |
| 245 | pub fn make(self: &Builder, step_names: []const []const u8) %void { | |
| 246 | 246 | var wanted_steps = ArrayList(&Step).init(self.allocator); |
| 247 | 247 | defer wanted_steps.deinit(); |
| 248 | 248 | |
| ... | ... | @@ -260,7 +260,7 @@ pub const Builder = struct { |
| 260 | 260 | } |
| 261 | 261 | } |
| 262 | 262 | |
| 263 | pub fn getInstallStep(self: &Builder) -> &Step { | |
| 263 | pub fn getInstallStep(self: &Builder) &Step { | |
| 264 | 264 | if (self.have_install_step) |
| 265 | 265 | return &self.install_tls.step; |
| 266 | 266 | |
| ... | ... | @@ -269,7 +269,7 @@ pub const Builder = struct { |
| 269 | 269 | return &self.install_tls.step; |
| 270 | 270 | } |
| 271 | 271 | |
| 272 | pub fn getUninstallStep(self: &Builder) -> &Step { | |
| 272 | pub fn getUninstallStep(self: &Builder) &Step { | |
| 273 | 273 | if (self.have_uninstall_step) |
| 274 | 274 | return &self.uninstall_tls.step; |
| 275 | 275 | |
| ... | ... | @@ -278,7 +278,7 @@ pub const Builder = struct { |
| 278 | 278 | return &self.uninstall_tls.step; |
| 279 | 279 | } |
| 280 | 280 | |
| 281 | fn makeUninstall(uninstall_step: &Step) -> %void { | |
| 281 | fn makeUninstall(uninstall_step: &Step) %void { | |
| 282 | 282 | const uninstall_tls = @fieldParentPtr(TopLevelStep, "step", uninstall_step); |
| 283 | 283 | const self = @fieldParentPtr(Builder, "uninstall_tls", uninstall_tls); |
| 284 | 284 | |
| ... | ... | @@ -292,7 +292,7 @@ pub const Builder = struct { |
| 292 | 292 | // TODO remove empty directories |
| 293 | 293 | } |
| 294 | 294 | |
| 295 | fn makeOneStep(self: &Builder, s: &Step) -> %void { | |
| 295 | fn makeOneStep(self: &Builder, s: &Step) %void { | |
| 296 | 296 | if (s.loop_flag) { |
| 297 | 297 | warn("Dependency loop detected:\n {}\n", s.name); |
| 298 | 298 | return error.DependencyLoopDetected; |
| ... | ... | @@ -313,7 +313,7 @@ pub const Builder = struct { |
| 313 | 313 | try s.make(); |
| 314 | 314 | } |
| 315 | 315 | |
| 316 | fn getTopLevelStepByName(self: &Builder, name: []const u8) -> %&Step { | |
| 316 | fn getTopLevelStepByName(self: &Builder, name: []const u8) %&Step { | |
| 317 | 317 | for (self.top_level_steps.toSliceConst()) |top_level_step| { |
| 318 | 318 | if (mem.eql(u8, top_level_step.step.name, name)) { |
| 319 | 319 | return &top_level_step.step; |
| ... | ... | @@ -323,7 +323,7 @@ pub const Builder = struct { |
| 323 | 323 | return error.InvalidStepName; |
| 324 | 324 | } |
| 325 | 325 | |
| 326 | fn processNixOSEnvVars(self: &Builder) { | |
| 326 | fn processNixOSEnvVars(self: &Builder) void { | |
| 327 | 327 | if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| { |
| 328 | 328 | var it = mem.split(nix_cflags_compile, " "); |
| 329 | 329 | while (true) { |
| ... | ... | @@ -365,7 +365,7 @@ pub const Builder = struct { |
| 365 | 365 | } |
| 366 | 366 | } |
| 367 | 367 | |
| 368 | pub fn option(self: &Builder, comptime T: type, name: []const u8, description: []const u8) -> ?T { | |
| 368 | pub fn option(self: &Builder, comptime T: type, name: []const u8, description: []const u8) ?T { | |
| 369 | 369 | const type_id = comptime typeToEnum(T); |
| 370 | 370 | const available_option = AvailableOption { |
| 371 | 371 | .name = name, |
| ... | ... | @@ -418,7 +418,7 @@ pub const Builder = struct { |
| 418 | 418 | } |
| 419 | 419 | } |
| 420 | 420 | |
| 421 | pub fn step(self: &Builder, name: []const u8, description: []const u8) -> &Step { | |
| 421 | pub fn step(self: &Builder, name: []const u8, description: []const u8) &Step { | |
| 422 | 422 | const step_info = self.allocator.create(TopLevelStep) catch unreachable; |
| 423 | 423 | *step_info = TopLevelStep { |
| 424 | 424 | .step = Step.initNoOp(name, self.allocator), |
| ... | ... | @@ -428,7 +428,7 @@ pub const Builder = struct { |
| 428 | 428 | return &step_info.step; |
| 429 | 429 | } |
| 430 | 430 | |
| 431 | pub fn standardReleaseOptions(self: &Builder) -> builtin.Mode { | |
| 431 | pub fn standardReleaseOptions(self: &Builder) builtin.Mode { | |
| 432 | 432 | if (self.release_mode) |mode| return mode; |
| 433 | 433 | |
| 434 | 434 | const release_safe = self.option(bool, "release-safe", "optimizations on and safety on") ?? false; |
| ... | ... | @@ -449,7 +449,7 @@ pub const Builder = struct { |
| 449 | 449 | return mode; |
| 450 | 450 | } |
| 451 | 451 | |
| 452 | pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool { | |
| 452 | pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) bool { | |
| 453 | 453 | if (self.user_input_options.put(name, UserInputOption { |
| 454 | 454 | .name = name, |
| 455 | 455 | .value = UserValue { .Scalar = value }, |
| ... | ... | @@ -486,7 +486,7 @@ pub const Builder = struct { |
| 486 | 486 | return false; |
| 487 | 487 | } |
| 488 | 488 | |
| 489 | pub fn addUserInputFlag(self: &Builder, name: []const u8) -> bool { | |
| 489 | pub fn addUserInputFlag(self: &Builder, name: []const u8) bool { | |
| 490 | 490 | if (self.user_input_options.put(name, UserInputOption { |
| 491 | 491 | .name = name, |
| 492 | 492 | .value = UserValue {.Flag = {} }, |
| ... | ... | @@ -507,7 +507,7 @@ pub const Builder = struct { |
| 507 | 507 | return false; |
| 508 | 508 | } |
| 509 | 509 | |
| 510 | fn typeToEnum(comptime T: type) -> TypeId { | |
| 510 | fn typeToEnum(comptime T: type) TypeId { | |
| 511 | 511 | return switch (@typeId(T)) { |
| 512 | 512 | builtin.TypeId.Int => TypeId.Int, |
| 513 | 513 | builtin.TypeId.Float => TypeId.Float, |
| ... | ... | @@ -520,11 +520,11 @@ pub const Builder = struct { |
| 520 | 520 | }; |
| 521 | 521 | } |
| 522 | 522 | |
| 523 | fn markInvalidUserInput(self: &Builder) { | |
| 523 | fn markInvalidUserInput(self: &Builder) void { | |
| 524 | 524 | self.invalid_user_input = true; |
| 525 | 525 | } |
| 526 | 526 | |
| 527 | pub fn typeIdName(id: TypeId) -> []const u8 { | |
| 527 | pub fn typeIdName(id: TypeId) []const u8 { | |
| 528 | 528 | return switch (id) { |
| 529 | 529 | TypeId.Bool => "bool", |
| 530 | 530 | TypeId.Int => "int", |
| ... | ... | @@ -534,7 +534,7 @@ pub const Builder = struct { |
| 534 | 534 | }; |
| 535 | 535 | } |
| 536 | 536 | |
| 537 | pub fn validateUserInputDidItFail(self: &Builder) -> bool { | |
| 537 | pub fn validateUserInputDidItFail(self: &Builder) bool { | |
| 538 | 538 | // make sure all args are used |
| 539 | 539 | var it = self.user_input_options.iterator(); |
| 540 | 540 | while (true) { |
| ... | ... | @@ -548,11 +548,11 @@ pub const Builder = struct { |
| 548 | 548 | return self.invalid_user_input; |
| 549 | 549 | } |
| 550 | 550 | |
| 551 | fn spawnChild(self: &Builder, argv: []const []const u8) -> %void { | |
| 551 | fn spawnChild(self: &Builder, argv: []const []const u8) %void { | |
| 552 | 552 | return self.spawnChildEnvMap(null, &self.env_map, argv); |
| 553 | 553 | } |
| 554 | 554 | |
| 555 | fn printCmd(cwd: ?[]const u8, argv: []const []const u8) { | |
| 555 | fn printCmd(cwd: ?[]const u8, argv: []const []const u8) void { | |
| 556 | 556 | if (cwd) |yes_cwd| warn("cd {} && ", yes_cwd); |
| 557 | 557 | for (argv) |arg| { |
| 558 | 558 | warn("{} ", arg); |
| ... | ... | @@ -561,7 +561,7 @@ pub const Builder = struct { |
| 561 | 561 | } |
| 562 | 562 | |
| 563 | 563 | fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap, |
| 564 | argv: []const []const u8) -> %void | |
| 564 | argv: []const []const u8) %void | |
| 565 | 565 | { |
| 566 | 566 | if (self.verbose) { |
| 567 | 567 | printCmd(cwd, argv); |
| ... | ... | @@ -595,28 +595,28 @@ pub const Builder = struct { |
| 595 | 595 | } |
| 596 | 596 | } |
| 597 | 597 | |
| 598 | pub fn makePath(self: &Builder, path: []const u8) -> %void { | |
| 598 | pub fn makePath(self: &Builder, path: []const u8) %void { | |
| 599 | 599 | os.makePath(self.allocator, self.pathFromRoot(path)) catch |err| { |
| 600 | 600 | warn("Unable to create path {}: {}\n", path, @errorName(err)); |
| 601 | 601 | return err; |
| 602 | 602 | }; |
| 603 | 603 | } |
| 604 | 604 | |
| 605 | pub fn installArtifact(self: &Builder, artifact: &LibExeObjStep) { | |
| 605 | pub fn installArtifact(self: &Builder, artifact: &LibExeObjStep) void { | |
| 606 | 606 | self.getInstallStep().dependOn(&self.addInstallArtifact(artifact).step); |
| 607 | 607 | } |
| 608 | 608 | |
| 609 | pub fn addInstallArtifact(self: &Builder, artifact: &LibExeObjStep) -> &InstallArtifactStep { | |
| 609 | pub fn addInstallArtifact(self: &Builder, artifact: &LibExeObjStep) &InstallArtifactStep { | |
| 610 | 610 | return InstallArtifactStep.create(self, artifact); |
| 611 | 611 | } |
| 612 | 612 | |
| 613 | 613 | ///::dest_rel_path is relative to prefix path or it can be an absolute path |
| 614 | pub fn installFile(self: &Builder, src_path: []const u8, dest_rel_path: []const u8) { | |
| 614 | pub fn installFile(self: &Builder, src_path: []const u8, dest_rel_path: []const u8) void { | |
| 615 | 615 | self.getInstallStep().dependOn(&self.addInstallFile(src_path, dest_rel_path).step); |
| 616 | 616 | } |
| 617 | 617 | |
| 618 | 618 | ///::dest_rel_path is relative to prefix path or it can be an absolute path |
| 619 | pub fn addInstallFile(self: &Builder, src_path: []const u8, dest_rel_path: []const u8) -> &InstallFileStep { | |
| 619 | pub fn addInstallFile(self: &Builder, src_path: []const u8, dest_rel_path: []const u8) &InstallFileStep { | |
| 620 | 620 | const full_dest_path = os.path.resolve(self.allocator, self.prefix, dest_rel_path) catch unreachable; |
| 621 | 621 | self.pushInstalledFile(full_dest_path); |
| 622 | 622 | |
| ... | ... | @@ -625,16 +625,16 @@ pub const Builder = struct { |
| 625 | 625 | return install_step; |
| 626 | 626 | } |
| 627 | 627 | |
| 628 | pub fn pushInstalledFile(self: &Builder, full_path: []const u8) { | |
| 628 | pub fn pushInstalledFile(self: &Builder, full_path: []const u8) void { | |
| 629 | 629 | _ = self.getUninstallStep(); |
| 630 | 630 | self.installed_files.append(full_path) catch unreachable; |
| 631 | 631 | } |
| 632 | 632 | |
| 633 | fn copyFile(self: &Builder, source_path: []const u8, dest_path: []const u8) -> %void { | |
| 633 | fn copyFile(self: &Builder, source_path: []const u8, dest_path: []const u8) %void { | |
| 634 | 634 | return self.copyFileMode(source_path, dest_path, 0o666); |
| 635 | 635 | } |
| 636 | 636 | |
| 637 | fn copyFileMode(self: &Builder, source_path: []const u8, dest_path: []const u8, mode: usize) -> %void { | |
| 637 | fn copyFileMode(self: &Builder, source_path: []const u8, dest_path: []const u8, mode: usize) %void { | |
| 638 | 638 | if (self.verbose) { |
| 639 | 639 | warn("cp {} {}\n", source_path, dest_path); |
| 640 | 640 | } |
| ... | ... | @@ -651,15 +651,15 @@ pub const Builder = struct { |
| 651 | 651 | }; |
| 652 | 652 | } |
| 653 | 653 | |
| 654 | fn pathFromRoot(self: &Builder, rel_path: []const u8) -> []u8 { | |
| 654 | fn pathFromRoot(self: &Builder, rel_path: []const u8) []u8 { | |
| 655 | 655 | return os.path.resolve(self.allocator, self.build_root, rel_path) catch unreachable; |
| 656 | 656 | } |
| 657 | 657 | |
| 658 | pub fn fmt(self: &Builder, comptime format: []const u8, args: ...) -> []u8 { | |
| 658 | pub fn fmt(self: &Builder, comptime format: []const u8, args: ...) []u8 { | |
| 659 | 659 | return fmt_lib.allocPrint(self.allocator, format, args) catch unreachable; |
| 660 | 660 | } |
| 661 | 661 | |
| 662 | fn getCCExe(self: &Builder) -> []const u8 { | |
| 662 | fn getCCExe(self: &Builder) []const u8 { | |
| 663 | 663 | if (builtin.environ == builtin.Environ.msvc) { |
| 664 | 664 | return "cl.exe"; |
| 665 | 665 | } else { |
| ... | ... | @@ -672,7 +672,7 @@ pub const Builder = struct { |
| 672 | 672 | } |
| 673 | 673 | } |
| 674 | 674 | |
| 675 | pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) -> %[]const u8 { | |
| 675 | pub fn findProgram(self: &Builder, names: []const []const u8, paths: []const []const u8) %[]const u8 { | |
| 676 | 676 | // TODO report error for ambiguous situations |
| 677 | 677 | const exe_extension = (Target { .Native = {}}).exeFileExt(); |
| 678 | 678 | for (self.search_prefixes.toSliceConst()) |search_prefix| { |
| ... | ... | @@ -721,7 +721,7 @@ pub const Builder = struct { |
| 721 | 721 | return error.FileNotFound; |
| 722 | 722 | } |
| 723 | 723 | |
| 724 | pub fn exec(self: &Builder, argv: []const []const u8) -> %[]u8 { | |
| 724 | pub fn exec(self: &Builder, argv: []const []const u8) %[]u8 { | |
| 725 | 725 | const max_output_size = 100 * 1024; |
| 726 | 726 | const result = try os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size); |
| 727 | 727 | switch (result.term) { |
| ... | ... | @@ -743,7 +743,7 @@ pub const Builder = struct { |
| 743 | 743 | } |
| 744 | 744 | } |
| 745 | 745 | |
| 746 | pub fn addSearchPrefix(self: &Builder, search_prefix: []const u8) { | |
| 746 | pub fn addSearchPrefix(self: &Builder, search_prefix: []const u8) void { | |
| 747 | 747 | self.search_prefixes.append(search_prefix) catch unreachable; |
| 748 | 748 | } |
| 749 | 749 | }; |
| ... | ... | @@ -764,7 +764,7 @@ pub const Target = union(enum) { |
| 764 | 764 | Native: void, |
| 765 | 765 | Cross: CrossTarget, |
| 766 | 766 | |
| 767 | pub fn oFileExt(self: &const Target) -> []const u8 { | |
| 767 | pub fn oFileExt(self: &const Target) []const u8 { | |
| 768 | 768 | const environ = switch (*self) { |
| 769 | 769 | Target.Native => builtin.environ, |
| 770 | 770 | Target.Cross => |t| t.environ, |
| ... | ... | @@ -775,42 +775,42 @@ pub const Target = union(enum) { |
| 775 | 775 | }; |
| 776 | 776 | } |
| 777 | 777 | |
| 778 | pub fn exeFileExt(self: &const Target) -> []const u8 { | |
| 778 | pub fn exeFileExt(self: &const Target) []const u8 { | |
| 779 | 779 | return switch (self.getOs()) { |
| 780 | 780 | builtin.Os.windows => ".exe", |
| 781 | 781 | else => "", |
| 782 | 782 | }; |
| 783 | 783 | } |
| 784 | 784 | |
| 785 | pub fn libFileExt(self: &const Target) -> []const u8 { | |
| 785 | pub fn libFileExt(self: &const Target) []const u8 { | |
| 786 | 786 | return switch (self.getOs()) { |
| 787 | 787 | builtin.Os.windows => ".lib", |
| 788 | 788 | else => ".a", |
| 789 | 789 | }; |
| 790 | 790 | } |
| 791 | 791 | |
| 792 | pub fn getOs(self: &const Target) -> builtin.Os { | |
| 792 | pub fn getOs(self: &const Target) builtin.Os { | |
| 793 | 793 | return switch (*self) { |
| 794 | 794 | Target.Native => builtin.os, |
| 795 | 795 | Target.Cross => |t| t.os, |
| 796 | 796 | }; |
| 797 | 797 | } |
| 798 | 798 | |
| 799 | pub fn isDarwin(self: &const Target) -> bool { | |
| 799 | pub fn isDarwin(self: &const Target) bool { | |
| 800 | 800 | return switch (self.getOs()) { |
| 801 | 801 | builtin.Os.ios, builtin.Os.macosx => true, |
| 802 | 802 | else => false, |
| 803 | 803 | }; |
| 804 | 804 | } |
| 805 | 805 | |
| 806 | pub fn isWindows(self: &const Target) -> bool { | |
| 806 | pub fn isWindows(self: &const Target) bool { | |
| 807 | 807 | return switch (self.getOs()) { |
| 808 | 808 | builtin.Os.windows => true, |
| 809 | 809 | else => false, |
| 810 | 810 | }; |
| 811 | 811 | } |
| 812 | 812 | |
| 813 | pub fn wantSharedLibSymLinks(self: &const Target) -> bool { | |
| 813 | pub fn wantSharedLibSymLinks(self: &const Target) bool { | |
| 814 | 814 | return !self.isWindows(); |
| 815 | 815 | } |
| 816 | 816 | }; |
| ... | ... | @@ -865,58 +865,58 @@ pub const LibExeObjStep = struct { |
| 865 | 865 | }; |
| 866 | 866 | |
| 867 | 867 | pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8, |
| 868 | ver: &const Version) -> &LibExeObjStep | |
| 868 | ver: &const Version) &LibExeObjStep | |
| 869 | 869 | { |
| 870 | 870 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 871 | 871 | *self = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver); |
| 872 | 872 | return self; |
| 873 | 873 | } |
| 874 | 874 | |
| 875 | pub fn createCSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) -> &LibExeObjStep { | |
| 875 | pub fn createCSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) &LibExeObjStep { | |
| 876 | 876 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 877 | 877 | *self = initC(builder, name, Kind.Lib, version, false); |
| 878 | 878 | return self; |
| 879 | 879 | } |
| 880 | 880 | |
| 881 | pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep { | |
| 881 | pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep { | |
| 882 | 882 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 883 | 883 | *self = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0)); |
| 884 | 884 | return self; |
| 885 | 885 | } |
| 886 | 886 | |
| 887 | pub fn createCStaticLibrary(builder: &Builder, name: []const u8) -> &LibExeObjStep { | |
| 887 | pub fn createCStaticLibrary(builder: &Builder, name: []const u8) &LibExeObjStep { | |
| 888 | 888 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 889 | 889 | *self = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true); |
| 890 | 890 | return self; |
| 891 | 891 | } |
| 892 | 892 | |
| 893 | pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) -> &LibExeObjStep { | |
| 893 | pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) &LibExeObjStep { | |
| 894 | 894 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 895 | 895 | *self = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0)); |
| 896 | 896 | return self; |
| 897 | 897 | } |
| 898 | 898 | |
| 899 | pub fn createCObject(builder: &Builder, name: []const u8, src: []const u8) -> &LibExeObjStep { | |
| 899 | pub fn createCObject(builder: &Builder, name: []const u8, src: []const u8) &LibExeObjStep { | |
| 900 | 900 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 901 | 901 | *self = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false); |
| 902 | 902 | self.object_src = src; |
| 903 | 903 | return self; |
| 904 | 904 | } |
| 905 | 905 | |
| 906 | pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep { | |
| 906 | pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) &LibExeObjStep { | |
| 907 | 907 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 908 | 908 | *self = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0)); |
| 909 | 909 | return self; |
| 910 | 910 | } |
| 911 | 911 | |
| 912 | pub fn createCExecutable(builder: &Builder, name: []const u8) -> &LibExeObjStep { | |
| 912 | pub fn createCExecutable(builder: &Builder, name: []const u8) &LibExeObjStep { | |
| 913 | 913 | const self = builder.allocator.create(LibExeObjStep) catch unreachable; |
| 914 | 914 | *self = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false); |
| 915 | 915 | return self; |
| 916 | 916 | } |
| 917 | 917 | |
| 918 | 918 | fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, |
| 919 | static: bool, ver: &const Version) -> LibExeObjStep | |
| 919 | static: bool, ver: &const Version) LibExeObjStep | |
| 920 | 920 | { |
| 921 | 921 | var self = LibExeObjStep { |
| 922 | 922 | .strip = false, |
| ... | ... | @@ -956,7 +956,7 @@ pub const LibExeObjStep = struct { |
| 956 | 956 | return self; |
| 957 | 957 | } |
| 958 | 958 | |
| 959 | fn initC(builder: &Builder, name: []const u8, kind: Kind, version: &const Version, static: bool) -> LibExeObjStep { | |
| 959 | fn initC(builder: &Builder, name: []const u8, kind: Kind, version: &const Version, static: bool) LibExeObjStep { | |
| 960 | 960 | var self = LibExeObjStep { |
| 961 | 961 | .builder = builder, |
| 962 | 962 | .name = name, |
| ... | ... | @@ -996,7 +996,7 @@ pub const LibExeObjStep = struct { |
| 996 | 996 | return self; |
| 997 | 997 | } |
| 998 | 998 | |
| 999 | fn computeOutFileNames(self: &LibExeObjStep) { | |
| 999 | fn computeOutFileNames(self: &LibExeObjStep) void { | |
| 1000 | 1000 | switch (self.kind) { |
| 1001 | 1001 | Kind.Obj => { |
| 1002 | 1002 | self.out_filename = self.builder.fmt("{}{}", self.name, self.target.oFileExt()); |
| ... | ... | @@ -1031,7 +1031,7 @@ pub const LibExeObjStep = struct { |
| 1031 | 1031 | } |
| 1032 | 1032 | |
| 1033 | 1033 | pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, |
| 1034 | target_environ: builtin.Environ) | |
| 1034 | target_environ: builtin.Environ) void | |
| 1035 | 1035 | { |
| 1036 | 1036 | self.target = Target { |
| 1037 | 1037 | .Cross = CrossTarget { |
| ... | ... | @@ -1044,16 +1044,16 @@ pub const LibExeObjStep = struct { |
| 1044 | 1044 | } |
| 1045 | 1045 | |
| 1046 | 1046 | // TODO respect this in the C args |
| 1047 | pub fn setLinkerScriptPath(self: &LibExeObjStep, path: []const u8) { | |
| 1047 | pub fn setLinkerScriptPath(self: &LibExeObjStep, path: []const u8) void { | |
| 1048 | 1048 | self.linker_script = path; |
| 1049 | 1049 | } |
| 1050 | 1050 | |
| 1051 | pub fn linkFramework(self: &LibExeObjStep, framework_name: []const u8) { | |
| 1051 | pub fn linkFramework(self: &LibExeObjStep, framework_name: []const u8) void { | |
| 1052 | 1052 | assert(self.target.isDarwin()); |
| 1053 | 1053 | self.frameworks.put(framework_name) catch unreachable; |
| 1054 | 1054 | } |
| 1055 | 1055 | |
| 1056 | pub fn linkLibrary(self: &LibExeObjStep, lib: &LibExeObjStep) { | |
| 1056 | pub fn linkLibrary(self: &LibExeObjStep, lib: &LibExeObjStep) void { | |
| 1057 | 1057 | assert(self.kind != Kind.Obj); |
| 1058 | 1058 | assert(lib.kind == Kind.Lib); |
| 1059 | 1059 | |
| ... | ... | @@ -1074,26 +1074,26 @@ pub const LibExeObjStep = struct { |
| 1074 | 1074 | } |
| 1075 | 1075 | } |
| 1076 | 1076 | |
| 1077 | pub fn linkSystemLibrary(self: &LibExeObjStep, name: []const u8) { | |
| 1077 | pub fn linkSystemLibrary(self: &LibExeObjStep, name: []const u8) void { | |
| 1078 | 1078 | assert(self.kind != Kind.Obj); |
| 1079 | 1079 | self.link_libs.put(name) catch unreachable; |
| 1080 | 1080 | } |
| 1081 | 1081 | |
| 1082 | pub fn addSourceFile(self: &LibExeObjStep, file: []const u8) { | |
| 1082 | pub fn addSourceFile(self: &LibExeObjStep, file: []const u8) void { | |
| 1083 | 1083 | assert(self.kind != Kind.Obj); |
| 1084 | 1084 | assert(!self.is_zig); |
| 1085 | 1085 | self.source_files.append(file) catch unreachable; |
| 1086 | 1086 | } |
| 1087 | 1087 | |
| 1088 | pub fn setVerboseLink(self: &LibExeObjStep, value: bool) { | |
| 1088 | pub fn setVerboseLink(self: &LibExeObjStep, value: bool) void { | |
| 1089 | 1089 | self.verbose_link = value; |
| 1090 | 1090 | } |
| 1091 | 1091 | |
| 1092 | pub fn setBuildMode(self: &LibExeObjStep, mode: builtin.Mode) { | |
| 1092 | pub fn setBuildMode(self: &LibExeObjStep, mode: builtin.Mode) void { | |
| 1093 | 1093 | self.build_mode = mode; |
| 1094 | 1094 | } |
| 1095 | 1095 | |
| 1096 | pub fn setOutputPath(self: &LibExeObjStep, file_path: []const u8) { | |
| 1096 | pub fn setOutputPath(self: &LibExeObjStep, file_path: []const u8) void { | |
| 1097 | 1097 | self.output_path = file_path; |
| 1098 | 1098 | |
| 1099 | 1099 | // catch a common mistake |
| ... | ... | @@ -1102,14 +1102,14 @@ pub const LibExeObjStep = struct { |
| 1102 | 1102 | } |
| 1103 | 1103 | } |
| 1104 | 1104 | |
| 1105 | pub fn getOutputPath(self: &LibExeObjStep) -> []const u8 { | |
| 1105 | pub fn getOutputPath(self: &LibExeObjStep) []const u8 { | |
| 1106 | 1106 | return if (self.output_path) |output_path| |
| 1107 | 1107 | output_path |
| 1108 | 1108 | else |
| 1109 | 1109 | os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable; |
| 1110 | 1110 | } |
| 1111 | 1111 | |
| 1112 | pub fn setOutputHPath(self: &LibExeObjStep, file_path: []const u8) { | |
| 1112 | pub fn setOutputHPath(self: &LibExeObjStep, file_path: []const u8) void { | |
| 1113 | 1113 | self.output_h_path = file_path; |
| 1114 | 1114 | |
| 1115 | 1115 | // catch a common mistake |
| ... | ... | @@ -1118,24 +1118,24 @@ pub const LibExeObjStep = struct { |
| 1118 | 1118 | } |
| 1119 | 1119 | } |
| 1120 | 1120 | |
| 1121 | pub fn getOutputHPath(self: &LibExeObjStep) -> []const u8 { | |
| 1121 | pub fn getOutputHPath(self: &LibExeObjStep) []const u8 { | |
| 1122 | 1122 | return if (self.output_h_path) |output_h_path| |
| 1123 | 1123 | output_h_path |
| 1124 | 1124 | else |
| 1125 | 1125 | os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable; |
| 1126 | 1126 | } |
| 1127 | 1127 | |
| 1128 | pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) { | |
| 1128 | pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) void { | |
| 1129 | 1129 | self.assembly_files.append(path) catch unreachable; |
| 1130 | 1130 | } |
| 1131 | 1131 | |
| 1132 | pub fn addObjectFile(self: &LibExeObjStep, path: []const u8) { | |
| 1132 | pub fn addObjectFile(self: &LibExeObjStep, path: []const u8) void { | |
| 1133 | 1133 | assert(self.kind != Kind.Obj); |
| 1134 | 1134 | |
| 1135 | 1135 | self.object_files.append(path) catch unreachable; |
| 1136 | 1136 | } |
| 1137 | 1137 | |
| 1138 | pub fn addObject(self: &LibExeObjStep, obj: &LibExeObjStep) { | |
| 1138 | pub fn addObject(self: &LibExeObjStep, obj: &LibExeObjStep) void { | |
| 1139 | 1139 | assert(obj.kind == Kind.Obj); |
| 1140 | 1140 | assert(self.kind != Kind.Obj); |
| 1141 | 1141 | |
| ... | ... | @@ -1152,15 +1152,15 @@ pub const LibExeObjStep = struct { |
| 1152 | 1152 | self.include_dirs.append(self.builder.cache_root) catch unreachable; |
| 1153 | 1153 | } |
| 1154 | 1154 | |
| 1155 | pub fn addIncludeDir(self: &LibExeObjStep, path: []const u8) { | |
| 1155 | pub fn addIncludeDir(self: &LibExeObjStep, path: []const u8) void { | |
| 1156 | 1156 | self.include_dirs.append(path) catch unreachable; |
| 1157 | 1157 | } |
| 1158 | 1158 | |
| 1159 | pub fn addLibPath(self: &LibExeObjStep, path: []const u8) { | |
| 1159 | pub fn addLibPath(self: &LibExeObjStep, path: []const u8) void { | |
| 1160 | 1160 | self.lib_paths.append(path) catch unreachable; |
| 1161 | 1161 | } |
| 1162 | 1162 | |
| 1163 | pub fn addPackagePath(self: &LibExeObjStep, name: []const u8, pkg_index_path: []const u8) { | |
| 1163 | pub fn addPackagePath(self: &LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void { | |
| 1164 | 1164 | assert(self.is_zig); |
| 1165 | 1165 | |
| 1166 | 1166 | self.packages.append(Pkg { |
| ... | ... | @@ -1169,23 +1169,23 @@ pub const LibExeObjStep = struct { |
| 1169 | 1169 | }) catch unreachable; |
| 1170 | 1170 | } |
| 1171 | 1171 | |
| 1172 | pub fn addCompileFlags(self: &LibExeObjStep, flags: []const []const u8) { | |
| 1172 | pub fn addCompileFlags(self: &LibExeObjStep, flags: []const []const u8) void { | |
| 1173 | 1173 | for (flags) |flag| { |
| 1174 | 1174 | self.cflags.append(flag) catch unreachable; |
| 1175 | 1175 | } |
| 1176 | 1176 | } |
| 1177 | 1177 | |
| 1178 | pub fn setNoStdLib(self: &LibExeObjStep, disable: bool) { | |
| 1178 | pub fn setNoStdLib(self: &LibExeObjStep, disable: bool) void { | |
| 1179 | 1179 | assert(!self.is_zig); |
| 1180 | 1180 | self.disable_libc = disable; |
| 1181 | 1181 | } |
| 1182 | 1182 | |
| 1183 | fn make(step: &Step) -> %void { | |
| 1183 | fn make(step: &Step) %void { | |
| 1184 | 1184 | const self = @fieldParentPtr(LibExeObjStep, "step", step); |
| 1185 | 1185 | return if (self.is_zig) self.makeZig() else self.makeC(); |
| 1186 | 1186 | } |
| 1187 | 1187 | |
| 1188 | fn makeZig(self: &LibExeObjStep) -> %void { | |
| 1188 | fn makeZig(self: &LibExeObjStep) %void { | |
| 1189 | 1189 | const builder = self.builder; |
| 1190 | 1190 | |
| 1191 | 1191 | assert(self.is_zig); |
| ... | ... | @@ -1351,7 +1351,7 @@ pub const LibExeObjStep = struct { |
| 1351 | 1351 | } |
| 1352 | 1352 | } |
| 1353 | 1353 | |
| 1354 | fn appendCompileFlags(self: &LibExeObjStep, args: &ArrayList([]const u8)) { | |
| 1354 | fn appendCompileFlags(self: &LibExeObjStep, args: &ArrayList([]const u8)) void { | |
| 1355 | 1355 | if (!self.strip) { |
| 1356 | 1356 | args.append("-g") catch unreachable; |
| 1357 | 1357 | } |
| ... | ... | @@ -1396,7 +1396,7 @@ pub const LibExeObjStep = struct { |
| 1396 | 1396 | } |
| 1397 | 1397 | } |
| 1398 | 1398 | |
| 1399 | fn makeC(self: &LibExeObjStep) -> %void { | |
| 1399 | fn makeC(self: &LibExeObjStep) %void { | |
| 1400 | 1400 | const builder = self.builder; |
| 1401 | 1401 | |
| 1402 | 1402 | const cc = builder.getCCExe(); |
| ... | ... | @@ -1635,7 +1635,7 @@ pub const TestStep = struct { |
| 1635 | 1635 | target: Target, |
| 1636 | 1636 | exec_cmd_args: ?[]const ?[]const u8, |
| 1637 | 1637 | |
| 1638 | pub fn init(builder: &Builder, root_src: []const u8) -> TestStep { | |
| 1638 | pub fn init(builder: &Builder, root_src: []const u8) TestStep { | |
| 1639 | 1639 | const step_name = builder.fmt("test {}", root_src); |
| 1640 | 1640 | return TestStep { |
| 1641 | 1641 | .step = Step.init(step_name, builder.allocator, make), |
| ... | ... | @@ -1651,28 +1651,28 @@ pub const TestStep = struct { |
| 1651 | 1651 | }; |
| 1652 | 1652 | } |
| 1653 | 1653 | |
| 1654 | pub fn setVerbose(self: &TestStep, value: bool) { | |
| 1654 | pub fn setVerbose(self: &TestStep, value: bool) void { | |
| 1655 | 1655 | self.verbose = value; |
| 1656 | 1656 | } |
| 1657 | 1657 | |
| 1658 | pub fn setBuildMode(self: &TestStep, mode: builtin.Mode) { | |
| 1658 | pub fn setBuildMode(self: &TestStep, mode: builtin.Mode) void { | |
| 1659 | 1659 | self.build_mode = mode; |
| 1660 | 1660 | } |
| 1661 | 1661 | |
| 1662 | pub fn linkSystemLibrary(self: &TestStep, name: []const u8) { | |
| 1662 | pub fn linkSystemLibrary(self: &TestStep, name: []const u8) void { | |
| 1663 | 1663 | self.link_libs.put(name) catch unreachable; |
| 1664 | 1664 | } |
| 1665 | 1665 | |
| 1666 | pub fn setNamePrefix(self: &TestStep, text: []const u8) { | |
| 1666 | pub fn setNamePrefix(self: &TestStep, text: []const u8) void { | |
| 1667 | 1667 | self.name_prefix = text; |
| 1668 | 1668 | } |
| 1669 | 1669 | |
| 1670 | pub fn setFilter(self: &TestStep, text: ?[]const u8) { | |
| 1670 | pub fn setFilter(self: &TestStep, text: ?[]const u8) void { | |
| 1671 | 1671 | self.filter = text; |
| 1672 | 1672 | } |
| 1673 | 1673 | |
| 1674 | 1674 | pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, |
| 1675 | target_environ: builtin.Environ) | |
| 1675 | target_environ: builtin.Environ) void | |
| 1676 | 1676 | { |
| 1677 | 1677 | self.target = Target { |
| 1678 | 1678 | .Cross = CrossTarget { |
| ... | ... | @@ -1683,11 +1683,11 @@ pub const TestStep = struct { |
| 1683 | 1683 | }; |
| 1684 | 1684 | } |
| 1685 | 1685 | |
| 1686 | pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) { | |
| 1686 | pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) void { | |
| 1687 | 1687 | self.exec_cmd_args = args; |
| 1688 | 1688 | } |
| 1689 | 1689 | |
| 1690 | fn make(step: &Step) -> %void { | |
| 1690 | fn make(step: &Step) %void { | |
| 1691 | 1691 | const self = @fieldParentPtr(TestStep, "step", step); |
| 1692 | 1692 | const builder = self.builder; |
| 1693 | 1693 | |
| ... | ... | @@ -1781,7 +1781,7 @@ pub const CommandStep = struct { |
| 1781 | 1781 | |
| 1782 | 1782 | /// ::argv is copied. |
| 1783 | 1783 | pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap, |
| 1784 | argv: []const []const u8) -> &CommandStep | |
| 1784 | argv: []const []const u8) &CommandStep | |
| 1785 | 1785 | { |
| 1786 | 1786 | const self = builder.allocator.create(CommandStep) catch unreachable; |
| 1787 | 1787 | *self = CommandStep { |
| ... | ... | @@ -1796,7 +1796,7 @@ pub const CommandStep = struct { |
| 1796 | 1796 | return self; |
| 1797 | 1797 | } |
| 1798 | 1798 | |
| 1799 | fn make(step: &Step) -> %void { | |
| 1799 | fn make(step: &Step) %void { | |
| 1800 | 1800 | const self = @fieldParentPtr(CommandStep, "step", step); |
| 1801 | 1801 | |
| 1802 | 1802 | const cwd = if (self.cwd) |cwd| self.builder.pathFromRoot(cwd) else self.builder.build_root; |
| ... | ... | @@ -1812,7 +1812,7 @@ const InstallArtifactStep = struct { |
| 1812 | 1812 | |
| 1813 | 1813 | const Self = this; |
| 1814 | 1814 | |
| 1815 | pub fn create(builder: &Builder, artifact: &LibExeObjStep) -> &Self { | |
| 1815 | pub fn create(builder: &Builder, artifact: &LibExeObjStep) &Self { | |
| 1816 | 1816 | const self = builder.allocator.create(Self) catch unreachable; |
| 1817 | 1817 | const dest_dir = switch (artifact.kind) { |
| 1818 | 1818 | LibExeObjStep.Kind.Obj => unreachable, |
| ... | ... | @@ -1836,7 +1836,7 @@ const InstallArtifactStep = struct { |
| 1836 | 1836 | return self; |
| 1837 | 1837 | } |
| 1838 | 1838 | |
| 1839 | fn make(step: &Step) -> %void { | |
| 1839 | fn make(step: &Step) %void { | |
| 1840 | 1840 | const self = @fieldParentPtr(Self, "step", step); |
| 1841 | 1841 | const builder = self.builder; |
| 1842 | 1842 | |
| ... | ... | @@ -1859,7 +1859,7 @@ pub const InstallFileStep = struct { |
| 1859 | 1859 | src_path: []const u8, |
| 1860 | 1860 | dest_path: []const u8, |
| 1861 | 1861 | |
| 1862 | pub fn init(builder: &Builder, src_path: []const u8, dest_path: []const u8) -> InstallFileStep { | |
| 1862 | pub fn init(builder: &Builder, src_path: []const u8, dest_path: []const u8) InstallFileStep { | |
| 1863 | 1863 | return InstallFileStep { |
| 1864 | 1864 | .builder = builder, |
| 1865 | 1865 | .step = Step.init(builder.fmt("install {}", src_path), builder.allocator, make), |
| ... | ... | @@ -1868,7 +1868,7 @@ pub const InstallFileStep = struct { |
| 1868 | 1868 | }; |
| 1869 | 1869 | } |
| 1870 | 1870 | |
| 1871 | fn make(step: &Step) -> %void { | |
| 1871 | fn make(step: &Step) %void { | |
| 1872 | 1872 | const self = @fieldParentPtr(InstallFileStep, "step", step); |
| 1873 | 1873 | try self.builder.copyFile(self.src_path, self.dest_path); |
| 1874 | 1874 | } |
| ... | ... | @@ -1880,7 +1880,7 @@ pub const WriteFileStep = struct { |
| 1880 | 1880 | file_path: []const u8, |
| 1881 | 1881 | data: []const u8, |
| 1882 | 1882 | |
| 1883 | pub fn init(builder: &Builder, file_path: []const u8, data: []const u8) -> WriteFileStep { | |
| 1883 | pub fn init(builder: &Builder, file_path: []const u8, data: []const u8) WriteFileStep { | |
| 1884 | 1884 | return WriteFileStep { |
| 1885 | 1885 | .builder = builder, |
| 1886 | 1886 | .step = Step.init(builder.fmt("writefile {}", file_path), builder.allocator, make), |
| ... | ... | @@ -1889,7 +1889,7 @@ pub const WriteFileStep = struct { |
| 1889 | 1889 | }; |
| 1890 | 1890 | } |
| 1891 | 1891 | |
| 1892 | fn make(step: &Step) -> %void { | |
| 1892 | fn make(step: &Step) %void { | |
| 1893 | 1893 | const self = @fieldParentPtr(WriteFileStep, "step", step); |
| 1894 | 1894 | const full_path = self.builder.pathFromRoot(self.file_path); |
| 1895 | 1895 | const full_path_dir = os.path.dirname(full_path); |
| ... | ... | @@ -1909,7 +1909,7 @@ pub const LogStep = struct { |
| 1909 | 1909 | builder: &Builder, |
| 1910 | 1910 | data: []const u8, |
| 1911 | 1911 | |
| 1912 | pub fn init(builder: &Builder, data: []const u8) -> LogStep { | |
| 1912 | pub fn init(builder: &Builder, data: []const u8) LogStep { | |
| 1913 | 1913 | return LogStep { |
| 1914 | 1914 | .builder = builder, |
| 1915 | 1915 | .step = Step.init(builder.fmt("log {}", data), builder.allocator, make), |
| ... | ... | @@ -1917,7 +1917,7 @@ pub const LogStep = struct { |
| 1917 | 1917 | }; |
| 1918 | 1918 | } |
| 1919 | 1919 | |
| 1920 | fn make(step: &Step) -> %void { | |
| 1920 | fn make(step: &Step) %void { | |
| 1921 | 1921 | const self = @fieldParentPtr(LogStep, "step", step); |
| 1922 | 1922 | warn("{}", self.data); |
| 1923 | 1923 | } |
| ... | ... | @@ -1928,7 +1928,7 @@ pub const RemoveDirStep = struct { |
| 1928 | 1928 | builder: &Builder, |
| 1929 | 1929 | dir_path: []const u8, |
| 1930 | 1930 | |
| 1931 | pub fn init(builder: &Builder, dir_path: []const u8) -> RemoveDirStep { | |
| 1931 | pub fn init(builder: &Builder, dir_path: []const u8) RemoveDirStep { | |
| 1932 | 1932 | return RemoveDirStep { |
| 1933 | 1933 | .builder = builder, |
| 1934 | 1934 | .step = Step.init(builder.fmt("RemoveDir {}", dir_path), builder.allocator, make), |
| ... | ... | @@ -1936,7 +1936,7 @@ pub const RemoveDirStep = struct { |
| 1936 | 1936 | }; |
| 1937 | 1937 | } |
| 1938 | 1938 | |
| 1939 | fn make(step: &Step) -> %void { | |
| 1939 | fn make(step: &Step) %void { | |
| 1940 | 1940 | const self = @fieldParentPtr(RemoveDirStep, "step", step); |
| 1941 | 1941 | |
| 1942 | 1942 | const full_path = self.builder.pathFromRoot(self.dir_path); |
| ... | ... | @@ -1949,12 +1949,12 @@ pub const RemoveDirStep = struct { |
| 1949 | 1949 | |
| 1950 | 1950 | pub const Step = struct { |
| 1951 | 1951 | name: []const u8, |
| 1952 | makeFn: fn(self: &Step) -> %void, | |
| 1952 | makeFn: fn(self: &Step) %void, | |
| 1953 | 1953 | dependencies: ArrayList(&Step), |
| 1954 | 1954 | loop_flag: bool, |
| 1955 | 1955 | done_flag: bool, |
| 1956 | 1956 | |
| 1957 | pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)->%void) -> Step { | |
| 1957 | pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)%void) Step { | |
| 1958 | 1958 | return Step { |
| 1959 | 1959 | .name = name, |
| 1960 | 1960 | .makeFn = makeFn, |
| ... | ... | @@ -1963,11 +1963,11 @@ pub const Step = struct { |
| 1963 | 1963 | .done_flag = false, |
| 1964 | 1964 | }; |
| 1965 | 1965 | } |
| 1966 | pub fn initNoOp(name: []const u8, allocator: &Allocator) -> Step { | |
| 1966 | pub fn initNoOp(name: []const u8, allocator: &Allocator) Step { | |
| 1967 | 1967 | return init(name, allocator, makeNoOp); |
| 1968 | 1968 | } |
| 1969 | 1969 | |
| 1970 | pub fn make(self: &Step) -> %void { | |
| 1970 | pub fn make(self: &Step) %void { | |
| 1971 | 1971 | if (self.done_flag) |
| 1972 | 1972 | return; |
| 1973 | 1973 | |
| ... | ... | @@ -1975,15 +1975,15 @@ pub const Step = struct { |
| 1975 | 1975 | self.done_flag = true; |
| 1976 | 1976 | } |
| 1977 | 1977 | |
| 1978 | pub fn dependOn(self: &Step, other: &Step) { | |
| 1978 | pub fn dependOn(self: &Step, other: &Step) void { | |
| 1979 | 1979 | self.dependencies.append(other) catch unreachable; |
| 1980 | 1980 | } |
| 1981 | 1981 | |
| 1982 | fn makeNoOp(self: &Step) -> %void {} | |
| 1982 | fn makeNoOp(self: &Step) %void {} | |
| 1983 | 1983 | }; |
| 1984 | 1984 | |
| 1985 | 1985 | fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8, |
| 1986 | filename_name_only: []const u8) -> %void | |
| 1986 | filename_name_only: []const u8) %void | |
| 1987 | 1987 | { |
| 1988 | 1988 | const out_dir = os.path.dirname(output_path); |
| 1989 | 1989 | const out_basename = os.path.basename(output_path); |
std/c/darwin.zig+3-3| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | extern "c" fn __error() -> &c_int; | |
| 2 | pub extern "c" fn _NSGetExecutablePath(buf: &u8, bufsize: &u32) -> c_int; | |
| 1 | extern "c" fn __error() &c_int; | |
| 2 | pub extern "c" fn _NSGetExecutablePath(buf: &u8, bufsize: &u32) c_int; | |
| 3 | 3 | |
| 4 | 4 | |
| 5 | 5 | pub use @import("../os/darwin_errno.zig"); |
| ... | ... | @@ -41,7 +41,7 @@ pub const sigset_t = u32; |
| 41 | 41 | |
| 42 | 42 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. |
| 43 | 43 | pub const Sigaction = extern struct { |
| 44 | handler: extern fn(c_int), | |
| 44 | handler: extern fn(c_int)void, | |
| 45 | 45 | sa_mask: sigset_t, |
| 46 | 46 | sa_flags: c_int, |
| 47 | 47 | }; |
std/c/index.zig+37-37| ... | ... | @@ -9,43 +9,43 @@ pub use switch(builtin.os) { |
| 9 | 9 | }; |
| 10 | 10 | const empty_import = @import("../empty.zig"); |
| 11 | 11 | |
| 12 | pub extern "c" fn abort() -> noreturn; | |
| 13 | pub extern "c" fn exit(code: c_int) -> noreturn; | |
| 14 | pub extern "c" fn isatty(fd: c_int) -> c_int; | |
| 15 | pub extern "c" fn close(fd: c_int) -> c_int; | |
| 16 | pub extern "c" fn fstat(fd: c_int, buf: &Stat) -> c_int; | |
| 17 | pub extern "c" fn @"fstat$INODE64"(fd: c_int, buf: &Stat) -> c_int; | |
| 18 | pub extern "c" fn lseek(fd: c_int, offset: isize, whence: c_int) -> isize; | |
| 19 | pub extern "c" fn open(path: &const u8, oflag: c_int, ...) -> c_int; | |
| 20 | pub extern "c" fn raise(sig: c_int) -> c_int; | |
| 21 | pub extern "c" fn read(fd: c_int, buf: &c_void, nbyte: usize) -> isize; | |
| 22 | pub extern "c" fn stat(noalias path: &const u8, noalias buf: &Stat) -> c_int; | |
| 23 | pub extern "c" fn write(fd: c_int, buf: &const c_void, nbyte: usize) -> c_int; | |
| 12 | pub extern "c" fn abort() noreturn; | |
| 13 | pub extern "c" fn exit(code: c_int) noreturn; | |
| 14 | pub extern "c" fn isatty(fd: c_int) c_int; | |
| 15 | pub extern "c" fn close(fd: c_int) c_int; | |
| 16 | pub extern "c" fn fstat(fd: c_int, buf: &Stat) c_int; | |
| 17 | pub extern "c" fn @"fstat$INODE64"(fd: c_int, buf: &Stat) c_int; | |
| 18 | pub extern "c" fn lseek(fd: c_int, offset: isize, whence: c_int) isize; | |
| 19 | pub extern "c" fn open(path: &const u8, oflag: c_int, ...) c_int; | |
| 20 | pub extern "c" fn raise(sig: c_int) c_int; | |
| 21 | pub extern "c" fn read(fd: c_int, buf: &c_void, nbyte: usize) isize; | |
| 22 | pub extern "c" fn stat(noalias path: &const u8, noalias buf: &Stat) c_int; | |
| 23 | pub extern "c" fn write(fd: c_int, buf: &const c_void, nbyte: usize) c_int; | |
| 24 | 24 | pub extern "c" fn mmap(addr: ?&c_void, len: usize, prot: c_int, flags: c_int, |
| 25 | fd: c_int, offset: isize) -> ?&c_void; | |
| 26 | pub extern "c" fn munmap(addr: &c_void, len: usize) -> c_int; | |
| 27 | pub extern "c" fn unlink(path: &const u8) -> c_int; | |
| 28 | pub extern "c" fn getcwd(buf: &u8, size: usize) -> ?&u8; | |
| 29 | pub extern "c" fn waitpid(pid: c_int, stat_loc: &c_int, options: c_int) -> c_int; | |
| 30 | pub extern "c" fn fork() -> c_int; | |
| 31 | pub extern "c" fn pipe(fds: &c_int) -> c_int; | |
| 32 | pub extern "c" fn mkdir(path: &const u8, mode: c_uint) -> c_int; | |
| 33 | pub extern "c" fn symlink(existing: &const u8, new: &const u8) -> c_int; | |
| 34 | pub extern "c" fn rename(old: &const u8, new: &const u8) -> c_int; | |
| 35 | pub extern "c" fn chdir(path: &const u8) -> c_int; | |
| 25 | fd: c_int, offset: isize) ?&c_void; | |
| 26 | pub extern "c" fn munmap(addr: &c_void, len: usize) c_int; | |
| 27 | pub extern "c" fn unlink(path: &const u8) c_int; | |
| 28 | pub extern "c" fn getcwd(buf: &u8, size: usize) ?&u8; | |
| 29 | pub extern "c" fn waitpid(pid: c_int, stat_loc: &c_int, options: c_int) c_int; | |
| 30 | pub extern "c" fn fork() c_int; | |
| 31 | pub extern "c" fn pipe(fds: &c_int) c_int; | |
| 32 | pub extern "c" fn mkdir(path: &const u8, mode: c_uint) c_int; | |
| 33 | pub extern "c" fn symlink(existing: &const u8, new: &const u8) c_int; | |
| 34 | pub extern "c" fn rename(old: &const u8, new: &const u8) c_int; | |
| 35 | pub extern "c" fn chdir(path: &const u8) c_int; | |
| 36 | 36 | pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8, |
| 37 | envp: &const ?&const u8) -> c_int; | |
| 38 | pub extern "c" fn dup(fd: c_int) -> c_int; | |
| 39 | pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) -> c_int; | |
| 40 | pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: usize) -> isize; | |
| 41 | pub extern "c" fn realpath(noalias file_name: &const u8, noalias resolved_name: &u8) -> ?&u8; | |
| 42 | pub extern "c" fn sigprocmask(how: c_int, noalias set: &const sigset_t, noalias oset: ?&sigset_t) -> c_int; | |
| 43 | pub extern "c" fn sigaction(sig: c_int, noalias act: &const Sigaction, noalias oact: ?&Sigaction) -> c_int; | |
| 44 | pub extern "c" fn nanosleep(rqtp: &const timespec, rmtp: ?&timespec) -> c_int; | |
| 45 | pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) -> c_int; | |
| 46 | pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) -> c_int; | |
| 37 | envp: &const ?&const u8) c_int; | |
| 38 | pub extern "c" fn dup(fd: c_int) c_int; | |
| 39 | pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int; | |
| 40 | pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: usize) isize; | |
| 41 | pub extern "c" fn realpath(noalias file_name: &const u8, noalias resolved_name: &u8) ?&u8; | |
| 42 | pub extern "c" fn sigprocmask(how: c_int, noalias set: &const sigset_t, noalias oset: ?&sigset_t) c_int; | |
| 43 | pub extern "c" fn sigaction(sig: c_int, noalias act: &const Sigaction, noalias oact: ?&Sigaction) c_int; | |
| 44 | pub extern "c" fn nanosleep(rqtp: &const timespec, rmtp: ?&timespec) c_int; | |
| 45 | pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int; | |
| 46 | pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) c_int; | |
| 47 | 47 | |
| 48 | pub extern "c" fn malloc(usize) -> ?&c_void; | |
| 49 | pub extern "c" fn realloc(&c_void, usize) -> ?&c_void; | |
| 50 | pub extern "c" fn free(&c_void); | |
| 51 | pub extern "c" fn posix_memalign(memptr: &&c_void, alignment: usize, size: usize) -> c_int; | |
| 48 | pub extern "c" fn malloc(usize) ?&c_void; | |
| 49 | pub extern "c" fn realloc(&c_void, usize) ?&c_void; | |
| 50 | pub extern "c" fn free(&c_void) void; | |
| 51 | pub extern "c" fn posix_memalign(memptr: &&c_void, alignment: usize, size: usize) c_int; |
std/c/linux.zig+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | pub use @import("../os/linux_errno.zig"); |
| 2 | 2 | |
| 3 | pub extern "c" fn getrandom(buf_ptr: &u8, buf_len: usize, flags: c_uint) -> c_int; | |
| 4 | extern "c" fn __errno_location() -> &c_int; | |
| 3 | pub extern "c" fn getrandom(buf_ptr: &u8, buf_len: usize, flags: c_uint) c_int; | |
| 4 | extern "c" fn __errno_location() &c_int; | |
| 5 | 5 | pub const _errno = __errno_location; |
std/c/windows.zig+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | pub extern "c" fn _errno() -> &c_int; | |
| 1 | pub extern "c" fn _errno() &c_int; |
std/crypto/blake2.zig+15-15| ... | ... | @@ -9,7 +9,7 @@ const RoundParam = struct { |
| 9 | 9 | a: usize, b: usize, c: usize, d: usize, x: usize, y: usize, |
| 10 | 10 | }; |
| 11 | 11 | |
| 12 | fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) -> RoundParam { | |
| 12 | fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) RoundParam { | |
| 13 | 13 | return RoundParam { .a = a, .b = b, .c = c, .d = d, .x = x, .y = y, }; |
| 14 | 14 | } |
| 15 | 15 | |
| ... | ... | @@ -19,7 +19,7 @@ fn Rp(a: usize, b: usize, c: usize, d: usize, x: usize, y: usize) -> RoundParam |
| 19 | 19 | pub const Blake2s224 = Blake2s(224); |
| 20 | 20 | pub const Blake2s256 = Blake2s(256); |
| 21 | 21 | |
| 22 | fn Blake2s(comptime out_len: usize) -> type { return struct { | |
| 22 | fn Blake2s(comptime out_len: usize) type { return struct { | |
| 23 | 23 | const Self = this; |
| 24 | 24 | const block_size = 64; |
| 25 | 25 | const digest_size = out_len / 8; |
| ... | ... | @@ -48,7 +48,7 @@ fn Blake2s(comptime out_len: usize) -> type { return struct { |
| 48 | 48 | buf: [64]u8, |
| 49 | 49 | buf_len: u8, |
| 50 | 50 | |
| 51 | pub fn init() -> Self { | |
| 51 | pub fn init() Self { | |
| 52 | 52 | debug.assert(8 <= out_len and out_len <= 512); |
| 53 | 53 | |
| 54 | 54 | var s: Self = undefined; |
| ... | ... | @@ -56,7 +56,7 @@ fn Blake2s(comptime out_len: usize) -> type { return struct { |
| 56 | 56 | return s; |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | pub fn reset(d: &Self) { | |
| 59 | pub fn reset(d: &Self) void { | |
| 60 | 60 | mem.copy(u32, d.h[0..], iv[0..]); |
| 61 | 61 | |
| 62 | 62 | // No key plus default parameters |
| ... | ... | @@ -65,13 +65,13 @@ fn Blake2s(comptime out_len: usize) -> type { return struct { |
| 65 | 65 | d.buf_len = 0; |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | pub fn hash(b: []const u8, out: []u8) { | |
| 68 | pub fn hash(b: []const u8, out: []u8) void { | |
| 69 | 69 | var d = Self.init(); |
| 70 | 70 | d.update(b); |
| 71 | 71 | d.final(out); |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | pub fn update(d: &Self, b: []const u8) { | |
| 74 | pub fn update(d: &Self, b: []const u8) void { | |
| 75 | 75 | var off: usize = 0; |
| 76 | 76 | |
| 77 | 77 | // Partial buffer exists from previous update. Copy into buffer then hash. |
| ... | ... | @@ -94,7 +94,7 @@ fn Blake2s(comptime out_len: usize) -> type { return struct { |
| 94 | 94 | d.buf_len += u8(b[off..].len); |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | pub fn final(d: &Self, out: []u8) { | |
| 97 | pub fn final(d: &Self, out: []u8) void { | |
| 98 | 98 | debug.assert(out.len >= out_len / 8); |
| 99 | 99 | |
| 100 | 100 | mem.set(u8, d.buf[d.buf_len..], 0); |
| ... | ... | @@ -108,7 +108,7 @@ fn Blake2s(comptime out_len: usize) -> type { return struct { |
| 108 | 108 | } |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | fn round(d: &Self, b: []const u8, last: bool) { | |
| 111 | fn round(d: &Self, b: []const u8, last: bool) void { | |
| 112 | 112 | debug.assert(b.len == 64); |
| 113 | 113 | |
| 114 | 114 | var m: [16]u32 = undefined; |
| ... | ... | @@ -236,7 +236,7 @@ test "blake2s256 streaming" { |
| 236 | 236 | pub const Blake2b384 = Blake2b(384); |
| 237 | 237 | pub const Blake2b512 = Blake2b(512); |
| 238 | 238 | |
| 239 | fn Blake2b(comptime out_len: usize) -> type { return struct { | |
| 239 | fn Blake2b(comptime out_len: usize) type { return struct { | |
| 240 | 240 | const Self = this; |
| 241 | 241 | const block_size = 128; |
| 242 | 242 | const digest_size = out_len / 8; |
| ... | ... | @@ -269,7 +269,7 @@ fn Blake2b(comptime out_len: usize) -> type { return struct { |
| 269 | 269 | buf: [128]u8, |
| 270 | 270 | buf_len: u8, |
| 271 | 271 | |
| 272 | pub fn init() -> Self { | |
| 272 | pub fn init() Self { | |
| 273 | 273 | debug.assert(8 <= out_len and out_len <= 512); |
| 274 | 274 | |
| 275 | 275 | var s: Self = undefined; |
| ... | ... | @@ -277,7 +277,7 @@ fn Blake2b(comptime out_len: usize) -> type { return struct { |
| 277 | 277 | return s; |
| 278 | 278 | } |
| 279 | 279 | |
| 280 | pub fn reset(d: &Self) { | |
| 280 | pub fn reset(d: &Self) void { | |
| 281 | 281 | mem.copy(u64, d.h[0..], iv[0..]); |
| 282 | 282 | |
| 283 | 283 | // No key plus default parameters |
| ... | ... | @@ -286,13 +286,13 @@ fn Blake2b(comptime out_len: usize) -> type { return struct { |
| 286 | 286 | d.buf_len = 0; |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | pub fn hash(b: []const u8, out: []u8) { | |
| 289 | pub fn hash(b: []const u8, out: []u8) void { | |
| 290 | 290 | var d = Self.init(); |
| 291 | 291 | d.update(b); |
| 292 | 292 | d.final(out); |
| 293 | 293 | } |
| 294 | 294 | |
| 295 | pub fn update(d: &Self, b: []const u8) { | |
| 295 | pub fn update(d: &Self, b: []const u8) void { | |
| 296 | 296 | var off: usize = 0; |
| 297 | 297 | |
| 298 | 298 | // Partial buffer exists from previous update. Copy into buffer then hash. |
| ... | ... | @@ -315,7 +315,7 @@ fn Blake2b(comptime out_len: usize) -> type { return struct { |
| 315 | 315 | d.buf_len += u8(b[off..].len); |
| 316 | 316 | } |
| 317 | 317 | |
| 318 | pub fn final(d: &Self, out: []u8) { | |
| 318 | pub fn final(d: &Self, out: []u8) void { | |
| 319 | 319 | mem.set(u8, d.buf[d.buf_len..], 0); |
| 320 | 320 | d.t += d.buf_len; |
| 321 | 321 | d.round(d.buf[0..], true); |
| ... | ... | @@ -327,7 +327,7 @@ fn Blake2b(comptime out_len: usize) -> type { return struct { |
| 327 | 327 | } |
| 328 | 328 | } |
| 329 | 329 | |
| 330 | fn round(d: &Self, b: []const u8, last: bool) { | |
| 330 | fn round(d: &Self, b: []const u8, last: bool) void { | |
| 331 | 331 | debug.assert(b.len == 128); |
| 332 | 332 | |
| 333 | 333 | var m: [16]u64 = undefined; |
std/crypto/md5.zig+7-7| ... | ... | @@ -10,7 +10,7 @@ const RoundParam = struct { |
| 10 | 10 | k: usize, s: u32, t: u32 |
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) -> RoundParam { | |
| 13 | fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundParam { | |
| 14 | 14 | return RoundParam { .a = a, .b = b, .c = c, .d = d, .k = k, .s = s, .t = t }; |
| 15 | 15 | } |
| 16 | 16 | |
| ... | ... | @@ -25,13 +25,13 @@ pub const Md5 = struct { |
| 25 | 25 | buf_len: u8, |
| 26 | 26 | total_len: u64, |
| 27 | 27 | |
| 28 | pub fn init() -> Self { | |
| 28 | pub fn init() Self { | |
| 29 | 29 | var d: Self = undefined; |
| 30 | 30 | d.reset(); |
| 31 | 31 | return d; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | pub fn reset(d: &Self) { | |
| 34 | pub fn reset(d: &Self) void { | |
| 35 | 35 | d.s[0] = 0x67452301; |
| 36 | 36 | d.s[1] = 0xEFCDAB89; |
| 37 | 37 | d.s[2] = 0x98BADCFE; |
| ... | ... | @@ -40,13 +40,13 @@ pub const Md5 = struct { |
| 40 | 40 | d.total_len = 0; |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | pub fn hash(b: []const u8, out: []u8) { | |
| 43 | pub fn hash(b: []const u8, out: []u8) void { | |
| 44 | 44 | var d = Md5.init(); |
| 45 | 45 | d.update(b); |
| 46 | 46 | d.final(out); |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | pub fn update(d: &Self, b: []const u8) { | |
| 49 | pub fn update(d: &Self, b: []const u8) void { | |
| 50 | 50 | var off: usize = 0; |
| 51 | 51 | |
| 52 | 52 | // Partial buffer exists from previous update. Copy into buffer then hash. |
| ... | ... | @@ -71,7 +71,7 @@ pub const Md5 = struct { |
| 71 | 71 | d.total_len +%= b.len; |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | pub fn final(d: &Self, out: []u8) { | |
| 74 | pub fn final(d: &Self, out: []u8) void { | |
| 75 | 75 | debug.assert(out.len >= 16); |
| 76 | 76 | |
| 77 | 77 | // The buffer here will never be completely full. |
| ... | ... | @@ -103,7 +103,7 @@ pub const Md5 = struct { |
| 103 | 103 | } |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | fn round(d: &Self, b: []const u8) { | |
| 106 | fn round(d: &Self, b: []const u8) void { | |
| 107 | 107 | debug.assert(b.len == 64); |
| 108 | 108 | |
| 109 | 109 | var s: [16]u32 = undefined; |
std/crypto/sha1.zig+7-7| ... | ... | @@ -10,7 +10,7 @@ const RoundParam = struct { |
| 10 | 10 | a: usize, b: usize, c: usize, d: usize, e: usize, i: u32, |
| 11 | 11 | }; |
| 12 | 12 | |
| 13 | fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) -> RoundParam { | |
| 13 | fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam { | |
| 14 | 14 | return RoundParam { .a = a, .b = b, .c = c, .d = d, .e = e, .i = i }; |
| 15 | 15 | } |
| 16 | 16 | |
| ... | ... | @@ -25,13 +25,13 @@ pub const Sha1 = struct { |
| 25 | 25 | buf_len: u8, |
| 26 | 26 | total_len: u64, |
| 27 | 27 | |
| 28 | pub fn init() -> Self { | |
| 28 | pub fn init() Self { | |
| 29 | 29 | var d: Self = undefined; |
| 30 | 30 | d.reset(); |
| 31 | 31 | return d; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | pub fn reset(d: &Self) { | |
| 34 | pub fn reset(d: &Self) void { | |
| 35 | 35 | d.s[0] = 0x67452301; |
| 36 | 36 | d.s[1] = 0xEFCDAB89; |
| 37 | 37 | d.s[2] = 0x98BADCFE; |
| ... | ... | @@ -41,13 +41,13 @@ pub const Sha1 = struct { |
| 41 | 41 | d.total_len = 0; |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | pub fn hash(b: []const u8, out: []u8) { | |
| 44 | pub fn hash(b: []const u8, out: []u8) void { | |
| 45 | 45 | var d = Sha1.init(); |
| 46 | 46 | d.update(b); |
| 47 | 47 | d.final(out); |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | pub fn update(d: &Self, b: []const u8) { | |
| 50 | pub fn update(d: &Self, b: []const u8) void { | |
| 51 | 51 | var off: usize = 0; |
| 52 | 52 | |
| 53 | 53 | // Partial buffer exists from previous update. Copy into buffer then hash. |
| ... | ... | @@ -71,7 +71,7 @@ pub const Sha1 = struct { |
| 71 | 71 | d.total_len += b.len; |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | pub fn final(d: &Self, out: []u8) { | |
| 74 | pub fn final(d: &Self, out: []u8) void { | |
| 75 | 75 | debug.assert(out.len >= 20); |
| 76 | 76 | |
| 77 | 77 | // The buffer here will never be completely full. |
| ... | ... | @@ -103,7 +103,7 @@ pub const Sha1 = struct { |
| 103 | 103 | } |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | fn round(d: &Self, b: []const u8) { | |
| 106 | fn round(d: &Self, b: []const u8) void { | |
| 107 | 107 | debug.assert(b.len == 64); |
| 108 | 108 | |
| 109 | 109 | var s: [16]u32 = undefined; |
std/crypto/sha2.zig+16-16| ... | ... | @@ -13,7 +13,7 @@ const RoundParam256 = struct { |
| 13 | 13 | i: usize, k: u32, |
| 14 | 14 | }; |
| 15 | 15 | |
| 16 | fn Rp256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u32) -> RoundParam256 { | |
| 16 | fn Rp256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u32) RoundParam256 { | |
| 17 | 17 | return RoundParam256 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k }; |
| 18 | 18 | } |
| 19 | 19 | |
| ... | ... | @@ -56,7 +56,7 @@ const Sha256Params = Sha2Params32 { |
| 56 | 56 | pub const Sha224 = Sha2_32(Sha224Params); |
| 57 | 57 | pub const Sha256 = Sha2_32(Sha256Params); |
| 58 | 58 | |
| 59 | fn Sha2_32(comptime params: Sha2Params32) -> type { return struct { | |
| 59 | fn Sha2_32(comptime params: Sha2Params32) type { return struct { | |
| 60 | 60 | const Self = this; |
| 61 | 61 | const block_size = 64; |
| 62 | 62 | const digest_size = params.out_len / 8; |
| ... | ... | @@ -67,13 +67,13 @@ fn Sha2_32(comptime params: Sha2Params32) -> type { return struct { |
| 67 | 67 | buf_len: u8, |
| 68 | 68 | total_len: u64, |
| 69 | 69 | |
| 70 | pub fn init() -> Self { | |
| 70 | pub fn init() Self { | |
| 71 | 71 | var d: Self = undefined; |
| 72 | 72 | d.reset(); |
| 73 | 73 | return d; |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | pub fn reset(d: &Self) { | |
| 76 | pub fn reset(d: &Self) void { | |
| 77 | 77 | d.s[0] = params.iv0; |
| 78 | 78 | d.s[1] = params.iv1; |
| 79 | 79 | d.s[2] = params.iv2; |
| ... | ... | @@ -86,13 +86,13 @@ fn Sha2_32(comptime params: Sha2Params32) -> type { return struct { |
| 86 | 86 | d.total_len = 0; |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | pub fn hash(b: []const u8, out: []u8) { | |
| 89 | pub fn hash(b: []const u8, out: []u8) void { | |
| 90 | 90 | var d = Self.init(); |
| 91 | 91 | d.update(b); |
| 92 | 92 | d.final(out); |
| 93 | 93 | } |
| 94 | 94 | |
| 95 | pub fn update(d: &Self, b: []const u8) { | |
| 95 | pub fn update(d: &Self, b: []const u8) void { | |
| 96 | 96 | var off: usize = 0; |
| 97 | 97 | |
| 98 | 98 | // Partial buffer exists from previous update. Copy into buffer then hash. |
| ... | ... | @@ -116,7 +116,7 @@ fn Sha2_32(comptime params: Sha2Params32) -> type { return struct { |
| 116 | 116 | d.total_len += b.len; |
| 117 | 117 | } |
| 118 | 118 | |
| 119 | pub fn final(d: &Self, out: []u8) { | |
| 119 | pub fn final(d: &Self, out: []u8) void { | |
| 120 | 120 | debug.assert(out.len >= params.out_len / 8); |
| 121 | 121 | |
| 122 | 122 | // The buffer here will never be completely full. |
| ... | ... | @@ -151,7 +151,7 @@ fn Sha2_32(comptime params: Sha2Params32) -> type { return struct { |
| 151 | 151 | } |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | fn round(d: &Self, b: []const u8) { | |
| 154 | fn round(d: &Self, b: []const u8) void { | |
| 155 | 155 | debug.assert(b.len == 64); |
| 156 | 156 | |
| 157 | 157 | var s: [64]u32 = undefined; |
| ... | ... | @@ -329,7 +329,7 @@ const RoundParam512 = struct { |
| 329 | 329 | i: usize, k: u64, |
| 330 | 330 | }; |
| 331 | 331 | |
| 332 | fn Rp512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) -> RoundParam512 { | |
| 332 | fn Rp512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) RoundParam512 { | |
| 333 | 333 | return RoundParam512 { .a = a, .b = b, .c = c, .d = d, .e = e, .f = f, .g = g, .h = h, .i = i, .k = k }; |
| 334 | 334 | } |
| 335 | 335 | |
| ... | ... | @@ -372,7 +372,7 @@ const Sha512Params = Sha2Params64 { |
| 372 | 372 | pub const Sha384 = Sha2_64(Sha384Params); |
| 373 | 373 | pub const Sha512 = Sha2_64(Sha512Params); |
| 374 | 374 | |
| 375 | fn Sha2_64(comptime params: Sha2Params64) -> type { return struct { | |
| 375 | fn Sha2_64(comptime params: Sha2Params64) type { return struct { | |
| 376 | 376 | const Self = this; |
| 377 | 377 | const block_size = 128; |
| 378 | 378 | const digest_size = params.out_len / 8; |
| ... | ... | @@ -383,13 +383,13 @@ fn Sha2_64(comptime params: Sha2Params64) -> type { return struct { |
| 383 | 383 | buf_len: u8, |
| 384 | 384 | total_len: u128, |
| 385 | 385 | |
| 386 | pub fn init() -> Self { | |
| 386 | pub fn init() Self { | |
| 387 | 387 | var d: Self = undefined; |
| 388 | 388 | d.reset(); |
| 389 | 389 | return d; |
| 390 | 390 | } |
| 391 | 391 | |
| 392 | pub fn reset(d: &Self) { | |
| 392 | pub fn reset(d: &Self) void { | |
| 393 | 393 | d.s[0] = params.iv0; |
| 394 | 394 | d.s[1] = params.iv1; |
| 395 | 395 | d.s[2] = params.iv2; |
| ... | ... | @@ -402,13 +402,13 @@ fn Sha2_64(comptime params: Sha2Params64) -> type { return struct { |
| 402 | 402 | d.total_len = 0; |
| 403 | 403 | } |
| 404 | 404 | |
| 405 | pub fn hash(b: []const u8, out: []u8) { | |
| 405 | pub fn hash(b: []const u8, out: []u8) void { | |
| 406 | 406 | var d = Self.init(); |
| 407 | 407 | d.update(b); |
| 408 | 408 | d.final(out); |
| 409 | 409 | } |
| 410 | 410 | |
| 411 | pub fn update(d: &Self, b: []const u8) { | |
| 411 | pub fn update(d: &Self, b: []const u8) void { | |
| 412 | 412 | var off: usize = 0; |
| 413 | 413 | |
| 414 | 414 | // Partial buffer exists from previous update. Copy into buffer then hash. |
| ... | ... | @@ -432,7 +432,7 @@ fn Sha2_64(comptime params: Sha2Params64) -> type { return struct { |
| 432 | 432 | d.total_len += b.len; |
| 433 | 433 | } |
| 434 | 434 | |
| 435 | pub fn final(d: &Self, out: []u8) { | |
| 435 | pub fn final(d: &Self, out: []u8) void { | |
| 436 | 436 | debug.assert(out.len >= params.out_len / 8); |
| 437 | 437 | |
| 438 | 438 | // The buffer here will never be completely full. |
| ... | ... | @@ -467,7 +467,7 @@ fn Sha2_64(comptime params: Sha2Params64) -> type { return struct { |
| 467 | 467 | } |
| 468 | 468 | } |
| 469 | 469 | |
| 470 | fn round(d: &Self, b: []const u8) { | |
| 470 | fn round(d: &Self, b: []const u8) void { | |
| 471 | 471 | debug.assert(b.len == 128); |
| 472 | 472 | |
| 473 | 473 | var s: [80]u64 = undefined; |
std/crypto/sha3.zig+7-7| ... | ... | @@ -10,7 +10,7 @@ pub const Sha3_256 = Keccak(256, 0x06); |
| 10 | 10 | pub const Sha3_384 = Keccak(384, 0x06); |
| 11 | 11 | pub const Sha3_512 = Keccak(512, 0x06); |
| 12 | 12 | |
| 13 | fn Keccak(comptime bits: usize, comptime delim: u8) -> type { return struct { | |
| 13 | fn Keccak(comptime bits: usize, comptime delim: u8) type { return struct { | |
| 14 | 14 | const Self = this; |
| 15 | 15 | const block_size = 200; |
| 16 | 16 | const digest_size = bits / 8; |
| ... | ... | @@ -19,25 +19,25 @@ fn Keccak(comptime bits: usize, comptime delim: u8) -> type { return struct { |
| 19 | 19 | offset: usize, |
| 20 | 20 | rate: usize, |
| 21 | 21 | |
| 22 | pub fn init() -> Self { | |
| 22 | pub fn init() Self { | |
| 23 | 23 | var d: Self = undefined; |
| 24 | 24 | d.reset(); |
| 25 | 25 | return d; |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | pub fn reset(d: &Self) { | |
| 28 | pub fn reset(d: &Self) void { | |
| 29 | 29 | mem.set(u8, d.s[0..], 0); |
| 30 | 30 | d.offset = 0; |
| 31 | 31 | d.rate = 200 - (bits / 4); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | pub fn hash(b: []const u8, out: []u8) { | |
| 34 | pub fn hash(b: []const u8, out: []u8) void { | |
| 35 | 35 | var d = Self.init(); |
| 36 | 36 | d.update(b); |
| 37 | 37 | d.final(out); |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | pub fn update(d: &Self, b: []const u8) { | |
| 40 | pub fn update(d: &Self, b: []const u8) void { | |
| 41 | 41 | var ip: usize = 0; |
| 42 | 42 | var len = b.len; |
| 43 | 43 | var rate = d.rate - d.offset; |
| ... | ... | @@ -62,7 +62,7 @@ fn Keccak(comptime bits: usize, comptime delim: u8) -> type { return struct { |
| 62 | 62 | d.offset = offset + len; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | pub fn final(d: &Self, out: []u8) { | |
| 65 | pub fn final(d: &Self, out: []u8) void { | |
| 66 | 66 | // padding |
| 67 | 67 | d.s[d.offset] ^= delim; |
| 68 | 68 | d.s[d.rate - 1] ^= 0x80; |
| ... | ... | @@ -109,7 +109,7 @@ const M5 = []const usize { |
| 109 | 109 | 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 |
| 110 | 110 | }; |
| 111 | 111 | |
| 112 | fn keccak_f(comptime F: usize, d: []u8) { | |
| 112 | fn keccak_f(comptime F: usize, d: []u8) void { | |
| 113 | 113 | debug.assert(d.len == F / 8); |
| 114 | 114 | |
| 115 | 115 | const B = F / 25; |
std/crypto/test.zig+2-2| ... | ... | @@ -3,7 +3,7 @@ const mem = @import("../mem.zig"); |
| 3 | 3 | const fmt = @import("../fmt/index.zig"); |
| 4 | 4 | |
| 5 | 5 | // Hash using the specified hasher `H` asserting `expected == H(input)`. |
| 6 | pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, input: []const u8) { | |
| 6 | pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, input: []const u8) void { | |
| 7 | 7 | var h: [expected.len / 2]u8 = undefined; |
| 8 | 8 | Hasher.hash(input, h[0..]); |
| 9 | 9 | |
| ... | ... | @@ -11,7 +11,7 @@ pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, inpu |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | 13 | // Assert `expected` == `input` where `input` is a bytestring. |
| 14 | pub fn assertEqual(comptime expected: []const u8, input: []const u8) { | |
| 14 | pub fn assertEqual(comptime expected: []const u8, input: []const u8) void { | |
| 15 | 15 | var expected_bytes: [expected.len / 2]u8 = undefined; |
| 16 | 16 | for (expected_bytes) |*r, i| { |
| 17 | 17 | *r = fmt.parseInt(u8, expected[2*i .. 2*i+2], 16) catch unreachable; |
std/crypto/throughput_test.zig+1-1| ... | ... | @@ -18,7 +18,7 @@ const c = @cImport({ |
| 18 | 18 | |
| 19 | 19 | const Mb = 1024 * 1024; |
| 20 | 20 | |
| 21 | pub fn main() -> %void { | |
| 21 | pub fn main() %void { | |
| 22 | 22 | var stdout_file = try std.io.getStdOut(); |
| 23 | 23 | var stdout_out_stream = std.io.FileOutStream.init(&stdout_file); |
| 24 | 24 | const stdout = &stdout_out_stream.stream; |
std/cstr.zig+9-9| ... | ... | @@ -3,13 +3,13 @@ const debug = std.debug; |
| 3 | 3 | const mem = std.mem; |
| 4 | 4 | const assert = debug.assert; |
| 5 | 5 | |
| 6 | pub fn len(ptr: &const u8) -> usize { | |
| 6 | pub fn len(ptr: &const u8) usize { | |
| 7 | 7 | var count: usize = 0; |
| 8 | 8 | while (ptr[count] != 0) : (count += 1) {} |
| 9 | 9 | return count; |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | pub fn cmp(a: &const u8, b: &const u8) -> i8 { | |
| 12 | pub fn cmp(a: &const u8, b: &const u8) i8 { | |
| 13 | 13 | var index: usize = 0; |
| 14 | 14 | while (a[index] == b[index] and a[index] != 0) : (index += 1) {} |
| 15 | 15 | if (a[index] > b[index]) { |
| ... | ... | @@ -21,11 +21,11 @@ pub fn cmp(a: &const u8, b: &const u8) -> i8 { |
| 21 | 21 | } |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | pub fn toSliceConst(str: &const u8) -> []const u8 { | |
| 24 | pub fn toSliceConst(str: &const u8) []const u8 { | |
| 25 | 25 | return str[0..len(str)]; |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | pub fn toSlice(str: &u8) -> []u8 { | |
| 28 | pub fn toSlice(str: &u8) []u8 { | |
| 29 | 29 | return str[0..len(str)]; |
| 30 | 30 | } |
| 31 | 31 | |
| ... | ... | @@ -34,7 +34,7 @@ test "cstr fns" { |
| 34 | 34 | testCStrFnsImpl(); |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | fn testCStrFnsImpl() { | |
| 37 | fn testCStrFnsImpl() void { | |
| 38 | 38 | assert(cmp(c"aoeu", c"aoez") == -1); |
| 39 | 39 | assert(len(c"123456789") == 9); |
| 40 | 40 | } |
| ... | ... | @@ -42,7 +42,7 @@ fn testCStrFnsImpl() { |
| 42 | 42 | /// Returns a mutable slice with exactly the same size which is guaranteed to |
| 43 | 43 | /// have a null byte after it. |
| 44 | 44 | /// Caller owns the returned memory. |
| 45 | pub fn addNullByte(allocator: &mem.Allocator, slice: []const u8) -> %[]u8 { | |
| 45 | pub fn addNullByte(allocator: &mem.Allocator, slice: []const u8) %[]u8 { | |
| 46 | 46 | const result = try allocator.alloc(u8, slice.len + 1); |
| 47 | 47 | mem.copy(u8, result, slice); |
| 48 | 48 | result[slice.len] = 0; |
| ... | ... | @@ -56,7 +56,7 @@ pub const NullTerminated2DArray = struct { |
| 56 | 56 | |
| 57 | 57 | /// Takes N lists of strings, concatenates the lists together, and adds a null terminator |
| 58 | 58 | /// Caller must deinit result |
| 59 | pub fn fromSlices(allocator: &mem.Allocator, slices: []const []const []const u8) -> %NullTerminated2DArray { | |
| 59 | pub fn fromSlices(allocator: &mem.Allocator, slices: []const []const []const u8) %NullTerminated2DArray { | |
| 60 | 60 | var new_len: usize = 1; // 1 for the list null |
| 61 | 61 | var byte_count: usize = 0; |
| 62 | 62 | for (slices) |slice| { |
| ... | ... | @@ -71,7 +71,7 @@ pub const NullTerminated2DArray = struct { |
| 71 | 71 | byte_count += index_size; |
| 72 | 72 | |
| 73 | 73 | const buf = try allocator.alignedAlloc(u8, @alignOf(?&u8), byte_count); |
| 74 | %defer allocator.free(buf); | |
| 74 | errdefer allocator.free(buf); | |
| 75 | 75 | |
| 76 | 76 | var write_index = index_size; |
| 77 | 77 | const index_buf = ([]?&u8)(buf); |
| ... | ... | @@ -96,7 +96,7 @@ pub const NullTerminated2DArray = struct { |
| 96 | 96 | }; |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | pub fn deinit(self: &NullTerminated2DArray) { | |
| 99 | pub fn deinit(self: &NullTerminated2DArray) void { | |
| 100 | 100 | const buf = @ptrCast(&u8, self.ptr); |
| 101 | 101 | self.allocator.free(buf[0..self.byte_count]); |
| 102 | 102 | } |
std/debug/failing_allocator.zig+4-4| ... | ... | @@ -12,7 +12,7 @@ pub const FailingAllocator = struct { |
| 12 | 12 | freed_bytes: usize, |
| 13 | 13 | deallocations: usize, |
| 14 | 14 | |
| 15 | pub fn init(allocator: &mem.Allocator, fail_index: usize) -> FailingAllocator { | |
| 15 | pub fn init(allocator: &mem.Allocator, fail_index: usize) FailingAllocator { | |
| 16 | 16 | return FailingAllocator { |
| 17 | 17 | .internal_allocator = allocator, |
| 18 | 18 | .fail_index = fail_index, |
| ... | ... | @@ -28,7 +28,7 @@ pub const FailingAllocator = struct { |
| 28 | 28 | }; |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | fn alloc(allocator: &mem.Allocator, n: usize, alignment: u29) -> %[]u8 { | |
| 31 | fn alloc(allocator: &mem.Allocator, n: usize, alignment: u29) %[]u8 { | |
| 32 | 32 | const self = @fieldParentPtr(FailingAllocator, "allocator", allocator); |
| 33 | 33 | if (self.index == self.fail_index) { |
| 34 | 34 | return error.OutOfMemory; |
| ... | ... | @@ -39,7 +39,7 @@ pub const FailingAllocator = struct { |
| 39 | 39 | return result; |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | fn realloc(allocator: &mem.Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 { | |
| 42 | fn realloc(allocator: &mem.Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 { | |
| 43 | 43 | const self = @fieldParentPtr(FailingAllocator, "allocator", allocator); |
| 44 | 44 | if (new_size <= old_mem.len) { |
| 45 | 45 | self.freed_bytes += old_mem.len - new_size; |
| ... | ... | @@ -55,7 +55,7 @@ pub const FailingAllocator = struct { |
| 55 | 55 | return result; |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | fn free(allocator: &mem.Allocator, bytes: []u8) { | |
| 58 | fn free(allocator: &mem.Allocator, bytes: []u8) void { | |
| 59 | 59 | const self = @fieldParentPtr(FailingAllocator, "allocator", allocator); |
| 60 | 60 | self.freed_bytes += bytes.len; |
| 61 | 61 | self.deallocations += 1; |
std/debug/index.zig+51-51| ... | ... | @@ -25,11 +25,11 @@ error TodoSupportCOFFDebugInfo; |
| 25 | 25 | var stderr_file: io.File = undefined; |
| 26 | 26 | var stderr_file_out_stream: io.FileOutStream = undefined; |
| 27 | 27 | var stderr_stream: ?&io.OutStream = null; |
| 28 | pub fn warn(comptime fmt: []const u8, args: ...) { | |
| 28 | pub fn warn(comptime fmt: []const u8, args: ...) void { | |
| 29 | 29 | const stderr = getStderrStream() catch return; |
| 30 | 30 | stderr.print(fmt, args) catch return; |
| 31 | 31 | } |
| 32 | fn getStderrStream() -> %&io.OutStream { | |
| 32 | fn getStderrStream() %&io.OutStream { | |
| 33 | 33 | if (stderr_stream) |st| { |
| 34 | 34 | return st; |
| 35 | 35 | } else { |
| ... | ... | @@ -42,7 +42,7 @@ fn getStderrStream() -> %&io.OutStream { |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | var self_debug_info: ?&ElfStackTrace = null; |
| 45 | pub fn getSelfDebugInfo() -> %&ElfStackTrace { | |
| 45 | pub fn getSelfDebugInfo() %&ElfStackTrace { | |
| 46 | 46 | if (self_debug_info) |info| { |
| 47 | 47 | return info; |
| 48 | 48 | } else { |
| ... | ... | @@ -53,7 +53,7 @@ pub fn getSelfDebugInfo() -> %&ElfStackTrace { |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | 55 | /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. |
| 56 | pub fn dumpCurrentStackTrace() { | |
| 56 | pub fn dumpCurrentStackTrace() void { | |
| 57 | 57 | const stderr = getStderrStream() catch return; |
| 58 | 58 | const debug_info = getSelfDebugInfo() catch |err| { |
| 59 | 59 | stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return; |
| ... | ... | @@ -67,7 +67,7 @@ pub fn dumpCurrentStackTrace() { |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | 69 | /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. |
| 70 | pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) { | |
| 70 | pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) void { | |
| 71 | 71 | const stderr = getStderrStream() catch return; |
| 72 | 72 | const debug_info = getSelfDebugInfo() catch |err| { |
| 73 | 73 | stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return; |
| ... | ... | @@ -85,7 +85,7 @@ pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) { |
| 85 | 85 | /// generated, and the `unreachable` statement triggers a panic. |
| 86 | 86 | /// In ReleaseFast and ReleaseSmall modes, calls to this function can be |
| 87 | 87 | /// optimized away. |
| 88 | pub fn assert(ok: bool) { | |
| 88 | pub fn assert(ok: bool) void { | |
| 89 | 89 | if (!ok) { |
| 90 | 90 | // In ReleaseFast test mode, we still want assert(false) to crash, so |
| 91 | 91 | // we insert an explicit call to @panic instead of unreachable. |
| ... | ... | @@ -100,7 +100,7 @@ pub fn assert(ok: bool) { |
| 100 | 100 | |
| 101 | 101 | /// Call this function when you want to panic if the condition is not true. |
| 102 | 102 | /// If `ok` is `false`, this function will panic in every release mode. |
| 103 | pub fn assertOrPanic(ok: bool) { | |
| 103 | pub fn assertOrPanic(ok: bool) void { | |
| 104 | 104 | if (!ok) { |
| 105 | 105 | @panic("assertion failure"); |
| 106 | 106 | } |
| ... | ... | @@ -108,7 +108,7 @@ pub fn assertOrPanic(ok: bool) { |
| 108 | 108 | |
| 109 | 109 | var panicking = false; |
| 110 | 110 | /// This is the default panic implementation. |
| 111 | pub fn panic(comptime format: []const u8, args: ...) -> noreturn { | |
| 111 | pub fn panic(comptime format: []const u8, args: ...) noreturn { | |
| 112 | 112 | // TODO an intrinsic that labels this as unlikely to be reached |
| 113 | 113 | |
| 114 | 114 | // TODO |
| ... | ... | @@ -130,7 +130,7 @@ pub fn panic(comptime format: []const u8, args: ...) -> noreturn { |
| 130 | 130 | os.abort(); |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | pub fn panicWithTrace(trace: &const builtin.StackTrace, comptime format: []const u8, args: ...) -> noreturn { | |
| 133 | pub fn panicWithTrace(trace: &const builtin.StackTrace, comptime format: []const u8, args: ...) noreturn { | |
| 134 | 134 | if (panicking) { |
| 135 | 135 | os.abort(); |
| 136 | 136 | } else { |
| ... | ... | @@ -153,7 +153,7 @@ error PathNotFound; |
| 153 | 153 | error InvalidDebugInfo; |
| 154 | 154 | |
| 155 | 155 | pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator, |
| 156 | debug_info: &ElfStackTrace, tty_color: bool) -> %void | |
| 156 | debug_info: &ElfStackTrace, tty_color: bool) %void | |
| 157 | 157 | { |
| 158 | 158 | var frame_index: usize = undefined; |
| 159 | 159 | var frames_left: usize = undefined; |
| ... | ... | @@ -175,7 +175,7 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.O |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | 177 | pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, |
| 178 | debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) -> %void | |
| 178 | debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) %void | |
| 179 | 179 | { |
| 180 | 180 | var ignored_count: usize = 0; |
| 181 | 181 | |
| ... | ... | @@ -191,7 +191,7 @@ pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocat |
| 191 | 191 | } |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) -> %void { | |
| 194 | fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) %void { | |
| 195 | 195 | if (builtin.os == builtin.Os.windows) { |
| 196 | 196 | return error.UnsupportedDebugInfo; |
| 197 | 197 | } |
| ... | ... | @@ -232,7 +232,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, a |
| 232 | 232 | } |
| 233 | 233 | } |
| 234 | 234 | |
| 235 | pub fn openSelfDebugInfo(allocator: &mem.Allocator) -> %&ElfStackTrace { | |
| 235 | pub fn openSelfDebugInfo(allocator: &mem.Allocator) %&ElfStackTrace { | |
| 236 | 236 | switch (builtin.object_format) { |
| 237 | 237 | builtin.ObjectFormat.elf => { |
| 238 | 238 | const st = try allocator.create(ElfStackTrace); |
| ... | ... | @@ -248,10 +248,10 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) -> %&ElfStackTrace { |
| 248 | 248 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), |
| 249 | 249 | }; |
| 250 | 250 | st.self_exe_file = try os.openSelfExe(); |
| 251 | %defer st.self_exe_file.close(); | |
| 251 | errdefer st.self_exe_file.close(); | |
| 252 | 252 | |
| 253 | 253 | try st.elf.openFile(allocator, &st.self_exe_file); |
| 254 | %defer st.elf.close(); | |
| 254 | errdefer st.elf.close(); | |
| 255 | 255 | |
| 256 | 256 | st.debug_info = (try st.elf.findSection(".debug_info")) ?? return error.MissingDebugInfo; |
| 257 | 257 | st.debug_abbrev = (try st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; |
| ... | ... | @@ -276,7 +276,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) -> %&ElfStackTrace { |
| 276 | 276 | } |
| 277 | 277 | } |
| 278 | 278 | |
| 279 | fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_info: &const LineInfo) -> %void { | |
| 279 | fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_info: &const LineInfo) %void { | |
| 280 | 280 | var f = try io.File.openRead(line_info.file_name, allocator); |
| 281 | 281 | defer f.close(); |
| 282 | 282 | // TODO fstat and make sure that the file has the correct size |
| ... | ... | @@ -320,17 +320,17 @@ pub const ElfStackTrace = struct { |
| 320 | 320 | abbrev_table_list: ArrayList(AbbrevTableHeader), |
| 321 | 321 | compile_unit_list: ArrayList(CompileUnit), |
| 322 | 322 | |
| 323 | pub fn allocator(self: &const ElfStackTrace) -> &mem.Allocator { | |
| 323 | pub fn allocator(self: &const ElfStackTrace) &mem.Allocator { | |
| 324 | 324 | return self.abbrev_table_list.allocator; |
| 325 | 325 | } |
| 326 | 326 | |
| 327 | pub fn readString(self: &ElfStackTrace) -> %[]u8 { | |
| 327 | pub fn readString(self: &ElfStackTrace) %[]u8 { | |
| 328 | 328 | var in_file_stream = io.FileInStream.init(&self.self_exe_file); |
| 329 | 329 | const in_stream = &in_file_stream.stream; |
| 330 | 330 | return readStringRaw(self.allocator(), in_stream); |
| 331 | 331 | } |
| 332 | 332 | |
| 333 | pub fn close(self: &ElfStackTrace) { | |
| 333 | pub fn close(self: &ElfStackTrace) void { | |
| 334 | 334 | self.self_exe_file.close(); |
| 335 | 335 | self.elf.close(); |
| 336 | 336 | } |
| ... | ... | @@ -387,7 +387,7 @@ const Constant = struct { |
| 387 | 387 | payload: []u8, |
| 388 | 388 | signed: bool, |
| 389 | 389 | |
| 390 | fn asUnsignedLe(self: &const Constant) -> %u64 { | |
| 390 | fn asUnsignedLe(self: &const Constant) %u64 { | |
| 391 | 391 | if (self.payload.len > @sizeOf(u64)) |
| 392 | 392 | return error.InvalidDebugInfo; |
| 393 | 393 | if (self.signed) |
| ... | ... | @@ -406,7 +406,7 @@ const Die = struct { |
| 406 | 406 | value: FormValue, |
| 407 | 407 | }; |
| 408 | 408 | |
| 409 | fn getAttr(self: &const Die, id: u64) -> ?&const FormValue { | |
| 409 | fn getAttr(self: &const Die, id: u64) ?&const FormValue { | |
| 410 | 410 | for (self.attrs.toSliceConst()) |*attr| { |
| 411 | 411 | if (attr.id == id) |
| 412 | 412 | return &attr.value; |
| ... | ... | @@ -414,7 +414,7 @@ const Die = struct { |
| 414 | 414 | return null; |
| 415 | 415 | } |
| 416 | 416 | |
| 417 | fn getAttrAddr(self: &const Die, id: u64) -> %u64 { | |
| 417 | fn getAttrAddr(self: &const Die, id: u64) %u64 { | |
| 418 | 418 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 419 | 419 | return switch (*form_value) { |
| 420 | 420 | FormValue.Address => |value| value, |
| ... | ... | @@ -422,7 +422,7 @@ const Die = struct { |
| 422 | 422 | }; |
| 423 | 423 | } |
| 424 | 424 | |
| 425 | fn getAttrSecOffset(self: &const Die, id: u64) -> %u64 { | |
| 425 | fn getAttrSecOffset(self: &const Die, id: u64) %u64 { | |
| 426 | 426 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 427 | 427 | return switch (*form_value) { |
| 428 | 428 | FormValue.Const => |value| value.asUnsignedLe(), |
| ... | ... | @@ -431,7 +431,7 @@ const Die = struct { |
| 431 | 431 | }; |
| 432 | 432 | } |
| 433 | 433 | |
| 434 | fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 { | |
| 434 | fn getAttrUnsignedLe(self: &const Die, id: u64) %u64 { | |
| 435 | 435 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 436 | 436 | return switch (*form_value) { |
| 437 | 437 | FormValue.Const => |value| value.asUnsignedLe(), |
| ... | ... | @@ -439,7 +439,7 @@ const Die = struct { |
| 439 | 439 | }; |
| 440 | 440 | } |
| 441 | 441 | |
| 442 | fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) -> %[]u8 { | |
| 442 | fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) %[]u8 { | |
| 443 | 443 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 444 | 444 | return switch (*form_value) { |
| 445 | 445 | FormValue.String => |value| value, |
| ... | ... | @@ -462,7 +462,7 @@ const LineInfo = struct { |
| 462 | 462 | file_name: []u8, |
| 463 | 463 | allocator: &mem.Allocator, |
| 464 | 464 | |
| 465 | fn deinit(self: &const LineInfo) { | |
| 465 | fn deinit(self: &const LineInfo) void { | |
| 466 | 466 | self.allocator.free(self.file_name); |
| 467 | 467 | } |
| 468 | 468 | }; |
| ... | ... | @@ -489,7 +489,7 @@ const LineNumberProgram = struct { |
| 489 | 489 | prev_end_sequence: bool, |
| 490 | 490 | |
| 491 | 491 | pub fn init(is_stmt: bool, include_dirs: []const []const u8, |
| 492 | file_entries: &ArrayList(FileEntry), target_address: usize) -> LineNumberProgram | |
| 492 | file_entries: &ArrayList(FileEntry), target_address: usize) LineNumberProgram | |
| 493 | 493 | { |
| 494 | 494 | return LineNumberProgram { |
| 495 | 495 | .address = 0, |
| ... | ... | @@ -512,7 +512,7 @@ const LineNumberProgram = struct { |
| 512 | 512 | }; |
| 513 | 513 | } |
| 514 | 514 | |
| 515 | pub fn checkLineMatch(self: &LineNumberProgram) -> %?LineInfo { | |
| 515 | pub fn checkLineMatch(self: &LineNumberProgram) %?LineInfo { | |
| 516 | 516 | if (self.target_address >= self.prev_address and self.target_address < self.address) { |
| 517 | 517 | const file_entry = if (self.prev_file == 0) { |
| 518 | 518 | return error.MissingDebugInfo; |
| ... | ... | @@ -524,7 +524,7 @@ const LineNumberProgram = struct { |
| 524 | 524 | return error.InvalidDebugInfo; |
| 525 | 525 | } else self.include_dirs[file_entry.dir_index]; |
| 526 | 526 | const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name); |
| 527 | %defer self.file_entries.allocator.free(file_name); | |
| 527 | errdefer self.file_entries.allocator.free(file_name); | |
| 528 | 528 | return LineInfo { |
| 529 | 529 | .line = if (self.prev_line >= 0) usize(self.prev_line) else 0, |
| 530 | 530 | .column = self.prev_column, |
| ... | ... | @@ -544,7 +544,7 @@ const LineNumberProgram = struct { |
| 544 | 544 | } |
| 545 | 545 | }; |
| 546 | 546 | |
| 547 | fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) -> %[]u8 { | |
| 547 | fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) %[]u8 { | |
| 548 | 548 | var buf = ArrayList(u8).init(allocator); |
| 549 | 549 | while (true) { |
| 550 | 550 | const byte = try in_stream.readByte(); |
| ... | ... | @@ -555,58 +555,58 @@ fn readStringRaw(allocator: &mem.Allocator, in_stream: &io.InStream) -> %[]u8 { |
| 555 | 555 | return buf.toSlice(); |
| 556 | 556 | } |
| 557 | 557 | |
| 558 | fn getString(st: &ElfStackTrace, offset: u64) -> %[]u8 { | |
| 558 | fn getString(st: &ElfStackTrace, offset: u64) %[]u8 { | |
| 559 | 559 | const pos = st.debug_str.offset + offset; |
| 560 | 560 | try st.self_exe_file.seekTo(pos); |
| 561 | 561 | return st.readString(); |
| 562 | 562 | } |
| 563 | 563 | |
| 564 | fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %[]u8 { | |
| 564 | fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %[]u8 { | |
| 565 | 565 | const buf = try global_allocator.alloc(u8, size); |
| 566 | %defer global_allocator.free(buf); | |
| 566 | errdefer global_allocator.free(buf); | |
| 567 | 567 | if ((try in_stream.read(buf)) < size) return error.EndOfFile; |
| 568 | 568 | return buf; |
| 569 | 569 | } |
| 570 | 570 | |
| 571 | fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | |
| 571 | fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue { | |
| 572 | 572 | const buf = try readAllocBytes(allocator, in_stream, size); |
| 573 | 573 | return FormValue { .Block = buf }; |
| 574 | 574 | } |
| 575 | 575 | |
| 576 | fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | |
| 576 | fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue { | |
| 577 | 577 | const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size); |
| 578 | 578 | return parseFormValueBlockLen(allocator, in_stream, block_len); |
| 579 | 579 | } |
| 580 | 580 | |
| 581 | fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) -> %FormValue { | |
| 581 | fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: &io.InStream, signed: bool, size: usize) %FormValue { | |
| 582 | 582 | return FormValue { .Const = Constant { |
| 583 | 583 | .signed = signed, |
| 584 | 584 | .payload = try readAllocBytes(allocator, in_stream, size), |
| 585 | 585 | }}; |
| 586 | 586 | } |
| 587 | 587 | |
| 588 | fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) -> %u64 { | |
| 588 | fn parseFormValueDwarfOffsetSize(in_stream: &io.InStream, is_64: bool) %u64 { | |
| 589 | 589 | return if (is_64) try in_stream.readIntLe(u64) |
| 590 | 590 | else u64(try in_stream.readIntLe(u32)) ; |
| 591 | 591 | } |
| 592 | 592 | |
| 593 | fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 { | |
| 593 | fn parseFormValueTargetAddrSize(in_stream: &io.InStream) %u64 { | |
| 594 | 594 | return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) |
| 595 | 595 | else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) |
| 596 | 596 | else unreachable; |
| 597 | 597 | } |
| 598 | 598 | |
| 599 | fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %FormValue { | |
| 599 | fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) %FormValue { | |
| 600 | 600 | const buf = try readAllocBytes(allocator, in_stream, size); |
| 601 | 601 | return FormValue { .Ref = buf }; |
| 602 | 602 | } |
| 603 | 603 | |
| 604 | fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) -> %FormValue { | |
| 604 | fn parseFormValueRef(allocator: &mem.Allocator, in_stream: &io.InStream, comptime T: type) %FormValue { | |
| 605 | 605 | const block_len = try in_stream.readIntLe(T); |
| 606 | 606 | return parseFormValueRefLen(allocator, in_stream, block_len); |
| 607 | 607 | } |
| 608 | 608 | |
| 609 | fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) -> %FormValue { | |
| 609 | fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u64, is_64: bool) %FormValue { | |
| 610 | 610 | return switch (form_id) { |
| 611 | 611 | DW.FORM_addr => FormValue { .Address = try parseFormValueTargetAddrSize(in_stream) }, |
| 612 | 612 | DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), |
| ... | ... | @@ -656,7 +656,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: &io.InStream, form_id: u |
| 656 | 656 | }; |
| 657 | 657 | } |
| 658 | 658 | |
| 659 | fn parseAbbrevTable(st: &ElfStackTrace) -> %AbbrevTable { | |
| 659 | fn parseAbbrevTable(st: &ElfStackTrace) %AbbrevTable { | |
| 660 | 660 | const in_file = &st.self_exe_file; |
| 661 | 661 | var in_file_stream = io.FileInStream.init(in_file); |
| 662 | 662 | const in_stream = &in_file_stream.stream; |
| ... | ... | @@ -688,7 +688,7 @@ fn parseAbbrevTable(st: &ElfStackTrace) -> %AbbrevTable { |
| 688 | 688 | |
| 689 | 689 | /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, |
| 690 | 690 | /// seeks in the stream and parses it. |
| 691 | fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) -> %&const AbbrevTable { | |
| 691 | fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) %&const AbbrevTable { | |
| 692 | 692 | for (st.abbrev_table_list.toSlice()) |*header| { |
| 693 | 693 | if (header.offset == abbrev_offset) { |
| 694 | 694 | return &header.table; |
| ... | ... | @@ -702,7 +702,7 @@ fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) -> %&const AbbrevTable |
| 702 | 702 | return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table; |
| 703 | 703 | } |
| 704 | 704 | |
| 705 | fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) -> ?&const AbbrevTableEntry { | |
| 705 | fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) ?&const AbbrevTableEntry { | |
| 706 | 706 | for (abbrev_table.toSliceConst()) |*table_entry| { |
| 707 | 707 | if (table_entry.abbrev_code == abbrev_code) |
| 708 | 708 | return table_entry; |
| ... | ... | @@ -710,7 +710,7 @@ fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) -> ?& |
| 710 | 710 | return null; |
| 711 | 711 | } |
| 712 | 712 | |
| 713 | fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) -> %Die { | |
| 713 | fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) %Die { | |
| 714 | 714 | const in_file = &st.self_exe_file; |
| 715 | 715 | var in_file_stream = io.FileInStream.init(in_file); |
| 716 | 716 | const in_stream = &in_file_stream.stream; |
| ... | ... | @@ -732,7 +732,7 @@ fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) - |
| 732 | 732 | return result; |
| 733 | 733 | } |
| 734 | 734 | |
| 735 | fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, target_address: usize) -> %LineInfo { | |
| 735 | fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, target_address: usize) %LineInfo { | |
| 736 | 736 | const compile_unit_cwd = try compile_unit.die.getAttrString(st, DW.AT_comp_dir); |
| 737 | 737 | |
| 738 | 738 | const in_file = &st.self_exe_file; |
| ... | ... | @@ -910,7 +910,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe |
| 910 | 910 | return error.MissingDebugInfo; |
| 911 | 911 | } |
| 912 | 912 | |
| 913 | fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { | |
| 913 | fn scanAllCompileUnits(st: &ElfStackTrace) %void { | |
| 914 | 914 | const debug_info_end = st.debug_info.offset + st.debug_info.size; |
| 915 | 915 | var this_unit_offset = st.debug_info.offset; |
| 916 | 916 | var cu_index: usize = 0; |
| ... | ... | @@ -986,7 +986,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { |
| 986 | 986 | } |
| 987 | 987 | } |
| 988 | 988 | |
| 989 | fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> %&const CompileUnit { | |
| 989 | fn findCompileUnit(st: &ElfStackTrace, target_address: u64) %&const CompileUnit { | |
| 990 | 990 | var in_file_stream = io.FileInStream.init(&st.self_exe_file); |
| 991 | 991 | const in_stream = &in_file_stream.stream; |
| 992 | 992 | for (st.compile_unit_list.toSlice()) |*compile_unit| { |
| ... | ... | @@ -1022,7 +1022,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> %&const CompileUn |
| 1022 | 1022 | return error.MissingDebugInfo; |
| 1023 | 1023 | } |
| 1024 | 1024 | |
| 1025 | fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 { | |
| 1025 | fn readInitialLength(in_stream: &io.InStream, is_64: &bool) %u64 { | |
| 1026 | 1026 | const first_32_bits = try in_stream.readIntLe(u32); |
| 1027 | 1027 | *is_64 = (first_32_bits == 0xffffffff); |
| 1028 | 1028 | if (*is_64) { |
| ... | ... | @@ -1033,7 +1033,7 @@ fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 { |
| 1033 | 1033 | } |
| 1034 | 1034 | } |
| 1035 | 1035 | |
| 1036 | fn readULeb128(in_stream: &io.InStream) -> %u64 { | |
| 1036 | fn readULeb128(in_stream: &io.InStream) %u64 { | |
| 1037 | 1037 | var result: u64 = 0; |
| 1038 | 1038 | var shift: usize = 0; |
| 1039 | 1039 | |
| ... | ... | @@ -1054,7 +1054,7 @@ fn readULeb128(in_stream: &io.InStream) -> %u64 { |
| 1054 | 1054 | } |
| 1055 | 1055 | } |
| 1056 | 1056 | |
| 1057 | fn readILeb128(in_stream: &io.InStream) -> %i64 { | |
| 1057 | fn readILeb128(in_stream: &io.InStream) %i64 { | |
| 1058 | 1058 | var result: i64 = 0; |
| 1059 | 1059 | var shift: usize = 0; |
| 1060 | 1060 |
std/elf.zig+6-6| ... | ... | @@ -81,14 +81,14 @@ pub const Elf = struct { |
| 81 | 81 | prealloc_file: io.File, |
| 82 | 82 | |
| 83 | 83 | /// Call close when done. |
| 84 | pub fn openPath(elf: &Elf, allocator: &mem.Allocator, path: []const u8) -> %void { | |
| 84 | pub fn openPath(elf: &Elf, allocator: &mem.Allocator, path: []const u8) %void { | |
| 85 | 85 | try elf.prealloc_file.open(path); |
| 86 | 86 | try elf.openFile(allocator, &elf.prealloc_file); |
| 87 | 87 | elf.auto_close_stream = true; |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | 90 | /// Call close when done. |
| 91 | pub fn openFile(elf: &Elf, allocator: &mem.Allocator, file: &io.File) -> %void { | |
| 91 | pub fn openFile(elf: &Elf, allocator: &mem.Allocator, file: &io.File) %void { | |
| 92 | 92 | elf.allocator = allocator; |
| 93 | 93 | elf.in_file = file; |
| 94 | 94 | elf.auto_close_stream = false; |
| ... | ... | @@ -183,7 +183,7 @@ pub const Elf = struct { |
| 183 | 183 | try elf.in_file.seekTo(elf.section_header_offset); |
| 184 | 184 | |
| 185 | 185 | elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count); |
| 186 | %defer elf.allocator.free(elf.section_headers); | |
| 186 | errdefer elf.allocator.free(elf.section_headers); | |
| 187 | 187 | |
| 188 | 188 | if (elf.is_64) { |
| 189 | 189 | if (sh_entry_size != 64) return error.InvalidFormat; |
| ... | ... | @@ -232,14 +232,14 @@ pub const Elf = struct { |
| 232 | 232 | } |
| 233 | 233 | } |
| 234 | 234 | |
| 235 | pub fn close(elf: &Elf) { | |
| 235 | pub fn close(elf: &Elf) void { | |
| 236 | 236 | elf.allocator.free(elf.section_headers); |
| 237 | 237 | |
| 238 | 238 | if (elf.auto_close_stream) |
| 239 | 239 | elf.in_file.close(); |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | pub fn findSection(elf: &Elf, name: []const u8) -> %?&SectionHeader { | |
| 242 | pub fn findSection(elf: &Elf, name: []const u8) %?&SectionHeader { | |
| 243 | 243 | var file_stream = io.FileInStream.init(elf.in_file); |
| 244 | 244 | const in = &file_stream.stream; |
| 245 | 245 | |
| ... | ... | @@ -263,7 +263,7 @@ pub const Elf = struct { |
| 263 | 263 | return null; |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | pub fn seekToSection(elf: &Elf, elf_section: &SectionHeader) -> %void { | |
| 266 | pub fn seekToSection(elf: &Elf, elf_section: &SectionHeader) %void { | |
| 267 | 267 | try elf.in_file.seekTo(elf_section.offset); |
| 268 | 268 | } |
| 269 | 269 | }; |
std/endian.zig+4-4| ... | ... | @@ -1,19 +1,19 @@ |
| 1 | 1 | const mem = @import("mem.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub fn swapIfLe(comptime T: type, x: T) -> T { | |
| 4 | pub fn swapIfLe(comptime T: type, x: T) T { | |
| 5 | 5 | return swapIf(builtin.Endian.Little, T, x); |
| 6 | 6 | } |
| 7 | 7 | |
| 8 | pub fn swapIfBe(comptime T: type, x: T) -> T { | |
| 8 | pub fn swapIfBe(comptime T: type, x: T) T { | |
| 9 | 9 | return swapIf(builtin.Endian.Big, T, x); |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) -> T { | |
| 12 | pub fn swapIf(endian: builtin.Endian, comptime T: type, x: T) T { | |
| 13 | 13 | return if (builtin.endian == endian) swap(T, x) else x; |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | pub fn swap(comptime T: type, x: T) -> T { | |
| 16 | pub fn swap(comptime T: type, x: T) T { | |
| 17 | 17 | var buf: [@sizeOf(T)]u8 = undefined; |
| 18 | 18 | mem.writeInt(buf[0..], x, builtin.Endian.Little); |
| 19 | 19 | return mem.readInt(buf, T, builtin.Endian.Big); |
std/fmt/errol/enum3.zig+1-1| ... | ... | @@ -438,7 +438,7 @@ const Slab = struct { |
| 438 | 438 | exp: i32, |
| 439 | 439 | }; |
| 440 | 440 | |
| 441 | fn slab(str: []const u8, exp: i32) -> Slab { | |
| 441 | fn slab(str: []const u8, exp: i32) Slab { | |
| 442 | 442 | return Slab { |
| 443 | 443 | .str = str, |
| 444 | 444 | .exp = exp, |
std/fmt/errol/index.zig+16-16| ... | ... | @@ -13,7 +13,7 @@ pub const FloatDecimal = struct { |
| 13 | 13 | }; |
| 14 | 14 | |
| 15 | 15 | /// Corrected Errol3 double to ASCII conversion. |
| 16 | pub fn errol3(value: f64, buffer: []u8) -> FloatDecimal { | |
| 16 | pub fn errol3(value: f64, buffer: []u8) FloatDecimal { | |
| 17 | 17 | const bits = @bitCast(u64, value); |
| 18 | 18 | const i = tableLowerBound(bits); |
| 19 | 19 | if (i < enum3.len and enum3[i] == bits) { |
| ... | ... | @@ -30,7 +30,7 @@ pub fn errol3(value: f64, buffer: []u8) -> FloatDecimal { |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | /// Uncorrected Errol3 double to ASCII conversion. |
| 33 | fn errol3u(val: f64, buffer: []u8) -> FloatDecimal { | |
| 33 | fn errol3u(val: f64, buffer: []u8) FloatDecimal { | |
| 34 | 34 | // check if in integer or fixed range |
| 35 | 35 | |
| 36 | 36 | if (val > 9.007199254740992e15 and val < 3.40282366920938e+38) { |
| ... | ... | @@ -133,7 +133,7 @@ fn errol3u(val: f64, buffer: []u8) -> FloatDecimal { |
| 133 | 133 | }; |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | fn tableLowerBound(k: u64) -> usize { | |
| 136 | fn tableLowerBound(k: u64) usize { | |
| 137 | 137 | var i = enum3.len; |
| 138 | 138 | var j: usize = 0; |
| 139 | 139 | |
| ... | ... | @@ -153,7 +153,7 @@ fn tableLowerBound(k: u64) -> usize { |
| 153 | 153 | /// @in: The HP number. |
| 154 | 154 | /// @val: The double. |
| 155 | 155 | /// &returns: The HP number. |
| 156 | fn hpProd(in: &const HP, val: f64) -> HP { | |
| 156 | fn hpProd(in: &const HP, val: f64) HP { | |
| 157 | 157 | var hi: f64 = undefined; |
| 158 | 158 | var lo: f64 = undefined; |
| 159 | 159 | split(in.val, &hi, &lo); |
| ... | ... | @@ -175,12 +175,12 @@ fn hpProd(in: &const HP, val: f64) -> HP { |
| 175 | 175 | /// @val: The double. |
| 176 | 176 | /// @hi: The high bits. |
| 177 | 177 | /// @lo: The low bits. |
| 178 | fn split(val: f64, hi: &f64, lo: &f64) { | |
| 178 | fn split(val: f64, hi: &f64, lo: &f64) void { | |
| 179 | 179 | *hi = gethi(val); |
| 180 | 180 | *lo = val - *hi; |
| 181 | 181 | } |
| 182 | 182 | |
| 183 | fn gethi(in: f64) -> f64 { | |
| 183 | fn gethi(in: f64) f64 { | |
| 184 | 184 | const bits = @bitCast(u64, in); |
| 185 | 185 | const new_bits = bits & 0xFFFFFFFFF8000000; |
| 186 | 186 | return @bitCast(f64, new_bits); |
| ... | ... | @@ -188,7 +188,7 @@ fn gethi(in: f64) -> f64 { |
| 188 | 188 | |
| 189 | 189 | /// Normalize the number by factoring in the error. |
| 190 | 190 | /// @hp: The float pair. |
| 191 | fn hpNormalize(hp: &HP) { | |
| 191 | fn hpNormalize(hp: &HP) void { | |
| 192 | 192 | const val = hp.val; |
| 193 | 193 | |
| 194 | 194 | hp.val += hp.off; |
| ... | ... | @@ -197,7 +197,7 @@ fn hpNormalize(hp: &HP) { |
| 197 | 197 | |
| 198 | 198 | /// Divide the high-precision number by ten. |
| 199 | 199 | /// @hp: The high-precision number |
| 200 | fn hpDiv10(hp: &HP) { | |
| 200 | fn hpDiv10(hp: &HP) void { | |
| 201 | 201 | var val = hp.val; |
| 202 | 202 | |
| 203 | 203 | hp.val /= 10.0; |
| ... | ... | @@ -213,7 +213,7 @@ fn hpDiv10(hp: &HP) { |
| 213 | 213 | |
| 214 | 214 | /// Multiply the high-precision number by ten. |
| 215 | 215 | /// @hp: The high-precision number |
| 216 | fn hpMul10(hp: &HP) { | |
| 216 | fn hpMul10(hp: &HP) void { | |
| 217 | 217 | const val = hp.val; |
| 218 | 218 | |
| 219 | 219 | hp.val *= 10.0; |
| ... | ... | @@ -233,7 +233,7 @@ fn hpMul10(hp: &HP) { |
| 233 | 233 | /// @val: The val. |
| 234 | 234 | /// @buf: The output buffer. |
| 235 | 235 | /// &return: The exponent. |
| 236 | fn errolInt(val: f64, buffer: []u8) -> FloatDecimal { | |
| 236 | fn errolInt(val: f64, buffer: []u8) FloatDecimal { | |
| 237 | 237 | const pow19 = u128(1e19); |
| 238 | 238 | |
| 239 | 239 | assert((val > 9.007199254740992e15) and val < (3.40282366920938e38)); |
| ... | ... | @@ -291,7 +291,7 @@ fn errolInt(val: f64, buffer: []u8) -> FloatDecimal { |
| 291 | 291 | /// @val: The val. |
| 292 | 292 | /// @buf: The output buffer. |
| 293 | 293 | /// &return: The exponent. |
| 294 | fn errolFixed(val: f64, buffer: []u8) -> FloatDecimal { | |
| 294 | fn errolFixed(val: f64, buffer: []u8) FloatDecimal { | |
| 295 | 295 | assert((val >= 16.0) and (val < 9.007199254740992e15)); |
| 296 | 296 | |
| 297 | 297 | const u = u64(val); |
| ... | ... | @@ -347,11 +347,11 @@ fn errolFixed(val: f64, buffer: []u8) -> FloatDecimal { |
| 347 | 347 | }; |
| 348 | 348 | } |
| 349 | 349 | |
| 350 | fn fpnext(val: f64) -> f64 { | |
| 350 | fn fpnext(val: f64) f64 { | |
| 351 | 351 | return @bitCast(f64, @bitCast(u64, val) +% 1); |
| 352 | 352 | } |
| 353 | 353 | |
| 354 | fn fpprev(val: f64) -> f64 { | |
| 354 | fn fpprev(val: f64) f64 { | |
| 355 | 355 | return @bitCast(f64, @bitCast(u64, val) -% 1); |
| 356 | 356 | } |
| 357 | 357 | |
| ... | ... | @@ -373,7 +373,7 @@ pub const c_digits_lut = []u8 { |
| 373 | 373 | '9', '8', '9', '9', |
| 374 | 374 | }; |
| 375 | 375 | |
| 376 | fn u64toa(value_param: u64, buffer: []u8) -> usize { | |
| 376 | fn u64toa(value_param: u64, buffer: []u8) usize { | |
| 377 | 377 | var value = value_param; |
| 378 | 378 | const kTen8: u64 = 100000000; |
| 379 | 379 | const kTen9: u64 = kTen8 * 10; |
| ... | ... | @@ -606,7 +606,7 @@ fn u64toa(value_param: u64, buffer: []u8) -> usize { |
| 606 | 606 | return buf_index; |
| 607 | 607 | } |
| 608 | 608 | |
| 609 | fn fpeint(from: f64) -> u128 { | |
| 609 | fn fpeint(from: f64) u128 { | |
| 610 | 610 | const bits = @bitCast(u64, from); |
| 611 | 611 | assert((bits & ((1 << 52) - 1)) == 0); |
| 612 | 612 | |
| ... | ... | @@ -621,7 +621,7 @@ fn fpeint(from: f64) -> u128 { |
| 621 | 621 | /// @a: Integer a. |
| 622 | 622 | /// @b: Integer b. |
| 623 | 623 | /// &returns: An index within [0, 19). |
| 624 | fn mismatch10(a: u64, b: u64) -> i32 { | |
| 624 | fn mismatch10(a: u64, b: u64) i32 { | |
| 625 | 625 | const pow10 = 10000000000; |
| 626 | 626 | const af = a / pow10; |
| 627 | 627 | const bf = b / pow10; |
std/fmt/index.zig+23-23| ... | ... | @@ -24,8 +24,8 @@ const State = enum { // TODO put inside format function and make sure the name a |
| 24 | 24 | /// Renders fmt string with args, calling output with slices of bytes. |
| 25 | 25 | /// If `output` returns an error, the error is returned from `format` and |
| 26 | 26 | /// `output` is not called again. |
| 27 | pub fn format(context: var, output: fn(@typeOf(context), []const u8)->%void, | |
| 28 | comptime fmt: []const u8, args: ...) -> %void | |
| 27 | pub fn format(context: var, output: fn(@typeOf(context), []const u8)%void, | |
| 28 | comptime fmt: []const u8, args: ...) %void | |
| 29 | 29 | { |
| 30 | 30 | comptime var start_index = 0; |
| 31 | 31 | comptime var state = State.Start; |
| ... | ... | @@ -191,7 +191,7 @@ pub fn format(context: var, output: fn(@typeOf(context), []const u8)->%void, |
| 191 | 191 | } |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | pub fn formatValue(value: var, context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void { | |
| 194 | pub fn formatValue(value: var, context: var, output: fn(@typeOf(context), []const u8)%void) %void { | |
| 195 | 195 | const T = @typeOf(value); |
| 196 | 196 | switch (@typeId(T)) { |
| 197 | 197 | builtin.TypeId.Int => { |
| ... | ... | @@ -240,12 +240,12 @@ pub fn formatValue(value: var, context: var, output: fn(@typeOf(context), []cons |
| 240 | 240 | } |
| 241 | 241 | } |
| 242 | 242 | |
| 243 | pub fn formatAsciiChar(c: u8, context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void { | |
| 243 | pub fn formatAsciiChar(c: u8, context: var, output: fn(@typeOf(context), []const u8)%void) %void { | |
| 244 | 244 | return output(context, (&c)[0..1]); |
| 245 | 245 | } |
| 246 | 246 | |
| 247 | 247 | pub fn formatBuf(buf: []const u8, width: usize, |
| 248 | context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void | |
| 248 | context: var, output: fn(@typeOf(context), []const u8)%void) %void | |
| 249 | 249 | { |
| 250 | 250 | try output(context, buf); |
| 251 | 251 | |
| ... | ... | @@ -256,7 +256,7 @@ pub fn formatBuf(buf: []const u8, width: usize, |
| 256 | 256 | } |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void { | |
| 259 | pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []const u8)%void) %void { | |
| 260 | 260 | var x = f64(value); |
| 261 | 261 | |
| 262 | 262 | // Errol doesn't handle these special cases. |
| ... | ... | @@ -294,7 +294,7 @@ pub fn formatFloat(value: var, context: var, output: fn(@typeOf(context), []cons |
| 294 | 294 | } |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | pub fn formatFloatDecimal(value: var, precision: usize, context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void { | |
| 297 | pub fn formatFloatDecimal(value: var, precision: usize, context: var, output: fn(@typeOf(context), []const u8)%void) %void { | |
| 298 | 298 | var x = f64(value); |
| 299 | 299 | |
| 300 | 300 | // Errol doesn't handle these special cases. |
| ... | ... | @@ -336,7 +336,7 @@ pub fn formatFloatDecimal(value: var, precision: usize, context: var, output: fn |
| 336 | 336 | |
| 337 | 337 | |
| 338 | 338 | pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, |
| 339 | context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void | |
| 339 | context: var, output: fn(@typeOf(context), []const u8)%void) %void | |
| 340 | 340 | { |
| 341 | 341 | if (@typeOf(value).is_signed) { |
| 342 | 342 | return formatIntSigned(value, base, uppercase, width, context, output); |
| ... | ... | @@ -346,7 +346,7 @@ pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | 348 | fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, |
| 349 | context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void | |
| 349 | context: var, output: fn(@typeOf(context), []const u8)%void) %void | |
| 350 | 350 | { |
| 351 | 351 | const uint = @IntType(false, @typeOf(value).bit_count); |
| 352 | 352 | if (value < 0) { |
| ... | ... | @@ -367,7 +367,7 @@ fn formatIntSigned(value: var, base: u8, uppercase: bool, width: usize, |
| 367 | 367 | } |
| 368 | 368 | |
| 369 | 369 | fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, |
| 370 | context: var, output: fn(@typeOf(context), []const u8)->%void) -> %void | |
| 370 | context: var, output: fn(@typeOf(context), []const u8)%void) %void | |
| 371 | 371 | { |
| 372 | 372 | // max_int_digits accounts for the minus sign. when printing an unsigned |
| 373 | 373 | // number we don't need to do that. |
| ... | ... | @@ -405,7 +405,7 @@ fn formatIntUnsigned(value: var, base: u8, uppercase: bool, width: usize, |
| 405 | 405 | } |
| 406 | 406 | } |
| 407 | 407 | |
| 408 | pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, width: usize) -> usize { | |
| 408 | pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, width: usize) usize { | |
| 409 | 409 | var context = FormatIntBuf { |
| 410 | 410 | .out_buf = out_buf, |
| 411 | 411 | .index = 0, |
| ... | ... | @@ -417,12 +417,12 @@ const FormatIntBuf = struct { |
| 417 | 417 | out_buf: []u8, |
| 418 | 418 | index: usize, |
| 419 | 419 | }; |
| 420 | fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) -> %void { | |
| 420 | fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) %void { | |
| 421 | 421 | mem.copy(u8, context.out_buf[context.index..], bytes); |
| 422 | 422 | context.index += bytes.len; |
| 423 | 423 | } |
| 424 | 424 | |
| 425 | pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) -> %T { | |
| 425 | pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) %T { | |
| 426 | 426 | if (!T.is_signed) |
| 427 | 427 | return parseUnsigned(T, buf, radix); |
| 428 | 428 | if (buf.len == 0) |
| ... | ... | @@ -446,7 +446,7 @@ test "fmt.parseInt" { |
| 446 | 446 | assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow); |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) -> %T { | |
| 449 | pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) %T { | |
| 450 | 450 | var x: T = 0; |
| 451 | 451 | |
| 452 | 452 | for (buf) |c| { |
| ... | ... | @@ -459,7 +459,7 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) -> %T { |
| 459 | 459 | } |
| 460 | 460 | |
| 461 | 461 | error InvalidChar; |
| 462 | fn charToDigit(c: u8, radix: u8) -> %u8 { | |
| 462 | fn charToDigit(c: u8, radix: u8) %u8 { | |
| 463 | 463 | const value = switch (c) { |
| 464 | 464 | '0' ... '9' => c - '0', |
| 465 | 465 | 'A' ... 'Z' => c - 'A' + 10, |
| ... | ... | @@ -473,7 +473,7 @@ fn charToDigit(c: u8, radix: u8) -> %u8 { |
| 473 | 473 | return value; |
| 474 | 474 | } |
| 475 | 475 | |
| 476 | fn digitToChar(digit: u8, uppercase: bool) -> u8 { | |
| 476 | fn digitToChar(digit: u8, uppercase: bool) u8 { | |
| 477 | 477 | return switch (digit) { |
| 478 | 478 | 0 ... 9 => digit + '0', |
| 479 | 479 | 10 ... 35 => digit + ((if (uppercase) u8('A') else u8('a')) - 10), |
| ... | ... | @@ -486,19 +486,19 @@ const BufPrintContext = struct { |
| 486 | 486 | }; |
| 487 | 487 | |
| 488 | 488 | error BufferTooSmall; |
| 489 | fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) -> %void { | |
| 489 | fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) %void { | |
| 490 | 490 | if (context.remaining.len < bytes.len) return error.BufferTooSmall; |
| 491 | 491 | mem.copy(u8, context.remaining, bytes); |
| 492 | 492 | context.remaining = context.remaining[bytes.len..]; |
| 493 | 493 | } |
| 494 | 494 | |
| 495 | pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) -> %[]u8 { | |
| 495 | pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) %[]u8 { | |
| 496 | 496 | var context = BufPrintContext { .remaining = buf, }; |
| 497 | 497 | try format(&context, bufPrintWrite, fmt, args); |
| 498 | 498 | return buf[0..buf.len - context.remaining.len]; |
| 499 | 499 | } |
| 500 | 500 | |
| 501 | pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) -> %[]u8 { | |
| 501 | pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) %[]u8 { | |
| 502 | 502 | var size: usize = 0; |
| 503 | 503 | // Cannot fail because `countSize` cannot fail. |
| 504 | 504 | format(&size, countSize, fmt, args) catch unreachable; |
| ... | ... | @@ -506,7 +506,7 @@ pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ... |
| 506 | 506 | return bufPrint(buf, fmt, args); |
| 507 | 507 | } |
| 508 | 508 | |
| 509 | fn countSize(size: &usize, bytes: []const u8) -> %void { | |
| 509 | fn countSize(size: &usize, bytes: []const u8) %void { | |
| 510 | 510 | *size += bytes.len; |
| 511 | 511 | } |
| 512 | 512 | |
| ... | ... | @@ -528,7 +528,7 @@ test "buf print int" { |
| 528 | 528 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42")); |
| 529 | 529 | } |
| 530 | 530 | |
| 531 | fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) -> []u8 { | |
| 531 | fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) []u8 { | |
| 532 | 532 | return buf[0..formatIntBuf(buf, value, base, uppercase, width)]; |
| 533 | 533 | } |
| 534 | 534 | |
| ... | ... | @@ -644,7 +644,7 @@ test "fmt.format" { |
| 644 | 644 | } |
| 645 | 645 | } |
| 646 | 646 | |
| 647 | pub fn trim(buf: []const u8) -> []const u8 { | |
| 647 | pub fn trim(buf: []const u8) []const u8 { | |
| 648 | 648 | var start: usize = 0; |
| 649 | 649 | while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) { } |
| 650 | 650 | |
| ... | ... | @@ -671,7 +671,7 @@ test "fmt.trim" { |
| 671 | 671 | assert(mem.eql(u8, "abc", trim("abc "))); |
| 672 | 672 | } |
| 673 | 673 | |
| 674 | pub fn isWhiteSpace(byte: u8) -> bool { | |
| 674 | pub fn isWhiteSpace(byte: u8) bool { | |
| 675 | 675 | return switch (byte) { |
| 676 | 676 | ' ', '\t', '\n', '\r' => true, |
| 677 | 677 | else => false, |
std/hash_map.zig+18-18| ... | ... | @@ -10,8 +10,8 @@ const want_modification_safety = builtin.mode != builtin.Mode.ReleaseFast; |
| 10 | 10 | const debug_u32 = if (want_modification_safety) u32 else void; |
| 11 | 11 | |
| 12 | 12 | pub fn HashMap(comptime K: type, comptime V: type, |
| 13 | comptime hash: fn(key: K)->u32, | |
| 14 | comptime eql: fn(a: K, b: K)->bool) -> type | |
| 13 | comptime hash: fn(key: K)u32, | |
| 14 | comptime eql: fn(a: K, b: K)bool) type | |
| 15 | 15 | { |
| 16 | 16 | return struct { |
| 17 | 17 | entries: []Entry, |
| ... | ... | @@ -39,7 +39,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 39 | 39 | // used to detect concurrent modification |
| 40 | 40 | initial_modification_count: debug_u32, |
| 41 | 41 | |
| 42 | pub fn next(it: &Iterator) -> ?&Entry { | |
| 42 | pub fn next(it: &Iterator) ?&Entry { | |
| 43 | 43 | if (want_modification_safety) { |
| 44 | 44 | assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification |
| 45 | 45 | } |
| ... | ... | @@ -56,7 +56,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 56 | 56 | } |
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | pub fn init(allocator: &Allocator) -> Self { | |
| 59 | pub fn init(allocator: &Allocator) Self { | |
| 60 | 60 | return Self { |
| 61 | 61 | .entries = []Entry{}, |
| 62 | 62 | .allocator = allocator, |
| ... | ... | @@ -66,11 +66,11 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 66 | 66 | }; |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | pub fn deinit(hm: &Self) { | |
| 69 | pub fn deinit(hm: &Self) void { | |
| 70 | 70 | hm.allocator.free(hm.entries); |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | pub fn clear(hm: &Self) { | |
| 73 | pub fn clear(hm: &Self) void { | |
| 74 | 74 | for (hm.entries) |*entry| { |
| 75 | 75 | entry.used = false; |
| 76 | 76 | } |
| ... | ... | @@ -80,7 +80,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | /// Returns the value that was already there. |
| 83 | pub fn put(hm: &Self, key: K, value: &const V) -> %?V { | |
| 83 | pub fn put(hm: &Self, key: K, value: &const V) %?V { | |
| 84 | 84 | if (hm.entries.len == 0) { |
| 85 | 85 | try hm.initCapacity(16); |
| 86 | 86 | } |
| ... | ... | @@ -102,18 +102,18 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 102 | 102 | return hm.internalPut(key, value); |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | pub fn get(hm: &Self, key: K) -> ?&Entry { | |
| 105 | pub fn get(hm: &Self, key: K) ?&Entry { | |
| 106 | 106 | if (hm.entries.len == 0) { |
| 107 | 107 | return null; |
| 108 | 108 | } |
| 109 | 109 | return hm.internalGet(key); |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | pub fn contains(hm: &Self, key: K) -> bool { | |
| 112 | pub fn contains(hm: &Self, key: K) bool { | |
| 113 | 113 | return hm.get(key) != null; |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | pub fn remove(hm: &Self, key: K) -> ?&Entry { | |
| 116 | pub fn remove(hm: &Self, key: K) ?&Entry { | |
| 117 | 117 | hm.incrementModificationCount(); |
| 118 | 118 | const start_index = hm.keyToIndex(key); |
| 119 | 119 | {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) { |
| ... | ... | @@ -142,7 +142,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 142 | 142 | return null; |
| 143 | 143 | } |
| 144 | 144 | |
| 145 | pub fn iterator(hm: &const Self) -> Iterator { | |
| 145 | pub fn iterator(hm: &const Self) Iterator { | |
| 146 | 146 | return Iterator { |
| 147 | 147 | .hm = hm, |
| 148 | 148 | .count = 0, |
| ... | ... | @@ -151,7 +151,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 151 | 151 | }; |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | fn initCapacity(hm: &Self, capacity: usize) -> %void { | |
| 154 | fn initCapacity(hm: &Self, capacity: usize) %void { | |
| 155 | 155 | hm.entries = try hm.allocator.alloc(Entry, capacity); |
| 156 | 156 | hm.size = 0; |
| 157 | 157 | hm.max_distance_from_start_index = 0; |
| ... | ... | @@ -160,14 +160,14 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 160 | 160 | } |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | fn incrementModificationCount(hm: &Self) { | |
| 163 | fn incrementModificationCount(hm: &Self) void { | |
| 164 | 164 | if (want_modification_safety) { |
| 165 | 165 | hm.modification_count +%= 1; |
| 166 | 166 | } |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 169 | /// Returns the value that was already there. |
| 170 | fn internalPut(hm: &Self, orig_key: K, orig_value: &const V) -> ?V { | |
| 170 | fn internalPut(hm: &Self, orig_key: K, orig_value: &const V) ?V { | |
| 171 | 171 | var key = orig_key; |
| 172 | 172 | var value = *orig_value; |
| 173 | 173 | const start_index = hm.keyToIndex(key); |
| ... | ... | @@ -217,7 +217,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 217 | 217 | unreachable; // put into a full map |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | fn internalGet(hm: &Self, key: K) -> ?&Entry { | |
| 220 | fn internalGet(hm: &Self, key: K) ?&Entry { | |
| 221 | 221 | const start_index = hm.keyToIndex(key); |
| 222 | 222 | {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index) : (roll_over += 1) { |
| 223 | 223 | const index = (start_index + roll_over) % hm.entries.len; |
| ... | ... | @@ -229,7 +229,7 @@ pub fn HashMap(comptime K: type, comptime V: type, |
| 229 | 229 | return null; |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | fn keyToIndex(hm: &Self, key: K) -> usize { | |
| 232 | fn keyToIndex(hm: &Self, key: K) usize { | |
| 233 | 233 | return usize(hash(key)) % hm.entries.len; |
| 234 | 234 | } |
| 235 | 235 | }; |
| ... | ... | @@ -254,10 +254,10 @@ test "basicHashMapTest" { |
| 254 | 254 | assert(map.get(2) == null); |
| 255 | 255 | } |
| 256 | 256 | |
| 257 | fn hash_i32(x: i32) -> u32 { | |
| 257 | fn hash_i32(x: i32) u32 { | |
| 258 | 258 | return @bitCast(u32, x); |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | fn eql_i32(a: i32, b: i32) -> bool { | |
| 261 | fn eql_i32(a: i32, b: i32) bool { | |
| 262 | 262 | return a == b; |
| 263 | 263 | } |
std/heap.zig+10-10| ... | ... | @@ -18,14 +18,14 @@ var c_allocator_state = Allocator { |
| 18 | 18 | .freeFn = cFree, |
| 19 | 19 | }; |
| 20 | 20 | |
| 21 | fn cAlloc(self: &Allocator, n: usize, alignment: u29) -> %[]u8 { | |
| 21 | fn cAlloc(self: &Allocator, n: usize, alignment: u29) %[]u8 { | |
| 22 | 22 | return if (c.malloc(usize(n))) |buf| |
| 23 | 23 | @ptrCast(&u8, buf)[0..n] |
| 24 | 24 | else |
| 25 | 25 | error.OutOfMemory; |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 { | |
| 28 | fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 { | |
| 29 | 29 | const old_ptr = @ptrCast(&c_void, old_mem.ptr); |
| 30 | 30 | if (c.realloc(old_ptr, new_size)) |buf| { |
| 31 | 31 | return @ptrCast(&u8, buf)[0..new_size]; |
| ... | ... | @@ -36,7 +36,7 @@ fn cRealloc(self: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> |
| 36 | 36 | } |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | fn cFree(self: &Allocator, old_mem: []u8) { | |
| 39 | fn cFree(self: &Allocator, old_mem: []u8) void { | |
| 40 | 40 | const old_ptr = @ptrCast(&c_void, old_mem.ptr); |
| 41 | 41 | c.free(old_ptr); |
| 42 | 42 | } |
| ... | ... | @@ -47,7 +47,7 @@ pub const IncrementingAllocator = struct { |
| 47 | 47 | end_index: usize, |
| 48 | 48 | heap_handle: if (builtin.os == Os.windows) os.windows.HANDLE else void, |
| 49 | 49 | |
| 50 | fn init(capacity: usize) -> %IncrementingAllocator { | |
| 50 | fn init(capacity: usize) %IncrementingAllocator { | |
| 51 | 51 | switch (builtin.os) { |
| 52 | 52 | Os.linux, Os.macosx, Os.ios => { |
| 53 | 53 | const p = os.posix; |
| ... | ... | @@ -85,7 +85,7 @@ pub const IncrementingAllocator = struct { |
| 85 | 85 | } |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | fn deinit(self: &IncrementingAllocator) { | |
| 88 | fn deinit(self: &IncrementingAllocator) void { | |
| 89 | 89 | switch (builtin.os) { |
| 90 | 90 | Os.linux, Os.macosx, Os.ios => { |
| 91 | 91 | _ = os.posix.munmap(self.bytes.ptr, self.bytes.len); |
| ... | ... | @@ -97,15 +97,15 @@ pub const IncrementingAllocator = struct { |
| 97 | 97 | } |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | fn reset(self: &IncrementingAllocator) { | |
| 100 | fn reset(self: &IncrementingAllocator) void { | |
| 101 | 101 | self.end_index = 0; |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | fn bytesLeft(self: &const IncrementingAllocator) -> usize { | |
| 104 | fn bytesLeft(self: &const IncrementingAllocator) usize { | |
| 105 | 105 | return self.bytes.len - self.end_index; |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | fn alloc(allocator: &Allocator, n: usize, alignment: u29) -> %[]u8 { | |
| 108 | fn alloc(allocator: &Allocator, n: usize, alignment: u29) %[]u8 { | |
| 109 | 109 | const self = @fieldParentPtr(IncrementingAllocator, "allocator", allocator); |
| 110 | 110 | const addr = @ptrToInt(&self.bytes[self.end_index]); |
| 111 | 111 | const rem = @rem(addr, alignment); |
| ... | ... | @@ -120,7 +120,7 @@ pub const IncrementingAllocator = struct { |
| 120 | 120 | return result; |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 { | |
| 123 | fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 { | |
| 124 | 124 | if (new_size <= old_mem.len) { |
| 125 | 125 | return old_mem[0..new_size]; |
| 126 | 126 | } else { |
| ... | ... | @@ -130,7 +130,7 @@ pub const IncrementingAllocator = struct { |
| 130 | 130 | } |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | fn free(allocator: &Allocator, bytes: []u8) { | |
| 133 | fn free(allocator: &Allocator, bytes: []u8) void { | |
| 134 | 134 | // Do nothing. That's the point of an incrementing allocator. |
| 135 | 135 | } |
| 136 | 136 | }; |
std/io.zig+91-51| ... | ... | @@ -48,8 +48,9 @@ error PathNotFound; |
| 48 | 48 | error OutOfMemory; |
| 49 | 49 | error Unseekable; |
| 50 | 50 | error EndOfFile; |
| 51 | error FilePosLargerThanPointerRange; | |
| 51 | 52 | |
| 52 | pub fn getStdErr() -> %File { | |
| 53 | pub fn getStdErr() %File { | |
| 53 | 54 | const handle = if (is_windows) |
| 54 | 55 | try os.windowsGetStdHandle(system.STD_ERROR_HANDLE) |
| 55 | 56 | else if (is_posix) |
| ... | ... | @@ -59,7 +60,7 @@ pub fn getStdErr() -> %File { |
| 59 | 60 | return File.openHandle(handle); |
| 60 | 61 | } |
| 61 | 62 | |
| 62 | pub fn getStdOut() -> %File { | |
| 63 | pub fn getStdOut() %File { | |
| 63 | 64 | const handle = if (is_windows) |
| 64 | 65 | try os.windowsGetStdHandle(system.STD_OUTPUT_HANDLE) |
| 65 | 66 | else if (is_posix) |
| ... | ... | @@ -69,7 +70,7 @@ pub fn getStdOut() -> %File { |
| 69 | 70 | return File.openHandle(handle); |
| 70 | 71 | } |
| 71 | 72 | |
| 72 | pub fn getStdIn() -> %File { | |
| 73 | pub fn getStdIn() %File { | |
| 73 | 74 | const handle = if (is_windows) |
| 74 | 75 | try os.windowsGetStdHandle(system.STD_INPUT_HANDLE) |
| 75 | 76 | else if (is_posix) |
| ... | ... | @@ -84,7 +85,7 @@ pub const FileInStream = struct { |
| 84 | 85 | file: &File, |
| 85 | 86 | stream: InStream, |
| 86 | 87 | |
| 87 | pub fn init(file: &File) -> FileInStream { | |
| 88 | pub fn init(file: &File) FileInStream { | |
| 88 | 89 | return FileInStream { |
| 89 | 90 | .file = file, |
| 90 | 91 | .stream = InStream { |
| ... | ... | @@ -93,7 +94,7 @@ pub const FileInStream = struct { |
| 93 | 94 | }; |
| 94 | 95 | } |
| 95 | 96 | |
| 96 | fn readFn(in_stream: &InStream, buffer: []u8) -> %usize { | |
| 97 | fn readFn(in_stream: &InStream, buffer: []u8) %usize { | |
| 97 | 98 | const self = @fieldParentPtr(FileInStream, "stream", in_stream); |
| 98 | 99 | return self.file.read(buffer); |
| 99 | 100 | } |
| ... | ... | @@ -104,7 +105,7 @@ pub const FileOutStream = struct { |
| 104 | 105 | file: &File, |
| 105 | 106 | stream: OutStream, |
| 106 | 107 | |
| 107 | pub fn init(file: &File) -> FileOutStream { | |
| 108 | pub fn init(file: &File) FileOutStream { | |
| 108 | 109 | return FileOutStream { |
| 109 | 110 | .file = file, |
| 110 | 111 | .stream = OutStream { |
| ... | ... | @@ -113,7 +114,7 @@ pub const FileOutStream = struct { |
| 113 | 114 | }; |
| 114 | 115 | } |
| 115 | 116 | |
| 116 | fn writeFn(out_stream: &OutStream, bytes: []const u8) -> %void { | |
| 117 | fn writeFn(out_stream: &OutStream, bytes: []const u8) %void { | |
| 117 | 118 | const self = @fieldParentPtr(FileOutStream, "stream", out_stream); |
| 118 | 119 | return self.file.write(bytes); |
| 119 | 120 | } |
| ... | ... | @@ -128,7 +129,7 @@ pub const File = struct { |
| 128 | 129 | /// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned. |
| 129 | 130 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. |
| 130 | 131 | /// Call close to clean up. |
| 131 | pub fn openRead(path: []const u8, allocator: ?&mem.Allocator) -> %File { | |
| 132 | pub fn openRead(path: []const u8, allocator: ?&mem.Allocator) %File { | |
| 132 | 133 | if (is_posix) { |
| 133 | 134 | const flags = system.O_LARGEFILE|system.O_RDONLY; |
| 134 | 135 | const fd = try os.posixOpen(path, flags, 0, allocator); |
| ... | ... | @@ -143,7 +144,7 @@ pub const File = struct { |
| 143 | 144 | } |
| 144 | 145 | |
| 145 | 146 | /// Calls `openWriteMode` with 0o666 for the mode. |
| 146 | pub fn openWrite(path: []const u8, allocator: ?&mem.Allocator) -> %File { | |
| 147 | pub fn openWrite(path: []const u8, allocator: ?&mem.Allocator) %File { | |
| 147 | 148 | return openWriteMode(path, 0o666, allocator); |
| 148 | 149 | |
| 149 | 150 | } |
| ... | ... | @@ -153,7 +154,7 @@ pub const File = struct { |
| 153 | 154 | /// size buffer is too small, and the provided allocator is null, error.NameTooLong is returned. |
| 154 | 155 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. |
| 155 | 156 | /// Call close to clean up. |
| 156 | pub fn openWriteMode(path: []const u8, mode: usize, allocator: ?&mem.Allocator) -> %File { | |
| 157 | pub fn openWriteMode(path: []const u8, mode: usize, allocator: ?&mem.Allocator) %File { | |
| 157 | 158 | if (is_posix) { |
| 158 | 159 | const flags = system.O_LARGEFILE|system.O_WRONLY|system.O_CREAT|system.O_CLOEXEC|system.O_TRUNC; |
| 159 | 160 | const fd = try os.posixOpen(path, flags, mode, allocator); |
| ... | ... | @@ -169,7 +170,7 @@ pub const File = struct { |
| 169 | 170 | |
| 170 | 171 | } |
| 171 | 172 | |
| 172 | pub fn openHandle(handle: os.FileHandle) -> File { | |
| 173 | pub fn openHandle(handle: os.FileHandle) File { | |
| 173 | 174 | return File { |
| 174 | 175 | .handle = handle, |
| 175 | 176 | }; |
| ... | ... | @@ -178,17 +179,17 @@ pub const File = struct { |
| 178 | 179 | |
| 179 | 180 | /// Upon success, the stream is in an uninitialized state. To continue using it, |
| 180 | 181 | /// you must use the open() function. |
| 181 | pub fn close(self: &File) { | |
| 182 | pub fn close(self: &File) void { | |
| 182 | 183 | os.close(self.handle); |
| 183 | 184 | self.handle = undefined; |
| 184 | 185 | } |
| 185 | 186 | |
| 186 | 187 | /// Calls `os.isTty` on `self.handle`. |
| 187 | pub fn isTty(self: &File) -> bool { | |
| 188 | pub fn isTty(self: &File) bool { | |
| 188 | 189 | return os.isTty(self.handle); |
| 189 | 190 | } |
| 190 | 191 | |
| 191 | pub fn seekForward(self: &File, amount: isize) -> %void { | |
| 192 | pub fn seekForward(self: &File, amount: isize) %void { | |
| 192 | 193 | switch (builtin.os) { |
| 193 | 194 | Os.linux, Os.macosx, Os.ios => { |
| 194 | 195 | const result = system.lseek(self.handle, amount, system.SEEK_CUR); |
| ... | ... | @@ -204,14 +205,24 @@ pub const File = struct { |
| 204 | 205 | }; |
| 205 | 206 | } |
| 206 | 207 | }, |
| 208 | Os.windows => { | |
| 209 | if (system.SetFilePointerEx(self.handle, amount, null, system.FILE_CURRENT) == 0) { | |
| 210 | const err = system.GetLastError(); | |
| 211 | return switch (err) { | |
| 212 | system.ERROR.INVALID_PARAMETER => error.BadFd, | |
| 213 | else => os.unexpectedErrorWindows(err), | |
| 214 | }; | |
| 215 | } | |
| 216 | }, | |
| 207 | 217 | else => @compileError("unsupported OS"), |
| 208 | 218 | } |
| 209 | 219 | } |
| 210 | 220 | |
| 211 | pub fn seekTo(self: &File, pos: usize) -> %void { | |
| 221 | pub fn seekTo(self: &File, pos: usize) %void { | |
| 212 | 222 | switch (builtin.os) { |
| 213 | 223 | Os.linux, Os.macosx, Os.ios => { |
| 214 | const result = system.lseek(self.handle, @bitCast(isize, pos), system.SEEK_SET); | |
| 224 | const ipos = try math.cast(isize, pos); | |
| 225 | const result = system.lseek(self.handle, ipos, system.SEEK_SET); | |
| 215 | 226 | const err = system.getErrno(result); |
| 216 | 227 | if (err > 0) { |
| 217 | 228 | return switch (err) { |
| ... | ... | @@ -224,11 +235,21 @@ pub const File = struct { |
| 224 | 235 | }; |
| 225 | 236 | } |
| 226 | 237 | }, |
| 238 | Os.windows => { | |
| 239 | const ipos = try math.cast(isize, pos); | |
| 240 | if (system.SetFilePointerEx(self.handle, ipos, null, system.FILE_BEGIN) == 0) { | |
| 241 | const err = system.GetLastError(); | |
| 242 | return switch (err) { | |
| 243 | system.ERROR.INVALID_PARAMETER => error.BadFd, | |
| 244 | else => os.unexpectedErrorWindows(err), | |
| 245 | }; | |
| 246 | } | |
| 247 | }, | |
| 227 | 248 | else => @compileError("unsupported OS: " ++ @tagName(builtin.os)), |
| 228 | 249 | } |
| 229 | 250 | } |
| 230 | 251 | |
| 231 | pub fn getPos(self: &File) -> %usize { | |
| 252 | pub fn getPos(self: &File) %usize { | |
| 232 | 253 | switch (builtin.os) { |
| 233 | 254 | Os.linux, Os.macosx, Os.ios => { |
| 234 | 255 | const result = system.lseek(self.handle, 0, system.SEEK_CUR); |
| ... | ... | @@ -245,11 +266,30 @@ pub const File = struct { |
| 245 | 266 | } |
| 246 | 267 | return result; |
| 247 | 268 | }, |
| 269 | Os.windows => { | |
| 270 | var pos : system.LARGE_INTEGER = undefined; | |
| 271 | if (system.SetFilePointerEx(self.handle, 0, &pos, system.FILE_CURRENT) == 0) { | |
| 272 | const err = system.GetLastError(); | |
| 273 | return switch (err) { | |
| 274 | system.ERROR.INVALID_PARAMETER => error.BadFd, | |
| 275 | else => os.unexpectedErrorWindows(err), | |
| 276 | }; | |
| 277 | } | |
| 278 | ||
| 279 | assert(pos >= 0); | |
| 280 | if (@sizeOf(@typeOf(pos)) > @sizeOf(usize)) { | |
| 281 | if (pos > @maxValue(usize)) { | |
| 282 | return error.FilePosLargerThanPointerRange; | |
| 283 | } | |
| 284 | } | |
| 285 | ||
| 286 | return usize(pos); | |
| 287 | }, | |
| 248 | 288 | else => @compileError("unsupported OS"), |
| 249 | 289 | } |
| 250 | 290 | } |
| 251 | 291 | |
| 252 | pub fn getEndPos(self: &File) -> %usize { | |
| 292 | pub fn getEndPos(self: &File) %usize { | |
| 253 | 293 | if (is_posix) { |
| 254 | 294 | var stat: system.Stat = undefined; |
| 255 | 295 | const err = system.getErrno(system.fstat(self.handle, &stat)); |
| ... | ... | @@ -278,7 +318,7 @@ pub const File = struct { |
| 278 | 318 | } |
| 279 | 319 | } |
| 280 | 320 | |
| 281 | pub fn read(self: &File, buffer: []u8) -> %usize { | |
| 321 | pub fn read(self: &File, buffer: []u8) %usize { | |
| 282 | 322 | if (is_posix) { |
| 283 | 323 | var index: usize = 0; |
| 284 | 324 | while (index < buffer.len) { |
| ... | ... | @@ -320,7 +360,7 @@ pub const File = struct { |
| 320 | 360 | } |
| 321 | 361 | } |
| 322 | 362 | |
| 323 | fn write(self: &File, bytes: []const u8) -> %void { | |
| 363 | fn write(self: &File, bytes: []const u8) %void { | |
| 324 | 364 | if (is_posix) { |
| 325 | 365 | try os.posixWrite(self.handle, bytes); |
| 326 | 366 | } else if (is_windows) { |
| ... | ... | @@ -338,12 +378,12 @@ pub const InStream = struct { |
| 338 | 378 | /// Return the number of bytes read. If the number read is smaller than buf.len, it |
| 339 | 379 | /// means the stream reached the end. Reaching the end of a stream is not an error |
| 340 | 380 | /// condition. |
| 341 | readFn: fn(self: &InStream, buffer: []u8) -> %usize, | |
| 381 | readFn: fn(self: &InStream, buffer: []u8) %usize, | |
| 342 | 382 | |
| 343 | 383 | /// Replaces `buffer` contents by reading from the stream until it is finished. |
| 344 | 384 | /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and |
| 345 | 385 | /// the contents read from the stream are lost. |
| 346 | pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) -> %void { | |
| 386 | pub fn readAllBuffer(self: &InStream, buffer: &Buffer, max_size: usize) %void { | |
| 347 | 387 | try buffer.resize(0); |
| 348 | 388 | |
| 349 | 389 | var actual_buf_len: usize = 0; |
| ... | ... | @@ -368,7 +408,7 @@ pub const InStream = struct { |
| 368 | 408 | /// memory would be greater than `max_size`, returns `error.StreamTooLong`. |
| 369 | 409 | /// Caller owns returned memory. |
| 370 | 410 | /// If this function returns an error, the contents from the stream read so far are lost. |
| 371 | pub fn readAllAlloc(self: &InStream, allocator: &mem.Allocator, max_size: usize) -> %[]u8 { | |
| 411 | pub fn readAllAlloc(self: &InStream, allocator: &mem.Allocator, max_size: usize) %[]u8 { | |
| 372 | 412 | var buf = Buffer.initNull(allocator); |
| 373 | 413 | defer buf.deinit(); |
| 374 | 414 | |
| ... | ... | @@ -380,7 +420,7 @@ pub const InStream = struct { |
| 380 | 420 | /// Does not include the delimiter in the result. |
| 381 | 421 | /// If `buffer.len()` would exceed `max_size`, `error.StreamTooLong` is returned and the contents |
| 382 | 422 | /// read from the stream so far are lost. |
| 383 | pub fn readUntilDelimiterBuffer(self: &InStream, buffer: &Buffer, delimiter: u8, max_size: usize) -> %void { | |
| 423 | pub fn readUntilDelimiterBuffer(self: &InStream, buffer: &Buffer, delimiter: u8, max_size: usize) %void { | |
| 384 | 424 | try buf.resize(0); |
| 385 | 425 | |
| 386 | 426 | while (true) { |
| ... | ... | @@ -403,7 +443,7 @@ pub const InStream = struct { |
| 403 | 443 | /// Caller owns returned memory. |
| 404 | 444 | /// If this function returns an error, the contents from the stream read so far are lost. |
| 405 | 445 | pub fn readUntilDelimiterAlloc(self: &InStream, allocator: &mem.Allocator, |
| 406 | delimiter: u8, max_size: usize) -> %[]u8 | |
| 446 | delimiter: u8, max_size: usize) %[]u8 | |
| 407 | 447 | { |
| 408 | 448 | var buf = Buffer.initNull(allocator); |
| 409 | 449 | defer buf.deinit(); |
| ... | ... | @@ -415,43 +455,43 @@ pub const InStream = struct { |
| 415 | 455 | /// Returns the number of bytes read. If the number read is smaller than buf.len, it |
| 416 | 456 | /// means the stream reached the end. Reaching the end of a stream is not an error |
| 417 | 457 | /// condition. |
| 418 | pub fn read(self: &InStream, buffer: []u8) -> %usize { | |
| 458 | pub fn read(self: &InStream, buffer: []u8) %usize { | |
| 419 | 459 | return self.readFn(self, buffer); |
| 420 | 460 | } |
| 421 | 461 | |
| 422 | 462 | /// Same as `read` but end of stream returns `error.EndOfStream`. |
| 423 | pub fn readNoEof(self: &InStream, buf: []u8) -> %void { | |
| 463 | pub fn readNoEof(self: &InStream, buf: []u8) %void { | |
| 424 | 464 | const amt_read = try self.read(buf); |
| 425 | 465 | if (amt_read < buf.len) return error.EndOfStream; |
| 426 | 466 | } |
| 427 | 467 | |
| 428 | 468 | /// Reads 1 byte from the stream or returns `error.EndOfStream`. |
| 429 | pub fn readByte(self: &InStream) -> %u8 { | |
| 469 | pub fn readByte(self: &InStream) %u8 { | |
| 430 | 470 | var result: [1]u8 = undefined; |
| 431 | 471 | try self.readNoEof(result[0..]); |
| 432 | 472 | return result[0]; |
| 433 | 473 | } |
| 434 | 474 | |
| 435 | 475 | /// Same as `readByte` except the returned byte is signed. |
| 436 | pub fn readByteSigned(self: &InStream) -> %i8 { | |
| 476 | pub fn readByteSigned(self: &InStream) %i8 { | |
| 437 | 477 | return @bitCast(i8, try self.readByte()); |
| 438 | 478 | } |
| 439 | 479 | |
| 440 | pub fn readIntLe(self: &InStream, comptime T: type) -> %T { | |
| 480 | pub fn readIntLe(self: &InStream, comptime T: type) %T { | |
| 441 | 481 | return self.readInt(builtin.Endian.Little, T); |
| 442 | 482 | } |
| 443 | 483 | |
| 444 | pub fn readIntBe(self: &InStream, comptime T: type) -> %T { | |
| 484 | pub fn readIntBe(self: &InStream, comptime T: type) %T { | |
| 445 | 485 | return self.readInt(builtin.Endian.Big, T); |
| 446 | 486 | } |
| 447 | 487 | |
| 448 | pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) -> %T { | |
| 488 | pub fn readInt(self: &InStream, endian: builtin.Endian, comptime T: type) %T { | |
| 449 | 489 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 450 | 490 | try self.readNoEof(bytes[0..]); |
| 451 | 491 | return mem.readInt(bytes, T, endian); |
| 452 | 492 | } |
| 453 | 493 | |
| 454 | pub fn readVarInt(self: &InStream, endian: builtin.Endian, comptime T: type, size: usize) -> %T { | |
| 494 | pub fn readVarInt(self: &InStream, endian: builtin.Endian, comptime T: type, size: usize) %T { | |
| 455 | 495 | assert(size <= @sizeOf(T)); |
| 456 | 496 | assert(size <= 8); |
| 457 | 497 | var input_buf: [8]u8 = undefined; |
| ... | ... | @@ -464,22 +504,22 @@ pub const InStream = struct { |
| 464 | 504 | }; |
| 465 | 505 | |
| 466 | 506 | pub const OutStream = struct { |
| 467 | writeFn: fn(self: &OutStream, bytes: []const u8) -> %void, | |
| 507 | writeFn: fn(self: &OutStream, bytes: []const u8) %void, | |
| 468 | 508 | |
| 469 | pub fn print(self: &OutStream, comptime format: []const u8, args: ...) -> %void { | |
| 509 | pub fn print(self: &OutStream, comptime format: []const u8, args: ...) %void { | |
| 470 | 510 | return std.fmt.format(self, self.writeFn, format, args); |
| 471 | 511 | } |
| 472 | 512 | |
| 473 | pub fn write(self: &OutStream, bytes: []const u8) -> %void { | |
| 513 | pub fn write(self: &OutStream, bytes: []const u8) %void { | |
| 474 | 514 | return self.writeFn(self, bytes); |
| 475 | 515 | } |
| 476 | 516 | |
| 477 | pub fn writeByte(self: &OutStream, byte: u8) -> %void { | |
| 517 | pub fn writeByte(self: &OutStream, byte: u8) %void { | |
| 478 | 518 | const slice = (&byte)[0..1]; |
| 479 | 519 | return self.writeFn(self, slice); |
| 480 | 520 | } |
| 481 | 521 | |
| 482 | pub fn writeByteNTimes(self: &OutStream, byte: u8, n: usize) -> %void { | |
| 522 | pub fn writeByteNTimes(self: &OutStream, byte: u8, n: usize) %void { | |
| 483 | 523 | const slice = (&byte)[0..1]; |
| 484 | 524 | var i: usize = 0; |
| 485 | 525 | while (i < n) : (i += 1) { |
| ... | ... | @@ -492,25 +532,25 @@ pub const OutStream = struct { |
| 492 | 532 | /// a fixed size buffer of size `std.os.max_noalloc_path_len` is an attempted solution. If the fixed |
| 493 | 533 | /// size buffer is too small, and the provided allocator is null, `error.NameTooLong` is returned. |
| 494 | 534 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. |
| 495 | pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator) -> %void { | |
| 535 | pub fn writeFile(path: []const u8, data: []const u8, allocator: ?&mem.Allocator) %void { | |
| 496 | 536 | var file = try File.openWrite(path, allocator); |
| 497 | 537 | defer file.close(); |
| 498 | 538 | try file.write(data); |
| 499 | 539 | } |
| 500 | 540 | |
| 501 | 541 | /// On success, caller owns returned buffer. |
| 502 | pub fn readFileAlloc(path: []const u8, allocator: &mem.Allocator) -> %[]u8 { | |
| 542 | pub fn readFileAlloc(path: []const u8, allocator: &mem.Allocator) %[]u8 { | |
| 503 | 543 | return readFileAllocExtra(path, allocator, 0); |
| 504 | 544 | } |
| 505 | 545 | /// On success, caller owns returned buffer. |
| 506 | 546 | /// Allocates extra_len extra bytes at the end of the file buffer, which are uninitialized. |
| 507 | pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len: usize) -> %[]u8 { | |
| 547 | pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len: usize) %[]u8 { | |
| 508 | 548 | var file = try File.openRead(path, allocator); |
| 509 | 549 | defer file.close(); |
| 510 | 550 | |
| 511 | 551 | const size = try file.getEndPos(); |
| 512 | 552 | const buf = try allocator.alloc(u8, size + extra_len); |
| 513 | %defer allocator.free(buf); | |
| 553 | errdefer allocator.free(buf); | |
| 514 | 554 | |
| 515 | 555 | var adapter = FileInStream.init(&file); |
| 516 | 556 | try adapter.stream.readNoEof(buf[0..size]); |
| ... | ... | @@ -519,7 +559,7 @@ pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len |
| 519 | 559 | |
| 520 | 560 | pub const BufferedInStream = BufferedInStreamCustom(os.page_size); |
| 521 | 561 | |
| 522 | pub fn BufferedInStreamCustom(comptime buffer_size: usize) -> type { | |
| 562 | pub fn BufferedInStreamCustom(comptime buffer_size: usize) type { | |
| 523 | 563 | return struct { |
| 524 | 564 | const Self = this; |
| 525 | 565 | |
| ... | ... | @@ -531,7 +571,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize) -> type { |
| 531 | 571 | start_index: usize, |
| 532 | 572 | end_index: usize, |
| 533 | 573 | |
| 534 | pub fn init(unbuffered_in_stream: &InStream) -> Self { | |
| 574 | pub fn init(unbuffered_in_stream: &InStream) Self { | |
| 535 | 575 | return Self { |
| 536 | 576 | .unbuffered_in_stream = unbuffered_in_stream, |
| 537 | 577 | .buffer = undefined, |
| ... | ... | @@ -549,7 +589,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize) -> type { |
| 549 | 589 | }; |
| 550 | 590 | } |
| 551 | 591 | |
| 552 | fn readFn(in_stream: &InStream, dest: []u8) -> %usize { | |
| 592 | fn readFn(in_stream: &InStream, dest: []u8) %usize { | |
| 553 | 593 | const self = @fieldParentPtr(Self, "stream", in_stream); |
| 554 | 594 | |
| 555 | 595 | var dest_index: usize = 0; |
| ... | ... | @@ -590,7 +630,7 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize) -> type { |
| 590 | 630 | |
| 591 | 631 | pub const BufferedOutStream = BufferedOutStreamCustom(os.page_size); |
| 592 | 632 | |
| 593 | pub fn BufferedOutStreamCustom(comptime buffer_size: usize) -> type { | |
| 633 | pub fn BufferedOutStreamCustom(comptime buffer_size: usize) type { | |
| 594 | 634 | return struct { |
| 595 | 635 | const Self = this; |
| 596 | 636 | |
| ... | ... | @@ -601,7 +641,7 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize) -> type { |
| 601 | 641 | buffer: [buffer_size]u8, |
| 602 | 642 | index: usize, |
| 603 | 643 | |
| 604 | pub fn init(unbuffered_out_stream: &OutStream) -> Self { | |
| 644 | pub fn init(unbuffered_out_stream: &OutStream) Self { | |
| 605 | 645 | return Self { |
| 606 | 646 | .unbuffered_out_stream = unbuffered_out_stream, |
| 607 | 647 | .buffer = undefined, |
| ... | ... | @@ -612,7 +652,7 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize) -> type { |
| 612 | 652 | }; |
| 613 | 653 | } |
| 614 | 654 | |
| 615 | pub fn flush(self: &Self) -> %void { | |
| 655 | pub fn flush(self: &Self) %void { | |
| 616 | 656 | if (self.index == 0) |
| 617 | 657 | return; |
| 618 | 658 | |
| ... | ... | @@ -620,7 +660,7 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize) -> type { |
| 620 | 660 | self.index = 0; |
| 621 | 661 | } |
| 622 | 662 | |
| 623 | fn writeFn(out_stream: &OutStream, bytes: []const u8) -> %void { | |
| 663 | fn writeFn(out_stream: &OutStream, bytes: []const u8) %void { | |
| 624 | 664 | const self = @fieldParentPtr(Self, "stream", out_stream); |
| 625 | 665 | |
| 626 | 666 | if (bytes.len >= self.buffer.len) { |
| ... | ... | @@ -649,7 +689,7 @@ pub const BufferOutStream = struct { |
| 649 | 689 | buffer: &Buffer, |
| 650 | 690 | stream: OutStream, |
| 651 | 691 | |
| 652 | pub fn init(buffer: &Buffer) -> BufferOutStream { | |
| 692 | pub fn init(buffer: &Buffer) BufferOutStream { | |
| 653 | 693 | return BufferOutStream { |
| 654 | 694 | .buffer = buffer, |
| 655 | 695 | .stream = OutStream { |
| ... | ... | @@ -658,7 +698,7 @@ pub const BufferOutStream = struct { |
| 658 | 698 | }; |
| 659 | 699 | } |
| 660 | 700 | |
| 661 | fn writeFn(out_stream: &OutStream, bytes: []const u8) -> %void { | |
| 701 | fn writeFn(out_stream: &OutStream, bytes: []const u8) %void { | |
| 662 | 702 | const self = @fieldParentPtr(BufferOutStream, "stream", out_stream); |
| 663 | 703 | return self.buffer.append(bytes); |
| 664 | 704 | } |
std/linked_list.zig+18-18| ... | ... | @@ -5,17 +5,17 @@ const mem = std.mem; |
| 5 | 5 | const Allocator = mem.Allocator; |
| 6 | 6 | |
| 7 | 7 | /// Generic non-intrusive doubly linked list. |
| 8 | pub fn LinkedList(comptime T: type) -> type { | |
| 8 | pub fn LinkedList(comptime T: type) type { | |
| 9 | 9 | return BaseLinkedList(T, void, ""); |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | 12 | /// Generic intrusive doubly linked list. |
| 13 | pub fn IntrusiveLinkedList(comptime ParentType: type, comptime field_name: []const u8) -> type { | |
| 13 | pub fn IntrusiveLinkedList(comptime ParentType: type, comptime field_name: []const u8) type { | |
| 14 | 14 | return BaseLinkedList(void, ParentType, field_name); |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | 17 | /// Generic doubly linked list. |
| 18 | fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_name: []const u8) -> type { | |
| 18 | fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_name: []const u8) type { | |
| 19 | 19 | return struct { |
| 20 | 20 | const Self = this; |
| 21 | 21 | |
| ... | ... | @@ -25,7 +25,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 25 | 25 | next: ?&Node, |
| 26 | 26 | data: T, |
| 27 | 27 | |
| 28 | pub fn init(value: &const T) -> Node { | |
| 28 | pub fn init(value: &const T) Node { | |
| 29 | 29 | return Node { |
| 30 | 30 | .prev = null, |
| 31 | 31 | .next = null, |
| ... | ... | @@ -33,12 +33,12 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 33 | 33 | }; |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | pub fn initIntrusive() -> Node { | |
| 36 | pub fn initIntrusive() Node { | |
| 37 | 37 | // TODO: when #678 is solved this can become `init`. |
| 38 | 38 | return Node.init({}); |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | pub fn toData(node: &Node) -> &ParentType { | |
| 41 | pub fn toData(node: &Node) &ParentType { | |
| 42 | 42 | comptime assert(isIntrusive()); |
| 43 | 43 | return @fieldParentPtr(ParentType, field_name, node); |
| 44 | 44 | } |
| ... | ... | @@ -52,7 +52,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 52 | 52 | /// |
| 53 | 53 | /// Returns: |
| 54 | 54 | /// An empty linked list. |
| 55 | pub fn init() -> Self { | |
| 55 | pub fn init() Self { | |
| 56 | 56 | return Self { |
| 57 | 57 | .first = null, |
| 58 | 58 | .last = null, |
| ... | ... | @@ -60,7 +60,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 60 | 60 | }; |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | fn isIntrusive() -> bool { | |
| 63 | fn isIntrusive() bool { | |
| 64 | 64 | return ParentType != void or field_name.len != 0; |
| 65 | 65 | } |
| 66 | 66 | |
| ... | ... | @@ -69,7 +69,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 69 | 69 | /// Arguments: |
| 70 | 70 | /// node: Pointer to a node in the list. |
| 71 | 71 | /// new_node: Pointer to the new node to insert. |
| 72 | pub fn insertAfter(list: &Self, node: &Node, new_node: &Node) { | |
| 72 | pub fn insertAfter(list: &Self, node: &Node, new_node: &Node) void { | |
| 73 | 73 | new_node.prev = node; |
| 74 | 74 | if (node.next) |next_node| { |
| 75 | 75 | // Intermediate node. |
| ... | ... | @@ -90,7 +90,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 90 | 90 | /// Arguments: |
| 91 | 91 | /// node: Pointer to a node in the list. |
| 92 | 92 | /// new_node: Pointer to the new node to insert. |
| 93 | pub fn insertBefore(list: &Self, node: &Node, new_node: &Node) { | |
| 93 | pub fn insertBefore(list: &Self, node: &Node, new_node: &Node) void { | |
| 94 | 94 | new_node.next = node; |
| 95 | 95 | if (node.prev) |prev_node| { |
| 96 | 96 | // Intermediate node. |
| ... | ... | @@ -110,7 +110,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 110 | 110 | /// |
| 111 | 111 | /// Arguments: |
| 112 | 112 | /// new_node: Pointer to the new node to insert. |
| 113 | pub fn append(list: &Self, new_node: &Node) { | |
| 113 | pub fn append(list: &Self, new_node: &Node) void { | |
| 114 | 114 | if (list.last) |last| { |
| 115 | 115 | // Insert after last. |
| 116 | 116 | list.insertAfter(last, new_node); |
| ... | ... | @@ -124,7 +124,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 124 | 124 | /// |
| 125 | 125 | /// Arguments: |
| 126 | 126 | /// new_node: Pointer to the new node to insert. |
| 127 | pub fn prepend(list: &Self, new_node: &Node) { | |
| 127 | pub fn prepend(list: &Self, new_node: &Node) void { | |
| 128 | 128 | if (list.first) |first| { |
| 129 | 129 | // Insert before first. |
| 130 | 130 | list.insertBefore(first, new_node); |
| ... | ... | @@ -143,7 +143,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 143 | 143 | /// |
| 144 | 144 | /// Arguments: |
| 145 | 145 | /// node: Pointer to the node to be removed. |
| 146 | pub fn remove(list: &Self, node: &Node) { | |
| 146 | pub fn remove(list: &Self, node: &Node) void { | |
| 147 | 147 | if (node.prev) |prev_node| { |
| 148 | 148 | // Intermediate node. |
| 149 | 149 | prev_node.next = node.next; |
| ... | ... | @@ -167,7 +167,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 167 | 167 | /// |
| 168 | 168 | /// Returns: |
| 169 | 169 | /// A pointer to the last node in the list. |
| 170 | pub fn pop(list: &Self) -> ?&Node { | |
| 170 | pub fn pop(list: &Self) ?&Node { | |
| 171 | 171 | const last = list.last ?? return null; |
| 172 | 172 | list.remove(last); |
| 173 | 173 | return last; |
| ... | ... | @@ -177,7 +177,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 177 | 177 | /// |
| 178 | 178 | /// Returns: |
| 179 | 179 | /// A pointer to the first node in the list. |
| 180 | pub fn popFirst(list: &Self) -> ?&Node { | |
| 180 | pub fn popFirst(list: &Self) ?&Node { | |
| 181 | 181 | const first = list.first ?? return null; |
| 182 | 182 | list.remove(first); |
| 183 | 183 | return first; |
| ... | ... | @@ -190,7 +190,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 190 | 190 | /// |
| 191 | 191 | /// Returns: |
| 192 | 192 | /// A pointer to the new node. |
| 193 | pub fn allocateNode(list: &Self, allocator: &Allocator) -> %&Node { | |
| 193 | pub fn allocateNode(list: &Self, allocator: &Allocator) %&Node { | |
| 194 | 194 | comptime assert(!isIntrusive()); |
| 195 | 195 | return allocator.create(Node); |
| 196 | 196 | } |
| ... | ... | @@ -200,7 +200,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 200 | 200 | /// Arguments: |
| 201 | 201 | /// node: Pointer to the node to deallocate. |
| 202 | 202 | /// allocator: Dynamic memory allocator. |
| 203 | pub fn destroyNode(list: &Self, node: &Node, allocator: &Allocator) { | |
| 203 | pub fn destroyNode(list: &Self, node: &Node, allocator: &Allocator) void { | |
| 204 | 204 | comptime assert(!isIntrusive()); |
| 205 | 205 | allocator.destroy(node); |
| 206 | 206 | } |
| ... | ... | @@ -213,7 +213,7 @@ fn BaseLinkedList(comptime T: type, comptime ParentType: type, comptime field_na |
| 213 | 213 | /// |
| 214 | 214 | /// Returns: |
| 215 | 215 | /// A pointer to the new node. |
| 216 | pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) -> %&Node { | |
| 216 | pub fn createNode(list: &Self, data: &const T, allocator: &Allocator) %&Node { | |
| 217 | 217 | comptime assert(!isIntrusive()); |
| 218 | 218 | var node = try list.allocateNode(allocator); |
| 219 | 219 | *node = Node.init(data); |
std/math/acos.zig+5-5| ... | ... | @@ -6,7 +6,7 @@ const std = @import("../index.zig"); |
| 6 | 6 | const math = std.math; |
| 7 | 7 | const assert = std.debug.assert; |
| 8 | 8 | |
| 9 | pub fn acos(x: var) -> @typeOf(x) { | |
| 9 | pub fn acos(x: var) @typeOf(x) { | |
| 10 | 10 | const T = @typeOf(x); |
| 11 | 11 | return switch (T) { |
| 12 | 12 | f32 => acos32(x), |
| ... | ... | @@ -15,7 +15,7 @@ pub fn acos(x: var) -> @typeOf(x) { |
| 15 | 15 | }; |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | fn r32(z: f32) -> f32 { | |
| 18 | fn r32(z: f32) f32 { | |
| 19 | 19 | const pS0 = 1.6666586697e-01; |
| 20 | 20 | const pS1 = -4.2743422091e-02; |
| 21 | 21 | const pS2 = -8.6563630030e-03; |
| ... | ... | @@ -26,7 +26,7 @@ fn r32(z: f32) -> f32 { |
| 26 | 26 | return p / q; |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | fn acos32(x: f32) -> f32 { | |
| 29 | fn acos32(x: f32) f32 { | |
| 30 | 30 | const pio2_hi = 1.5707962513e+00; |
| 31 | 31 | const pio2_lo = 7.5497894159e-08; |
| 32 | 32 | |
| ... | ... | @@ -73,7 +73,7 @@ fn acos32(x: f32) -> f32 { |
| 73 | 73 | return 2 * (df + w); |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | fn r64(z: f64) -> f64 { | |
| 76 | fn r64(z: f64) f64 { | |
| 77 | 77 | const pS0: f64 = 1.66666666666666657415e-01; |
| 78 | 78 | const pS1: f64 = -3.25565818622400915405e-01; |
| 79 | 79 | const pS2: f64 = 2.01212532134862925881e-01; |
| ... | ... | @@ -90,7 +90,7 @@ fn r64(z: f64) -> f64 { |
| 90 | 90 | return p / q; |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | fn acos64(x: f64) -> f64 { | |
| 93 | fn acos64(x: f64) f64 { | |
| 94 | 94 | const pio2_hi: f64 = 1.57079632679489655800e+00; |
| 95 | 95 | const pio2_lo: f64 = 6.12323399573676603587e-17; |
| 96 | 96 |
std/math/acosh.zig+3-3| ... | ... | @@ -8,7 +8,7 @@ const std = @import("../index.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const assert = std.debug.assert; |
| 10 | 10 | |
| 11 | pub fn acosh(x: var) -> @typeOf(x) { | |
| 11 | pub fn acosh(x: var) @typeOf(x) { | |
| 12 | 12 | const T = @typeOf(x); |
| 13 | 13 | return switch (T) { |
| 14 | 14 | f32 => acosh32(x), |
| ... | ... | @@ -18,7 +18,7 @@ pub fn acosh(x: var) -> @typeOf(x) { |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | // acosh(x) = log(x + sqrt(x * x - 1)) |
| 21 | fn acosh32(x: f32) -> f32 { | |
| 21 | fn acosh32(x: f32) f32 { | |
| 22 | 22 | const u = @bitCast(u32, x); |
| 23 | 23 | const i = u & 0x7FFFFFFF; |
| 24 | 24 | |
| ... | ... | @@ -36,7 +36,7 @@ fn acosh32(x: f32) -> f32 { |
| 36 | 36 | } |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | fn acosh64(x: f64) -> f64 { | |
| 39 | fn acosh64(x: f64) f64 { | |
| 40 | 40 | const u = @bitCast(u64, x); |
| 41 | 41 | const e = (u >> 52) & 0x7FF; |
| 42 | 42 |
std/math/asin.zig+5-5| ... | ... | @@ -7,7 +7,7 @@ const std = @import("../index.zig"); |
| 7 | 7 | const math = std.math; |
| 8 | 8 | const assert = std.debug.assert; |
| 9 | 9 | |
| 10 | pub fn asin(x: var) -> @typeOf(x) { | |
| 10 | pub fn asin(x: var) @typeOf(x) { | |
| 11 | 11 | const T = @typeOf(x); |
| 12 | 12 | return switch (T) { |
| 13 | 13 | f32 => asin32(x), |
| ... | ... | @@ -16,7 +16,7 @@ pub fn asin(x: var) -> @typeOf(x) { |
| 16 | 16 | }; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | fn r32(z: f32) -> f32 { | |
| 19 | fn r32(z: f32) f32 { | |
| 20 | 20 | const pS0 = 1.6666586697e-01; |
| 21 | 21 | const pS1 = -4.2743422091e-02; |
| 22 | 22 | const pS2 = -8.6563630030e-03; |
| ... | ... | @@ -27,7 +27,7 @@ fn r32(z: f32) -> f32 { |
| 27 | 27 | return p / q; |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | fn asin32(x: f32) -> f32 { | |
| 30 | fn asin32(x: f32) f32 { | |
| 31 | 31 | const pio2 = 1.570796326794896558e+00; |
| 32 | 32 | |
| 33 | 33 | const hx: u32 = @bitCast(u32, x); |
| ... | ... | @@ -65,7 +65,7 @@ fn asin32(x: f32) -> f32 { |
| 65 | 65 | } |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | fn r64(z: f64) -> f64 { | |
| 68 | fn r64(z: f64) f64 { | |
| 69 | 69 | const pS0: f64 = 1.66666666666666657415e-01; |
| 70 | 70 | const pS1: f64 = -3.25565818622400915405e-01; |
| 71 | 71 | const pS2: f64 = 2.01212532134862925881e-01; |
| ... | ... | @@ -82,7 +82,7 @@ fn r64(z: f64) -> f64 { |
| 82 | 82 | return p / q; |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | fn asin64(x: f64) -> f64 { | |
| 85 | fn asin64(x: f64) f64 { | |
| 86 | 86 | const pio2_hi: f64 = 1.57079632679489655800e+00; |
| 87 | 87 | const pio2_lo: f64 = 6.12323399573676603587e-17; |
| 88 | 88 |
std/math/asinh.zig+3-3| ... | ... | @@ -8,7 +8,7 @@ const std = @import("../index.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const assert = std.debug.assert; |
| 10 | 10 | |
| 11 | pub fn asinh(x: var) -> @typeOf(x) { | |
| 11 | pub fn asinh(x: var) @typeOf(x) { | |
| 12 | 12 | const T = @typeOf(x); |
| 13 | 13 | return switch (T) { |
| 14 | 14 | f32 => asinh32(x), |
| ... | ... | @@ -18,7 +18,7 @@ pub fn asinh(x: var) -> @typeOf(x) { |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | // asinh(x) = sign(x) * log(|x| + sqrt(x * x + 1)) ~= x - x^3/6 + o(x^5) |
| 21 | fn asinh32(x: f32) -> f32 { | |
| 21 | fn asinh32(x: f32) f32 { | |
| 22 | 22 | const u = @bitCast(u32, x); |
| 23 | 23 | const i = u & 0x7FFFFFFF; |
| 24 | 24 | const s = i >> 31; |
| ... | ... | @@ -50,7 +50,7 @@ fn asinh32(x: f32) -> f32 { |
| 50 | 50 | return if (s != 0) -rx else rx; |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | fn asinh64(x: f64) -> f64 { | |
| 53 | fn asinh64(x: f64) f64 { | |
| 54 | 54 | const u = @bitCast(u64, x); |
| 55 | 55 | const e = (u >> 52) & 0x7FF; |
| 56 | 56 | const s = u >> 63; |
std/math/atan.zig+3-3| ... | ... | @@ -7,7 +7,7 @@ const std = @import("../index.zig"); |
| 7 | 7 | const math = std.math; |
| 8 | 8 | const assert = std.debug.assert; |
| 9 | 9 | |
| 10 | pub fn atan(x: var) -> @typeOf(x) { | |
| 10 | pub fn atan(x: var) @typeOf(x) { | |
| 11 | 11 | const T = @typeOf(x); |
| 12 | 12 | return switch (T) { |
| 13 | 13 | f32 => atan32(x), |
| ... | ... | @@ -16,7 +16,7 @@ pub fn atan(x: var) -> @typeOf(x) { |
| 16 | 16 | }; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | fn atan32(x_: f32) -> f32 { | |
| 19 | fn atan32(x_: f32) f32 { | |
| 20 | 20 | const atanhi = []const f32 { |
| 21 | 21 | 4.6364760399e-01, // atan(0.5)hi |
| 22 | 22 | 7.8539812565e-01, // atan(1.0)hi |
| ... | ... | @@ -108,7 +108,7 @@ fn atan32(x_: f32) -> f32 { |
| 108 | 108 | } |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | fn atan64(x_: f64) -> f64 { | |
| 111 | fn atan64(x_: f64) f64 { | |
| 112 | 112 | const atanhi = []const f64 { |
| 113 | 113 | 4.63647609000806093515e-01, // atan(0.5)hi |
| 114 | 114 | 7.85398163397448278999e-01, // atan(1.0)hi |
std/math/atan2.zig+3-3| ... | ... | @@ -22,7 +22,7 @@ const std = @import("../index.zig"); |
| 22 | 22 | const math = std.math; |
| 23 | 23 | const assert = std.debug.assert; |
| 24 | 24 | |
| 25 | fn atan2(comptime T: type, x: T, y: T) -> T { | |
| 25 | fn atan2(comptime T: type, x: T, y: T) T { | |
| 26 | 26 | return switch (T) { |
| 27 | 27 | f32 => atan2_32(x, y), |
| 28 | 28 | f64 => atan2_64(x, y), |
| ... | ... | @@ -30,7 +30,7 @@ fn atan2(comptime T: type, x: T, y: T) -> T { |
| 30 | 30 | }; |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | fn atan2_32(y: f32, x: f32) -> f32 { | |
| 33 | fn atan2_32(y: f32, x: f32) f32 { | |
| 34 | 34 | const pi: f32 = 3.1415927410e+00; |
| 35 | 35 | const pi_lo: f32 = -8.7422776573e-08; |
| 36 | 36 | |
| ... | ... | @@ -115,7 +115,7 @@ fn atan2_32(y: f32, x: f32) -> f32 { |
| 115 | 115 | } |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | fn atan2_64(y: f64, x: f64) -> f64 { | |
| 118 | fn atan2_64(y: f64, x: f64) f64 { | |
| 119 | 119 | const pi: f64 = 3.1415926535897931160E+00; |
| 120 | 120 | const pi_lo: f64 = 1.2246467991473531772E-16; |
| 121 | 121 |
std/math/atanh.zig+3-3| ... | ... | @@ -8,7 +8,7 @@ const std = @import("../index.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const assert = std.debug.assert; |
| 10 | 10 | |
| 11 | pub fn atanh(x: var) -> @typeOf(x) { | |
| 11 | pub fn atanh(x: var) @typeOf(x) { | |
| 12 | 12 | const T = @typeOf(x); |
| 13 | 13 | return switch (T) { |
| 14 | 14 | f32 => atanh_32(x), |
| ... | ... | @@ -18,7 +18,7 @@ pub fn atanh(x: var) -> @typeOf(x) { |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | // atanh(x) = log((1 + x) / (1 - x)) / 2 = log1p(2x / (1 - x)) / 2 ~= x + x^3 / 3 + o(x^5) |
| 21 | fn atanh_32(x: f32) -> f32 { | |
| 21 | fn atanh_32(x: f32) f32 { | |
| 22 | 22 | const u = @bitCast(u32, x); |
| 23 | 23 | const i = u & 0x7FFFFFFF; |
| 24 | 24 | const s = u >> 31; |
| ... | ... | @@ -47,7 +47,7 @@ fn atanh_32(x: f32) -> f32 { |
| 47 | 47 | return if (s != 0) -y else y; |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | fn atanh_64(x: f64) -> f64 { | |
| 50 | fn atanh_64(x: f64) f64 { | |
| 51 | 51 | const u = @bitCast(u64, x); |
| 52 | 52 | const e = (u >> 52) & 0x7FF; |
| 53 | 53 | const s = u >> 63; |
std/math/cbrt.zig+3-3| ... | ... | @@ -8,7 +8,7 @@ const std = @import("../index.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const assert = std.debug.assert; |
| 10 | 10 | |
| 11 | pub fn cbrt(x: var) -> @typeOf(x) { | |
| 11 | pub fn cbrt(x: var) @typeOf(x) { | |
| 12 | 12 | const T = @typeOf(x); |
| 13 | 13 | return switch (T) { |
| 14 | 14 | f32 => cbrt32(x), |
| ... | ... | @@ -17,7 +17,7 @@ pub fn cbrt(x: var) -> @typeOf(x) { |
| 17 | 17 | }; |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | fn cbrt32(x: f32) -> f32 { | |
| 20 | fn cbrt32(x: f32) f32 { | |
| 21 | 21 | const B1: u32 = 709958130; // (127 - 127.0 / 3 - 0.03306235651) * 2^23 |
| 22 | 22 | const B2: u32 = 642849266; // (127 - 127.0 / 3 - 24 / 3 - 0.03306235651) * 2^23 |
| 23 | 23 | |
| ... | ... | @@ -57,7 +57,7 @@ fn cbrt32(x: f32) -> f32 { |
| 57 | 57 | return f32(t); |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | fn cbrt64(x: f64) -> f64 { | |
| 60 | fn cbrt64(x: f64) f64 { | |
| 61 | 61 | const B1: u32 = 715094163; // (1023 - 1023 / 3 - 0.03306235651 * 2^20 |
| 62 | 62 | const B2: u32 = 696219795; // (1023 - 1023 / 3 - 54 / 3 - 0.03306235651 * 2^20 |
| 63 | 63 |
std/math/ceil.zig+3-3| ... | ... | @@ -9,7 +9,7 @@ const std = @import("../index.zig"); |
| 9 | 9 | const math = std.math; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | 11 | |
| 12 | pub fn ceil(x: var) -> @typeOf(x) { | |
| 12 | pub fn ceil(x: var) @typeOf(x) { | |
| 13 | 13 | const T = @typeOf(x); |
| 14 | 14 | return switch (T) { |
| 15 | 15 | f32 => ceil32(x), |
| ... | ... | @@ -18,7 +18,7 @@ pub fn ceil(x: var) -> @typeOf(x) { |
| 18 | 18 | }; |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | fn ceil32(x: f32) -> f32 { | |
| 21 | fn ceil32(x: f32) f32 { | |
| 22 | 22 | var u = @bitCast(u32, x); |
| 23 | 23 | var e = i32((u >> 23) & 0xFF) - 0x7F; |
| 24 | 24 | var m: u32 = undefined; |
| ... | ... | @@ -51,7 +51,7 @@ fn ceil32(x: f32) -> f32 { |
| 51 | 51 | } |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | fn ceil64(x: f64) -> f64 { | |
| 54 | fn ceil64(x: f64) f64 { | |
| 55 | 55 | const u = @bitCast(u64, x); |
| 56 | 56 | const e = (u >> 52) & 0x7FF; |
| 57 | 57 | var y: f64 = undefined; |
std/math/copysign.zig+3-3| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | |
| 5 | pub fn copysign(comptime T: type, x: T, y: T) -> T { | |
| 5 | pub fn copysign(comptime T: type, x: T, y: T) T { | |
| 6 | 6 | return switch (T) { |
| 7 | 7 | f32 => copysign32(x, y), |
| 8 | 8 | f64 => copysign64(x, y), |
| ... | ... | @@ -10,7 +10,7 @@ pub fn copysign(comptime T: type, x: T, y: T) -> T { |
| 10 | 10 | }; |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | fn copysign32(x: f32, y: f32) -> f32 { | |
| 13 | fn copysign32(x: f32, y: f32) f32 { | |
| 14 | 14 | const ux = @bitCast(u32, x); |
| 15 | 15 | const uy = @bitCast(u32, y); |
| 16 | 16 | |
| ... | ... | @@ -19,7 +19,7 @@ fn copysign32(x: f32, y: f32) -> f32 { |
| 19 | 19 | return @bitCast(f32, h1 | h2); |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | fn copysign64(x: f64, y: f64) -> f64 { | |
| 22 | fn copysign64(x: f64, y: f64) f64 { | |
| 23 | 23 | const ux = @bitCast(u64, x); |
| 24 | 24 | const uy = @bitCast(u64, y); |
| 25 | 25 |
std/math/cos.zig+3-3| ... | ... | @@ -8,7 +8,7 @@ const std = @import("../index.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const assert = std.debug.assert; |
| 10 | 10 | |
| 11 | pub fn cos(x: var) -> @typeOf(x) { | |
| 11 | pub fn cos(x: var) @typeOf(x) { | |
| 12 | 12 | const T = @typeOf(x); |
| 13 | 13 | return switch (T) { |
| 14 | 14 | f32 => cos32(x), |
| ... | ... | @@ -36,7 +36,7 @@ const C5 = 4.16666666666665929218E-2; |
| 36 | 36 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. |
| 37 | 37 | // |
| 38 | 38 | // This may have slight differences on some edge cases and may need to replaced if so. |
| 39 | fn cos32(x_: f32) -> f32 { | |
| 39 | fn cos32(x_: f32) f32 { | |
| 40 | 40 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 41 | 41 | |
| 42 | 42 | const pi4a = 7.85398125648498535156e-1; |
| ... | ... | @@ -89,7 +89,7 @@ fn cos32(x_: f32) -> f32 { |
| 89 | 89 | } |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | fn cos64(x_: f64) -> f64 { | |
| 92 | fn cos64(x_: f64) f64 { | |
| 93 | 93 | const pi4a = 7.85398125648498535156e-1; |
| 94 | 94 | const pi4b = 3.77489470793079817668E-8; |
| 95 | 95 | const pi4c = 2.69515142907905952645E-15; |
std/math/cosh.zig+3-3| ... | ... | @@ -10,7 +10,7 @@ const math = std.math; |
| 10 | 10 | const expo2 = @import("expo2.zig").expo2; |
| 11 | 11 | const assert = std.debug.assert; |
| 12 | 12 | |
| 13 | pub fn cosh(x: var) -> @typeOf(x) { | |
| 13 | pub fn cosh(x: var) @typeOf(x) { | |
| 14 | 14 | const T = @typeOf(x); |
| 15 | 15 | return switch (T) { |
| 16 | 16 | f32 => cosh32(x), |
| ... | ... | @@ -22,7 +22,7 @@ pub fn cosh(x: var) -> @typeOf(x) { |
| 22 | 22 | // cosh(x) = (exp(x) + 1 / exp(x)) / 2 |
| 23 | 23 | // = 1 + 0.5 * (exp(x) - 1) * (exp(x) - 1) / exp(x) |
| 24 | 24 | // = 1 + (x * x) / 2 + o(x^4) |
| 25 | fn cosh32(x: f32) -> f32 { | |
| 25 | fn cosh32(x: f32) f32 { | |
| 26 | 26 | const u = @bitCast(u32, x); |
| 27 | 27 | const ux = u & 0x7FFFFFFF; |
| 28 | 28 | const ax = @bitCast(f32, ux); |
| ... | ... | @@ -47,7 +47,7 @@ fn cosh32(x: f32) -> f32 { |
| 47 | 47 | return expo2(ax); |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | fn cosh64(x: f64) -> f64 { | |
| 50 | fn cosh64(x: f64) f64 { | |
| 51 | 51 | const u = @bitCast(u64, x); |
| 52 | 52 | const w = u32(u >> 32); |
| 53 | 53 | const ax = @bitCast(f64, u & (@maxValue(u64) >> 1)); |
std/math/exp.zig+3-3| ... | ... | @@ -7,7 +7,7 @@ const std = @import("../index.zig"); |
| 7 | 7 | const math = std.math; |
| 8 | 8 | const assert = std.debug.assert; |
| 9 | 9 | |
| 10 | pub fn exp(x: var) -> @typeOf(x) { | |
| 10 | pub fn exp(x: var) @typeOf(x) { | |
| 11 | 11 | const T = @typeOf(x); |
| 12 | 12 | return switch (T) { |
| 13 | 13 | f32 => exp32(x), |
| ... | ... | @@ -16,7 +16,7 @@ pub fn exp(x: var) -> @typeOf(x) { |
| 16 | 16 | }; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | fn exp32(x_: f32) -> f32 { | |
| 19 | fn exp32(x_: f32) f32 { | |
| 20 | 20 | const half = []f32 { 0.5, -0.5 }; |
| 21 | 21 | const ln2hi = 6.9314575195e-1; |
| 22 | 22 | const ln2lo = 1.4286067653e-6; |
| ... | ... | @@ -93,7 +93,7 @@ fn exp32(x_: f32) -> f32 { |
| 93 | 93 | } |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | fn exp64(x_: f64) -> f64 { | |
| 96 | fn exp64(x_: f64) f64 { | |
| 97 | 97 | const half = []const f64 { 0.5, -0.5 }; |
| 98 | 98 | const ln2hi: f64 = 6.93147180369123816490e-01; |
| 99 | 99 | const ln2lo: f64 = 1.90821492927058770002e-10; |
std/math/exp2.zig+3-3| ... | ... | @@ -7,7 +7,7 @@ const std = @import("../index.zig"); |
| 7 | 7 | const math = std.math; |
| 8 | 8 | const assert = std.debug.assert; |
| 9 | 9 | |
| 10 | pub fn exp2(x: var) -> @typeOf(x) { | |
| 10 | pub fn exp2(x: var) @typeOf(x) { | |
| 11 | 11 | const T = @typeOf(x); |
| 12 | 12 | return switch (T) { |
| 13 | 13 | f32 => exp2_32(x), |
| ... | ... | @@ -35,7 +35,7 @@ const exp2ft = []const f64 { |
| 35 | 35 | 0x1.5ab07dd485429p+0, |
| 36 | 36 | }; |
| 37 | 37 | |
| 38 | fn exp2_32(x: f32) -> f32 { | |
| 38 | fn exp2_32(x: f32) f32 { | |
| 39 | 39 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 40 | 40 | |
| 41 | 41 | const tblsiz = u32(exp2ft.len); |
| ... | ... | @@ -352,7 +352,7 @@ const exp2dt = []f64 { |
| 352 | 352 | 0x1.690f4b19e9471p+0, -0x1.9780p-45, |
| 353 | 353 | }; |
| 354 | 354 | |
| 355 | fn exp2_64(x: f64) -> f64 { | |
| 355 | fn exp2_64(x: f64) f64 { | |
| 356 | 356 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 357 | 357 | |
| 358 | 358 | const tblsiz = u32(exp2dt.len / 2); |
std/math/expm1.zig+3-3| ... | ... | @@ -9,7 +9,7 @@ const std = @import("../index.zig"); |
| 9 | 9 | const math = std.math; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | 11 | |
| 12 | pub fn expm1(x: var) -> @typeOf(x) { | |
| 12 | pub fn expm1(x: var) @typeOf(x) { | |
| 13 | 13 | const T = @typeOf(x); |
| 14 | 14 | return switch (T) { |
| 15 | 15 | f32 => expm1_32(x), |
| ... | ... | @@ -18,7 +18,7 @@ pub fn expm1(x: var) -> @typeOf(x) { |
| 18 | 18 | }; |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | fn expm1_32(x_: f32) -> f32 { | |
| 21 | fn expm1_32(x_: f32) f32 { | |
| 22 | 22 | @setFloatMode(this, builtin.FloatMode.Strict); |
| 23 | 23 | const o_threshold: f32 = 8.8721679688e+01; |
| 24 | 24 | const ln2_hi: f32 = 6.9313812256e-01; |
| ... | ... | @@ -145,7 +145,7 @@ fn expm1_32(x_: f32) -> f32 { |
| 145 | 145 | } |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | fn expm1_64(x_: f64) -> f64 { | |
| 148 | fn expm1_64(x_: f64) f64 { | |
| 149 | 149 | @setFloatMode(this, builtin.FloatMode.Strict); |
| 150 | 150 | const o_threshold: f64 = 7.09782712893383973096e+02; |
| 151 | 151 | const ln2_hi: f64 = 6.93147180369123816490e-01; |
std/math/expo2.zig+3-3| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | |
| 3 | pub fn expo2(x: var) -> @typeOf(x) { | |
| 3 | pub fn expo2(x: var) @typeOf(x) { | |
| 4 | 4 | const T = @typeOf(x); |
| 5 | 5 | return switch (T) { |
| 6 | 6 | f32 => expo2f(x), |
| ... | ... | @@ -9,7 +9,7 @@ pub fn expo2(x: var) -> @typeOf(x) { |
| 9 | 9 | }; |
| 10 | 10 | } |
| 11 | 11 | |
| 12 | fn expo2f(x: f32) -> f32 { | |
| 12 | fn expo2f(x: f32) f32 { | |
| 13 | 13 | const k: u32 = 235; |
| 14 | 14 | const kln2 = 0x1.45C778p+7; |
| 15 | 15 | |
| ... | ... | @@ -18,7 +18,7 @@ fn expo2f(x: f32) -> f32 { |
| 18 | 18 | return math.exp(x - kln2) * scale * scale; |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | fn expo2d(x: f64) -> f64 { | |
| 21 | fn expo2d(x: f64) f64 { | |
| 22 | 22 | const k: u32 = 2043; |
| 23 | 23 | const kln2 = 0x1.62066151ADD8BP+10; |
| 24 | 24 |
std/math/fabs.zig+3-3| ... | ... | @@ -7,7 +7,7 @@ const std = @import("../index.zig"); |
| 7 | 7 | const math = std.math; |
| 8 | 8 | const assert = std.debug.assert; |
| 9 | 9 | |
| 10 | pub fn fabs(x: var) -> @typeOf(x) { | |
| 10 | pub fn fabs(x: var) @typeOf(x) { | |
| 11 | 11 | const T = @typeOf(x); |
| 12 | 12 | return switch (T) { |
| 13 | 13 | f32 => fabs32(x), |
| ... | ... | @@ -16,13 +16,13 @@ pub fn fabs(x: var) -> @typeOf(x) { |
| 16 | 16 | }; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | fn fabs32(x: f32) -> f32 { | |
| 19 | fn fabs32(x: f32) f32 { | |
| 20 | 20 | var u = @bitCast(u32, x); |
| 21 | 21 | u &= 0x7FFFFFFF; |
| 22 | 22 | return @bitCast(f32, u); |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | fn fabs64(x: f64) -> f64 { | |
| 25 | fn fabs64(x: f64) f64 { | |
| 26 | 26 | var u = @bitCast(u64, x); |
| 27 | 27 | u &= @maxValue(u64) >> 1; |
| 28 | 28 | return @bitCast(f64, u); |
std/math/floor.zig+3-3| ... | ... | @@ -9,7 +9,7 @@ const assert = std.debug.assert; |
| 9 | 9 | const std = @import("../index.zig"); |
| 10 | 10 | const math = std.math; |
| 11 | 11 | |
| 12 | pub fn floor(x: var) -> @typeOf(x) { | |
| 12 | pub fn floor(x: var) @typeOf(x) { | |
| 13 | 13 | const T = @typeOf(x); |
| 14 | 14 | return switch (T) { |
| 15 | 15 | f32 => floor32(x), |
| ... | ... | @@ -18,7 +18,7 @@ pub fn floor(x: var) -> @typeOf(x) { |
| 18 | 18 | }; |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | fn floor32(x: f32) -> f32 { | |
| 21 | fn floor32(x: f32) f32 { | |
| 22 | 22 | var u = @bitCast(u32, x); |
| 23 | 23 | const e = i32((u >> 23) & 0xFF) - 0x7F; |
| 24 | 24 | var m: u32 = undefined; |
| ... | ... | @@ -52,7 +52,7 @@ fn floor32(x: f32) -> f32 { |
| 52 | 52 | } |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | fn floor64(x: f64) -> f64 { | |
| 55 | fn floor64(x: f64) f64 { | |
| 56 | 56 | const u = @bitCast(u64, x); |
| 57 | 57 | const e = (u >> 52) & 0x7FF; |
| 58 | 58 | var y: f64 = undefined; |
std/math/fma.zig+7-7| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | |
| 5 | pub fn fma(comptime T: type, x: T, y: T, z: T) -> T { | |
| 5 | pub fn fma(comptime T: type, x: T, y: T, z: T) T { | |
| 6 | 6 | return switch (T) { |
| 7 | 7 | f32 => fma32(x, y, z), |
| 8 | 8 | f64 => fma64(x, y ,z), |
| ... | ... | @@ -10,7 +10,7 @@ pub fn fma(comptime T: type, x: T, y: T, z: T) -> T { |
| 10 | 10 | }; |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | fn fma32(x: f32, y: f32, z: f32) -> f32 { | |
| 13 | fn fma32(x: f32, y: f32, z: f32) f32 { | |
| 14 | 14 | const xy = f64(x) * y; |
| 15 | 15 | const xy_z = xy + z; |
| 16 | 16 | const u = @bitCast(u64, xy_z); |
| ... | ... | @@ -24,7 +24,7 @@ fn fma32(x: f32, y: f32, z: f32) -> f32 { |
| 24 | 24 | } |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | fn fma64(x: f64, y: f64, z: f64) -> f64 { | |
| 27 | fn fma64(x: f64, y: f64, z: f64) f64 { | |
| 28 | 28 | if (!math.isFinite(x) or !math.isFinite(y)) { |
| 29 | 29 | return x * y + z; |
| 30 | 30 | } |
| ... | ... | @@ -73,7 +73,7 @@ fn fma64(x: f64, y: f64, z: f64) -> f64 { |
| 73 | 73 | |
| 74 | 74 | const dd = struct { hi: f64, lo: f64, }; |
| 75 | 75 | |
| 76 | fn dd_add(a: f64, b: f64) -> dd { | |
| 76 | fn dd_add(a: f64, b: f64) dd { | |
| 77 | 77 | var ret: dd = undefined; |
| 78 | 78 | ret.hi = a + b; |
| 79 | 79 | const s = ret.hi - a; |
| ... | ... | @@ -81,7 +81,7 @@ fn dd_add(a: f64, b: f64) -> dd { |
| 81 | 81 | return ret; |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | fn dd_mul(a: f64, b: f64) -> dd { | |
| 84 | fn dd_mul(a: f64, b: f64) dd { | |
| 85 | 85 | var ret: dd = undefined; |
| 86 | 86 | const split: f64 = 0x1.0p27 + 1.0; |
| 87 | 87 | |
| ... | ... | @@ -103,7 +103,7 @@ fn dd_mul(a: f64, b: f64) -> dd { |
| 103 | 103 | return ret; |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | fn add_adjusted(a: f64, b: f64) -> f64 { | |
| 106 | fn add_adjusted(a: f64, b: f64) f64 { | |
| 107 | 107 | var sum = dd_add(a, b); |
| 108 | 108 | if (sum.lo != 0) { |
| 109 | 109 | var uhii = @bitCast(u64, sum.hi); |
| ... | ... | @@ -117,7 +117,7 @@ fn add_adjusted(a: f64, b: f64) -> f64 { |
| 117 | 117 | return sum.hi; |
| 118 | 118 | } |
| 119 | 119 | |
| 120 | fn add_and_denorm(a: f64, b: f64, scale: i32) -> f64 { | |
| 120 | fn add_and_denorm(a: f64, b: f64, scale: i32) f64 { | |
| 121 | 121 | var sum = dd_add(a, b); |
| 122 | 122 | if (sum.lo != 0) { |
| 123 | 123 | var uhii = @bitCast(u64, sum.hi); |
std/math/frexp.zig+4-4| ... | ... | @@ -8,7 +8,7 @@ const std = @import("../index.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const assert = std.debug.assert; |
| 10 | 10 | |
| 11 | fn frexp_result(comptime T: type) -> type { | |
| 11 | fn frexp_result(comptime T: type) type { | |
| 12 | 12 | return struct { |
| 13 | 13 | significand: T, |
| 14 | 14 | exponent: i32, |
| ... | ... | @@ -17,7 +17,7 @@ fn frexp_result(comptime T: type) -> type { |
| 17 | 17 | pub const frexp32_result = frexp_result(f32); |
| 18 | 18 | pub const frexp64_result = frexp_result(f64); |
| 19 | 19 | |
| 20 | pub fn frexp(x: var) -> frexp_result(@typeOf(x)) { | |
| 20 | pub fn frexp(x: var) frexp_result(@typeOf(x)) { | |
| 21 | 21 | const T = @typeOf(x); |
| 22 | 22 | return switch (T) { |
| 23 | 23 | f32 => frexp32(x), |
| ... | ... | @@ -26,7 +26,7 @@ pub fn frexp(x: var) -> frexp_result(@typeOf(x)) { |
| 26 | 26 | }; |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | fn frexp32(x: f32) -> frexp32_result { | |
| 29 | fn frexp32(x: f32) frexp32_result { | |
| 30 | 30 | var result: frexp32_result = undefined; |
| 31 | 31 | |
| 32 | 32 | var y = @bitCast(u32, x); |
| ... | ... | @@ -63,7 +63,7 @@ fn frexp32(x: f32) -> frexp32_result { |
| 63 | 63 | return result; |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | fn frexp64(x: f64) -> frexp64_result { | |
| 66 | fn frexp64(x: f64) frexp64_result { | |
| 67 | 67 | var result: frexp64_result = undefined; |
| 68 | 68 | |
| 69 | 69 | var y = @bitCast(u64, x); |
std/math/hypot.zig+4-4| ... | ... | @@ -9,7 +9,7 @@ const std = @import("../index.zig"); |
| 9 | 9 | const math = std.math; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | 11 | |
| 12 | pub fn hypot(comptime T: type, x: T, y: T) -> T { | |
| 12 | pub fn hypot(comptime T: type, x: T, y: T) T { | |
| 13 | 13 | return switch (T) { |
| 14 | 14 | f32 => hypot32(x, y), |
| 15 | 15 | f64 => hypot64(x, y), |
| ... | ... | @@ -17,7 +17,7 @@ pub fn hypot(comptime T: type, x: T, y: T) -> T { |
| 17 | 17 | }; |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | fn hypot32(x: f32, y: f32) -> f32 { | |
| 20 | fn hypot32(x: f32, y: f32) f32 { | |
| 21 | 21 | var ux = @bitCast(u32, x); |
| 22 | 22 | var uy = @bitCast(u32, y); |
| 23 | 23 | |
| ... | ... | @@ -52,7 +52,7 @@ fn hypot32(x: f32, y: f32) -> f32 { |
| 52 | 52 | return z * math.sqrt(f32(f64(x) * x + f64(y) * y)); |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | fn sq(hi: &f64, lo: &f64, x: f64) { | |
| 55 | fn sq(hi: &f64, lo: &f64, x: f64) void { | |
| 56 | 56 | const split: f64 = 0x1.0p27 + 1.0; |
| 57 | 57 | const xc = x * split; |
| 58 | 58 | const xh = x - xc + xc; |
| ... | ... | @@ -61,7 +61,7 @@ fn sq(hi: &f64, lo: &f64, x: f64) { |
| 61 | 61 | *lo = xh * xh - *hi + 2 * xh * xl + xl * xl; |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | fn hypot64(x: f64, y: f64) -> f64 { | |
| 64 | fn hypot64(x: f64, y: f64) f64 { | |
| 65 | 65 | var ux = @bitCast(u64, x); |
| 66 | 66 | var uy = @bitCast(u64, y); |
| 67 | 67 |
std/math/ilogb.zig+3-3| ... | ... | @@ -8,7 +8,7 @@ const std = @import("../index.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const assert = std.debug.assert; |
| 10 | 10 | |
| 11 | pub fn ilogb(x: var) -> i32 { | |
| 11 | pub fn ilogb(x: var) i32 { | |
| 12 | 12 | const T = @typeOf(x); |
| 13 | 13 | return switch (T) { |
| 14 | 14 | f32 => ilogb32(x), |
| ... | ... | @@ -21,7 +21,7 @@ pub fn ilogb(x: var) -> i32 { |
| 21 | 21 | const fp_ilogbnan = -1 - i32(@maxValue(u32) >> 1); |
| 22 | 22 | const fp_ilogb0 = fp_ilogbnan; |
| 23 | 23 | |
| 24 | fn ilogb32(x: f32) -> i32 { | |
| 24 | fn ilogb32(x: f32) i32 { | |
| 25 | 25 | var u = @bitCast(u32, x); |
| 26 | 26 | var e = i32((u >> 23) & 0xFF); |
| 27 | 27 | |
| ... | ... | @@ -57,7 +57,7 @@ fn ilogb32(x: f32) -> i32 { |
| 57 | 57 | return e - 0x7F; |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | fn ilogb64(x: f64) -> i32 { | |
| 60 | fn ilogb64(x: f64) i32 { | |
| 61 | 61 | var u = @bitCast(u64, x); |
| 62 | 62 | var e = i32((u >> 52) & 0x7FF); |
| 63 | 63 |
std/math/index.zig+43-43| ... | ... | @@ -35,13 +35,13 @@ pub const nan = @import("nan.zig").nan; |
| 35 | 35 | pub const snan = @import("nan.zig").snan; |
| 36 | 36 | pub const inf = @import("inf.zig").inf; |
| 37 | 37 | |
| 38 | pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) -> bool { | |
| 38 | pub fn approxEq(comptime T: type, x: T, y: T, epsilon: T) bool { | |
| 39 | 39 | assert(@typeId(T) == TypeId.Float); |
| 40 | 40 | return fabs(x - y) < epsilon; |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | 43 | // TODO: Hide the following in an internal module. |
| 44 | pub fn forceEval(value: var) { | |
| 44 | pub fn forceEval(value: var) void { | |
| 45 | 45 | const T = @typeOf(value); |
| 46 | 46 | switch (T) { |
| 47 | 47 | f32 => { |
| ... | ... | @@ -60,23 +60,23 @@ pub fn forceEval(value: var) { |
| 60 | 60 | } |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | pub fn raiseInvalid() { | |
| 63 | pub fn raiseInvalid() void { | |
| 64 | 64 | // Raise INVALID fpu exception |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | pub fn raiseUnderflow() { | |
| 67 | pub fn raiseUnderflow() void { | |
| 68 | 68 | // Raise UNDERFLOW fpu exception |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | pub fn raiseOverflow() { | |
| 71 | pub fn raiseOverflow() void { | |
| 72 | 72 | // Raise OVERFLOW fpu exception |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | pub fn raiseInexact() { | |
| 75 | pub fn raiseInexact() void { | |
| 76 | 76 | // Raise INEXACT fpu exception |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | pub fn raiseDivByZero() { | |
| 79 | pub fn raiseDivByZero() void { | |
| 80 | 80 | // Raise INEXACT fpu exception |
| 81 | 81 | } |
| 82 | 82 | |
| ... | ... | @@ -175,7 +175,7 @@ test "math" { |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | 177 | |
| 178 | pub fn min(x: var, y: var) -> @typeOf(x + y) { | |
| 178 | pub fn min(x: var, y: var) @typeOf(x + y) { | |
| 179 | 179 | return if (x < y) x else y; |
| 180 | 180 | } |
| 181 | 181 | |
| ... | ... | @@ -183,7 +183,7 @@ test "math.min" { |
| 183 | 183 | assert(min(i32(-1), i32(2)) == -1); |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | pub fn max(x: var, y: var) -> @typeOf(x + y) { | |
| 186 | pub fn max(x: var, y: var) @typeOf(x + y) { | |
| 187 | 187 | return if (x > y) x else y; |
| 188 | 188 | } |
| 189 | 189 | |
| ... | ... | @@ -192,36 +192,36 @@ test "math.max" { |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | 194 | error Overflow; |
| 195 | pub fn mul(comptime T: type, a: T, b: T) -> %T { | |
| 195 | pub fn mul(comptime T: type, a: T, b: T) %T { | |
| 196 | 196 | var answer: T = undefined; |
| 197 | 197 | return if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer; |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | 200 | error Overflow; |
| 201 | pub fn add(comptime T: type, a: T, b: T) -> %T { | |
| 201 | pub fn add(comptime T: type, a: T, b: T) %T { | |
| 202 | 202 | var answer: T = undefined; |
| 203 | 203 | return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer; |
| 204 | 204 | } |
| 205 | 205 | |
| 206 | 206 | error Overflow; |
| 207 | pub fn sub(comptime T: type, a: T, b: T) -> %T { | |
| 207 | pub fn sub(comptime T: type, a: T, b: T) %T { | |
| 208 | 208 | var answer: T = undefined; |
| 209 | 209 | return if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer; |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | pub fn negate(x: var) -> %@typeOf(x) { | |
| 212 | pub fn negate(x: var) %@typeOf(x) { | |
| 213 | 213 | return sub(@typeOf(x), 0, x); |
| 214 | 214 | } |
| 215 | 215 | |
| 216 | 216 | error Overflow; |
| 217 | pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) -> %T { | |
| 217 | pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) %T { | |
| 218 | 218 | var answer: T = undefined; |
| 219 | 219 | return if (@shlWithOverflow(T, a, shift_amt, &answer)) error.Overflow else answer; |
| 220 | 220 | } |
| 221 | 221 | |
| 222 | 222 | /// Shifts left. Overflowed bits are truncated. |
| 223 | 223 | /// A negative shift amount results in a right shift. |
| 224 | pub fn shl(comptime T: type, a: T, shift_amt: var) -> T { | |
| 224 | pub fn shl(comptime T: type, a: T, shift_amt: var) T { | |
| 225 | 225 | const abs_shift_amt = absCast(shift_amt); |
| 226 | 226 | const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else Log2Int(T)(abs_shift_amt); |
| 227 | 227 | |
| ... | ... | @@ -245,7 +245,7 @@ test "math.shl" { |
| 245 | 245 | |
| 246 | 246 | /// Shifts right. Overflowed bits are truncated. |
| 247 | 247 | /// A negative shift amount results in a lefft shift. |
| 248 | pub fn shr(comptime T: type, a: T, shift_amt: var) -> T { | |
| 248 | pub fn shr(comptime T: type, a: T, shift_amt: var) T { | |
| 249 | 249 | const abs_shift_amt = absCast(shift_amt); |
| 250 | 250 | const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else Log2Int(T)(abs_shift_amt); |
| 251 | 251 | |
| ... | ... | @@ -269,7 +269,7 @@ test "math.shr" { |
| 269 | 269 | |
| 270 | 270 | /// Rotates right. Only unsigned values can be rotated. |
| 271 | 271 | /// Negative shift values results in shift modulo the bit count. |
| 272 | pub fn rotr(comptime T: type, x: T, r: var) -> T { | |
| 272 | pub fn rotr(comptime T: type, x: T, r: var) T { | |
| 273 | 273 | if (T.is_signed) { |
| 274 | 274 | @compileError("cannot rotate signed integer"); |
| 275 | 275 | } else { |
| ... | ... | @@ -288,7 +288,7 @@ test "math.rotr" { |
| 288 | 288 | |
| 289 | 289 | /// Rotates left. Only unsigned values can be rotated. |
| 290 | 290 | /// Negative shift values results in shift modulo the bit count. |
| 291 | pub fn rotl(comptime T: type, x: T, r: var) -> T { | |
| 291 | pub fn rotl(comptime T: type, x: T, r: var) T { | |
| 292 | 292 | if (T.is_signed) { |
| 293 | 293 | @compileError("cannot rotate signed integer"); |
| 294 | 294 | } else { |
| ... | ... | @@ -306,7 +306,7 @@ test "math.rotl" { |
| 306 | 306 | } |
| 307 | 307 | |
| 308 | 308 | |
| 309 | pub fn Log2Int(comptime T: type) -> type { | |
| 309 | pub fn Log2Int(comptime T: type) type { | |
| 310 | 310 | return @IntType(false, log2(T.bit_count)); |
| 311 | 311 | } |
| 312 | 312 | |
| ... | ... | @@ -315,7 +315,7 @@ test "math overflow functions" { |
| 315 | 315 | comptime testOverflow(); |
| 316 | 316 | } |
| 317 | 317 | |
| 318 | fn testOverflow() { | |
| 318 | fn testOverflow() void { | |
| 319 | 319 | assert((mul(i32, 3, 4) catch unreachable) == 12); |
| 320 | 320 | assert((add(i32, 3, 4) catch unreachable) == 7); |
| 321 | 321 | assert((sub(i32, 3, 4) catch unreachable) == -1); |
| ... | ... | @@ -324,14 +324,14 @@ fn testOverflow() { |
| 324 | 324 | |
| 325 | 325 | |
| 326 | 326 | error Overflow; |
| 327 | pub fn absInt(x: var) -> %@typeOf(x) { | |
| 327 | pub fn absInt(x: var) %@typeOf(x) { | |
| 328 | 328 | const T = @typeOf(x); |
| 329 | 329 | comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt |
| 330 | 330 | comptime assert(T.is_signed); // must pass a signed integer to absInt |
| 331 | 331 | if (x == @minValue(@typeOf(x))) |
| 332 | 332 | return error.Overflow; |
| 333 | 333 | { |
| 334 | @setDebugSafety(this, false); | |
| 334 | @setRuntimeSafety(false); | |
| 335 | 335 | return if (x < 0) -x else x; |
| 336 | 336 | } |
| 337 | 337 | } |
| ... | ... | @@ -340,7 +340,7 @@ test "math.absInt" { |
| 340 | 340 | testAbsInt(); |
| 341 | 341 | comptime testAbsInt(); |
| 342 | 342 | } |
| 343 | fn testAbsInt() { | |
| 343 | fn testAbsInt() void { | |
| 344 | 344 | assert((absInt(i32(-10)) catch unreachable) == 10); |
| 345 | 345 | assert((absInt(i32(10)) catch unreachable) == 10); |
| 346 | 346 | } |
| ... | ... | @@ -349,8 +349,8 @@ pub const absFloat = @import("fabs.zig").fabs; |
| 349 | 349 | |
| 350 | 350 | error DivisionByZero; |
| 351 | 351 | error Overflow; |
| 352 | pub fn divTrunc(comptime T: type, numerator: T, denominator: T) -> %T { | |
| 353 | @setDebugSafety(this, false); | |
| 352 | pub fn divTrunc(comptime T: type, numerator: T, denominator: T) %T { | |
| 353 | @setRuntimeSafety(false); | |
| 354 | 354 | if (denominator == 0) |
| 355 | 355 | return error.DivisionByZero; |
| 356 | 356 | if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) |
| ... | ... | @@ -362,7 +362,7 @@ test "math.divTrunc" { |
| 362 | 362 | testDivTrunc(); |
| 363 | 363 | comptime testDivTrunc(); |
| 364 | 364 | } |
| 365 | fn testDivTrunc() { | |
| 365 | fn testDivTrunc() void { | |
| 366 | 366 | assert((divTrunc(i32, 5, 3) catch unreachable) == 1); |
| 367 | 367 | assert((divTrunc(i32, -5, 3) catch unreachable) == -1); |
| 368 | 368 | if (divTrunc(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); |
| ... | ... | @@ -374,8 +374,8 @@ fn testDivTrunc() { |
| 374 | 374 | |
| 375 | 375 | error DivisionByZero; |
| 376 | 376 | error Overflow; |
| 377 | pub fn divFloor(comptime T: type, numerator: T, denominator: T) -> %T { | |
| 378 | @setDebugSafety(this, false); | |
| 377 | pub fn divFloor(comptime T: type, numerator: T, denominator: T) %T { | |
| 378 | @setRuntimeSafety(false); | |
| 379 | 379 | if (denominator == 0) |
| 380 | 380 | return error.DivisionByZero; |
| 381 | 381 | if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) |
| ... | ... | @@ -387,7 +387,7 @@ test "math.divFloor" { |
| 387 | 387 | testDivFloor(); |
| 388 | 388 | comptime testDivFloor(); |
| 389 | 389 | } |
| 390 | fn testDivFloor() { | |
| 390 | fn testDivFloor() void { | |
| 391 | 391 | assert((divFloor(i32, 5, 3) catch unreachable) == 1); |
| 392 | 392 | assert((divFloor(i32, -5, 3) catch unreachable) == -2); |
| 393 | 393 | if (divFloor(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); |
| ... | ... | @@ -400,8 +400,8 @@ fn testDivFloor() { |
| 400 | 400 | error DivisionByZero; |
| 401 | 401 | error Overflow; |
| 402 | 402 | error UnexpectedRemainder; |
| 403 | pub fn divExact(comptime T: type, numerator: T, denominator: T) -> %T { | |
| 404 | @setDebugSafety(this, false); | |
| 403 | pub fn divExact(comptime T: type, numerator: T, denominator: T) %T { | |
| 404 | @setRuntimeSafety(false); | |
| 405 | 405 | if (denominator == 0) |
| 406 | 406 | return error.DivisionByZero; |
| 407 | 407 | if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) |
| ... | ... | @@ -416,7 +416,7 @@ test "math.divExact" { |
| 416 | 416 | testDivExact(); |
| 417 | 417 | comptime testDivExact(); |
| 418 | 418 | } |
| 419 | fn testDivExact() { | |
| 419 | fn testDivExact() void { | |
| 420 | 420 | assert((divExact(i32, 10, 5) catch unreachable) == 2); |
| 421 | 421 | assert((divExact(i32, -10, 5) catch unreachable) == -2); |
| 422 | 422 | if (divExact(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero); |
| ... | ... | @@ -430,8 +430,8 @@ fn testDivExact() { |
| 430 | 430 | |
| 431 | 431 | error DivisionByZero; |
| 432 | 432 | error NegativeDenominator; |
| 433 | pub fn mod(comptime T: type, numerator: T, denominator: T) -> %T { | |
| 434 | @setDebugSafety(this, false); | |
| 433 | pub fn mod(comptime T: type, numerator: T, denominator: T) %T { | |
| 434 | @setRuntimeSafety(false); | |
| 435 | 435 | if (denominator == 0) |
| 436 | 436 | return error.DivisionByZero; |
| 437 | 437 | if (denominator < 0) |
| ... | ... | @@ -443,7 +443,7 @@ test "math.mod" { |
| 443 | 443 | testMod(); |
| 444 | 444 | comptime testMod(); |
| 445 | 445 | } |
| 446 | fn testMod() { | |
| 446 | fn testMod() void { | |
| 447 | 447 | assert((mod(i32, -5, 3) catch unreachable) == 1); |
| 448 | 448 | assert((mod(i32, 5, 3) catch unreachable) == 2); |
| 449 | 449 | if (mod(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator); |
| ... | ... | @@ -457,8 +457,8 @@ fn testMod() { |
| 457 | 457 | |
| 458 | 458 | error DivisionByZero; |
| 459 | 459 | error NegativeDenominator; |
| 460 | pub fn rem(comptime T: type, numerator: T, denominator: T) -> %T { | |
| 461 | @setDebugSafety(this, false); | |
| 460 | pub fn rem(comptime T: type, numerator: T, denominator: T) %T { | |
| 461 | @setRuntimeSafety(false); | |
| 462 | 462 | if (denominator == 0) |
| 463 | 463 | return error.DivisionByZero; |
| 464 | 464 | if (denominator < 0) |
| ... | ... | @@ -470,7 +470,7 @@ test "math.rem" { |
| 470 | 470 | testRem(); |
| 471 | 471 | comptime testRem(); |
| 472 | 472 | } |
| 473 | fn testRem() { | |
| 473 | fn testRem() void { | |
| 474 | 474 | assert((rem(i32, -5, 3) catch unreachable) == -2); |
| 475 | 475 | assert((rem(i32, 5, 3) catch unreachable) == 2); |
| 476 | 476 | if (rem(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator); |
| ... | ... | @@ -484,7 +484,7 @@ fn testRem() { |
| 484 | 484 | |
| 485 | 485 | /// Returns the absolute value of the integer parameter. |
| 486 | 486 | /// Result is an unsigned integer. |
| 487 | pub fn absCast(x: var) -> @IntType(false, @typeOf(x).bit_count) { | |
| 487 | pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) { | |
| 488 | 488 | const uint = @IntType(false, @typeOf(x).bit_count); |
| 489 | 489 | if (x >= 0) |
| 490 | 490 | return uint(x); |
| ... | ... | @@ -506,7 +506,7 @@ test "math.absCast" { |
| 506 | 506 | /// Returns the negation of the integer parameter. |
| 507 | 507 | /// Result is a signed integer. |
| 508 | 508 | error Overflow; |
| 509 | pub fn negateCast(x: var) -> %@IntType(true, @typeOf(x).bit_count) { | |
| 509 | pub fn negateCast(x: var) %@IntType(true, @typeOf(x).bit_count) { | |
| 510 | 510 | if (@typeOf(x).is_signed) |
| 511 | 511 | return negate(x); |
| 512 | 512 | |
| ... | ... | @@ -533,7 +533,7 @@ test "math.negateCast" { |
| 533 | 533 | /// Cast an integer to a different integer type. If the value doesn't fit, |
| 534 | 534 | /// return an error. |
| 535 | 535 | error Overflow; |
| 536 | pub fn cast(comptime T: type, x: var) -> %T { | |
| 536 | pub fn cast(comptime T: type, x: var) %T { | |
| 537 | 537 | comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer |
| 538 | 538 | if (x > @maxValue(T)) { |
| 539 | 539 | return error.Overflow; |
| ... | ... | @@ -542,7 +542,7 @@ pub fn cast(comptime T: type, x: var) -> %T { |
| 542 | 542 | } |
| 543 | 543 | } |
| 544 | 544 | |
| 545 | pub fn floorPowerOfTwo(comptime T: type, value: T) -> T { | |
| 545 | pub fn floorPowerOfTwo(comptime T: type, value: T) T { | |
| 546 | 546 | var x = value; |
| 547 | 547 | |
| 548 | 548 | comptime var i = 1; |
| ... | ... | @@ -558,7 +558,7 @@ test "math.floorPowerOfTwo" { |
| 558 | 558 | comptime testFloorPowerOfTwo(); |
| 559 | 559 | } |
| 560 | 560 | |
| 561 | fn testFloorPowerOfTwo() { | |
| 561 | fn testFloorPowerOfTwo() void { | |
| 562 | 562 | assert(floorPowerOfTwo(u32, 63) == 32); |
| 563 | 563 | assert(floorPowerOfTwo(u32, 64) == 64); |
| 564 | 564 | assert(floorPowerOfTwo(u32, 65) == 64); |
std/math/inf.zig+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | |
| 5 | pub fn inf(comptime T: type) -> T { | |
| 5 | pub fn inf(comptime T: type) T { | |
| 6 | 6 | return switch (T) { |
| 7 | 7 | f32 => @bitCast(f32, math.inf_u32), |
| 8 | 8 | f64 => @bitCast(f64, math.inf_u64), |
std/math/isfinite.zig+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | |
| 5 | pub fn isFinite(x: var) -> bool { | |
| 5 | pub fn isFinite(x: var) bool { | |
| 6 | 6 | const T = @typeOf(x); |
| 7 | 7 | switch (T) { |
| 8 | 8 | f32 => { |
std/math/isinf.zig+3-3| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | |
| 5 | pub fn isInf(x: var) -> bool { | |
| 5 | pub fn isInf(x: var) bool { | |
| 6 | 6 | const T = @typeOf(x); |
| 7 | 7 | switch (T) { |
| 8 | 8 | f32 => { |
| ... | ... | @@ -19,7 +19,7 @@ pub fn isInf(x: var) -> bool { |
| 19 | 19 | } |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | pub fn isPositiveInf(x: var) -> bool { | |
| 22 | pub fn isPositiveInf(x: var) bool { | |
| 23 | 23 | const T = @typeOf(x); |
| 24 | 24 | switch (T) { |
| 25 | 25 | f32 => { |
| ... | ... | @@ -34,7 +34,7 @@ pub fn isPositiveInf(x: var) -> bool { |
| 34 | 34 | } |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | pub fn isNegativeInf(x: var) -> bool { | |
| 37 | pub fn isNegativeInf(x: var) bool { | |
| 38 | 38 | const T = @typeOf(x); |
| 39 | 39 | switch (T) { |
| 40 | 40 | f32 => { |
std/math/isnan.zig+2-2| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | |
| 5 | pub fn isNan(x: var) -> bool { | |
| 5 | pub fn isNan(x: var) bool { | |
| 6 | 6 | const T = @typeOf(x); |
| 7 | 7 | switch (T) { |
| 8 | 8 | f32 => { |
| ... | ... | @@ -21,7 +21,7 @@ pub fn isNan(x: var) -> bool { |
| 21 | 21 | |
| 22 | 22 | // Note: A signalling nan is identical to a standard right now by may have a different bit |
| 23 | 23 | // representation in the future when required. |
| 24 | pub fn isSignalNan(x: var) -> bool { | |
| 24 | pub fn isSignalNan(x: var) bool { | |
| 25 | 25 | return isNan(x); |
| 26 | 26 | } |
| 27 | 27 |
std/math/isnormal.zig+1-1| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | |
| 5 | pub fn isNormal(x: var) -> bool { | |
| 5 | pub fn isNormal(x: var) bool { | |
| 6 | 6 | const T = @typeOf(x); |
| 7 | 7 | switch (T) { |
| 8 | 8 | f32 => { |
std/math/ln.zig+3-3| ... | ... | @@ -11,7 +11,7 @@ const assert = std.debug.assert; |
| 11 | 11 | const builtin = @import("builtin"); |
| 12 | 12 | const TypeId = builtin.TypeId; |
| 13 | 13 | |
| 14 | pub fn ln(x: var) -> @typeOf(x) { | |
| 14 | pub fn ln(x: var) @typeOf(x) { | |
| 15 | 15 | const T = @typeOf(x); |
| 16 | 16 | switch (@typeId(T)) { |
| 17 | 17 | TypeId.FloatLiteral => { |
| ... | ... | @@ -34,7 +34,7 @@ pub fn ln(x: var) -> @typeOf(x) { |
| 34 | 34 | } |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | pub fn ln_32(x_: f32) -> f32 { | |
| 37 | pub fn ln_32(x_: f32) f32 { | |
| 38 | 38 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 39 | 39 | |
| 40 | 40 | const ln2_hi: f32 = 6.9313812256e-01; |
| ... | ... | @@ -88,7 +88,7 @@ pub fn ln_32(x_: f32) -> f32 { |
| 88 | 88 | return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi; |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | pub fn ln_64(x_: f64) -> f64 { | |
| 91 | pub fn ln_64(x_: f64) f64 { | |
| 92 | 92 | const ln2_hi: f64 = 6.93147180369123816490e-01; |
| 93 | 93 | const ln2_lo: f64 = 1.90821492927058770002e-10; |
| 94 | 94 | const Lg1: f64 = 6.666666666666735130e-01; |
std/math/log.zig+1-1| ... | ... | @@ -4,7 +4,7 @@ const builtin = @import("builtin"); |
| 4 | 4 | const TypeId = builtin.TypeId; |
| 5 | 5 | const assert = std.debug.assert; |
| 6 | 6 | |
| 7 | pub fn log(comptime T: type, base: T, x: T) -> T { | |
| 7 | pub fn log(comptime T: type, base: T, x: T) T { | |
| 8 | 8 | if (base == 2) { |
| 9 | 9 | return math.log2(x); |
| 10 | 10 | } else if (base == 10) { |
std/math/log10.zig+3-3| ... | ... | @@ -11,7 +11,7 @@ const assert = std.debug.assert; |
| 11 | 11 | const builtin = @import("builtin"); |
| 12 | 12 | const TypeId = builtin.TypeId; |
| 13 | 13 | |
| 14 | pub fn log10(x: var) -> @typeOf(x) { | |
| 14 | pub fn log10(x: var) @typeOf(x) { | |
| 15 | 15 | const T = @typeOf(x); |
| 16 | 16 | switch (@typeId(T)) { |
| 17 | 17 | TypeId.FloatLiteral => { |
| ... | ... | @@ -34,7 +34,7 @@ pub fn log10(x: var) -> @typeOf(x) { |
| 34 | 34 | } |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | pub fn log10_32(x_: f32) -> f32 { | |
| 37 | pub fn log10_32(x_: f32) f32 { | |
| 38 | 38 | const ivln10hi: f32 = 4.3432617188e-01; |
| 39 | 39 | const ivln10lo: f32 = -3.1689971365e-05; |
| 40 | 40 | const log10_2hi: f32 = 3.0102920532e-01; |
| ... | ... | @@ -94,7 +94,7 @@ pub fn log10_32(x_: f32) -> f32 { |
| 94 | 94 | return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi; |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | pub fn log10_64(x_: f64) -> f64 { | |
| 97 | pub fn log10_64(x_: f64) f64 { | |
| 98 | 98 | const ivln10hi: f64 = 4.34294481878168880939e-01; |
| 99 | 99 | const ivln10lo: f64 = 2.50829467116452752298e-11; |
| 100 | 100 | const log10_2hi: f64 = 3.01029995663611771306e-01; |
std/math/log1p.zig+3-3| ... | ... | @@ -10,7 +10,7 @@ const std = @import("../index.zig"); |
| 10 | 10 | const math = std.math; |
| 11 | 11 | const assert = std.debug.assert; |
| 12 | 12 | |
| 13 | pub fn log1p(x: var) -> @typeOf(x) { | |
| 13 | pub fn log1p(x: var) @typeOf(x) { | |
| 14 | 14 | const T = @typeOf(x); |
| 15 | 15 | return switch (T) { |
| 16 | 16 | f32 => log1p_32(x), |
| ... | ... | @@ -19,7 +19,7 @@ pub fn log1p(x: var) -> @typeOf(x) { |
| 19 | 19 | }; |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | fn log1p_32(x: f32) -> f32 { | |
| 22 | fn log1p_32(x: f32) f32 { | |
| 23 | 23 | const ln2_hi = 6.9313812256e-01; |
| 24 | 24 | const ln2_lo = 9.0580006145e-06; |
| 25 | 25 | const Lg1: f32 = 0xaaaaaa.0p-24; |
| ... | ... | @@ -95,7 +95,7 @@ fn log1p_32(x: f32) -> f32 { |
| 95 | 95 | return s * (hfsq + R) + (dk * ln2_lo + c) - hfsq + f + dk * ln2_hi; |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | fn log1p_64(x: f64) -> f64 { | |
| 98 | fn log1p_64(x: f64) f64 { | |
| 99 | 99 | const ln2_hi: f64 = 6.93147180369123816490e-01; |
| 100 | 100 | const ln2_lo: f64 = 1.90821492927058770002e-10; |
| 101 | 101 | const Lg1: f64 = 6.666666666666735130e-01; |
std/math/log2.zig+4-4| ... | ... | @@ -11,7 +11,7 @@ const assert = std.debug.assert; |
| 11 | 11 | const builtin = @import("builtin"); |
| 12 | 12 | const TypeId = builtin.TypeId; |
| 13 | 13 | |
| 14 | pub fn log2(x: var) -> @typeOf(x) { | |
| 14 | pub fn log2(x: var) @typeOf(x) { | |
| 15 | 15 | const T = @typeOf(x); |
| 16 | 16 | switch (@typeId(T)) { |
| 17 | 17 | TypeId.FloatLiteral => { |
| ... | ... | @@ -37,12 +37,12 @@ pub fn log2(x: var) -> @typeOf(x) { |
| 37 | 37 | } |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | pub fn log2_int(comptime T: type, x: T) -> T { | |
| 40 | pub fn log2_int(comptime T: type, x: T) T { | |
| 41 | 41 | assert(x != 0); |
| 42 | 42 | return T.bit_count - 1 - T(@clz(x)); |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | pub fn log2_32(x_: f32) -> f32 { | |
| 45 | pub fn log2_32(x_: f32) f32 { | |
| 46 | 46 | const ivln2hi: f32 = 1.4428710938e+00; |
| 47 | 47 | const ivln2lo: f32 = -1.7605285393e-04; |
| 48 | 48 | const Lg1: f32 = 0xaaaaaa.0p-24; |
| ... | ... | @@ -98,7 +98,7 @@ pub fn log2_32(x_: f32) -> f32 { |
| 98 | 98 | return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + f32(k); |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | pub fn log2_64(x_: f64) -> f64 { | |
| 101 | pub fn log2_64(x_: f64) f64 { | |
| 102 | 102 | const ivln2hi: f64 = 1.44269504072144627571e+00; |
| 103 | 103 | const ivln2lo: f64 = 1.67517131648865118353e-10; |
| 104 | 104 | const Lg1: f64 = 6.666666666666735130e-01; |
std/math/modf.zig+4-4| ... | ... | @@ -7,7 +7,7 @@ const std = @import("../index.zig"); |
| 7 | 7 | const math = std.math; |
| 8 | 8 | const assert = std.debug.assert; |
| 9 | 9 | |
| 10 | fn modf_result(comptime T: type) -> type { | |
| 10 | fn modf_result(comptime T: type) type { | |
| 11 | 11 | return struct { |
| 12 | 12 | fpart: T, |
| 13 | 13 | ipart: T, |
| ... | ... | @@ -16,7 +16,7 @@ fn modf_result(comptime T: type) -> type { |
| 16 | 16 | pub const modf32_result = modf_result(f32); |
| 17 | 17 | pub const modf64_result = modf_result(f64); |
| 18 | 18 | |
| 19 | pub fn modf(x: var) -> modf_result(@typeOf(x)) { | |
| 19 | pub fn modf(x: var) modf_result(@typeOf(x)) { | |
| 20 | 20 | const T = @typeOf(x); |
| 21 | 21 | return switch (T) { |
| 22 | 22 | f32 => modf32(x), |
| ... | ... | @@ -25,7 +25,7 @@ pub fn modf(x: var) -> modf_result(@typeOf(x)) { |
| 25 | 25 | }; |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | fn modf32(x: f32) -> modf32_result { | |
| 28 | fn modf32(x: f32) modf32_result { | |
| 29 | 29 | var result: modf32_result = undefined; |
| 30 | 30 | |
| 31 | 31 | const u = @bitCast(u32, x); |
| ... | ... | @@ -70,7 +70,7 @@ fn modf32(x: f32) -> modf32_result { |
| 70 | 70 | return result; |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | fn modf64(x: f64) -> modf64_result { | |
| 73 | fn modf64(x: f64) modf64_result { | |
| 74 | 74 | var result: modf64_result = undefined; |
| 75 | 75 | |
| 76 | 76 | const u = @bitCast(u64, x); |
std/math/nan.zig+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const math = @import("index.zig"); |
| 2 | 2 | |
| 3 | pub fn nan(comptime T: type) -> T { | |
| 3 | pub fn nan(comptime T: type) T { | |
| 4 | 4 | return switch (T) { |
| 5 | 5 | f32 => @bitCast(f32, math.nan_u32), |
| 6 | 6 | f64 => @bitCast(f64, math.nan_u64), |
| ... | ... | @@ -10,7 +10,7 @@ pub fn nan(comptime T: type) -> T { |
| 10 | 10 | |
| 11 | 11 | // Note: A signalling nan is identical to a standard right now by may have a different bit |
| 12 | 12 | // representation in the future when required. |
| 13 | pub fn snan(comptime T: type) -> T { | |
| 13 | pub fn snan(comptime T: type) T { | |
| 14 | 14 | return switch (T) { |
| 15 | 15 | f32 => @bitCast(f32, math.nan_u32), |
| 16 | 16 | f64 => @bitCast(f64, math.nan_u64), |
std/math/pow.zig+2-2| ... | ... | @@ -27,7 +27,7 @@ const math = std.math; |
| 27 | 27 | const assert = std.debug.assert; |
| 28 | 28 | |
| 29 | 29 | // This implementation is taken from the go stlib, musl is a bit more complex. |
| 30 | pub fn pow(comptime T: type, x: T, y: T) -> T { | |
| 30 | pub fn pow(comptime T: type, x: T, y: T) T { | |
| 31 | 31 | |
| 32 | 32 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 33 | 33 | |
| ... | ... | @@ -170,7 +170,7 @@ pub fn pow(comptime T: type, x: T, y: T) -> T { |
| 170 | 170 | return math.scalbn(a1, ae); |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | fn isOddInteger(x: f64) -> bool { | |
| 173 | fn isOddInteger(x: f64) bool { | |
| 174 | 174 | const r = math.modf(x); |
| 175 | 175 | return r.fpart == 0.0 and i64(r.ipart) & 1 == 1; |
| 176 | 176 | } |
std/math/round.zig+3-3| ... | ... | @@ -9,7 +9,7 @@ const assert = std.debug.assert; |
| 9 | 9 | const std = @import("../index.zig"); |
| 10 | 10 | const math = std.math; |
| 11 | 11 | |
| 12 | pub fn round(x: var) -> @typeOf(x) { | |
| 12 | pub fn round(x: var) @typeOf(x) { | |
| 13 | 13 | const T = @typeOf(x); |
| 14 | 14 | return switch (T) { |
| 15 | 15 | f32 => round32(x), |
| ... | ... | @@ -18,7 +18,7 @@ pub fn round(x: var) -> @typeOf(x) { |
| 18 | 18 | }; |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | fn round32(x_: f32) -> f32 { | |
| 21 | fn round32(x_: f32) f32 { | |
| 22 | 22 | var x = x_; |
| 23 | 23 | const u = @bitCast(u32, x); |
| 24 | 24 | const e = (u >> 23) & 0xFF; |
| ... | ... | @@ -55,7 +55,7 @@ fn round32(x_: f32) -> f32 { |
| 55 | 55 | } |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | fn round64(x_: f64) -> f64 { | |
| 58 | fn round64(x_: f64) f64 { | |
| 59 | 59 | var x = x_; |
| 60 | 60 | const u = @bitCast(u64, x); |
| 61 | 61 | const e = (u >> 52) & 0x7FF; |
std/math/scalbn.zig+3-3| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | |
| 5 | pub fn scalbn(x: var, n: i32) -> @typeOf(x) { | |
| 5 | pub fn scalbn(x: var, n: i32) @typeOf(x) { | |
| 6 | 6 | const T = @typeOf(x); |
| 7 | 7 | return switch (T) { |
| 8 | 8 | f32 => scalbn32(x, n), |
| ... | ... | @@ -11,7 +11,7 @@ pub fn scalbn(x: var, n: i32) -> @typeOf(x) { |
| 11 | 11 | }; |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | fn scalbn32(x: f32, n_: i32) -> f32 { | |
| 14 | fn scalbn32(x: f32, n_: i32) f32 { | |
| 15 | 15 | var y = x; |
| 16 | 16 | var n = n_; |
| 17 | 17 | |
| ... | ... | @@ -41,7 +41,7 @@ fn scalbn32(x: f32, n_: i32) -> f32 { |
| 41 | 41 | return y * @bitCast(f32, u); |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | fn scalbn64(x: f64, n_: i32) -> f64 { | |
| 44 | fn scalbn64(x: f64, n_: i32) f64 { | |
| 45 | 45 | var y = x; |
| 46 | 46 | var n = n_; |
| 47 | 47 |
std/math/signbit.zig+3-3| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../index.zig"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | |
| 5 | pub fn signbit(x: var) -> bool { | |
| 5 | pub fn signbit(x: var) bool { | |
| 6 | 6 | const T = @typeOf(x); |
| 7 | 7 | return switch (T) { |
| 8 | 8 | f32 => signbit32(x), |
| ... | ... | @@ -11,12 +11,12 @@ pub fn signbit(x: var) -> bool { |
| 11 | 11 | }; |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | fn signbit32(x: f32) -> bool { | |
| 14 | fn signbit32(x: f32) bool { | |
| 15 | 15 | const bits = @bitCast(u32, x); |
| 16 | 16 | return bits >> 31 != 0; |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | fn signbit64(x: f64) -> bool { | |
| 19 | fn signbit64(x: f64) bool { | |
| 20 | 20 | const bits = @bitCast(u64, x); |
| 21 | 21 | return bits >> 63 != 0; |
| 22 | 22 | } |
std/math/sin.zig+3-3| ... | ... | @@ -9,7 +9,7 @@ const std = @import("../index.zig"); |
| 9 | 9 | const math = std.math; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | 11 | |
| 12 | pub fn sin(x: var) -> @typeOf(x) { | |
| 12 | pub fn sin(x: var) @typeOf(x) { | |
| 13 | 13 | const T = @typeOf(x); |
| 14 | 14 | return switch (T) { |
| 15 | 15 | f32 => sin32(x), |
| ... | ... | @@ -37,7 +37,7 @@ const C5 = 4.16666666666665929218E-2; |
| 37 | 37 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. |
| 38 | 38 | // |
| 39 | 39 | // This may have slight differences on some edge cases and may need to replaced if so. |
| 40 | fn sin32(x_: f32) -> f32 { | |
| 40 | fn sin32(x_: f32) f32 { | |
| 41 | 41 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 42 | 42 | |
| 43 | 43 | const pi4a = 7.85398125648498535156e-1; |
| ... | ... | @@ -91,7 +91,7 @@ fn sin32(x_: f32) -> f32 { |
| 91 | 91 | } |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | fn sin64(x_: f64) -> f64 { | |
| 94 | fn sin64(x_: f64) f64 { | |
| 95 | 95 | const pi4a = 7.85398125648498535156e-1; |
| 96 | 96 | const pi4b = 3.77489470793079817668E-8; |
| 97 | 97 | const pi4c = 2.69515142907905952645E-15; |
std/math/sinh.zig+3-3| ... | ... | @@ -10,7 +10,7 @@ const math = std.math; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | 11 | const expo2 = @import("expo2.zig").expo2; |
| 12 | 12 | |
| 13 | pub fn sinh(x: var) -> @typeOf(x) { | |
| 13 | pub fn sinh(x: var) @typeOf(x) { | |
| 14 | 14 | const T = @typeOf(x); |
| 15 | 15 | return switch (T) { |
| 16 | 16 | f32 => sinh32(x), |
| ... | ... | @@ -22,7 +22,7 @@ pub fn sinh(x: var) -> @typeOf(x) { |
| 22 | 22 | // sinh(x) = (exp(x) - 1 / exp(x)) / 2 |
| 23 | 23 | // = (exp(x) - 1 + (exp(x) - 1) / exp(x)) / 2 |
| 24 | 24 | // = x + x^3 / 6 + o(x^5) |
| 25 | fn sinh32(x: f32) -> f32 { | |
| 25 | fn sinh32(x: f32) f32 { | |
| 26 | 26 | const u = @bitCast(u32, x); |
| 27 | 27 | const ux = u & 0x7FFFFFFF; |
| 28 | 28 | const ax = @bitCast(f32, ux); |
| ... | ... | @@ -53,7 +53,7 @@ fn sinh32(x: f32) -> f32 { |
| 53 | 53 | return 2 * h * expo2(ax); |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | fn sinh64(x: f64) -> f64 { | |
| 56 | fn sinh64(x: f64) f64 { | |
| 57 | 57 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 58 | 58 | |
| 59 | 59 | const u = @bitCast(u64, x); |
std/math/sqrt.zig+4-4| ... | ... | @@ -11,7 +11,7 @@ const assert = std.debug.assert; |
| 11 | 11 | const builtin = @import("builtin"); |
| 12 | 12 | const TypeId = builtin.TypeId; |
| 13 | 13 | |
| 14 | pub fn sqrt(x: var) -> (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) { | |
| 14 | pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) { | |
| 15 | 15 | const T = @typeOf(x); |
| 16 | 16 | switch (@typeId(T)) { |
| 17 | 17 | TypeId.FloatLiteral => { |
| ... | ... | @@ -50,7 +50,7 @@ pub fn sqrt(x: var) -> (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @ |
| 50 | 50 | } |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | fn sqrt32(x: f32) -> f32 { | |
| 53 | fn sqrt32(x: f32) f32 { | |
| 54 | 54 | const tiny: f32 = 1.0e-30; |
| 55 | 55 | const sign: i32 = @bitCast(i32, u32(0x80000000)); |
| 56 | 56 | var ix: i32 = @bitCast(i32, x); |
| ... | ... | @@ -129,7 +129,7 @@ fn sqrt32(x: f32) -> f32 { |
| 129 | 129 | // NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound |
| 130 | 130 | // behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are |
| 131 | 131 | // potentially some edge cases remaining that are not handled in the same way. |
| 132 | fn sqrt64(x: f64) -> f64 { | |
| 132 | fn sqrt64(x: f64) f64 { | |
| 133 | 133 | const tiny: f64 = 1.0e-300; |
| 134 | 134 | const sign: u32 = 0x80000000; |
| 135 | 135 | const u = @bitCast(u64, x); |
| ... | ... | @@ -308,7 +308,7 @@ test "math.sqrt64.special" { |
| 308 | 308 | assert(math.isNan(sqrt64(math.nan(f64)))); |
| 309 | 309 | } |
| 310 | 310 | |
| 311 | fn sqrt_int(comptime T: type, value: T) -> @IntType(false, T.bit_count / 2) { | |
| 311 | fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) { | |
| 312 | 312 | var op = value; |
| 313 | 313 | var res: T = 0; |
| 314 | 314 | var one: T = 1 << (T.bit_count - 2); |
std/math/tan.zig+3-3| ... | ... | @@ -9,7 +9,7 @@ const std = @import("../index.zig"); |
| 9 | 9 | const math = std.math; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | 11 | |
| 12 | pub fn tan(x: var) -> @typeOf(x) { | |
| 12 | pub fn tan(x: var) @typeOf(x) { | |
| 13 | 13 | const T = @typeOf(x); |
| 14 | 14 | return switch (T) { |
| 15 | 15 | f32 => tan32(x), |
| ... | ... | @@ -30,7 +30,7 @@ const Tq4 = -5.38695755929454629881E7; |
| 30 | 30 | // NOTE: This is taken from the go stdlib. The musl implementation is much more complex. |
| 31 | 31 | // |
| 32 | 32 | // This may have slight differences on some edge cases and may need to replaced if so. |
| 33 | fn tan32(x_: f32) -> f32 { | |
| 33 | fn tan32(x_: f32) f32 { | |
| 34 | 34 | @setFloatMode(this, @import("builtin").FloatMode.Strict); |
| 35 | 35 | |
| 36 | 36 | const pi4a = 7.85398125648498535156e-1; |
| ... | ... | @@ -81,7 +81,7 @@ fn tan32(x_: f32) -> f32 { |
| 81 | 81 | return r; |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | fn tan64(x_: f64) -> f64 { | |
| 84 | fn tan64(x_: f64) f64 { | |
| 85 | 85 | const pi4a = 7.85398125648498535156e-1; |
| 86 | 86 | const pi4b = 3.77489470793079817668E-8; |
| 87 | 87 | const pi4c = 2.69515142907905952645E-15; |
std/math/tanh.zig+3-3| ... | ... | @@ -10,7 +10,7 @@ const math = std.math; |
| 10 | 10 | const assert = std.debug.assert; |
| 11 | 11 | const expo2 = @import("expo2.zig").expo2; |
| 12 | 12 | |
| 13 | pub fn tanh(x: var) -> @typeOf(x) { | |
| 13 | pub fn tanh(x: var) @typeOf(x) { | |
| 14 | 14 | const T = @typeOf(x); |
| 15 | 15 | return switch (T) { |
| 16 | 16 | f32 => tanh32(x), |
| ... | ... | @@ -22,7 +22,7 @@ pub fn tanh(x: var) -> @typeOf(x) { |
| 22 | 22 | // tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x)) |
| 23 | 23 | // = (exp(2x) - 1) / (exp(2x) - 1 + 2) |
| 24 | 24 | // = (1 - exp(-2x)) / (exp(-2x) - 1 + 2) |
| 25 | fn tanh32(x: f32) -> f32 { | |
| 25 | fn tanh32(x: f32) f32 { | |
| 26 | 26 | const u = @bitCast(u32, x); |
| 27 | 27 | const ux = u & 0x7FFFFFFF; |
| 28 | 28 | const ax = @bitCast(f32, ux); |
| ... | ... | @@ -66,7 +66,7 @@ fn tanh32(x: f32) -> f32 { |
| 66 | 66 | } |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | fn tanh64(x: f64) -> f64 { | |
| 69 | fn tanh64(x: f64) f64 { | |
| 70 | 70 | const u = @bitCast(u64, x); |
| 71 | 71 | const w = u32(u >> 32); |
| 72 | 72 | const ax = @bitCast(f64, u & (@maxValue(u64) >> 1)); |
std/math/trunc.zig+3-3| ... | ... | @@ -8,7 +8,7 @@ const std = @import("../index.zig"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const assert = std.debug.assert; |
| 10 | 10 | |
| 11 | pub fn trunc(x: var) -> @typeOf(x) { | |
| 11 | pub fn trunc(x: var) @typeOf(x) { | |
| 12 | 12 | const T = @typeOf(x); |
| 13 | 13 | return switch (T) { |
| 14 | 14 | f32 => trunc32(x), |
| ... | ... | @@ -17,7 +17,7 @@ pub fn trunc(x: var) -> @typeOf(x) { |
| 17 | 17 | }; |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | fn trunc32(x: f32) -> f32 { | |
| 20 | fn trunc32(x: f32) f32 { | |
| 21 | 21 | const u = @bitCast(u32, x); |
| 22 | 22 | var e = i32(((u >> 23) & 0xFF)) - 0x7F + 9; |
| 23 | 23 | var m: u32 = undefined; |
| ... | ... | @@ -38,7 +38,7 @@ fn trunc32(x: f32) -> f32 { |
| 38 | 38 | } |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | fn trunc64(x: f64) -> f64 { | |
| 41 | fn trunc64(x: f64) f64 { | |
| 42 | 42 | const u = @bitCast(u64, x); |
| 43 | 43 | var e = i32(((u >> 52) & 0x7FF)) - 0x3FF + 12; |
| 44 | 44 | var m: u64 = undefined; |
std/math/x86_64/sqrt.zig+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | pub fn sqrt32(x: f32) -> f32 { | |
| 1 | pub fn sqrt32(x: f32) f32 { | |
| 2 | 2 | return asm ( |
| 3 | 3 | \\sqrtss %%xmm0, %%xmm0 |
| 4 | 4 | : [ret] "={xmm0}" (-> f32) |
| ... | ... | @@ -6,7 +6,7 @@ pub fn sqrt32(x: f32) -> f32 { |
| 6 | 6 | ); |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | pub fn sqrt64(x: f64) -> f64 { | |
| 9 | pub fn sqrt64(x: f64) f64 { | |
| 10 | 10 | return asm ( |
| 11 | 11 | \\sqrtsd %%xmm0, %%xmm0 |
| 12 | 12 | : [ret] "={xmm0}" (-> f64) |
std/mem.zig+50-50| ... | ... | @@ -10,7 +10,7 @@ pub const Allocator = struct { |
| 10 | 10 | /// Allocate byte_count bytes and return them in a slice, with the |
| 11 | 11 | /// slice's pointer aligned at least to alignment bytes. |
| 12 | 12 | /// The returned newly allocated memory is undefined. |
| 13 | allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) -> %[]u8, | |
| 13 | allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) %[]u8, | |
| 14 | 14 | |
| 15 | 15 | /// If `new_byte_count > old_mem.len`: |
| 16 | 16 | /// * `old_mem.len` is the same as what was returned from allocFn or reallocFn. |
| ... | ... | @@ -21,26 +21,26 @@ pub const Allocator = struct { |
| 21 | 21 | /// * alignment <= alignment of old_mem.ptr |
| 22 | 22 | /// |
| 23 | 23 | /// The returned newly allocated memory is undefined. |
| 24 | reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) -> %[]u8, | |
| 24 | reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) %[]u8, | |
| 25 | 25 | |
| 26 | 26 | /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn` |
| 27 | freeFn: fn (self: &Allocator, old_mem: []u8), | |
| 27 | freeFn: fn (self: &Allocator, old_mem: []u8) void, | |
| 28 | 28 | |
| 29 | fn create(self: &Allocator, comptime T: type) -> %&T { | |
| 29 | fn create(self: &Allocator, comptime T: type) %&T { | |
| 30 | 30 | const slice = try self.alloc(T, 1); |
| 31 | 31 | return &slice[0]; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | fn destroy(self: &Allocator, ptr: var) { | |
| 34 | fn destroy(self: &Allocator, ptr: var) void { | |
| 35 | 35 | self.free(ptr[0..1]); |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | fn alloc(self: &Allocator, comptime T: type, n: usize) -> %[]T { | |
| 38 | fn alloc(self: &Allocator, comptime T: type, n: usize) %[]T { | |
| 39 | 39 | return self.alignedAlloc(T, @alignOf(T), n); |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | 42 | fn alignedAlloc(self: &Allocator, comptime T: type, comptime alignment: u29, |
| 43 | n: usize) -> %[]align(alignment) T | |
| 43 | n: usize) %[]align(alignment) T | |
| 44 | 44 | { |
| 45 | 45 | const byte_count = try math.mul(usize, @sizeOf(T), n); |
| 46 | 46 | const byte_slice = try self.allocFn(self, byte_count, alignment); |
| ... | ... | @@ -51,12 +51,12 @@ pub const Allocator = struct { |
| 51 | 51 | return ([]align(alignment) T)(@alignCast(alignment, byte_slice)); |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | fn realloc(self: &Allocator, comptime T: type, old_mem: []T, n: usize) -> %[]T { | |
| 54 | fn realloc(self: &Allocator, comptime T: type, old_mem: []T, n: usize) %[]T { | |
| 55 | 55 | return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n); |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | 58 | fn alignedRealloc(self: &Allocator, comptime T: type, comptime alignment: u29, |
| 59 | old_mem: []align(alignment) T, n: usize) -> %[]align(alignment) T | |
| 59 | old_mem: []align(alignment) T, n: usize) %[]align(alignment) T | |
| 60 | 60 | { |
| 61 | 61 | if (old_mem.len == 0) { |
| 62 | 62 | return self.alloc(T, n); |
| ... | ... | @@ -75,12 +75,12 @@ pub const Allocator = struct { |
| 75 | 75 | /// Reallocate, but `n` must be less than or equal to `old_mem.len`. |
| 76 | 76 | /// Unlike `realloc`, this function cannot fail. |
| 77 | 77 | /// Shrinking to 0 is the same as calling `free`. |
| 78 | fn shrink(self: &Allocator, comptime T: type, old_mem: []T, n: usize) -> []T { | |
| 78 | fn shrink(self: &Allocator, comptime T: type, old_mem: []T, n: usize) []T { | |
| 79 | 79 | return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n); |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | fn alignedShrink(self: &Allocator, comptime T: type, comptime alignment: u29, |
| 83 | old_mem: []align(alignment) T, n: usize) -> []align(alignment) T | |
| 83 | old_mem: []align(alignment) T, n: usize) []align(alignment) T | |
| 84 | 84 | { |
| 85 | 85 | if (n == 0) { |
| 86 | 86 | self.free(old_mem); |
| ... | ... | @@ -97,7 +97,7 @@ pub const Allocator = struct { |
| 97 | 97 | return ([]align(alignment) T)(@alignCast(alignment, byte_slice)); |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | fn free(self: &Allocator, memory: var) { | |
| 100 | fn free(self: &Allocator, memory: var) void { | |
| 101 | 101 | const bytes = ([]const u8)(memory); |
| 102 | 102 | if (bytes.len == 0) |
| 103 | 103 | return; |
| ... | ... | @@ -111,7 +111,7 @@ pub const FixedBufferAllocator = struct { |
| 111 | 111 | end_index: usize, |
| 112 | 112 | buffer: []u8, |
| 113 | 113 | |
| 114 | pub fn init(buffer: []u8) -> FixedBufferAllocator { | |
| 114 | pub fn init(buffer: []u8) FixedBufferAllocator { | |
| 115 | 115 | return FixedBufferAllocator { |
| 116 | 116 | .allocator = Allocator { |
| 117 | 117 | .allocFn = alloc, |
| ... | ... | @@ -123,7 +123,7 @@ pub const FixedBufferAllocator = struct { |
| 123 | 123 | }; |
| 124 | 124 | } |
| 125 | 125 | |
| 126 | fn alloc(allocator: &Allocator, n: usize, alignment: u29) -> %[]u8 { | |
| 126 | fn alloc(allocator: &Allocator, n: usize, alignment: u29) %[]u8 { | |
| 127 | 127 | const self = @fieldParentPtr(FixedBufferAllocator, "allocator", allocator); |
| 128 | 128 | const addr = @ptrToInt(&self.buffer[self.end_index]); |
| 129 | 129 | const rem = @rem(addr, alignment); |
| ... | ... | @@ -138,7 +138,7 @@ pub const FixedBufferAllocator = struct { |
| 138 | 138 | return result; |
| 139 | 139 | } |
| 140 | 140 | |
| 141 | fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) -> %[]u8 { | |
| 141 | fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: u29) %[]u8 { | |
| 142 | 142 | if (new_size <= old_mem.len) { |
| 143 | 143 | return old_mem[0..new_size]; |
| 144 | 144 | } else { |
| ... | ... | @@ -148,27 +148,27 @@ pub const FixedBufferAllocator = struct { |
| 148 | 148 | } |
| 149 | 149 | } |
| 150 | 150 | |
| 151 | fn free(allocator: &Allocator, bytes: []u8) { } | |
| 151 | fn free(allocator: &Allocator, bytes: []u8) void { } | |
| 152 | 152 | }; |
| 153 | 153 | |
| 154 | 154 | |
| 155 | 155 | /// Copy all of source into dest at position 0. |
| 156 | 156 | /// dest.len must be >= source.len. |
| 157 | pub fn copy(comptime T: type, dest: []T, source: []const T) { | |
| 157 | pub fn copy(comptime T: type, dest: []T, source: []const T) void { | |
| 158 | 158 | // TODO instead of manually doing this check for the whole array |
| 159 | // and turning off debug safety, the compiler should detect loops like | |
| 159 | // and turning off runtime safety, the compiler should detect loops like | |
| 160 | 160 | // this and automatically omit safety checks for loops |
| 161 | @setDebugSafety(this, false); | |
| 161 | @setRuntimeSafety(false); | |
| 162 | 162 | assert(dest.len >= source.len); |
| 163 | 163 | for (source) |s, i| dest[i] = s; |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | pub fn set(comptime T: type, dest: []T, value: T) { | |
| 166 | pub fn set(comptime T: type, dest: []T, value: T) void { | |
| 167 | 167 | for (dest) |*d| *d = value; |
| 168 | 168 | } |
| 169 | 169 | |
| 170 | 170 | /// Returns true if lhs < rhs, false otherwise |
| 171 | pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) -> bool { | |
| 171 | pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool { | |
| 172 | 172 | const n = math.min(lhs.len, rhs.len); |
| 173 | 173 | var i: usize = 0; |
| 174 | 174 | while (i < n) : (i += 1) { |
| ... | ... | @@ -188,7 +188,7 @@ test "mem.lessThan" { |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | 190 | /// Compares two slices and returns whether they are equal. |
| 191 | pub fn eql(comptime T: type, a: []const T, b: []const T) -> bool { | |
| 191 | pub fn eql(comptime T: type, a: []const T, b: []const T) bool { | |
| 192 | 192 | if (a.len != b.len) return false; |
| 193 | 193 | for (a) |item, index| { |
| 194 | 194 | if (b[index] != item) return false; |
| ... | ... | @@ -197,14 +197,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) -> bool { |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | 199 | /// Copies ::m to newly allocated memory. Caller is responsible to free it. |
| 200 | pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) -> %[]T { | |
| 200 | pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) %[]T { | |
| 201 | 201 | const new_buf = try allocator.alloc(T, m.len); |
| 202 | 202 | copy(T, new_buf, m); |
| 203 | 203 | return new_buf; |
| 204 | 204 | } |
| 205 | 205 | |
| 206 | 206 | /// Remove values from the beginning and end of a slice. |
| 207 | pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) -> []const T { | |
| 207 | pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []const T { | |
| 208 | 208 | var begin: usize = 0; |
| 209 | 209 | var end: usize = slice.len; |
| 210 | 210 | while (begin < end and indexOfScalar(T, values_to_strip, slice[begin]) != null) : (begin += 1) {} |
| ... | ... | @@ -218,11 +218,11 @@ test "mem.trim" { |
| 218 | 218 | } |
| 219 | 219 | |
| 220 | 220 | /// Linear search for the index of a scalar value inside a slice. |
| 221 | pub fn indexOfScalar(comptime T: type, slice: []const T, value: T) -> ?usize { | |
| 221 | pub fn indexOfScalar(comptime T: type, slice: []const T, value: T) ?usize { | |
| 222 | 222 | return indexOfScalarPos(T, slice, 0, value); |
| 223 | 223 | } |
| 224 | 224 | |
| 225 | pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) -> ?usize { | |
| 225 | pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize { | |
| 226 | 226 | var i: usize = start_index; |
| 227 | 227 | while (i < slice.len) : (i += 1) { |
| 228 | 228 | if (slice[i] == value) |
| ... | ... | @@ -231,11 +231,11 @@ pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, |
| 231 | 231 | return null; |
| 232 | 232 | } |
| 233 | 233 | |
| 234 | pub fn indexOfAny(comptime T: type, slice: []const T, values: []const T) -> ?usize { | |
| 234 | pub fn indexOfAny(comptime T: type, slice: []const T, values: []const T) ?usize { | |
| 235 | 235 | return indexOfAnyPos(T, slice, 0, values); |
| 236 | 236 | } |
| 237 | 237 | |
| 238 | pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, values: []const T) -> ?usize { | |
| 238 | pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, values: []const T) ?usize { | |
| 239 | 239 | var i: usize = start_index; |
| 240 | 240 | while (i < slice.len) : (i += 1) { |
| 241 | 241 | for (values) |value| { |
| ... | ... | @@ -246,12 +246,12 @@ pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, val |
| 246 | 246 | return null; |
| 247 | 247 | } |
| 248 | 248 | |
| 249 | pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) -> ?usize { | |
| 249 | pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize { | |
| 250 | 250 | return indexOfPos(T, haystack, 0, needle); |
| 251 | 251 | } |
| 252 | 252 | |
| 253 | 253 | // TODO boyer-moore algorithm |
| 254 | pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) -> ?usize { | |
| 254 | pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize { | |
| 255 | 255 | if (needle.len > haystack.len) |
| 256 | 256 | return null; |
| 257 | 257 | |
| ... | ... | @@ -275,7 +275,7 @@ test "mem.indexOf" { |
| 275 | 275 | /// T specifies the return type, which must be large enough to store |
| 276 | 276 | /// the result. |
| 277 | 277 | /// See also ::readIntBE or ::readIntLE. |
| 278 | pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) -> T { | |
| 278 | pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T { | |
| 279 | 279 | if (T.bit_count == 8) { |
| 280 | 280 | return bytes[0]; |
| 281 | 281 | } |
| ... | ... | @@ -298,7 +298,7 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) -> T |
| 298 | 298 | |
| 299 | 299 | /// Reads a big-endian int of type T from bytes. |
| 300 | 300 | /// bytes.len must be exactly @sizeOf(T). |
| 301 | pub fn readIntBE(comptime T: type, bytes: []const u8) -> T { | |
| 301 | pub fn readIntBE(comptime T: type, bytes: []const u8) T { | |
| 302 | 302 | if (T.is_signed) { |
| 303 | 303 | return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes)); |
| 304 | 304 | } |
| ... | ... | @@ -312,7 +312,7 @@ pub fn readIntBE(comptime T: type, bytes: []const u8) -> T { |
| 312 | 312 | |
| 313 | 313 | /// Reads a little-endian int of type T from bytes. |
| 314 | 314 | /// bytes.len must be exactly @sizeOf(T). |
| 315 | pub fn readIntLE(comptime T: type, bytes: []const u8) -> T { | |
| 315 | pub fn readIntLE(comptime T: type, bytes: []const u8) T { | |
| 316 | 316 | if (T.is_signed) { |
| 317 | 317 | return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes)); |
| 318 | 318 | } |
| ... | ... | @@ -327,7 +327,7 @@ pub fn readIntLE(comptime T: type, bytes: []const u8) -> T { |
| 327 | 327 | /// Writes an integer to memory with size equal to bytes.len. Pads with zeroes |
| 328 | 328 | /// to fill the entire buffer provided. |
| 329 | 329 | /// value must be an integer. |
| 330 | pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) { | |
| 330 | pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void { | |
| 331 | 331 | const uint = @IntType(false, @typeOf(value).bit_count); |
| 332 | 332 | var bits = @truncate(uint, value); |
| 333 | 333 | switch (endian) { |
| ... | ... | @@ -351,7 +351,7 @@ pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) { |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | 353 | |
| 354 | pub fn hash_slice_u8(k: []const u8) -> u32 { | |
| 354 | pub fn hash_slice_u8(k: []const u8) u32 { | |
| 355 | 355 | // FNV 32-bit hash |
| 356 | 356 | var h: u32 = 2166136261; |
| 357 | 357 | for (k) |b| { |
| ... | ... | @@ -360,7 +360,7 @@ pub fn hash_slice_u8(k: []const u8) -> u32 { |
| 360 | 360 | return h; |
| 361 | 361 | } |
| 362 | 362 | |
| 363 | pub fn eql_slice_u8(a: []const u8, b: []const u8) -> bool { | |
| 363 | pub fn eql_slice_u8(a: []const u8, b: []const u8) bool { | |
| 364 | 364 | return eql(u8, a, b); |
| 365 | 365 | } |
| 366 | 366 | |
| ... | ... | @@ -368,7 +368,7 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) -> bool { |
| 368 | 368 | /// any of the bytes in `split_bytes`. |
| 369 | 369 | /// split(" abc def ghi ", " ") |
| 370 | 370 | /// Will return slices for "abc", "def", "ghi", null, in that order. |
| 371 | pub fn split(buffer: []const u8, split_bytes: []const u8) -> SplitIterator { | |
| 371 | pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator { | |
| 372 | 372 | return SplitIterator { |
| 373 | 373 | .index = 0, |
| 374 | 374 | .buffer = buffer, |
| ... | ... | @@ -384,7 +384,7 @@ test "mem.split" { |
| 384 | 384 | assert(it.next() == null); |
| 385 | 385 | } |
| 386 | 386 | |
| 387 | pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) -> bool { | |
| 387 | pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool { | |
| 388 | 388 | return if (needle.len > haystack.len) false else eql(T, haystack[0 .. needle.len], needle); |
| 389 | 389 | } |
| 390 | 390 | |
| ... | ... | @@ -393,7 +393,7 @@ const SplitIterator = struct { |
| 393 | 393 | split_bytes: []const u8, |
| 394 | 394 | index: usize, |
| 395 | 395 | |
| 396 | pub fn next(self: &SplitIterator) -> ?[]const u8 { | |
| 396 | pub fn next(self: &SplitIterator) ?[]const u8 { | |
| 397 | 397 | // move to beginning of token |
| 398 | 398 | while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {} |
| 399 | 399 | const start = self.index; |
| ... | ... | @@ -409,14 +409,14 @@ const SplitIterator = struct { |
| 409 | 409 | } |
| 410 | 410 | |
| 411 | 411 | /// Returns a slice of the remaining bytes. Does not affect iterator state. |
| 412 | pub fn rest(self: &const SplitIterator) -> []const u8 { | |
| 412 | pub fn rest(self: &const SplitIterator) []const u8 { | |
| 413 | 413 | // move to beginning of token |
| 414 | 414 | var index: usize = self.index; |
| 415 | 415 | while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {} |
| 416 | 416 | return self.buffer[index..]; |
| 417 | 417 | } |
| 418 | 418 | |
| 419 | fn isSplitByte(self: &const SplitIterator, byte: u8) -> bool { | |
| 419 | fn isSplitByte(self: &const SplitIterator, byte: u8) bool { | |
| 420 | 420 | for (self.split_bytes) |split_byte| { |
| 421 | 421 | if (byte == split_byte) { |
| 422 | 422 | return true; |
| ... | ... | @@ -428,7 +428,7 @@ const SplitIterator = struct { |
| 428 | 428 | |
| 429 | 429 | /// Naively combines a series of strings with a separator. |
| 430 | 430 | /// Allocates memory for the result, which must be freed by the caller. |
| 431 | pub fn join(allocator: &Allocator, sep: u8, strings: ...) -> %[]u8 { | |
| 431 | pub fn join(allocator: &Allocator, sep: u8, strings: ...) %[]u8 { | |
| 432 | 432 | comptime assert(strings.len >= 1); |
| 433 | 433 | var total_strings_len: usize = strings.len; // 1 sep per string |
| 434 | 434 | { |
| ... | ... | @@ -440,7 +440,7 @@ pub fn join(allocator: &Allocator, sep: u8, strings: ...) -> %[]u8 { |
| 440 | 440 | } |
| 441 | 441 | |
| 442 | 442 | const buf = try allocator.alloc(u8, total_strings_len); |
| 443 | %defer allocator.free(buf); | |
| 443 | errdefer allocator.free(buf); | |
| 444 | 444 | |
| 445 | 445 | var buf_index: usize = 0; |
| 446 | 446 | comptime var string_i = 0; |
| ... | ... | @@ -474,7 +474,7 @@ test "testReadInt" { |
| 474 | 474 | testReadIntImpl(); |
| 475 | 475 | comptime testReadIntImpl(); |
| 476 | 476 | } |
| 477 | fn testReadIntImpl() { | |
| 477 | fn testReadIntImpl() void { | |
| 478 | 478 | { |
| 479 | 479 | const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 }; |
| 480 | 480 | assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678); |
| ... | ... | @@ -507,7 +507,7 @@ test "testWriteInt" { |
| 507 | 507 | testWriteIntImpl(); |
| 508 | 508 | comptime testWriteIntImpl(); |
| 509 | 509 | } |
| 510 | fn testWriteIntImpl() { | |
| 510 | fn testWriteIntImpl() void { | |
| 511 | 511 | var bytes: [4]u8 = undefined; |
| 512 | 512 | |
| 513 | 513 | writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big); |
| ... | ... | @@ -524,7 +524,7 @@ fn testWriteIntImpl() { |
| 524 | 524 | } |
| 525 | 525 | |
| 526 | 526 | |
| 527 | pub fn min(comptime T: type, slice: []const T) -> T { | |
| 527 | pub fn min(comptime T: type, slice: []const T) T { | |
| 528 | 528 | var best = slice[0]; |
| 529 | 529 | for (slice[1..]) |item| { |
| 530 | 530 | best = math.min(best, item); |
| ... | ... | @@ -536,7 +536,7 @@ test "mem.min" { |
| 536 | 536 | assert(min(u8, "abcdefg") == 'a'); |
| 537 | 537 | } |
| 538 | 538 | |
| 539 | pub fn max(comptime T: type, slice: []const T) -> T { | |
| 539 | pub fn max(comptime T: type, slice: []const T) T { | |
| 540 | 540 | var best = slice[0]; |
| 541 | 541 | for (slice[1..]) |item| { |
| 542 | 542 | best = math.max(best, item); |
| ... | ... | @@ -548,14 +548,14 @@ test "mem.max" { |
| 548 | 548 | assert(max(u8, "abcdefg") == 'g'); |
| 549 | 549 | } |
| 550 | 550 | |
| 551 | pub fn swap(comptime T: type, a: &T, b: &T) { | |
| 551 | pub fn swap(comptime T: type, a: &T, b: &T) void { | |
| 552 | 552 | const tmp = *a; |
| 553 | 553 | *a = *b; |
| 554 | 554 | *b = tmp; |
| 555 | 555 | } |
| 556 | 556 | |
| 557 | 557 | /// In-place order reversal of a slice |
| 558 | pub fn reverse(comptime T: type, items: []T) { | |
| 558 | pub fn reverse(comptime T: type, items: []T) void { | |
| 559 | 559 | var i: usize = 0; |
| 560 | 560 | const end = items.len / 2; |
| 561 | 561 | while (i < end) : (i += 1) { |
| ... | ... | @@ -572,7 +572,7 @@ test "std.mem.reverse" { |
| 572 | 572 | |
| 573 | 573 | /// In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1) |
| 574 | 574 | /// Assumes 0 <= amount <= items.len |
| 575 | pub fn rotate(comptime T: type, items: []T, amount: usize) { | |
| 575 | pub fn rotate(comptime T: type, items: []T, amount: usize) void { | |
| 576 | 576 | reverse(T, items[0..amount]); |
| 577 | 577 | reverse(T, items[amount..]); |
| 578 | 578 | reverse(T, items); |
std/net.zig+10-10| ... | ... | @@ -17,7 +17,7 @@ error BadFd; |
| 17 | 17 | const Connection = struct { |
| 18 | 18 | socket_fd: i32, |
| 19 | 19 | |
| 20 | pub fn send(c: Connection, buf: []const u8) -> %usize { | |
| 20 | pub fn send(c: Connection, buf: []const u8) %usize { | |
| 21 | 21 | const send_ret = linux.sendto(c.socket_fd, buf.ptr, buf.len, 0, null, 0); |
| 22 | 22 | const send_err = linux.getErrno(send_ret); |
| 23 | 23 | switch (send_err) { |
| ... | ... | @@ -31,7 +31,7 @@ const Connection = struct { |
| 31 | 31 | } |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | pub fn recv(c: Connection, buf: []u8) -> %[]u8 { | |
| 34 | pub fn recv(c: Connection, buf: []u8) %[]u8 { | |
| 35 | 35 | const recv_ret = linux.recvfrom(c.socket_fd, buf.ptr, buf.len, 0, null, null); |
| 36 | 36 | const recv_err = linux.getErrno(recv_ret); |
| 37 | 37 | switch (recv_err) { |
| ... | ... | @@ -48,7 +48,7 @@ const Connection = struct { |
| 48 | 48 | } |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | pub fn close(c: Connection) -> %void { | |
| 51 | pub fn close(c: Connection) %void { | |
| 52 | 52 | switch (linux.getErrno(linux.close(c.socket_fd))) { |
| 53 | 53 | 0 => return, |
| 54 | 54 | linux.EBADF => unreachable, |
| ... | ... | @@ -66,7 +66,7 @@ const Address = struct { |
| 66 | 66 | sort_key: i32, |
| 67 | 67 | }; |
| 68 | 68 | |
| 69 | pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address { | |
| 69 | pub fn lookup(hostname: []const u8, out_addrs: []Address) %[]Address { | |
| 70 | 70 | if (hostname.len == 0) { |
| 71 | 71 | |
| 72 | 72 | unreachable; // TODO |
| ... | ... | @@ -75,7 +75,7 @@ pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address { |
| 75 | 75 | unreachable; // TODO |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | pub fn connectAddr(addr: &Address, port: u16) -> %Connection { | |
| 78 | pub fn connectAddr(addr: &Address, port: u16) %Connection { | |
| 79 | 79 | const socket_ret = linux.socket(addr.family, linux.SOCK_STREAM, linux.PROTO_tcp); |
| 80 | 80 | const socket_err = linux.getErrno(socket_ret); |
| 81 | 81 | if (socket_err > 0) { |
| ... | ... | @@ -118,7 +118,7 @@ pub fn connectAddr(addr: &Address, port: u16) -> %Connection { |
| 118 | 118 | }; |
| 119 | 119 | } |
| 120 | 120 | |
| 121 | pub fn connect(hostname: []const u8, port: u16) -> %Connection { | |
| 121 | pub fn connect(hostname: []const u8, port: u16) %Connection { | |
| 122 | 122 | var addrs_buf: [1]Address = undefined; |
| 123 | 123 | const addrs_slice = try lookup(hostname, addrs_buf[0..]); |
| 124 | 124 | const main_addr = &addrs_slice[0]; |
| ... | ... | @@ -128,12 +128,12 @@ pub fn connect(hostname: []const u8, port: u16) -> %Connection { |
| 128 | 128 | |
| 129 | 129 | error InvalidIpLiteral; |
| 130 | 130 | |
| 131 | pub fn parseIpLiteral(buf: []const u8) -> %Address { | |
| 131 | pub fn parseIpLiteral(buf: []const u8) %Address { | |
| 132 | 132 | |
| 133 | 133 | return error.InvalidIpLiteral; |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | fn hexDigit(c: u8) -> u8 { | |
| 136 | fn hexDigit(c: u8) u8 { | |
| 137 | 137 | // TODO use switch with range |
| 138 | 138 | if ('0' <= c and c <= '9') { |
| 139 | 139 | return c - '0'; |
| ... | ... | @@ -151,7 +151,7 @@ error Overflow; |
| 151 | 151 | error JunkAtEnd; |
| 152 | 152 | error Incomplete; |
| 153 | 153 | |
| 154 | fn parseIp6(buf: []const u8) -> %Address { | |
| 154 | fn parseIp6(buf: []const u8) %Address { | |
| 155 | 155 | var result: Address = undefined; |
| 156 | 156 | result.family = linux.AF_INET6; |
| 157 | 157 | result.scope_id = 0; |
| ... | ... | @@ -232,7 +232,7 @@ fn parseIp6(buf: []const u8) -> %Address { |
| 232 | 232 | return error.Incomplete; |
| 233 | 233 | } |
| 234 | 234 | |
| 235 | fn parseIp4(buf: []const u8) -> %u32 { | |
| 235 | fn parseIp4(buf: []const u8) %u32 { | |
| 236 | 236 | var result: u32 = undefined; |
| 237 | 237 | const out_ptr = ([]u8)((&result)[0..1]); |
| 238 | 238 |
std/os/child_process.zig+49-49| ... | ... | @@ -37,7 +37,7 @@ pub const ChildProcess = struct { |
| 37 | 37 | pub argv: []const []const u8, |
| 38 | 38 | |
| 39 | 39 | /// Possibly called from a signal handler. Must set this before calling `spawn`. |
| 40 | pub onTerm: ?fn(&ChildProcess), | |
| 40 | pub onTerm: ?fn(&ChildProcess)void, | |
| 41 | 41 | |
| 42 | 42 | /// Leave as null to use the current env map using the supplied allocator. |
| 43 | 43 | pub env_map: ?&const BufMap, |
| ... | ... | @@ -74,9 +74,9 @@ pub const ChildProcess = struct { |
| 74 | 74 | |
| 75 | 75 | /// First argument in argv is the executable. |
| 76 | 76 | /// On success must call deinit. |
| 77 | pub fn init(argv: []const []const u8, allocator: &mem.Allocator) -> %&ChildProcess { | |
| 77 | pub fn init(argv: []const []const u8, allocator: &mem.Allocator) %&ChildProcess { | |
| 78 | 78 | const child = try allocator.create(ChildProcess); |
| 79 | %defer allocator.destroy(child); | |
| 79 | errdefer allocator.destroy(child); | |
| 80 | 80 | |
| 81 | 81 | *child = ChildProcess { |
| 82 | 82 | .allocator = allocator, |
| ... | ... | @@ -103,7 +103,7 @@ pub const ChildProcess = struct { |
| 103 | 103 | return child; |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | pub fn setUserName(self: &ChildProcess, name: []const u8) -> %void { | |
| 106 | pub fn setUserName(self: &ChildProcess, name: []const u8) %void { | |
| 107 | 107 | const user_info = try os.getUserInfo(name); |
| 108 | 108 | self.uid = user_info.uid; |
| 109 | 109 | self.gid = user_info.gid; |
| ... | ... | @@ -111,7 +111,7 @@ pub const ChildProcess = struct { |
| 111 | 111 | |
| 112 | 112 | /// onTerm can be called before `spawn` returns. |
| 113 | 113 | /// On success must call `kill` or `wait`. |
| 114 | pub fn spawn(self: &ChildProcess) -> %void { | |
| 114 | pub fn spawn(self: &ChildProcess) %void { | |
| 115 | 115 | if (is_windows) { |
| 116 | 116 | return self.spawnWindows(); |
| 117 | 117 | } else { |
| ... | ... | @@ -119,13 +119,13 @@ pub const ChildProcess = struct { |
| 119 | 119 | } |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | pub fn spawnAndWait(self: &ChildProcess) -> %Term { | |
| 122 | pub fn spawnAndWait(self: &ChildProcess) %Term { | |
| 123 | 123 | try self.spawn(); |
| 124 | 124 | return self.wait(); |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | /// Forcibly terminates child process and then cleans up all resources. |
| 128 | pub fn kill(self: &ChildProcess) -> %Term { | |
| 128 | pub fn kill(self: &ChildProcess) %Term { | |
| 129 | 129 | if (is_windows) { |
| 130 | 130 | return self.killWindows(1); |
| 131 | 131 | } else { |
| ... | ... | @@ -133,7 +133,7 @@ pub const ChildProcess = struct { |
| 133 | 133 | } |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | pub fn killWindows(self: &ChildProcess, exit_code: windows.UINT) -> %Term { | |
| 136 | pub fn killWindows(self: &ChildProcess, exit_code: windows.UINT) %Term { | |
| 137 | 137 | if (self.term) |term| { |
| 138 | 138 | self.cleanupStreams(); |
| 139 | 139 | return term; |
| ... | ... | @@ -149,7 +149,7 @@ pub const ChildProcess = struct { |
| 149 | 149 | return ??self.term; |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | pub fn killPosix(self: &ChildProcess) -> %Term { | |
| 152 | pub fn killPosix(self: &ChildProcess) %Term { | |
| 153 | 153 | block_SIGCHLD(); |
| 154 | 154 | defer restore_SIGCHLD(); |
| 155 | 155 | |
| ... | ... | @@ -172,7 +172,7 @@ pub const ChildProcess = struct { |
| 172 | 172 | } |
| 173 | 173 | |
| 174 | 174 | /// Blocks until child process terminates and then cleans up all resources. |
| 175 | pub fn wait(self: &ChildProcess) -> %Term { | |
| 175 | pub fn wait(self: &ChildProcess) %Term { | |
| 176 | 176 | if (is_windows) { |
| 177 | 177 | return self.waitWindows(); |
| 178 | 178 | } else { |
| ... | ... | @@ -189,7 +189,7 @@ pub const ChildProcess = struct { |
| 189 | 189 | /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. |
| 190 | 190 | /// If it succeeds, the caller owns result.stdout and result.stderr memory. |
| 191 | 191 | pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, |
| 192 | env_map: ?&const BufMap, max_output_size: usize) -> %ExecResult | |
| 192 | env_map: ?&const BufMap, max_output_size: usize) %ExecResult | |
| 193 | 193 | { |
| 194 | 194 | const child = try ChildProcess.init(argv, allocator); |
| 195 | 195 | defer child.deinit(); |
| ... | ... | @@ -220,7 +220,7 @@ pub const ChildProcess = struct { |
| 220 | 220 | }; |
| 221 | 221 | } |
| 222 | 222 | |
| 223 | fn waitWindows(self: &ChildProcess) -> %Term { | |
| 223 | fn waitWindows(self: &ChildProcess) %Term { | |
| 224 | 224 | if (self.term) |term| { |
| 225 | 225 | self.cleanupStreams(); |
| 226 | 226 | return term; |
| ... | ... | @@ -230,7 +230,7 @@ pub const ChildProcess = struct { |
| 230 | 230 | return ??self.term; |
| 231 | 231 | } |
| 232 | 232 | |
| 233 | fn waitPosix(self: &ChildProcess) -> %Term { | |
| 233 | fn waitPosix(self: &ChildProcess) %Term { | |
| 234 | 234 | block_SIGCHLD(); |
| 235 | 235 | defer restore_SIGCHLD(); |
| 236 | 236 | |
| ... | ... | @@ -243,11 +243,11 @@ pub const ChildProcess = struct { |
| 243 | 243 | return ??self.term; |
| 244 | 244 | } |
| 245 | 245 | |
| 246 | pub fn deinit(self: &ChildProcess) { | |
| 246 | pub fn deinit(self: &ChildProcess) void { | |
| 247 | 247 | self.allocator.destroy(self); |
| 248 | 248 | } |
| 249 | 249 | |
| 250 | fn waitUnwrappedWindows(self: &ChildProcess) -> %void { | |
| 250 | fn waitUnwrappedWindows(self: &ChildProcess) %void { | |
| 251 | 251 | const result = os.windowsWaitSingle(self.handle, windows.INFINITE); |
| 252 | 252 | |
| 253 | 253 | self.term = (%Term)(x: { |
| ... | ... | @@ -265,7 +265,7 @@ pub const ChildProcess = struct { |
| 265 | 265 | return result; |
| 266 | 266 | } |
| 267 | 267 | |
| 268 | fn waitUnwrapped(self: &ChildProcess) { | |
| 268 | fn waitUnwrapped(self: &ChildProcess) void { | |
| 269 | 269 | var status: i32 = undefined; |
| 270 | 270 | while (true) { |
| 271 | 271 | const err = posix.getErrno(posix.waitpid(self.pid, &status, 0)); |
| ... | ... | @@ -281,7 +281,7 @@ pub const ChildProcess = struct { |
| 281 | 281 | } |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | fn handleWaitResult(self: &ChildProcess, status: i32) { | |
| 284 | fn handleWaitResult(self: &ChildProcess, status: i32) void { | |
| 285 | 285 | self.term = self.cleanupAfterWait(status); |
| 286 | 286 | |
| 287 | 287 | if (self.onTerm) |onTerm| { |
| ... | ... | @@ -289,13 +289,13 @@ pub const ChildProcess = struct { |
| 289 | 289 | } |
| 290 | 290 | } |
| 291 | 291 | |
| 292 | fn cleanupStreams(self: &ChildProcess) { | |
| 292 | fn cleanupStreams(self: &ChildProcess) void { | |
| 293 | 293 | if (self.stdin) |*stdin| { stdin.close(); self.stdin = null; } |
| 294 | 294 | if (self.stdout) |*stdout| { stdout.close(); self.stdout = null; } |
| 295 | 295 | if (self.stderr) |*stderr| { stderr.close(); self.stderr = null; } |
| 296 | 296 | } |
| 297 | 297 | |
| 298 | fn cleanupAfterWait(self: &ChildProcess, status: i32) -> %Term { | |
| 298 | fn cleanupAfterWait(self: &ChildProcess, status: i32) %Term { | |
| 299 | 299 | children_nodes.remove(&self.llnode); |
| 300 | 300 | |
| 301 | 301 | defer { |
| ... | ... | @@ -319,7 +319,7 @@ pub const ChildProcess = struct { |
| 319 | 319 | return statusToTerm(status); |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | fn statusToTerm(status: i32) -> Term { | |
| 322 | fn statusToTerm(status: i32) Term { | |
| 323 | 323 | return if (posix.WIFEXITED(status)) |
| 324 | 324 | Term { .Exited = posix.WEXITSTATUS(status) } |
| 325 | 325 | else if (posix.WIFSIGNALED(status)) |
| ... | ... | @@ -331,18 +331,18 @@ pub const ChildProcess = struct { |
| 331 | 331 | ; |
| 332 | 332 | } |
| 333 | 333 | |
| 334 | fn spawnPosix(self: &ChildProcess) -> %void { | |
| 334 | fn spawnPosix(self: &ChildProcess) %void { | |
| 335 | 335 | // TODO atomically set a flag saying that we already did this |
| 336 | 336 | install_SIGCHLD_handler(); |
| 337 | 337 | |
| 338 | 338 | const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined; |
| 339 | %defer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); }; | |
| 339 | errdefer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); }; | |
| 340 | 340 | |
| 341 | 341 | const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined; |
| 342 | %defer if (self.stdout_behavior == StdIo.Pipe) { destroyPipe(stdout_pipe); }; | |
| 342 | errdefer if (self.stdout_behavior == StdIo.Pipe) { destroyPipe(stdout_pipe); }; | |
| 343 | 343 | |
| 344 | 344 | const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined; |
| 345 | %defer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); }; | |
| 345 | errdefer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); }; | |
| 346 | 346 | |
| 347 | 347 | const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); |
| 348 | 348 | const dev_null_fd = if (any_ignore) |
| ... | ... | @@ -367,7 +367,7 @@ pub const ChildProcess = struct { |
| 367 | 367 | // This pipe is used to communicate errors between the time of fork |
| 368 | 368 | // and execve from the child process to the parent process. |
| 369 | 369 | const err_pipe = try makePipe(); |
| 370 | %defer destroyPipe(err_pipe); | |
| 370 | errdefer destroyPipe(err_pipe); | |
| 371 | 371 | |
| 372 | 372 | block_SIGCHLD(); |
| 373 | 373 | const pid_result = posix.fork(); |
| ... | ... | @@ -440,7 +440,7 @@ pub const ChildProcess = struct { |
| 440 | 440 | if (self.stderr_behavior == StdIo.Pipe) { os.close(stderr_pipe[1]); } |
| 441 | 441 | } |
| 442 | 442 | |
| 443 | fn spawnWindows(self: &ChildProcess) -> %void { | |
| 443 | fn spawnWindows(self: &ChildProcess) %void { | |
| 444 | 444 | const saAttr = windows.SECURITY_ATTRIBUTES { |
| 445 | 445 | .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES), |
| 446 | 446 | .bInheritHandle = windows.TRUE, |
| ... | ... | @@ -479,7 +479,7 @@ pub const ChildProcess = struct { |
| 479 | 479 | g_hChildStd_IN_Rd = null; |
| 480 | 480 | }, |
| 481 | 481 | } |
| 482 | %defer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); }; | |
| 482 | errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); }; | |
| 483 | 483 | |
| 484 | 484 | var g_hChildStd_OUT_Rd: ?windows.HANDLE = null; |
| 485 | 485 | var g_hChildStd_OUT_Wr: ?windows.HANDLE = null; |
| ... | ... | @@ -497,7 +497,7 @@ pub const ChildProcess = struct { |
| 497 | 497 | g_hChildStd_OUT_Wr = null; |
| 498 | 498 | }, |
| 499 | 499 | } |
| 500 | %defer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); }; | |
| 500 | errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); }; | |
| 501 | 501 | |
| 502 | 502 | var g_hChildStd_ERR_Rd: ?windows.HANDLE = null; |
| 503 | 503 | var g_hChildStd_ERR_Wr: ?windows.HANDLE = null; |
| ... | ... | @@ -515,7 +515,7 @@ pub const ChildProcess = struct { |
| 515 | 515 | g_hChildStd_ERR_Wr = null; |
| 516 | 516 | }, |
| 517 | 517 | } |
| 518 | %defer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); }; | |
| 518 | errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); }; | |
| 519 | 519 | |
| 520 | 520 | const cmd_line = try windowsCreateCommandLine(self.allocator, self.argv); |
| 521 | 521 | defer self.allocator.free(cmd_line); |
| ... | ... | @@ -623,7 +623,7 @@ pub const ChildProcess = struct { |
| 623 | 623 | if (self.stdout_behavior == StdIo.Pipe) { os.close(??g_hChildStd_OUT_Wr); } |
| 624 | 624 | } |
| 625 | 625 | |
| 626 | fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) -> %void { | |
| 626 | fn setUpChildIo(stdio: StdIo, pipe_fd: i32, std_fileno: i32, dev_null_fd: i32) %void { | |
| 627 | 627 | switch (stdio) { |
| 628 | 628 | StdIo.Pipe => try os.posixDup2(pipe_fd, std_fileno), |
| 629 | 629 | StdIo.Close => os.close(std_fileno), |
| ... | ... | @@ -635,7 +635,7 @@ pub const ChildProcess = struct { |
| 635 | 635 | }; |
| 636 | 636 | |
| 637 | 637 | fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8, |
| 638 | lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) -> %void | |
| 638 | lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) %void | |
| 639 | 639 | { |
| 640 | 640 | if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0, |
| 641 | 641 | @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0) |
| ... | ... | @@ -655,7 +655,7 @@ fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ? |
| 655 | 655 | |
| 656 | 656 | /// Caller must dealloc. |
| 657 | 657 | /// Guarantees a null byte at result[result.len]. |
| 658 | fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) -> %[]u8 { | |
| 658 | fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) %[]u8 { | |
| 659 | 659 | var buf = try Buffer.initSize(allocator, 0); |
| 660 | 660 | defer buf.deinit(); |
| 661 | 661 | |
| ... | ... | @@ -690,7 +690,7 @@ fn windowsCreateCommandLine(allocator: &mem.Allocator, argv: []const []const u8) |
| 690 | 690 | return buf.toOwnedSlice(); |
| 691 | 691 | } |
| 692 | 692 | |
| 693 | fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) { | |
| 693 | fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) void { | |
| 694 | 694 | if (rd) |h| os.close(h); |
| 695 | 695 | if (wr) |h| os.close(h); |
| 696 | 696 | } |
| ... | ... | @@ -700,7 +700,7 @@ fn windowsDestroyPipe(rd: ?windows.HANDLE, wr: ?windows.HANDLE) { |
| 700 | 700 | // a namespace field lookup |
| 701 | 701 | const SECURITY_ATTRIBUTES = windows.SECURITY_ATTRIBUTES; |
| 702 | 702 | |
| 703 | fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void { | |
| 703 | fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) %void { | |
| 704 | 704 | if (windows.CreatePipe(rd, wr, sattr, 0) == 0) { |
| 705 | 705 | const err = windows.GetLastError(); |
| 706 | 706 | return switch (err) { |
| ... | ... | @@ -709,7 +709,7 @@ fn windowsMakePipe(rd: &windows.HANDLE, wr: &windows.HANDLE, sattr: &const SECUR |
| 709 | 709 | } |
| 710 | 710 | } |
| 711 | 711 | |
| 712 | fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.DWORD) -> %void { | |
| 712 | fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.DWORD) %void { | |
| 713 | 713 | if (windows.SetHandleInformation(h, mask, flags) == 0) { |
| 714 | 714 | const err = windows.GetLastError(); |
| 715 | 715 | return switch (err) { |
| ... | ... | @@ -718,27 +718,27 @@ fn windowsSetHandleInfo(h: windows.HANDLE, mask: windows.DWORD, flags: windows.D |
| 718 | 718 | } |
| 719 | 719 | } |
| 720 | 720 | |
| 721 | fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void { | |
| 721 | fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) %void { | |
| 722 | 722 | var rd_h: windows.HANDLE = undefined; |
| 723 | 723 | var wr_h: windows.HANDLE = undefined; |
| 724 | 724 | try windowsMakePipe(&rd_h, &wr_h, sattr); |
| 725 | %defer windowsDestroyPipe(rd_h, wr_h); | |
| 725 | errdefer windowsDestroyPipe(rd_h, wr_h); | |
| 726 | 726 | try windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0); |
| 727 | 727 | *rd = rd_h; |
| 728 | 728 | *wr = wr_h; |
| 729 | 729 | } |
| 730 | 730 | |
| 731 | fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) -> %void { | |
| 731 | fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const SECURITY_ATTRIBUTES) %void { | |
| 732 | 732 | var rd_h: windows.HANDLE = undefined; |
| 733 | 733 | var wr_h: windows.HANDLE = undefined; |
| 734 | 734 | try windowsMakePipe(&rd_h, &wr_h, sattr); |
| 735 | %defer windowsDestroyPipe(rd_h, wr_h); | |
| 735 | errdefer windowsDestroyPipe(rd_h, wr_h); | |
| 736 | 736 | try windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0); |
| 737 | 737 | *rd = rd_h; |
| 738 | 738 | *wr = wr_h; |
| 739 | 739 | } |
| 740 | 740 | |
| 741 | fn makePipe() -> %[2]i32 { | |
| 741 | fn makePipe() %[2]i32 { | |
| 742 | 742 | var fds: [2]i32 = undefined; |
| 743 | 743 | const err = posix.getErrno(posix.pipe(&fds)); |
| 744 | 744 | if (err > 0) { |
| ... | ... | @@ -750,33 +750,33 @@ fn makePipe() -> %[2]i32 { |
| 750 | 750 | return fds; |
| 751 | 751 | } |
| 752 | 752 | |
| 753 | fn destroyPipe(pipe: &const [2]i32) { | |
| 753 | fn destroyPipe(pipe: &const [2]i32) void { | |
| 754 | 754 | os.close((*pipe)[0]); |
| 755 | 755 | os.close((*pipe)[1]); |
| 756 | 756 | } |
| 757 | 757 | |
| 758 | 758 | // Child of fork calls this to report an error to the fork parent. |
| 759 | 759 | // Then the child exits. |
| 760 | fn forkChildErrReport(fd: i32, err: error) -> noreturn { | |
| 760 | fn forkChildErrReport(fd: i32, err: error) noreturn { | |
| 761 | 761 | _ = writeIntFd(fd, ErrInt(err)); |
| 762 | 762 | posix.exit(1); |
| 763 | 763 | } |
| 764 | 764 | |
| 765 | 765 | const ErrInt = @IntType(false, @sizeOf(error) * 8); |
| 766 | 766 | |
| 767 | fn writeIntFd(fd: i32, value: ErrInt) -> %void { | |
| 767 | fn writeIntFd(fd: i32, value: ErrInt) %void { | |
| 768 | 768 | var bytes: [@sizeOf(ErrInt)]u8 = undefined; |
| 769 | 769 | mem.writeInt(bytes[0..], value, builtin.endian); |
| 770 | 770 | os.posixWrite(fd, bytes[0..]) catch return error.SystemResources; |
| 771 | 771 | } |
| 772 | 772 | |
| 773 | fn readIntFd(fd: i32) -> %ErrInt { | |
| 773 | fn readIntFd(fd: i32) %ErrInt { | |
| 774 | 774 | var bytes: [@sizeOf(ErrInt)]u8 = undefined; |
| 775 | 775 | os.posixRead(fd, bytes[0..]) catch return error.SystemResources; |
| 776 | 776 | return mem.readInt(bytes[0..], ErrInt, builtin.endian); |
| 777 | 777 | } |
| 778 | 778 | |
| 779 | extern fn sigchld_handler(_: i32) { | |
| 779 | extern fn sigchld_handler(_: i32) void { | |
| 780 | 780 | while (true) { |
| 781 | 781 | var status: i32 = undefined; |
| 782 | 782 | const pid_result = posix.waitpid(-1, &status, posix.WNOHANG); |
| ... | ... | @@ -794,7 +794,7 @@ extern fn sigchld_handler(_: i32) { |
| 794 | 794 | } |
| 795 | 795 | } |
| 796 | 796 | |
| 797 | fn handleTerm(pid: i32, status: i32) { | |
| 797 | fn handleTerm(pid: i32, status: i32) void { | |
| 798 | 798 | var it = children_nodes.first; |
| 799 | 799 | while (it) |node| : (it = node.next) { |
| 800 | 800 | if (node.data.pid == pid) { |
| ... | ... | @@ -810,12 +810,12 @@ const sigchld_set = x: { |
| 810 | 810 | break :x signal_set; |
| 811 | 811 | }; |
| 812 | 812 | |
| 813 | fn block_SIGCHLD() { | |
| 813 | fn block_SIGCHLD() void { | |
| 814 | 814 | const err = posix.getErrno(posix.sigprocmask(posix.SIG_BLOCK, &sigchld_set, null)); |
| 815 | 815 | assert(err == 0); |
| 816 | 816 | } |
| 817 | 817 | |
| 818 | fn restore_SIGCHLD() { | |
| 818 | fn restore_SIGCHLD() void { | |
| 819 | 819 | const err = posix.getErrno(posix.sigprocmask(posix.SIG_UNBLOCK, &sigchld_set, null)); |
| 820 | 820 | assert(err == 0); |
| 821 | 821 | } |
| ... | ... | @@ -826,7 +826,7 @@ const sigchld_action = posix.Sigaction { |
| 826 | 826 | .flags = posix.SA_RESTART | posix.SA_NOCLDSTOP, |
| 827 | 827 | }; |
| 828 | 828 | |
| 829 | fn install_SIGCHLD_handler() { | |
| 829 | fn install_SIGCHLD_handler() void { | |
| 830 | 830 | const err = posix.getErrno(posix.sigaction(posix.SIGCHLD, &sigchld_action, null)); |
| 831 | 831 | assert(err == 0); |
| 832 | 832 | } |
std/os/darwin.zig+44-46| ... | ... | @@ -98,67 +98,67 @@ pub const SIGINFO = 29; /// information request |
| 98 | 98 | pub const SIGUSR1 = 30; /// user defined signal 1 |
| 99 | 99 | pub const SIGUSR2 = 31; /// user defined signal 2 |
| 100 | 100 | |
| 101 | fn wstatus(x: i32) -> i32 { return x & 0o177; } | |
| 101 | fn wstatus(x: i32) i32 { return x & 0o177; } | |
| 102 | 102 | const wstopped = 0o177; |
| 103 | pub fn WEXITSTATUS(x: i32) -> i32 { return x >> 8; } | |
| 104 | pub fn WTERMSIG(x: i32) -> i32 { return wstatus(x); } | |
| 105 | pub fn WSTOPSIG(x: i32) -> i32 { return x >> 8; } | |
| 106 | pub fn WIFEXITED(x: i32) -> bool { return wstatus(x) == 0; } | |
| 107 | pub fn WIFSTOPPED(x: i32) -> bool { return wstatus(x) == wstopped and WSTOPSIG(x) != 0x13; } | |
| 108 | pub fn WIFSIGNALED(x: i32) -> bool { return wstatus(x) != wstopped and wstatus(x) != 0; } | |
| 103 | pub fn WEXITSTATUS(x: i32) i32 { return x >> 8; } | |
| 104 | pub fn WTERMSIG(x: i32) i32 { return wstatus(x); } | |
| 105 | pub fn WSTOPSIG(x: i32) i32 { return x >> 8; } | |
| 106 | pub fn WIFEXITED(x: i32) bool { return wstatus(x) == 0; } | |
| 107 | pub fn WIFSTOPPED(x: i32) bool { return wstatus(x) == wstopped and WSTOPSIG(x) != 0x13; } | |
| 108 | pub fn WIFSIGNALED(x: i32) bool { return wstatus(x) != wstopped and wstatus(x) != 0; } | |
| 109 | 109 | |
| 110 | 110 | /// Get the errno from a syscall return value, or 0 for no error. |
| 111 | pub fn getErrno(r: usize) -> usize { | |
| 111 | pub fn getErrno(r: usize) usize { | |
| 112 | 112 | const signed_r = @bitCast(isize, r); |
| 113 | 113 | return if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0; |
| 114 | 114 | } |
| 115 | 115 | |
| 116 | pub fn close(fd: i32) -> usize { | |
| 116 | pub fn close(fd: i32) usize { | |
| 117 | 117 | return errnoWrap(c.close(fd)); |
| 118 | 118 | } |
| 119 | 119 | |
| 120 | pub fn abort() -> noreturn { | |
| 120 | pub fn abort() noreturn { | |
| 121 | 121 | c.abort(); |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | pub fn exit(code: i32) -> noreturn { | |
| 124 | pub fn exit(code: i32) noreturn { | |
| 125 | 125 | c.exit(code); |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | pub fn isatty(fd: i32) -> bool { | |
| 128 | pub fn isatty(fd: i32) bool { | |
| 129 | 129 | return c.isatty(fd) != 0; |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | pub fn fstat(fd: i32, buf: &c.Stat) -> usize { | |
| 132 | pub fn fstat(fd: i32, buf: &c.Stat) usize { | |
| 133 | 133 | return errnoWrap(c.@"fstat$INODE64"(fd, buf)); |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | pub fn lseek(fd: i32, offset: isize, whence: c_int) -> usize { | |
| 136 | pub fn lseek(fd: i32, offset: isize, whence: c_int) usize { | |
| 137 | 137 | return errnoWrap(c.lseek(fd, offset, whence)); |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | pub fn open(path: &const u8, flags: u32, mode: usize) -> usize { | |
| 140 | pub fn open(path: &const u8, flags: u32, mode: usize) usize { | |
| 141 | 141 | return errnoWrap(c.open(path, @bitCast(c_int, flags), mode)); |
| 142 | 142 | } |
| 143 | 143 | |
| 144 | pub fn raise(sig: i32) -> usize { | |
| 144 | pub fn raise(sig: i32) usize { | |
| 145 | 145 | return errnoWrap(c.raise(sig)); |
| 146 | 146 | } |
| 147 | 147 | |
| 148 | pub fn read(fd: i32, buf: &u8, nbyte: usize) -> usize { | |
| 148 | pub fn read(fd: i32, buf: &u8, nbyte: usize) usize { | |
| 149 | 149 | return errnoWrap(c.read(fd, @ptrCast(&c_void, buf), nbyte)); |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | pub fn stat(noalias path: &const u8, noalias buf: &stat) -> usize { | |
| 152 | pub fn stat(noalias path: &const u8, noalias buf: &stat) usize { | |
| 153 | 153 | return errnoWrap(c.stat(path, buf)); |
| 154 | 154 | } |
| 155 | 155 | |
| 156 | pub fn write(fd: i32, buf: &const u8, nbyte: usize) -> usize { | |
| 156 | pub fn write(fd: i32, buf: &const u8, nbyte: usize) usize { | |
| 157 | 157 | return errnoWrap(c.write(fd, @ptrCast(&const c_void, buf), nbyte)); |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | 160 | pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, |
| 161 | offset: isize) -> usize | |
| 161 | offset: isize) usize | |
| 162 | 162 | { |
| 163 | 163 | const ptr_result = c.mmap(@ptrCast(&c_void, address), length, |
| 164 | 164 | @bitCast(c_int, c_uint(prot)), @bitCast(c_int, c_uint(flags)), fd, offset); |
| ... | ... | @@ -166,87 +166,85 @@ pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, |
| 166 | 166 | return errnoWrap(isize_result); |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | pub fn munmap(address: &u8, length: usize) -> usize { | |
| 169 | pub fn munmap(address: &u8, length: usize) usize { | |
| 170 | 170 | return errnoWrap(c.munmap(@ptrCast(&c_void, address), length)); |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | pub fn unlink(path: &const u8) -> usize { | |
| 173 | pub fn unlink(path: &const u8) usize { | |
| 174 | 174 | return errnoWrap(c.unlink(path)); |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | pub fn getcwd(buf: &u8, size: usize) -> usize { | |
| 177 | pub fn getcwd(buf: &u8, size: usize) usize { | |
| 178 | 178 | return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(*c._errno())) else 0; |
| 179 | 179 | } |
| 180 | 180 | |
| 181 | pub fn waitpid(pid: i32, status: &i32, options: u32) -> usize { | |
| 181 | pub fn waitpid(pid: i32, status: &i32, options: u32) usize { | |
| 182 | 182 | comptime assert(i32.bit_count == c_int.bit_count); |
| 183 | 183 | return errnoWrap(c.waitpid(pid, @ptrCast(&c_int, status), @bitCast(c_int, options))); |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | pub fn fork() -> usize { | |
| 186 | pub fn fork() usize { | |
| 187 | 187 | return errnoWrap(c.fork()); |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | pub fn pipe(fds: &[2]i32) -> usize { | |
| 190 | pub fn pipe(fds: &[2]i32) usize { | |
| 191 | 191 | comptime assert(i32.bit_count == c_int.bit_count); |
| 192 | 192 | return errnoWrap(c.pipe(@ptrCast(&c_int, fds))); |
| 193 | 193 | } |
| 194 | 194 | |
| 195 | pub fn mkdir(path: &const u8, mode: u32) -> usize { | |
| 195 | pub fn mkdir(path: &const u8, mode: u32) usize { | |
| 196 | 196 | return errnoWrap(c.mkdir(path, mode)); |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | pub fn symlink(existing: &const u8, new: &const u8) -> usize { | |
| 199 | pub fn symlink(existing: &const u8, new: &const u8) usize { | |
| 200 | 200 | return errnoWrap(c.symlink(existing, new)); |
| 201 | 201 | } |
| 202 | 202 | |
| 203 | pub fn rename(old: &const u8, new: &const u8) -> usize { | |
| 203 | pub fn rename(old: &const u8, new: &const u8) usize { | |
| 204 | 204 | return errnoWrap(c.rename(old, new)); |
| 205 | 205 | } |
| 206 | 206 | |
| 207 | pub fn chdir(path: &const u8) -> usize { | |
| 207 | pub fn chdir(path: &const u8) usize { | |
| 208 | 208 | return errnoWrap(c.chdir(path)); |
| 209 | 209 | } |
| 210 | 210 | |
| 211 | pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) | |
| 212 | -> usize | |
| 213 | { | |
| 211 | pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) usize { | |
| 214 | 212 | return errnoWrap(c.execve(path, argv, envp)); |
| 215 | 213 | } |
| 216 | 214 | |
| 217 | pub fn dup2(old: i32, new: i32) -> usize { | |
| 215 | pub fn dup2(old: i32, new: i32) usize { | |
| 218 | 216 | return errnoWrap(c.dup2(old, new)); |
| 219 | 217 | } |
| 220 | 218 | |
| 221 | pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -> usize { | |
| 219 | pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) usize { | |
| 222 | 220 | return errnoWrap(c.readlink(path, buf_ptr, buf_len)); |
| 223 | 221 | } |
| 224 | 222 | |
| 225 | pub fn nanosleep(req: &const timespec, rem: ?&timespec) -> usize { | |
| 223 | pub fn nanosleep(req: &const timespec, rem: ?&timespec) usize { | |
| 226 | 224 | return errnoWrap(c.nanosleep(req, rem)); |
| 227 | 225 | } |
| 228 | 226 | |
| 229 | pub fn realpath(noalias filename: &const u8, noalias resolved_name: &u8) -> usize { | |
| 227 | pub fn realpath(noalias filename: &const u8, noalias resolved_name: &u8) usize { | |
| 230 | 228 | return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(*c._errno())) else 0; |
| 231 | 229 | } |
| 232 | 230 | |
| 233 | pub fn setreuid(ruid: u32, euid: u32) -> usize { | |
| 231 | pub fn setreuid(ruid: u32, euid: u32) usize { | |
| 234 | 232 | return errnoWrap(c.setreuid(ruid, euid)); |
| 235 | 233 | } |
| 236 | 234 | |
| 237 | pub fn setregid(rgid: u32, egid: u32) -> usize { | |
| 235 | pub fn setregid(rgid: u32, egid: u32) usize { | |
| 238 | 236 | return errnoWrap(c.setregid(rgid, egid)); |
| 239 | 237 | } |
| 240 | 238 | |
| 241 | pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) -> usize { | |
| 239 | pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) usize { | |
| 242 | 240 | return errnoWrap(c.sigprocmask(@bitCast(c_int, flags), set, oldset)); |
| 243 | 241 | } |
| 244 | 242 | |
| 245 | pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigaction) -> usize { | |
| 243 | pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigaction) usize { | |
| 246 | 244 | assert(sig != SIGKILL); |
| 247 | 245 | assert(sig != SIGSTOP); |
| 248 | 246 | var cact = c.Sigaction { |
| 249 | .handler = @ptrCast(extern fn(c_int), act.handler), | |
| 247 | .handler = @ptrCast(extern fn(c_int)void, act.handler), | |
| 250 | 248 | .sa_flags = @bitCast(c_int, act.flags), |
| 251 | 249 | .sa_mask = act.mask, |
| 252 | 250 | }; |
| ... | ... | @@ -257,7 +255,7 @@ pub fn sigaction(sig: u5, noalias act: &const Sigaction, noalias oact: ?&Sigacti |
| 257 | 255 | } |
| 258 | 256 | if (oact) |old| { |
| 259 | 257 | *old = Sigaction { |
| 260 | .handler = @ptrCast(extern fn(i32), coact.handler), | |
| 258 | .handler = @ptrCast(extern fn(i32)void, coact.handler), | |
| 261 | 259 | .flags = @bitCast(u32, coact.sa_flags), |
| 262 | 260 | .mask = coact.sa_mask, |
| 263 | 261 | }; |
| ... | ... | @@ -273,18 +271,18 @@ pub const Stat = c.Stat; |
| 273 | 271 | |
| 274 | 272 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 275 | 273 | pub const Sigaction = struct { |
| 276 | handler: extern fn(i32), | |
| 274 | handler: extern fn(i32)void, | |
| 277 | 275 | mask: sigset_t, |
| 278 | 276 | flags: u32, |
| 279 | 277 | }; |
| 280 | 278 | |
| 281 | pub fn sigaddset(set: &sigset_t, signo: u5) { | |
| 279 | pub fn sigaddset(set: &sigset_t, signo: u5) void { | |
| 282 | 280 | *set |= u32(1) << (signo - 1); |
| 283 | 281 | } |
| 284 | 282 | |
| 285 | 283 | /// Takes the return value from a syscall and formats it back in the way |
| 286 | 284 | /// that the kernel represents it to libc. Errno was a mistake, let's make |
| 287 | 285 | /// it go away forever. |
| 288 | fn errnoWrap(value: isize) -> usize { | |
| 286 | fn errnoWrap(value: isize) usize { | |
| 289 | 287 | return @bitCast(usize, if (value == -1) -isize(*c._errno()) else value); |
| 290 | 288 | } |
std/os/get_user_id.zig+2-2| ... | ... | @@ -9,7 +9,7 @@ pub const UserInfo = struct { |
| 9 | 9 | }; |
| 10 | 10 | |
| 11 | 11 | /// POSIX function which gets a uid from username. |
| 12 | pub fn getUserInfo(name: []const u8) -> %UserInfo { | |
| 12 | pub fn getUserInfo(name: []const u8) %UserInfo { | |
| 13 | 13 | return switch (builtin.os) { |
| 14 | 14 | Os.linux, Os.macosx, Os.ios => posixGetUserInfo(name), |
| 15 | 15 | else => @compileError("Unsupported OS"), |
| ... | ... | @@ -30,7 +30,7 @@ error CorruptPasswordFile; |
| 30 | 30 | // TODO this reads /etc/passwd. But sometimes the user/id mapping is in something else |
| 31 | 31 | // like NIS, AD, etc. See `man nss` or look at an strace for `id myuser`. |
| 32 | 32 | |
| 33 | pub fn posixGetUserInfo(name: []const u8) -> %UserInfo { | |
| 33 | pub fn posixGetUserInfo(name: []const u8) %UserInfo { | |
| 34 | 34 | var in_stream = try io.InStream.open("/etc/passwd", null); |
| 35 | 35 | defer in_stream.close(); |
| 36 | 36 |
std/os/index.zig+82-80| ... | ... | @@ -75,7 +75,7 @@ error WouldBlock; |
| 75 | 75 | /// Fills `buf` with random bytes. If linking against libc, this calls the |
| 76 | 76 | /// appropriate OS-specific library call. Otherwise it uses the zig standard |
| 77 | 77 | /// library implementation. |
| 78 | pub fn getRandomBytes(buf: []u8) -> %void { | |
| 78 | pub fn getRandomBytes(buf: []u8) %void { | |
| 79 | 79 | switch (builtin.os) { |
| 80 | 80 | Os.linux => while (true) { |
| 81 | 81 | // TODO check libc version and potentially call c.getrandom. |
| ... | ... | @@ -127,7 +127,8 @@ test "os.getRandomBytes" { |
| 127 | 127 | /// Raises a signal in the current kernel thread, ending its execution. |
| 128 | 128 | /// If linking against libc, this calls the abort() libc function. Otherwise |
| 129 | 129 | /// it uses the zig standard library implementation. |
| 130 | pub coldcc fn abort() -> noreturn { | |
| 130 | pub fn abort() noreturn { | |
| 131 | @setCold(true); | |
| 131 | 132 | if (builtin.link_libc) { |
| 132 | 133 | c.abort(); |
| 133 | 134 | } |
| ... | ... | @@ -148,7 +149,8 @@ pub coldcc fn abort() -> noreturn { |
| 148 | 149 | } |
| 149 | 150 | |
| 150 | 151 | /// Exits the program cleanly with the specified status code. |
| 151 | pub coldcc fn exit(status: u8) -> noreturn { | |
| 152 | pub fn exit(status: u8) noreturn { | |
| 153 | @setCold(true); | |
| 152 | 154 | if (builtin.link_libc) { |
| 153 | 155 | c.exit(status); |
| 154 | 156 | } |
| ... | ... | @@ -164,7 +166,7 @@ pub coldcc fn exit(status: u8) -> noreturn { |
| 164 | 166 | } |
| 165 | 167 | |
| 166 | 168 | /// Closes the file handle. Keeps trying if it gets interrupted by a signal. |
| 167 | pub fn close(handle: FileHandle) { | |
| 169 | pub fn close(handle: FileHandle) void { | |
| 168 | 170 | if (is_windows) { |
| 169 | 171 | windows_util.windowsClose(handle); |
| 170 | 172 | } else { |
| ... | ... | @@ -180,7 +182,7 @@ pub fn close(handle: FileHandle) { |
| 180 | 182 | } |
| 181 | 183 | |
| 182 | 184 | /// Calls POSIX read, and keeps trying if it gets interrupted. |
| 183 | pub fn posixRead(fd: i32, buf: []u8) -> %void { | |
| 185 | pub fn posixRead(fd: i32, buf: []u8) %void { | |
| 184 | 186 | var index: usize = 0; |
| 185 | 187 | while (index < buf.len) { |
| 186 | 188 | const amt_written = posix.read(fd, &buf[index], buf.len - index); |
| ... | ... | @@ -211,7 +213,7 @@ error NoSpaceLeft; |
| 211 | 213 | error BrokenPipe; |
| 212 | 214 | |
| 213 | 215 | /// Calls POSIX write, and keeps trying if it gets interrupted. |
| 214 | pub fn posixWrite(fd: i32, bytes: []const u8) -> %void { | |
| 216 | pub fn posixWrite(fd: i32, bytes: []const u8) %void { | |
| 215 | 217 | while (true) { |
| 216 | 218 | const write_ret = posix.write(fd, bytes.ptr, bytes.len); |
| 217 | 219 | const write_err = posix.getErrno(write_ret); |
| ... | ... | @@ -241,7 +243,7 @@ pub fn posixWrite(fd: i32, bytes: []const u8) -> %void { |
| 241 | 243 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. |
| 242 | 244 | /// Calls POSIX open, keeps trying if it gets interrupted, and translates |
| 243 | 245 | /// the return value into zig errors. |
| 244 | pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Allocator) -> %i32 { | |
| 246 | pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Allocator) %i32 { | |
| 245 | 247 | var stack_buf: [max_noalloc_path_len]u8 = undefined; |
| 246 | 248 | var path0: []u8 = undefined; |
| 247 | 249 | var need_free = false; |
| ... | ... | @@ -290,7 +292,7 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al |
| 290 | 292 | } |
| 291 | 293 | } |
| 292 | 294 | |
| 293 | pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void { | |
| 295 | pub fn posixDup2(old_fd: i32, new_fd: i32) %void { | |
| 294 | 296 | while (true) { |
| 295 | 297 | const err = posix.getErrno(posix.dup2(old_fd, new_fd)); |
| 296 | 298 | if (err > 0) { |
| ... | ... | @@ -305,11 +307,11 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) -> %void { |
| 305 | 307 | } |
| 306 | 308 | } |
| 307 | 309 | |
| 308 | pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap) -> %[]?&u8 { | |
| 310 | pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap) %[]?&u8 { | |
| 309 | 311 | const envp_count = env_map.count(); |
| 310 | 312 | const envp_buf = try allocator.alloc(?&u8, envp_count + 1); |
| 311 | 313 | mem.set(?&u8, envp_buf, null); |
| 312 | %defer freeNullDelimitedEnvMap(allocator, envp_buf); | |
| 314 | errdefer freeNullDelimitedEnvMap(allocator, envp_buf); | |
| 313 | 315 | { |
| 314 | 316 | var it = env_map.iterator(); |
| 315 | 317 | var i: usize = 0; |
| ... | ... | @@ -328,7 +330,7 @@ pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap) |
| 328 | 330 | return envp_buf; |
| 329 | 331 | } |
| 330 | 332 | |
| 331 | pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) { | |
| 333 | pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void { | |
| 332 | 334 | for (envp_buf) |env| { |
| 333 | 335 | const env_buf = if (env) |ptr| ptr[0 .. cstr.len(ptr) + 1] else break; |
| 334 | 336 | allocator.free(env_buf); |
| ... | ... | @@ -342,7 +344,7 @@ pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) { |
| 342 | 344 | /// `argv[0]` is the executable path. |
| 343 | 345 | /// This function also uses the PATH environment variable to get the full path to the executable. |
| 344 | 346 | pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, |
| 345 | allocator: &Allocator) -> %void | |
| 347 | allocator: &Allocator) %void | |
| 346 | 348 | { |
| 347 | 349 | const argv_buf = try allocator.alloc(?&u8, argv.len + 1); |
| 348 | 350 | mem.set(?&u8, argv_buf, null); |
| ... | ... | @@ -398,7 +400,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, |
| 398 | 400 | return posixExecveErrnoToErr(err); |
| 399 | 401 | } |
| 400 | 402 | |
| 401 | fn posixExecveErrnoToErr(err: usize) -> error { | |
| 403 | fn posixExecveErrnoToErr(err: usize) error { | |
| 402 | 404 | assert(err > 0); |
| 403 | 405 | return switch (err) { |
| 404 | 406 | posix.EFAULT => unreachable, |
| ... | ... | @@ -417,9 +419,9 @@ fn posixExecveErrnoToErr(err: usize) -> error { |
| 417 | 419 | pub var posix_environ_raw: []&u8 = undefined; |
| 418 | 420 | |
| 419 | 421 | /// Caller must free result when done. |
| 420 | pub fn getEnvMap(allocator: &Allocator) -> %BufMap { | |
| 422 | pub fn getEnvMap(allocator: &Allocator) %BufMap { | |
| 421 | 423 | var result = BufMap.init(allocator); |
| 422 | %defer result.deinit(); | |
| 424 | errdefer result.deinit(); | |
| 423 | 425 | |
| 424 | 426 | if (is_windows) { |
| 425 | 427 | const ptr = windows.GetEnvironmentStringsA() ?? return error.OutOfMemory; |
| ... | ... | @@ -461,7 +463,7 @@ pub fn getEnvMap(allocator: &Allocator) -> %BufMap { |
| 461 | 463 | } |
| 462 | 464 | } |
| 463 | 465 | |
| 464 | pub fn getEnvPosix(key: []const u8) -> ?[]const u8 { | |
| 466 | pub fn getEnvPosix(key: []const u8) ?[]const u8 { | |
| 465 | 467 | for (posix_environ_raw) |ptr| { |
| 466 | 468 | var line_i: usize = 0; |
| 467 | 469 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} |
| ... | ... | @@ -481,13 +483,13 @@ pub fn getEnvPosix(key: []const u8) -> ?[]const u8 { |
| 481 | 483 | error EnvironmentVariableNotFound; |
| 482 | 484 | |
| 483 | 485 | /// Caller must free returned memory. |
| 484 | pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) -> %[]u8 { | |
| 486 | pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) %[]u8 { | |
| 485 | 487 | if (is_windows) { |
| 486 | 488 | const key_with_null = try cstr.addNullByte(allocator, key); |
| 487 | 489 | defer allocator.free(key_with_null); |
| 488 | 490 | |
| 489 | 491 | var buf = try allocator.alloc(u8, 256); |
| 490 | %defer allocator.free(buf); | |
| 492 | errdefer allocator.free(buf); | |
| 491 | 493 | |
| 492 | 494 | while (true) { |
| 493 | 495 | const windows_buf_len = try math.cast(windows.DWORD, buf.len); |
| ... | ... | @@ -515,11 +517,11 @@ pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) -> %[]u8 { |
| 515 | 517 | } |
| 516 | 518 | |
| 517 | 519 | /// Caller must free the returned memory. |
| 518 | pub fn getCwd(allocator: &Allocator) -> %[]u8 { | |
| 520 | pub fn getCwd(allocator: &Allocator) %[]u8 { | |
| 519 | 521 | switch (builtin.os) { |
| 520 | 522 | Os.windows => { |
| 521 | 523 | var buf = try allocator.alloc(u8, 256); |
| 522 | %defer allocator.free(buf); | |
| 524 | errdefer allocator.free(buf); | |
| 523 | 525 | |
| 524 | 526 | while (true) { |
| 525 | 527 | const result = windows.GetCurrentDirectoryA(windows.WORD(buf.len), buf.ptr); |
| ... | ... | @@ -541,7 +543,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { |
| 541 | 543 | }, |
| 542 | 544 | else => { |
| 543 | 545 | var buf = try allocator.alloc(u8, 1024); |
| 544 | %defer allocator.free(buf); | |
| 546 | errdefer allocator.free(buf); | |
| 545 | 547 | while (true) { |
| 546 | 548 | const err = posix.getErrno(posix.getcwd(buf.ptr, buf.len)); |
| 547 | 549 | if (err == posix.ERANGE) { |
| ... | ... | @@ -562,7 +564,7 @@ test "os.getCwd" { |
| 562 | 564 | _ = getCwd(debug.global_allocator); |
| 563 | 565 | } |
| 564 | 566 | |
| 565 | pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) -> %void { | |
| 567 | pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void { | |
| 566 | 568 | if (is_windows) { |
| 567 | 569 | return symLinkWindows(allocator, existing_path, new_path); |
| 568 | 570 | } else { |
| ... | ... | @@ -570,7 +572,7 @@ pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []con |
| 570 | 572 | } |
| 571 | 573 | } |
| 572 | 574 | |
| 573 | pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) -> %void { | |
| 575 | pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void { | |
| 574 | 576 | const existing_with_null = try cstr.addNullByte(allocator, existing_path); |
| 575 | 577 | defer allocator.free(existing_with_null); |
| 576 | 578 | const new_with_null = try cstr.addNullByte(allocator, new_path); |
| ... | ... | @@ -584,7 +586,7 @@ pub fn symLinkWindows(allocator: &Allocator, existing_path: []const u8, new_path |
| 584 | 586 | } |
| 585 | 587 | } |
| 586 | 588 | |
| 587 | pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) -> %void { | |
| 589 | pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void { | |
| 588 | 590 | const full_buf = try allocator.alloc(u8, existing_path.len + new_path.len + 2); |
| 589 | 591 | defer allocator.free(full_buf); |
| 590 | 592 | |
| ... | ... | @@ -621,7 +623,7 @@ const b64_fs_encoder = base64.Base64Encoder.init( |
| 621 | 623 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", |
| 622 | 624 | base64.standard_pad_char); |
| 623 | 625 | |
| 624 | pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) -> %void { | |
| 626 | pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) %void { | |
| 625 | 627 | if (symLink(allocator, existing_path, new_path)) { |
| 626 | 628 | return; |
| 627 | 629 | } else |err| { |
| ... | ... | @@ -650,7 +652,7 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: |
| 650 | 652 | |
| 651 | 653 | } |
| 652 | 654 | |
| 653 | pub fn deleteFile(allocator: &Allocator, file_path: []const u8) -> %void { | |
| 655 | pub fn deleteFile(allocator: &Allocator, file_path: []const u8) %void { | |
| 654 | 656 | if (builtin.os == Os.windows) { |
| 655 | 657 | return deleteFileWindows(allocator, file_path); |
| 656 | 658 | } else { |
| ... | ... | @@ -661,7 +663,7 @@ pub fn deleteFile(allocator: &Allocator, file_path: []const u8) -> %void { |
| 661 | 663 | error FileNotFound; |
| 662 | 664 | error AccessDenied; |
| 663 | 665 | |
| 664 | pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) -> %void { | |
| 666 | pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) %void { | |
| 665 | 667 | const buf = try allocator.alloc(u8, file_path.len + 1); |
| 666 | 668 | defer allocator.free(buf); |
| 667 | 669 | |
| ... | ... | @@ -679,7 +681,7 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) -> %void |
| 679 | 681 | } |
| 680 | 682 | } |
| 681 | 683 | |
| 682 | pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) -> %void { | |
| 684 | pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) %void { | |
| 683 | 685 | const buf = try allocator.alloc(u8, file_path.len + 1); |
| 684 | 686 | defer allocator.free(buf); |
| 685 | 687 | |
| ... | ... | @@ -706,13 +708,13 @@ pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) -> %void { |
| 706 | 708 | } |
| 707 | 709 | |
| 708 | 710 | /// Calls ::copyFileMode with 0o666 for the mode. |
| 709 | pub fn copyFile(allocator: &Allocator, source_path: []const u8, dest_path: []const u8) -> %void { | |
| 711 | pub fn copyFile(allocator: &Allocator, source_path: []const u8, dest_path: []const u8) %void { | |
| 710 | 712 | return copyFileMode(allocator, source_path, dest_path, 0o666); |
| 711 | 713 | } |
| 712 | 714 | |
| 713 | 715 | // TODO instead of accepting a mode argument, use the mode from fstat'ing the source path once open |
| 714 | 716 | /// Guaranteed to be atomic. |
| 715 | pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: []const u8, mode: usize) -> %void { | |
| 717 | pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: []const u8, mode: usize) %void { | |
| 716 | 718 | var rand_buf: [12]u8 = undefined; |
| 717 | 719 | const tmp_path = try allocator.alloc(u8, dest_path.len + base64.Base64Encoder.calcSize(rand_buf.len)); |
| 718 | 720 | defer allocator.free(tmp_path); |
| ... | ... | @@ -722,7 +724,7 @@ pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: [ |
| 722 | 724 | |
| 723 | 725 | var out_file = try io.File.openWriteMode(tmp_path, mode, allocator); |
| 724 | 726 | defer out_file.close(); |
| 725 | %defer _ = deleteFile(allocator, tmp_path); | |
| 727 | errdefer _ = deleteFile(allocator, tmp_path); | |
| 726 | 728 | |
| 727 | 729 | var in_file = try io.File.openRead(source_path, allocator); |
| 728 | 730 | defer in_file.close(); |
| ... | ... | @@ -736,7 +738,7 @@ pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: [ |
| 736 | 738 | } |
| 737 | 739 | } |
| 738 | 740 | |
| 739 | pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) -> %void { | |
| 741 | pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) %void { | |
| 740 | 742 | const full_buf = try allocator.alloc(u8, old_path.len + new_path.len + 2); |
| 741 | 743 | defer allocator.free(full_buf); |
| 742 | 744 | |
| ... | ... | @@ -781,7 +783,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) |
| 781 | 783 | } |
| 782 | 784 | } |
| 783 | 785 | |
| 784 | pub fn makeDir(allocator: &Allocator, dir_path: []const u8) -> %void { | |
| 786 | pub fn makeDir(allocator: &Allocator, dir_path: []const u8) %void { | |
| 785 | 787 | if (is_windows) { |
| 786 | 788 | return makeDirWindows(allocator, dir_path); |
| 787 | 789 | } else { |
| ... | ... | @@ -789,7 +791,7 @@ pub fn makeDir(allocator: &Allocator, dir_path: []const u8) -> %void { |
| 789 | 791 | } |
| 790 | 792 | } |
| 791 | 793 | |
| 792 | pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) -> %void { | |
| 794 | pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) %void { | |
| 793 | 795 | const path_buf = try cstr.addNullByte(allocator, dir_path); |
| 794 | 796 | defer allocator.free(path_buf); |
| 795 | 797 | |
| ... | ... | @@ -803,7 +805,7 @@ pub fn makeDirWindows(allocator: &Allocator, dir_path: []const u8) -> %void { |
| 803 | 805 | } |
| 804 | 806 | } |
| 805 | 807 | |
| 806 | pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) -> %void { | |
| 808 | pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) %void { | |
| 807 | 809 | const path_buf = try cstr.addNullByte(allocator, dir_path); |
| 808 | 810 | defer allocator.free(path_buf); |
| 809 | 811 | |
| ... | ... | @@ -829,7 +831,7 @@ pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) -> %void { |
| 829 | 831 | |
| 830 | 832 | /// Calls makeDir recursively to make an entire path. Returns success if the path |
| 831 | 833 | /// already exists and is a directory. |
| 832 | pub fn makePath(allocator: &Allocator, full_path: []const u8) -> %void { | |
| 834 | pub fn makePath(allocator: &Allocator, full_path: []const u8) %void { | |
| 833 | 835 | const resolved_path = try path.resolve(allocator, full_path); |
| 834 | 836 | defer allocator.free(resolved_path); |
| 835 | 837 | |
| ... | ... | @@ -867,7 +869,7 @@ pub fn makePath(allocator: &Allocator, full_path: []const u8) -> %void { |
| 867 | 869 | |
| 868 | 870 | /// Returns ::error.DirNotEmpty if the directory is not empty. |
| 869 | 871 | /// To delete a directory recursively, see ::deleteTree |
| 870 | pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) -> %void { | |
| 872 | pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) %void { | |
| 871 | 873 | const path_buf = try allocator.alloc(u8, dir_path.len + 1); |
| 872 | 874 | defer allocator.free(path_buf); |
| 873 | 875 | |
| ... | ... | @@ -896,7 +898,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) -> %void { |
| 896 | 898 | /// removes it. If it cannot be removed because it is a non-empty directory, |
| 897 | 899 | /// this function recursively removes its entries and then tries again. |
| 898 | 900 | // TODO non-recursive implementation |
| 899 | pub fn deleteTree(allocator: &Allocator, full_path: []const u8) -> %void { | |
| 901 | pub fn deleteTree(allocator: &Allocator, full_path: []const u8) %void { | |
| 900 | 902 | start_over: while (true) { |
| 901 | 903 | // First, try deleting the item as a file. This way we don't follow sym links. |
| 902 | 904 | if (deleteFile(allocator, full_path)) { |
| ... | ... | @@ -965,7 +967,7 @@ pub const Dir = struct { |
| 965 | 967 | }; |
| 966 | 968 | }; |
| 967 | 969 | |
| 968 | pub fn open(allocator: &Allocator, dir_path: []const u8) -> %Dir { | |
| 970 | pub fn open(allocator: &Allocator, dir_path: []const u8) %Dir { | |
| 969 | 971 | const fd = try posixOpen(dir_path, posix.O_RDONLY|posix.O_DIRECTORY|posix.O_CLOEXEC, 0, allocator); |
| 970 | 972 | return Dir { |
| 971 | 973 | .allocator = allocator, |
| ... | ... | @@ -976,14 +978,14 @@ pub const Dir = struct { |
| 976 | 978 | }; |
| 977 | 979 | } |
| 978 | 980 | |
| 979 | pub fn close(self: &Dir) { | |
| 981 | pub fn close(self: &Dir) void { | |
| 980 | 982 | self.allocator.free(self.buf); |
| 981 | 983 | os.close(self.fd); |
| 982 | 984 | } |
| 983 | 985 | |
| 984 | 986 | /// Memory such as file names referenced in this returned entry becomes invalid |
| 985 | 987 | /// with subsequent calls to next, as well as when this ::Dir is deinitialized. |
| 986 | pub fn next(self: &Dir) -> %?Entry { | |
| 988 | pub fn next(self: &Dir) %?Entry { | |
| 987 | 989 | start_over: while (true) { |
| 988 | 990 | if (self.index >= self.end_index) { |
| 989 | 991 | if (self.buf.len == 0) { |
| ... | ... | @@ -1040,7 +1042,7 @@ pub const Dir = struct { |
| 1040 | 1042 | } |
| 1041 | 1043 | }; |
| 1042 | 1044 | |
| 1043 | pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) -> %void { | |
| 1045 | pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) %void { | |
| 1044 | 1046 | const path_buf = try allocator.alloc(u8, dir_path.len + 1); |
| 1045 | 1047 | defer allocator.free(path_buf); |
| 1046 | 1048 | |
| ... | ... | @@ -1064,7 +1066,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) -> %void { |
| 1064 | 1066 | } |
| 1065 | 1067 | |
| 1066 | 1068 | /// Read value of a symbolic link. |
| 1067 | pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 { | |
| 1069 | pub fn readLink(allocator: &Allocator, pathname: []const u8) %[]u8 { | |
| 1068 | 1070 | const path_buf = try allocator.alloc(u8, pathname.len + 1); |
| 1069 | 1071 | defer allocator.free(path_buf); |
| 1070 | 1072 | |
| ... | ... | @@ -1072,7 +1074,7 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 { |
| 1072 | 1074 | path_buf[pathname.len] = 0; |
| 1073 | 1075 | |
| 1074 | 1076 | var result_buf = try allocator.alloc(u8, 1024); |
| 1075 | %defer allocator.free(result_buf); | |
| 1077 | errdefer allocator.free(result_buf); | |
| 1076 | 1078 | while (true) { |
| 1077 | 1079 | const ret_val = posix.readlink(path_buf.ptr, result_buf.ptr, result_buf.len); |
| 1078 | 1080 | const err = posix.getErrno(ret_val); |
| ... | ... | @@ -1097,7 +1099,7 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 { |
| 1097 | 1099 | } |
| 1098 | 1100 | } |
| 1099 | 1101 | |
| 1100 | pub fn sleep(seconds: usize, nanoseconds: usize) { | |
| 1102 | pub fn sleep(seconds: usize, nanoseconds: usize) void { | |
| 1101 | 1103 | switch(builtin.os) { |
| 1102 | 1104 | Os.linux, Os.macosx, Os.ios => { |
| 1103 | 1105 | posixSleep(u63(seconds), u63(nanoseconds)); |
| ... | ... | @@ -1111,7 +1113,7 @@ pub fn sleep(seconds: usize, nanoseconds: usize) { |
| 1111 | 1113 | } |
| 1112 | 1114 | |
| 1113 | 1115 | const u63 = @IntType(false, 63); |
| 1114 | pub fn posixSleep(seconds: u63, nanoseconds: u63) { | |
| 1116 | pub fn posixSleep(seconds: u63, nanoseconds: u63) void { | |
| 1115 | 1117 | var req = posix.timespec { |
| 1116 | 1118 | .tv_sec = seconds, |
| 1117 | 1119 | .tv_nsec = nanoseconds, |
| ... | ... | @@ -1145,7 +1147,7 @@ error ResourceLimitReached; |
| 1145 | 1147 | error InvalidUserId; |
| 1146 | 1148 | error PermissionDenied; |
| 1147 | 1149 | |
| 1148 | pub fn posix_setuid(uid: u32) -> %void { | |
| 1150 | pub fn posix_setuid(uid: u32) %void { | |
| 1149 | 1151 | const err = posix.getErrno(posix.setuid(uid)); |
| 1150 | 1152 | if (err == 0) return; |
| 1151 | 1153 | return switch (err) { |
| ... | ... | @@ -1156,7 +1158,7 @@ pub fn posix_setuid(uid: u32) -> %void { |
| 1156 | 1158 | }; |
| 1157 | 1159 | } |
| 1158 | 1160 | |
| 1159 | pub fn posix_setreuid(ruid: u32, euid: u32) -> %void { | |
| 1161 | pub fn posix_setreuid(ruid: u32, euid: u32) %void { | |
| 1160 | 1162 | const err = posix.getErrno(posix.setreuid(ruid, euid)); |
| 1161 | 1163 | if (err == 0) return; |
| 1162 | 1164 | return switch (err) { |
| ... | ... | @@ -1167,7 +1169,7 @@ pub fn posix_setreuid(ruid: u32, euid: u32) -> %void { |
| 1167 | 1169 | }; |
| 1168 | 1170 | } |
| 1169 | 1171 | |
| 1170 | pub fn posix_setgid(gid: u32) -> %void { | |
| 1172 | pub fn posix_setgid(gid: u32) %void { | |
| 1171 | 1173 | const err = posix.getErrno(posix.setgid(gid)); |
| 1172 | 1174 | if (err == 0) return; |
| 1173 | 1175 | return switch (err) { |
| ... | ... | @@ -1178,7 +1180,7 @@ pub fn posix_setgid(gid: u32) -> %void { |
| 1178 | 1180 | }; |
| 1179 | 1181 | } |
| 1180 | 1182 | |
| 1181 | pub fn posix_setregid(rgid: u32, egid: u32) -> %void { | |
| 1183 | pub fn posix_setregid(rgid: u32, egid: u32) %void { | |
| 1182 | 1184 | const err = posix.getErrno(posix.setregid(rgid, egid)); |
| 1183 | 1185 | if (err == 0) return; |
| 1184 | 1186 | return switch (err) { |
| ... | ... | @@ -1190,7 +1192,7 @@ pub fn posix_setregid(rgid: u32, egid: u32) -> %void { |
| 1190 | 1192 | } |
| 1191 | 1193 | |
| 1192 | 1194 | error NoStdHandles; |
| 1193 | pub fn windowsGetStdHandle(handle_id: windows.DWORD) -> %windows.HANDLE { | |
| 1195 | pub fn windowsGetStdHandle(handle_id: windows.DWORD) %windows.HANDLE { | |
| 1194 | 1196 | if (windows.GetStdHandle(handle_id)) |handle| { |
| 1195 | 1197 | if (handle == windows.INVALID_HANDLE_VALUE) { |
| 1196 | 1198 | const err = windows.GetLastError(); |
| ... | ... | @@ -1208,14 +1210,14 @@ pub const ArgIteratorPosix = struct { |
| 1208 | 1210 | index: usize, |
| 1209 | 1211 | count: usize, |
| 1210 | 1212 | |
| 1211 | pub fn init() -> ArgIteratorPosix { | |
| 1213 | pub fn init() ArgIteratorPosix { | |
| 1212 | 1214 | return ArgIteratorPosix { |
| 1213 | 1215 | .index = 0, |
| 1214 | 1216 | .count = raw.len, |
| 1215 | 1217 | }; |
| 1216 | 1218 | } |
| 1217 | 1219 | |
| 1218 | pub fn next(self: &ArgIteratorPosix) -> ?[]const u8 { | |
| 1220 | pub fn next(self: &ArgIteratorPosix) ?[]const u8 { | |
| 1219 | 1221 | if (self.index == self.count) |
| 1220 | 1222 | return null; |
| 1221 | 1223 | |
| ... | ... | @@ -1224,7 +1226,7 @@ pub const ArgIteratorPosix = struct { |
| 1224 | 1226 | return cstr.toSlice(s); |
| 1225 | 1227 | } |
| 1226 | 1228 | |
| 1227 | pub fn skip(self: &ArgIteratorPosix) -> bool { | |
| 1229 | pub fn skip(self: &ArgIteratorPosix) bool { | |
| 1228 | 1230 | if (self.index == self.count) |
| 1229 | 1231 | return false; |
| 1230 | 1232 | |
| ... | ... | @@ -1244,11 +1246,11 @@ pub const ArgIteratorWindows = struct { |
| 1244 | 1246 | quote_count: usize, |
| 1245 | 1247 | seen_quote_count: usize, |
| 1246 | 1248 | |
| 1247 | pub fn init() -> ArgIteratorWindows { | |
| 1249 | pub fn init() ArgIteratorWindows { | |
| 1248 | 1250 | return initWithCmdLine(windows.GetCommandLineA()); |
| 1249 | 1251 | } |
| 1250 | 1252 | |
| 1251 | pub fn initWithCmdLine(cmd_line: &const u8) -> ArgIteratorWindows { | |
| 1253 | pub fn initWithCmdLine(cmd_line: &const u8) ArgIteratorWindows { | |
| 1252 | 1254 | return ArgIteratorWindows { |
| 1253 | 1255 | .index = 0, |
| 1254 | 1256 | .cmd_line = cmd_line, |
| ... | ... | @@ -1259,7 +1261,7 @@ pub const ArgIteratorWindows = struct { |
| 1259 | 1261 | } |
| 1260 | 1262 | |
| 1261 | 1263 | /// You must free the returned memory when done. |
| 1262 | pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) -> ?%[]u8 { | |
| 1264 | pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?%[]u8 { | |
| 1263 | 1265 | // march forward over whitespace |
| 1264 | 1266 | while (true) : (self.index += 1) { |
| 1265 | 1267 | const byte = self.cmd_line[self.index]; |
| ... | ... | @@ -1273,7 +1275,7 @@ pub const ArgIteratorWindows = struct { |
| 1273 | 1275 | return self.internalNext(allocator); |
| 1274 | 1276 | } |
| 1275 | 1277 | |
| 1276 | pub fn skip(self: &ArgIteratorWindows) -> bool { | |
| 1278 | pub fn skip(self: &ArgIteratorWindows) bool { | |
| 1277 | 1279 | // march forward over whitespace |
| 1278 | 1280 | while (true) : (self.index += 1) { |
| 1279 | 1281 | const byte = self.cmd_line[self.index]; |
| ... | ... | @@ -1312,7 +1314,7 @@ pub const ArgIteratorWindows = struct { |
| 1312 | 1314 | } |
| 1313 | 1315 | } |
| 1314 | 1316 | |
| 1315 | fn internalNext(self: &ArgIteratorWindows, allocator: &Allocator) -> %[]u8 { | |
| 1317 | fn internalNext(self: &ArgIteratorWindows, allocator: &Allocator) %[]u8 { | |
| 1316 | 1318 | var buf = try Buffer.initSize(allocator, 0); |
| 1317 | 1319 | defer buf.deinit(); |
| 1318 | 1320 | |
| ... | ... | @@ -1356,14 +1358,14 @@ pub const ArgIteratorWindows = struct { |
| 1356 | 1358 | } |
| 1357 | 1359 | } |
| 1358 | 1360 | |
| 1359 | fn emitBackslashes(self: &ArgIteratorWindows, buf: &Buffer, emit_count: usize) -> %void { | |
| 1361 | fn emitBackslashes(self: &ArgIteratorWindows, buf: &Buffer, emit_count: usize) %void { | |
| 1360 | 1362 | var i: usize = 0; |
| 1361 | 1363 | while (i < emit_count) : (i += 1) { |
| 1362 | 1364 | try buf.appendByte('\\'); |
| 1363 | 1365 | } |
| 1364 | 1366 | } |
| 1365 | 1367 | |
| 1366 | fn countQuotes(cmd_line: &const u8) -> usize { | |
| 1368 | fn countQuotes(cmd_line: &const u8) usize { | |
| 1367 | 1369 | var result: usize = 0; |
| 1368 | 1370 | var backslash_count: usize = 0; |
| 1369 | 1371 | var index: usize = 0; |
| ... | ... | @@ -1388,14 +1390,14 @@ pub const ArgIteratorWindows = struct { |
| 1388 | 1390 | pub const ArgIterator = struct { |
| 1389 | 1391 | inner: if (builtin.os == Os.windows) ArgIteratorWindows else ArgIteratorPosix, |
| 1390 | 1392 | |
| 1391 | pub fn init() -> ArgIterator { | |
| 1393 | pub fn init() ArgIterator { | |
| 1392 | 1394 | return ArgIterator { |
| 1393 | 1395 | .inner = if (builtin.os == Os.windows) ArgIteratorWindows.init() else ArgIteratorPosix.init(), |
| 1394 | 1396 | }; |
| 1395 | 1397 | } |
| 1396 | 1398 | |
| 1397 | 1399 | /// You must free the returned memory when done. |
| 1398 | pub fn next(self: &ArgIterator, allocator: &Allocator) -> ?%[]u8 { | |
| 1400 | pub fn next(self: &ArgIterator, allocator: &Allocator) ?%[]u8 { | |
| 1399 | 1401 | if (builtin.os == Os.windows) { |
| 1400 | 1402 | return self.inner.next(allocator); |
| 1401 | 1403 | } else { |
| ... | ... | @@ -1404,23 +1406,23 @@ pub const ArgIterator = struct { |
| 1404 | 1406 | } |
| 1405 | 1407 | |
| 1406 | 1408 | /// If you only are targeting posix you can call this and not need an allocator. |
| 1407 | pub fn nextPosix(self: &ArgIterator) -> ?[]const u8 { | |
| 1409 | pub fn nextPosix(self: &ArgIterator) ?[]const u8 { | |
| 1408 | 1410 | return self.inner.next(); |
| 1409 | 1411 | } |
| 1410 | 1412 | |
| 1411 | 1413 | /// Parse past 1 argument without capturing it. |
| 1412 | 1414 | /// Returns `true` if skipped an arg, `false` if we are at the end. |
| 1413 | pub fn skip(self: &ArgIterator) -> bool { | |
| 1415 | pub fn skip(self: &ArgIterator) bool { | |
| 1414 | 1416 | return self.inner.skip(); |
| 1415 | 1417 | } |
| 1416 | 1418 | }; |
| 1417 | 1419 | |
| 1418 | pub fn args() -> ArgIterator { | |
| 1420 | pub fn args() ArgIterator { | |
| 1419 | 1421 | return ArgIterator.init(); |
| 1420 | 1422 | } |
| 1421 | 1423 | |
| 1422 | 1424 | /// Caller must call freeArgs on result. |
| 1423 | pub fn argsAlloc(allocator: &mem.Allocator) -> %[]const []u8 { | |
| 1425 | pub fn argsAlloc(allocator: &mem.Allocator) %[]const []u8 { | |
| 1424 | 1426 | // TODO refactor to only make 1 allocation. |
| 1425 | 1427 | var it = args(); |
| 1426 | 1428 | var contents = try Buffer.initSize(allocator, 0); |
| ... | ... | @@ -1441,7 +1443,7 @@ pub fn argsAlloc(allocator: &mem.Allocator) -> %[]const []u8 { |
| 1441 | 1443 | const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len); |
| 1442 | 1444 | const total_bytes = try math.add(usize, slice_list_bytes, contents_slice.len); |
| 1443 | 1445 | const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes); |
| 1444 | %defer allocator.free(buf); | |
| 1446 | errdefer allocator.free(buf); | |
| 1445 | 1447 | |
| 1446 | 1448 | const result_slice_list = ([][]u8)(buf[0..slice_list_bytes]); |
| 1447 | 1449 | const result_contents = buf[slice_list_bytes..]; |
| ... | ... | @@ -1457,7 +1459,7 @@ pub fn argsAlloc(allocator: &mem.Allocator) -> %[]const []u8 { |
| 1457 | 1459 | return result_slice_list; |
| 1458 | 1460 | } |
| 1459 | 1461 | |
| 1460 | pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) { | |
| 1462 | pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void { | |
| 1461 | 1463 | var total_bytes: usize = 0; |
| 1462 | 1464 | for (args_alloc) |arg| { |
| 1463 | 1465 | total_bytes += @sizeOf([]u8) + arg.len; |
| ... | ... | @@ -1479,7 +1481,7 @@ test "windows arg parsing" { |
| 1479 | 1481 | [][]const u8{".\\..\\zig-cache\\build", "bin\\zig.exe", ".\\..", ".\\..\\zig-cache", "--help"}); |
| 1480 | 1482 | } |
| 1481 | 1483 | |
| 1482 | fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const u8) { | |
| 1484 | fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const u8) void { | |
| 1483 | 1485 | var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line); |
| 1484 | 1486 | for (expected_args) |expected_arg| { |
| 1485 | 1487 | const arg = ??it.next(debug.global_allocator) catch unreachable; |
| ... | ... | @@ -1509,7 +1511,7 @@ const unexpected_error_tracing = false; |
| 1509 | 1511 | |
| 1510 | 1512 | /// Call this when you made a syscall or something that sets errno |
| 1511 | 1513 | /// and you get an unexpected error. |
| 1512 | pub fn unexpectedErrorPosix(errno: usize) -> error { | |
| 1514 | pub fn unexpectedErrorPosix(errno: usize) error { | |
| 1513 | 1515 | if (unexpected_error_tracing) { |
| 1514 | 1516 | debug.warn("unexpected errno: {}\n", errno); |
| 1515 | 1517 | debug.dumpStackTrace(); |
| ... | ... | @@ -1519,7 +1521,7 @@ pub fn unexpectedErrorPosix(errno: usize) -> error { |
| 1519 | 1521 | |
| 1520 | 1522 | /// Call this when you made a windows DLL call or something that does SetLastError |
| 1521 | 1523 | /// and you get an unexpected error. |
| 1522 | pub fn unexpectedErrorWindows(err: windows.DWORD) -> error { | |
| 1524 | pub fn unexpectedErrorWindows(err: windows.DWORD) error { | |
| 1523 | 1525 | if (unexpected_error_tracing) { |
| 1524 | 1526 | debug.warn("unexpected GetLastError(): {}\n", err); |
| 1525 | 1527 | debug.dumpStackTrace(); |
| ... | ... | @@ -1527,7 +1529,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) -> error { |
| 1527 | 1529 | return error.Unexpected; |
| 1528 | 1530 | } |
| 1529 | 1531 | |
| 1530 | pub fn openSelfExe() -> %io.File { | |
| 1532 | pub fn openSelfExe() %io.File { | |
| 1531 | 1533 | switch (builtin.os) { |
| 1532 | 1534 | Os.linux => { |
| 1533 | 1535 | return io.File.openRead("/proc/self/exe", null); |
| ... | ... | @@ -1545,7 +1547,7 @@ pub fn openSelfExe() -> %io.File { |
| 1545 | 1547 | /// This function may return an error if the current executable |
| 1546 | 1548 | /// was deleted after spawning. |
| 1547 | 1549 | /// Caller owns returned memory. |
| 1548 | pub fn selfExePath(allocator: &mem.Allocator) -> %[]u8 { | |
| 1550 | pub fn selfExePath(allocator: &mem.Allocator) %[]u8 { | |
| 1549 | 1551 | switch (builtin.os) { |
| 1550 | 1552 | Os.linux => { |
| 1551 | 1553 | // If the currently executing binary has been deleted, |
| ... | ... | @@ -1554,7 +1556,7 @@ pub fn selfExePath(allocator: &mem.Allocator) -> %[]u8 { |
| 1554 | 1556 | }, |
| 1555 | 1557 | Os.windows => { |
| 1556 | 1558 | var out_path = try Buffer.initSize(allocator, 0xff); |
| 1557 | %defer out_path.deinit(); | |
| 1559 | errdefer out_path.deinit(); | |
| 1558 | 1560 | while (true) { |
| 1559 | 1561 | const dword_len = try math.cast(windows.DWORD, out_path.len()); |
| 1560 | 1562 | const copied_amt = windows.GetModuleFileNameA(null, out_path.ptr(), dword_len); |
| ... | ... | @@ -1577,7 +1579,7 @@ pub fn selfExePath(allocator: &mem.Allocator) -> %[]u8 { |
| 1577 | 1579 | const ret1 = c._NSGetExecutablePath(undefined, &u32_len); |
| 1578 | 1580 | assert(ret1 != 0); |
| 1579 | 1581 | const bytes = try allocator.alloc(u8, u32_len); |
| 1580 | %defer allocator.free(bytes); | |
| 1582 | errdefer allocator.free(bytes); | |
| 1581 | 1583 | const ret2 = c._NSGetExecutablePath(bytes.ptr, &u32_len); |
| 1582 | 1584 | assert(ret2 == 0); |
| 1583 | 1585 | return bytes; |
| ... | ... | @@ -1588,7 +1590,7 @@ pub fn selfExePath(allocator: &mem.Allocator) -> %[]u8 { |
| 1588 | 1590 | |
| 1589 | 1591 | /// Get the directory path that contains the current executable. |
| 1590 | 1592 | /// Caller owns returned memory. |
| 1591 | pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 { | |
| 1593 | pub fn selfExeDirPath(allocator: &mem.Allocator) %[]u8 { | |
| 1592 | 1594 | switch (builtin.os) { |
| 1593 | 1595 | Os.linux => { |
| 1594 | 1596 | // If the currently executing binary has been deleted, |
| ... | ... | @@ -1596,13 +1598,13 @@ pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 { |
| 1596 | 1598 | // This path cannot be opened, but it's valid for determining the directory |
| 1597 | 1599 | // the executable was in when it was run. |
| 1598 | 1600 | const full_exe_path = try readLink(allocator, "/proc/self/exe"); |
| 1599 | %defer allocator.free(full_exe_path); | |
| 1601 | errdefer allocator.free(full_exe_path); | |
| 1600 | 1602 | const dir = path.dirname(full_exe_path); |
| 1601 | 1603 | return allocator.shrink(u8, full_exe_path, dir.len); |
| 1602 | 1604 | }, |
| 1603 | 1605 | Os.windows, Os.macosx, Os.ios => { |
| 1604 | 1606 | const self_exe_path = try selfExePath(allocator); |
| 1605 | %defer allocator.free(self_exe_path); | |
| 1607 | errdefer allocator.free(self_exe_path); | |
| 1606 | 1608 | const dirname = os.path.dirname(self_exe_path); |
| 1607 | 1609 | return allocator.shrink(u8, self_exe_path, dirname.len); |
| 1608 | 1610 | }, |
| ... | ... | @@ -1610,7 +1612,7 @@ pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 { |
| 1610 | 1612 | } |
| 1611 | 1613 | } |
| 1612 | 1614 | |
| 1613 | pub fn isTty(handle: FileHandle) -> bool { | |
| 1615 | pub fn isTty(handle: FileHandle) bool { | |
| 1614 | 1616 | if (is_windows) { |
| 1615 | 1617 | return windows_util.windowsIsTty(handle); |
| 1616 | 1618 | } else { |
std/os/linux.zig+83-85| ... | ... | @@ -368,14 +368,14 @@ pub const TFD_CLOEXEC = O_CLOEXEC; |
| 368 | 368 | pub const TFD_TIMER_ABSTIME = 1; |
| 369 | 369 | pub const TFD_TIMER_CANCEL_ON_SET = (1 << 1); |
| 370 | 370 | |
| 371 | fn unsigned(s: i32) -> u32 { return @bitCast(u32, s); } | |
| 372 | fn signed(s: u32) -> i32 { return @bitCast(i32, s); } | |
| 373 | pub fn WEXITSTATUS(s: i32) -> i32 { return signed((unsigned(s) & 0xff00) >> 8); } | |
| 374 | pub fn WTERMSIG(s: i32) -> i32 { return signed(unsigned(s) & 0x7f); } | |
| 375 | pub fn WSTOPSIG(s: i32) -> i32 { return WEXITSTATUS(s); } | |
| 376 | pub fn WIFEXITED(s: i32) -> bool { return WTERMSIG(s) == 0; } | |
| 377 | pub fn WIFSTOPPED(s: i32) -> bool { return (u16)(((unsigned(s)&0xffff)*%0x10001)>>8) > 0x7f00; } | |
| 378 | pub fn WIFSIGNALED(s: i32) -> bool { return (unsigned(s)&0xffff)-%1 < 0xff; } | |
| 371 | fn unsigned(s: i32) u32 { return @bitCast(u32, s); } | |
| 372 | fn signed(s: u32) i32 { return @bitCast(i32, s); } | |
| 373 | pub fn WEXITSTATUS(s: i32) i32 { return signed((unsigned(s) & 0xff00) >> 8); } | |
| 374 | pub fn WTERMSIG(s: i32) i32 { return signed(unsigned(s) & 0x7f); } | |
| 375 | pub fn WSTOPSIG(s: i32) i32 { return WEXITSTATUS(s); } | |
| 376 | pub fn WIFEXITED(s: i32) bool { return WTERMSIG(s) == 0; } | |
| 377 | pub fn WIFSTOPPED(s: i32) bool { return (u16)(((unsigned(s)&0xffff)*%0x10001)>>8) > 0x7f00; } | |
| 378 | pub fn WIFSIGNALED(s: i32) bool { return (unsigned(s)&0xffff)-%1 < 0xff; } | |
| 379 | 379 | |
| 380 | 380 | |
| 381 | 381 | pub const winsize = extern struct { |
| ... | ... | @@ -386,161 +386,159 @@ pub const winsize = extern struct { |
| 386 | 386 | }; |
| 387 | 387 | |
| 388 | 388 | /// Get the errno from a syscall return value, or 0 for no error. |
| 389 | pub fn getErrno(r: usize) -> usize { | |
| 389 | pub fn getErrno(r: usize) usize { | |
| 390 | 390 | const signed_r = @bitCast(isize, r); |
| 391 | 391 | return if (signed_r > -4096 and signed_r < 0) usize(-signed_r) else 0; |
| 392 | 392 | } |
| 393 | 393 | |
| 394 | pub fn dup2(old: i32, new: i32) -> usize { | |
| 394 | pub fn dup2(old: i32, new: i32) usize { | |
| 395 | 395 | return arch.syscall2(arch.SYS_dup2, usize(old), usize(new)); |
| 396 | 396 | } |
| 397 | 397 | |
| 398 | pub fn chdir(path: &const u8) -> usize { | |
| 398 | pub fn chdir(path: &const u8) usize { | |
| 399 | 399 | return arch.syscall1(arch.SYS_chdir, @ptrToInt(path)); |
| 400 | 400 | } |
| 401 | 401 | |
| 402 | pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) -> usize { | |
| 402 | pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) usize { | |
| 403 | 403 | return arch.syscall3(arch.SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp)); |
| 404 | 404 | } |
| 405 | 405 | |
| 406 | pub fn fork() -> usize { | |
| 406 | pub fn fork() usize { | |
| 407 | 407 | return arch.syscall0(arch.SYS_fork); |
| 408 | 408 | } |
| 409 | 409 | |
| 410 | pub fn getcwd(buf: &u8, size: usize) -> usize { | |
| 410 | pub fn getcwd(buf: &u8, size: usize) usize { | |
| 411 | 411 | return arch.syscall2(arch.SYS_getcwd, @ptrToInt(buf), size); |
| 412 | 412 | } |
| 413 | 413 | |
| 414 | pub fn getdents(fd: i32, dirp: &u8, count: usize) -> usize { | |
| 414 | pub fn getdents(fd: i32, dirp: &u8, count: usize) usize { | |
| 415 | 415 | return arch.syscall3(arch.SYS_getdents, usize(fd), @ptrToInt(dirp), count); |
| 416 | 416 | } |
| 417 | 417 | |
| 418 | pub fn isatty(fd: i32) -> bool { | |
| 418 | pub fn isatty(fd: i32) bool { | |
| 419 | 419 | var wsz: winsize = undefined; |
| 420 | 420 | return arch.syscall3(arch.SYS_ioctl, usize(fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0; |
| 421 | 421 | } |
| 422 | 422 | |
| 423 | pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -> usize { | |
| 423 | pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) usize { | |
| 424 | 424 | return arch.syscall3(arch.SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); |
| 425 | 425 | } |
| 426 | 426 | |
| 427 | pub fn mkdir(path: &const u8, mode: u32) -> usize { | |
| 427 | pub fn mkdir(path: &const u8, mode: u32) usize { | |
| 428 | 428 | return arch.syscall2(arch.SYS_mkdir, @ptrToInt(path), mode); |
| 429 | 429 | } |
| 430 | 430 | |
| 431 | pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) | |
| 432 | -> usize | |
| 433 | { | |
| 431 | pub fn mmap(address: ?&u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) usize { | |
| 434 | 432 | return arch.syscall6(arch.SYS_mmap, @ptrToInt(address), length, prot, flags, usize(fd), |
| 435 | 433 | @bitCast(usize, offset)); |
| 436 | 434 | } |
| 437 | 435 | |
| 438 | pub fn munmap(address: &u8, length: usize) -> usize { | |
| 436 | pub fn munmap(address: &u8, length: usize) usize { | |
| 439 | 437 | return arch.syscall2(arch.SYS_munmap, @ptrToInt(address), length); |
| 440 | 438 | } |
| 441 | 439 | |
| 442 | pub fn read(fd: i32, buf: &u8, count: usize) -> usize { | |
| 440 | pub fn read(fd: i32, buf: &u8, count: usize) usize { | |
| 443 | 441 | return arch.syscall3(arch.SYS_read, usize(fd), @ptrToInt(buf), count); |
| 444 | 442 | } |
| 445 | 443 | |
| 446 | pub fn rmdir(path: &const u8) -> usize { | |
| 444 | pub fn rmdir(path: &const u8) usize { | |
| 447 | 445 | return arch.syscall1(arch.SYS_rmdir, @ptrToInt(path)); |
| 448 | 446 | } |
| 449 | 447 | |
| 450 | pub fn symlink(existing: &const u8, new: &const u8) -> usize { | |
| 448 | pub fn symlink(existing: &const u8, new: &const u8) usize { | |
| 451 | 449 | return arch.syscall2(arch.SYS_symlink, @ptrToInt(existing), @ptrToInt(new)); |
| 452 | 450 | } |
| 453 | 451 | |
| 454 | pub fn pread(fd: i32, buf: &u8, count: usize, offset: usize) -> usize { | |
| 452 | pub fn pread(fd: i32, buf: &u8, count: usize, offset: usize) usize { | |
| 455 | 453 | return arch.syscall4(arch.SYS_pread, usize(fd), @ptrToInt(buf), count, offset); |
| 456 | 454 | } |
| 457 | 455 | |
| 458 | pub fn pipe(fd: &[2]i32) -> usize { | |
| 456 | pub fn pipe(fd: &[2]i32) usize { | |
| 459 | 457 | return pipe2(fd, 0); |
| 460 | 458 | } |
| 461 | 459 | |
| 462 | pub fn pipe2(fd: &[2]i32, flags: usize) -> usize { | |
| 460 | pub fn pipe2(fd: &[2]i32, flags: usize) usize { | |
| 463 | 461 | return arch.syscall2(arch.SYS_pipe2, @ptrToInt(fd), flags); |
| 464 | 462 | } |
| 465 | 463 | |
| 466 | pub fn write(fd: i32, buf: &const u8, count: usize) -> usize { | |
| 464 | pub fn write(fd: i32, buf: &const u8, count: usize) usize { | |
| 467 | 465 | return arch.syscall3(arch.SYS_write, usize(fd), @ptrToInt(buf), count); |
| 468 | 466 | } |
| 469 | 467 | |
| 470 | pub fn pwrite(fd: i32, buf: &const u8, count: usize, offset: usize) -> usize { | |
| 468 | pub fn pwrite(fd: i32, buf: &const u8, count: usize, offset: usize) usize { | |
| 471 | 469 | return arch.syscall4(arch.SYS_pwrite, usize(fd), @ptrToInt(buf), count, offset); |
| 472 | 470 | } |
| 473 | 471 | |
| 474 | pub fn rename(old: &const u8, new: &const u8) -> usize { | |
| 472 | pub fn rename(old: &const u8, new: &const u8) usize { | |
| 475 | 473 | return arch.syscall2(arch.SYS_rename, @ptrToInt(old), @ptrToInt(new)); |
| 476 | 474 | } |
| 477 | 475 | |
| 478 | pub fn open(path: &const u8, flags: u32, perm: usize) -> usize { | |
| 476 | pub fn open(path: &const u8, flags: u32, perm: usize) usize { | |
| 479 | 477 | return arch.syscall3(arch.SYS_open, @ptrToInt(path), flags, perm); |
| 480 | 478 | } |
| 481 | 479 | |
| 482 | pub fn create(path: &const u8, perm: usize) -> usize { | |
| 480 | pub fn create(path: &const u8, perm: usize) usize { | |
| 483 | 481 | return arch.syscall2(arch.SYS_creat, @ptrToInt(path), perm); |
| 484 | 482 | } |
| 485 | 483 | |
| 486 | pub fn openat(dirfd: i32, path: &const u8, flags: usize, mode: usize) -> usize { | |
| 484 | pub fn openat(dirfd: i32, path: &const u8, flags: usize, mode: usize) usize { | |
| 487 | 485 | return arch.syscall4(arch.SYS_openat, usize(dirfd), @ptrToInt(path), flags, mode); |
| 488 | 486 | } |
| 489 | 487 | |
| 490 | pub fn close(fd: i32) -> usize { | |
| 488 | pub fn close(fd: i32) usize { | |
| 491 | 489 | return arch.syscall1(arch.SYS_close, usize(fd)); |
| 492 | 490 | } |
| 493 | 491 | |
| 494 | pub fn lseek(fd: i32, offset: isize, ref_pos: usize) -> usize { | |
| 492 | pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize { | |
| 495 | 493 | return arch.syscall3(arch.SYS_lseek, usize(fd), @bitCast(usize, offset), ref_pos); |
| 496 | 494 | } |
| 497 | 495 | |
| 498 | pub fn exit(status: i32) -> noreturn { | |
| 496 | pub fn exit(status: i32) noreturn { | |
| 499 | 497 | _ = arch.syscall1(arch.SYS_exit, @bitCast(usize, isize(status))); |
| 500 | 498 | unreachable; |
| 501 | 499 | } |
| 502 | 500 | |
| 503 | pub fn getrandom(buf: &u8, count: usize, flags: u32) -> usize { | |
| 501 | pub fn getrandom(buf: &u8, count: usize, flags: u32) usize { | |
| 504 | 502 | return arch.syscall3(arch.SYS_getrandom, @ptrToInt(buf), count, usize(flags)); |
| 505 | 503 | } |
| 506 | 504 | |
| 507 | pub fn kill(pid: i32, sig: i32) -> usize { | |
| 505 | pub fn kill(pid: i32, sig: i32) usize { | |
| 508 | 506 | return arch.syscall2(arch.SYS_kill, @bitCast(usize, isize(pid)), usize(sig)); |
| 509 | 507 | } |
| 510 | 508 | |
| 511 | pub fn unlink(path: &const u8) -> usize { | |
| 509 | pub fn unlink(path: &const u8) usize { | |
| 512 | 510 | return arch.syscall1(arch.SYS_unlink, @ptrToInt(path)); |
| 513 | 511 | } |
| 514 | 512 | |
| 515 | pub fn waitpid(pid: i32, status: &i32, options: i32) -> usize { | |
| 513 | pub fn waitpid(pid: i32, status: &i32, options: i32) usize { | |
| 516 | 514 | return arch.syscall4(arch.SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0); |
| 517 | 515 | } |
| 518 | 516 | |
| 519 | pub fn nanosleep(req: &const timespec, rem: ?&timespec) -> usize { | |
| 517 | pub fn nanosleep(req: &const timespec, rem: ?&timespec) usize { | |
| 520 | 518 | return arch.syscall2(arch.SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem)); |
| 521 | 519 | } |
| 522 | 520 | |
| 523 | pub fn setuid(uid: u32) -> usize { | |
| 521 | pub fn setuid(uid: u32) usize { | |
| 524 | 522 | return arch.syscall1(arch.SYS_setuid, uid); |
| 525 | 523 | } |
| 526 | 524 | |
| 527 | pub fn setgid(gid: u32) -> usize { | |
| 525 | pub fn setgid(gid: u32) usize { | |
| 528 | 526 | return arch.syscall1(arch.SYS_setgid, gid); |
| 529 | 527 | } |
| 530 | 528 | |
| 531 | pub fn setreuid(ruid: u32, euid: u32) -> usize { | |
| 529 | pub fn setreuid(ruid: u32, euid: u32) usize { | |
| 532 | 530 | return arch.syscall2(arch.SYS_setreuid, ruid, euid); |
| 533 | 531 | } |
| 534 | 532 | |
| 535 | pub fn setregid(rgid: u32, egid: u32) -> usize { | |
| 533 | pub fn setregid(rgid: u32, egid: u32) usize { | |
| 536 | 534 | return arch.syscall2(arch.SYS_setregid, rgid, egid); |
| 537 | 535 | } |
| 538 | 536 | |
| 539 | pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) -> usize { | |
| 537 | pub fn sigprocmask(flags: u32, noalias set: &const sigset_t, noalias oldset: ?&sigset_t) usize { | |
| 540 | 538 | return arch.syscall4(arch.SYS_rt_sigprocmask, flags, @ptrToInt(set), @ptrToInt(oldset), NSIG/8); |
| 541 | 539 | } |
| 542 | 540 | |
| 543 | pub fn sigaction(sig: u6, noalias act: &const Sigaction, noalias oact: ?&Sigaction) -> usize { | |
| 541 | pub fn sigaction(sig: u6, noalias act: &const Sigaction, noalias oact: ?&Sigaction) usize { | |
| 544 | 542 | assert(sig >= 1); |
| 545 | 543 | assert(sig != SIGKILL); |
| 546 | 544 | assert(sig != SIGSTOP); |
| ... | ... | @@ -548,7 +546,7 @@ pub fn sigaction(sig: u6, noalias act: &const Sigaction, noalias oact: ?&Sigacti |
| 548 | 546 | .handler = act.handler, |
| 549 | 547 | .flags = act.flags | SA_RESTORER, |
| 550 | 548 | .mask = undefined, |
| 551 | .restorer = @ptrCast(extern fn(), arch.restore_rt), | |
| 549 | .restorer = @ptrCast(extern fn()void, arch.restore_rt), | |
| 552 | 550 | }; |
| 553 | 551 | var ksa_old: k_sigaction = undefined; |
| 554 | 552 | @memcpy(@ptrCast(&u8, &ksa.mask), @ptrCast(&const u8, &act.mask), 8); |
| ... | ... | @@ -571,25 +569,25 @@ const all_mask = []usize{@maxValue(usize)}; |
| 571 | 569 | const app_mask = []usize{0xfffffffc7fffffff}; |
| 572 | 570 | |
| 573 | 571 | const k_sigaction = extern struct { |
| 574 | handler: extern fn(i32), | |
| 572 | handler: extern fn(i32)void, | |
| 575 | 573 | flags: usize, |
| 576 | restorer: extern fn(), | |
| 574 | restorer: extern fn()void, | |
| 577 | 575 | mask: [2]u32, |
| 578 | 576 | }; |
| 579 | 577 | |
| 580 | 578 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 581 | 579 | pub const Sigaction = struct { |
| 582 | handler: extern fn(i32), | |
| 580 | handler: extern fn(i32)void, | |
| 583 | 581 | mask: sigset_t, |
| 584 | 582 | flags: u32, |
| 585 | 583 | }; |
| 586 | 584 | |
| 587 | pub const SIG_ERR = @intToPtr(extern fn(i32), @maxValue(usize)); | |
| 588 | pub const SIG_DFL = @intToPtr(extern fn(i32), 0); | |
| 589 | pub const SIG_IGN = @intToPtr(extern fn(i32), 1); | |
| 585 | pub const SIG_ERR = @intToPtr(extern fn(i32)void, @maxValue(usize)); | |
| 586 | pub const SIG_DFL = @intToPtr(extern fn(i32)void, 0); | |
| 587 | pub const SIG_IGN = @intToPtr(extern fn(i32)void, 1); | |
| 590 | 588 | pub const empty_sigset = []usize{0} ** sigset_t.len; |
| 591 | 589 | |
| 592 | pub fn raise(sig: i32) -> usize { | |
| 590 | pub fn raise(sig: i32) usize { | |
| 593 | 591 | var set: sigset_t = undefined; |
| 594 | 592 | blockAppSignals(&set); |
| 595 | 593 | const tid = i32(arch.syscall0(arch.SYS_gettid)); |
| ... | ... | @@ -598,24 +596,24 @@ pub fn raise(sig: i32) -> usize { |
| 598 | 596 | return ret; |
| 599 | 597 | } |
| 600 | 598 | |
| 601 | fn blockAllSignals(set: &sigset_t) { | |
| 599 | fn blockAllSignals(set: &sigset_t) void { | |
| 602 | 600 | _ = arch.syscall4(arch.SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&all_mask), @ptrToInt(set), NSIG/8); |
| 603 | 601 | } |
| 604 | 602 | |
| 605 | fn blockAppSignals(set: &sigset_t) { | |
| 603 | fn blockAppSignals(set: &sigset_t) void { | |
| 606 | 604 | _ = arch.syscall4(arch.SYS_rt_sigprocmask, SIG_BLOCK, @ptrToInt(&app_mask), @ptrToInt(set), NSIG/8); |
| 607 | 605 | } |
| 608 | 606 | |
| 609 | fn restoreSignals(set: &sigset_t) { | |
| 607 | fn restoreSignals(set: &sigset_t) void { | |
| 610 | 608 | _ = arch.syscall4(arch.SYS_rt_sigprocmask, SIG_SETMASK, @ptrToInt(set), 0, NSIG/8); |
| 611 | 609 | } |
| 612 | 610 | |
| 613 | pub fn sigaddset(set: &sigset_t, sig: u6) { | |
| 611 | pub fn sigaddset(set: &sigset_t, sig: u6) void { | |
| 614 | 612 | const s = sig - 1; |
| 615 | 613 | (*set)[usize(s) / usize.bit_count] |= usize(1) << (s & (usize.bit_count - 1)); |
| 616 | 614 | } |
| 617 | 615 | |
| 618 | pub fn sigismember(set: &const sigset_t, sig: u6) -> bool { | |
| 616 | pub fn sigismember(set: &const sigset_t, sig: u6) bool { | |
| 619 | 617 | const s = sig - 1; |
| 620 | 618 | return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0; |
| 621 | 619 | } |
| ... | ... | @@ -652,69 +650,69 @@ pub const iovec = extern struct { |
| 652 | 650 | iov_len: usize, |
| 653 | 651 | }; |
| 654 | 652 | |
| 655 | pub fn getsockname(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize { | |
| 653 | pub fn getsockname(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) usize { | |
| 656 | 654 | return arch.syscall3(arch.SYS_getsockname, usize(fd), @ptrToInt(addr), @ptrToInt(len)); |
| 657 | 655 | } |
| 658 | 656 | |
| 659 | pub fn getpeername(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize { | |
| 657 | pub fn getpeername(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) usize { | |
| 660 | 658 | return arch.syscall3(arch.SYS_getpeername, usize(fd), @ptrToInt(addr), @ptrToInt(len)); |
| 661 | 659 | } |
| 662 | 660 | |
| 663 | pub fn socket(domain: i32, socket_type: i32, protocol: i32) -> usize { | |
| 661 | pub fn socket(domain: i32, socket_type: i32, protocol: i32) usize { | |
| 664 | 662 | return arch.syscall3(arch.SYS_socket, usize(domain), usize(socket_type), usize(protocol)); |
| 665 | 663 | } |
| 666 | 664 | |
| 667 | pub fn setsockopt(fd: i32, level: i32, optname: i32, optval: &const u8, optlen: socklen_t) -> usize { | |
| 665 | pub fn setsockopt(fd: i32, level: i32, optname: i32, optval: &const u8, optlen: socklen_t) usize { | |
| 668 | 666 | return arch.syscall5(arch.SYS_setsockopt, usize(fd), usize(level), usize(optname), usize(optval), @ptrToInt(optlen)); |
| 669 | 667 | } |
| 670 | 668 | |
| 671 | pub fn getsockopt(fd: i32, level: i32, optname: i32, noalias optval: &u8, noalias optlen: &socklen_t) -> usize { | |
| 669 | pub fn getsockopt(fd: i32, level: i32, optname: i32, noalias optval: &u8, noalias optlen: &socklen_t) usize { | |
| 672 | 670 | return arch.syscall5(arch.SYS_getsockopt, usize(fd), usize(level), usize(optname), @ptrToInt(optval), @ptrToInt(optlen)); |
| 673 | 671 | } |
| 674 | 672 | |
| 675 | pub fn sendmsg(fd: i32, msg: &const arch.msghdr, flags: u32) -> usize { | |
| 673 | pub fn sendmsg(fd: i32, msg: &const arch.msghdr, flags: u32) usize { | |
| 676 | 674 | return arch.syscall3(arch.SYS_sendmsg, usize(fd), @ptrToInt(msg), flags); |
| 677 | 675 | } |
| 678 | 676 | |
| 679 | pub fn connect(fd: i32, addr: &const sockaddr, len: socklen_t) -> usize { | |
| 677 | pub fn connect(fd: i32, addr: &const sockaddr, len: socklen_t) usize { | |
| 680 | 678 | return arch.syscall3(arch.SYS_connect, usize(fd), @ptrToInt(addr), usize(len)); |
| 681 | 679 | } |
| 682 | 680 | |
| 683 | pub fn recvmsg(fd: i32, msg: &arch.msghdr, flags: u32) -> usize { | |
| 681 | pub fn recvmsg(fd: i32, msg: &arch.msghdr, flags: u32) usize { | |
| 684 | 682 | return arch.syscall3(arch.SYS_recvmsg, usize(fd), @ptrToInt(msg), flags); |
| 685 | 683 | } |
| 686 | 684 | |
| 687 | 685 | pub fn recvfrom(fd: i32, noalias buf: &u8, len: usize, flags: u32, |
| 688 | noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) -> usize | |
| 686 | noalias addr: ?&sockaddr, noalias alen: ?&socklen_t) usize | |
| 689 | 687 | { |
| 690 | 688 | return arch.syscall6(arch.SYS_recvfrom, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)); |
| 691 | 689 | } |
| 692 | 690 | |
| 693 | pub fn shutdown(fd: i32, how: i32) -> usize { | |
| 691 | pub fn shutdown(fd: i32, how: i32) usize { | |
| 694 | 692 | return arch.syscall2(arch.SYS_shutdown, usize(fd), usize(how)); |
| 695 | 693 | } |
| 696 | 694 | |
| 697 | pub fn bind(fd: i32, addr: &const sockaddr, len: socklen_t) -> usize { | |
| 695 | pub fn bind(fd: i32, addr: &const sockaddr, len: socklen_t) usize { | |
| 698 | 696 | return arch.syscall3(arch.SYS_bind, usize(fd), @ptrToInt(addr), usize(len)); |
| 699 | 697 | } |
| 700 | 698 | |
| 701 | pub fn listen(fd: i32, backlog: i32) -> usize { | |
| 699 | pub fn listen(fd: i32, backlog: i32) usize { | |
| 702 | 700 | return arch.syscall2(arch.SYS_listen, usize(fd), usize(backlog)); |
| 703 | 701 | } |
| 704 | 702 | |
| 705 | pub fn sendto(fd: i32, buf: &const u8, len: usize, flags: u32, addr: ?&const sockaddr, alen: socklen_t) -> usize { | |
| 703 | pub fn sendto(fd: i32, buf: &const u8, len: usize, flags: u32, addr: ?&const sockaddr, alen: socklen_t) usize { | |
| 706 | 704 | return arch.syscall6(arch.SYS_sendto, usize(fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), usize(alen)); |
| 707 | 705 | } |
| 708 | 706 | |
| 709 | pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) -> usize { | |
| 707 | pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize { | |
| 710 | 708 | return arch.syscall4(arch.SYS_socketpair, usize(domain), usize(socket_type), usize(protocol), @ptrToInt(&fd[0])); |
| 711 | 709 | } |
| 712 | 710 | |
| 713 | pub fn accept(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize { | |
| 711 | pub fn accept(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) usize { | |
| 714 | 712 | return accept4(fd, addr, len, 0); |
| 715 | 713 | } |
| 716 | 714 | |
| 717 | pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags: u32) -> usize { | |
| 715 | pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags: u32) usize { | |
| 718 | 716 | return arch.syscall4(arch.SYS_accept4, usize(fd), @ptrToInt(addr), @ptrToInt(len), flags); |
| 719 | 717 | } |
| 720 | 718 | |
| ... | ... | @@ -722,7 +720,7 @@ pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags: |
| 722 | 720 | // error SystemResources; |
| 723 | 721 | // error Io; |
| 724 | 722 | // |
| 725 | // pub fn if_nametoindex(name: []u8) -> %u32 { | |
| 723 | // pub fn if_nametoindex(name: []u8) %u32 { | |
| 726 | 724 | // var ifr: ifreq = undefined; |
| 727 | 725 | // |
| 728 | 726 | // if (name.len >= ifr.ifr_name.len) { |
| ... | ... | @@ -749,7 +747,7 @@ pub fn accept4(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t, flags: |
| 749 | 747 | pub const Stat = arch.Stat; |
| 750 | 748 | pub const timespec = arch.timespec; |
| 751 | 749 | |
| 752 | pub fn fstat(fd: i32, stat_buf: &Stat) -> usize { | |
| 750 | pub fn fstat(fd: i32, stat_buf: &Stat) usize { | |
| 753 | 751 | return arch.syscall2(arch.SYS_fstat, usize(fd), @ptrToInt(stat_buf)); |
| 754 | 752 | } |
| 755 | 753 | |
| ... | ... | @@ -760,19 +758,19 @@ pub const epoll_event = extern struct { |
| 760 | 758 | data: epoll_data |
| 761 | 759 | }; |
| 762 | 760 | |
| 763 | pub fn epoll_create() -> usize { | |
| 761 | pub fn epoll_create() usize { | |
| 764 | 762 | return arch.syscall1(arch.SYS_epoll_create, usize(1)); |
| 765 | 763 | } |
| 766 | 764 | |
| 767 | pub fn epoll_ctl(epoll_fd: i32, op: i32, fd: i32, ev: &epoll_event) -> usize { | |
| 765 | pub fn epoll_ctl(epoll_fd: i32, op: i32, fd: i32, ev: &epoll_event) usize { | |
| 768 | 766 | return arch.syscall4(arch.SYS_epoll_ctl, usize(epoll_fd), usize(op), usize(fd), @ptrToInt(ev)); |
| 769 | 767 | } |
| 770 | 768 | |
| 771 | pub fn epoll_wait(epoll_fd: i32, events: &epoll_event, maxevents: i32, timeout: i32) -> usize { | |
| 769 | pub fn epoll_wait(epoll_fd: i32, events: &epoll_event, maxevents: i32, timeout: i32) usize { | |
| 772 | 770 | return arch.syscall4(arch.SYS_epoll_wait, usize(epoll_fd), @ptrToInt(events), usize(maxevents), usize(timeout)); |
| 773 | 771 | } |
| 774 | 772 | |
| 775 | pub fn timerfd_create(clockid: i32, flags: u32) -> usize { | |
| 773 | pub fn timerfd_create(clockid: i32, flags: u32) usize { | |
| 776 | 774 | return arch.syscall2(arch.SYS_timerfd_create, usize(clockid), usize(flags)); |
| 777 | 775 | } |
| 778 | 776 | |
| ... | ... | @@ -781,11 +779,11 @@ pub const itimerspec = extern struct { |
| 781 | 779 | it_value: timespec |
| 782 | 780 | }; |
| 783 | 781 | |
| 784 | pub fn timerfd_gettime(fd: i32, curr_value: &itimerspec) -> usize { | |
| 782 | pub fn timerfd_gettime(fd: i32, curr_value: &itimerspec) usize { | |
| 785 | 783 | return arch.syscall2(arch.SYS_timerfd_gettime, usize(fd), @ptrToInt(curr_value)); |
| 786 | 784 | } |
| 787 | 785 | |
| 788 | pub fn timerfd_settime(fd: i32, flags: u32, new_value: &const itimerspec, old_value: ?&itimerspec) -> usize { | |
| 786 | pub fn timerfd_settime(fd: i32, flags: u32, new_value: &const itimerspec, old_value: ?&itimerspec) usize { | |
| 789 | 787 | return arch.syscall4(arch.SYS_timerfd_settime, usize(fd), usize(flags), @ptrToInt(new_value), @ptrToInt(old_value)); |
| 790 | 788 | } |
| 791 | 789 |
std/os/linux_i386.zig+7-7| ... | ... | @@ -419,20 +419,20 @@ pub const F_GETOWN_EX = 16; |
| 419 | 419 | |
| 420 | 420 | pub const F_GETOWNER_UIDS = 17; |
| 421 | 421 | |
| 422 | pub inline fn syscall0(number: usize) -> usize { | |
| 422 | pub inline fn syscall0(number: usize) usize { | |
| 423 | 423 | asm volatile ("int $0x80" |
| 424 | 424 | : [ret] "={eax}" (-> usize) |
| 425 | 425 | : [number] "{eax}" (number)) |
| 426 | 426 | } |
| 427 | 427 | |
| 428 | pub inline fn syscall1(number: usize, arg1: usize) -> usize { | |
| 428 | pub inline fn syscall1(number: usize, arg1: usize) usize { | |
| 429 | 429 | asm volatile ("int $0x80" |
| 430 | 430 | : [ret] "={eax}" (-> usize) |
| 431 | 431 | : [number] "{eax}" (number), |
| 432 | 432 | [arg1] "{ebx}" (arg1)) |
| 433 | 433 | } |
| 434 | 434 | |
| 435 | pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { | |
| 435 | pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) usize { | |
| 436 | 436 | asm volatile ("int $0x80" |
| 437 | 437 | : [ret] "={eax}" (-> usize) |
| 438 | 438 | : [number] "{eax}" (number), |
| ... | ... | @@ -440,7 +440,7 @@ pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { |
| 440 | 440 | [arg2] "{ecx}" (arg2)) |
| 441 | 441 | } |
| 442 | 442 | |
| 443 | pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { | |
| 443 | pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize { | |
| 444 | 444 | asm volatile ("int $0x80" |
| 445 | 445 | : [ret] "={eax}" (-> usize) |
| 446 | 446 | : [number] "{eax}" (number), |
| ... | ... | @@ -449,7 +449,7 @@ pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> |
| 449 | 449 | [arg3] "{edx}" (arg3)) |
| 450 | 450 | } |
| 451 | 451 | |
| 452 | pub inline fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> usize { | |
| 452 | pub inline fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { | |
| 453 | 453 | asm volatile ("int $0x80" |
| 454 | 454 | : [ret] "={eax}" (-> usize) |
| 455 | 455 | : [number] "{eax}" (number), |
| ... | ... | @@ -486,7 +486,7 @@ pub inline fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, |
| 486 | 486 | [arg6] "{ebp}" (arg6)) |
| 487 | 487 | } |
| 488 | 488 | |
| 489 | pub nakedcc fn restore() { | |
| 489 | pub nakedcc fn restore() void { | |
| 490 | 490 | asm volatile ( |
| 491 | 491 | \\popl %%eax |
| 492 | 492 | \\movl $119, %%eax |
| ... | ... | @@ -496,7 +496,7 @@ pub nakedcc fn restore() { |
| 496 | 496 | : "rcx", "r11") |
| 497 | 497 | } |
| 498 | 498 | |
| 499 | pub nakedcc fn restore_rt() { | |
| 499 | pub nakedcc fn restore_rt() void { | |
| 500 | 500 | asm volatile ("int $0x80" |
| 501 | 501 | : |
| 502 | 502 | : [number] "{eax}" (usize(SYS_rt_sigreturn)) |
std/os/linux_x86_64.zig+8-8| ... | ... | @@ -370,14 +370,14 @@ pub const F_GETOWN_EX = 16; |
| 370 | 370 | |
| 371 | 371 | pub const F_GETOWNER_UIDS = 17; |
| 372 | 372 | |
| 373 | pub fn syscall0(number: usize) -> usize { | |
| 373 | pub fn syscall0(number: usize) usize { | |
| 374 | 374 | return asm volatile ("syscall" |
| 375 | 375 | : [ret] "={rax}" (-> usize) |
| 376 | 376 | : [number] "{rax}" (number) |
| 377 | 377 | : "rcx", "r11"); |
| 378 | 378 | } |
| 379 | 379 | |
| 380 | pub fn syscall1(number: usize, arg1: usize) -> usize { | |
| 380 | pub fn syscall1(number: usize, arg1: usize) usize { | |
| 381 | 381 | return asm volatile ("syscall" |
| 382 | 382 | : [ret] "={rax}" (-> usize) |
| 383 | 383 | : [number] "{rax}" (number), |
| ... | ... | @@ -385,7 +385,7 @@ pub fn syscall1(number: usize, arg1: usize) -> usize { |
| 385 | 385 | : "rcx", "r11"); |
| 386 | 386 | } |
| 387 | 387 | |
| 388 | pub fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { | |
| 388 | pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize { | |
| 389 | 389 | return asm volatile ("syscall" |
| 390 | 390 | : [ret] "={rax}" (-> usize) |
| 391 | 391 | : [number] "{rax}" (number), |
| ... | ... | @@ -394,7 +394,7 @@ pub fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { |
| 394 | 394 | : "rcx", "r11"); |
| 395 | 395 | } |
| 396 | 396 | |
| 397 | pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { | |
| 397 | pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize { | |
| 398 | 398 | return asm volatile ("syscall" |
| 399 | 399 | : [ret] "={rax}" (-> usize) |
| 400 | 400 | : [number] "{rax}" (number), |
| ... | ... | @@ -404,7 +404,7 @@ pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { |
| 404 | 404 | : "rcx", "r11"); |
| 405 | 405 | } |
| 406 | 406 | |
| 407 | pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> usize { | |
| 407 | pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { | |
| 408 | 408 | return asm volatile ("syscall" |
| 409 | 409 | : [ret] "={rax}" (-> usize) |
| 410 | 410 | : [number] "{rax}" (number), |
| ... | ... | @@ -415,7 +415,7 @@ pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz |
| 415 | 415 | : "rcx", "r11"); |
| 416 | 416 | } |
| 417 | 417 | |
| 418 | pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> usize { | |
| 418 | pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { | |
| 419 | 419 | return asm volatile ("syscall" |
| 420 | 420 | : [ret] "={rax}" (-> usize) |
| 421 | 421 | : [number] "{rax}" (number), |
| ... | ... | @@ -428,7 +428,7 @@ pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz |
| 428 | 428 | } |
| 429 | 429 | |
| 430 | 430 | pub fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, |
| 431 | arg5: usize, arg6: usize) -> usize | |
| 431 | arg5: usize, arg6: usize) usize | |
| 432 | 432 | { |
| 433 | 433 | return asm volatile ("syscall" |
| 434 | 434 | : [ret] "={rax}" (-> usize) |
| ... | ... | @@ -442,7 +442,7 @@ pub fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usiz |
| 442 | 442 | : "rcx", "r11"); |
| 443 | 443 | } |
| 444 | 444 | |
| 445 | pub nakedcc fn restore_rt() { | |
| 445 | pub nakedcc fn restore_rt() void { | |
| 446 | 446 | return asm volatile ("syscall" |
| 447 | 447 | : |
| 448 | 448 | : [number] "{rax}" (usize(SYS_rt_sigreturn)) |
std/os/path.zig+45-45| ... | ... | @@ -22,7 +22,7 @@ pub const delimiter = if (is_windows) delimiter_windows else delimiter_posix; |
| 22 | 22 | |
| 23 | 23 | const is_windows = builtin.os == builtin.Os.windows; |
| 24 | 24 | |
| 25 | pub fn isSep(byte: u8) -> bool { | |
| 25 | pub fn isSep(byte: u8) bool { | |
| 26 | 26 | if (is_windows) { |
| 27 | 27 | return byte == '/' or byte == '\\'; |
| 28 | 28 | } else { |
| ... | ... | @@ -32,7 +32,7 @@ pub fn isSep(byte: u8) -> bool { |
| 32 | 32 | |
| 33 | 33 | /// Naively combines a series of paths with the native path seperator. |
| 34 | 34 | /// Allocates memory for the result, which must be freed by the caller. |
| 35 | pub fn join(allocator: &Allocator, paths: ...) -> %[]u8 { | |
| 35 | pub fn join(allocator: &Allocator, paths: ...) %[]u8 { | |
| 36 | 36 | if (is_windows) { |
| 37 | 37 | return joinWindows(allocator, paths); |
| 38 | 38 | } else { |
| ... | ... | @@ -40,11 +40,11 @@ pub fn join(allocator: &Allocator, paths: ...) -> %[]u8 { |
| 40 | 40 | } |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | pub fn joinWindows(allocator: &Allocator, paths: ...) -> %[]u8 { | |
| 43 | pub fn joinWindows(allocator: &Allocator, paths: ...) %[]u8 { | |
| 44 | 44 | return mem.join(allocator, sep_windows, paths); |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | pub fn joinPosix(allocator: &Allocator, paths: ...) -> %[]u8 { | |
| 47 | pub fn joinPosix(allocator: &Allocator, paths: ...) %[]u8 { | |
| 48 | 48 | return mem.join(allocator, sep_posix, paths); |
| 49 | 49 | } |
| 50 | 50 | |
| ... | ... | @@ -69,7 +69,7 @@ test "os.path.join" { |
| 69 | 69 | "/home/andy/dev/zig/build/lib/zig/std/io.zig")); |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | pub fn isAbsolute(path: []const u8) -> bool { | |
| 72 | pub fn isAbsolute(path: []const u8) bool { | |
| 73 | 73 | if (is_windows) { |
| 74 | 74 | return isAbsoluteWindows(path); |
| 75 | 75 | } else { |
| ... | ... | @@ -77,7 +77,7 @@ pub fn isAbsolute(path: []const u8) -> bool { |
| 77 | 77 | } |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | pub fn isAbsoluteWindows(path: []const u8) -> bool { | |
| 80 | pub fn isAbsoluteWindows(path: []const u8) bool { | |
| 81 | 81 | if (path[0] == '/') |
| 82 | 82 | return true; |
| 83 | 83 | |
| ... | ... | @@ -96,7 +96,7 @@ pub fn isAbsoluteWindows(path: []const u8) -> bool { |
| 96 | 96 | return false; |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | pub fn isAbsolutePosix(path: []const u8) -> bool { | |
| 99 | pub fn isAbsolutePosix(path: []const u8) bool { | |
| 100 | 100 | return path[0] == sep_posix; |
| 101 | 101 | } |
| 102 | 102 | |
| ... | ... | @@ -129,11 +129,11 @@ test "os.path.isAbsolutePosix" { |
| 129 | 129 | testIsAbsolutePosix("./baz", false); |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | fn testIsAbsoluteWindows(path: []const u8, expected_result: bool) { | |
| 132 | fn testIsAbsoluteWindows(path: []const u8, expected_result: bool) void { | |
| 133 | 133 | assert(isAbsoluteWindows(path) == expected_result); |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | fn testIsAbsolutePosix(path: []const u8, expected_result: bool) { | |
| 136 | fn testIsAbsolutePosix(path: []const u8, expected_result: bool) void { | |
| 137 | 137 | assert(isAbsolutePosix(path) == expected_result); |
| 138 | 138 | } |
| 139 | 139 | |
| ... | ... | @@ -149,7 +149,7 @@ pub const WindowsPath = struct { |
| 149 | 149 | }; |
| 150 | 150 | }; |
| 151 | 151 | |
| 152 | pub fn windowsParsePath(path: []const u8) -> WindowsPath { | |
| 152 | pub fn windowsParsePath(path: []const u8) WindowsPath { | |
| 153 | 153 | if (path.len >= 2 and path[1] == ':') { |
| 154 | 154 | return WindowsPath { |
| 155 | 155 | .is_abs = isAbsoluteWindows(path), |
| ... | ... | @@ -248,7 +248,7 @@ test "os.path.windowsParsePath" { |
| 248 | 248 | } |
| 249 | 249 | } |
| 250 | 250 | |
| 251 | pub fn diskDesignator(path: []const u8) -> []const u8 { | |
| 251 | pub fn diskDesignator(path: []const u8) []const u8 { | |
| 252 | 252 | if (is_windows) { |
| 253 | 253 | return diskDesignatorWindows(path); |
| 254 | 254 | } else { |
| ... | ... | @@ -256,11 +256,11 @@ pub fn diskDesignator(path: []const u8) -> []const u8 { |
| 256 | 256 | } |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | pub fn diskDesignatorWindows(path: []const u8) -> []const u8 { | |
| 259 | pub fn diskDesignatorWindows(path: []const u8) []const u8 { | |
| 260 | 260 | return windowsParsePath(path).disk_designator; |
| 261 | 261 | } |
| 262 | 262 | |
| 263 | fn networkShareServersEql(ns1: []const u8, ns2: []const u8) -> bool { | |
| 263 | fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool { | |
| 264 | 264 | const sep1 = ns1[0]; |
| 265 | 265 | const sep2 = ns2[0]; |
| 266 | 266 | |
| ... | ... | @@ -271,7 +271,7 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) -> bool { |
| 271 | 271 | return asciiEqlIgnoreCase(??it1.next(), ??it2.next()); |
| 272 | 272 | } |
| 273 | 273 | |
| 274 | fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8) -> bool { | |
| 274 | fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8) bool { | |
| 275 | 275 | switch (kind) { |
| 276 | 276 | WindowsPath.Kind.None => { |
| 277 | 277 | assert(p1.len == 0); |
| ... | ... | @@ -294,14 +294,14 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8 |
| 294 | 294 | } |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | fn asciiUpper(byte: u8) -> u8 { | |
| 297 | fn asciiUpper(byte: u8) u8 { | |
| 298 | 298 | return switch (byte) { |
| 299 | 299 | 'a' ... 'z' => 'A' + (byte - 'a'), |
| 300 | 300 | else => byte, |
| 301 | 301 | }; |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) -> bool { | |
| 304 | fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool { | |
| 305 | 305 | if (s1.len != s2.len) |
| 306 | 306 | return false; |
| 307 | 307 | var i: usize = 0; |
| ... | ... | @@ -313,7 +313,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) -> bool { |
| 313 | 313 | } |
| 314 | 314 | |
| 315 | 315 | /// Converts the command line arguments into a slice and calls `resolveSlice`. |
| 316 | pub fn resolve(allocator: &Allocator, args: ...) -> %[]u8 { | |
| 316 | pub fn resolve(allocator: &Allocator, args: ...) %[]u8 { | |
| 317 | 317 | var paths: [args.len][]const u8 = undefined; |
| 318 | 318 | comptime var arg_i = 0; |
| 319 | 319 | inline while (arg_i < args.len) : (arg_i += 1) { |
| ... | ... | @@ -323,7 +323,7 @@ pub fn resolve(allocator: &Allocator, args: ...) -> %[]u8 { |
| 323 | 323 | } |
| 324 | 324 | |
| 325 | 325 | /// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`. |
| 326 | pub fn resolveSlice(allocator: &Allocator, paths: []const []const u8) -> %[]u8 { | |
| 326 | pub fn resolveSlice(allocator: &Allocator, paths: []const []const u8) %[]u8 { | |
| 327 | 327 | if (is_windows) { |
| 328 | 328 | return resolveWindows(allocator, paths); |
| 329 | 329 | } else { |
| ... | ... | @@ -337,7 +337,7 @@ pub fn resolveSlice(allocator: &Allocator, paths: []const []const u8) -> %[]u8 { |
| 337 | 337 | /// If all paths are relative it uses the current working directory as a starting point. |
| 338 | 338 | /// Each drive has its own current working directory. |
| 339 | 339 | /// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters. |
| 340 | pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8 { | |
| 340 | pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) %[]u8 { | |
| 341 | 341 | if (paths.len == 0) { |
| 342 | 342 | assert(is_windows); // resolveWindows called on non windows can't use getCwd |
| 343 | 343 | return os.getCwd(allocator); |
| ... | ... | @@ -468,7 +468,7 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8 |
| 468 | 468 | } |
| 469 | 469 | have_drive_kind = parsed_cwd.kind; |
| 470 | 470 | } |
| 471 | %defer allocator.free(result); | |
| 471 | errdefer allocator.free(result); | |
| 472 | 472 | |
| 473 | 473 | // Now we know the disk designator to use, if any, and what kind it is. And our result |
| 474 | 474 | // is big enough to append all the paths to. |
| ... | ... | @@ -520,7 +520,7 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8 |
| 520 | 520 | /// It resolves "." and "..". |
| 521 | 521 | /// The result does not have a trailing path separator. |
| 522 | 522 | /// If all paths are relative it uses the current working directory as a starting point. |
| 523 | pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) -> %[]u8 { | |
| 523 | pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) %[]u8 { | |
| 524 | 524 | if (paths.len == 0) { |
| 525 | 525 | assert(!is_windows); // resolvePosix called on windows can't use getCwd |
| 526 | 526 | return os.getCwd(allocator); |
| ... | ... | @@ -551,7 +551,7 @@ pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) -> %[]u8 { |
| 551 | 551 | mem.copy(u8, result, cwd); |
| 552 | 552 | result_index += cwd.len; |
| 553 | 553 | } |
| 554 | %defer allocator.free(result); | |
| 554 | errdefer allocator.free(result); | |
| 555 | 555 | |
| 556 | 556 | for (paths[first_index..]) |p, i| { |
| 557 | 557 | var it = mem.split(p, "/"); |
| ... | ... | @@ -648,15 +648,15 @@ test "os.path.resolvePosix" { |
| 648 | 648 | assert(mem.eql(u8, testResolvePosix([][]const u8{"/foo/tmp.3/", "../tmp.3/cycles/root.js"}), "/foo/tmp.3/cycles/root.js")); |
| 649 | 649 | } |
| 650 | 650 | |
| 651 | fn testResolveWindows(paths: []const []const u8) -> []u8 { | |
| 651 | fn testResolveWindows(paths: []const []const u8) []u8 { | |
| 652 | 652 | return resolveWindows(debug.global_allocator, paths) catch unreachable; |
| 653 | 653 | } |
| 654 | 654 | |
| 655 | fn testResolvePosix(paths: []const []const u8) -> []u8 { | |
| 655 | fn testResolvePosix(paths: []const []const u8) []u8 { | |
| 656 | 656 | return resolvePosix(debug.global_allocator, paths) catch unreachable; |
| 657 | 657 | } |
| 658 | 658 | |
| 659 | pub fn dirname(path: []const u8) -> []const u8 { | |
| 659 | pub fn dirname(path: []const u8) []const u8 { | |
| 660 | 660 | if (is_windows) { |
| 661 | 661 | return dirnameWindows(path); |
| 662 | 662 | } else { |
| ... | ... | @@ -664,7 +664,7 @@ pub fn dirname(path: []const u8) -> []const u8 { |
| 664 | 664 | } |
| 665 | 665 | } |
| 666 | 666 | |
| 667 | pub fn dirnameWindows(path: []const u8) -> []const u8 { | |
| 667 | pub fn dirnameWindows(path: []const u8) []const u8 { | |
| 668 | 668 | if (path.len == 0) |
| 669 | 669 | return path[0..0]; |
| 670 | 670 | |
| ... | ... | @@ -695,7 +695,7 @@ pub fn dirnameWindows(path: []const u8) -> []const u8 { |
| 695 | 695 | return path[0..end_index]; |
| 696 | 696 | } |
| 697 | 697 | |
| 698 | pub fn dirnamePosix(path: []const u8) -> []const u8 { | |
| 698 | pub fn dirnamePosix(path: []const u8) []const u8 { | |
| 699 | 699 | if (path.len == 0) |
| 700 | 700 | return path[0..0]; |
| 701 | 701 | |
| ... | ... | @@ -766,15 +766,15 @@ test "os.path.dirnameWindows" { |
| 766 | 766 | testDirnameWindows("foo", ""); |
| 767 | 767 | } |
| 768 | 768 | |
| 769 | fn testDirnamePosix(input: []const u8, expected_output: []const u8) { | |
| 769 | fn testDirnamePosix(input: []const u8, expected_output: []const u8) void { | |
| 770 | 770 | assert(mem.eql(u8, dirnamePosix(input), expected_output)); |
| 771 | 771 | } |
| 772 | 772 | |
| 773 | fn testDirnameWindows(input: []const u8, expected_output: []const u8) { | |
| 773 | fn testDirnameWindows(input: []const u8, expected_output: []const u8) void { | |
| 774 | 774 | assert(mem.eql(u8, dirnameWindows(input), expected_output)); |
| 775 | 775 | } |
| 776 | 776 | |
| 777 | pub fn basename(path: []const u8) -> []const u8 { | |
| 777 | pub fn basename(path: []const u8) []const u8 { | |
| 778 | 778 | if (is_windows) { |
| 779 | 779 | return basenameWindows(path); |
| 780 | 780 | } else { |
| ... | ... | @@ -782,7 +782,7 @@ pub fn basename(path: []const u8) -> []const u8 { |
| 782 | 782 | } |
| 783 | 783 | } |
| 784 | 784 | |
| 785 | pub fn basenamePosix(path: []const u8) -> []const u8 { | |
| 785 | pub fn basenamePosix(path: []const u8) []const u8 { | |
| 786 | 786 | if (path.len == 0) |
| 787 | 787 | return []u8{}; |
| 788 | 788 | |
| ... | ... | @@ -803,7 +803,7 @@ pub fn basenamePosix(path: []const u8) -> []const u8 { |
| 803 | 803 | return path[start_index + 1..end_index]; |
| 804 | 804 | } |
| 805 | 805 | |
| 806 | pub fn basenameWindows(path: []const u8) -> []const u8 { | |
| 806 | pub fn basenameWindows(path: []const u8) []const u8 { | |
| 807 | 807 | if (path.len == 0) |
| 808 | 808 | return []u8{}; |
| 809 | 809 | |
| ... | ... | @@ -874,15 +874,15 @@ test "os.path.basename" { |
| 874 | 874 | testBasenameWindows("file:stream", "file:stream"); |
| 875 | 875 | } |
| 876 | 876 | |
| 877 | fn testBasename(input: []const u8, expected_output: []const u8) { | |
| 877 | fn testBasename(input: []const u8, expected_output: []const u8) void { | |
| 878 | 878 | assert(mem.eql(u8, basename(input), expected_output)); |
| 879 | 879 | } |
| 880 | 880 | |
| 881 | fn testBasenamePosix(input: []const u8, expected_output: []const u8) { | |
| 881 | fn testBasenamePosix(input: []const u8, expected_output: []const u8) void { | |
| 882 | 882 | assert(mem.eql(u8, basenamePosix(input), expected_output)); |
| 883 | 883 | } |
| 884 | 884 | |
| 885 | fn testBasenameWindows(input: []const u8, expected_output: []const u8) { | |
| 885 | fn testBasenameWindows(input: []const u8, expected_output: []const u8) void { | |
| 886 | 886 | assert(mem.eql(u8, basenameWindows(input), expected_output)); |
| 887 | 887 | } |
| 888 | 888 | |
| ... | ... | @@ -890,7 +890,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) { |
| 890 | 890 | /// resolve to the same path (after calling `resolve` on each), a zero-length |
| 891 | 891 | /// string is returned. |
| 892 | 892 | /// On Windows this canonicalizes the drive to a capital letter and paths to `\\`. |
| 893 | pub fn relative(allocator: &Allocator, from: []const u8, to: []const u8) -> %[]u8 { | |
| 893 | pub fn relative(allocator: &Allocator, from: []const u8, to: []const u8) %[]u8 { | |
| 894 | 894 | if (is_windows) { |
| 895 | 895 | return relativeWindows(allocator, from, to); |
| 896 | 896 | } else { |
| ... | ... | @@ -898,7 +898,7 @@ pub fn relative(allocator: &Allocator, from: []const u8, to: []const u8) -> %[]u |
| 898 | 898 | } |
| 899 | 899 | } |
| 900 | 900 | |
| 901 | pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8) -> %[]u8 { | |
| 901 | pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8) %[]u8 { | |
| 902 | 902 | const resolved_from = try resolveWindows(allocator, [][]const u8{from}); |
| 903 | 903 | defer allocator.free(resolved_from); |
| 904 | 904 | |
| ... | ... | @@ -943,7 +943,7 @@ pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8) |
| 943 | 943 | } |
| 944 | 944 | const up_index_end = up_count * "..\\".len; |
| 945 | 945 | const result = try allocator.alloc(u8, up_index_end + to_rest.len); |
| 946 | %defer allocator.free(result); | |
| 946 | errdefer allocator.free(result); | |
| 947 | 947 | |
| 948 | 948 | var result_index: usize = 0; |
| 949 | 949 | while (result_index < up_index_end) { |
| ... | ... | @@ -971,7 +971,7 @@ pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8) |
| 971 | 971 | return []u8{}; |
| 972 | 972 | } |
| 973 | 973 | |
| 974 | pub fn relativePosix(allocator: &Allocator, from: []const u8, to: []const u8) -> %[]u8 { | |
| 974 | pub fn relativePosix(allocator: &Allocator, from: []const u8, to: []const u8) %[]u8 { | |
| 975 | 975 | const resolved_from = try resolvePosix(allocator, [][]const u8{from}); |
| 976 | 976 | defer allocator.free(resolved_from); |
| 977 | 977 | |
| ... | ... | @@ -993,7 +993,7 @@ pub fn relativePosix(allocator: &Allocator, from: []const u8, to: []const u8) -> |
| 993 | 993 | } |
| 994 | 994 | const up_index_end = up_count * "../".len; |
| 995 | 995 | const result = try allocator.alloc(u8, up_index_end + to_rest.len); |
| 996 | %defer allocator.free(result); | |
| 996 | errdefer allocator.free(result); | |
| 997 | 997 | |
| 998 | 998 | var result_index: usize = 0; |
| 999 | 999 | while (result_index < up_index_end) { |
| ... | ... | @@ -1056,12 +1056,12 @@ test "os.path.relative" { |
| 1056 | 1056 | testRelativePosix("/baz", "/baz-quux", "../baz-quux"); |
| 1057 | 1057 | } |
| 1058 | 1058 | |
| 1059 | fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) { | |
| 1059 | fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) void { | |
| 1060 | 1060 | const result = relativePosix(debug.global_allocator, from, to) catch unreachable; |
| 1061 | 1061 | assert(mem.eql(u8, result, expected_output)); |
| 1062 | 1062 | } |
| 1063 | 1063 | |
| 1064 | fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) { | |
| 1064 | fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) void { | |
| 1065 | 1065 | const result = relativeWindows(debug.global_allocator, from, to) catch unreachable; |
| 1066 | 1066 | assert(mem.eql(u8, result, expected_output)); |
| 1067 | 1067 | } |
| ... | ... | @@ -1077,7 +1077,7 @@ error InputOutput; |
| 1077 | 1077 | /// Expands all symbolic links and resolves references to `.`, `..`, and |
| 1078 | 1078 | /// extra `/` characters in ::pathname. |
| 1079 | 1079 | /// Caller must deallocate result. |
| 1080 | pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { | |
| 1080 | pub fn real(allocator: &Allocator, pathname: []const u8) %[]u8 { | |
| 1081 | 1081 | switch (builtin.os) { |
| 1082 | 1082 | Os.windows => { |
| 1083 | 1083 | const pathname_buf = try allocator.alloc(u8, pathname.len + 1); |
| ... | ... | @@ -1100,7 +1100,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { |
| 1100 | 1100 | } |
| 1101 | 1101 | defer os.close(h_file); |
| 1102 | 1102 | var buf = try allocator.alloc(u8, 256); |
| 1103 | %defer allocator.free(buf); | |
| 1103 | errdefer allocator.free(buf); | |
| 1104 | 1104 | while (true) { |
| 1105 | 1105 | const buf_len = math.cast(windows.DWORD, buf.len) catch return error.NameTooLong; |
| 1106 | 1106 | const result = windows.GetFinalPathNameByHandleA(h_file, buf.ptr, buf_len, windows.VOLUME_NAME_DOS); |
| ... | ... | @@ -1144,7 +1144,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { |
| 1144 | 1144 | defer allocator.free(pathname_buf); |
| 1145 | 1145 | |
| 1146 | 1146 | const result_buf = try allocator.alloc(u8, posix.PATH_MAX); |
| 1147 | %defer allocator.free(result_buf); | |
| 1147 | errdefer allocator.free(result_buf); | |
| 1148 | 1148 | |
| 1149 | 1149 | mem.copy(u8, pathname_buf, pathname); |
| 1150 | 1150 | pathname_buf[pathname.len] = 0; |
std/os/windows/index.zig+44-37| ... | ... | @@ -1,97 +1,100 @@ |
| 1 | 1 | pub const ERROR = @import("error.zig"); |
| 2 | 2 | |
| 3 | 3 | pub extern "advapi32" stdcallcc fn CryptAcquireContextA(phProv: &HCRYPTPROV, pszContainer: ?LPCSTR, |
| 4 | pszProvider: ?LPCSTR, dwProvType: DWORD, dwFlags: DWORD) -> BOOL; | |
| 4 | pszProvider: ?LPCSTR, dwProvType: DWORD, dwFlags: DWORD) BOOL; | |
| 5 | 5 | |
| 6 | pub extern "advapi32" stdcallcc fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL; | |
| 6 | pub extern "advapi32" stdcallcc fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) BOOL; | |
| 7 | 7 | |
| 8 | pub extern "advapi32" stdcallcc fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: &BYTE) -> BOOL; | |
| 8 | pub extern "advapi32" stdcallcc fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: &BYTE) BOOL; | |
| 9 | 9 | |
| 10 | 10 | |
| 11 | pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) -> BOOL; | |
| 11 | pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) BOOL; | |
| 12 | 12 | |
| 13 | 13 | pub extern "kernel32" stdcallcc fn CreateDirectoryA(lpPathName: LPCSTR, |
| 14 | lpSecurityAttributes: ?&SECURITY_ATTRIBUTES) -> BOOL; | |
| 14 | lpSecurityAttributes: ?&SECURITY_ATTRIBUTES) BOOL; | |
| 15 | 15 | |
| 16 | 16 | pub extern "kernel32" stdcallcc fn CreateFileA(lpFileName: LPCSTR, dwDesiredAccess: DWORD, |
| 17 | 17 | dwShareMode: DWORD, lpSecurityAttributes: ?LPSECURITY_ATTRIBUTES, dwCreationDisposition: DWORD, |
| 18 | dwFlagsAndAttributes: DWORD, hTemplateFile: ?HANDLE) -> HANDLE; | |
| 18 | dwFlagsAndAttributes: DWORD, hTemplateFile: ?HANDLE) HANDLE; | |
| 19 | 19 | |
| 20 | 20 | pub extern "kernel32" stdcallcc fn CreatePipe(hReadPipe: &HANDLE, hWritePipe: &HANDLE, |
| 21 | lpPipeAttributes: &const SECURITY_ATTRIBUTES, nSize: DWORD) -> BOOL; | |
| 21 | lpPipeAttributes: &const SECURITY_ATTRIBUTES, nSize: DWORD) BOOL; | |
| 22 | 22 | |
| 23 | 23 | pub extern "kernel32" stdcallcc fn CreateProcessA(lpApplicationName: ?LPCSTR, lpCommandLine: LPSTR, |
| 24 | 24 | lpProcessAttributes: ?&SECURITY_ATTRIBUTES, lpThreadAttributes: ?&SECURITY_ATTRIBUTES, bInheritHandles: BOOL, |
| 25 | 25 | dwCreationFlags: DWORD, lpEnvironment: ?LPVOID, lpCurrentDirectory: ?LPCSTR, lpStartupInfo: &STARTUPINFOA, |
| 26 | lpProcessInformation: &PROCESS_INFORMATION) -> BOOL; | |
| 26 | lpProcessInformation: &PROCESS_INFORMATION) BOOL; | |
| 27 | 27 | |
| 28 | 28 | pub extern "kernel32" stdcallcc fn CreateSymbolicLinkA(lpSymlinkFileName: LPCSTR, lpTargetFileName: LPCSTR, |
| 29 | dwFlags: DWORD) -> BOOLEAN; | |
| 29 | dwFlags: DWORD) BOOLEAN; | |
| 30 | 30 | |
| 31 | pub extern "kernel32" stdcallcc fn DeleteFileA(lpFileName: LPCSTR) -> BOOL; | |
| 31 | pub extern "kernel32" stdcallcc fn DeleteFileA(lpFileName: LPCSTR) BOOL; | |
| 32 | 32 | |
| 33 | pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) -> noreturn; | |
| 33 | pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) noreturn; | |
| 34 | 34 | |
| 35 | pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: LPCH) -> BOOL; | |
| 35 | pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: LPCH) BOOL; | |
| 36 | 36 | |
| 37 | pub extern "kernel32" stdcallcc fn GetCommandLineA() -> LPSTR; | |
| 37 | pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR; | |
| 38 | 38 | |
| 39 | pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: &DWORD) -> BOOL; | |
| 39 | pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: &DWORD) BOOL; | |
| 40 | 40 | |
| 41 | pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPSTR) -> DWORD; | |
| 41 | pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPSTR) DWORD; | |
| 42 | 42 | |
| 43 | pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() -> ?LPCH; | |
| 43 | pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?LPCH; | |
| 44 | 44 | |
| 45 | pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) -> DWORD; | |
| 45 | pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD; | |
| 46 | 46 | |
| 47 | pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: &DWORD) -> BOOL; | |
| 47 | pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: &DWORD) BOOL; | |
| 48 | 48 | |
| 49 | pub extern "kernel32" stdcallcc fn GetFileSizeEx(hFile: HANDLE, lpFileSize: &LARGE_INTEGER) -> BOOL; | |
| 49 | pub extern "kernel32" stdcallcc fn GetFileSizeEx(hFile: HANDLE, lpFileSize: &LARGE_INTEGER) BOOL; | |
| 50 | 50 | |
| 51 | pub extern "kernel32" stdcallcc fn GetModuleFileNameA(hModule: ?HMODULE, lpFilename: LPSTR, nSize: DWORD) -> DWORD; | |
| 51 | pub extern "kernel32" stdcallcc fn GetModuleFileNameA(hModule: ?HMODULE, lpFilename: LPSTR, nSize: DWORD) DWORD; | |
| 52 | 52 | |
| 53 | pub extern "kernel32" stdcallcc fn GetLastError() -> DWORD; | |
| 53 | pub extern "kernel32" stdcallcc fn GetLastError() DWORD; | |
| 54 | 54 | |
| 55 | 55 | pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(in_hFile: HANDLE, |
| 56 | 56 | in_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, out_lpFileInformation: &c_void, |
| 57 | in_dwBufferSize: DWORD) -> BOOL; | |
| 57 | in_dwBufferSize: DWORD) BOOL; | |
| 58 | 58 | |
| 59 | 59 | pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleA(hFile: HANDLE, lpszFilePath: LPSTR, |
| 60 | cchFilePath: DWORD, dwFlags: DWORD) -> DWORD; | |
| 60 | cchFilePath: DWORD, dwFlags: DWORD) DWORD; | |
| 61 | 61 | |
| 62 | pub extern "kernel32" stdcallcc fn GetProcessHeap() -> ?HANDLE; | |
| 62 | pub extern "kernel32" stdcallcc fn GetProcessHeap() ?HANDLE; | |
| 63 | 63 | |
| 64 | pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) -> ?HANDLE; | |
| 64 | pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) ?HANDLE; | |
| 65 | 65 | |
| 66 | pub extern "kernel32" stdcallcc fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> ?LPVOID; | |
| 66 | pub extern "kernel32" stdcallcc fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) ?LPVOID; | |
| 67 | 67 | |
| 68 | pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; | |
| 68 | pub extern "kernel32" stdcallcc fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) BOOL; | |
| 69 | 69 | |
| 70 | 70 | pub extern "kernel32" stdcallcc fn MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, |
| 71 | dwFlags: DWORD) -> BOOL; | |
| 71 | dwFlags: DWORD) BOOL; | |
| 72 | 72 | |
| 73 | 73 | pub extern "kernel32" stdcallcc fn ReadFile(in_hFile: HANDLE, out_lpBuffer: LPVOID, |
| 74 | 74 | in_nNumberOfBytesToRead: DWORD, out_lpNumberOfBytesRead: &DWORD, |
| 75 | in_out_lpOverlapped: ?&OVERLAPPED) -> BOOL; | |
| 75 | in_out_lpOverlapped: ?&OVERLAPPED) BOOL; | |
| 76 | 76 | |
| 77 | pub extern "kernel32" stdcallcc fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) -> BOOL; | |
| 77 | pub extern "kernel32" stdcallcc fn SetFilePointerEx(in_fFile: HANDLE, in_liDistanceToMove: LARGE_INTEGER, | |
| 78 | out_opt_ldNewFilePointer: ?&LARGE_INTEGER, in_dwMoveMethod: DWORD) BOOL; | |
| 78 | 79 | |
| 79 | pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD); | |
| 80 | pub extern "kernel32" stdcallcc fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) BOOL; | |
| 80 | 81 | |
| 81 | pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL; | |
| 82 | pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void; | |
| 82 | 83 | |
| 83 | pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; | |
| 84 | pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL; | |
| 85 | ||
| 86 | pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD; | |
| 84 | 87 | |
| 85 | 88 | pub extern "kernel32" stdcallcc fn WriteFile(in_hFile: HANDLE, in_lpBuffer: &const c_void, |
| 86 | 89 | in_nNumberOfBytesToWrite: DWORD, out_lpNumberOfBytesWritten: ?&DWORD, |
| 87 | in_out_lpOverlapped: ?&OVERLAPPED) -> BOOL; | |
| 90 | in_out_lpOverlapped: ?&OVERLAPPED) BOOL; | |
| 88 | 91 | |
| 89 | 92 | //TODO: call unicode versions instead of relying on ANSI code page |
| 90 | pub extern "kernel32" stdcallcc fn LoadLibraryA(lpLibFileName: LPCSTR) -> ?HMODULE; | |
| 93 | pub extern "kernel32" stdcallcc fn LoadLibraryA(lpLibFileName: LPCSTR) ?HMODULE; | |
| 91 | 94 | |
| 92 | pub extern "kernel32" stdcallcc fn FreeLibrary(hModule: HMODULE) -> BOOL; | |
| 95 | pub extern "kernel32" stdcallcc fn FreeLibrary(hModule: HMODULE) BOOL; | |
| 93 | 96 | |
| 94 | pub extern "user32" stdcallcc fn MessageBoxA(hWnd: ?HANDLE, lpText: ?LPCTSTR, lpCaption: ?LPCTSTR, uType: UINT) -> c_int; | |
| 97 | pub extern "user32" stdcallcc fn MessageBoxA(hWnd: ?HANDLE, lpText: ?LPCTSTR, lpCaption: ?LPCTSTR, uType: UINT) c_int; | |
| 95 | 98 | |
| 96 | 99 | pub const PROV_RSA_FULL = 1; |
| 97 | 100 | |
| ... | ... | @@ -289,3 +292,7 @@ pub const MOVEFILE_DELAY_UNTIL_REBOOT = 4; |
| 289 | 292 | pub const MOVEFILE_FAIL_IF_NOT_TRACKABLE = 32; |
| 290 | 293 | pub const MOVEFILE_REPLACE_EXISTING = 1; |
| 291 | 294 | pub const MOVEFILE_WRITE_THROUGH = 8; |
| 295 | ||
| 296 | pub const FILE_BEGIN = 0; | |
| 297 | pub const FILE_CURRENT = 1; | |
| 298 | pub const FILE_END = 2; |
std/os/windows/util.zig+10-10| ... | ... | @@ -10,7 +10,7 @@ error WaitAbandoned; |
| 10 | 10 | error WaitTimeOut; |
| 11 | 11 | error Unexpected; |
| 12 | 12 | |
| 13 | pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) -> %void { | |
| 13 | pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) %void { | |
| 14 | 14 | const result = windows.WaitForSingleObject(handle, milliseconds); |
| 15 | 15 | return switch (result) { |
| 16 | 16 | windows.WAIT_ABANDONED => error.WaitAbandoned, |
| ... | ... | @@ -26,7 +26,7 @@ pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) -> |
| 26 | 26 | }; |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | pub fn windowsClose(handle: windows.HANDLE) { | |
| 29 | pub fn windowsClose(handle: windows.HANDLE) void { | |
| 30 | 30 | assert(windows.CloseHandle(handle) != 0); |
| 31 | 31 | } |
| 32 | 32 | |
| ... | ... | @@ -35,7 +35,7 @@ error OperationAborted; |
| 35 | 35 | error IoPending; |
| 36 | 36 | error BrokenPipe; |
| 37 | 37 | |
| 38 | pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) -> %void { | |
| 38 | pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) %void { | |
| 39 | 39 | if (windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null) == 0) { |
| 40 | 40 | const err = windows.GetLastError(); |
| 41 | 41 | return switch (err) { |
| ... | ... | @@ -50,7 +50,7 @@ pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) -> %void { |
| 50 | 50 | } |
| 51 | 51 | } |
| 52 | 52 | |
| 53 | pub fn windowsIsTty(handle: windows.HANDLE) -> bool { | |
| 53 | pub fn windowsIsTty(handle: windows.HANDLE) bool { | |
| 54 | 54 | if (windowsIsCygwinPty(handle)) |
| 55 | 55 | return true; |
| 56 | 56 | |
| ... | ... | @@ -58,7 +58,7 @@ pub fn windowsIsTty(handle: windows.HANDLE) -> bool { |
| 58 | 58 | return windows.GetConsoleMode(handle, &out) != 0; |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | pub fn windowsIsCygwinPty(handle: windows.HANDLE) -> bool { | |
| 61 | pub fn windowsIsCygwinPty(handle: windows.HANDLE) bool { | |
| 62 | 62 | const size = @sizeOf(windows.FILE_NAME_INFO); |
| 63 | 63 | var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = []u8{0} ** (size + windows.MAX_PATH); |
| 64 | 64 | |
| ... | ... | @@ -83,7 +83,7 @@ error PipeBusy; |
| 83 | 83 | /// size buffer is too small, and the provided allocator is null, ::error.NameTooLong is returned. |
| 84 | 84 | /// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. |
| 85 | 85 | pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_mode: windows.DWORD, |
| 86 | creation_disposition: windows.DWORD, flags_and_attrs: windows.DWORD, allocator: ?&mem.Allocator) -> %windows.HANDLE | |
| 86 | creation_disposition: windows.DWORD, flags_and_attrs: windows.DWORD, allocator: ?&mem.Allocator) %windows.HANDLE | |
| 87 | 87 | { |
| 88 | 88 | var stack_buf: [os.max_noalloc_path_len]u8 = undefined; |
| 89 | 89 | var path0: []u8 = undefined; |
| ... | ... | @@ -120,7 +120,7 @@ pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_m |
| 120 | 120 | } |
| 121 | 121 | |
| 122 | 122 | /// Caller must free result. |
| 123 | pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) -> %[]u8 { | |
| 123 | pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) %[]u8 { | |
| 124 | 124 | // count bytes needed |
| 125 | 125 | const bytes_needed = x: { |
| 126 | 126 | var bytes_needed: usize = 1; // 1 for the final null byte |
| ... | ... | @@ -133,7 +133,7 @@ pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) |
| 133 | 133 | break :x bytes_needed; |
| 134 | 134 | }; |
| 135 | 135 | const result = try allocator.alloc(u8, bytes_needed); |
| 136 | %defer allocator.free(result); | |
| 136 | errdefer allocator.free(result); | |
| 137 | 137 | |
| 138 | 138 | var it = env_map.iterator(); |
| 139 | 139 | var i: usize = 0; |
| ... | ... | @@ -152,13 +152,13 @@ pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) |
| 152 | 152 | } |
| 153 | 153 | |
| 154 | 154 | error DllNotFound; |
| 155 | pub fn windowsLoadDll(allocator: &mem.Allocator, dll_path: []const u8) -> %windows.HMODULE { | |
| 155 | pub fn windowsLoadDll(allocator: &mem.Allocator, dll_path: []const u8) %windows.HMODULE { | |
| 156 | 156 | const padded_buff = try cstr.addNullByte(allocator, dll_path); |
| 157 | 157 | defer allocator.free(padded_buff); |
| 158 | 158 | return windows.LoadLibraryA(padded_buff.ptr) ?? error.DllNotFound; |
| 159 | 159 | } |
| 160 | 160 | |
| 161 | pub fn windowsUnloadDll(hModule: windows.HMODULE) { | |
| 161 | pub fn windowsUnloadDll(hModule: windows.HMODULE) void { | |
| 162 | 162 | assert(windows.FreeLibrary(hModule)!= 0); |
| 163 | 163 | } |
| 164 | 164 |
std/os/zen.zig+12-12| ... | ... | @@ -21,28 +21,28 @@ pub const SYS_createThread = 5; |
| 21 | 21 | //// Syscalls //// |
| 22 | 22 | //////////////////// |
| 23 | 23 | |
| 24 | pub fn exit(status: i32) -> noreturn { | |
| 24 | pub fn exit(status: i32) noreturn { | |
| 25 | 25 | _ = syscall1(SYS_exit, @bitCast(usize, isize(status))); |
| 26 | 26 | unreachable; |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | pub fn createMailbox(id: u16) { | |
| 29 | pub fn createMailbox(id: u16) void { | |
| 30 | 30 | _ = syscall1(SYS_createMailbox, id); |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | pub fn send(mailbox_id: u16, data: usize) { | |
| 33 | pub fn send(mailbox_id: u16, data: usize) void { | |
| 34 | 34 | _ = syscall2(SYS_send, mailbox_id, data); |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | pub fn receive(mailbox_id: u16) -> usize { | |
| 37 | pub fn receive(mailbox_id: u16) usize { | |
| 38 | 38 | return syscall1(SYS_receive, mailbox_id); |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | pub fn map(v_addr: usize, p_addr: usize, size: usize, writable: bool) -> bool { | |
| 41 | pub fn map(v_addr: usize, p_addr: usize, size: usize, writable: bool) bool { | |
| 42 | 42 | return syscall4(SYS_map, v_addr, p_addr, size, usize(writable)) != 0; |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | pub fn createThread(function: fn()) -> u16 { | |
| 45 | pub fn createThread(function: fn()) u16 { | |
| 46 | 46 | return u16(syscall1(SYS_createThread, @ptrToInt(function))); |
| 47 | 47 | } |
| 48 | 48 | |
| ... | ... | @@ -51,20 +51,20 @@ pub fn createThread(function: fn()) -> u16 { |
| 51 | 51 | //// Syscall stubs //// |
| 52 | 52 | ///////////////////////// |
| 53 | 53 | |
| 54 | pub inline fn syscall0(number: usize) -> usize { | |
| 54 | pub inline fn syscall0(number: usize) usize { | |
| 55 | 55 | return asm volatile ("int $0x80" |
| 56 | 56 | : [ret] "={eax}" (-> usize) |
| 57 | 57 | : [number] "{eax}" (number)); |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | pub inline fn syscall1(number: usize, arg1: usize) -> usize { | |
| 60 | pub inline fn syscall1(number: usize, arg1: usize) usize { | |
| 61 | 61 | return asm volatile ("int $0x80" |
| 62 | 62 | : [ret] "={eax}" (-> usize) |
| 63 | 63 | : [number] "{eax}" (number), |
| 64 | 64 | [arg1] "{ecx}" (arg1)); |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { | |
| 67 | pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) usize { | |
| 68 | 68 | return asm volatile ("int $0x80" |
| 69 | 69 | : [ret] "={eax}" (-> usize) |
| 70 | 70 | : [number] "{eax}" (number), |
| ... | ... | @@ -72,7 +72,7 @@ pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) -> usize { |
| 72 | 72 | [arg2] "{edx}" (arg2)); |
| 73 | 73 | } |
| 74 | 74 | |
| 75 | pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize { | |
| 75 | pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize { | |
| 76 | 76 | return asm volatile ("int $0x80" |
| 77 | 77 | : [ret] "={eax}" (-> usize) |
| 78 | 78 | : [number] "{eax}" (number), |
| ... | ... | @@ -81,7 +81,7 @@ pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> |
| 81 | 81 | [arg3] "{ebx}" (arg3)); |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | pub inline fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) -> usize { | |
| 84 | pub inline fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { | |
| 85 | 85 | return asm volatile ("int $0x80" |
| 86 | 86 | : [ret] "={eax}" (-> usize) |
| 87 | 87 | : [number] "{eax}" (number), |
| ... | ... | @@ -92,7 +92,7 @@ pub inline fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg |
| 92 | 92 | } |
| 93 | 93 | |
| 94 | 94 | pub inline fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, |
| 95 | arg4: usize, arg5: usize) -> usize | |
| 95 | arg4: usize, arg5: usize) usize | |
| 96 | 96 | { |
| 97 | 97 | return asm volatile ("int $0x80" |
| 98 | 98 | : [ret] "={eax}" (-> usize) |
std/rand.zig+9-9| ... | ... | @@ -28,14 +28,14 @@ pub const Rand = struct { |
| 28 | 28 | rng: Rng, |
| 29 | 29 | |
| 30 | 30 | /// Initialize random state with the given seed. |
| 31 | pub fn init(seed: usize) -> Rand { | |
| 31 | pub fn init(seed: usize) Rand { | |
| 32 | 32 | return Rand { |
| 33 | 33 | .rng = Rng.init(seed), |
| 34 | 34 | }; |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | 37 | /// Get an integer or boolean with random bits. |
| 38 | pub fn scalar(r: &Rand, comptime T: type) -> T { | |
| 38 | pub fn scalar(r: &Rand, comptime T: type) T { | |
| 39 | 39 | if (T == usize) { |
| 40 | 40 | return r.rng.get(); |
| 41 | 41 | } else if (T == bool) { |
| ... | ... | @@ -48,7 +48,7 @@ pub const Rand = struct { |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | /// Fill `buf` with randomness. |
| 51 | pub fn fillBytes(r: &Rand, buf: []u8) { | |
| 51 | pub fn fillBytes(r: &Rand, buf: []u8) void { | |
| 52 | 52 | var bytes_left = buf.len; |
| 53 | 53 | while (bytes_left >= @sizeOf(usize)) { |
| 54 | 54 | mem.writeInt(buf[buf.len - bytes_left..], r.rng.get(), builtin.Endian.Little); |
| ... | ... | @@ -66,7 +66,7 @@ pub const Rand = struct { |
| 66 | 66 | |
| 67 | 67 | /// Get a random unsigned integer with even distribution between `start` |
| 68 | 68 | /// inclusive and `end` exclusive. |
| 69 | pub fn range(r: &Rand, comptime T: type, start: T, end: T) -> T { | |
| 69 | pub fn range(r: &Rand, comptime T: type, start: T, end: T) T { | |
| 70 | 70 | assert(start <= end); |
| 71 | 71 | if (T.is_signed) { |
| 72 | 72 | const uint = @IntType(false, T.bit_count); |
| ... | ... | @@ -108,7 +108,7 @@ pub const Rand = struct { |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | 110 | /// Get a floating point value in the range 0.0..1.0. |
| 111 | pub fn float(r: &Rand, comptime T: type) -> T { | |
| 111 | pub fn float(r: &Rand, comptime T: type) T { | |
| 112 | 112 | // TODO Implement this way instead: |
| 113 | 113 | // const int = @int_type(false, @sizeOf(T) * 8); |
| 114 | 114 | // const mask = ((1 << @float_mantissa_bit_count(T)) - 1); |
| ... | ... | @@ -132,7 +132,7 @@ fn MersenneTwister( |
| 132 | 132 | comptime u: math.Log2Int(int), comptime d: int, |
| 133 | 133 | comptime s: math.Log2Int(int), comptime b: int, |
| 134 | 134 | comptime t: math.Log2Int(int), comptime c: int, |
| 135 | comptime l: math.Log2Int(int), comptime f: int) -> type | |
| 135 | comptime l: math.Log2Int(int), comptime f: int) type | |
| 136 | 136 | { |
| 137 | 137 | return struct { |
| 138 | 138 | const Self = this; |
| ... | ... | @@ -140,7 +140,7 @@ fn MersenneTwister( |
| 140 | 140 | array: [n]int, |
| 141 | 141 | index: usize, |
| 142 | 142 | |
| 143 | pub fn init(seed: int) -> Self { | |
| 143 | pub fn init(seed: int) Self { | |
| 144 | 144 | var mt = Self { |
| 145 | 145 | .array = undefined, |
| 146 | 146 | .index = n, |
| ... | ... | @@ -156,7 +156,7 @@ fn MersenneTwister( |
| 156 | 156 | return mt; |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | pub fn get(mt: &Self) -> int { | |
| 159 | pub fn get(mt: &Self) int { | |
| 160 | 160 | const mag01 = []int{0, a}; |
| 161 | 161 | const LM: int = (1 << r) - 1; |
| 162 | 162 | const UM = ~LM; |
| ... | ... | @@ -224,7 +224,7 @@ test "rand.Rand.range" { |
| 224 | 224 | testRange(&r, 10, 14); |
| 225 | 225 | } |
| 226 | 226 | |
| 227 | fn testRange(r: &Rand, start: i32, end: i32) { | |
| 227 | fn testRange(r: &Rand, start: i32, end: i32) void { | |
| 228 | 228 | const count = usize(end - start); |
| 229 | 229 | var values_buffer = []bool{false} ** 20; |
| 230 | 230 | const values = values_buffer[0..count]; |
std/sort.zig+31-31| ... | ... | @@ -5,7 +5,7 @@ const math = std.math; |
| 5 | 5 | const builtin = @import("builtin"); |
| 6 | 6 | |
| 7 | 7 | /// Stable in-place sort. O(n) best case, O(pow(n, 2)) worst case. O(1) memory (no allocator required). |
| 8 | pub fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)->bool) { | |
| 8 | pub fn insertionSort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void { | |
| 9 | 9 | {var i: usize = 1; while (i < items.len) : (i += 1) { |
| 10 | 10 | const x = items[i]; |
| 11 | 11 | var j: usize = i; |
| ... | ... | @@ -20,11 +20,11 @@ const Range = struct { |
| 20 | 20 | start: usize, |
| 21 | 21 | end: usize, |
| 22 | 22 | |
| 23 | fn init(start: usize, end: usize) -> Range { | |
| 23 | fn init(start: usize, end: usize) Range { | |
| 24 | 24 | return Range { .start = start, .end = end }; |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | fn length(self: &const Range) -> usize { | |
| 27 | fn length(self: &const Range) usize { | |
| 28 | 28 | return self.end - self.start; |
| 29 | 29 | } |
| 30 | 30 | }; |
| ... | ... | @@ -39,7 +39,7 @@ const Iterator = struct { |
| 39 | 39 | decimal_step: usize, |
| 40 | 40 | numerator_step: usize, |
| 41 | 41 | |
| 42 | fn init(size2: usize, min_level: usize) -> Iterator { | |
| 42 | fn init(size2: usize, min_level: usize) Iterator { | |
| 43 | 43 | const power_of_two = math.floorPowerOfTwo(usize, size2); |
| 44 | 44 | const denominator = power_of_two / min_level; |
| 45 | 45 | return Iterator { |
| ... | ... | @@ -53,12 +53,12 @@ const Iterator = struct { |
| 53 | 53 | }; |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | fn begin(self: &Iterator) { | |
| 56 | fn begin(self: &Iterator) void { | |
| 57 | 57 | self.numerator = 0; |
| 58 | 58 | self.decimal = 0; |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | fn nextRange(self: &Iterator) -> Range { | |
| 61 | fn nextRange(self: &Iterator) Range { | |
| 62 | 62 | const start = self.decimal; |
| 63 | 63 | |
| 64 | 64 | self.decimal += self.decimal_step; |
| ... | ... | @@ -71,11 +71,11 @@ const Iterator = struct { |
| 71 | 71 | return Range {.start = start, .end = self.decimal}; |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | fn finished(self: &Iterator) -> bool { | |
| 74 | fn finished(self: &Iterator) bool { | |
| 75 | 75 | return self.decimal >= self.size; |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | fn nextLevel(self: &Iterator) -> bool { | |
| 78 | fn nextLevel(self: &Iterator) bool { | |
| 79 | 79 | self.decimal_step += self.decimal_step; |
| 80 | 80 | self.numerator_step += self.numerator_step; |
| 81 | 81 | if (self.numerator_step >= self.denominator) { |
| ... | ... | @@ -86,7 +86,7 @@ const Iterator = struct { |
| 86 | 86 | return (self.decimal_step < self.size); |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | fn length(self: &Iterator) -> usize { | |
| 89 | fn length(self: &Iterator) usize { | |
| 90 | 90 | return self.decimal_step; |
| 91 | 91 | } |
| 92 | 92 | }; |
| ... | ... | @@ -100,7 +100,7 @@ const Pull = struct { |
| 100 | 100 | |
| 101 | 101 | /// Stable in-place sort. O(n) best case, O(n*log(n)) worst case and average case. O(1) memory (no allocator required). |
| 102 | 102 | /// Currently implemented as block sort. |
| 103 | pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)->bool) { | |
| 103 | pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) void { | |
| 104 | 104 | // Implementation ported from https://github.com/BonzaiThePenguin/WikiSort/blob/master/WikiSort.c |
| 105 | 105 | var cache: [512]T = undefined; |
| 106 | 106 | |
| ... | ... | @@ -709,7 +709,7 @@ pub fn sort(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &cons |
| 709 | 709 | } |
| 710 | 710 | |
| 711 | 711 | // merge operation without a buffer |
| 712 | fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T,&const T)->bool) { | |
| 712 | fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const Range, lessThan: fn(&const T,&const T)bool) void { | |
| 713 | 713 | if (A_arg.length() == 0 or B_arg.length() == 0) return; |
| 714 | 714 | |
| 715 | 715 | // this just repeatedly binary searches into B and rotates A into position. |
| ... | ... | @@ -751,7 +751,7 @@ fn mergeInPlace(comptime T: type, items: []T, A_arg: &const Range, B_arg: &const |
| 751 | 751 | } |
| 752 | 752 | |
| 753 | 753 | // merge operation using an internal buffer |
| 754 | fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)->bool, buffer: &const Range) { | |
| 754 | fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, buffer: &const Range) void { | |
| 755 | 755 | // whenever we find a value to add to the final array, swap it with the value that's already in that spot |
| 756 | 756 | // when this algorithm is finished, 'buffer' will contain its original contents, but in a different order |
| 757 | 757 | var A_count: usize = 0; |
| ... | ... | @@ -778,7 +778,7 @@ fn mergeInternal(comptime T: type, items: []T, A: &const Range, B: &const Range, |
| 778 | 778 | blockSwap(T, items, buffer.start + A_count, A.start + insert, A.length() - A_count); |
| 779 | 779 | } |
| 780 | 780 | |
| 781 | fn blockSwap(comptime T: type, items: []T, start1: usize, start2: usize, block_size: usize) { | |
| 781 | fn blockSwap(comptime T: type, items: []T, start1: usize, start2: usize, block_size: usize) void { | |
| 782 | 782 | var index: usize = 0; |
| 783 | 783 | while (index < block_size) : (index += 1) { |
| 784 | 784 | mem.swap(T, &items[start1 + index], &items[start2 + index]); |
| ... | ... | @@ -787,7 +787,7 @@ fn blockSwap(comptime T: type, items: []T, start1: usize, start2: usize, block_s |
| 787 | 787 | |
| 788 | 788 | // combine a linear search with a binary search to reduce the number of comparisons in situations |
| 789 | 789 | // where have some idea as to how many unique values there are and where the next value might be |
| 790 | fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)->bool, unique: usize) -> usize { | |
| 790 | fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 791 | 791 | if (range.length() == 0) return range.start; |
| 792 | 792 | const skip = math.max(range.length()/unique, usize(1)); |
| 793 | 793 | |
| ... | ... | @@ -801,7 +801,7 @@ fn findFirstForward(comptime T: type, items: []T, value: &const T, range: &const |
| 801 | 801 | return binaryFirst(T, items, value, Range.init(index - skip, index), lessThan); |
| 802 | 802 | } |
| 803 | 803 | |
| 804 | fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)->bool, unique: usize) -> usize { | |
| 804 | fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 805 | 805 | if (range.length() == 0) return range.start; |
| 806 | 806 | const skip = math.max(range.length()/unique, usize(1)); |
| 807 | 807 | |
| ... | ... | @@ -815,7 +815,7 @@ fn findFirstBackward(comptime T: type, items: []T, value: &const T, range: &cons |
| 815 | 815 | return binaryFirst(T, items, value, Range.init(index, index + skip), lessThan); |
| 816 | 816 | } |
| 817 | 817 | |
| 818 | fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)->bool, unique: usize) -> usize { | |
| 818 | fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 819 | 819 | if (range.length() == 0) return range.start; |
| 820 | 820 | const skip = math.max(range.length()/unique, usize(1)); |
| 821 | 821 | |
| ... | ... | @@ -829,7 +829,7 @@ fn findLastForward(comptime T: type, items: []T, value: &const T, range: &const |
| 829 | 829 | return binaryLast(T, items, value, Range.init(index - skip, index), lessThan); |
| 830 | 830 | } |
| 831 | 831 | |
| 832 | fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)->bool, unique: usize) -> usize { | |
| 832 | fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool, unique: usize) usize { | |
| 833 | 833 | if (range.length() == 0) return range.start; |
| 834 | 834 | const skip = math.max(range.length()/unique, usize(1)); |
| 835 | 835 | |
| ... | ... | @@ -843,7 +843,7 @@ fn findLastBackward(comptime T: type, items: []T, value: &const T, range: &const |
| 843 | 843 | return binaryLast(T, items, value, Range.init(index, index + skip), lessThan); |
| 844 | 844 | } |
| 845 | 845 | |
| 846 | fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)->bool) -> usize { | |
| 846 | fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize { | |
| 847 | 847 | var start = range.start; |
| 848 | 848 | var end = range.end - 1; |
| 849 | 849 | if (range.start >= range.end) return range.end; |
| ... | ... | @@ -861,7 +861,7 @@ fn binaryFirst(comptime T: type, items: []T, value: &const T, range: &const Rang |
| 861 | 861 | return start; |
| 862 | 862 | } |
| 863 | 863 | |
| 864 | fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)->bool) -> usize { | |
| 864 | fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range, lessThan: fn(&const T,&const T)bool) usize { | |
| 865 | 865 | var start = range.start; |
| 866 | 866 | var end = range.end - 1; |
| 867 | 867 | if (range.start >= range.end) return range.end; |
| ... | ... | @@ -879,7 +879,7 @@ fn binaryLast(comptime T: type, items: []T, value: &const T, range: &const Range |
| 879 | 879 | return start; |
| 880 | 880 | } |
| 881 | 881 | |
| 882 | fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)->bool, into: []T) { | |
| 882 | fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, into: []T) void { | |
| 883 | 883 | var A_index: usize = A.start; |
| 884 | 884 | var B_index: usize = B.start; |
| 885 | 885 | const A_last = A.end; |
| ... | ... | @@ -909,7 +909,7 @@ fn mergeInto(comptime T: type, from: []T, A: &const Range, B: &const Range, less |
| 909 | 909 | } |
| 910 | 910 | } |
| 911 | 911 | |
| 912 | fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)->bool, cache: []T) { | |
| 912 | fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, lessThan: fn(&const T,&const T)bool, cache: []T) void { | |
| 913 | 913 | // A fits into the cache, so use that instead of the internal buffer |
| 914 | 914 | var A_index: usize = 0; |
| 915 | 915 | var B_index: usize = B.start; |
| ... | ... | @@ -937,7 +937,7 @@ fn mergeExternal(comptime T: type, items: []T, A: &const Range, B: &const Range, |
| 937 | 937 | mem.copy(T, items[insert_index..], cache[A_index..A_last]); |
| 938 | 938 | } |
| 939 | 939 | |
| 940 | fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)->bool, order: &[8]u8, x: usize, y: usize) { | |
| 940 | fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool, order: &[8]u8, x: usize, y: usize) void { | |
| 941 | 941 | if (lessThan(items[y], items[x]) or |
| 942 | 942 | ((*order)[x] > (*order)[y] and !lessThan(items[x], items[y]))) |
| 943 | 943 | { |
| ... | ... | @@ -946,19 +946,19 @@ fn swap(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T) |
| 946 | 946 | } |
| 947 | 947 | } |
| 948 | 948 | |
| 949 | fn i32asc(lhs: &const i32, rhs: &const i32) -> bool { | |
| 949 | fn i32asc(lhs: &const i32, rhs: &const i32) bool { | |
| 950 | 950 | return *lhs < *rhs; |
| 951 | 951 | } |
| 952 | 952 | |
| 953 | fn i32desc(lhs: &const i32, rhs: &const i32) -> bool { | |
| 953 | fn i32desc(lhs: &const i32, rhs: &const i32) bool { | |
| 954 | 954 | return *rhs < *lhs; |
| 955 | 955 | } |
| 956 | 956 | |
| 957 | fn u8asc(lhs: &const u8, rhs: &const u8) -> bool { | |
| 957 | fn u8asc(lhs: &const u8, rhs: &const u8) bool { | |
| 958 | 958 | return *lhs < *rhs; |
| 959 | 959 | } |
| 960 | 960 | |
| 961 | fn u8desc(lhs: &const u8, rhs: &const u8) -> bool { | |
| 961 | fn u8desc(lhs: &const u8, rhs: &const u8) bool { | |
| 962 | 962 | return *rhs < *lhs; |
| 963 | 963 | } |
| 964 | 964 | |
| ... | ... | @@ -967,7 +967,7 @@ test "stable sort" { |
| 967 | 967 | // TODO: uncomment this after https://github.com/zig-lang/zig/issues/639 |
| 968 | 968 | //comptime testStableSort(); |
| 969 | 969 | } |
| 970 | fn testStableSort() { | |
| 970 | fn testStableSort() void { | |
| 971 | 971 | var expected = []IdAndValue { |
| 972 | 972 | IdAndValue{.id = 0, .value = 0}, |
| 973 | 973 | IdAndValue{.id = 1, .value = 0}, |
| ... | ... | @@ -1015,7 +1015,7 @@ const IdAndValue = struct { |
| 1015 | 1015 | id: usize, |
| 1016 | 1016 | value: i32, |
| 1017 | 1017 | }; |
| 1018 | fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) -> bool { | |
| 1018 | fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) bool { | |
| 1019 | 1019 | return i32asc(a.value, b.value); |
| 1020 | 1020 | } |
| 1021 | 1021 | |
| ... | ... | @@ -1092,7 +1092,7 @@ test "sort fuzz testing" { |
| 1092 | 1092 | |
| 1093 | 1093 | var fixed_buffer_mem: [100 * 1024]u8 = undefined; |
| 1094 | 1094 | |
| 1095 | fn fuzzTest(rng: &std.rand.Rand) { | |
| 1095 | fn fuzzTest(rng: &std.rand.Rand) void { | |
| 1096 | 1096 | const array_size = rng.range(usize, 0, 1000); |
| 1097 | 1097 | var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]); |
| 1098 | 1098 | var array = fixed_allocator.allocator.alloc(IdAndValue, array_size) catch unreachable; |
| ... | ... | @@ -1113,7 +1113,7 @@ fn fuzzTest(rng: &std.rand.Rand) { |
| 1113 | 1113 | } |
| 1114 | 1114 | } |
| 1115 | 1115 | |
| 1116 | pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)->bool) -> T { | |
| 1116 | pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T { | |
| 1117 | 1117 | var i: usize = 0; |
| 1118 | 1118 | var smallest = items[0]; |
| 1119 | 1119 | for (items[1..]) |item| { |
| ... | ... | @@ -1124,7 +1124,7 @@ pub fn min(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const |
| 1124 | 1124 | return smallest; |
| 1125 | 1125 | } |
| 1126 | 1126 | |
| 1127 | pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)->bool) -> T { | |
| 1127 | pub fn max(comptime T: type, items: []T, lessThan: fn(lhs: &const T, rhs: &const T)bool) T { | |
| 1128 | 1128 | var i: usize = 0; |
| 1129 | 1129 | var biggest = items[0]; |
| 1130 | 1130 | for (items[1..]) |item| { |
std/special/bootstrap.zig+7-7| ... | ... | @@ -20,11 +20,11 @@ comptime { |
| 20 | 20 | } |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | extern fn zenMain() -> noreturn { | |
| 23 | extern fn zenMain() noreturn { | |
| 24 | 24 | std.os.posix.exit(callMain()); |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | nakedcc fn _start() -> noreturn { | |
| 27 | nakedcc fn _start() noreturn { | |
| 28 | 28 | switch (builtin.arch) { |
| 29 | 29 | builtin.Arch.x86_64 => { |
| 30 | 30 | argc_ptr = asm("lea (%%rsp), %[argc]": [argc] "=r" (-> &usize)); |
| ... | ... | @@ -39,20 +39,20 @@ nakedcc fn _start() -> noreturn { |
| 39 | 39 | @noInlineCall(posixCallMainAndExit); |
| 40 | 40 | } |
| 41 | 41 | |
| 42 | extern fn WinMainCRTStartup() -> noreturn { | |
| 42 | extern fn WinMainCRTStartup() noreturn { | |
| 43 | 43 | @setAlignStack(16); |
| 44 | 44 | |
| 45 | 45 | std.os.windows.ExitProcess(callMain()); |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | fn posixCallMainAndExit() -> noreturn { | |
| 48 | fn posixCallMainAndExit() noreturn { | |
| 49 | 49 | const argc = *argc_ptr; |
| 50 | 50 | const argv = @ptrCast(&&u8, &argc_ptr[1]); |
| 51 | 51 | const envp = @ptrCast(&?&u8, &argv[argc + 1]); |
| 52 | 52 | std.os.posix.exit(callMainWithArgs(argc, argv, envp)); |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | fn callMainWithArgs(argc: usize, argv: &&u8, envp: &?&u8) -> u8 { | |
| 55 | fn callMainWithArgs(argc: usize, argv: &&u8, envp: &?&u8) u8 { | |
| 56 | 56 | std.os.ArgIteratorPosix.raw = argv[0..argc]; |
| 57 | 57 | |
| 58 | 58 | var env_count: usize = 0; |
| ... | ... | @@ -62,11 +62,11 @@ fn callMainWithArgs(argc: usize, argv: &&u8, envp: &?&u8) -> u8 { |
| 62 | 62 | return callMain(); |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 { | |
| 65 | extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) i32 { | |
| 66 | 66 | return callMainWithArgs(usize(c_argc), c_argv, c_envp); |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | fn callMain() -> u8 { | |
| 69 | fn callMain() u8 { | |
| 70 | 70 | switch (@typeId(@typeOf(root.main).ReturnType)) { |
| 71 | 71 | builtin.TypeId.NoReturn => { |
| 72 | 72 | root.main(); |
std/special/bootstrap_lib.zig+1-1| ... | ... | @@ -7,7 +7,7 @@ comptime { |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | 9 | stdcallcc fn _DllMainCRTStartup(hinstDLL: std.os.windows.HINSTANCE, fdwReason: std.os.windows.DWORD, |
| 10 | lpReserved: std.os.windows.LPVOID) -> std.os.windows.BOOL | |
| 10 | lpReserved: std.os.windows.LPVOID) std.os.windows.BOOL | |
| 11 | 11 | { |
| 12 | 12 | return std.os.windows.TRUE; |
| 13 | 13 | } |
std/special/build_file_template.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | |
| 3 | pub fn build(b: &Builder) { | |
| 3 | pub fn build(b: &Builder) %void { | |
| 4 | 4 | const mode = b.standardReleaseOptions(); |
| 5 | 5 | const exe = b.addExecutable("YOUR_NAME_HERE", "src/main.zig"); |
| 6 | 6 | exe.setBuildMode(mode); |
std/special/build_runner.zig+4-4| ... | ... | @@ -10,7 +10,7 @@ const warn = std.debug.warn; |
| 10 | 10 | |
| 11 | 11 | error InvalidArgs; |
| 12 | 12 | |
| 13 | pub fn main() -> %void { | |
| 13 | pub fn main() %void { | |
| 14 | 14 | var arg_it = os.args(); |
| 15 | 15 | |
| 16 | 16 | // TODO use a more general purpose allocator here |
| ... | ... | @@ -125,7 +125,7 @@ pub fn main() -> %void { |
| 125 | 125 | }; |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) -> %void { | |
| 128 | fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) %void { | |
| 129 | 129 | // run the build script to collect the options |
| 130 | 130 | if (!already_ran_build) { |
| 131 | 131 | builder.setInstallPrefix(null); |
| ... | ... | @@ -183,12 +183,12 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) |
| 183 | 183 | ); |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | fn usageAndErr(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) -> error { | |
| 186 | fn usageAndErr(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) error { | |
| 187 | 187 | usage(builder, already_ran_build, out_stream) catch {}; |
| 188 | 188 | return error.InvalidArgs; |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | fn unwrapArg(arg: %[]u8) -> %[]u8 { | |
| 191 | fn unwrapArg(arg: %[]u8) %[]u8 { | |
| 192 | 192 | return arg catch |err| { |
| 193 | 193 | warn("Unable to parse command line: {}\n", err); |
| 194 | 194 | return err; |
std/special/builtin.zig+17-16| ... | ... | @@ -3,10 +3,11 @@ |
| 3 | 3 | |
| 4 | 4 | const builtin = @import("builtin"); |
| 5 | 5 | |
| 6 | // Avoid dragging in the debug safety mechanisms into this .o file, | |
| 6 | // Avoid dragging in the runtime safety mechanisms into this .o file, | |
| 7 | 7 | // unless we're trying to test this file. |
| 8 | pub coldcc fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) -> noreturn { | |
| 8 | pub fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) noreturn { | |
| 9 | 9 | if (builtin.is_test) { |
| 10 | @setCold(true); | |
| 10 | 11 | @import("std").debug.panic("{}", msg); |
| 11 | 12 | } else { |
| 12 | 13 | unreachable; |
| ... | ... | @@ -16,8 +17,8 @@ pub coldcc fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) - |
| 16 | 17 | // Note that memset does not return `dest`, like the libc API. |
| 17 | 18 | // The semantics of memset is dictated by the corresponding |
| 18 | 19 | // LLVM intrinsics, not by the libc API. |
| 19 | export fn memset(dest: ?&u8, c: u8, n: usize) { | |
| 20 | @setDebugSafety(this, false); | |
| 20 | export fn memset(dest: ?&u8, c: u8, n: usize) void { | |
| 21 | @setRuntimeSafety(false); | |
| 21 | 22 | |
| 22 | 23 | var index: usize = 0; |
| 23 | 24 | while (index != n) : (index += 1) |
| ... | ... | @@ -27,8 +28,8 @@ export fn memset(dest: ?&u8, c: u8, n: usize) { |
| 27 | 28 | // Note that memcpy does not return `dest`, like the libc API. |
| 28 | 29 | // The semantics of memcpy is dictated by the corresponding |
| 29 | 30 | // LLVM intrinsics, not by the libc API. |
| 30 | export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) { | |
| 31 | @setDebugSafety(this, false); | |
| 31 | export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) void { | |
| 32 | @setRuntimeSafety(false); | |
| 32 | 33 | |
| 33 | 34 | var index: usize = 0; |
| 34 | 35 | while (index != n) : (index += 1) |
| ... | ... | @@ -40,24 +41,24 @@ comptime { |
| 40 | 41 | @export("__stack_chk_fail", __stack_chk_fail, builtin.GlobalLinkage.Strong); |
| 41 | 42 | } |
| 42 | 43 | } |
| 43 | extern fn __stack_chk_fail() -> noreturn { | |
| 44 | extern fn __stack_chk_fail() noreturn { | |
| 44 | 45 | @panic("stack smashing detected"); |
| 45 | 46 | } |
| 46 | 47 | |
| 47 | 48 | const math = @import("../math/index.zig"); |
| 48 | 49 | |
| 49 | export fn fmodf(x: f32, y: f32) -> f32 { return generic_fmod(f32, x, y); } | |
| 50 | export fn fmod(x: f64, y: f64) -> f64 { return generic_fmod(f64, x, y); } | |
| 50 | export fn fmodf(x: f32, y: f32) f32 { return generic_fmod(f32, x, y); } | |
| 51 | export fn fmod(x: f64, y: f64) f64 { return generic_fmod(f64, x, y); } | |
| 51 | 52 | |
| 52 | 53 | // TODO add intrinsics for these (and probably the double version too) |
| 53 | 54 | // and have the math stuff use the intrinsic. same as @mod and @rem |
| 54 | export fn floorf(x: f32) -> f32 { return math.floor(x); } | |
| 55 | export fn ceilf(x: f32) -> f32 { return math.ceil(x); } | |
| 56 | export fn floor(x: f64) -> f64 { return math.floor(x); } | |
| 57 | export fn ceil(x: f64) -> f64 { return math.ceil(x); } | |
| 55 | export fn floorf(x: f32) f32 { return math.floor(x); } | |
| 56 | export fn ceilf(x: f32) f32 { return math.ceil(x); } | |
| 57 | export fn floor(x: f64) f64 { return math.floor(x); } | |
| 58 | export fn ceil(x: f64) f64 { return math.ceil(x); } | |
| 58 | 59 | |
| 59 | fn generic_fmod(comptime T: type, x: T, y: T) -> T { | |
| 60 | @setDebugSafety(this, false); | |
| 60 | fn generic_fmod(comptime T: type, x: T, y: T) T { | |
| 61 | @setRuntimeSafety(false); | |
| 61 | 62 | |
| 62 | 63 | const uint = @IntType(false, T.bit_count); |
| 63 | 64 | const log2uint = math.Log2Int(uint); |
| ... | ... | @@ -132,7 +133,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) -> T { |
| 132 | 133 | return @bitCast(T, ux); |
| 133 | 134 | } |
| 134 | 135 | |
| 135 | fn isNan(comptime T: type, bits: T) -> bool { | |
| 136 | fn isNan(comptime T: type, bits: T) bool { | |
| 136 | 137 | if (T == u32) { |
| 137 | 138 | return (bits & 0x7fffffff) > 0x7f800000; |
| 138 | 139 | } else if (T == u64) { |
std/special/compiler_rt/aulldiv.zig+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | pub nakedcc fn _aulldiv() { | |
| 2 | @setDebugSafety(this, false); | |
| 1 | pub nakedcc fn _aulldiv() void { | |
| 2 | @setRuntimeSafety(false); | |
| 3 | 3 | asm volatile ( |
| 4 | 4 | \\.intel_syntax noprefix |
| 5 | 5 | \\ |
std/special/compiler_rt/aullrem.zig+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | pub nakedcc fn _aullrem() { | |
| 2 | @setDebugSafety(this, false); | |
| 1 | pub nakedcc fn _aullrem() void { | |
| 2 | @setRuntimeSafety(false); | |
| 3 | 3 | asm volatile ( |
| 4 | 4 | \\.intel_syntax noprefix |
| 5 | 5 | \\ |
std/special/compiler_rt/comparetf2.zig+6-6| ... | ... | @@ -21,8 +21,8 @@ const infRep = exponentMask; |
| 21 | 21 | const builtin = @import("builtin"); |
| 22 | 22 | const is_test = builtin.is_test; |
| 23 | 23 | |
| 24 | pub extern fn __letf2(a: f128, b: f128) -> c_int { | |
| 25 | @setDebugSafety(this, is_test); | |
| 24 | pub extern fn __letf2(a: f128, b: f128) c_int { | |
| 25 | @setRuntimeSafety(is_test); | |
| 26 | 26 | |
| 27 | 27 | const aInt = @bitCast(rep_t, a); |
| 28 | 28 | const bInt = @bitCast(rep_t, b); |
| ... | ... | @@ -66,8 +66,8 @@ const GE_EQUAL = c_int(0); |
| 66 | 66 | const GE_GREATER = c_int(1); |
| 67 | 67 | const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED |
| 68 | 68 | |
| 69 | pub extern fn __getf2(a: f128, b: f128) -> c_int { | |
| 70 | @setDebugSafety(this, is_test); | |
| 69 | pub extern fn __getf2(a: f128, b: f128) c_int { | |
| 70 | @setRuntimeSafety(is_test); | |
| 71 | 71 | |
| 72 | 72 | const aInt = @bitCast(srep_t, a); |
| 73 | 73 | const bInt = @bitCast(srep_t, b); |
| ... | ... | @@ -93,8 +93,8 @@ pub extern fn __getf2(a: f128, b: f128) -> c_int { |
| 93 | 93 | ; |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | pub extern fn __unordtf2(a: f128, b: f128) -> c_int { | |
| 97 | @setDebugSafety(this, is_test); | |
| 96 | pub extern fn __unordtf2(a: f128, b: f128) c_int { | |
| 97 | @setRuntimeSafety(is_test); | |
| 98 | 98 | |
| 99 | 99 | const aAbs = @bitCast(rep_t, a) & absMask; |
| 100 | 100 | const bAbs = @bitCast(rep_t, b) & absMask; |
std/special/compiler_rt/fixuint.zig+4-4| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const is_test = @import("builtin").is_test; |
| 2 | 2 | const Log2Int = @import("../../math/index.zig").Log2Int; |
| 3 | 3 | |
| 4 | pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) -> fixuint_t { | |
| 5 | @setDebugSafety(this, is_test); | |
| 4 | pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t { | |
| 5 | @setRuntimeSafety(is_test); | |
| 6 | 6 | |
| 7 | 7 | const rep_t = switch (fp_t) { |
| 8 | 8 | f32 => u32, |
| ... | ... | @@ -48,12 +48,12 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) -> fixuin |
| 48 | 48 | if (exponent < significandBits) { |
| 49 | 49 | // TODO this is a workaround for the mysterious "integer cast truncated bits" |
| 50 | 50 | // happening on the next line |
| 51 | @setDebugSafety(this, false); | |
| 51 | @setRuntimeSafety(false); | |
| 52 | 52 | return fixuint_t(significand >> Log2Int(rep_t)(significandBits - exponent)); |
| 53 | 53 | } else { |
| 54 | 54 | // TODO this is a workaround for the mysterious "integer cast truncated bits" |
| 55 | 55 | // happening on the next line |
| 56 | @setDebugSafety(this, false); | |
| 56 | @setRuntimeSafety(false); | |
| 57 | 57 | return fixuint_t(significand) << Log2Int(fixuint_t)(exponent - significandBits); |
| 58 | 58 | } |
| 59 | 59 | } |
std/special/compiler_rt/fixunsdfdi.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __fixunsdfdi(a: f64) -> u64 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __fixunsdfdi(a: f64) u64 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return fixuint(f64, u64, a); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/fixunsdfdi_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi; |
| 2 | 2 | const assert = @import("../../index.zig").debug.assert; |
| 3 | 3 | |
| 4 | fn test__fixunsdfdi(a: f64, expected: u64) { | |
| 4 | fn test__fixunsdfdi(a: f64, expected: u64) void { | |
| 5 | 5 | const x = __fixunsdfdi(a); |
| 6 | 6 | assert(x == expected); |
| 7 | 7 | } |
std/special/compiler_rt/fixunsdfsi.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __fixunsdfsi(a: f64) -> u32 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __fixunsdfsi(a: f64) u32 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return fixuint(f64, u32, a); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/fixunsdfsi_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi; |
| 2 | 2 | const assert = @import("../../index.zig").debug.assert; |
| 3 | 3 | |
| 4 | fn test__fixunsdfsi(a: f64, expected: u32) { | |
| 4 | fn test__fixunsdfsi(a: f64, expected: u32) void { | |
| 5 | 5 | const x = __fixunsdfsi(a); |
| 6 | 6 | assert(x == expected); |
| 7 | 7 | } |
std/special/compiler_rt/fixunsdfti.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __fixunsdfti(a: f64) -> u128 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __fixunsdfti(a: f64) u128 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return fixuint(f64, u128, a); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/fixunsdfti_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti; |
| 2 | 2 | const assert = @import("../../index.zig").debug.assert; |
| 3 | 3 | |
| 4 | fn test__fixunsdfti(a: f64, expected: u128) { | |
| 4 | fn test__fixunsdfti(a: f64, expected: u128) void { | |
| 5 | 5 | const x = __fixunsdfti(a); |
| 6 | 6 | assert(x == expected); |
| 7 | 7 | } |
std/special/compiler_rt/fixunssfdi.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __fixunssfdi(a: f32) -> u64 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __fixunssfdi(a: f32) u64 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return fixuint(f32, u64, a); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/fixunssfdi_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi; |
| 2 | 2 | const assert = @import("../../index.zig").debug.assert; |
| 3 | 3 | |
| 4 | fn test__fixunssfdi(a: f32, expected: u64) { | |
| 4 | fn test__fixunssfdi(a: f32, expected: u64) void { | |
| 5 | 5 | const x = __fixunssfdi(a); |
| 6 | 6 | assert(x == expected); |
| 7 | 7 | } |
std/special/compiler_rt/fixunssfsi.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __fixunssfsi(a: f32) -> u32 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __fixunssfsi(a: f32) u32 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return fixuint(f32, u32, a); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/fixunssfsi_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi; |
| 2 | 2 | const assert = @import("../../index.zig").debug.assert; |
| 3 | 3 | |
| 4 | fn test__fixunssfsi(a: f32, expected: u32) { | |
| 4 | fn test__fixunssfsi(a: f32, expected: u32) void { | |
| 5 | 5 | const x = __fixunssfsi(a); |
| 6 | 6 | assert(x == expected); |
| 7 | 7 | } |
std/special/compiler_rt/fixunssfti.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __fixunssfti(a: f32) -> u128 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __fixunssfti(a: f32) u128 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return fixuint(f32, u128, a); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/fixunssfti_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __fixunssfti = @import("fixunssfti.zig").__fixunssfti; |
| 2 | 2 | const assert = @import("../../index.zig").debug.assert; |
| 3 | 3 | |
| 4 | fn test__fixunssfti(a: f32, expected: u128) { | |
| 4 | fn test__fixunssfti(a: f32, expected: u128) void { | |
| 5 | 5 | const x = __fixunssfti(a); |
| 6 | 6 | assert(x == expected); |
| 7 | 7 | } |
std/special/compiler_rt/fixunstfdi.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __fixunstfdi(a: f128) -> u64 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __fixunstfdi(a: f128) u64 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return fixuint(f128, u64, a); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/fixunstfdi_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi; |
| 2 | 2 | const assert = @import("../../index.zig").debug.assert; |
| 3 | 3 | |
| 4 | fn test__fixunstfdi(a: f128, expected: u64) { | |
| 4 | fn test__fixunstfdi(a: f128, expected: u64) void { | |
| 5 | 5 | const x = __fixunstfdi(a); |
| 6 | 6 | assert(x == expected); |
| 7 | 7 | } |
std/special/compiler_rt/fixunstfsi.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __fixunstfsi(a: f128) -> u32 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __fixunstfsi(a: f128) u32 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return fixuint(f128, u32, a); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/fixunstfsi_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; |
| 2 | 2 | const assert = @import("../../index.zig").debug.assert; |
| 3 | 3 | |
| 4 | fn test__fixunstfsi(a: f128, expected: u32) { | |
| 4 | fn test__fixunstfsi(a: f128, expected: u32) void { | |
| 5 | 5 | const x = __fixunstfsi(a); |
| 6 | 6 | assert(x == expected); |
| 7 | 7 | } |
std/special/compiler_rt/fixunstfti.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __fixunstfti(a: f128) -> u128 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __fixunstfti(a: f128) u128 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return fixuint(f128, u128, a); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/fixunstfti_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __fixunstfti = @import("fixunstfti.zig").__fixunstfti; |
| 2 | 2 | const assert = @import("../../index.zig").debug.assert; |
| 3 | 3 | |
| 4 | fn test__fixunstfti(a: f128, expected: u128) { | |
| 4 | fn test__fixunstfti(a: f128, expected: u128) void { | |
| 5 | 5 | const x = __fixunstfti(a); |
| 6 | 6 | assert(x == expected); |
| 7 | 7 | } |
std/special/compiler_rt/index.zig+26-25| ... | ... | @@ -72,9 +72,10 @@ const assert = @import("../../index.zig").debug.assert; |
| 72 | 72 | |
| 73 | 73 | const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; |
| 74 | 74 | |
| 75 | // Avoid dragging in the debug safety mechanisms into this .o file, | |
| 75 | // Avoid dragging in the runtime safety mechanisms into this .o file, | |
| 76 | 76 | // unless we're trying to test this file. |
| 77 | pub coldcc fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) -> noreturn { | |
| 77 | pub fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) noreturn { | |
| 78 | @setCold(true); | |
| 78 | 79 | if (is_test) { |
| 79 | 80 | @import("std").debug.panic("{}", msg); |
| 80 | 81 | } else { |
| ... | ... | @@ -82,13 +83,13 @@ pub coldcc fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) - |
| 82 | 83 | } |
| 83 | 84 | } |
| 84 | 85 | |
| 85 | extern fn __udivdi3(a: u64, b: u64) -> u64 { | |
| 86 | @setDebugSafety(this, is_test); | |
| 86 | extern fn __udivdi3(a: u64, b: u64) u64 { | |
| 87 | @setRuntimeSafety(is_test); | |
| 87 | 88 | return __udivmoddi4(a, b, null); |
| 88 | 89 | } |
| 89 | 90 | |
| 90 | extern fn __umoddi3(a: u64, b: u64) -> u64 { | |
| 91 | @setDebugSafety(this, is_test); | |
| 91 | extern fn __umoddi3(a: u64, b: u64) u64 { | |
| 92 | @setRuntimeSafety(is_test); | |
| 92 | 93 | |
| 93 | 94 | var r: u64 = undefined; |
| 94 | 95 | _ = __udivmoddi4(a, b, &r); |
| ... | ... | @@ -99,14 +100,14 @@ const AeabiUlDivModResult = extern struct { |
| 99 | 100 | quot: u64, |
| 100 | 101 | rem: u64, |
| 101 | 102 | }; |
| 102 | extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) -> AeabiUlDivModResult { | |
| 103 | @setDebugSafety(this, is_test); | |
| 103 | extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult { | |
| 104 | @setRuntimeSafety(is_test); | |
| 104 | 105 | var result: AeabiUlDivModResult = undefined; |
| 105 | 106 | result.quot = __udivmoddi4(numerator, denominator, &result.rem); |
| 106 | 107 | return result; |
| 107 | 108 | } |
| 108 | 109 | |
| 109 | fn isArmArch() -> bool { | |
| 110 | fn isArmArch() bool { | |
| 110 | 111 | return switch (builtin.arch) { |
| 111 | 112 | builtin.Arch.armv8_2a, |
| 112 | 113 | builtin.Arch.armv8_1a, |
| ... | ... | @@ -148,8 +149,8 @@ fn isArmArch() -> bool { |
| 148 | 149 | }; |
| 149 | 150 | } |
| 150 | 151 | |
| 151 | nakedcc fn __aeabi_uidivmod() { | |
| 152 | @setDebugSafety(this, false); | |
| 152 | nakedcc fn __aeabi_uidivmod() void { | |
| 153 | @setRuntimeSafety(false); | |
| 153 | 154 | asm volatile ( |
| 154 | 155 | \\ push { lr } |
| 155 | 156 | \\ sub sp, sp, #4 |
| ... | ... | @@ -165,8 +166,8 @@ nakedcc fn __aeabi_uidivmod() { |
| 165 | 166 | // then decrement %esp by %eax. Preserves all registers except %esp and flags. |
| 166 | 167 | // This routine is windows specific |
| 167 | 168 | // http://msdn.microsoft.com/en-us/library/ms648426.aspx |
| 168 | nakedcc fn _chkstk() align(4) { | |
| 169 | @setDebugSafety(this, false); | |
| 169 | nakedcc fn _chkstk() align(4) void { | |
| 170 | @setRuntimeSafety(false); | |
| 170 | 171 | |
| 171 | 172 | asm volatile ( |
| 172 | 173 | \\ push %%ecx |
| ... | ... | @@ -189,8 +190,8 @@ nakedcc fn _chkstk() align(4) { |
| 189 | 190 | ); |
| 190 | 191 | } |
| 191 | 192 | |
| 192 | nakedcc fn __chkstk() align(4) { | |
| 193 | @setDebugSafety(this, false); | |
| 193 | nakedcc fn __chkstk() align(4) void { | |
| 194 | @setRuntimeSafety(false); | |
| 194 | 195 | |
| 195 | 196 | asm volatile ( |
| 196 | 197 | \\ push %%rcx |
| ... | ... | @@ -216,8 +217,8 @@ nakedcc fn __chkstk() align(4) { |
| 216 | 217 | // _chkstk routine |
| 217 | 218 | // This routine is windows specific |
| 218 | 219 | // http://msdn.microsoft.com/en-us/library/ms648426.aspx |
| 219 | nakedcc fn __chkstk_ms() align(4) { | |
| 220 | @setDebugSafety(this, false); | |
| 220 | nakedcc fn __chkstk_ms() align(4) void { | |
| 221 | @setRuntimeSafety(false); | |
| 221 | 222 | |
| 222 | 223 | asm volatile ( |
| 223 | 224 | \\ push %%ecx |
| ... | ... | @@ -240,8 +241,8 @@ nakedcc fn __chkstk_ms() align(4) { |
| 240 | 241 | ); |
| 241 | 242 | } |
| 242 | 243 | |
| 243 | nakedcc fn ___chkstk_ms() align(4) { | |
| 244 | @setDebugSafety(this, false); | |
| 244 | nakedcc fn ___chkstk_ms() align(4) void { | |
| 245 | @setRuntimeSafety(false); | |
| 245 | 246 | |
| 246 | 247 | asm volatile ( |
| 247 | 248 | \\ push %%rcx |
| ... | ... | @@ -264,8 +265,8 @@ nakedcc fn ___chkstk_ms() align(4) { |
| 264 | 265 | ); |
| 265 | 266 | } |
| 266 | 267 | |
| 267 | extern fn __udivmodsi4(a: u32, b: u32, rem: &u32) -> u32 { | |
| 268 | @setDebugSafety(this, is_test); | |
| 268 | extern fn __udivmodsi4(a: u32, b: u32, rem: &u32) u32 { | |
| 269 | @setRuntimeSafety(is_test); | |
| 269 | 270 | |
| 270 | 271 | const d = __udivsi3(a, b); |
| 271 | 272 | *rem = u32(i32(a) -% (i32(d) * i32(b))); |
| ... | ... | @@ -273,8 +274,8 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: &u32) -> u32 { |
| 273 | 274 | } |
| 274 | 275 | |
| 275 | 276 | |
| 276 | extern fn __udivsi3(n: u32, d: u32) -> u32 { | |
| 277 | @setDebugSafety(this, is_test); | |
| 277 | extern fn __udivsi3(n: u32, d: u32) u32 { | |
| 278 | @setRuntimeSafety(is_test); | |
| 278 | 279 | |
| 279 | 280 | const n_uword_bits: c_uint = u32.bit_count; |
| 280 | 281 | // special cases |
| ... | ... | @@ -320,7 +321,7 @@ test "test_umoddi3" { |
| 320 | 321 | test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1); |
| 321 | 322 | } |
| 322 | 323 | |
| 323 | fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) { | |
| 324 | fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void { | |
| 324 | 325 | const r = __umoddi3(a, b); |
| 325 | 326 | assert(r == expected_r); |
| 326 | 327 | } |
| ... | ... | @@ -466,7 +467,7 @@ test "test_udivsi3" { |
| 466 | 467 | } |
| 467 | 468 | } |
| 468 | 469 | |
| 469 | fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) { | |
| 470 | fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void { | |
| 470 | 471 | const q: u32 = __udivsi3(a, b); |
| 471 | 472 | assert(q == expected_q); |
| 472 | 473 | } |
std/special/compiler_rt/udivmod.zig+2-2| ... | ... | @@ -4,8 +4,8 @@ const is_test = builtin.is_test; |
| 4 | 4 | const low = switch (builtin.endian) { builtin.Endian.Big => 1, builtin.Endian.Little => 0 }; |
| 5 | 5 | const high = 1 - low; |
| 6 | 6 | |
| 7 | pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?&DoubleInt) -> DoubleInt { | |
| 8 | @setDebugSafety(this, is_test); | |
| 7 | pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?&DoubleInt) DoubleInt { | |
| 8 | @setRuntimeSafety(is_test); | |
| 9 | 9 | |
| 10 | 10 | const SingleInt = @IntType(false, @divExact(DoubleInt.bit_count, 2)); |
| 11 | 11 | const SignedDoubleInt = @IntType(true, DoubleInt.bit_count); |
std/special/compiler_rt/udivmoddi4.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const udivmod = @import("udivmod.zig").udivmod; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?&u64) -> u64 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?&u64) u64 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return udivmod(u64, a, b, maybe_rem); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/udivmoddi4_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; |
| 2 | 2 | const assert = @import("std").debug.assert; |
| 3 | 3 | |
| 4 | fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) { | |
| 4 | fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) void { | |
| 5 | 5 | var r: u64 = undefined; |
| 6 | 6 | const q = __udivmoddi4(a, b, &r); |
| 7 | 7 | assert(q == expected_q); |
std/special/compiler_rt/udivmodti4.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const udivmod = @import("udivmod.zig").udivmod; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?&u128) -> u128 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?&u128) u128 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return udivmod(u128, a, b, maybe_rem); |
| 7 | 7 | } |
| 8 | 8 |
std/special/compiler_rt/udivmodti4_test.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4; |
| 2 | 2 | const assert = @import("std").debug.assert; |
| 3 | 3 | |
| 4 | fn test__udivmodti4(a: u128, b: u128, expected_q: u128, expected_r: u128) { | |
| 4 | fn test__udivmodti4(a: u128, b: u128, expected_q: u128, expected_r: u128) void { | |
| 5 | 5 | var r: u128 = undefined; |
| 6 | 6 | const q = __udivmodti4(a, b, &r); |
| 7 | 7 | assert(q == expected_q); |
std/special/compiler_rt/udivti3.zig+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __udivti3(a: u128, b: u128) -> u128 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __udivti3(a: u128, b: u128) u128 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | return __udivmodti4(a, b, null); |
| 7 | 7 | } |
std/special/compiler_rt/umodti3.zig+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | pub extern fn __umodti3(a: u128, b: u128) -> u128 { | |
| 5 | @setDebugSafety(this, builtin.is_test); | |
| 4 | pub extern fn __umodti3(a: u128, b: u128) u128 { | |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | 6 | var r: u128 = undefined; |
| 7 | 7 | _ = __udivmodti4(a, b, &r); |
| 8 | 8 | return r; |
std/special/panic.zig+2-1| ... | ... | @@ -6,7 +6,8 @@ |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | 7 | const std = @import("std"); |
| 8 | 8 | |
| 9 | pub coldcc fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) -> noreturn { | |
| 9 | pub fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) noreturn { | |
| 10 | @setCold(true); | |
| 10 | 11 | switch (builtin.os) { |
| 11 | 12 | // TODO: fix panic in zen. |
| 12 | 13 | builtin.Os.freestanding, builtin.Os.zen => { |
std/special/test_runner.zig+1-1| ... | ... | @@ -4,7 +4,7 @@ const builtin = @import("builtin"); |
| 4 | 4 | const test_fn_list = builtin.__zig_test_fn_slice; |
| 5 | 5 | const warn = std.debug.warn; |
| 6 | 6 | |
| 7 | pub fn main() -> %void { | |
| 7 | pub fn main() %void { | |
| 8 | 8 | for (test_fn_list) |test_fn, i| { |
| 9 | 9 | warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); |
| 10 | 10 |
std/unicode.zig+8-8| ... | ... | @@ -5,7 +5,7 @@ error Utf8InvalidStartByte; |
| 5 | 5 | /// Given the first byte of a UTF-8 codepoint, |
| 6 | 6 | /// returns a number 1-4 indicating the total length of the codepoint in bytes. |
| 7 | 7 | /// If this byte does not match the form of a UTF-8 start byte, returns Utf8InvalidStartByte. |
| 8 | pub fn utf8ByteSequenceLength(first_byte: u8) -> %u3 { | |
| 8 | pub fn utf8ByteSequenceLength(first_byte: u8) %u3 { | |
| 9 | 9 | if (first_byte < 0b10000000) return u3(1); |
| 10 | 10 | if (first_byte & 0b11100000 == 0b11000000) return u3(2); |
| 11 | 11 | if (first_byte & 0b11110000 == 0b11100000) return u3(3); |
| ... | ... | @@ -22,7 +22,7 @@ error Utf8CodepointTooLarge; |
| 22 | 22 | /// bytes.len must be equal to utf8ByteSequenceLength(bytes[0]) catch unreachable. |
| 23 | 23 | /// If you already know the length at comptime, you can call one of |
| 24 | 24 | /// utf8Decode2,utf8Decode3,utf8Decode4 directly instead of this function. |
| 25 | pub fn utf8Decode(bytes: []const u8) -> %u32 { | |
| 25 | pub fn utf8Decode(bytes: []const u8) %u32 { | |
| 26 | 26 | return switch (bytes.len) { |
| 27 | 27 | 1 => u32(bytes[0]), |
| 28 | 28 | 2 => utf8Decode2(bytes), |
| ... | ... | @@ -31,7 +31,7 @@ pub fn utf8Decode(bytes: []const u8) -> %u32 { |
| 31 | 31 | else => unreachable, |
| 32 | 32 | }; |
| 33 | 33 | } |
| 34 | pub fn utf8Decode2(bytes: []const u8) -> %u32 { | |
| 34 | pub fn utf8Decode2(bytes: []const u8) %u32 { | |
| 35 | 35 | std.debug.assert(bytes.len == 2); |
| 36 | 36 | std.debug.assert(bytes[0] & 0b11100000 == 0b11000000); |
| 37 | 37 | var value: u32 = bytes[0] & 0b00011111; |
| ... | ... | @@ -44,7 +44,7 @@ pub fn utf8Decode2(bytes: []const u8) -> %u32 { |
| 44 | 44 | |
| 45 | 45 | return value; |
| 46 | 46 | } |
| 47 | pub fn utf8Decode3(bytes: []const u8) -> %u32 { | |
| 47 | pub fn utf8Decode3(bytes: []const u8) %u32 { | |
| 48 | 48 | std.debug.assert(bytes.len == 3); |
| 49 | 49 | std.debug.assert(bytes[0] & 0b11110000 == 0b11100000); |
| 50 | 50 | var value: u32 = bytes[0] & 0b00001111; |
| ... | ... | @@ -62,7 +62,7 @@ pub fn utf8Decode3(bytes: []const u8) -> %u32 { |
| 62 | 62 | |
| 63 | 63 | return value; |
| 64 | 64 | } |
| 65 | pub fn utf8Decode4(bytes: []const u8) -> %u32 { | |
| 65 | pub fn utf8Decode4(bytes: []const u8) %u32 { | |
| 66 | 66 | std.debug.assert(bytes.len == 4); |
| 67 | 67 | std.debug.assert(bytes[0] & 0b11111000 == 0b11110000); |
| 68 | 68 | var value: u32 = bytes[0] & 0b00000111; |
| ... | ... | @@ -149,7 +149,7 @@ test "misc invalid utf8" { |
| 149 | 149 | testValid("\xee\x80\x80", 0xe000); |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | fn testError(bytes: []const u8, expected_err: error) { | |
| 152 | fn testError(bytes: []const u8, expected_err: error) void { | |
| 153 | 153 | if (testDecode(bytes)) |_| { |
| 154 | 154 | unreachable; |
| 155 | 155 | } else |err| { |
| ... | ... | @@ -157,11 +157,11 @@ fn testError(bytes: []const u8, expected_err: error) { |
| 157 | 157 | } |
| 158 | 158 | } |
| 159 | 159 | |
| 160 | fn testValid(bytes: []const u8, expected_codepoint: u32) { | |
| 160 | fn testValid(bytes: []const u8, expected_codepoint: u32) void { | |
| 161 | 161 | std.debug.assert((testDecode(bytes) catch unreachable) == expected_codepoint); |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | fn testDecode(bytes: []const u8) -> %u32 { | |
| 164 | fn testDecode(bytes: []const u8) %u32 { | |
| 165 | 165 | const length = try utf8ByteSequenceLength(bytes[0]); |
| 166 | 166 | if (bytes.len < length) return error.UnexpectedEof; |
| 167 | 167 | std.debug.assert(bytes.len == length); |
std/zlib/deflate.zig deleted-522| ... | ... | @@ -1,522 +0,0 @@ |
| 1 | const z_stream = struct { | |
| 2 | /// next input byte */ | |
| 3 | next_in: &const u8, | |
| 4 | ||
| 5 | /// number of bytes available at next_in | |
| 6 | avail_in: u16, | |
| 7 | /// total number of input bytes read so far | |
| 8 | total_in: u32, | |
| 9 | ||
| 10 | /// next output byte will go here | |
| 11 | next_out: u8, | |
| 12 | /// remaining free space at next_out | |
| 13 | avail_out: u16, | |
| 14 | /// total number of bytes output so far | |
| 15 | total_out: u32, | |
| 16 | ||
| 17 | /// last error message, NULL if no error | |
| 18 | msg: ?&const u8, | |
| 19 | /// not visible by applications | |
| 20 | state: | |
| 21 | struct internal_state FAR *state; // not visible by applications */ | |
| 22 | ||
| 23 | alloc_func zalloc; // used to allocate the internal state */ | |
| 24 | free_func zfree; // used to free the internal state */ | |
| 25 | voidpf opaque; // private data object passed to zalloc and zfree */ | |
| 26 | ||
| 27 | int data_type; // best guess about the data type: binary or text | |
| 28 | // for deflate, or the decoding state for inflate */ | |
| 29 | uint32_t adler; // Adler-32 or CRC-32 value of the uncompressed data */ | |
| 30 | uint32_t reserved; // reserved for future use */ | |
| 31 | }; | |
| 32 | ||
| 33 | typedef struct internal_state { | |
| 34 | z_stream * strm; /* pointer back to this zlib stream */ | |
| 35 | int status; /* as the name implies */ | |
| 36 | uint8_t *pending_buf; /* output still pending */ | |
| 37 | ulg pending_buf_size; /* size of pending_buf */ | |
| 38 | uint8_t *pending_out; /* next pending byte to output to the stream */ | |
| 39 | ulg pending; /* nb of bytes in the pending buffer */ | |
| 40 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ | |
| 41 | gz_headerp gzhead; /* gzip header information to write */ | |
| 42 | ulg gzindex; /* where in extra, name, or comment */ | |
| 43 | uint8_t method; /* can only be DEFLATED */ | |
| 44 | int last_flush; /* value of flush param for previous deflate call */ | |
| 45 | ||
| 46 | /* used by deflate.c: */ | |
| 47 | ||
| 48 | uint16_t w_size; /* LZ77 window size (32K by default) */ | |
| 49 | uint16_t w_bits; /* log2(w_size) (8..16) */ | |
| 50 | uint16_t w_mask; /* w_size - 1 */ | |
| 51 | ||
| 52 | uint8_t *window; | |
| 53 | /* Sliding window. Input bytes are read into the second half of the window, | |
| 54 | * and move to the first half later to keep a dictionary of at least wSize | |
| 55 | * bytes. With this organization, matches are limited to a distance of | |
| 56 | * wSize-MAX_MATCH bytes, but this ensures that IO is always | |
| 57 | * performed with a length multiple of the block size. Also, it limits | |
| 58 | * the window size to 64K, which is quite useful on MSDOS. | |
| 59 | * To do: use the user input buffer as sliding window. | |
| 60 | */ | |
| 61 | ||
| 62 | ulg window_size; | |
| 63 | /* Actual size of window: 2*wSize, except when the user input buffer | |
| 64 | * is directly used as sliding window. | |
| 65 | */ | |
| 66 | ||
| 67 | Posf *prev; | |
| 68 | /* Link to older string with same hash index. To limit the size of this | |
| 69 | * array to 64K, this link is maintained only for the last 32K strings. | |
| 70 | * An index in this array is thus a window index modulo 32K. | |
| 71 | */ | |
| 72 | ||
| 73 | Posf *head; /* Heads of the hash chains or NIL. */ | |
| 74 | ||
| 75 | uint16_t ins_h; /* hash index of string to be inserted */ | |
| 76 | uint16_t hash_size; /* number of elements in hash table */ | |
| 77 | uint16_t hash_bits; /* log2(hash_size) */ | |
| 78 | uint16_t hash_mask; /* hash_size-1 */ | |
| 79 | ||
| 80 | uint16_t hash_shift; | |
| 81 | /* Number of bits by which ins_h must be shifted at each input | |
| 82 | * step. It must be such that after MIN_MATCH steps, the oldest | |
| 83 | * byte no longer takes part in the hash key, that is: | |
| 84 | * hash_shift * MIN_MATCH >= hash_bits | |
| 85 | */ | |
| 86 | ||
| 87 | long block_start; | |
| 88 | /* Window position at the beginning of the current output block. Gets | |
| 89 | * negative when the window is moved backwards. | |
| 90 | */ | |
| 91 | ||
| 92 | uint16_t match_length; /* length of best match */ | |
| 93 | IPos prev_match; /* previous match */ | |
| 94 | int match_available; /* set if previous match exists */ | |
| 95 | uint16_t strstart; /* start of string to insert */ | |
| 96 | uint16_t match_start; /* start of matching string */ | |
| 97 | uint16_t lookahead; /* number of valid bytes ahead in window */ | |
| 98 | ||
| 99 | uint16_t prev_length; | |
| 100 | /* Length of the best match at previous step. Matches not greater than this | |
| 101 | * are discarded. This is used in the lazy match evaluation. | |
| 102 | */ | |
| 103 | ||
| 104 | uint16_t max_chain_length; | |
| 105 | /* To speed up deflation, hash chains are never searched beyond this | |
| 106 | * length. A higher limit improves compression ratio but degrades the | |
| 107 | * speed. | |
| 108 | */ | |
| 109 | ||
| 110 | uint16_t max_lazy_match; | |
| 111 | /* Attempt to find a better match only when the current match is strictly | |
| 112 | * smaller than this value. This mechanism is used only for compression | |
| 113 | * levels >= 4. | |
| 114 | */ | |
| 115 | # define max_insert_length max_lazy_match | |
| 116 | /* Insert new strings in the hash table only if the match length is not | |
| 117 | * greater than this length. This saves time but degrades compression. | |
| 118 | * max_insert_length is used only for compression levels <= 3. | |
| 119 | */ | |
| 120 | ||
| 121 | int level; /* compression level (1..9) */ | |
| 122 | int strategy; /* favor or force Huffman coding*/ | |
| 123 | ||
| 124 | uint16_t good_match; | |
| 125 | /* Use a faster search when the previous match is longer than this */ | |
| 126 | ||
| 127 | int nice_match; /* Stop searching when current match exceeds this */ | |
| 128 | ||
| 129 | /* used by trees.c: */ | |
| 130 | /* Didn't use ct_data typedef below to suppress compiler warning */ | |
| 131 | struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ | |
| 132 | struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ | |
| 133 | struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ | |
| 134 | ||
| 135 | struct tree_desc_s l_desc; /* desc. for literal tree */ | |
| 136 | struct tree_desc_s d_desc; /* desc. for distance tree */ | |
| 137 | struct tree_desc_s bl_desc; /* desc. for bit length tree */ | |
| 138 | ||
| 139 | ush bl_count[MAX_BITS+1]; | |
| 140 | /* number of codes at each bit length for an optimal tree */ | |
| 141 | ||
| 142 | int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ | |
| 143 | int heap_len; /* number of elements in the heap */ | |
| 144 | int heap_max; /* element of largest frequency */ | |
| 145 | /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. | |
| 146 | * The same heap array is used to build all trees. | |
| 147 | */ | |
| 148 | ||
| 149 | uch depth[2*L_CODES+1]; | |
| 150 | /* Depth of each subtree used as tie breaker for trees of equal frequency | |
| 151 | */ | |
| 152 | ||
| 153 | uchf *l_buf; /* buffer for literals or lengths */ | |
| 154 | ||
| 155 | uint16_t lit_bufsize; | |
| 156 | /* Size of match buffer for literals/lengths. There are 4 reasons for | |
| 157 | * limiting lit_bufsize to 64K: | |
| 158 | * - frequencies can be kept in 16 bit counters | |
| 159 | * - if compression is not successful for the first block, all input | |
| 160 | * data is still in the window so we can still emit a stored block even | |
| 161 | * when input comes from standard input. (This can also be done for | |
| 162 | * all blocks if lit_bufsize is not greater than 32K.) | |
| 163 | * - if compression is not successful for a file smaller than 64K, we can | |
| 164 | * even emit a stored file instead of a stored block (saving 5 bytes). | |
| 165 | * This is applicable only for zip (not gzip or zlib). | |
| 166 | * - creating new Huffman trees less frequently may not provide fast | |
| 167 | * adaptation to changes in the input data statistics. (Take for | |
| 168 | * example a binary file with poorly compressible code followed by | |
| 169 | * a highly compressible string table.) Smaller buffer sizes give | |
| 170 | * fast adaptation but have of course the overhead of transmitting | |
| 171 | * trees more frequently. | |
| 172 | * - I can't count above 4 | |
| 173 | */ | |
| 174 | ||
| 175 | uint16_t last_lit; /* running index in l_buf */ | |
| 176 | ||
| 177 | ushf *d_buf; | |
| 178 | /* Buffer for distances. To simplify the code, d_buf and l_buf have | |
| 179 | * the same number of elements. To use different lengths, an extra flag | |
| 180 | * array would be necessary. | |
| 181 | */ | |
| 182 | ||
| 183 | ulg opt_len; /* bit length of current block with optimal trees */ | |
| 184 | ulg static_len; /* bit length of current block with static trees */ | |
| 185 | uint16_t matches; /* number of string matches in current block */ | |
| 186 | uint16_t insert; /* bytes at end of window left to insert */ | |
| 187 | ||
| 188 | #ifdef ZLIB_DEBUG | |
| 189 | ulg compressed_len; /* total bit length of compressed file mod 2^32 */ | |
| 190 | ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ | |
| 191 | #endif | |
| 192 | ||
| 193 | ush bi_buf; | |
| 194 | /* Output buffer. bits are inserted starting at the bottom (least | |
| 195 | * significant bits). | |
| 196 | */ | |
| 197 | int bi_valid; | |
| 198 | /* Number of valid bits in bi_buf. All bits above the last valid bit | |
| 199 | * are always zero. | |
| 200 | */ | |
| 201 | ||
| 202 | ulg high_water; | |
| 203 | /* High water mark offset in window for initialized bytes -- bytes above | |
| 204 | * this are set to zero in order to avoid memory check warnings when | |
| 205 | * longest match routines access bytes past the input. This is then | |
| 206 | * updated to the new high water mark. | |
| 207 | */ | |
| 208 | ||
| 209 | } FAR deflate_state; | |
| 210 | ||
| 211 | fn deflate(strm: &z_stream, flush: int) -> %void { | |
| 212 | ||
| 213 | } | |
| 214 | ||
| 215 | int deflate (z_stream * strm, int flush) { | |
| 216 | int old_flush; /* value of flush param for previous deflate call */ | |
| 217 | deflate_state *s; | |
| 218 | ||
| 219 | if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { | |
| 220 | return Z_STREAM_ERROR; | |
| 221 | } | |
| 222 | s = strm->state; | |
| 223 | ||
| 224 | if (strm->next_out == Z_NULL || | |
| 225 | (strm->avail_in != 0 && strm->next_in == Z_NULL) || | |
| 226 | (s->status == FINISH_STATE && flush != Z_FINISH)) { | |
| 227 | ERR_RETURN(strm, Z_STREAM_ERROR); | |
| 228 | } | |
| 229 | if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); | |
| 230 | ||
| 231 | old_flush = s->last_flush; | |
| 232 | s->last_flush = flush; | |
| 233 | ||
| 234 | /* Flush as much pending output as possible */ | |
| 235 | if (s->pending != 0) { | |
| 236 | flush_pending(strm); | |
| 237 | if (strm->avail_out == 0) { | |
| 238 | /* Since avail_out is 0, deflate will be called again with | |
| 239 | * more output space, but possibly with both pending and | |
| 240 | * avail_in equal to zero. There won't be anything to do, | |
| 241 | * but this is not an error situation so make sure we | |
| 242 | * return OK instead of BUF_ERROR at next call of deflate: | |
| 243 | */ | |
| 244 | s->last_flush = -1; | |
| 245 | return Z_OK; | |
| 246 | } | |
| 247 | ||
| 248 | /* Make sure there is something to do and avoid duplicate consecutive | |
| 249 | * flushes. For repeated and useless calls with Z_FINISH, we keep | |
| 250 | * returning Z_STREAM_END instead of Z_BUF_ERROR. | |
| 251 | */ | |
| 252 | } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && | |
| 253 | flush != Z_FINISH) { | |
| 254 | ERR_RETURN(strm, Z_BUF_ERROR); | |
| 255 | } | |
| 256 | ||
| 257 | /* User must not provide more input after the first FINISH: */ | |
| 258 | if (s->status == FINISH_STATE && strm->avail_in != 0) { | |
| 259 | ERR_RETURN(strm, Z_BUF_ERROR); | |
| 260 | } | |
| 261 | ||
| 262 | /* Write the header */ | |
| 263 | if (s->status == INIT_STATE) { | |
| 264 | /* zlib header */ | |
| 265 | uint16_t header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; | |
| 266 | uint16_t level_flags; | |
| 267 | ||
| 268 | if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) | |
| 269 | level_flags = 0; | |
| 270 | else if (s->level < 6) | |
| 271 | level_flags = 1; | |
| 272 | else if (s->level == 6) | |
| 273 | level_flags = 2; | |
| 274 | else | |
| 275 | level_flags = 3; | |
| 276 | header |= (level_flags << 6); | |
| 277 | if (s->strstart != 0) header |= PRESET_DICT; | |
| 278 | header += 31 - (header % 31); | |
| 279 | ||
| 280 | putShortMSB(s, header); | |
| 281 | ||
| 282 | /* Save the adler32 of the preset dictionary: */ | |
| 283 | if (s->strstart != 0) { | |
| 284 | putShortMSB(s, (uint16_t)(strm->adler >> 16)); | |
| 285 | putShortMSB(s, (uint16_t)(strm->adler & 0xffff)); | |
| 286 | } | |
| 287 | strm->adler = adler32(0L, Z_NULL, 0); | |
| 288 | s->status = BUSY_STATE; | |
| 289 | ||
| 290 | /* Compression must start with an empty pending buffer */ | |
| 291 | flush_pending(strm); | |
| 292 | if (s->pending != 0) { | |
| 293 | s->last_flush = -1; | |
| 294 | return Z_OK; | |
| 295 | } | |
| 296 | } | |
| 297 | #ifdef GZIP | |
| 298 | if (s->status == GZIP_STATE) { | |
| 299 | /* gzip header */ | |
| 300 | strm->adler = crc32(0L, Z_NULL, 0); | |
| 301 | put_byte(s, 31); | |
| 302 | put_byte(s, 139); | |
| 303 | put_byte(s, 8); | |
| 304 | if (s->gzhead == Z_NULL) { | |
| 305 | put_byte(s, 0); | |
| 306 | put_byte(s, 0); | |
| 307 | put_byte(s, 0); | |
| 308 | put_byte(s, 0); | |
| 309 | put_byte(s, 0); | |
| 310 | put_byte(s, s->level == 9 ? 2 : | |
| 311 | (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? | |
| 312 | 4 : 0)); | |
| 313 | put_byte(s, OS_CODE); | |
| 314 | s->status = BUSY_STATE; | |
| 315 | ||
| 316 | /* Compression must start with an empty pending buffer */ | |
| 317 | flush_pending(strm); | |
| 318 | if (s->pending != 0) { | |
| 319 | s->last_flush = -1; | |
| 320 | return Z_OK; | |
| 321 | } | |
| 322 | } | |
| 323 | else { | |
| 324 | put_byte(s, (s->gzhead->text ? 1 : 0) + | |
| 325 | (s->gzhead->hcrc ? 2 : 0) + | |
| 326 | (s->gzhead->extra == Z_NULL ? 0 : 4) + | |
| 327 | (s->gzhead->name == Z_NULL ? 0 : 8) + | |
| 328 | (s->gzhead->comment == Z_NULL ? 0 : 16) | |
| 329 | ); | |
| 330 | put_byte(s, (uint8_t)(s->gzhead->time & 0xff)); | |
| 331 | put_byte(s, (uint8_t)((s->gzhead->time >> 8) & 0xff)); | |
| 332 | put_byte(s, (uint8_t)((s->gzhead->time >> 16) & 0xff)); | |
| 333 | put_byte(s, (uint8_t)((s->gzhead->time >> 24) & 0xff)); | |
| 334 | put_byte(s, s->level == 9 ? 2 : | |
| 335 | (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? | |
| 336 | 4 : 0)); | |
| 337 | put_byte(s, s->gzhead->os & 0xff); | |
| 338 | if (s->gzhead->extra != Z_NULL) { | |
| 339 | put_byte(s, s->gzhead->extra_len & 0xff); | |
| 340 | put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); | |
| 341 | } | |
| 342 | if (s->gzhead->hcrc) | |
| 343 | strm->adler = crc32(strm->adler, s->pending_buf, | |
| 344 | s->pending); | |
| 345 | s->gzindex = 0; | |
| 346 | s->status = EXTRA_STATE; | |
| 347 | } | |
| 348 | } | |
| 349 | if (s->status == EXTRA_STATE) { | |
| 350 | if (s->gzhead->extra != Z_NULL) { | |
| 351 | ulg beg = s->pending; /* start of bytes to update crc */ | |
| 352 | uint16_t left = (s->gzhead->extra_len & 0xffff) - s->gzindex; | |
| 353 | while (s->pending + left > s->pending_buf_size) { | |
| 354 | uint16_t copy = s->pending_buf_size - s->pending; | |
| 355 | zmemcpy(s->pending_buf + s->pending, | |
| 356 | s->gzhead->extra + s->gzindex, copy); | |
| 357 | s->pending = s->pending_buf_size; | |
| 358 | HCRC_UPDATE(beg); | |
| 359 | s->gzindex += copy; | |
| 360 | flush_pending(strm); | |
| 361 | if (s->pending != 0) { | |
| 362 | s->last_flush = -1; | |
| 363 | return Z_OK; | |
| 364 | } | |
| 365 | beg = 0; | |
| 366 | left -= copy; | |
| 367 | } | |
| 368 | zmemcpy(s->pending_buf + s->pending, | |
| 369 | s->gzhead->extra + s->gzindex, left); | |
| 370 | s->pending += left; | |
| 371 | HCRC_UPDATE(beg); | |
| 372 | s->gzindex = 0; | |
| 373 | } | |
| 374 | s->status = NAME_STATE; | |
| 375 | } | |
| 376 | if (s->status == NAME_STATE) { | |
| 377 | if (s->gzhead->name != Z_NULL) { | |
| 378 | ulg beg = s->pending; /* start of bytes to update crc */ | |
| 379 | int val; | |
| 380 | do { | |
| 381 | if (s->pending == s->pending_buf_size) { | |
| 382 | HCRC_UPDATE(beg); | |
| 383 | flush_pending(strm); | |
| 384 | if (s->pending != 0) { | |
| 385 | s->last_flush = -1; | |
| 386 | return Z_OK; | |
| 387 | } | |
| 388 | beg = 0; | |
| 389 | } | |
| 390 | val = s->gzhead->name[s->gzindex++]; | |
| 391 | put_byte(s, val); | |
| 392 | } while (val != 0); | |
| 393 | HCRC_UPDATE(beg); | |
| 394 | s->gzindex = 0; | |
| 395 | } | |
| 396 | s->status = COMMENT_STATE; | |
| 397 | } | |
| 398 | if (s->status == COMMENT_STATE) { | |
| 399 | if (s->gzhead->comment != Z_NULL) { | |
| 400 | ulg beg = s->pending; /* start of bytes to update crc */ | |
| 401 | int val; | |
| 402 | do { | |
| 403 | if (s->pending == s->pending_buf_size) { | |
| 404 | HCRC_UPDATE(beg); | |
| 405 | flush_pending(strm); | |
| 406 | if (s->pending != 0) { | |
| 407 | s->last_flush = -1; | |
| 408 | return Z_OK; | |
| 409 | } | |
| 410 | beg = 0; | |
| 411 | } | |
| 412 | val = s->gzhead->comment[s->gzindex++]; | |
| 413 | put_byte(s, val); | |
| 414 | } while (val != 0); | |
| 415 | HCRC_UPDATE(beg); | |
| 416 | } | |
| 417 | s->status = HCRC_STATE; | |
| 418 | } | |
| 419 | if (s->status == HCRC_STATE) { | |
| 420 | if (s->gzhead->hcrc) { | |
| 421 | if (s->pending + 2 > s->pending_buf_size) { | |
| 422 | flush_pending(strm); | |
| 423 | if (s->pending != 0) { | |
| 424 | s->last_flush = -1; | |
| 425 | return Z_OK; | |
| 426 | } | |
| 427 | } | |
| 428 | put_byte(s, (uint8_t)(strm->adler & 0xff)); | |
| 429 | put_byte(s, (uint8_t)((strm->adler >> 8) & 0xff)); | |
| 430 | strm->adler = crc32(0L, Z_NULL, 0); | |
| 431 | } | |
| 432 | s->status = BUSY_STATE; | |
| 433 | ||
| 434 | /* Compression must start with an empty pending buffer */ | |
| 435 | flush_pending(strm); | |
| 436 | if (s->pending != 0) { | |
| 437 | s->last_flush = -1; | |
| 438 | return Z_OK; | |
| 439 | } | |
| 440 | } | |
| 441 | #endif | |
| 442 | ||
| 443 | /* Start a new block or continue the current one. | |
| 444 | */ | |
| 445 | if (strm->avail_in != 0 || s->lookahead != 0 || | |
| 446 | (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { | |
| 447 | block_state bstate; | |
| 448 | ||
| 449 | bstate = s->level == 0 ? deflate_stored(s, flush) : | |
| 450 | s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : | |
| 451 | s->strategy == Z_RLE ? deflate_rle(s, flush) : | |
| 452 | (*(configuration_table[s->level].func))(s, flush); | |
| 453 | ||
| 454 | if (bstate == finish_started || bstate == finish_done) { | |
| 455 | s->status = FINISH_STATE; | |
| 456 | } | |
| 457 | if (bstate == need_more || bstate == finish_started) { | |
| 458 | if (strm->avail_out == 0) { | |
| 459 | s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ | |
| 460 | } | |
| 461 | return Z_OK; | |
| 462 | /* If flush != Z_NO_FLUSH && avail_out == 0, the next call | |
| 463 | * of deflate should use the same flush parameter to make sure | |
| 464 | * that the flush is complete. So we don't have to output an | |
| 465 | * empty block here, this will be done at next call. This also | |
| 466 | * ensures that for a very small output buffer, we emit at most | |
| 467 | * one empty block. | |
| 468 | */ | |
| 469 | } | |
| 470 | if (bstate == block_done) { | |
| 471 | if (flush == Z_PARTIAL_FLUSH) { | |
| 472 | _tr_align(s); | |
| 473 | } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ | |
| 474 | _tr_stored_block(s, (char*)0, 0L, 0); | |
| 475 | /* For a full flush, this empty block will be recognized | |
| 476 | * as a special marker by inflate_sync(). | |
| 477 | */ | |
| 478 | if (flush == Z_FULL_FLUSH) { | |
| 479 | CLEAR_HASH(s); /* forget history */ | |
| 480 | if (s->lookahead == 0) { | |
| 481 | s->strstart = 0; | |
| 482 | s->block_start = 0L; | |
| 483 | s->insert = 0; | |
| 484 | } | |
| 485 | } | |
| 486 | } | |
| 487 | flush_pending(strm); | |
| 488 | if (strm->avail_out == 0) { | |
| 489 | s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ | |
| 490 | return Z_OK; | |
| 491 | } | |
| 492 | } | |
| 493 | } | |
| 494 | ||
| 495 | if (flush != Z_FINISH) return Z_OK; | |
| 496 | if (s->wrap <= 0) return Z_STREAM_END; | |
| 497 | ||
| 498 | /* Write the trailer */ | |
| 499 | #ifdef GZIP | |
| 500 | if (s->wrap == 2) { | |
| 501 | put_byte(s, (uint8_t)(strm->adler & 0xff)); | |
| 502 | put_byte(s, (uint8_t)((strm->adler >> 8) & 0xff)); | |
| 503 | put_byte(s, (uint8_t)((strm->adler >> 16) & 0xff)); | |
| 504 | put_byte(s, (uint8_t)((strm->adler >> 24) & 0xff)); | |
| 505 | put_byte(s, (uint8_t)(strm->total_in & 0xff)); | |
| 506 | put_byte(s, (uint8_t)((strm->total_in >> 8) & 0xff)); | |
| 507 | put_byte(s, (uint8_t)((strm->total_in >> 16) & 0xff)); | |
| 508 | put_byte(s, (uint8_t)((strm->total_in >> 24) & 0xff)); | |
| 509 | } | |
| 510 | else | |
| 511 | #endif | |
| 512 | { | |
| 513 | putShortMSB(s, (uint16_t)(strm->adler >> 16)); | |
| 514 | putShortMSB(s, (uint16_t)(strm->adler & 0xffff)); | |
| 515 | } | |
| 516 | flush_pending(strm); | |
| 517 | /* If avail_out is zero, the application will call deflate again | |
| 518 | * to flush the rest. | |
| 519 | */ | |
| 520 | if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ | |
| 521 | return s->pending != 0 ? Z_OK : Z_STREAM_END; | |
| 522 | } |
std/zlib/inflate.zig deleted-969| ... | ... | @@ -1,969 +0,0 @@ |
| 1 | ||
| 2 | error Z_STREAM_ERROR; | |
| 3 | error Z_STREAM_END; | |
| 4 | error Z_NEED_DICT; | |
| 5 | error Z_ERRNO; | |
| 6 | error Z_STREAM_ERROR; | |
| 7 | error Z_DATA_ERROR; | |
| 8 | error Z_MEM_ERROR; | |
| 9 | error Z_BUF_ERROR; | |
| 10 | error Z_VERSION_ERROR; | |
| 11 | ||
| 12 | pub Flush = enum { | |
| 13 | NO_FLUSH, | |
| 14 | PARTIAL_FLUSH, | |
| 15 | SYNC_FLUSH, | |
| 16 | FULL_FLUSH, | |
| 17 | FINISH, | |
| 18 | BLOCK, | |
| 19 | TREES, | |
| 20 | }; | |
| 21 | ||
| 22 | const code = struct { | |
| 23 | /// operation, extra bits, table bits | |
| 24 | op: u8, | |
| 25 | /// bits in this part of the code | |
| 26 | bits: u8, | |
| 27 | /// offset in table or code value | |
| 28 | val: u16, | |
| 29 | }; | |
| 30 | ||
| 31 | /// State maintained between inflate() calls -- approximately 7K bytes, not | |
| 32 | /// including the allocated sliding window, which is up to 32K bytes. | |
| 33 | const inflate_state = struct { | |
| 34 | z_stream * strm; /* pointer back to this zlib stream */ | |
| 35 | inflate_mode mode; /* current inflate mode */ | |
| 36 | int last; /* true if processing last block */ | |
| 37 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip, | |
| 38 | bit 2 true to validate check value */ | |
| 39 | int havedict; /* true if dictionary provided */ | |
| 40 | int flags; /* gzip header method and flags (0 if zlib) */ | |
| 41 | unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ | |
| 42 | unsigned long check; /* protected copy of check value */ | |
| 43 | unsigned long total; /* protected copy of output count */ | |
| 44 | gz_headerp head; /* where to save gzip header information */ | |
| 45 | /* sliding window */ | |
| 46 | unsigned wbits; /* log base 2 of requested window size */ | |
| 47 | unsigned wsize; /* window size or zero if not using window */ | |
| 48 | unsigned whave; /* valid bytes in the window */ | |
| 49 | unsigned wnext; /* window write index */ | |
| 50 | u8 FAR *window; /* allocated sliding window, if needed */ | |
| 51 | /* bit accumulator */ | |
| 52 | unsigned long hold; /* input bit accumulator */ | |
| 53 | unsigned bits; /* number of bits in "in" */ | |
| 54 | /* for string and stored block copying */ | |
| 55 | unsigned length; /* literal or length of data to copy */ | |
| 56 | unsigned offset; /* distance back to copy string from */ | |
| 57 | /* for table and code decoding */ | |
| 58 | unsigned extra; /* extra bits needed */ | |
| 59 | /* fixed and dynamic code tables */ | |
| 60 | code const FAR *lencode; /* starting table for length/literal codes */ | |
| 61 | code const FAR *distcode; /* starting table for distance codes */ | |
| 62 | unsigned lenbits; /* index bits for lencode */ | |
| 63 | unsigned distbits; /* index bits for distcode */ | |
| 64 | /* dynamic table building */ | |
| 65 | unsigned ncode; /* number of code length code lengths */ | |
| 66 | unsigned nlen; /* number of length code lengths */ | |
| 67 | unsigned ndist; /* number of distance code lengths */ | |
| 68 | unsigned have; /* number of code lengths in lens[] */ | |
| 69 | code FAR *next; /* next available space in codes[] */ | |
| 70 | unsigned short lens[320]; /* temporary storage for code lengths */ | |
| 71 | unsigned short work[288]; /* work area for code table building */ | |
| 72 | code codes[ENOUGH]; /* space for code tables */ | |
| 73 | int sane; /* if false, allow invalid distance too far */ | |
| 74 | int back; /* bits back of last unprocessed length/lit */ | |
| 75 | unsigned was; /* initial length of match */ | |
| 76 | }; | |
| 77 | ||
| 78 | const alloc_func = fn(opaque: &c_void, items: u16, size: u16); | |
| 79 | const free_func = fn(opaque: &c_void, address: &c_void); | |
| 80 | ||
| 81 | const z_stream = struct { | |
| 82 | /// next input byte | |
| 83 | next_in: &u8, | |
| 84 | /// number of bytes available at next_in | |
| 85 | avail_in: u16, | |
| 86 | /// total number of input bytes read so far | |
| 87 | total_in: u32, | |
| 88 | ||
| 89 | /// next output byte will go here | |
| 90 | next_out: &u8, | |
| 91 | /// remaining free space at next_out | |
| 92 | avail_out: u16, | |
| 93 | /// total number of bytes output so far */ | |
| 94 | total_out: u32, | |
| 95 | ||
| 96 | /// last error message, NULL if no error | |
| 97 | msg: &const u8, | |
| 98 | /// not visible by applications | |
| 99 | state: &inflate_state, | |
| 100 | ||
| 101 | /// used to allocate the internal state | |
| 102 | zalloc: alloc_func, | |
| 103 | /// used to free the internal state | |
| 104 | zfree: free_func, | |
| 105 | /// private data object passed to zalloc and zfree | |
| 106 | opaque: &c_void, | |
| 107 | ||
| 108 | /// best guess about the data type: binary or text | |
| 109 | /// for deflate, or the decoding state for inflate | |
| 110 | data_type: i32, | |
| 111 | ||
| 112 | /// Adler-32 or CRC-32 value of the uncompressed data | |
| 113 | adler: u32, | |
| 114 | }; | |
| 115 | ||
| 116 | // Possible inflate modes between inflate() calls | |
| 117 | /// i: waiting for magic header | |
| 118 | pub const HEAD = 16180; | |
| 119 | /// i: waiting for method and flags (gzip) | |
| 120 | pub const FLAGS = 16181; | |
| 121 | /// i: waiting for modification time (gzip) | |
| 122 | pub const TIME = 16182; | |
| 123 | /// i: waiting for extra flags and operating system (gzip) | |
| 124 | pub const OS = 16183; | |
| 125 | /// i: waiting for extra length (gzip) | |
| 126 | pub const EXLEN = 16184; | |
| 127 | /// i: waiting for extra bytes (gzip) | |
| 128 | pub const EXTRA = 16185; | |
| 129 | /// i: waiting for end of file name (gzip) | |
| 130 | pub const NAME = 16186; | |
| 131 | /// i: waiting for end of comment (gzip) | |
| 132 | pub const COMMENT = 16187; | |
| 133 | /// i: waiting for header crc (gzip) | |
| 134 | pub const HCRC = 16188; | |
| 135 | /// i: waiting for dictionary check value | |
| 136 | pub const DICTID = 16189; | |
| 137 | /// waiting for inflateSetDictionary() call | |
| 138 | pub const DICT = 16190; | |
| 139 | /// i: waiting for type bits, including last-flag bit | |
| 140 | pub const TYPE = 16191; | |
| 141 | /// i: same, but skip check to exit inflate on new block | |
| 142 | pub const TYPEDO = 16192; | |
| 143 | /// i: waiting for stored size (length and complement) | |
| 144 | pub const STORED = 16193; | |
| 145 | /// i/o: same as COPY below, but only first time in | |
| 146 | pub const COPY_ = 16194; | |
| 147 | /// i/o: waiting for input or output to copy stored block | |
| 148 | pub const COPY = 16195; | |
| 149 | /// i: waiting for dynamic block table lengths | |
| 150 | pub const TABLE = 16196; | |
| 151 | /// i: waiting for code length code lengths | |
| 152 | pub const LENLENS = 16197; | |
| 153 | /// i: waiting for length/lit and distance code lengths | |
| 154 | pub const CODELENS = 16198; | |
| 155 | /// i: same as LEN below, but only first time in | |
| 156 | pub const LEN_ = 16199; | |
| 157 | /// i: waiting for length/lit/eob code | |
| 158 | pub const LEN = 16200; | |
| 159 | /// i: waiting for length extra bits | |
| 160 | pub const LENEXT = 16201; | |
| 161 | /// i: waiting for distance code | |
| 162 | pub const DIST = 16202; | |
| 163 | /// i: waiting for distance extra bits | |
| 164 | pub const DISTEXT = 16203; | |
| 165 | /// o: waiting for output space to copy string | |
| 166 | pub const MATCH = 16204; | |
| 167 | /// o: waiting for output space to write literal | |
| 168 | pub const LIT = 16205; | |
| 169 | /// i: waiting for 32-bit check value | |
| 170 | pub const CHECK = 16206; | |
| 171 | /// i: waiting for 32-bit length (gzip) | |
| 172 | pub const LENGTH = 16207; | |
| 173 | /// finished check, done -- remain here until reset | |
| 174 | pub const DONE = 16208; | |
| 175 | /// got a data error -- remain here until reset | |
| 176 | pub const BAD = 16209; | |
| 177 | /// got an inflate() memory error -- remain here until reset | |
| 178 | pub const MEM = 16210; | |
| 179 | /// looking for synchronization bytes to restart inflate() */ | |
| 180 | pub const SYNC = 16211; | |
| 181 | ||
| 182 | /// inflate() uses a state machine to process as much input data and generate as | |
| 183 | /// much output data as possible before returning. The state machine is | |
| 184 | /// structured roughly as follows: | |
| 185 | /// | |
| 186 | /// for (;;) switch (state) { | |
| 187 | /// ... | |
| 188 | /// case STATEn: | |
| 189 | /// if (not enough input data or output space to make progress) | |
| 190 | /// return; | |
| 191 | /// ... make progress ... | |
| 192 | /// state = STATEm; | |
| 193 | /// break; | |
| 194 | /// ... | |
| 195 | /// } | |
| 196 | /// | |
| 197 | /// so when inflate() is called again, the same case is attempted again, and | |
| 198 | /// if the appropriate resources are provided, the machine proceeds to the | |
| 199 | /// next state. The NEEDBITS() macro is usually the way the state evaluates | |
| 200 | /// whether it can proceed or should return. NEEDBITS() does the return if | |
| 201 | /// the requested bits are not available. The typical use of the BITS macros | |
| 202 | /// is: | |
| 203 | /// | |
| 204 | /// NEEDBITS(n); | |
| 205 | /// ... do something with BITS(n) ... | |
| 206 | /// DROPBITS(n); | |
| 207 | /// | |
| 208 | /// where NEEDBITS(n) either returns from inflate() if there isn't enough | |
| 209 | /// input left to load n bits into the accumulator, or it continues. BITS(n) | |
| 210 | /// gives the low n bits in the accumulator. When done, DROPBITS(n) drops | |
| 211 | /// the low n bits off the accumulator. INITBITS() clears the accumulator | |
| 212 | /// and sets the number of available bits to zero. BYTEBITS() discards just | |
| 213 | /// enough bits to put the accumulator on a byte boundary. After BYTEBITS() | |
| 214 | /// and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. | |
| 215 | /// | |
| 216 | /// NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return | |
| 217 | /// if there is no input available. The decoding of variable length codes uses | |
| 218 | /// PULLBYTE() directly in order to pull just enough bytes to decode the next | |
| 219 | /// code, and no more. | |
| 220 | /// | |
| 221 | /// Some states loop until they get enough input, making sure that enough | |
| 222 | /// state information is maintained to continue the loop where it left off | |
| 223 | /// if NEEDBITS() returns in the loop. For example, want, need, and keep | |
| 224 | /// would all have to actually be part of the saved state in case NEEDBITS() | |
| 225 | /// returns: | |
| 226 | /// | |
| 227 | /// case STATEw: | |
| 228 | /// while (want < need) { | |
| 229 | /// NEEDBITS(n); | |
| 230 | /// keep[want++] = BITS(n); | |
| 231 | /// DROPBITS(n); | |
| 232 | /// } | |
| 233 | /// state = STATEx; | |
| 234 | /// case STATEx: | |
| 235 | /// | |
| 236 | /// As shown above, if the next state is also the next case, then the break | |
| 237 | /// is omitted. | |
| 238 | /// | |
| 239 | /// A state may also return if there is not enough output space available to | |
| 240 | /// complete that state. Those states are copying stored data, writing a | |
| 241 | /// literal byte, and copying a matching string. | |
| 242 | /// | |
| 243 | /// When returning, a "goto inf_leave" is used to update the total counters, | |
| 244 | /// update the check value, and determine whether any progress has been made | |
| 245 | /// during that inflate() call in order to return the proper return code. | |
| 246 | /// Progress is defined as a change in either strm->avail_in or strm->avail_out. | |
| 247 | /// When there is a window, goto inf_leave will update the window with the last | |
| 248 | /// output written. If a goto inf_leave occurs in the middle of decompression | |
| 249 | /// and there is no window currently, goto inf_leave will create one and copy | |
| 250 | /// output to the window for the next call of inflate(). | |
| 251 | /// | |
| 252 | /// In this implementation, the flush parameter of inflate() only affects the | |
| 253 | /// return code (per zlib.h). inflate() always writes as much as possible to | |
| 254 | /// strm->next_out, given the space available and the provided input--the effect | |
| 255 | /// documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers | |
| 256 | /// the allocation of and copying into a sliding window until necessary, which | |
| 257 | /// provides the effect documented in zlib.h for Z_FINISH when the entire input | |
| 258 | /// stream available. So the only thing the flush parameter actually does is: | |
| 259 | /// when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it | |
| 260 | /// will return Z_BUF_ERROR if it has not reached the end of the stream. | |
| 261 | pub fn inflate(strm: &z_stream, flush: Flush, gunzip: bool) -> %void { | |
| 262 | // next input | |
| 263 | var next: &const u8 = undefined; | |
| 264 | // next output | |
| 265 | var put: &u8 = undefined; | |
| 266 | ||
| 267 | // available input and output | |
| 268 | var have: u16 = undefined; | |
| 269 | var left: u16 = undefined; | |
| 270 | ||
| 271 | // bit buffer | |
| 272 | var hold: u32 = undefined; | |
| 273 | // bits in bit buffer | |
| 274 | var bits: u16 = undefined; | |
| 275 | // save starting available input and output | |
| 276 | var in: u16 = undefined; | |
| 277 | var out: u16 = undefined; | |
| 278 | // number of stored or match bytes to copy | |
| 279 | var copy: u16 = undefined; | |
| 280 | // where to copy match bytes from | |
| 281 | var from: &u8 = undefined; | |
| 282 | // current decoding table entry | |
| 283 | var here: code = undefined; | |
| 284 | // parent table entry | |
| 285 | var last: code = undefined; | |
| 286 | // length to copy for repeats, bits to drop | |
| 287 | var len: u16 = undefined; | |
| 288 | ||
| 289 | // return code | |
| 290 | var ret: error = undefined; | |
| 291 | ||
| 292 | // buffer for gzip header crc calculation | |
| 293 | var hbuf: [4]u8 = undefined; | |
| 294 | ||
| 295 | // permutation of code lengths | |
| 296 | const short_order = []u16 = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; | |
| 297 | ||
| 298 | if (inflateStateCheck(strm) or strm.next_out == Z_NULL or (strm.next_in == Z_NULL and strm.avail_in != 0)) { | |
| 299 | return error.Z_STREAM_ERROR; | |
| 300 | } | |
| 301 | ||
| 302 | var state: &inflate_state = strm.state; | |
| 303 | if (state.mode == TYPE) { | |
| 304 | state.mode = TYPEDO; // skip check | |
| 305 | } | |
| 306 | put = strm.next_out; \ | |
| 307 | left = strm.avail_out; \ | |
| 308 | next = strm.next_in; \ | |
| 309 | have = strm.avail_in; \ | |
| 310 | hold = state.hold; \ | |
| 311 | bits = state.bits; \ | |
| 312 | in = have; | |
| 313 | out = left; | |
| 314 | ret = Z_OK; | |
| 315 | for (;;) | |
| 316 | switch (state.mode) { | |
| 317 | case HEAD: | |
| 318 | if (state.wrap == 0) { | |
| 319 | state.mode = TYPEDO; | |
| 320 | break; | |
| 321 | } | |
| 322 | NEEDBITS(16); | |
| 323 | #ifdef GUNZIP | |
| 324 | if ((state.wrap & 2) && hold == 0x8b1f) { /* gzip header */ | |
| 325 | if (state.wbits == 0) | |
| 326 | state.wbits = 15; | |
| 327 | state.check = crc32(0L, Z_NULL, 0); | |
| 328 | CRC2(state.check, hold); | |
| 329 | INITBITS(); | |
| 330 | state.mode = FLAGS; | |
| 331 | break; | |
| 332 | } | |
| 333 | state.flags = 0; /* expect zlib header */ | |
| 334 | if (state.head != Z_NULL) | |
| 335 | state.head.done = -1; | |
| 336 | if (!(state.wrap & 1) || /* check if zlib header allowed */ | |
| 337 | #else | |
| 338 | if ( | |
| 339 | #endif | |
| 340 | ((BITS(8) << 8) + (hold >> 8)) % 31) { | |
| 341 | strm.msg = (char *)"incorrect header check"; | |
| 342 | state.mode = BAD; | |
| 343 | break; | |
| 344 | } | |
| 345 | if (BITS(4) != Z_DEFLATED) { | |
| 346 | strm.msg = (char *)"unknown compression method"; | |
| 347 | state.mode = BAD; | |
| 348 | break; | |
| 349 | } | |
| 350 | DROPBITS(4); | |
| 351 | len = BITS(4) + 8; | |
| 352 | if (state.wbits == 0) | |
| 353 | state.wbits = len; | |
| 354 | if (len > 15 || len > state.wbits) { | |
| 355 | strm.msg = (char *)"invalid window size"; | |
| 356 | state.mode = BAD; | |
| 357 | break; | |
| 358 | } | |
| 359 | state.dmax = 1U << len; | |
| 360 | Tracev((stderr, "inflate: zlib header ok\n")); | |
| 361 | strm.adler = state.check = adler32(0L, Z_NULL, 0); | |
| 362 | state.mode = hold & 0x200 ? DICTID : TYPE; | |
| 363 | INITBITS(); | |
| 364 | break; | |
| 365 | #ifdef GUNZIP | |
| 366 | case FLAGS: | |
| 367 | NEEDBITS(16); | |
| 368 | state.flags = (int)(hold); | |
| 369 | if ((state.flags & 0xff) != Z_DEFLATED) { | |
| 370 | strm.msg = (char *)"unknown compression method"; | |
| 371 | state.mode = BAD; | |
| 372 | break; | |
| 373 | } | |
| 374 | if (state.flags & 0xe000) { | |
| 375 | strm.msg = (char *)"unknown header flags set"; | |
| 376 | state.mode = BAD; | |
| 377 | break; | |
| 378 | } | |
| 379 | if (state.head != Z_NULL) | |
| 380 | state.head.text = (int)((hold >> 8) & 1); | |
| 381 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 382 | CRC2(state.check, hold); | |
| 383 | INITBITS(); | |
| 384 | state.mode = TIME; | |
| 385 | case TIME: | |
| 386 | NEEDBITS(32); | |
| 387 | if (state.head != Z_NULL) | |
| 388 | state.head.time = hold; | |
| 389 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 390 | CRC4(state.check, hold); | |
| 391 | INITBITS(); | |
| 392 | state.mode = OS; | |
| 393 | case OS: | |
| 394 | NEEDBITS(16); | |
| 395 | if (state.head != Z_NULL) { | |
| 396 | state.head.xflags = (int)(hold & 0xff); | |
| 397 | state.head.os = (int)(hold >> 8); | |
| 398 | } | |
| 399 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 400 | CRC2(state.check, hold); | |
| 401 | INITBITS(); | |
| 402 | state.mode = EXLEN; | |
| 403 | case EXLEN: | |
| 404 | if (state.flags & 0x0400) { | |
| 405 | NEEDBITS(16); | |
| 406 | state.length = (unsigned)(hold); | |
| 407 | if (state.head != Z_NULL) | |
| 408 | state.head.extra_len = (unsigned)hold; | |
| 409 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 410 | CRC2(state.check, hold); | |
| 411 | INITBITS(); | |
| 412 | } | |
| 413 | else if (state.head != Z_NULL) | |
| 414 | state.head.extra = Z_NULL; | |
| 415 | state.mode = EXTRA; | |
| 416 | case EXTRA: | |
| 417 | if (state.flags & 0x0400) { | |
| 418 | copy = state.length; | |
| 419 | if (copy > have) copy = have; | |
| 420 | if (copy) { | |
| 421 | if (state.head != Z_NULL && | |
| 422 | state.head.extra != Z_NULL) { | |
| 423 | len = state.head.extra_len - state.length; | |
| 424 | zmemcpy(state.head.extra + len, next, | |
| 425 | len + copy > state.head.extra_max ? | |
| 426 | state.head.extra_max - len : copy); | |
| 427 | } | |
| 428 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 429 | state.check = crc32(state.check, next, copy); | |
| 430 | have -= copy; | |
| 431 | next += copy; | |
| 432 | state.length -= copy; | |
| 433 | } | |
| 434 | if (state.length) goto inf_leave; | |
| 435 | } | |
| 436 | state.length = 0; | |
| 437 | state.mode = NAME; | |
| 438 | case NAME: | |
| 439 | if (state.flags & 0x0800) { | |
| 440 | if (have == 0) goto inf_leave; | |
| 441 | copy = 0; | |
| 442 | do { | |
| 443 | len = (unsigned)(next[copy++]); | |
| 444 | if (state.head != Z_NULL && | |
| 445 | state.head.name != Z_NULL && | |
| 446 | state.length < state.head.name_max) | |
| 447 | state.head.name[state.length++] = (Bytef)len; | |
| 448 | } while (len && copy < have); | |
| 449 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 450 | state.check = crc32(state.check, next, copy); | |
| 451 | have -= copy; | |
| 452 | next += copy; | |
| 453 | if (len) goto inf_leave; | |
| 454 | } | |
| 455 | else if (state.head != Z_NULL) | |
| 456 | state.head.name = Z_NULL; | |
| 457 | state.length = 0; | |
| 458 | state.mode = COMMENT; | |
| 459 | case COMMENT: | |
| 460 | if (state.flags & 0x1000) { | |
| 461 | if (have == 0) goto inf_leave; | |
| 462 | copy = 0; | |
| 463 | do { | |
| 464 | len = (unsigned)(next[copy++]); | |
| 465 | if (state.head != Z_NULL && | |
| 466 | state.head.comment != Z_NULL && | |
| 467 | state.length < state.head.comm_max) | |
| 468 | state.head.comment[state.length++] = (Bytef)len; | |
| 469 | } while (len && copy < have); | |
| 470 | if ((state.flags & 0x0200) && (state.wrap & 4)) | |
| 471 | state.check = crc32(state.check, next, copy); | |
| 472 | have -= copy; | |
| 473 | next += copy; | |
| 474 | if (len) goto inf_leave; | |
| 475 | } | |
| 476 | else if (state.head != Z_NULL) | |
| 477 | state.head.comment = Z_NULL; | |
| 478 | state.mode = HCRC; | |
| 479 | case HCRC: | |
| 480 | if (state.flags & 0x0200) { | |
| 481 | NEEDBITS(16); | |
| 482 | if ((state.wrap & 4) && hold != (state.check & 0xffff)) { | |
| 483 | strm.msg = (char *)"header crc mismatch"; | |
| 484 | state.mode = BAD; | |
| 485 | break; | |
| 486 | } | |
| 487 | INITBITS(); | |
| 488 | } | |
| 489 | if (state.head != Z_NULL) { | |
| 490 | state.head.hcrc = (int)((state.flags >> 9) & 1); | |
| 491 | state.head.done = 1; | |
| 492 | } | |
| 493 | strm.adler = state.check = crc32(0L, Z_NULL, 0); | |
| 494 | state.mode = TYPE; | |
| 495 | break; | |
| 496 | #endif | |
| 497 | case DICTID: | |
| 498 | NEEDBITS(32); | |
| 499 | strm.adler = state.check = ZSWAP32(hold); | |
| 500 | INITBITS(); | |
| 501 | state.mode = DICT; | |
| 502 | case DICT: | |
| 503 | if (state.havedict == 0) { | |
| 504 | strm.next_out = put; \ | |
| 505 | strm.avail_out = left; \ | |
| 506 | strm.next_in = next; \ | |
| 507 | strm.avail_in = have; \ | |
| 508 | state.hold = hold; \ | |
| 509 | state.bits = bits; \ | |
| 510 | return Z_NEED_DICT; | |
| 511 | } | |
| 512 | strm.adler = state.check = adler32(0L, Z_NULL, 0); | |
| 513 | state.mode = TYPE; | |
| 514 | case TYPE: | |
| 515 | if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; | |
| 516 | case TYPEDO: | |
| 517 | if (state.last) { | |
| 518 | BYTEBITS(); | |
| 519 | state.mode = CHECK; | |
| 520 | break; | |
| 521 | } | |
| 522 | NEEDBITS(3); | |
| 523 | state.last = BITS(1); | |
| 524 | DROPBITS(1); | |
| 525 | switch (BITS(2)) { | |
| 526 | case 0: /* stored block */ | |
| 527 | Tracev((stderr, "inflate: stored block%s\n", | |
| 528 | state.last ? " (last)" : "")); | |
| 529 | state.mode = STORED; | |
| 530 | break; | |
| 531 | case 1: /* fixed block */ | |
| 532 | fixedtables(state); | |
| 533 | Tracev((stderr, "inflate: fixed codes block%s\n", | |
| 534 | state.last ? " (last)" : "")); | |
| 535 | state.mode = LEN_; /* decode codes */ | |
| 536 | if (flush == Z_TREES) { | |
| 537 | DROPBITS(2); | |
| 538 | goto inf_leave; | |
| 539 | } | |
| 540 | break; | |
| 541 | case 2: /* dynamic block */ | |
| 542 | Tracev((stderr, "inflate: dynamic codes block%s\n", | |
| 543 | state.last ? " (last)" : "")); | |
| 544 | state.mode = TABLE; | |
| 545 | break; | |
| 546 | case 3: | |
| 547 | strm.msg = (char *)"invalid block type"; | |
| 548 | state.mode = BAD; | |
| 549 | } | |
| 550 | DROPBITS(2); | |
| 551 | break; | |
| 552 | case STORED: | |
| 553 | BYTEBITS(); /* go to byte boundary */ | |
| 554 | NEEDBITS(32); | |
| 555 | if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { | |
| 556 | strm.msg = (char *)"invalid stored block lengths"; | |
| 557 | state.mode = BAD; | |
| 558 | break; | |
| 559 | } | |
| 560 | state.length = (unsigned)hold & 0xffff; | |
| 561 | Tracev((stderr, "inflate: stored length %u\n", | |
| 562 | state.length)); | |
| 563 | INITBITS(); | |
| 564 | state.mode = COPY_; | |
| 565 | if (flush == Z_TREES) goto inf_leave; | |
| 566 | case COPY_: | |
| 567 | state.mode = COPY; | |
| 568 | case COPY: | |
| 569 | copy = state.length; | |
| 570 | if (copy) { | |
| 571 | if (copy > have) copy = have; | |
| 572 | if (copy > left) copy = left; | |
| 573 | if (copy == 0) goto inf_leave; | |
| 574 | zmemcpy(put, next, copy); | |
| 575 | have -= copy; | |
| 576 | next += copy; | |
| 577 | left -= copy; | |
| 578 | put += copy; | |
| 579 | state.length -= copy; | |
| 580 | break; | |
| 581 | } | |
| 582 | Tracev((stderr, "inflate: stored end\n")); | |
| 583 | state.mode = TYPE; | |
| 584 | break; | |
| 585 | case TABLE: | |
| 586 | NEEDBITS(14); | |
| 587 | state.nlen = BITS(5) + 257; | |
| 588 | DROPBITS(5); | |
| 589 | state.ndist = BITS(5) + 1; | |
| 590 | DROPBITS(5); | |
| 591 | state.ncode = BITS(4) + 4; | |
| 592 | DROPBITS(4); | |
| 593 | #ifndef PKZIP_BUG_WORKAROUND | |
| 594 | if (state.nlen > 286 || state.ndist > 30) { | |
| 595 | strm.msg = (char *)"too many length or distance symbols"; | |
| 596 | state.mode = BAD; | |
| 597 | break; | |
| 598 | } | |
| 599 | #endif | |
| 600 | Tracev((stderr, "inflate: table sizes ok\n")); | |
| 601 | state.have = 0; | |
| 602 | state.mode = LENLENS; | |
| 603 | case LENLENS: | |
| 604 | while (state.have < state.ncode) { | |
| 605 | NEEDBITS(3); | |
| 606 | state.lens[order[state.have++]] = (unsigned short)BITS(3); | |
| 607 | DROPBITS(3); | |
| 608 | } | |
| 609 | while (state.have < 19) | |
| 610 | state.lens[order[state.have++]] = 0; | |
| 611 | state.next = state.codes; | |
| 612 | state.lencode = (const code FAR *)(state.next); | |
| 613 | state.lenbits = 7; | |
| 614 | ret = inflate_table(CODES, state.lens, 19, &(state.next), | |
| 615 | &(state.lenbits), state.work); | |
| 616 | if (ret) { | |
| 617 | strm.msg = (char *)"invalid code lengths set"; | |
| 618 | state.mode = BAD; | |
| 619 | break; | |
| 620 | } | |
| 621 | Tracev((stderr, "inflate: code lengths ok\n")); | |
| 622 | state.have = 0; | |
| 623 | state.mode = CODELENS; | |
| 624 | case CODELENS: | |
| 625 | while (state.have < state.nlen + state.ndist) { | |
| 626 | for (;;) { | |
| 627 | here = state.lencode[BITS(state.lenbits)]; | |
| 628 | if ((unsigned)(here.bits) <= bits) break; | |
| 629 | PULLBYTE(); | |
| 630 | } | |
| 631 | if (here.val < 16) { | |
| 632 | DROPBITS(here.bits); | |
| 633 | state.lens[state.have++] = here.val; | |
| 634 | } | |
| 635 | else { | |
| 636 | if (here.val == 16) { | |
| 637 | NEEDBITS(here.bits + 2); | |
| 638 | DROPBITS(here.bits); | |
| 639 | if (state.have == 0) { | |
| 640 | strm.msg = (char *)"invalid bit length repeat"; | |
| 641 | state.mode = BAD; | |
| 642 | break; | |
| 643 | } | |
| 644 | len = state.lens[state.have - 1]; | |
| 645 | copy = 3 + BITS(2); | |
| 646 | DROPBITS(2); | |
| 647 | } | |
| 648 | else if (here.val == 17) { | |
| 649 | NEEDBITS(here.bits + 3); | |
| 650 | DROPBITS(here.bits); | |
| 651 | len = 0; | |
| 652 | copy = 3 + BITS(3); | |
| 653 | DROPBITS(3); | |
| 654 | } | |
| 655 | else { | |
| 656 | NEEDBITS(here.bits + 7); | |
| 657 | DROPBITS(here.bits); | |
| 658 | len = 0; | |
| 659 | copy = 11 + BITS(7); | |
| 660 | DROPBITS(7); | |
| 661 | } | |
| 662 | if (state.have + copy > state.nlen + state.ndist) { | |
| 663 | strm.msg = (char *)"invalid bit length repeat"; | |
| 664 | state.mode = BAD; | |
| 665 | break; | |
| 666 | } | |
| 667 | while (copy--) | |
| 668 | state.lens[state.have++] = (unsigned short)len; | |
| 669 | } | |
| 670 | } | |
| 671 | ||
| 672 | /* handle error breaks in while */ | |
| 673 | if (state.mode == BAD) break; | |
| 674 | ||
| 675 | /* check for end-of-block code (better have one) */ | |
| 676 | if (state.lens[256] == 0) { | |
| 677 | strm.msg = (char *)"invalid code -- missing end-of-block"; | |
| 678 | state.mode = BAD; | |
| 679 | break; | |
| 680 | } | |
| 681 | ||
| 682 | /* build code tables -- note: do not change the lenbits or distbits | |
| 683 | values here (9 and 6) without reading the comments in inftrees.h | |
| 684 | concerning the ENOUGH constants, which depend on those values */ | |
| 685 | state.next = state.codes; | |
| 686 | state.lencode = (const code FAR *)(state.next); | |
| 687 | state.lenbits = 9; | |
| 688 | ret = inflate_table(LENS, state.lens, state.nlen, &(state.next), | |
| 689 | &(state.lenbits), state.work); | |
| 690 | if (ret) { | |
| 691 | strm.msg = (char *)"invalid literal/lengths set"; | |
| 692 | state.mode = BAD; | |
| 693 | break; | |
| 694 | } | |
| 695 | state.distcode = (const code FAR *)(state.next); | |
| 696 | state.distbits = 6; | |
| 697 | ret = inflate_table(DISTS, state.lens + state.nlen, state.ndist, | |
| 698 | &(state.next), &(state.distbits), state.work); | |
| 699 | if (ret) { | |
| 700 | strm.msg = (char *)"invalid distances set"; | |
| 701 | state.mode = BAD; | |
| 702 | break; | |
| 703 | } | |
| 704 | Tracev((stderr, "inflate: codes ok\n")); | |
| 705 | state.mode = LEN_; | |
| 706 | if (flush == Z_TREES) goto inf_leave; | |
| 707 | case LEN_: | |
| 708 | state.mode = LEN; | |
| 709 | case LEN: | |
| 710 | if (have >= 6 && left >= 258) { | |
| 711 | strm.next_out = put; \ | |
| 712 | strm.avail_out = left; \ | |
| 713 | strm.next_in = next; \ | |
| 714 | strm.avail_in = have; \ | |
| 715 | state.hold = hold; \ | |
| 716 | state.bits = bits; \ | |
| 717 | ||
| 718 | inflate_fast(strm, out); | |
| 719 | ||
| 720 | put = strm.next_out; \ | |
| 721 | left = strm.avail_out; \ | |
| 722 | next = strm.next_in; \ | |
| 723 | have = strm.avail_in; \ | |
| 724 | hold = state.hold; \ | |
| 725 | bits = state.bits; \ | |
| 726 | if (state.mode == TYPE) | |
| 727 | state.back = -1; | |
| 728 | break; | |
| 729 | } | |
| 730 | state.back = 0; | |
| 731 | for (;;) { | |
| 732 | here = state.lencode[BITS(state.lenbits)]; | |
| 733 | if ((unsigned)(here.bits) <= bits) break; | |
| 734 | PULLBYTE(); | |
| 735 | } | |
| 736 | if (here.op && (here.op & 0xf0) == 0) { | |
| 737 | last = here; | |
| 738 | for (;;) { | |
| 739 | here = state.lencode[last.val + | |
| 740 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 741 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 742 | PULLBYTE(); | |
| 743 | } | |
| 744 | DROPBITS(last.bits); | |
| 745 | state.back += last.bits; | |
| 746 | } | |
| 747 | DROPBITS(here.bits); | |
| 748 | state.back += here.bits; | |
| 749 | state.length = (unsigned)here.val; | |
| 750 | if ((int)(here.op) == 0) { | |
| 751 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? | |
| 752 | "inflate: literal '%c'\n" : | |
| 753 | "inflate: literal 0x%02x\n", here.val)); | |
| 754 | state.mode = LIT; | |
| 755 | break; | |
| 756 | } | |
| 757 | if (here.op & 32) { | |
| 758 | Tracevv((stderr, "inflate: end of block\n")); | |
| 759 | state.back = -1; | |
| 760 | state.mode = TYPE; | |
| 761 | break; | |
| 762 | } | |
| 763 | if (here.op & 64) { | |
| 764 | strm.msg = (char *)"invalid literal/length code"; | |
| 765 | state.mode = BAD; | |
| 766 | break; | |
| 767 | } | |
| 768 | state.extra = (unsigned)(here.op) & 15; | |
| 769 | state.mode = LENEXT; | |
| 770 | case LENEXT: | |
| 771 | if (state.extra) { | |
| 772 | NEEDBITS(state.extra); | |
| 773 | state.length += BITS(state.extra); | |
| 774 | DROPBITS(state.extra); | |
| 775 | state.back += state.extra; | |
| 776 | } | |
| 777 | Tracevv((stderr, "inflate: length %u\n", state.length)); | |
| 778 | state.was = state.length; | |
| 779 | state.mode = DIST; | |
| 780 | case DIST: | |
| 781 | for (;;) { | |
| 782 | here = state.distcode[BITS(state.distbits)]; | |
| 783 | if ((unsigned)(here.bits) <= bits) break; | |
| 784 | PULLBYTE(); | |
| 785 | } | |
| 786 | if ((here.op & 0xf0) == 0) { | |
| 787 | last = here; | |
| 788 | for (;;) { | |
| 789 | here = state.distcode[last.val + | |
| 790 | (BITS(last.bits + last.op) >> last.bits)]; | |
| 791 | if ((unsigned)(last.bits + here.bits) <= bits) break; | |
| 792 | PULLBYTE(); | |
| 793 | } | |
| 794 | DROPBITS(last.bits); | |
| 795 | state.back += last.bits; | |
| 796 | } | |
| 797 | DROPBITS(here.bits); | |
| 798 | state.back += here.bits; | |
| 799 | if (here.op & 64) { | |
| 800 | strm.msg = (char *)"invalid distance code"; | |
| 801 | state.mode = BAD; | |
| 802 | break; | |
| 803 | } | |
| 804 | state.offset = (unsigned)here.val; | |
| 805 | state.extra = (unsigned)(here.op) & 15; | |
| 806 | state.mode = DISTEXT; | |
| 807 | case DISTEXT: | |
| 808 | if (state.extra) { | |
| 809 | NEEDBITS(state.extra); | |
| 810 | state.offset += BITS(state.extra); | |
| 811 | DROPBITS(state.extra); | |
| 812 | state.back += state.extra; | |
| 813 | } | |
| 814 | #ifdef INFLATE_STRICT | |
| 815 | if (state.offset > state.dmax) { | |
| 816 | strm.msg = (char *)"invalid distance too far back"; | |
| 817 | state.mode = BAD; | |
| 818 | break; | |
| 819 | } | |
| 820 | #endif | |
| 821 | Tracevv((stderr, "inflate: distance %u\n", state.offset)); | |
| 822 | state.mode = MATCH; | |
| 823 | case MATCH: | |
| 824 | if (left == 0) goto inf_leave; | |
| 825 | copy = out - left; | |
| 826 | if (state.offset > copy) { /* copy from window */ | |
| 827 | copy = state.offset - copy; | |
| 828 | if (copy > state.whave) { | |
| 829 | if (state.sane) { | |
| 830 | strm.msg = (char *)"invalid distance too far back"; | |
| 831 | state.mode = BAD; | |
| 832 | break; | |
| 833 | } | |
| 834 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR | |
| 835 | Trace((stderr, "inflate.c too far\n")); | |
| 836 | copy -= state.whave; | |
| 837 | if (copy > state.length) copy = state.length; | |
| 838 | if (copy > left) copy = left; | |
| 839 | left -= copy; | |
| 840 | state.length -= copy; | |
| 841 | do { | |
| 842 | *put++ = 0; | |
| 843 | } while (--copy); | |
| 844 | if (state.length == 0) state.mode = LEN; | |
| 845 | break; | |
| 846 | #endif | |
| 847 | } | |
| 848 | if (copy > state.wnext) { | |
| 849 | copy -= state.wnext; | |
| 850 | from = state.window + (state.wsize - copy); | |
| 851 | } | |
| 852 | else | |
| 853 | from = state.window + (state.wnext - copy); | |
| 854 | if (copy > state.length) copy = state.length; | |
| 855 | } | |
| 856 | else { /* copy from output */ | |
| 857 | from = put - state.offset; | |
| 858 | copy = state.length; | |
| 859 | } | |
| 860 | if (copy > left) copy = left; | |
| 861 | left -= copy; | |
| 862 | state.length -= copy; | |
| 863 | do { | |
| 864 | *put++ = *from++; | |
| 865 | } while (--copy); | |
| 866 | if (state.length == 0) state.mode = LEN; | |
| 867 | break; | |
| 868 | case LIT: | |
| 869 | if (left == 0) goto inf_leave; | |
| 870 | *put++ = (u8)(state.length); | |
| 871 | left--; | |
| 872 | state.mode = LEN; | |
| 873 | break; | |
| 874 | case CHECK: | |
| 875 | if (state.wrap) { | |
| 876 | NEEDBITS(32); | |
| 877 | out -= left; | |
| 878 | strm.total_out += out; | |
| 879 | state.total += out; | |
| 880 | if ((state.wrap & 4) && out) | |
| 881 | strm.adler = state.check = | |
| 882 | UPDATE(state.check, put - out, out); | |
| 883 | out = left; | |
| 884 | if ((state.wrap & 4) && ( | |
| 885 | #ifdef GUNZIP | |
| 886 | state.flags ? hold : | |
| 887 | #endif | |
| 888 | ZSWAP32(hold)) != state.check) { | |
| 889 | strm.msg = (char *)"incorrect data check"; | |
| 890 | state.mode = BAD; | |
| 891 | break; | |
| 892 | } | |
| 893 | INITBITS(); | |
| 894 | Tracev((stderr, "inflate: check matches trailer\n")); | |
| 895 | } | |
| 896 | #ifdef GUNZIP | |
| 897 | state.mode = LENGTH; | |
| 898 | case LENGTH: | |
| 899 | if (state.wrap && state.flags) { | |
| 900 | NEEDBITS(32); | |
| 901 | if (hold != (state.total & 0xffffffffUL)) { | |
| 902 | strm.msg = (char *)"incorrect length check"; | |
| 903 | state.mode = BAD; | |
| 904 | break; | |
| 905 | } | |
| 906 | INITBITS(); | |
| 907 | Tracev((stderr, "inflate: length matches trailer\n")); | |
| 908 | } | |
| 909 | #endif | |
| 910 | state.mode = DONE; | |
| 911 | case DONE: | |
| 912 | ret = Z_STREAM_END; | |
| 913 | goto inf_leave; | |
| 914 | case BAD: | |
| 915 | ret = Z_DATA_ERROR; | |
| 916 | goto inf_leave; | |
| 917 | case MEM: | |
| 918 | return Z_MEM_ERROR; | |
| 919 | case SYNC: | |
| 920 | default: | |
| 921 | return Z_STREAM_ERROR; | |
| 922 | } | |
| 923 | ||
| 924 | /* | |
| 925 | Return from inflate(), updating the total counts and the check value. | |
| 926 | If there was no progress during the inflate() call, return a buffer | |
| 927 | error. Call updatewindow() to create and/or update the window state. | |
| 928 | Note: a memory error from inflate() is non-recoverable. | |
| 929 | */ | |
| 930 | inf_leave: | |
| 931 | strm.next_out = put; \ | |
| 932 | strm.avail_out = left; \ | |
| 933 | strm.next_in = next; \ | |
| 934 | strm.avail_in = have; \ | |
| 935 | state.hold = hold; \ | |
| 936 | state.bits = bits; \ | |
| 937 | if (state.wsize || (out != strm.avail_out && state.mode < BAD && | |
| 938 | (state.mode < CHECK || flush != Z_FINISH))) | |
| 939 | if (updatewindow(strm, strm.next_out, out - strm.avail_out)) { | |
| 940 | state.mode = MEM; | |
| 941 | return Z_MEM_ERROR; | |
| 942 | } | |
| 943 | in -= strm.avail_in; | |
| 944 | out -= strm.avail_out; | |
| 945 | strm.total_in += in; | |
| 946 | strm.total_out += out; | |
| 947 | state.total += out; | |
| 948 | if ((state.wrap & 4) && out) | |
| 949 | strm.adler = state.check = | |
| 950 | UPDATE(state.check, strm.next_out - out, out); | |
| 951 | strm.data_type = (int)state.bits + (state.last ? 64 : 0) + | |
| 952 | (state.mode == TYPE ? 128 : 0) + | |
| 953 | (state.mode == LEN_ || state.mode == COPY_ ? 256 : 0); | |
| 954 | if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) | |
| 955 | ret = Z_BUF_ERROR; | |
| 956 | return ret; | |
| 957 | } | |
| 958 | ||
| 959 | local int inflateStateCheck(z_stream * strm) { | |
| 960 | struct inflate_state FAR *state; | |
| 961 | if (strm == Z_NULL || | |
| 962 | strm.zalloc == (alloc_func)0 || strm.zfree == (free_func)0) | |
| 963 | return 1; | |
| 964 | state = (struct inflate_state FAR *)strm.state; | |
| 965 | if (state == Z_NULL || state.strm != strm || | |
| 966 | state.mode < HEAD || state.mode > SYNC) | |
| 967 | return 1; | |
| 968 | return 0; | |
| 969 | } |
test/assemble_and_link.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | 2 | const tests = @import("tests.zig"); |
| 3 | 3 | |
| 4 | pub fn addCases(cases: &tests.CompareOutputContext) { | |
| 4 | pub fn addCases(cases: &tests.CompareOutputContext) void { | |
| 5 | 5 | if (builtin.os == builtin.Os.linux and builtin.arch == builtin.Arch.x86_64) { |
| 6 | 6 | cases.addAsm("hello world linux x86_64", |
| 7 | 7 | \\.text |
test/build_examples.zig+1-1| ... | ... | @@ -2,7 +2,7 @@ const tests = @import("tests.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const is_windows = builtin.os == builtin.Os.windows; |
| 4 | 4 | |
| 5 | pub fn addCases(cases: &tests.BuildExamplesContext) { | |
| 5 | pub fn addCases(cases: &tests.BuildExamplesContext) void { | |
| 6 | 6 | cases.add("example/hello_world/hello.zig"); |
| 7 | 7 | cases.addC("example/hello_world/hello_libc.zig"); |
| 8 | 8 | cases.add("example/cat/main.zig"); |
test/cases/align.zig+23-23| ... | ... | @@ -10,14 +10,14 @@ test "global variable alignment" { |
| 10 | 10 | assert(@typeOf(slice) == []align(4) u8); |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | fn derp() align(@sizeOf(usize) * 2) -> i32 { return 1234; } | |
| 14 | fn noop1() align(1) {} | |
| 15 | fn noop4() align(4) {} | |
| 13 | fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; } | |
| 14 | fn noop1() align(1) void {} | |
| 15 | fn noop4() align(4) void {} | |
| 16 | 16 | |
| 17 | 17 | test "function alignment" { |
| 18 | 18 | assert(derp() == 1234); |
| 19 | assert(@typeOf(noop1) == fn() align(1)); | |
| 20 | assert(@typeOf(noop4) == fn() align(4)); | |
| 19 | assert(@typeOf(noop1) == fn() align(1) void); | |
| 20 | assert(@typeOf(noop4) == fn() align(4) void); | |
| 21 | 21 | noop1(); |
| 22 | 22 | noop4(); |
| 23 | 23 | } |
| ... | ... | @@ -53,19 +53,19 @@ test "implicitly decreasing pointer alignment" { |
| 53 | 53 | assert(addUnaligned(&a, &b) == 7); |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) -> u32 { return *a + *b; } | |
| 56 | fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) u32 { return *a + *b; } | |
| 57 | 57 | |
| 58 | 58 | test "implicitly decreasing slice alignment" { |
| 59 | 59 | const a: u32 align(4) = 3; |
| 60 | 60 | const b: u32 align(8) = 4; |
| 61 | 61 | assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7); |
| 62 | 62 | } |
| 63 | fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) -> u32 { return a[0] + b[0]; } | |
| 63 | fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { return a[0] + b[0]; } | |
| 64 | 64 | |
| 65 | 65 | test "specifying alignment allows pointer cast" { |
| 66 | 66 | testBytesAlign(0x33); |
| 67 | 67 | } |
| 68 | fn testBytesAlign(b: u8) { | |
| 68 | fn testBytesAlign(b: u8) void { | |
| 69 | 69 | var bytes align(4) = []u8{b, b, b, b}; |
| 70 | 70 | const ptr = @ptrCast(&u32, &bytes[0]); |
| 71 | 71 | assert(*ptr == 0x33333333); |
| ... | ... | @@ -74,7 +74,7 @@ fn testBytesAlign(b: u8) { |
| 74 | 74 | test "specifying alignment allows slice cast" { |
| 75 | 75 | testBytesAlignSlice(0x33); |
| 76 | 76 | } |
| 77 | fn testBytesAlignSlice(b: u8) { | |
| 77 | fn testBytesAlignSlice(b: u8) void { | |
| 78 | 78 | var bytes align(4) = []u8{b, b, b, b}; |
| 79 | 79 | const slice = ([]u32)(bytes[0..]); |
| 80 | 80 | assert(slice[0] == 0x33333333); |
| ... | ... | @@ -85,10 +85,10 @@ test "@alignCast pointers" { |
| 85 | 85 | expectsOnly1(&x); |
| 86 | 86 | assert(x == 2); |
| 87 | 87 | } |
| 88 | fn expectsOnly1(x: &align(1) u32) { | |
| 88 | fn expectsOnly1(x: &align(1) u32) void { | |
| 89 | 89 | expects4(@alignCast(4, x)); |
| 90 | 90 | } |
| 91 | fn expects4(x: &align(4) u32) { | |
| 91 | fn expects4(x: &align(4) u32) void { | |
| 92 | 92 | *x += 1; |
| 93 | 93 | } |
| 94 | 94 | |
| ... | ... | @@ -98,10 +98,10 @@ test "@alignCast slices" { |
| 98 | 98 | sliceExpectsOnly1(slice); |
| 99 | 99 | assert(slice[0] == 2); |
| 100 | 100 | } |
| 101 | fn sliceExpectsOnly1(slice: []align(1) u32) { | |
| 101 | fn sliceExpectsOnly1(slice: []align(1) u32) void { | |
| 102 | 102 | sliceExpects4(@alignCast(4, slice)); |
| 103 | 103 | } |
| 104 | fn sliceExpects4(slice: []align(4) u32) { | |
| 104 | fn sliceExpects4(slice: []align(4) u32) void { | |
| 105 | 105 | slice[0] += 1; |
| 106 | 106 | } |
| 107 | 107 | |
| ... | ... | @@ -111,24 +111,24 @@ test "implicitly decreasing fn alignment" { |
| 111 | 111 | testImplicitlyDecreaseFnAlign(alignedBig, 5678); |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) -> i32, answer: i32) { | |
| 114 | fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void { | |
| 115 | 115 | assert(ptr() == answer); |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | fn alignedSmall() align(8) -> i32 { return 1234; } | |
| 119 | fn alignedBig() align(16) -> i32 { return 5678; } | |
| 118 | fn alignedSmall() align(8) i32 { return 1234; } | |
| 119 | fn alignedBig() align(16) i32 { return 5678; } | |
| 120 | 120 | |
| 121 | 121 | |
| 122 | 122 | test "@alignCast functions" { |
| 123 | 123 | assert(fnExpectsOnly1(simple4) == 0x19); |
| 124 | 124 | } |
| 125 | fn fnExpectsOnly1(ptr: fn()align(1) -> i32) -> i32 { | |
| 125 | fn fnExpectsOnly1(ptr: fn()align(1) i32) i32 { | |
| 126 | 126 | return fnExpects4(@alignCast(4, ptr)); |
| 127 | 127 | } |
| 128 | fn fnExpects4(ptr: fn()align(4) -> i32) -> i32 { | |
| 128 | fn fnExpects4(ptr: fn()align(4) i32) i32 { | |
| 129 | 129 | return ptr(); |
| 130 | 130 | } |
| 131 | fn simple4() align(4) -> i32 { return 0x19; } | |
| 131 | fn simple4() align(4) i32 { return 0x19; } | |
| 132 | 132 | |
| 133 | 133 | |
| 134 | 134 | test "generic function with align param" { |
| ... | ... | @@ -137,7 +137,7 @@ test "generic function with align param" { |
| 137 | 137 | assert(whyWouldYouEverDoThis(8) == 0x1); |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) -> u8 { return 0x1; } | |
| 140 | fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { return 0x1; } | |
| 141 | 141 | |
| 142 | 142 | |
| 143 | 143 | test "@ptrCast preserves alignment of bigger source" { |
| ... | ... | @@ -175,10 +175,10 @@ test "compile-time known array index has best alignment possible" { |
| 175 | 175 | testIndex2(&array[0], 2, &u8); |
| 176 | 176 | testIndex2(&array[0], 3, &u8); |
| 177 | 177 | } |
| 178 | fn testIndex(smaller: &align(2) u32, index: usize, comptime T: type) { | |
| 178 | fn testIndex(smaller: &align(2) u32, index: usize, comptime T: type) void { | |
| 179 | 179 | assert(@typeOf(&smaller[index]) == T); |
| 180 | 180 | } |
| 181 | fn testIndex2(ptr: &align(4) u8, index: usize, comptime T: type) { | |
| 181 | fn testIndex2(ptr: &align(4) u8, index: usize, comptime T: type) void { | |
| 182 | 182 | assert(@typeOf(&ptr[index]) == T); |
| 183 | 183 | } |
| 184 | 184 | |
| ... | ... | @@ -187,7 +187,7 @@ test "alignstack" { |
| 187 | 187 | assert(fnWithAlignedStack() == 1234); |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | fn fnWithAlignedStack() -> i32 { | |
| 190 | fn fnWithAlignedStack() i32 { | |
| 191 | 191 | @setAlignStack(256); |
| 192 | 192 | return 1234; |
| 193 | 193 | } |
test/cases/array.zig+1-1| ... | ... | @@ -21,7 +21,7 @@ test "arrays" { |
| 21 | 21 | assert(accumulator == 15); |
| 22 | 22 | assert(getArrayLen(array) == 5); |
| 23 | 23 | } |
| 24 | fn getArrayLen(a: []const u32) -> usize { | |
| 24 | fn getArrayLen(a: []const u32) usize { | |
| 25 | 25 | return a.len; |
| 26 | 26 | } |
| 27 | 27 |
test/cases/asm.zig+2-2| ... | ... | @@ -17,8 +17,8 @@ test "module level assembly" { |
| 17 | 17 | } |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | extern fn aoeu() -> i32; | |
| 20 | extern fn aoeu() i32; | |
| 21 | 21 | |
| 22 | export fn derp() -> i32 { | |
| 22 | export fn derp() i32 { | |
| 23 | 23 | return 1234; |
| 24 | 24 | } |
test/cases/bitcast.zig+3-3| ... | ... | @@ -5,10 +5,10 @@ test "@bitCast i32 -> u32" { |
| 5 | 5 | comptime testBitCast_i32_u32(); |
| 6 | 6 | } |
| 7 | 7 | |
| 8 | fn testBitCast_i32_u32() { | |
| 8 | fn testBitCast_i32_u32() void { | |
| 9 | 9 | assert(conv(-1) == @maxValue(u32)); |
| 10 | 10 | assert(conv2(@maxValue(u32)) == -1); |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | fn conv(x: i32) -> u32 { return @bitCast(u32, x); } | |
| 14 | fn conv2(x: u32) -> i32 { return @bitCast(i32, x); } | |
| 13 | fn conv(x: i32) u32 { return @bitCast(u32, x); } | |
| 14 | fn conv2(x: u32) i32 { return @bitCast(i32, x); } |
test/cases/bool.zig+2-2| ... | ... | @@ -13,7 +13,7 @@ test "cast bool to int" { |
| 13 | 13 | nonConstCastBoolToInt(t, f); |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | fn nonConstCastBoolToInt(t: bool, f: bool) { | |
| 16 | fn nonConstCastBoolToInt(t: bool, f: bool) void { | |
| 17 | 17 | assert(i32(t) == i32(1)); |
| 18 | 18 | assert(i32(f) == i32(0)); |
| 19 | 19 | } |
| ... | ... | @@ -21,7 +21,7 @@ fn nonConstCastBoolToInt(t: bool, f: bool) { |
| 21 | 21 | test "bool cmp" { |
| 22 | 22 | assert(testBoolCmp(true, false) == false); |
| 23 | 23 | } |
| 24 | fn testBoolCmp(a: bool, b: bool) -> bool { | |
| 24 | fn testBoolCmp(a: bool, b: bool) bool { | |
| 25 | 25 | return a == b; |
| 26 | 26 | } |
| 27 | 27 |
test/cases/bugs/655.zig+1-1| ... | ... | @@ -7,6 +7,6 @@ test "function with &const parameter with type dereferenced by namespace" { |
| 7 | 7 | foo(x); |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | fn foo(x: &const other_file.Integer) { | |
| 10 | fn foo(x: &const other_file.Integer) void { | |
| 11 | 11 | std.debug.assert(*x == 1234); |
| 12 | 12 | } |
test/cases/bugs/656.zig+1-1| ... | ... | @@ -13,7 +13,7 @@ test "nullable if after an if in a switch prong of a switch with 2 prongs in an |
| 13 | 13 | foo(false, true); |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | fn foo(a: bool, b: bool) { | |
| 16 | fn foo(a: bool, b: bool) void { | |
| 17 | 17 | var prefix_op = PrefixOp { .AddrOf = Value { .align_expr = 1234 } }; |
| 18 | 18 | if (a) { |
| 19 | 19 | } else { |
test/cases/cast.zig+23-23| ... | ... | @@ -28,7 +28,7 @@ test "implicitly cast a pointer to a const pointer of it" { |
| 28 | 28 | assert(x == 2); |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | fn funcWithConstPtrPtr(x: &const &i32) { | |
| 31 | fn funcWithConstPtrPtr(x: &const &i32) void { | |
| 32 | 32 | **x += 1; |
| 33 | 33 | } |
| 34 | 34 | |
| ... | ... | @@ -37,7 +37,7 @@ test "explicit cast from integer to error type" { |
| 37 | 37 | testCastIntToErr(error.ItBroke); |
| 38 | 38 | comptime testCastIntToErr(error.ItBroke); |
| 39 | 39 | } |
| 40 | fn testCastIntToErr(err: error) { | |
| 40 | fn testCastIntToErr(err: error) void { | |
| 41 | 41 | const x = usize(err); |
| 42 | 42 | const y = error(x); |
| 43 | 43 | assert(error.ItBroke == y); |
| ... | ... | @@ -49,7 +49,7 @@ test "peer resolve arrays of different size to const slice" { |
| 49 | 49 | comptime assert(mem.eql(u8, boolToStr(true), "true")); |
| 50 | 50 | comptime assert(mem.eql(u8, boolToStr(false), "false")); |
| 51 | 51 | } |
| 52 | fn boolToStr(b: bool) -> []const u8 { | |
| 52 | fn boolToStr(b: bool) []const u8 { | |
| 53 | 53 | return if (b) "true" else "false"; |
| 54 | 54 | } |
| 55 | 55 | |
| ... | ... | @@ -58,7 +58,7 @@ test "peer resolve array and const slice" { |
| 58 | 58 | testPeerResolveArrayConstSlice(true); |
| 59 | 59 | comptime testPeerResolveArrayConstSlice(true); |
| 60 | 60 | } |
| 61 | fn testPeerResolveArrayConstSlice(b: bool) { | |
| 61 | fn testPeerResolveArrayConstSlice(b: bool) void { | |
| 62 | 62 | const value1 = if (b) "aoeu" else ([]const u8)("zz"); |
| 63 | 63 | const value2 = if (b) ([]const u8)("zz") else "aoeu"; |
| 64 | 64 | assert(mem.eql(u8, value1, "aoeu")); |
| ... | ... | @@ -82,7 +82,7 @@ test "implicitly cast from T to %?T" { |
| 82 | 82 | const A = struct { |
| 83 | 83 | a: i32, |
| 84 | 84 | }; |
| 85 | fn castToMaybeTypeError(z: i32) { | |
| 85 | fn castToMaybeTypeError(z: i32) void { | |
| 86 | 86 | const x = i32(1); |
| 87 | 87 | const y: %?i32 = x; |
| 88 | 88 | assert(??(try y) == 1); |
| ... | ... | @@ -99,22 +99,22 @@ test "implicitly cast from int to %?T" { |
| 99 | 99 | implicitIntLitToMaybe(); |
| 100 | 100 | comptime implicitIntLitToMaybe(); |
| 101 | 101 | } |
| 102 | fn implicitIntLitToMaybe() { | |
| 102 | fn implicitIntLitToMaybe() void { | |
| 103 | 103 | const f: ?i32 = 1; |
| 104 | 104 | const g: %?i32 = 1; |
| 105 | 105 | } |
| 106 | 106 | |
| 107 | 107 | |
| 108 | test "return null from fn() -> %?&T" { | |
| 108 | test "return null from fn() %?&T" { | |
| 109 | 109 | const a = returnNullFromMaybeTypeErrorRef(); |
| 110 | 110 | const b = returnNullLitFromMaybeTypeErrorRef(); |
| 111 | 111 | assert((try a) == null and (try b) == null); |
| 112 | 112 | } |
| 113 | fn returnNullFromMaybeTypeErrorRef() -> %?&A { | |
| 113 | fn returnNullFromMaybeTypeErrorRef() %?&A { | |
| 114 | 114 | const a: ?&A = null; |
| 115 | 115 | return a; |
| 116 | 116 | } |
| 117 | fn returnNullLitFromMaybeTypeErrorRef() -> %?&A { | |
| 117 | fn returnNullLitFromMaybeTypeErrorRef() %?&A { | |
| 118 | 118 | return null; |
| 119 | 119 | } |
| 120 | 120 | |
| ... | ... | @@ -126,7 +126,7 @@ test "peer type resolution: ?T and T" { |
| 126 | 126 | assert(??peerTypeTAndMaybeT(false, false) == 3); |
| 127 | 127 | } |
| 128 | 128 | } |
| 129 | fn peerTypeTAndMaybeT(c: bool, b: bool) -> ?usize { | |
| 129 | fn peerTypeTAndMaybeT(c: bool, b: bool) ?usize { | |
| 130 | 130 | if (c) { |
| 131 | 131 | return if (b) null else usize(0); |
| 132 | 132 | } |
| ... | ... | @@ -143,7 +143,7 @@ test "peer type resolution: [0]u8 and []const u8" { |
| 143 | 143 | assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); |
| 144 | 144 | } |
| 145 | 145 | } |
| 146 | fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) -> []const u8 { | |
| 146 | fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { | |
| 147 | 147 | if (a) { |
| 148 | 148 | return []const u8 {}; |
| 149 | 149 | } |
| ... | ... | @@ -156,7 +156,7 @@ test "implicitly cast from [N]T to ?[]const T" { |
| 156 | 156 | comptime assert(mem.eql(u8, ??castToMaybeSlice(), "hi")); |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | fn castToMaybeSlice() -> ?[]const u8 { | |
| 159 | fn castToMaybeSlice() ?[]const u8 { | |
| 160 | 160 | return "hi"; |
| 161 | 161 | } |
| 162 | 162 | |
| ... | ... | @@ -166,11 +166,11 @@ test "implicitly cast from [0]T to %[]T" { |
| 166 | 166 | comptime testCastZeroArrayToErrSliceMut(); |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | fn testCastZeroArrayToErrSliceMut() { | |
| 169 | fn testCastZeroArrayToErrSliceMut() void { | |
| 170 | 170 | assert((gimmeErrOrSlice() catch unreachable).len == 0); |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | fn gimmeErrOrSlice() -> %[]u8 { | |
| 173 | fn gimmeErrOrSlice() %[]u8 { | |
| 174 | 174 | return []u8{}; |
| 175 | 175 | } |
| 176 | 176 | |
| ... | ... | @@ -188,7 +188,7 @@ test "peer type resolution: [0]u8, []const u8, and %[]u8" { |
| 188 | 188 | assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); |
| 189 | 189 | } |
| 190 | 190 | } |
| 191 | fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) -> %[]u8 { | |
| 191 | fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) %[]u8 { | |
| 192 | 192 | if (a) { |
| 193 | 193 | return []u8{}; |
| 194 | 194 | } |
| ... | ... | @@ -200,7 +200,7 @@ test "resolve undefined with integer" { |
| 200 | 200 | testResolveUndefWithInt(true, 1234); |
| 201 | 201 | comptime testResolveUndefWithInt(true, 1234); |
| 202 | 202 | } |
| 203 | fn testResolveUndefWithInt(b: bool, x: i32) { | |
| 203 | fn testResolveUndefWithInt(b: bool, x: i32) void { | |
| 204 | 204 | const value = if (b) x else undefined; |
| 205 | 205 | if (b) { |
| 206 | 206 | assert(value == x); |
| ... | ... | @@ -212,7 +212,7 @@ test "implicit cast from &const [N]T to []const T" { |
| 212 | 212 | comptime testCastConstArrayRefToConstSlice(); |
| 213 | 213 | } |
| 214 | 214 | |
| 215 | fn testCastConstArrayRefToConstSlice() { | |
| 215 | fn testCastConstArrayRefToConstSlice() void { | |
| 216 | 216 | const blah = "aoeu"; |
| 217 | 217 | const const_array_ref = &blah; |
| 218 | 218 | assert(@typeOf(const_array_ref) == &const [4]u8); |
| ... | ... | @@ -224,7 +224,7 @@ test "var args implicitly casts by value arg to const ref" { |
| 224 | 224 | foo("hello"); |
| 225 | 225 | } |
| 226 | 226 | |
| 227 | fn foo(args: ...) { | |
| 227 | fn foo(args: ...) void { | |
| 228 | 228 | assert(@typeOf(args[0]) == &const [5]u8); |
| 229 | 229 | } |
| 230 | 230 | |
| ... | ... | @@ -239,13 +239,13 @@ test "peer type resolution: error and [N]T" { |
| 239 | 239 | } |
| 240 | 240 | |
| 241 | 241 | error BadValue; |
| 242 | //fn testPeerErrorAndArray(x: u8) -> %[]const u8 { | |
| 242 | //fn testPeerErrorAndArray(x: u8) %[]const u8 { | |
| 243 | 243 | // return switch (x) { |
| 244 | 244 | // 0x00 => "OK", |
| 245 | 245 | // else => error.BadValue, |
| 246 | 246 | // }; |
| 247 | 247 | //} |
| 248 | fn testPeerErrorAndArray2(x: u8) -> %[]const u8 { | |
| 248 | fn testPeerErrorAndArray2(x: u8) %[]const u8 { | |
| 249 | 249 | return switch (x) { |
| 250 | 250 | 0x00 => "OK", |
| 251 | 251 | 0x01 => "OKK", |
| ... | ... | @@ -265,15 +265,15 @@ test "cast u128 to f128 and back" { |
| 265 | 265 | testCast128(); |
| 266 | 266 | } |
| 267 | 267 | |
| 268 | fn testCast128() { | |
| 268 | fn testCast128() void { | |
| 269 | 269 | assert(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); |
| 270 | 270 | } |
| 271 | 271 | |
| 272 | fn cast128Int(x: f128) -> u128 { | |
| 272 | fn cast128Int(x: f128) u128 { | |
| 273 | 273 | return @bitCast(u128, x); |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | fn cast128Float(x: u128) -> f128 { | |
| 276 | fn cast128Float(x: u128) f128 { | |
| 277 | 277 | return @bitCast(f128, x); |
| 278 | 278 | } |
| 279 | 279 |
test/cases/const_slice_child.zig+4-4| ... | ... | @@ -13,14 +13,14 @@ test "const slice child" { |
| 13 | 13 | bar(strs.len); |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | fn foo(args: [][]const u8) { | |
| 16 | fn foo(args: [][]const u8) void { | |
| 17 | 17 | assert(args.len == 3); |
| 18 | 18 | assert(streql(args[0], "one")); |
| 19 | 19 | assert(streql(args[1], "two")); |
| 20 | 20 | assert(streql(args[2], "three")); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | fn bar(argc: usize) { | |
| 23 | fn bar(argc: usize) void { | |
| 24 | 24 | const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable; |
| 25 | 25 | for (args) |_, i| { |
| 26 | 26 | const ptr = argv[i]; |
| ... | ... | @@ -29,13 +29,13 @@ fn bar(argc: usize) { |
| 29 | 29 | foo(args); |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | fn strlen(ptr: &const u8) -> usize { | |
| 32 | fn strlen(ptr: &const u8) usize { | |
| 33 | 33 | var count: usize = 0; |
| 34 | 34 | while (ptr[count] != 0) : (count += 1) {} |
| 35 | 35 | return count; |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | fn streql(a: []const u8, b: []const u8) -> bool { | |
| 38 | fn streql(a: []const u8, b: []const u8) bool { | |
| 39 | 39 | if (a.len != b.len) return false; |
| 40 | 40 | for (a) |item, index| { |
| 41 | 41 | if (b[index] != item) return false; |
test/cases/defer.zig+3-3| ... | ... | @@ -5,10 +5,10 @@ var index: usize = undefined; |
| 5 | 5 | |
| 6 | 6 | error FalseNotAllowed; |
| 7 | 7 | |
| 8 | fn runSomeErrorDefers(x: bool) -> %bool { | |
| 8 | fn runSomeErrorDefers(x: bool) %bool { | |
| 9 | 9 | index = 0; |
| 10 | 10 | defer {result[index] = 'a'; index += 1;} |
| 11 | %defer {result[index] = 'b'; index += 1;} | |
| 11 | errdefer {result[index] = 'b'; index += 1;} | |
| 12 | 12 | defer {result[index] = 'c'; index += 1;} |
| 13 | 13 | return if (x) x else error.FalseNotAllowed; |
| 14 | 14 | } |
| ... | ... | @@ -33,7 +33,7 @@ test "break and continue inside loop inside defer expression" { |
| 33 | 33 | comptime testBreakContInDefer(10); |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | fn testBreakContInDefer(x: usize) { | |
| 36 | fn testBreakContInDefer(x: usize) void { | |
| 37 | 37 | defer { |
| 38 | 38 | var i: usize = 0; |
| 39 | 39 | while (i < x) : (i += 1) { |
test/cases/enum.zig+13-13| ... | ... | @@ -40,7 +40,7 @@ const Bar = enum { |
| 40 | 40 | D, |
| 41 | 41 | }; |
| 42 | 42 | |
| 43 | fn returnAnInt(x: i32) -> Foo { | |
| 43 | fn returnAnInt(x: i32) Foo { | |
| 44 | 44 | return Foo { .One = x }; |
| 45 | 45 | } |
| 46 | 46 | |
| ... | ... | @@ -52,14 +52,14 @@ test "constant enum with payload" { |
| 52 | 52 | shouldBeNotEmpty(full); |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | fn shouldBeEmpty(x: &const AnEnumWithPayload) { | |
| 55 | fn shouldBeEmpty(x: &const AnEnumWithPayload) void { | |
| 56 | 56 | switch (*x) { |
| 57 | 57 | AnEnumWithPayload.Empty => {}, |
| 58 | 58 | else => unreachable, |
| 59 | 59 | } |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | fn shouldBeNotEmpty(x: &const AnEnumWithPayload) { | |
| 62 | fn shouldBeNotEmpty(x: &const AnEnumWithPayload) void { | |
| 63 | 63 | switch (*x) { |
| 64 | 64 | AnEnumWithPayload.Empty => unreachable, |
| 65 | 65 | else => {}, |
| ... | ... | @@ -89,7 +89,7 @@ test "enum to int" { |
| 89 | 89 | shouldEqual(Number.Four, 4); |
| 90 | 90 | } |
| 91 | 91 | |
| 92 | fn shouldEqual(n: Number, expected: u3) { | |
| 92 | fn shouldEqual(n: Number, expected: u3) void { | |
| 93 | 93 | assert(u3(n) == expected); |
| 94 | 94 | } |
| 95 | 95 | |
| ... | ... | @@ -97,7 +97,7 @@ fn shouldEqual(n: Number, expected: u3) { |
| 97 | 97 | test "int to enum" { |
| 98 | 98 | testIntToEnumEval(3); |
| 99 | 99 | } |
| 100 | fn testIntToEnumEval(x: i32) { | |
| 100 | fn testIntToEnumEval(x: i32) void { | |
| 101 | 101 | assert(IntToEnumNumber(u3(x)) == IntToEnumNumber.Three); |
| 102 | 102 | } |
| 103 | 103 | const IntToEnumNumber = enum { |
| ... | ... | @@ -114,7 +114,7 @@ test "@tagName" { |
| 114 | 114 | comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); |
| 115 | 115 | } |
| 116 | 116 | |
| 117 | fn testEnumTagNameBare(n: BareNumber) -> []const u8 { | |
| 117 | fn testEnumTagNameBare(n: BareNumber) []const u8 { | |
| 118 | 118 | return @tagName(n); |
| 119 | 119 | } |
| 120 | 120 | |
| ... | ... | @@ -270,15 +270,15 @@ test "bit field access with enum fields" { |
| 270 | 270 | assert(data.b == B.Four3); |
| 271 | 271 | } |
| 272 | 272 | |
| 273 | fn getA(data: &const BitFieldOfEnums) -> A { | |
| 273 | fn getA(data: &const BitFieldOfEnums) A { | |
| 274 | 274 | return data.a; |
| 275 | 275 | } |
| 276 | 276 | |
| 277 | fn getB(data: &const BitFieldOfEnums) -> B { | |
| 277 | fn getB(data: &const BitFieldOfEnums) B { | |
| 278 | 278 | return data.b; |
| 279 | 279 | } |
| 280 | 280 | |
| 281 | fn getC(data: &const BitFieldOfEnums) -> C { | |
| 281 | fn getC(data: &const BitFieldOfEnums) C { | |
| 282 | 282 | return data.c; |
| 283 | 283 | } |
| 284 | 284 | |
| ... | ... | @@ -287,7 +287,7 @@ test "casting enum to its tag type" { |
| 287 | 287 | comptime testCastEnumToTagType(Small2.Two); |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | fn testCastEnumToTagType(value: Small2) { | |
| 290 | fn testCastEnumToTagType(value: Small2) void { | |
| 291 | 291 | assert(u2(value) == 1); |
| 292 | 292 | } |
| 293 | 293 | |
| ... | ... | @@ -303,7 +303,7 @@ test "enum with specified tag values" { |
| 303 | 303 | comptime testEnumWithSpecifiedTagValues(MultipleChoice.C); |
| 304 | 304 | } |
| 305 | 305 | |
| 306 | fn testEnumWithSpecifiedTagValues(x: MultipleChoice) { | |
| 306 | fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void { | |
| 307 | 307 | assert(u32(x) == 60); |
| 308 | 308 | assert(1234 == switch (x) { |
| 309 | 309 | MultipleChoice.A => 1, |
| ... | ... | @@ -330,7 +330,7 @@ test "enum with specified and unspecified tag values" { |
| 330 | 330 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); |
| 331 | 331 | } |
| 332 | 332 | |
| 333 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) { | |
| 333 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { | |
| 334 | 334 | assert(u32(x) == 1000); |
| 335 | 335 | assert(1234 == switch (x) { |
| 336 | 336 | MultipleChoice2.A => 1, |
| ... | ... | @@ -354,7 +354,7 @@ const EnumWithOneMember = enum { |
| 354 | 354 | Eof, |
| 355 | 355 | }; |
| 356 | 356 | |
| 357 | fn doALoopThing(id: EnumWithOneMember) { | |
| 357 | fn doALoopThing(id: EnumWithOneMember) void { | |
| 358 | 358 | while (true) { |
| 359 | 359 | if (id == EnumWithOneMember.Eof) { |
| 360 | 360 | break; |
test/cases/enum_with_members.zig+1-1| ... | ... | @@ -6,7 +6,7 @@ const ET = union(enum) { |
| 6 | 6 | SINT: i32, |
| 7 | 7 | UINT: u32, |
| 8 | 8 | |
| 9 | pub fn print(a: &const ET, buf: []u8) -> %usize { | |
| 9 | pub fn print(a: &const ET, buf: []u8) %usize { | |
| 10 | 10 | return switch (*a) { |
| 11 | 11 | ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), |
| 12 | 12 | ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), |
test/cases/error.zig+9-9| ... | ... | @@ -1,16 +1,16 @@ |
| 1 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | const mem = @import("std").mem; |
| 3 | 3 | |
| 4 | pub fn foo() -> %i32 { | |
| 4 | pub fn foo() %i32 { | |
| 5 | 5 | const x = try bar(); |
| 6 | 6 | return x + 1; |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | pub fn bar() -> %i32 { | |
| 9 | pub fn bar() %i32 { | |
| 10 | 10 | return 13; |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | pub fn baz() -> %i32 { | |
| 13 | pub fn baz() %i32 { | |
| 14 | 14 | const y = foo() catch 1234; |
| 15 | 15 | return y + 1; |
| 16 | 16 | } |
| ... | ... | @@ -20,7 +20,7 @@ test "error wrapping" { |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | 22 | error ItBroke; |
| 23 | fn gimmeItBroke() -> []const u8 { | |
| 23 | fn gimmeItBroke() []const u8 { | |
| 24 | 24 | return @errorName(error.ItBroke); |
| 25 | 25 | } |
| 26 | 26 | |
| ... | ... | @@ -47,7 +47,7 @@ test "redefinition of error values allowed" { |
| 47 | 47 | error AnError; |
| 48 | 48 | error AnError; |
| 49 | 49 | error SecondError; |
| 50 | fn shouldBeNotEqual(a: error, b: error) { | |
| 50 | fn shouldBeNotEqual(a: error, b: error) void { | |
| 51 | 51 | if (a == b) unreachable; |
| 52 | 52 | } |
| 53 | 53 | |
| ... | ... | @@ -59,7 +59,7 @@ test "error binary operator" { |
| 59 | 59 | assert(b == 10); |
| 60 | 60 | } |
| 61 | 61 | error ItBroke; |
| 62 | fn errBinaryOperatorG(x: bool) -> %isize { | |
| 62 | fn errBinaryOperatorG(x: bool) %isize { | |
| 63 | 63 | return if (x) error.ItBroke else isize(10); |
| 64 | 64 | } |
| 65 | 65 | |
| ... | ... | @@ -68,18 +68,18 @@ test "unwrap simple value from error" { |
| 68 | 68 | const i = unwrapSimpleValueFromErrorDo() catch unreachable; |
| 69 | 69 | assert(i == 13); |
| 70 | 70 | } |
| 71 | fn unwrapSimpleValueFromErrorDo() -> %isize { return 13; } | |
| 71 | fn unwrapSimpleValueFromErrorDo() %isize { return 13; } | |
| 72 | 72 | |
| 73 | 73 | |
| 74 | 74 | test "error return in assignment" { |
| 75 | 75 | doErrReturnInAssignment() catch unreachable; |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | fn doErrReturnInAssignment() -> %void { | |
| 78 | fn doErrReturnInAssignment() %void { | |
| 79 | 79 | var x : i32 = undefined; |
| 80 | 80 | x = try makeANonErr(); |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | fn makeANonErr() -> %i32 { | |
| 83 | fn makeANonErr() %i32 { | |
| 84 | 84 | return 1; |
| 85 | 85 | } |
test/cases/eval.zig+25-25| ... | ... | @@ -5,14 +5,14 @@ test "compile time recursion" { |
| 5 | 5 | assert(some_data.len == 21); |
| 6 | 6 | } |
| 7 | 7 | var some_data: [usize(fibonacci(7))]u8 = undefined; |
| 8 | fn fibonacci(x: i32) -> i32 { | |
| 8 | fn fibonacci(x: i32) i32 { | |
| 9 | 9 | if (x <= 1) return 1; |
| 10 | 10 | return fibonacci(x - 1) + fibonacci(x - 2); |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | 13 | |
| 14 | 14 | |
| 15 | fn unwrapAndAddOne(blah: ?i32) -> i32 { | |
| 15 | fn unwrapAndAddOne(blah: ?i32) i32 { | |
| 16 | 16 | return ??blah + 1; |
| 17 | 17 | } |
| 18 | 18 | const should_be_1235 = unwrapAndAddOne(1234); |
| ... | ... | @@ -28,7 +28,7 @@ test "inlined loop" { |
| 28 | 28 | assert(sum == 15); |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | fn gimme1or2(comptime a: bool) -> i32 { | |
| 31 | fn gimme1or2(comptime a: bool) i32 { | |
| 32 | 32 | const x: i32 = 1; |
| 33 | 33 | const y: i32 = 2; |
| 34 | 34 | comptime var z: i32 = if (a) x else y; |
| ... | ... | @@ -44,14 +44,14 @@ test "static function evaluation" { |
| 44 | 44 | assert(statically_added_number == 3); |
| 45 | 45 | } |
| 46 | 46 | const statically_added_number = staticAdd(1, 2); |
| 47 | fn staticAdd(a: i32, b: i32) -> i32 { return a + b; } | |
| 47 | fn staticAdd(a: i32, b: i32) i32 { return a + b; } | |
| 48 | 48 | |
| 49 | 49 | |
| 50 | 50 | test "const expr eval on single expr blocks" { |
| 51 | 51 | assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3); |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) -> i32 { | |
| 54 | fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { | |
| 55 | 55 | const literal = 3; |
| 56 | 56 | |
| 57 | 57 | const result = if (b) b: { |
| ... | ... | @@ -77,7 +77,7 @@ const Point = struct { |
| 77 | 77 | y: i32, |
| 78 | 78 | }; |
| 79 | 79 | const static_point_list = []Point { makePoint(1, 2), makePoint(3, 4) }; |
| 80 | fn makePoint(x: i32, y: i32) -> Point { | |
| 80 | fn makePoint(x: i32, y: i32) Point { | |
| 81 | 81 | return Point { |
| 82 | 82 | .x = x, |
| 83 | 83 | .y = y, |
| ... | ... | @@ -93,7 +93,7 @@ const static_vec3 = vec3(0.0, 0.0, 1.0); |
| 93 | 93 | pub const Vec3 = struct { |
| 94 | 94 | data: [3]f32, |
| 95 | 95 | }; |
| 96 | pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 { | |
| 96 | pub fn vec3(x: f32, y: f32, z: f32) Vec3 { | |
| 97 | 97 | return Vec3 { |
| 98 | 98 | .data = []f32 { x, y, z, }, |
| 99 | 99 | }; |
| ... | ... | @@ -156,7 +156,7 @@ test "try to trick eval with runtime if" { |
| 156 | 156 | assert(testTryToTrickEvalWithRuntimeIf(true) == 10); |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | fn testTryToTrickEvalWithRuntimeIf(b: bool) -> usize { | |
| 159 | fn testTryToTrickEvalWithRuntimeIf(b: bool) usize { | |
| 160 | 160 | comptime var i: usize = 0; |
| 161 | 161 | inline while (i < 10) : (i += 1) { |
| 162 | 162 | const result = if (b) false else true; |
| ... | ... | @@ -166,7 +166,7 @@ fn testTryToTrickEvalWithRuntimeIf(b: bool) -> usize { |
| 166 | 166 | } |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | fn max(comptime T: type, a: T, b: T) -> T { | |
| 169 | fn max(comptime T: type, a: T, b: T) T { | |
| 170 | 170 | if (T == bool) { |
| 171 | 171 | return a or b; |
| 172 | 172 | } else if (a > b) { |
| ... | ... | @@ -175,7 +175,7 @@ fn max(comptime T: type, a: T, b: T) -> T { |
| 175 | 175 | return b; |
| 176 | 176 | } |
| 177 | 177 | } |
| 178 | fn letsTryToCompareBools(a: bool, b: bool) -> bool { | |
| 178 | fn letsTryToCompareBools(a: bool, b: bool) bool { | |
| 179 | 179 | return max(bool, a, b); |
| 180 | 180 | } |
| 181 | 181 | test "inlined block and runtime block phi" { |
| ... | ... | @@ -194,7 +194,7 @@ test "inlined block and runtime block phi" { |
| 194 | 194 | |
| 195 | 195 | const CmdFn = struct { |
| 196 | 196 | name: []const u8, |
| 197 | func: fn(i32) -> i32, | |
| 197 | func: fn(i32) i32, | |
| 198 | 198 | }; |
| 199 | 199 | |
| 200 | 200 | const cmd_fns = []CmdFn{ |
| ... | ... | @@ -202,11 +202,11 @@ const cmd_fns = []CmdFn{ |
| 202 | 202 | CmdFn {.name = "two", .func = two}, |
| 203 | 203 | CmdFn {.name = "three", .func = three}, |
| 204 | 204 | }; |
| 205 | fn one(value: i32) -> i32 { return value + 1; } | |
| 206 | fn two(value: i32) -> i32 { return value + 2; } | |
| 207 | fn three(value: i32) -> i32 { return value + 3; } | |
| 205 | fn one(value: i32) i32 { return value + 1; } | |
| 206 | fn two(value: i32) i32 { return value + 2; } | |
| 207 | fn three(value: i32) i32 { return value + 3; } | |
| 208 | 208 | |
| 209 | fn performFn(comptime prefix_char: u8, start_value: i32) -> i32 { | |
| 209 | fn performFn(comptime prefix_char: u8, start_value: i32) i32 { | |
| 210 | 210 | var result: i32 = start_value; |
| 211 | 211 | comptime var i = 0; |
| 212 | 212 | inline while (i < cmd_fns.len) : (i += 1) { |
| ... | ... | @@ -223,13 +223,13 @@ test "comptime iterate over fn ptr list" { |
| 223 | 223 | assert(performFn('w', 99) == 99); |
| 224 | 224 | } |
| 225 | 225 | |
| 226 | test "eval @setDebugSafety at compile-time" { | |
| 227 | const result = comptime fnWithSetDebugSafety(); | |
| 226 | test "eval @setRuntimeSafety at compile-time" { | |
| 227 | const result = comptime fnWithSetRuntimeSafety(); | |
| 228 | 228 | assert(result == 1234); |
| 229 | 229 | } |
| 230 | 230 | |
| 231 | fn fnWithSetDebugSafety() -> i32{ | |
| 232 | @setDebugSafety(this, true); | |
| 231 | fn fnWithSetRuntimeSafety() i32{ | |
| 232 | @setRuntimeSafety(true); | |
| 233 | 233 | return 1234; |
| 234 | 234 | } |
| 235 | 235 | |
| ... | ... | @@ -238,7 +238,7 @@ test "eval @setFloatMode at compile-time" { |
| 238 | 238 | assert(result == 1234.0); |
| 239 | 239 | } |
| 240 | 240 | |
| 241 | fn fnWithFloatMode() -> f32 { | |
| 241 | fn fnWithFloatMode() f32 { | |
| 242 | 242 | @setFloatMode(this, builtin.FloatMode.Strict); |
| 243 | 243 | return 1234.0; |
| 244 | 244 | } |
| ... | ... | @@ -247,7 +247,7 @@ fn fnWithFloatMode() -> f32 { |
| 247 | 247 | const SimpleStruct = struct { |
| 248 | 248 | field: i32, |
| 249 | 249 | |
| 250 | fn method(self: &const SimpleStruct) -> i32 { | |
| 250 | fn method(self: &const SimpleStruct) i32 { | |
| 251 | 251 | return self.field + 3; |
| 252 | 252 | } |
| 253 | 253 | }; |
| ... | ... | @@ -271,7 +271,7 @@ test "ptr to local array argument at comptime" { |
| 271 | 271 | } |
| 272 | 272 | } |
| 273 | 273 | |
| 274 | fn modifySomeBytes(bytes: []u8) { | |
| 274 | fn modifySomeBytes(bytes: []u8) void { | |
| 275 | 275 | bytes[0] = 'a'; |
| 276 | 276 | bytes[9] = 'b'; |
| 277 | 277 | } |
| ... | ... | @@ -280,7 +280,7 @@ fn modifySomeBytes(bytes: []u8) { |
| 280 | 280 | test "comparisons 0 <= uint and 0 > uint should be comptime" { |
| 281 | 281 | testCompTimeUIntComparisons(1234); |
| 282 | 282 | } |
| 283 | fn testCompTimeUIntComparisons(x: u32) { | |
| 283 | fn testCompTimeUIntComparisons(x: u32) void { | |
| 284 | 284 | if (!(0 <= x)) { |
| 285 | 285 | @compileError("this condition should be comptime known"); |
| 286 | 286 | } |
| ... | ... | @@ -339,7 +339,7 @@ test "const global shares pointer with other same one" { |
| 339 | 339 | assertEqualPtrs(&hi1[0], &hi2[0]); |
| 340 | 340 | comptime assert(&hi1[0] == &hi2[0]); |
| 341 | 341 | } |
| 342 | fn assertEqualPtrs(ptr1: &const u8, ptr2: &const u8) { | |
| 342 | fn assertEqualPtrs(ptr1: &const u8, ptr2: &const u8) void { | |
| 343 | 343 | assert(ptr1 == ptr2); |
| 344 | 344 | } |
| 345 | 345 | |
| ... | ... | @@ -376,7 +376,7 @@ test "f128 at compile time is lossy" { |
| 376 | 376 | // TODO need a better implementation of bigfloat_init_bigint |
| 377 | 377 | // assert(f128(1 << 113) == 10384593717069655257060992658440192); |
| 378 | 378 | |
| 379 | pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) -> type { | |
| 379 | pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { | |
| 380 | 380 | return struct { |
| 381 | 381 | pub const Node = struct { }; |
| 382 | 382 | }; |
test/cases/field_parent_ptr.zig+2-2| ... | ... | @@ -24,7 +24,7 @@ const foo = Foo { |
| 24 | 24 | .d = -10, |
| 25 | 25 | }; |
| 26 | 26 | |
| 27 | fn testParentFieldPtr(c: &const i32) { | |
| 27 | fn testParentFieldPtr(c: &const i32) void { | |
| 28 | 28 | assert(c == &foo.c); |
| 29 | 29 | |
| 30 | 30 | const base = @fieldParentPtr(Foo, "c", c); |
| ... | ... | @@ -32,7 +32,7 @@ fn testParentFieldPtr(c: &const i32) { |
| 32 | 32 | assert(&base.c == c); |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | fn testParentFieldPtrFirst(a: &const bool) { | |
| 35 | fn testParentFieldPtrFirst(a: &const bool) void { | |
| 36 | 36 | assert(a == &foo.a); |
| 37 | 37 | |
| 38 | 38 | const base = @fieldParentPtr(Foo, "a", a); |
test/cases/fn.zig+12-12| ... | ... | @@ -3,7 +3,7 @@ const assert = @import("std").debug.assert; |
| 3 | 3 | test "params" { |
| 4 | 4 | assert(testParamsAdd(22, 11) == 33); |
| 5 | 5 | } |
| 6 | fn testParamsAdd(a: i32, b: i32) -> i32 { | |
| 6 | fn testParamsAdd(a: i32, b: i32) i32 { | |
| 7 | 7 | return a + b; |
| 8 | 8 | } |
| 9 | 9 | |
| ... | ... | @@ -11,7 +11,7 @@ fn testParamsAdd(a: i32, b: i32) -> i32 { |
| 11 | 11 | test "local variables" { |
| 12 | 12 | testLocVars(2); |
| 13 | 13 | } |
| 14 | fn testLocVars(b: i32) { | |
| 14 | fn testLocVars(b: i32) void { | |
| 15 | 15 | const a: i32 = 1; |
| 16 | 16 | if (a + b != 3) unreachable; |
| 17 | 17 | } |
| ... | ... | @@ -20,7 +20,7 @@ fn testLocVars(b: i32) { |
| 20 | 20 | test "void parameters" { |
| 21 | 21 | voidFun(1, void{}, 2, {}); |
| 22 | 22 | } |
| 23 | fn voidFun(a: i32, b: void, c: i32, d: void) { | |
| 23 | fn voidFun(a: i32, b: void, c: i32, d: void) void { | |
| 24 | 24 | const v = b; |
| 25 | 25 | const vv: void = if (a == 1) v else {}; |
| 26 | 26 | assert(a + c == 3); |
| ... | ... | @@ -56,10 +56,10 @@ test "call function with empty string" { |
| 56 | 56 | acceptsString(""); |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | fn acceptsString(foo: []u8) { } | |
| 59 | fn acceptsString(foo: []u8) void { } | |
| 60 | 60 | |
| 61 | 61 | |
| 62 | fn @"weird function name"() -> i32 { | |
| 62 | fn @"weird function name"() i32 { | |
| 63 | 63 | return 1234; |
| 64 | 64 | } |
| 65 | 65 | test "weird function name" { |
| ... | ... | @@ -70,9 +70,9 @@ test "implicit cast function unreachable return" { |
| 70 | 70 | wantsFnWithVoid(fnWithUnreachable); |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | fn wantsFnWithVoid(f: fn()) { } | |
| 73 | fn wantsFnWithVoid(f: fn() void) void { } | |
| 74 | 74 | |
| 75 | fn fnWithUnreachable() -> noreturn { | |
| 75 | fn fnWithUnreachable() noreturn { | |
| 76 | 76 | unreachable; |
| 77 | 77 | } |
| 78 | 78 | |
| ... | ... | @@ -83,14 +83,14 @@ test "function pointers" { |
| 83 | 83 | assert(f() == u32(i) + 5); |
| 84 | 84 | } |
| 85 | 85 | } |
| 86 | fn fn1() -> u32 {return 5;} | |
| 87 | fn fn2() -> u32 {return 6;} | |
| 88 | fn fn3() -> u32 {return 7;} | |
| 89 | fn fn4() -> u32 {return 8;} | |
| 86 | fn fn1() u32 {return 5;} | |
| 87 | fn fn2() u32 {return 6;} | |
| 88 | fn fn3() u32 {return 7;} | |
| 89 | fn fn4() u32 {return 8;} | |
| 90 | 90 | |
| 91 | 91 | |
| 92 | 92 | test "inline function call" { |
| 93 | 93 | assert(@inlineCall(add, 3, 9) == 12); |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | fn add(a: i32, b: i32) -> i32 { return a + b; } | |
| 96 | fn add(a: i32, b: i32) i32 { return a + b; } |
test/cases/for.zig+3-3| ... | ... | @@ -22,7 +22,7 @@ test "for loop with pointer elem var" { |
| 22 | 22 | mangleString(target[0..]); |
| 23 | 23 | assert(mem.eql(u8, target, "bcdefgh")); |
| 24 | 24 | } |
| 25 | fn mangleString(s: []u8) { | |
| 25 | fn mangleString(s: []u8) void { | |
| 26 | 26 | for (s) |*c| { |
| 27 | 27 | *c += 1; |
| 28 | 28 | } |
| ... | ... | @@ -61,7 +61,7 @@ test "break from outer for loop" { |
| 61 | 61 | comptime testBreakOuter(); |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | fn testBreakOuter() { | |
| 64 | fn testBreakOuter() void { | |
| 65 | 65 | var array = "aoeu"; |
| 66 | 66 | var count: usize = 0; |
| 67 | 67 | outer: for (array) |_| { |
| ... | ... | @@ -78,7 +78,7 @@ test "continue outer for loop" { |
| 78 | 78 | comptime testContinueOuter(); |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | fn testContinueOuter() { | |
| 81 | fn testContinueOuter() void { | |
| 82 | 82 | var array = "aoeu"; |
| 83 | 83 | var counter: usize = 0; |
| 84 | 84 | outer: for (array) |_| { |
test/cases/generics.zig+19-19| ... | ... | @@ -6,11 +6,11 @@ test "simple generic fn" { |
| 6 | 6 | assert(add(2, 3) == 5); |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | fn max(comptime T: type, a: T, b: T) -> T { | |
| 9 | fn max(comptime T: type, a: T, b: T) T { | |
| 10 | 10 | return if (a > b) a else b; |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | fn add(comptime a: i32, b: i32) -> i32 { | |
| 13 | fn add(comptime a: i32, b: i32) i32 { | |
| 14 | 14 | return (comptime a) + b; |
| 15 | 15 | } |
| 16 | 16 | |
| ... | ... | @@ -19,15 +19,15 @@ test "compile time generic eval" { |
| 19 | 19 | assert(the_max == 5678); |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | fn gimmeTheBigOne(a: u32, b: u32) -> u32 { | |
| 22 | fn gimmeTheBigOne(a: u32, b: u32) u32 { | |
| 23 | 23 | return max(u32, a, b); |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | fn shouldCallSameInstance(a: u32, b: u32) -> u32 { | |
| 26 | fn shouldCallSameInstance(a: u32, b: u32) u32 { | |
| 27 | 27 | return max(u32, a, b); |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | fn sameButWithFloats(a: f64, b: f64) -> f64 { | |
| 30 | fn sameButWithFloats(a: f64, b: f64) f64 { | |
| 31 | 31 | return max(f64, a, b); |
| 32 | 32 | } |
| 33 | 33 | |
| ... | ... | @@ -48,24 +48,24 @@ comptime { |
| 48 | 48 | assert(max_f64(1.2, 3.4) == 3.4); |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | fn max_var(a: var, b: var) -> @typeOf(a + b) { | |
| 51 | fn max_var(a: var, b: var) @typeOf(a + b) { | |
| 52 | 52 | return if (a > b) a else b; |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | fn max_i32(a: i32, b: i32) -> i32 { | |
| 55 | fn max_i32(a: i32, b: i32) i32 { | |
| 56 | 56 | return max_var(a, b); |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | fn max_f64(a: f64, b: f64) -> f64 { | |
| 59 | fn max_f64(a: f64, b: f64) f64 { | |
| 60 | 60 | return max_var(a, b); |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | 63 | |
| 64 | pub fn List(comptime T: type) -> type { | |
| 64 | pub fn List(comptime T: type) type { | |
| 65 | 65 | return SmallList(T, 8); |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type { | |
| 68 | pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type { | |
| 69 | 69 | return struct { |
| 70 | 70 | items: []T, |
| 71 | 71 | length: usize, |
| ... | ... | @@ -90,18 +90,18 @@ test "generic struct" { |
| 90 | 90 | assert(a1.value == a1.getVal()); |
| 91 | 91 | assert(b1.getVal()); |
| 92 | 92 | } |
| 93 | fn GenNode(comptime T: type) -> type { | |
| 93 | fn GenNode(comptime T: type) type { | |
| 94 | 94 | return struct { |
| 95 | 95 | value: T, |
| 96 | 96 | next: ?&GenNode(T), |
| 97 | fn getVal(n: &const GenNode(T)) -> T { return n.value; } | |
| 97 | fn getVal(n: &const GenNode(T)) T { return n.value; } | |
| 98 | 98 | }; |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | 101 | test "const decls in struct" { |
| 102 | 102 | assert(GenericDataThing(3).count_plus_one == 4); |
| 103 | 103 | } |
| 104 | fn GenericDataThing(comptime count: isize) -> type { | |
| 104 | fn GenericDataThing(comptime count: isize) type { | |
| 105 | 105 | return struct { |
| 106 | 106 | const count_plus_one = count + 1; |
| 107 | 107 | }; |
| ... | ... | @@ -111,7 +111,7 @@ fn GenericDataThing(comptime count: isize) -> type { |
| 111 | 111 | test "use generic param in generic param" { |
| 112 | 112 | assert(aGenericFn(i32, 3, 4) == 7); |
| 113 | 113 | } |
| 114 | fn aGenericFn(comptime T: type, comptime a: T, b: T) -> T { | |
| 114 | fn aGenericFn(comptime T: type, comptime a: T, b: T) T { | |
| 115 | 115 | return a + b; |
| 116 | 116 | } |
| 117 | 117 | |
| ... | ... | @@ -120,16 +120,16 @@ test "generic fn with implicit cast" { |
| 120 | 120 | assert(getFirstByte(u8, []u8 {13}) == 13); |
| 121 | 121 | assert(getFirstByte(u16, []u16 {0, 13}) == 0); |
| 122 | 122 | } |
| 123 | fn getByte(ptr: ?&const u8) -> u8 {return *??ptr;} | |
| 124 | fn getFirstByte(comptime T: type, mem: []const T) -> u8 { | |
| 123 | fn getByte(ptr: ?&const u8) u8 {return *??ptr;} | |
| 124 | fn getFirstByte(comptime T: type, mem: []const T) u8 { | |
| 125 | 125 | return getByte(@ptrCast(&const u8, &mem[0])); |
| 126 | 126 | } |
| 127 | 127 | |
| 128 | 128 | |
| 129 | const foos = []fn(var) -> bool { foo1, foo2 }; | |
| 129 | const foos = []fn(var) bool { foo1, foo2 }; | |
| 130 | 130 | |
| 131 | fn foo1(arg: var) -> bool { return arg; } | |
| 132 | fn foo2(arg: var) -> bool { return !arg; } | |
| 131 | fn foo1(arg: var) bool { return arg; } | |
| 132 | fn foo2(arg: var) bool { return !arg; } | |
| 133 | 133 | |
| 134 | 134 | test "array of generic fns" { |
| 135 | 135 | assert(foos[0](true)); |
test/cases/if.zig+3-3| ... | ... | @@ -4,14 +4,14 @@ test "if statements" { |
| 4 | 4 | shouldBeEqual(1, 1); |
| 5 | 5 | firstEqlThird(2, 1, 2); |
| 6 | 6 | } |
| 7 | fn shouldBeEqual(a: i32, b: i32) { | |
| 7 | fn shouldBeEqual(a: i32, b: i32) void { | |
| 8 | 8 | if (a != b) { |
| 9 | 9 | unreachable; |
| 10 | 10 | } else { |
| 11 | 11 | return; |
| 12 | 12 | } |
| 13 | 13 | } |
| 14 | fn firstEqlThird(a: i32, b: i32, c: i32) { | |
| 14 | fn firstEqlThird(a: i32, b: i32, c: i32) void { | |
| 15 | 15 | if (a == b) { |
| 16 | 16 | unreachable; |
| 17 | 17 | } else if (b == c) { |
| ... | ... | @@ -27,7 +27,7 @@ fn firstEqlThird(a: i32, b: i32, c: i32) { |
| 27 | 27 | test "else if expression" { |
| 28 | 28 | assert(elseIfExpressionF(1) == 1); |
| 29 | 29 | } |
| 30 | fn elseIfExpressionF(c: u8) -> u8 { | |
| 30 | fn elseIfExpressionF(c: u8) u8 { | |
| 31 | 31 | if (c == 0) { |
| 32 | 32 | return 0; |
| 33 | 33 | } else if (c == 1) { |
test/cases/import/a_namespace.zig+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | pub fn foo() -> i32 { return 1234; } | |
| 1 | pub fn foo() i32 { return 1234; } |
test/cases/incomplete_struct_param_tld.zig+2-2| ... | ... | @@ -11,12 +11,12 @@ const B = struct { |
| 11 | 11 | const C = struct { |
| 12 | 12 | x: i32, |
| 13 | 13 | |
| 14 | fn d(c: &const C) -> i32 { | |
| 14 | fn d(c: &const C) i32 { | |
| 15 | 15 | return c.x; |
| 16 | 16 | } |
| 17 | 17 | }; |
| 18 | 18 | |
| 19 | fn foo(a: &const A) -> i32 { | |
| 19 | fn foo(a: &const A) i32 { | |
| 20 | 20 | return a.b.c.d(); |
| 21 | 21 | } |
| 22 | 22 |
test/cases/ir_block_deps.zig+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | |
| 3 | fn foo(id: u64) -> %i32 { | |
| 3 | fn foo(id: u64) %i32 { | |
| 4 | 4 | return switch (id) { |
| 5 | 5 | 1 => getErrInt(), |
| 6 | 6 | 2 => { |
| ... | ... | @@ -11,7 +11,7 @@ fn foo(id: u64) -> %i32 { |
| 11 | 11 | }; |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | fn getErrInt() -> %i32 { return 0; } | |
| 14 | fn getErrInt() %i32 { return 0; } | |
| 15 | 15 | |
| 16 | 16 | error ItBroke; |
| 17 | 17 |
test/cases/math.zig+26-26| ... | ... | @@ -4,7 +4,7 @@ test "division" { |
| 4 | 4 | testDivision(); |
| 5 | 5 | comptime testDivision(); |
| 6 | 6 | } |
| 7 | fn testDivision() { | |
| 7 | fn testDivision() void { | |
| 8 | 8 | assert(div(u32, 13, 3) == 4); |
| 9 | 9 | assert(div(f32, 1.0, 2.0) == 0.5); |
| 10 | 10 | |
| ... | ... | @@ -50,16 +50,16 @@ fn testDivision() { |
| 50 | 50 | assert(4126227191251978491697987544882340798050766755606969681711 % 10 == 1); |
| 51 | 51 | } |
| 52 | 52 | } |
| 53 | fn div(comptime T: type, a: T, b: T) -> T { | |
| 53 | fn div(comptime T: type, a: T, b: T) T { | |
| 54 | 54 | return a / b; |
| 55 | 55 | } |
| 56 | fn divExact(comptime T: type, a: T, b: T) -> T { | |
| 56 | fn divExact(comptime T: type, a: T, b: T) T { | |
| 57 | 57 | return @divExact(a, b); |
| 58 | 58 | } |
| 59 | fn divFloor(comptime T: type, a: T, b: T) -> T { | |
| 59 | fn divFloor(comptime T: type, a: T, b: T) T { | |
| 60 | 60 | return @divFloor(a, b); |
| 61 | 61 | } |
| 62 | fn divTrunc(comptime T: type, a: T, b: T) -> T { | |
| 62 | fn divTrunc(comptime T: type, a: T, b: T) T { | |
| 63 | 63 | return @divTrunc(a, b); |
| 64 | 64 | } |
| 65 | 65 | |
| ... | ... | @@ -85,7 +85,7 @@ test "@clz" { |
| 85 | 85 | comptime testClz(); |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | fn testClz() { | |
| 88 | fn testClz() void { | |
| 89 | 89 | assert(clz(u8(0b00001010)) == 4); |
| 90 | 90 | assert(clz(u8(0b10001010)) == 0); |
| 91 | 91 | assert(clz(u8(0b00000000)) == 8); |
| ... | ... | @@ -93,7 +93,7 @@ fn testClz() { |
| 93 | 93 | assert(clz(u128(0x10000000000000000)) == 63); |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | fn clz(x: var) -> usize { | |
| 96 | fn clz(x: var) usize { | |
| 97 | 97 | return @clz(x); |
| 98 | 98 | } |
| 99 | 99 | |
| ... | ... | @@ -102,13 +102,13 @@ test "@ctz" { |
| 102 | 102 | comptime testCtz(); |
| 103 | 103 | } |
| 104 | 104 | |
| 105 | fn testCtz() { | |
| 105 | fn testCtz() void { | |
| 106 | 106 | assert(ctz(u8(0b10100000)) == 5); |
| 107 | 107 | assert(ctz(u8(0b10001010)) == 1); |
| 108 | 108 | assert(ctz(u8(0b00000000)) == 8); |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | fn ctz(x: var) -> usize { | |
| 111 | fn ctz(x: var) usize { | |
| 112 | 112 | return @ctz(x); |
| 113 | 113 | } |
| 114 | 114 | |
| ... | ... | @@ -132,7 +132,7 @@ test "three expr in a row" { |
| 132 | 132 | testThreeExprInARow(false, true); |
| 133 | 133 | comptime testThreeExprInARow(false, true); |
| 134 | 134 | } |
| 135 | fn testThreeExprInARow(f: bool, t: bool) { | |
| 135 | fn testThreeExprInARow(f: bool, t: bool) void { | |
| 136 | 136 | assertFalse(f or f or f); |
| 137 | 137 | assertFalse(t and t and f); |
| 138 | 138 | assertFalse(1 | 2 | 4 != 7); |
| ... | ... | @@ -146,7 +146,7 @@ fn testThreeExprInARow(f: bool, t: bool) { |
| 146 | 146 | assertFalse(!!false); |
| 147 | 147 | assertFalse(i32(7) != --(i32(7))); |
| 148 | 148 | } |
| 149 | fn assertFalse(b: bool) { | |
| 149 | fn assertFalse(b: bool) void { | |
| 150 | 150 | assert(!b); |
| 151 | 151 | } |
| 152 | 152 | |
| ... | ... | @@ -165,7 +165,7 @@ test "unsigned wrapping" { |
| 165 | 165 | testUnsignedWrappingEval(@maxValue(u32)); |
| 166 | 166 | comptime testUnsignedWrappingEval(@maxValue(u32)); |
| 167 | 167 | } |
| 168 | fn testUnsignedWrappingEval(x: u32) { | |
| 168 | fn testUnsignedWrappingEval(x: u32) void { | |
| 169 | 169 | const zero = x +% 1; |
| 170 | 170 | assert(zero == 0); |
| 171 | 171 | const orig = zero -% 1; |
| ... | ... | @@ -176,7 +176,7 @@ test "signed wrapping" { |
| 176 | 176 | testSignedWrappingEval(@maxValue(i32)); |
| 177 | 177 | comptime testSignedWrappingEval(@maxValue(i32)); |
| 178 | 178 | } |
| 179 | fn testSignedWrappingEval(x: i32) { | |
| 179 | fn testSignedWrappingEval(x: i32) void { | |
| 180 | 180 | const min_val = x +% 1; |
| 181 | 181 | assert(min_val == @minValue(i32)); |
| 182 | 182 | const max_val = min_val -% 1; |
| ... | ... | @@ -187,7 +187,7 @@ test "negation wrapping" { |
| 187 | 187 | testNegationWrappingEval(@minValue(i16)); |
| 188 | 188 | comptime testNegationWrappingEval(@minValue(i16)); |
| 189 | 189 | } |
| 190 | fn testNegationWrappingEval(x: i16) { | |
| 190 | fn testNegationWrappingEval(x: i16) void { | |
| 191 | 191 | assert(x == -32768); |
| 192 | 192 | const neg = -%x; |
| 193 | 193 | assert(neg == -32768); |
| ... | ... | @@ -197,12 +197,12 @@ test "unsigned 64-bit division" { |
| 197 | 197 | test_u64_div(); |
| 198 | 198 | comptime test_u64_div(); |
| 199 | 199 | } |
| 200 | fn test_u64_div() { | |
| 200 | fn test_u64_div() void { | |
| 201 | 201 | const result = divWithResult(1152921504606846976, 34359738365); |
| 202 | 202 | assert(result.quotient == 33554432); |
| 203 | 203 | assert(result.remainder == 100663296); |
| 204 | 204 | } |
| 205 | fn divWithResult(a: u64, b: u64) -> DivResult { | |
| 205 | fn divWithResult(a: u64, b: u64) DivResult { | |
| 206 | 206 | return DivResult { |
| 207 | 207 | .quotient = a / b, |
| 208 | 208 | .remainder = a % b, |
| ... | ... | @@ -219,7 +219,7 @@ test "binary not" { |
| 219 | 219 | testBinaryNot(0b1010101010101010); |
| 220 | 220 | } |
| 221 | 221 | |
| 222 | fn testBinaryNot(x: u16) { | |
| 222 | fn testBinaryNot(x: u16) void { | |
| 223 | 223 | assert(~x == 0b0101010101010101); |
| 224 | 224 | } |
| 225 | 225 | |
| ... | ... | @@ -250,7 +250,7 @@ test "float equality" { |
| 250 | 250 | comptime testFloatEqualityImpl(x, y); |
| 251 | 251 | } |
| 252 | 252 | |
| 253 | fn testFloatEqualityImpl(x: f64, y: f64) { | |
| 253 | fn testFloatEqualityImpl(x: f64, y: f64) void { | |
| 254 | 254 | const y2 = x + 1.0; |
| 255 | 255 | assert(y == y2); |
| 256 | 256 | } |
| ... | ... | @@ -285,7 +285,7 @@ test "truncating shift left" { |
| 285 | 285 | testShlTrunc(@maxValue(u16)); |
| 286 | 286 | comptime testShlTrunc(@maxValue(u16)); |
| 287 | 287 | } |
| 288 | fn testShlTrunc(x: u16) { | |
| 288 | fn testShlTrunc(x: u16) void { | |
| 289 | 289 | const shifted = x << 1; |
| 290 | 290 | assert(shifted == 65534); |
| 291 | 291 | } |
| ... | ... | @@ -294,7 +294,7 @@ test "truncating shift right" { |
| 294 | 294 | testShrTrunc(@maxValue(u16)); |
| 295 | 295 | comptime testShrTrunc(@maxValue(u16)); |
| 296 | 296 | } |
| 297 | fn testShrTrunc(x: u16) { | |
| 297 | fn testShrTrunc(x: u16) void { | |
| 298 | 298 | const shifted = x >> 1; |
| 299 | 299 | assert(shifted == 32767); |
| 300 | 300 | } |
| ... | ... | @@ -303,7 +303,7 @@ test "exact shift left" { |
| 303 | 303 | testShlExact(0b00110101); |
| 304 | 304 | comptime testShlExact(0b00110101); |
| 305 | 305 | } |
| 306 | fn testShlExact(x: u8) { | |
| 306 | fn testShlExact(x: u8) void { | |
| 307 | 307 | const shifted = @shlExact(x, 2); |
| 308 | 308 | assert(shifted == 0b11010100); |
| 309 | 309 | } |
| ... | ... | @@ -312,7 +312,7 @@ test "exact shift right" { |
| 312 | 312 | testShrExact(0b10110100); |
| 313 | 313 | comptime testShrExact(0b10110100); |
| 314 | 314 | } |
| 315 | fn testShrExact(x: u8) { | |
| 315 | fn testShrExact(x: u8) void { | |
| 316 | 316 | const shifted = @shrExact(x, 2); |
| 317 | 317 | assert(shifted == 0b00101101); |
| 318 | 318 | } |
| ... | ... | @@ -354,7 +354,7 @@ test "xor" { |
| 354 | 354 | comptime test_xor(); |
| 355 | 355 | } |
| 356 | 356 | |
| 357 | fn test_xor() { | |
| 357 | fn test_xor() void { | |
| 358 | 358 | assert(0xFF ^ 0x00 == 0xFF); |
| 359 | 359 | assert(0xF0 ^ 0x0F == 0xFF); |
| 360 | 360 | assert(0xFF ^ 0xF0 == 0x0F); |
| ... | ... | @@ -380,9 +380,9 @@ test "f128" { |
| 380 | 380 | comptime test_f128(); |
| 381 | 381 | } |
| 382 | 382 | |
| 383 | fn make_f128(x: f128) -> f128 { return x; } | |
| 383 | fn make_f128(x: f128) f128 { return x; } | |
| 384 | 384 | |
| 385 | fn test_f128() { | |
| 385 | fn test_f128() void { | |
| 386 | 386 | assert(@sizeOf(f128) == 16); |
| 387 | 387 | assert(make_f128(1.0) == 1.0); |
| 388 | 388 | assert(make_f128(1.0) != 1.1); |
| ... | ... | @@ -392,6 +392,6 @@ fn test_f128() { |
| 392 | 392 | should_not_be_zero(1.0); |
| 393 | 393 | } |
| 394 | 394 | |
| 395 | fn should_not_be_zero(x: f128) { | |
| 395 | fn should_not_be_zero(x: f128) void { | |
| 396 | 396 | assert(x != 0.0); |
| 397 | 397 | } |
| \ No newline at end of file |
test/cases/misc.zig+39-30| ... | ... | @@ -6,7 +6,7 @@ const builtin = @import("builtin"); |
| 6 | 6 | // normal comment |
| 7 | 7 | /// this is a documentation comment |
| 8 | 8 | /// doc comment line 2 |
| 9 | fn emptyFunctionWithComments() {} | |
| 9 | fn emptyFunctionWithComments() void {} | |
| 10 | 10 | |
| 11 | 11 | test "empty function with comments" { |
| 12 | 12 | emptyFunctionWithComments(); |
| ... | ... | @@ -16,7 +16,7 @@ comptime { |
| 16 | 16 | @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal); |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | extern fn disabledExternFn() { | |
| 19 | extern fn disabledExternFn() void { | |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | 22 | test "call disabled extern fn" { |
| ... | ... | @@ -104,7 +104,7 @@ test "short circuit" { |
| 104 | 104 | comptime testShortCircuit(false, true); |
| 105 | 105 | } |
| 106 | 106 | |
| 107 | fn testShortCircuit(f: bool, t: bool) { | |
| 107 | fn testShortCircuit(f: bool, t: bool) void { | |
| 108 | 108 | var hit_1 = f; |
| 109 | 109 | var hit_2 = f; |
| 110 | 110 | var hit_3 = f; |
| ... | ... | @@ -134,11 +134,11 @@ fn testShortCircuit(f: bool, t: bool) { |
| 134 | 134 | test "truncate" { |
| 135 | 135 | assert(testTruncate(0x10fd) == 0xfd); |
| 136 | 136 | } |
| 137 | fn testTruncate(x: u32) -> u8 { | |
| 137 | fn testTruncate(x: u32) u8 { | |
| 138 | 138 | return @truncate(u8, x); |
| 139 | 139 | } |
| 140 | 140 | |
| 141 | fn first4KeysOfHomeRow() -> []const u8 { | |
| 141 | fn first4KeysOfHomeRow() []const u8 { | |
| 142 | 142 | return "aoeu"; |
| 143 | 143 | } |
| 144 | 144 | |
| ... | ... | @@ -193,7 +193,7 @@ test "constant equal function pointers" { |
| 193 | 193 | assert(comptime x: {break :x emptyFn == alias;}); |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | fn emptyFn() {} | |
| 196 | fn emptyFn() void {} | |
| 197 | 197 | |
| 198 | 198 | |
| 199 | 199 | test "hex escape" { |
| ... | ... | @@ -262,10 +262,10 @@ test "generic malloc free" { |
| 262 | 262 | memFree(u8, a); |
| 263 | 263 | } |
| 264 | 264 | const some_mem : [100]u8 = undefined; |
| 265 | fn memAlloc(comptime T: type, n: usize) -> %[]T { | |
| 265 | fn memAlloc(comptime T: type, n: usize) %[]T { | |
| 266 | 266 | return @ptrCast(&T, &some_mem[0])[0..n]; |
| 267 | 267 | } |
| 268 | fn memFree(comptime T: type, memory: []T) { } | |
| 268 | fn memFree(comptime T: type, memory: []T) void { } | |
| 269 | 269 | |
| 270 | 270 | |
| 271 | 271 | test "cast undefined" { |
| ... | ... | @@ -273,22 +273,22 @@ test "cast undefined" { |
| 273 | 273 | const slice = ([]const u8)(array); |
| 274 | 274 | testCastUndefined(slice); |
| 275 | 275 | } |
| 276 | fn testCastUndefined(x: []const u8) {} | |
| 276 | fn testCastUndefined(x: []const u8) void {} | |
| 277 | 277 | |
| 278 | 278 | |
| 279 | 279 | test "cast small unsigned to larger signed" { |
| 280 | 280 | assert(castSmallUnsignedToLargerSigned1(200) == i16(200)); |
| 281 | 281 | assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); |
| 282 | 282 | } |
| 283 | fn castSmallUnsignedToLargerSigned1(x: u8) -> i16 { return x; } | |
| 284 | fn castSmallUnsignedToLargerSigned2(x: u16) -> i64 { return x; } | |
| 283 | fn castSmallUnsignedToLargerSigned1(x: u8) i16 { return x; } | |
| 284 | fn castSmallUnsignedToLargerSigned2(x: u16) i64 { return x; } | |
| 285 | 285 | |
| 286 | 286 | |
| 287 | 287 | test "implicit cast after unreachable" { |
| 288 | 288 | assert(outer() == 1234); |
| 289 | 289 | } |
| 290 | fn inner() -> i32 { return 1234; } | |
| 291 | fn outer() -> i64 { | |
| 290 | fn inner() i32 { return 1234; } | |
| 291 | fn outer() i64 { | |
| 292 | 292 | return inner(); |
| 293 | 293 | } |
| 294 | 294 | |
| ... | ... | @@ -307,11 +307,11 @@ test "call result of if else expression" { |
| 307 | 307 | assert(mem.eql(u8, f2(true), "a")); |
| 308 | 308 | assert(mem.eql(u8, f2(false), "b")); |
| 309 | 309 | } |
| 310 | fn f2(x: bool) -> []const u8 { | |
| 310 | fn f2(x: bool) []const u8 { | |
| 311 | 311 | return (if (x) fA else fB)(); |
| 312 | 312 | } |
| 313 | fn fA() -> []const u8 { return "a"; } | |
| 314 | fn fB() -> []const u8 { return "b"; } | |
| 313 | fn fA() []const u8 { return "a"; } | |
| 314 | fn fB() []const u8 { return "b"; } | |
| 315 | 315 | |
| 316 | 316 | |
| 317 | 317 | test "const expression eval handling of variables" { |
| ... | ... | @@ -338,7 +338,7 @@ const Test3Point = struct { |
| 338 | 338 | }; |
| 339 | 339 | const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}}; |
| 340 | 340 | const test3_bar = Test3Foo { .Two = 13}; |
| 341 | fn test3_1(f: &const Test3Foo) { | |
| 341 | fn test3_1(f: &const Test3Foo) void { | |
| 342 | 342 | switch (*f) { |
| 343 | 343 | Test3Foo.Three => |pt| { |
| 344 | 344 | assert(pt.x == 3); |
| ... | ... | @@ -347,7 +347,7 @@ fn test3_1(f: &const Test3Foo) { |
| 347 | 347 | else => unreachable, |
| 348 | 348 | } |
| 349 | 349 | } |
| 350 | fn test3_2(f: &const Test3Foo) { | |
| 350 | fn test3_2(f: &const Test3Foo) void { | |
| 351 | 351 | switch (*f) { |
| 352 | 352 | Test3Foo.Two => |x| { |
| 353 | 353 | assert(x == 13); |
| ... | ... | @@ -367,7 +367,7 @@ const single_quote = '\''; |
| 367 | 367 | test "take address of parameter" { |
| 368 | 368 | testTakeAddressOfParameter(12.34); |
| 369 | 369 | } |
| 370 | fn testTakeAddressOfParameter(f: f32) { | |
| 370 | fn testTakeAddressOfParameter(f: f32) void { | |
| 371 | 371 | const f_ptr = &f; |
| 372 | 372 | assert(*f_ptr == 12.34); |
| 373 | 373 | } |
| ... | ... | @@ -378,7 +378,7 @@ test "pointer comparison" { |
| 378 | 378 | const b = &a; |
| 379 | 379 | assert(ptrEql(b, b)); |
| 380 | 380 | } |
| 381 | fn ptrEql(a: &const []const u8, b: &const []const u8) -> bool { | |
| 381 | fn ptrEql(a: &const []const u8, b: &const []const u8) bool { | |
| 382 | 382 | return a == b; |
| 383 | 383 | } |
| 384 | 384 | |
| ... | ... | @@ -419,12 +419,12 @@ test "cast slice to u8 slice" { |
| 419 | 419 | test "pointer to void return type" { |
| 420 | 420 | testPointerToVoidReturnType() catch unreachable; |
| 421 | 421 | } |
| 422 | fn testPointerToVoidReturnType() -> %void { | |
| 422 | fn testPointerToVoidReturnType() %void { | |
| 423 | 423 | const a = testPointerToVoidReturnType2(); |
| 424 | 424 | return *a; |
| 425 | 425 | } |
| 426 | 426 | const test_pointer_to_void_return_type_x = void{}; |
| 427 | fn testPointerToVoidReturnType2() -> &const void { | |
| 427 | fn testPointerToVoidReturnType2() &const void { | |
| 428 | 428 | return &test_pointer_to_void_return_type_x; |
| 429 | 429 | } |
| 430 | 430 | |
| ... | ... | @@ -444,7 +444,7 @@ test "array 2D const double ptr" { |
| 444 | 444 | testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); |
| 445 | 445 | } |
| 446 | 446 | |
| 447 | fn testArray2DConstDoublePtr(ptr: &const f32) { | |
| 447 | fn testArray2DConstDoublePtr(ptr: &const f32) void { | |
| 448 | 448 | assert(ptr[0] == 1.0); |
| 449 | 449 | assert(ptr[1] == 2.0); |
| 450 | 450 | } |
| ... | ... | @@ -481,7 +481,7 @@ test "@typeId" { |
| 481 | 481 | assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); |
| 482 | 482 | assert(@typeId(AUnionEnum) == Tid.Union); |
| 483 | 483 | assert(@typeId(AUnion) == Tid.Union); |
| 484 | assert(@typeId(fn()) == Tid.Fn); | |
| 484 | assert(@typeId(fn()void) == Tid.Fn); | |
| 485 | 485 | assert(@typeId(@typeOf(builtin)) == Tid.Namespace); |
| 486 | 486 | assert(@typeId(@typeOf(x: {break :x this;})) == Tid.Block); |
| 487 | 487 | // TODO bound fn |
| ... | ... | @@ -536,7 +536,7 @@ var global_ptr = &gdt[0]; |
| 536 | 536 | // can't really run this test but we can make sure it has no compile error |
| 537 | 537 | // and generates code |
| 538 | 538 | const vram = @intToPtr(&volatile u8, 0x20000000)[0..0x8000]; |
| 539 | export fn writeToVRam() { | |
| 539 | export fn writeToVRam() void { | |
| 540 | 540 | vram[0] = 'X'; |
| 541 | 541 | } |
| 542 | 542 | |
| ... | ... | @@ -556,7 +556,7 @@ test "variable is allowed to be a pointer to an opaque type" { |
| 556 | 556 | var x: i32 = 1234; |
| 557 | 557 | _ = hereIsAnOpaqueType(@ptrCast(&OpaqueA, &x)); |
| 558 | 558 | } |
| 559 | fn hereIsAnOpaqueType(ptr: &OpaqueA) -> &OpaqueA { | |
| 559 | fn hereIsAnOpaqueType(ptr: &OpaqueA) &OpaqueA { | |
| 560 | 560 | var a = ptr; |
| 561 | 561 | return a; |
| 562 | 562 | } |
| ... | ... | @@ -565,7 +565,7 @@ test "comptime if inside runtime while which unconditionally breaks" { |
| 565 | 565 | testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); |
| 566 | 566 | comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); |
| 567 | 567 | } |
| 568 | fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) { | |
| 568 | fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { | |
| 569 | 569 | while (cond) { |
| 570 | 570 | if (false) { } |
| 571 | 571 | break; |
| ... | ... | @@ -583,7 +583,7 @@ test "struct inside function" { |
| 583 | 583 | comptime testStructInFn(); |
| 584 | 584 | } |
| 585 | 585 | |
| 586 | fn testStructInFn() { | |
| 586 | fn testStructInFn() void { | |
| 587 | 587 | const BlockKind = u32; |
| 588 | 588 | |
| 589 | 589 | const Block = struct { |
| ... | ... | @@ -597,10 +597,10 @@ fn testStructInFn() { |
| 597 | 597 | assert(block.kind == 1235); |
| 598 | 598 | } |
| 599 | 599 | |
| 600 | fn fnThatClosesOverLocalConst() -> type { | |
| 600 | fn fnThatClosesOverLocalConst() type { | |
| 601 | 601 | const c = 1; |
| 602 | 602 | return struct { |
| 603 | fn g() -> i32 { return c; } | |
| 603 | fn g() i32 { return c; } | |
| 604 | 604 | }; |
| 605 | 605 | } |
| 606 | 606 | |
| ... | ... | @@ -608,3 +608,12 @@ test "function closes over local const" { |
| 608 | 608 | const x = fnThatClosesOverLocalConst().g(); |
| 609 | 609 | assert(x == 1); |
| 610 | 610 | } |
| 611 | ||
| 612 | test "cold function" { | |
| 613 | thisIsAColdFn(); | |
| 614 | comptime thisIsAColdFn(); | |
| 615 | } | |
| 616 | ||
| 617 | fn thisIsAColdFn() void { | |
| 618 | @setCold(true); | |
| 619 | } |
test/cases/null.zig+6-6| ... | ... | @@ -48,14 +48,14 @@ test "maybe return" { |
| 48 | 48 | comptime maybeReturnImpl(); |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | fn maybeReturnImpl() { | |
| 51 | fn maybeReturnImpl() void { | |
| 52 | 52 | assert(??foo(1235)); |
| 53 | 53 | if (foo(null) != null) |
| 54 | 54 | unreachable; |
| 55 | 55 | assert(!??foo(1234)); |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | fn foo(x: ?i32) -> ?bool { | |
| 58 | fn foo(x: ?i32) ?bool { | |
| 59 | 59 | const value = x ?? return null; |
| 60 | 60 | return value > 1234; |
| 61 | 61 | } |
| ... | ... | @@ -64,7 +64,7 @@ fn foo(x: ?i32) -> ?bool { |
| 64 | 64 | test "if var maybe pointer" { |
| 65 | 65 | assert(shouldBeAPlus1(Particle {.a = 14, .b = 1, .c = 1, .d = 1}) == 15); |
| 66 | 66 | } |
| 67 | fn shouldBeAPlus1(p: &const Particle) -> u64 { | |
| 67 | fn shouldBeAPlus1(p: &const Particle) u64 { | |
| 68 | 68 | var maybe_particle: ?Particle = *p; |
| 69 | 69 | if (maybe_particle) |*particle| { |
| 70 | 70 | particle.a += 1; |
| ... | ... | @@ -100,7 +100,7 @@ const here_is_a_null_literal = SillyStruct { |
| 100 | 100 | test "test null runtime" { |
| 101 | 101 | testTestNullRuntime(null); |
| 102 | 102 | } |
| 103 | fn testTestNullRuntime(x: ?i32) { | |
| 103 | fn testTestNullRuntime(x: ?i32) void { | |
| 104 | 104 | assert(x == null); |
| 105 | 105 | assert(!(x != null)); |
| 106 | 106 | } |
| ... | ... | @@ -110,12 +110,12 @@ test "nullable void" { |
| 110 | 110 | comptime nullableVoidImpl(); |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | fn nullableVoidImpl() { | |
| 113 | fn nullableVoidImpl() void { | |
| 114 | 114 | assert(bar(null) == null); |
| 115 | 115 | assert(bar({}) != null); |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | fn bar(x: ?void) -> ?void { | |
| 118 | fn bar(x: ?void) ?void { | |
| 119 | 119 | if (x) |_| { |
| 120 | 120 | return {}; |
| 121 | 121 | } else { |
test/cases/pub_enum/index.zig+1-1| ... | ... | @@ -4,7 +4,7 @@ const assert = @import("std").debug.assert; |
| 4 | 4 | test "pub enum" { |
| 5 | 5 | pubEnumTest(other.APubEnum.Two); |
| 6 | 6 | } |
| 7 | fn pubEnumTest(foo: other.APubEnum) { | |
| 7 | fn pubEnumTest(foo: other.APubEnum) void { | |
| 8 | 8 | assert(foo == other.APubEnum.Two); |
| 9 | 9 | } |
| 10 | 10 |
test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig+2-2| ... | ... | @@ -16,7 +16,7 @@ const Num = enum { |
| 16 | 16 | Two, |
| 17 | 17 | }; |
| 18 | 18 | |
| 19 | fn foo(c: bool, k: Num, c2: bool, b: []const u8) { | |
| 19 | fn foo(c: bool, k: Num, c2: bool, b: []const u8) void { | |
| 20 | 20 | switch (k) { |
| 21 | 21 | Num.Two => {}, |
| 22 | 22 | Num.One => { |
| ... | ... | @@ -31,7 +31,7 @@ fn foo(c: bool, k: Num, c2: bool, b: []const u8) { |
| 31 | 31 | } |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | fn a(x: []const u8) { | |
| 34 | fn a(x: []const u8) void { | |
| 35 | 35 | assert(mem.eql(u8, x, "aoeu")); |
| 36 | 36 | ok = true; |
| 37 | 37 | } |
test/cases/reflection.zig+2-2| ... | ... | @@ -22,8 +22,8 @@ test "reflection: function return type, var args, and param types" { |
| 22 | 22 | } |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | fn dummy(a: bool, b: i32, c: f32) -> i32 { return 1234; } | |
| 26 | fn dummy_varargs(args: ...) {} | |
| 25 | fn dummy(a: bool, b: i32, c: f32) i32 { return 1234; } | |
| 26 | fn dummy_varargs(args: ...) void {} | |
| 27 | 27 | |
| 28 | 28 | test "reflection: struct member types and names" { |
| 29 | 29 | comptime { |
test/cases/slice.zig+3-3| ... | ... | @@ -17,12 +17,12 @@ test "slice child property" { |
| 17 | 17 | assert(@typeOf(slice).Child == i32); |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | test "debug safety lets us slice from len..len" { | |
| 20 | test "runtime safety lets us slice from len..len" { | |
| 21 | 21 | var an_array = []u8{1, 2, 3}; |
| 22 | 22 | assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) -> []u8 { | |
| 25 | fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { | |
| 26 | 26 | return a_slice[start..end]; |
| 27 | 27 | } |
| 28 | 28 | |
| ... | ... | @@ -31,6 +31,6 @@ test "implicitly cast array of size 0 to slice" { |
| 31 | 31 | assertLenIsZero(msg); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | fn assertLenIsZero(msg: []const u8) { | |
| 34 | fn assertLenIsZero(msg: []const u8) void { | |
| 35 | 35 | assert(msg.len == 0); |
| 36 | 36 | } |
test/cases/struct.zig+17-17| ... | ... | @@ -2,7 +2,7 @@ const assert = @import("std").debug.assert; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | const StructWithNoFields = struct { |
| 5 | fn add(a: i32, b: i32) -> i32 { return a + b; } | |
| 5 | fn add(a: i32, b: i32) i32 { return a + b; } | |
| 6 | 6 | }; |
| 7 | 7 | const empty_global_instance = StructWithNoFields {}; |
| 8 | 8 | |
| ... | ... | @@ -14,7 +14,7 @@ test "call struct static method" { |
| 14 | 14 | test "return empty struct instance" { |
| 15 | 15 | _ = returnEmptyStructInstance(); |
| 16 | 16 | } |
| 17 | fn returnEmptyStructInstance() -> StructWithNoFields { | |
| 17 | fn returnEmptyStructInstance() StructWithNoFields { | |
| 18 | 18 | return empty_global_instance; |
| 19 | 19 | } |
| 20 | 20 | |
| ... | ... | @@ -54,10 +54,10 @@ const StructFoo = struct { |
| 54 | 54 | b : bool, |
| 55 | 55 | c : f32, |
| 56 | 56 | }; |
| 57 | fn testFoo(foo: &const StructFoo) { | |
| 57 | fn testFoo(foo: &const StructFoo) void { | |
| 58 | 58 | assert(foo.b); |
| 59 | 59 | } |
| 60 | fn testMutation(foo: &StructFoo) { | |
| 60 | fn testMutation(foo: &StructFoo) void { | |
| 61 | 61 | foo.c = 100; |
| 62 | 62 | } |
| 63 | 63 | |
| ... | ... | @@ -95,7 +95,7 @@ test "struct byval assign" { |
| 95 | 95 | assert(foo2.a == 1234); |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | fn structInitializer() { | |
| 98 | fn structInitializer() void { | |
| 99 | 99 | const val = Val { .x = 42 }; |
| 100 | 100 | assert(val.x == 42); |
| 101 | 101 | } |
| ... | ... | @@ -106,12 +106,12 @@ test "fn call of struct field" { |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | 108 | const Foo = struct { |
| 109 | ptr: fn() -> i32, | |
| 109 | ptr: fn() i32, | |
| 110 | 110 | }; |
| 111 | 111 | |
| 112 | fn aFunc() -> i32 { return 13; } | |
| 112 | fn aFunc() i32 { return 13; } | |
| 113 | 113 | |
| 114 | fn callStructField(foo: &const Foo) -> i32 { | |
| 114 | fn callStructField(foo: &const Foo) i32 { | |
| 115 | 115 | return foo.ptr(); |
| 116 | 116 | } |
| 117 | 117 | |
| ... | ... | @@ -124,7 +124,7 @@ test "store member function in variable" { |
| 124 | 124 | } |
| 125 | 125 | const MemberFnTestFoo = struct { |
| 126 | 126 | x: i32, |
| 127 | fn member(foo: &const MemberFnTestFoo) -> i32 { return foo.x; } | |
| 127 | fn member(foo: &const MemberFnTestFoo) i32 { return foo.x; } | |
| 128 | 128 | }; |
| 129 | 129 | |
| 130 | 130 | |
| ... | ... | @@ -140,7 +140,7 @@ test "member functions" { |
| 140 | 140 | } |
| 141 | 141 | const MemberFnRand = struct { |
| 142 | 142 | seed: u32, |
| 143 | pub fn getSeed(r: &const MemberFnRand) -> u32 { | |
| 143 | pub fn getSeed(r: &const MemberFnRand) u32 { | |
| 144 | 144 | return r.seed; |
| 145 | 145 | } |
| 146 | 146 | }; |
| ... | ... | @@ -153,7 +153,7 @@ const Bar = struct { |
| 153 | 153 | x: i32, |
| 154 | 154 | y: i32, |
| 155 | 155 | }; |
| 156 | fn makeBar(x: i32, y: i32) -> Bar { | |
| 156 | fn makeBar(x: i32, y: i32) Bar { | |
| 157 | 157 | return Bar { |
| 158 | 158 | .x = x, |
| 159 | 159 | .y = y, |
| ... | ... | @@ -165,7 +165,7 @@ test "empty struct method call" { |
| 165 | 165 | assert(es.method() == 1234); |
| 166 | 166 | } |
| 167 | 167 | const EmptyStruct = struct { |
| 168 | fn method(es: &const EmptyStruct) -> i32 { | |
| 168 | fn method(es: &const EmptyStruct) i32 { | |
| 169 | 169 | return 1234; |
| 170 | 170 | } |
| 171 | 171 | }; |
| ... | ... | @@ -175,14 +175,14 @@ test "return empty struct from fn" { |
| 175 | 175 | _ = testReturnEmptyStructFromFn(); |
| 176 | 176 | } |
| 177 | 177 | const EmptyStruct2 = struct {}; |
| 178 | fn testReturnEmptyStructFromFn() -> EmptyStruct2 { | |
| 178 | fn testReturnEmptyStructFromFn() EmptyStruct2 { | |
| 179 | 179 | return EmptyStruct2 {}; |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | 182 | test "pass slice of empty struct to fn" { |
| 183 | 183 | assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1); |
| 184 | 184 | } |
| 185 | fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) -> usize { | |
| 185 | fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { | |
| 186 | 186 | return slice.len; |
| 187 | 187 | } |
| 188 | 188 | |
| ... | ... | @@ -229,15 +229,15 @@ test "bit field access" { |
| 229 | 229 | assert(data.b == 3); |
| 230 | 230 | } |
| 231 | 231 | |
| 232 | fn getA(data: &const BitField1) -> u3 { | |
| 232 | fn getA(data: &const BitField1) u3 { | |
| 233 | 233 | return data.a; |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | fn getB(data: &const BitField1) -> u3 { | |
| 236 | fn getB(data: &const BitField1) u3 { | |
| 237 | 237 | return data.b; |
| 238 | 238 | } |
| 239 | 239 | |
| 240 | fn getC(data: &const BitField1) -> u2 { | |
| 240 | fn getC(data: &const BitField1) u2 { | |
| 241 | 241 | return data.c; |
| 242 | 242 | } |
| 243 | 243 |
test/cases/switch.zig+15-15| ... | ... | @@ -4,7 +4,7 @@ test "switch with numbers" { |
| 4 | 4 | testSwitchWithNumbers(13); |
| 5 | 5 | } |
| 6 | 6 | |
| 7 | fn testSwitchWithNumbers(x: u32) { | |
| 7 | fn testSwitchWithNumbers(x: u32) void { | |
| 8 | 8 | const result = switch (x) { |
| 9 | 9 | 1, 2, 3, 4 ... 8 => false, |
| 10 | 10 | 13 => true, |
| ... | ... | @@ -20,7 +20,7 @@ test "switch with all ranges" { |
| 20 | 20 | assert(testSwitchWithAllRanges(301, 6) == 6); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | fn testSwitchWithAllRanges(x: u32, y: u32) -> u32 { | |
| 23 | fn testSwitchWithAllRanges(x: u32, y: u32) u32 { | |
| 24 | 24 | return switch (x) { |
| 25 | 25 | 0 ... 100 => 1, |
| 26 | 26 | 101 ... 200 => 2, |
| ... | ... | @@ -53,7 +53,7 @@ const Fruit = enum { |
| 53 | 53 | Orange, |
| 54 | 54 | Banana, |
| 55 | 55 | }; |
| 56 | fn nonConstSwitchOnEnum(fruit: Fruit) { | |
| 56 | fn nonConstSwitchOnEnum(fruit: Fruit) void { | |
| 57 | 57 | switch (fruit) { |
| 58 | 58 | Fruit.Apple => unreachable, |
| 59 | 59 | Fruit.Orange => {}, |
| ... | ... | @@ -65,7 +65,7 @@ fn nonConstSwitchOnEnum(fruit: Fruit) { |
| 65 | 65 | test "switch statement" { |
| 66 | 66 | nonConstSwitch(SwitchStatmentFoo.C); |
| 67 | 67 | } |
| 68 | fn nonConstSwitch(foo: SwitchStatmentFoo) { | |
| 68 | fn nonConstSwitch(foo: SwitchStatmentFoo) void { | |
| 69 | 69 | const val = switch (foo) { |
| 70 | 70 | SwitchStatmentFoo.A => i32(1), |
| 71 | 71 | SwitchStatmentFoo.B => 2, |
| ... | ... | @@ -92,7 +92,7 @@ const SwitchProngWithVarEnum = union(enum) { |
| 92 | 92 | Two: f32, |
| 93 | 93 | Meh: void, |
| 94 | 94 | }; |
| 95 | fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) { | |
| 95 | fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) void { | |
| 96 | 96 | switch(*a) { |
| 97 | 97 | SwitchProngWithVarEnum.One => |x| { |
| 98 | 98 | assert(x == 13); |
| ... | ... | @@ -111,7 +111,7 @@ test "switch on enum using pointer capture" { |
| 111 | 111 | comptime testSwitchEnumPtrCapture(); |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | fn testSwitchEnumPtrCapture() { | |
| 114 | fn testSwitchEnumPtrCapture() void { | |
| 115 | 115 | var value = SwitchProngWithVarEnum { .One = 1234 }; |
| 116 | 116 | switch (value) { |
| 117 | 117 | SwitchProngWithVarEnum.One => |*x| *x += 1, |
| ... | ... | @@ -131,7 +131,7 @@ test "switch with multiple expressions" { |
| 131 | 131 | }; |
| 132 | 132 | assert(x == 2); |
| 133 | 133 | } |
| 134 | fn returnsFive() -> i32 { | |
| 134 | fn returnsFive() i32 { | |
| 135 | 135 | return 5; |
| 136 | 136 | } |
| 137 | 137 | |
| ... | ... | @@ -144,7 +144,7 @@ const Number = union(enum) { |
| 144 | 144 | |
| 145 | 145 | const number = Number { .Three = 1.23 }; |
| 146 | 146 | |
| 147 | fn returnsFalse() -> bool { | |
| 147 | fn returnsFalse() bool { | |
| 148 | 148 | switch (number) { |
| 149 | 149 | Number.One => |x| return x > 1234, |
| 150 | 150 | Number.Two => |x| return x == 'a', |
| ... | ... | @@ -160,7 +160,7 @@ test "switch on type" { |
| 160 | 160 | assert(!trueIfBoolFalseOtherwise(i32)); |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | fn trueIfBoolFalseOtherwise(comptime T: type) -> bool { | |
| 163 | fn trueIfBoolFalseOtherwise(comptime T: type) bool { | |
| 164 | 164 | return switch (T) { |
| 165 | 165 | bool => true, |
| 166 | 166 | else => false, |
| ... | ... | @@ -172,7 +172,7 @@ test "switch handles all cases of number" { |
| 172 | 172 | comptime testSwitchHandleAllCases(); |
| 173 | 173 | } |
| 174 | 174 | |
| 175 | fn testSwitchHandleAllCases() { | |
| 175 | fn testSwitchHandleAllCases() void { | |
| 176 | 176 | assert(testSwitchHandleAllCasesExhaustive(0) == 3); |
| 177 | 177 | assert(testSwitchHandleAllCasesExhaustive(1) == 2); |
| 178 | 178 | assert(testSwitchHandleAllCasesExhaustive(2) == 1); |
| ... | ... | @@ -185,7 +185,7 @@ fn testSwitchHandleAllCases() { |
| 185 | 185 | assert(testSwitchHandleAllCasesRange(230) == 3); |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | fn testSwitchHandleAllCasesExhaustive(x: u2) -> u2 { | |
| 188 | fn testSwitchHandleAllCasesExhaustive(x: u2) u2 { | |
| 189 | 189 | return switch (x) { |
| 190 | 190 | 0 => u2(3), |
| 191 | 191 | 1 => 2, |
| ... | ... | @@ -194,7 +194,7 @@ fn testSwitchHandleAllCasesExhaustive(x: u2) -> u2 { |
| 194 | 194 | }; |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | fn testSwitchHandleAllCasesRange(x: u8) -> u8 { | |
| 197 | fn testSwitchHandleAllCasesRange(x: u8) u8 { | |
| 198 | 198 | return switch (x) { |
| 199 | 199 | 0 ... 100 => u8(0), |
| 200 | 200 | 101 ... 200 => 1, |
| ... | ... | @@ -209,12 +209,12 @@ test "switch all prongs unreachable" { |
| 209 | 209 | comptime testAllProngsUnreachable(); |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | fn testAllProngsUnreachable() { | |
| 212 | fn testAllProngsUnreachable() void { | |
| 213 | 213 | assert(switchWithUnreachable(1) == 2); |
| 214 | 214 | assert(switchWithUnreachable(2) == 10); |
| 215 | 215 | } |
| 216 | 216 | |
| 217 | fn switchWithUnreachable(x: i32) -> i32 { | |
| 217 | fn switchWithUnreachable(x: i32) i32 { | |
| 218 | 218 | while (true) { |
| 219 | 219 | switch (x) { |
| 220 | 220 | 1 => return 2, |
| ... | ... | @@ -225,7 +225,7 @@ fn switchWithUnreachable(x: i32) -> i32 { |
| 225 | 225 | return 10; |
| 226 | 226 | } |
| 227 | 227 | |
| 228 | fn return_a_number() -> %i32 { | |
| 228 | fn return_a_number() %i32 { | |
| 229 | 229 | return 1; |
| 230 | 230 | } |
| 231 | 231 |
test/cases/switch_prong_err_enum.zig+2-2| ... | ... | @@ -2,7 +2,7 @@ const assert = @import("std").debug.assert; |
| 2 | 2 | |
| 3 | 3 | var read_count: u64 = 0; |
| 4 | 4 | |
| 5 | fn readOnce() -> %u64 { | |
| 5 | fn readOnce() %u64 { | |
| 6 | 6 | read_count += 1; |
| 7 | 7 | return read_count; |
| 8 | 8 | } |
| ... | ... | @@ -14,7 +14,7 @@ const FormValue = union(enum) { |
| 14 | 14 | Other: bool, |
| 15 | 15 | }; |
| 16 | 16 | |
| 17 | fn doThing(form_id: u64) -> %FormValue { | |
| 17 | fn doThing(form_id: u64) %FormValue { | |
| 18 | 18 | return switch (form_id) { |
| 19 | 19 | 17 => FormValue { .Address = try readOnce() }, |
| 20 | 20 | else => error.InvalidDebugInfo, |
test/cases/switch_prong_implicit_cast.zig+1-1| ... | ... | @@ -7,7 +7,7 @@ const FormValue = union(enum) { |
| 7 | 7 | |
| 8 | 8 | error Whatever; |
| 9 | 9 | |
| 10 | fn foo(id: u64) -> %FormValue { | |
| 10 | fn foo(id: u64) %FormValue { | |
| 11 | 11 | return switch (id) { |
| 12 | 12 | 2 => FormValue { .Two = true }, |
| 13 | 13 | 1 => FormValue { .One = {} }, |
test/cases/syntax.zig+11-11| ... | ... | @@ -3,18 +3,18 @@ |
| 3 | 3 | const struct_trailing_comma = struct { x: i32, y: i32, }; |
| 4 | 4 | const struct_no_comma = struct { x: i32, y: i32 }; |
| 5 | 5 | const struct_no_comma_void_type = struct { x: i32, y }; |
| 6 | const struct_fn_no_comma = struct { fn m() {} y: i32 }; | |
| 6 | const struct_fn_no_comma = struct { fn m() void {} y: i32 }; | |
| 7 | 7 | |
| 8 | 8 | const enum_no_comma = enum { A, B }; |
| 9 | 9 | const enum_no_comma_type = enum { A, B: i32 }; |
| 10 | 10 | |
| 11 | fn container_init() { | |
| 11 | fn container_init() void { | |
| 12 | 12 | const S = struct { x: i32, y: i32 }; |
| 13 | 13 | _ = S { .x = 1, .y = 2 }; |
| 14 | 14 | _ = S { .x = 1, .y = 2, }; |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | fn switch_cases(x: i32) { | |
| 17 | fn switch_cases(x: i32) void { | |
| 18 | 18 | switch (x) { |
| 19 | 19 | 1,2,3 => {}, |
| 20 | 20 | 4,5, => {}, |
| ... | ... | @@ -23,7 +23,7 @@ fn switch_cases(x: i32) { |
| 23 | 23 | } |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | fn switch_prongs(x: i32) { | |
| 26 | fn switch_prongs(x: i32) void { | |
| 27 | 27 | switch (x) { |
| 28 | 28 | 0 => {}, |
| 29 | 29 | else => {}, |
| ... | ... | @@ -34,21 +34,21 @@ fn switch_prongs(x: i32) { |
| 34 | 34 | } |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | const fn_no_comma = fn(i32, i32); | |
| 38 | const fn_trailing_comma = fn(i32, i32,); | |
| 39 | const fn_vararg_trailing_comma = fn(i32, i32, ...,); | |
| 37 | const fn_no_comma = fn(i32, i32)void; | |
| 38 | const fn_trailing_comma = fn(i32, i32,)void; | |
| 39 | const fn_vararg_trailing_comma = fn(i32, i32, ...,)void; | |
| 40 | 40 | |
| 41 | fn fn_calls() { | |
| 42 | fn add(x: i32, y: i32,) -> i32 { x + y }; | |
| 41 | fn fn_calls() void { | |
| 42 | fn add(x: i32, y: i32,) i32 { x + y }; | |
| 43 | 43 | _ = add(1, 2); |
| 44 | 44 | _ = add(1, 2,); |
| 45 | 45 | |
| 46 | fn swallow(x: ...,) {}; | |
| 46 | fn swallow(x: ...,) void {}; | |
| 47 | 47 | _ = swallow(1,2,3,); |
| 48 | 48 | _ = swallow(); |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | fn asm_lists() { | |
| 51 | fn asm_lists() void { | |
| 52 | 52 | if (false) { // Build AST but don't analyze |
| 53 | 53 | asm ("not real assembly" |
| 54 | 54 | :[a] "x" (x),); |
test/cases/this.zig+4-4| ... | ... | @@ -2,24 +2,24 @@ const assert = @import("std").debug.assert; |
| 2 | 2 | |
| 3 | 3 | const module = this; |
| 4 | 4 | |
| 5 | fn Point(comptime T: type) -> type { | |
| 5 | fn Point(comptime T: type) type { | |
| 6 | 6 | return struct { |
| 7 | 7 | const Self = this; |
| 8 | 8 | x: T, |
| 9 | 9 | y: T, |
| 10 | 10 | |
| 11 | fn addOne(self: &Self) { | |
| 11 | fn addOne(self: &Self) void { | |
| 12 | 12 | self.x += 1; |
| 13 | 13 | self.y += 1; |
| 14 | 14 | } |
| 15 | 15 | }; |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | fn add(x: i32, y: i32) -> i32 { | |
| 18 | fn add(x: i32, y: i32) i32 { | |
| 19 | 19 | return x + y; |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | fn factorial(x: i32) -> i32 { | |
| 22 | fn factorial(x: i32) i32 { | |
| 23 | 23 | const selfFn = this; |
| 24 | 24 | return if (x == 0) 1 else x * selfFn(x - 1); |
| 25 | 25 | } |
test/cases/try.zig+3-3| ... | ... | @@ -6,7 +6,7 @@ test "try on error union" { |
| 6 | 6 | |
| 7 | 7 | } |
| 8 | 8 | |
| 9 | fn tryOnErrorUnionImpl() { | |
| 9 | fn tryOnErrorUnionImpl() void { | |
| 10 | 10 | const x = if (returnsTen()) |val| |
| 11 | 11 | val + 1 |
| 12 | 12 | else |err| switch (err) { |
| ... | ... | @@ -20,7 +20,7 @@ fn tryOnErrorUnionImpl() { |
| 20 | 20 | error ItBroke; |
| 21 | 21 | error NoMem; |
| 22 | 22 | error CrappedOut; |
| 23 | fn returnsTen() -> %i32 { | |
| 23 | fn returnsTen() %i32 { | |
| 24 | 24 | return 10; |
| 25 | 25 | } |
| 26 | 26 | |
| ... | ... | @@ -32,7 +32,7 @@ test "try without vars" { |
| 32 | 32 | assert(result2 == 1); |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | fn failIfTrue(ok: bool) -> %void { | |
| 35 | fn failIfTrue(ok: bool) %void { | |
| 36 | 36 | if (ok) { |
| 37 | 37 | return error.ItBroke; |
| 38 | 38 | } else { |
test/cases/undefined.zig+3-3| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | const mem = @import("std").mem; |
| 3 | 3 | |
| 4 | fn initStaticArray() -> [10]i32 { | |
| 4 | fn initStaticArray() [10]i32 { | |
| 5 | 5 | var array: [10]i32 = undefined; |
| 6 | 6 | array[0] = 1; |
| 7 | 7 | array[4] = 2; |
| ... | ... | @@ -27,12 +27,12 @@ test "init static array to undefined" { |
| 27 | 27 | const Foo = struct { |
| 28 | 28 | x: i32, |
| 29 | 29 | |
| 30 | fn setFooXMethod(foo: &Foo) { | |
| 30 | fn setFooXMethod(foo: &Foo) void { | |
| 31 | 31 | foo.x = 3; |
| 32 | 32 | } |
| 33 | 33 | }; |
| 34 | 34 | |
| 35 | fn setFooX(foo: &Foo) { | |
| 35 | fn setFooX(foo: &Foo) void { | |
| 36 | 36 | foo.x = 2; |
| 37 | 37 | } |
| 38 | 38 |
test/cases/union.zig+36-9| ... | ... | @@ -55,11 +55,11 @@ test "init union with runtime value" { |
| 55 | 55 | assert(foo.int == 42); |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | fn setFloat(foo: &Foo, x: f64) { | |
| 58 | fn setFloat(foo: &Foo, x: f64) void { | |
| 59 | 59 | *foo = Foo { .float = x }; |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | fn setInt(foo: &Foo, x: i32) { | |
| 62 | fn setInt(foo: &Foo, x: i32) void { | |
| 63 | 63 | *foo = Foo { .int = x }; |
| 64 | 64 | } |
| 65 | 65 | |
| ... | ... | @@ -92,11 +92,11 @@ test "union with specified enum tag" { |
| 92 | 92 | comptime doTest(); |
| 93 | 93 | } |
| 94 | 94 | |
| 95 | fn doTest() { | |
| 95 | fn doTest() void { | |
| 96 | 96 | assert(bar(Payload {.A = 1234}) == -10); |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | fn bar(value: &const Payload) -> i32 { | |
| 99 | fn bar(value: &const Payload) i32 { | |
| 100 | 100 | assert(Letter(*value) == Letter.A); |
| 101 | 101 | return switch (*value) { |
| 102 | 102 | Payload.A => |x| return x - 1244, |
| ... | ... | @@ -135,7 +135,7 @@ test "union(enum(u32)) with specified and unspecified tag values" { |
| 135 | 135 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 { .C = 123} ); |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) { | |
| 138 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) void { | |
| 139 | 139 | assert(u32(@TagType(MultipleChoice2)(*x)) == 60); |
| 140 | 140 | assert(1123 == switch (*x) { |
| 141 | 141 | MultipleChoice2.A => 1, |
| ... | ... | @@ -187,7 +187,7 @@ test "cast union to tag type of union" { |
| 187 | 187 | comptime testCastUnionToTagType(TheUnion {.B = 1234}); |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | fn testCastUnionToTagType(x: &const TheUnion) { | |
| 190 | fn testCastUnionToTagType(x: &const TheUnion) void { | |
| 191 | 191 | assert(TheTag(*x) == TheTag.B); |
| 192 | 192 | } |
| 193 | 193 | |
| ... | ... | @@ -203,7 +203,7 @@ test "implicit cast union to its tag type" { |
| 203 | 203 | assert(x == Letter2.B); |
| 204 | 204 | giveMeLetterB(x); |
| 205 | 205 | } |
| 206 | fn giveMeLetterB(x: Letter2) { | |
| 206 | fn giveMeLetterB(x: Letter2) void { | |
| 207 | 207 | assert(x == Value2.B); |
| 208 | 208 | } |
| 209 | 209 | |
| ... | ... | @@ -216,7 +216,7 @@ const TheUnion2 = union(enum) { |
| 216 | 216 | Item2: i32, |
| 217 | 217 | }; |
| 218 | 218 | |
| 219 | fn assertIsTheUnion2Item1(value: &const TheUnion2) { | |
| 219 | fn assertIsTheUnion2Item1(value: &const TheUnion2) void { | |
| 220 | 220 | assert(*value == TheUnion2.Item1); |
| 221 | 221 | } |
| 222 | 222 | |
| ... | ... | @@ -232,6 +232,33 @@ test "constant packed union" { |
| 232 | 232 | }); |
| 233 | 233 | } |
| 234 | 234 | |
| 235 | fn testConstPackedUnion(expected_tokens: []const PackThis) { | |
| 235 | fn testConstPackedUnion(expected_tokens: []const PackThis) void { | |
| 236 | 236 | assert(expected_tokens[0].StringLiteral == 1); |
| 237 | 237 | } |
| 238 | ||
| 239 | test "switch on union with only 1 field" { | |
| 240 | var r: PartialInst = undefined; | |
| 241 | r = PartialInst.Compiled; | |
| 242 | switch (r) { | |
| 243 | PartialInst.Compiled => { | |
| 244 | var z: PartialInstWithPayload = undefined; | |
| 245 | z = PartialInstWithPayload { .Compiled = 1234 }; | |
| 246 | switch (z) { | |
| 247 | PartialInstWithPayload.Compiled => |x| { | |
| 248 | assert(x == 1234); | |
| 249 | return; | |
| 250 | }, | |
| 251 | } | |
| 252 | }, | |
| 253 | } | |
| 254 | unreachable; | |
| 255 | } | |
| 256 | ||
| 257 | const PartialInst = union(enum) { | |
| 258 | Compiled, | |
| 259 | }; | |
| 260 | ||
| 261 | const PartialInstWithPayload = union(enum) { | |
| 262 | Compiled: i32, | |
| 263 | }; | |
| 264 |
test/cases/var_args.zig+16-8| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const assert = @import("std").debug.assert; |
| 2 | 2 | |
| 3 | fn add(args: ...) -> i32 { | |
| 3 | fn add(args: ...) i32 { | |
| 4 | 4 | var sum = i32(0); |
| 5 | 5 | {comptime var i: usize = 0; inline while (i < args.len) : (i += 1) { |
| 6 | 6 | sum += args[i]; |
| ... | ... | @@ -14,7 +14,7 @@ test "add arbitrary args" { |
| 14 | 14 | assert(add() == 0); |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | fn readFirstVarArg(args: ...) { | |
| 17 | fn readFirstVarArg(args: ...) void { | |
| 18 | 18 | const value = args[0]; |
| 19 | 19 | } |
| 20 | 20 | |
| ... | ... | @@ -28,7 +28,7 @@ test "pass args directly" { |
| 28 | 28 | assert(addSomeStuff() == 0); |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | fn addSomeStuff(args: ...) -> i32 { | |
| 31 | fn addSomeStuff(args: ...) i32 { | |
| 32 | 32 | return add(args); |
| 33 | 33 | } |
| 34 | 34 | |
| ... | ... | @@ -45,7 +45,7 @@ test "runtime parameter before var args" { |
| 45 | 45 | //} |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | fn extraFn(extra: u32, args: ...) -> usize { | |
| 48 | fn extraFn(extra: u32, args: ...) usize { | |
| 49 | 49 | if (args.len >= 1) { |
| 50 | 50 | assert(args[0] == false); |
| 51 | 51 | } |
| ... | ... | @@ -56,10 +56,10 @@ fn extraFn(extra: u32, args: ...) -> usize { |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | 58 | |
| 59 | const foos = []fn(...) -> bool { foo1, foo2 }; | |
| 59 | const foos = []fn(...) bool { foo1, foo2 }; | |
| 60 | 60 | |
| 61 | fn foo1(args: ...) -> bool { return true; } | |
| 62 | fn foo2(args: ...) -> bool { return false; } | |
| 61 | fn foo1(args: ...) bool { return true; } | |
| 62 | fn foo2(args: ...) bool { return false; } | |
| 63 | 63 | |
| 64 | 64 | test "array of var args functions" { |
| 65 | 65 | assert(foos[0]()); |
| ... | ... | @@ -73,9 +73,17 @@ test "pass array and slice of same array to var args should have same pointers" |
| 73 | 73 | return assertSlicePtrsEql(array, slice); |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | fn assertSlicePtrsEql(args: ...) { | |
| 76 | fn assertSlicePtrsEql(args: ...) void { | |
| 77 | 77 | const s1 = ([]const u8)(args[0]); |
| 78 | 78 | const s2 = args[1]; |
| 79 | 79 | assert(s1.ptr == s2.ptr); |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | ||
| 83 | test "pass zero length array to var args param" { | |
| 84 | doNothingWithFirstArg(""); | |
| 85 | } | |
| 86 | ||
| 87 | fn doNothingWithFirstArg(args: ...) void { | |
| 88 | const a = args[0]; | |
| 89 | } |
test/cases/while.zig+16-16| ... | ... | @@ -8,10 +8,10 @@ test "while loop" { |
| 8 | 8 | assert(i == 4); |
| 9 | 9 | assert(whileLoop1() == 1); |
| 10 | 10 | } |
| 11 | fn whileLoop1() -> i32 { | |
| 11 | fn whileLoop1() i32 { | |
| 12 | 12 | return whileLoop2(); |
| 13 | 13 | } |
| 14 | fn whileLoop2() -> i32 { | |
| 14 | fn whileLoop2() i32 { | |
| 15 | 15 | while (true) { |
| 16 | 16 | return 1; |
| 17 | 17 | } |
| ... | ... | @@ -20,10 +20,10 @@ test "static eval while" { |
| 20 | 20 | assert(static_eval_while_number == 1); |
| 21 | 21 | } |
| 22 | 22 | const static_eval_while_number = staticWhileLoop1(); |
| 23 | fn staticWhileLoop1() -> i32 { | |
| 23 | fn staticWhileLoop1() i32 { | |
| 24 | 24 | return whileLoop2(); |
| 25 | 25 | } |
| 26 | fn staticWhileLoop2() -> i32 { | |
| 26 | fn staticWhileLoop2() i32 { | |
| 27 | 27 | while (true) { |
| 28 | 28 | return 1; |
| 29 | 29 | } |
| ... | ... | @@ -34,7 +34,7 @@ test "continue and break" { |
| 34 | 34 | assert(continue_and_break_counter == 8); |
| 35 | 35 | } |
| 36 | 36 | var continue_and_break_counter: i32 = 0; |
| 37 | fn runContinueAndBreakTest() { | |
| 37 | fn runContinueAndBreakTest() void { | |
| 38 | 38 | var i : i32 = 0; |
| 39 | 39 | while (true) { |
| 40 | 40 | continue_and_break_counter += 2; |
| ... | ... | @@ -50,7 +50,7 @@ fn runContinueAndBreakTest() { |
| 50 | 50 | test "return with implicit cast from while loop" { |
| 51 | 51 | returnWithImplicitCastFromWhileLoopTest() catch unreachable; |
| 52 | 52 | } |
| 53 | fn returnWithImplicitCastFromWhileLoopTest() -> %void { | |
| 53 | fn returnWithImplicitCastFromWhileLoopTest() %void { | |
| 54 | 54 | while (true) { |
| 55 | 55 | return; |
| 56 | 56 | } |
| ... | ... | @@ -117,7 +117,7 @@ test "while with error union condition" { |
| 117 | 117 | |
| 118 | 118 | var numbers_left: i32 = undefined; |
| 119 | 119 | error OutOfNumbers; |
| 120 | fn getNumberOrErr() -> %i32 { | |
| 120 | fn getNumberOrErr() %i32 { | |
| 121 | 121 | return if (numbers_left == 0) |
| 122 | 122 | error.OutOfNumbers |
| 123 | 123 | else x: { |
| ... | ... | @@ -125,7 +125,7 @@ fn getNumberOrErr() -> %i32 { |
| 125 | 125 | break :x numbers_left; |
| 126 | 126 | }; |
| 127 | 127 | } |
| 128 | fn getNumberOrNull() -> ?i32 { | |
| 128 | fn getNumberOrNull() ?i32 { | |
| 129 | 129 | return if (numbers_left == 0) |
| 130 | 130 | null |
| 131 | 131 | else x: { |
| ... | ... | @@ -181,7 +181,7 @@ test "break from outer while loop" { |
| 181 | 181 | comptime testBreakOuter(); |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | fn testBreakOuter() { | |
| 184 | fn testBreakOuter() void { | |
| 185 | 185 | outer: while (true) { |
| 186 | 186 | while (true) { |
| 187 | 187 | break :outer; |
| ... | ... | @@ -194,7 +194,7 @@ test "continue outer while loop" { |
| 194 | 194 | comptime testContinueOuter(); |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | fn testContinueOuter() { | |
| 197 | fn testContinueOuter() void { | |
| 198 | 198 | var i: usize = 0; |
| 199 | 199 | outer: while (i < 10) : (i += 1) { |
| 200 | 200 | while (true) { |
| ... | ... | @@ -203,10 +203,10 @@ fn testContinueOuter() { |
| 203 | 203 | } |
| 204 | 204 | } |
| 205 | 205 | |
| 206 | fn returnNull() -> ?i32 { return null; } | |
| 207 | fn returnMaybe(x: i32) -> ?i32 { return x; } | |
| 206 | fn returnNull() ?i32 { return null; } | |
| 207 | fn returnMaybe(x: i32) ?i32 { return x; } | |
| 208 | 208 | error YouWantedAnError; |
| 209 | fn returnError() -> %i32 { return error.YouWantedAnError; } | |
| 210 | fn returnSuccess(x: i32) -> %i32 { return x; } | |
| 211 | fn returnFalse() -> bool { return false; } | |
| 212 | fn returnTrue() -> bool { return true; } | |
| 209 | fn returnError() %i32 { return error.YouWantedAnError; } | |
| 210 | fn returnSuccess(x: i32) %i32 { return x; } | |
| 211 | fn returnFalse() bool { return false; } | |
| 212 | fn returnTrue() bool { return true; } |
test/compare_output.zig+37-37| ... | ... | @@ -1,10 +1,10 @@ |
| 1 | 1 | const os = @import("std").os; |
| 2 | 2 | const tests = @import("tests.zig"); |
| 3 | 3 | |
| 4 | pub fn addCases(cases: &tests.CompareOutputContext) { | |
| 4 | pub fn addCases(cases: &tests.CompareOutputContext) void { | |
| 5 | 5 | cases.addC("hello world with libc", |
| 6 | 6 | \\const c = @cImport(@cInclude("stdio.h")); |
| 7 | \\export fn main(argc: c_int, argv: &&u8) -> c_int { | |
| 7 | \\export fn main(argc: c_int, argv: &&u8) c_int { | |
| 8 | 8 | \\ _ = c.puts(c"Hello, world!"); |
| 9 | 9 | \\ return 0; |
| 10 | 10 | \\} |
| ... | ... | @@ -15,13 +15,13 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 15 | 15 | \\use @import("std").io; |
| 16 | 16 | \\use @import("foo.zig"); |
| 17 | 17 | \\ |
| 18 | \\pub fn main() -> %void { | |
| 18 | \\pub fn main() %void { | |
| 19 | 19 | \\ privateFunction(); |
| 20 | 20 | \\ const stdout = &(FileOutStream.init(&(getStdOut() catch unreachable)).stream); |
| 21 | 21 | \\ stdout.print("OK 2\n") catch unreachable; |
| 22 | 22 | \\} |
| 23 | 23 | \\ |
| 24 | \\fn privateFunction() { | |
| 24 | \\fn privateFunction() void { | |
| 25 | 25 | \\ printText(); |
| 26 | 26 | \\} |
| 27 | 27 | , "OK 1\nOK 2\n"); |
| ... | ... | @@ -31,12 +31,12 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 31 | 31 | \\ |
| 32 | 32 | \\// purposefully conflicting function with main.zig |
| 33 | 33 | \\// but it's private so it should be OK |
| 34 | \\fn privateFunction() { | |
| 34 | \\fn privateFunction() void { | |
| 35 | 35 | \\ const stdout = &(FileOutStream.init(&(getStdOut() catch unreachable)).stream); |
| 36 | 36 | \\ stdout.print("OK 1\n") catch unreachable; |
| 37 | 37 | \\} |
| 38 | 38 | \\ |
| 39 | \\pub fn printText() { | |
| 39 | \\pub fn printText() void { | |
| 40 | 40 | \\ privateFunction(); |
| 41 | 41 | \\} |
| 42 | 42 | ); |
| ... | ... | @@ -49,7 +49,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 49 | 49 | \\use @import("foo.zig"); |
| 50 | 50 | \\use @import("bar.zig"); |
| 51 | 51 | \\ |
| 52 | \\pub fn main() -> %void { | |
| 52 | \\pub fn main() %void { | |
| 53 | 53 | \\ foo_function(); |
| 54 | 54 | \\ bar_function(); |
| 55 | 55 | \\} |
| ... | ... | @@ -57,7 +57,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 57 | 57 | |
| 58 | 58 | tc.addSourceFile("foo.zig", |
| 59 | 59 | \\use @import("std").io; |
| 60 | \\pub fn foo_function() { | |
| 60 | \\pub fn foo_function() void { | |
| 61 | 61 | \\ const stdout = &(FileOutStream.init(&(getStdOut() catch unreachable)).stream); |
| 62 | 62 | \\ stdout.print("OK\n") catch unreachable; |
| 63 | 63 | \\} |
| ... | ... | @@ -67,7 +67,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 67 | 67 | \\use @import("other.zig"); |
| 68 | 68 | \\use @import("std").io; |
| 69 | 69 | \\ |
| 70 | \\pub fn bar_function() { | |
| 70 | \\pub fn bar_function() void { | |
| 71 | 71 | \\ if (foo_function()) { |
| 72 | 72 | \\ const stdout = &(FileOutStream.init(&(getStdOut() catch unreachable)).stream); |
| 73 | 73 | \\ stdout.print("OK\n") catch unreachable; |
| ... | ... | @@ -76,7 +76,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 76 | 76 | ); |
| 77 | 77 | |
| 78 | 78 | tc.addSourceFile("other.zig", |
| 79 | \\pub fn foo_function() -> bool { | |
| 79 | \\pub fn foo_function() bool { | |
| 80 | 80 | \\ // this one conflicts with the one from foo |
| 81 | 81 | \\ return true; |
| 82 | 82 | \\} |
| ... | ... | @@ -89,7 +89,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 89 | 89 | var tc = cases.create("two files use import each other", |
| 90 | 90 | \\use @import("a.zig"); |
| 91 | 91 | \\ |
| 92 | \\pub fn main() -> %void { | |
| 92 | \\pub fn main() %void { | |
| 93 | 93 | \\ ok(); |
| 94 | 94 | \\} |
| 95 | 95 | , "OK\n"); |
| ... | ... | @@ -100,7 +100,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 100 | 100 | \\ |
| 101 | 101 | \\pub const a_text = "OK\n"; |
| 102 | 102 | \\ |
| 103 | \\pub fn ok() { | |
| 103 | \\pub fn ok() void { | |
| 104 | 104 | \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); |
| 105 | 105 | \\ stdout.print(b_text) catch unreachable; |
| 106 | 106 | \\} |
| ... | ... | @@ -118,7 +118,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 118 | 118 | cases.add("hello world without libc", |
| 119 | 119 | \\const io = @import("std").io; |
| 120 | 120 | \\ |
| 121 | \\pub fn main() -> %void { | |
| 121 | \\pub fn main() %void { | |
| 122 | 122 | \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); |
| 123 | 123 | \\ stdout.print("Hello, world!\n{d4} {x3} {c}\n", u32(12), u16(0x12), u8('a')) catch unreachable; |
| 124 | 124 | \\} |
| ... | ... | @@ -137,7 +137,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 137 | 137 | \\ @cInclude("stdio.h"); |
| 138 | 138 | \\}); |
| 139 | 139 | \\ |
| 140 | \\export fn main(argc: c_int, argv: &&u8) -> c_int { | |
| 140 | \\export fn main(argc: c_int, argv: &&u8) c_int { | |
| 141 | 141 | \\ if (is_windows) { |
| 142 | 142 | \\ // we want actual \n, not \r\n |
| 143 | 143 | \\ _ = c._setmode(1, c._O_BINARY); |
| ... | ... | @@ -268,10 +268,10 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 268 | 268 | \\const z = io.stdin_fileno; |
| 269 | 269 | \\const x : @typeOf(y) = 1234; |
| 270 | 270 | \\const y : u16 = 5678; |
| 271 | \\pub fn main() -> %void { | |
| 271 | \\pub fn main() %void { | |
| 272 | 272 | \\ var x_local : i32 = print_ok(x); |
| 273 | 273 | \\} |
| 274 | \\fn print_ok(val: @typeOf(x)) -> @typeOf(foo) { | |
| 274 | \\fn print_ok(val: @typeOf(x)) @typeOf(foo) { | |
| 275 | 275 | \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); |
| 276 | 276 | \\ stdout.print("OK\n") catch unreachable; |
| 277 | 277 | \\ return 0; |
| ... | ... | @@ -282,7 +282,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 282 | 282 | cases.addC("expose function pointer to C land", |
| 283 | 283 | \\const c = @cImport(@cInclude("stdlib.h")); |
| 284 | 284 | \\ |
| 285 | \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int { | |
| 285 | \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) c_int { | |
| 286 | 286 | \\ const a_int = @ptrCast(&align(1) i32, a ?? unreachable); |
| 287 | 287 | \\ const b_int = @ptrCast(&align(1) i32, b ?? unreachable); |
| 288 | 288 | \\ if (*a_int < *b_int) { |
| ... | ... | @@ -294,7 +294,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 294 | 294 | \\ } |
| 295 | 295 | \\} |
| 296 | 296 | \\ |
| 297 | \\export fn main() -> c_int { | |
| 297 | \\export fn main() c_int { | |
| 298 | 298 | \\ var array = []u32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 }; |
| 299 | 299 | \\ |
| 300 | 300 | \\ c.qsort(@ptrCast(&c_void, &array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn); |
| ... | ... | @@ -322,7 +322,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 322 | 322 | \\ @cInclude("stdio.h"); |
| 323 | 323 | \\}); |
| 324 | 324 | \\ |
| 325 | \\export fn main(argc: c_int, argv: &&u8) -> c_int { | |
| 325 | \\export fn main(argc: c_int, argv: &&u8) c_int { | |
| 326 | 326 | \\ if (is_windows) { |
| 327 | 327 | \\ // we want actual \n, not \r\n |
| 328 | 328 | \\ _ = c._setmode(1, c._O_BINARY); |
| ... | ... | @@ -342,16 +342,16 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 342 | 342 | \\const Foo = struct { |
| 343 | 343 | \\ field1: Bar, |
| 344 | 344 | \\ |
| 345 | \\ fn method(a: &const Foo) -> bool { return true; } | |
| 345 | \\ fn method(a: &const Foo) bool { return true; } | |
| 346 | 346 | \\}; |
| 347 | 347 | \\ |
| 348 | 348 | \\const Bar = struct { |
| 349 | 349 | \\ field2: i32, |
| 350 | 350 | \\ |
| 351 | \\ fn method(b: &const Bar) -> bool { return true; } | |
| 351 | \\ fn method(b: &const Bar) bool { return true; } | |
| 352 | 352 | \\}; |
| 353 | 353 | \\ |
| 354 | \\pub fn main() -> %void { | |
| 354 | \\pub fn main() %void { | |
| 355 | 355 | \\ const bar = Bar {.field2 = 13,}; |
| 356 | 356 | \\ const foo = Foo {.field1 = bar,}; |
| 357 | 357 | \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); |
| ... | ... | @@ -367,7 +367,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 367 | 367 | |
| 368 | 368 | cases.add("defer with only fallthrough", |
| 369 | 369 | \\const io = @import("std").io; |
| 370 | \\pub fn main() -> %void { | |
| 370 | \\pub fn main() %void { | |
| 371 | 371 | \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); |
| 372 | 372 | \\ stdout.print("before\n") catch unreachable; |
| 373 | 373 | \\ defer stdout.print("defer1\n") catch unreachable; |
| ... | ... | @@ -380,7 +380,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 380 | 380 | cases.add("defer with return", |
| 381 | 381 | \\const io = @import("std").io; |
| 382 | 382 | \\const os = @import("std").os; |
| 383 | \\pub fn main() -> %void { | |
| 383 | \\pub fn main() %void { | |
| 384 | 384 | \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); |
| 385 | 385 | \\ stdout.print("before\n") catch unreachable; |
| 386 | 386 | \\ defer stdout.print("defer1\n") catch unreachable; |
| ... | ... | @@ -392,41 +392,41 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 392 | 392 | \\} |
| 393 | 393 | , "before\ndefer2\ndefer1\n"); |
| 394 | 394 | |
| 395 | cases.add("%defer and it fails", | |
| 395 | cases.add("errdefer and it fails", | |
| 396 | 396 | \\const io = @import("std").io; |
| 397 | \\pub fn main() -> %void { | |
| 397 | \\pub fn main() %void { | |
| 398 | 398 | \\ do_test() catch return; |
| 399 | 399 | \\} |
| 400 | \\fn do_test() -> %void { | |
| 400 | \\fn do_test() %void { | |
| 401 | 401 | \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); |
| 402 | 402 | \\ stdout.print("before\n") catch unreachable; |
| 403 | 403 | \\ defer stdout.print("defer1\n") catch unreachable; |
| 404 | \\ %defer stdout.print("deferErr\n") catch unreachable; | |
| 404 | \\ errdefer stdout.print("deferErr\n") catch unreachable; | |
| 405 | 405 | \\ try its_gonna_fail(); |
| 406 | 406 | \\ defer stdout.print("defer3\n") catch unreachable; |
| 407 | 407 | \\ stdout.print("after\n") catch unreachable; |
| 408 | 408 | \\} |
| 409 | 409 | \\error IToldYouItWouldFail; |
| 410 | \\fn its_gonna_fail() -> %void { | |
| 410 | \\fn its_gonna_fail() %void { | |
| 411 | 411 | \\ return error.IToldYouItWouldFail; |
| 412 | 412 | \\} |
| 413 | 413 | , "before\ndeferErr\ndefer1\n"); |
| 414 | 414 | |
| 415 | cases.add("%defer and it passes", | |
| 415 | cases.add("errdefer and it passes", | |
| 416 | 416 | \\const io = @import("std").io; |
| 417 | \\pub fn main() -> %void { | |
| 417 | \\pub fn main() %void { | |
| 418 | 418 | \\ do_test() catch return; |
| 419 | 419 | \\} |
| 420 | \\fn do_test() -> %void { | |
| 420 | \\fn do_test() %void { | |
| 421 | 421 | \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); |
| 422 | 422 | \\ stdout.print("before\n") catch unreachable; |
| 423 | 423 | \\ defer stdout.print("defer1\n") catch unreachable; |
| 424 | \\ %defer stdout.print("deferErr\n") catch unreachable; | |
| 424 | \\ errdefer stdout.print("deferErr\n") catch unreachable; | |
| 425 | 425 | \\ try its_gonna_pass(); |
| 426 | 426 | \\ defer stdout.print("defer3\n") catch unreachable; |
| 427 | 427 | \\ stdout.print("after\n") catch unreachable; |
| 428 | 428 | \\} |
| 429 | \\fn its_gonna_pass() -> %void { } | |
| 429 | \\fn its_gonna_pass() %void { } | |
| 430 | 430 | , "before\nafter\ndefer3\ndefer1\n"); |
| 431 | 431 | |
| 432 | 432 | cases.addCase(x: { |
| ... | ... | @@ -434,7 +434,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 434 | 434 | \\const foo_txt = @embedFile("foo.txt"); |
| 435 | 435 | \\const io = @import("std").io; |
| 436 | 436 | \\ |
| 437 | \\pub fn main() -> %void { | |
| 437 | \\pub fn main() %void { | |
| 438 | 438 | \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); |
| 439 | 439 | \\ stdout.print(foo_txt) catch unreachable; |
| 440 | 440 | \\} |
| ... | ... | @@ -452,7 +452,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 452 | 452 | \\const os = std.os; |
| 453 | 453 | \\const allocator = std.debug.global_allocator; |
| 454 | 454 | \\ |
| 455 | \\pub fn main() -> %void { | |
| 455 | \\pub fn main() %void { | |
| 456 | 456 | \\ var args_it = os.args(); |
| 457 | 457 | \\ var stdout_file = try io.getStdOut(); |
| 458 | 458 | \\ var stdout_adapter = io.FileOutStream.init(&stdout_file); |
| ... | ... | @@ -493,7 +493,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 493 | 493 | \\const os = std.os; |
| 494 | 494 | \\const allocator = std.debug.global_allocator; |
| 495 | 495 | \\ |
| 496 | \\pub fn main() -> %void { | |
| 496 | \\pub fn main() %void { | |
| 497 | 497 | \\ var args_it = os.args(); |
| 498 | 498 | \\ var stdout_file = try io.getStdOut(); |
| 499 | 499 | \\ var stdout_adapter = io.FileOutStream.init(&stdout_file); |
test/compile_errors.zig+459-413| ... | ... | @@ -1,17 +1,63 @@ |
| 1 | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | |
| 3 | pub fn addCases(cases: &tests.CompileErrorContext) { | |
| 3 | pub fn addCases(cases: &tests.CompileErrorContext) void { | |
| 4 | cases.add("function with non-extern enum parameter", | |
| 5 | \\const Foo = enum { A, B, C }; | |
| 6 | \\export fn entry(foo: Foo) void { } | |
| 7 | , ".tmp_source.zig:2:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'"); | |
| 8 | ||
| 9 | cases.add("function with non-extern struct parameter", | |
| 10 | \\const Foo = struct { | |
| 11 | \\ A: i32, | |
| 12 | \\ B: f32, | |
| 13 | \\ C: bool, | |
| 14 | \\}; | |
| 15 | \\export fn entry(foo: Foo) void { } | |
| 16 | , ".tmp_source.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'"); | |
| 17 | ||
| 18 | cases.add("function with non-extern union parameter", | |
| 19 | \\const Foo = union { | |
| 20 | \\ A: i32, | |
| 21 | \\ B: f32, | |
| 22 | \\ C: bool, | |
| 23 | \\}; | |
| 24 | \\export fn entry(foo: Foo) void { } | |
| 25 | , ".tmp_source.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'"); | |
| 26 | ||
| 27 | cases.add("switch on enum with 1 field with no prongs", | |
| 28 | \\const Foo = enum { M }; | |
| 29 | \\ | |
| 30 | \\export fn entry() void { | |
| 31 | \\ var f = Foo.M; | |
| 32 | \\ switch (f) {} | |
| 33 | \\} | |
| 34 | , ".tmp_source.zig:5:5: error: enumeration value 'Foo.M' not handled in switch"); | |
| 35 | ||
| 36 | cases.add("shift by negative comptime integer", | |
| 37 | \\comptime { | |
| 38 | \\ var a = 1 >> -1; | |
| 39 | \\} | |
| 40 | , ".tmp_source.zig:2:18: error: shift by negative value -1"); | |
| 41 | ||
| 42 | cases.add("@panic called at compile time", | |
| 43 | \\export fn entry() void { | |
| 44 | \\ comptime { | |
| 45 | \\ @panic("aoeu"); | |
| 46 | \\ } | |
| 47 | \\} | |
| 48 | , ".tmp_source.zig:3:9: error: encountered @panic at compile-time"); | |
| 49 | ||
| 4 | 50 | cases.add("wrong return type for main", |
| 5 | \\pub fn main() -> f32 { } | |
| 51 | \\pub fn main() f32 { } | |
| 6 | 52 | , "error: expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"); |
| 7 | 53 | |
| 8 | 54 | cases.add("double ?? on main return value", |
| 9 | \\pub fn main() -> ??void { | |
| 55 | \\pub fn main() ??void { | |
| 10 | 56 | \\} |
| 11 | 57 | , "error: expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"); |
| 12 | 58 | |
| 13 | 59 | cases.add("bad identifier in function with struct defined inside function which references local const", |
| 14 | \\export fn entry() { | |
| 60 | \\export fn entry() void { | |
| 15 | 61 | \\ const BlockKind = u32; |
| 16 | 62 | \\ |
| 17 | 63 | \\ const Block = struct { |
| ... | ... | @@ -23,7 +69,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 23 | 69 | , ".tmp_source.zig:8:5: error: use of undeclared identifier 'bogus'"); |
| 24 | 70 | |
| 25 | 71 | cases.add("labeled break not found", |
| 26 | \\export fn entry() { | |
| 72 | \\export fn entry() void { | |
| 27 | 73 | \\ blah: while (true) { |
| 28 | 74 | \\ while (true) { |
| 29 | 75 | \\ break :outer; |
| ... | ... | @@ -33,7 +79,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 33 | 79 | , ".tmp_source.zig:4:13: error: label not found: 'outer'"); |
| 34 | 80 | |
| 35 | 81 | cases.add("labeled continue not found", |
| 36 | \\export fn entry() { | |
| 82 | \\export fn entry() void { | |
| 37 | 83 | \\ var i: usize = 0; |
| 38 | 84 | \\ blah: while (i < 10) : (i += 1) { |
| 39 | 85 | \\ while (true) { |
| ... | ... | @@ -44,17 +90,17 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 44 | 90 | , ".tmp_source.zig:5:13: error: labeled loop not found: 'outer'"); |
| 45 | 91 | |
| 46 | 92 | cases.add("attempt to use 0 bit type in extern fn", |
| 47 | \\extern fn foo(ptr: extern fn(&void)); | |
| 93 | \\extern fn foo(ptr: extern fn(&void) void) void; | |
| 48 | 94 | \\ |
| 49 | \\export fn entry() { | |
| 95 | \\export fn entry() void { | |
| 50 | 96 | \\ foo(bar); |
| 51 | 97 | \\} |
| 52 | 98 | \\ |
| 53 | \\extern fn bar(x: &void) { } | |
| 99 | \\extern fn bar(x: &void) void { } | |
| 54 | 100 | , ".tmp_source.zig:7:18: error: parameter of type '&void' has 0 bits; not allowed in function with calling convention 'ccc'"); |
| 55 | 101 | |
| 56 | 102 | cases.add("implicit semicolon - block statement", |
| 57 | \\export fn entry() { | |
| 103 | \\export fn entry() void { | |
| 58 | 104 | \\ {} |
| 59 | 105 | \\ var good = {}; |
| 60 | 106 | \\ ({}) |
| ... | ... | @@ -63,7 +109,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 63 | 109 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 64 | 110 | |
| 65 | 111 | cases.add("implicit semicolon - block expr", |
| 66 | \\export fn entry() { | |
| 112 | \\export fn entry() void { | |
| 67 | 113 | \\ _ = {}; |
| 68 | 114 | \\ var good = {}; |
| 69 | 115 | \\ _ = {} |
| ... | ... | @@ -72,7 +118,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 72 | 118 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 73 | 119 | |
| 74 | 120 | cases.add("implicit semicolon - comptime statement", |
| 75 | \\export fn entry() { | |
| 121 | \\export fn entry() void { | |
| 76 | 122 | \\ comptime {} |
| 77 | 123 | \\ var good = {}; |
| 78 | 124 | \\ comptime ({}) |
| ... | ... | @@ -81,7 +127,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 81 | 127 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 82 | 128 | |
| 83 | 129 | cases.add("implicit semicolon - comptime expression", |
| 84 | \\export fn entry() { | |
| 130 | \\export fn entry() void { | |
| 85 | 131 | \\ _ = comptime {}; |
| 86 | 132 | \\ var good = {}; |
| 87 | 133 | \\ _ = comptime {} |
| ... | ... | @@ -90,7 +136,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 90 | 136 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 91 | 137 | |
| 92 | 138 | cases.add("implicit semicolon - defer", |
| 93 | \\export fn entry() { | |
| 139 | \\export fn entry() void { | |
| 94 | 140 | \\ defer {} |
| 95 | 141 | \\ var good = {}; |
| 96 | 142 | \\ defer ({}) |
| ... | ... | @@ -99,7 +145,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 99 | 145 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 100 | 146 | |
| 101 | 147 | cases.add("implicit semicolon - if statement", |
| 102 | \\export fn entry() { | |
| 148 | \\export fn entry() void { | |
| 103 | 149 | \\ if(true) {} |
| 104 | 150 | \\ var good = {}; |
| 105 | 151 | \\ if(true) ({}) |
| ... | ... | @@ -108,7 +154,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 108 | 154 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 109 | 155 | |
| 110 | 156 | cases.add("implicit semicolon - if expression", |
| 111 | \\export fn entry() { | |
| 157 | \\export fn entry() void { | |
| 112 | 158 | \\ _ = if(true) {}; |
| 113 | 159 | \\ var good = {}; |
| 114 | 160 | \\ _ = if(true) {} |
| ... | ... | @@ -117,7 +163,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 117 | 163 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 118 | 164 | |
| 119 | 165 | cases.add("implicit semicolon - if-else statement", |
| 120 | \\export fn entry() { | |
| 166 | \\export fn entry() void { | |
| 121 | 167 | \\ if(true) {} else {} |
| 122 | 168 | \\ var good = {}; |
| 123 | 169 | \\ if(true) ({}) else ({}) |
| ... | ... | @@ -126,7 +172,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 126 | 172 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 127 | 173 | |
| 128 | 174 | cases.add("implicit semicolon - if-else expression", |
| 129 | \\export fn entry() { | |
| 175 | \\export fn entry() void { | |
| 130 | 176 | \\ _ = if(true) {} else {}; |
| 131 | 177 | \\ var good = {}; |
| 132 | 178 | \\ _ = if(true) {} else {} |
| ... | ... | @@ -135,7 +181,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 135 | 181 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 136 | 182 | |
| 137 | 183 | cases.add("implicit semicolon - if-else-if statement", |
| 138 | \\export fn entry() { | |
| 184 | \\export fn entry() void { | |
| 139 | 185 | \\ if(true) {} else if(true) {} |
| 140 | 186 | \\ var good = {}; |
| 141 | 187 | \\ if(true) ({}) else if(true) ({}) |
| ... | ... | @@ -144,7 +190,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 144 | 190 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 145 | 191 | |
| 146 | 192 | cases.add("implicit semicolon - if-else-if expression", |
| 147 | \\export fn entry() { | |
| 193 | \\export fn entry() void { | |
| 148 | 194 | \\ _ = if(true) {} else if(true) {}; |
| 149 | 195 | \\ var good = {}; |
| 150 | 196 | \\ _ = if(true) {} else if(true) {} |
| ... | ... | @@ -153,7 +199,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 153 | 199 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 154 | 200 | |
| 155 | 201 | cases.add("implicit semicolon - if-else-if-else statement", |
| 156 | \\export fn entry() { | |
| 202 | \\export fn entry() void { | |
| 157 | 203 | \\ if(true) {} else if(true) {} else {} |
| 158 | 204 | \\ var good = {}; |
| 159 | 205 | \\ if(true) ({}) else if(true) ({}) else ({}) |
| ... | ... | @@ -162,7 +208,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 162 | 208 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 163 | 209 | |
| 164 | 210 | cases.add("implicit semicolon - if-else-if-else expression", |
| 165 | \\export fn entry() { | |
| 211 | \\export fn entry() void { | |
| 166 | 212 | \\ _ = if(true) {} else if(true) {} else {}; |
| 167 | 213 | \\ var good = {}; |
| 168 | 214 | \\ _ = if(true) {} else if(true) {} else {} |
| ... | ... | @@ -171,7 +217,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 171 | 217 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 172 | 218 | |
| 173 | 219 | cases.add("implicit semicolon - test statement", |
| 174 | \\export fn entry() { | |
| 220 | \\export fn entry() void { | |
| 175 | 221 | \\ if (foo()) |_| {} |
| 176 | 222 | \\ var good = {}; |
| 177 | 223 | \\ if (foo()) |_| ({}) |
| ... | ... | @@ -180,7 +226,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 180 | 226 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 181 | 227 | |
| 182 | 228 | cases.add("implicit semicolon - test expression", |
| 183 | \\export fn entry() { | |
| 229 | \\export fn entry() void { | |
| 184 | 230 | \\ _ = if (foo()) |_| {}; |
| 185 | 231 | \\ var good = {}; |
| 186 | 232 | \\ _ = if (foo()) |_| {} |
| ... | ... | @@ -189,7 +235,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 189 | 235 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 190 | 236 | |
| 191 | 237 | cases.add("implicit semicolon - while statement", |
| 192 | \\export fn entry() { | |
| 238 | \\export fn entry() void { | |
| 193 | 239 | \\ while(true) {} |
| 194 | 240 | \\ var good = {}; |
| 195 | 241 | \\ while(true) ({}) |
| ... | ... | @@ -198,7 +244,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 198 | 244 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 199 | 245 | |
| 200 | 246 | cases.add("implicit semicolon - while expression", |
| 201 | \\export fn entry() { | |
| 247 | \\export fn entry() void { | |
| 202 | 248 | \\ _ = while(true) {}; |
| 203 | 249 | \\ var good = {}; |
| 204 | 250 | \\ _ = while(true) {} |
| ... | ... | @@ -207,7 +253,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 207 | 253 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 208 | 254 | |
| 209 | 255 | cases.add("implicit semicolon - while-continue statement", |
| 210 | \\export fn entry() { | |
| 256 | \\export fn entry() void { | |
| 211 | 257 | \\ while(true):({}) {} |
| 212 | 258 | \\ var good = {}; |
| 213 | 259 | \\ while(true):({}) ({}) |
| ... | ... | @@ -216,7 +262,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 216 | 262 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 217 | 263 | |
| 218 | 264 | cases.add("implicit semicolon - while-continue expression", |
| 219 | \\export fn entry() { | |
| 265 | \\export fn entry() void { | |
| 220 | 266 | \\ _ = while(true):({}) {}; |
| 221 | 267 | \\ var good = {}; |
| 222 | 268 | \\ _ = while(true):({}) {} |
| ... | ... | @@ -225,7 +271,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 225 | 271 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 226 | 272 | |
| 227 | 273 | cases.add("implicit semicolon - for statement", |
| 228 | \\export fn entry() { | |
| 274 | \\export fn entry() void { | |
| 229 | 275 | \\ for(foo()) {} |
| 230 | 276 | \\ var good = {}; |
| 231 | 277 | \\ for(foo()) ({}) |
| ... | ... | @@ -234,7 +280,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 234 | 280 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 235 | 281 | |
| 236 | 282 | cases.add("implicit semicolon - for expression", |
| 237 | \\export fn entry() { | |
| 283 | \\export fn entry() void { | |
| 238 | 284 | \\ _ = for(foo()) {}; |
| 239 | 285 | \\ var good = {}; |
| 240 | 286 | \\ _ = for(foo()) {} |
| ... | ... | @@ -243,60 +289,60 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 243 | 289 | , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); |
| 244 | 290 | |
| 245 | 291 | cases.add("multiple function definitions", |
| 246 | \\fn a() {} | |
| 247 | \\fn a() {} | |
| 248 | \\export fn entry() { a(); } | |
| 292 | \\fn a() void {} | |
| 293 | \\fn a() void {} | |
| 294 | \\export fn entry() void { a(); } | |
| 249 | 295 | , ".tmp_source.zig:2:1: error: redefinition of 'a'"); |
| 250 | 296 | |
| 251 | 297 | cases.add("unreachable with return", |
| 252 | \\fn a() -> noreturn {return;} | |
| 253 | \\export fn entry() { a(); } | |
| 254 | , ".tmp_source.zig:1:21: error: expected type 'noreturn', found 'void'"); | |
| 298 | \\fn a() noreturn {return;} | |
| 299 | \\export fn entry() void { a(); } | |
| 300 | , ".tmp_source.zig:1:18: error: expected type 'noreturn', found 'void'"); | |
| 255 | 301 | |
| 256 | 302 | cases.add("control reaches end of non-void function", |
| 257 | \\fn a() -> i32 {} | |
| 258 | \\export fn entry() { _ = a(); } | |
| 259 | , ".tmp_source.zig:1:15: error: expected type 'i32', found 'void'"); | |
| 303 | \\fn a() i32 {} | |
| 304 | \\export fn entry() void { _ = a(); } | |
| 305 | , ".tmp_source.zig:1:12: error: expected type 'i32', found 'void'"); | |
| 260 | 306 | |
| 261 | 307 | cases.add("undefined function call", |
| 262 | \\export fn a() { | |
| 308 | \\export fn a() void { | |
| 263 | 309 | \\ b(); |
| 264 | 310 | \\} |
| 265 | 311 | , ".tmp_source.zig:2:5: error: use of undeclared identifier 'b'"); |
| 266 | 312 | |
| 267 | 313 | cases.add("wrong number of arguments", |
| 268 | \\export fn a() { | |
| 314 | \\export fn a() void { | |
| 269 | 315 | \\ b(1); |
| 270 | 316 | \\} |
| 271 | \\fn b(a: i32, b: i32, c: i32) { } | |
| 317 | \\fn b(a: i32, b: i32, c: i32) void { } | |
| 272 | 318 | , ".tmp_source.zig:2:6: error: expected 3 arguments, found 1"); |
| 273 | 319 | |
| 274 | 320 | cases.add("invalid type", |
| 275 | \\fn a() -> bogus {} | |
| 276 | \\export fn entry() { _ = a(); } | |
| 277 | , ".tmp_source.zig:1:11: error: use of undeclared identifier 'bogus'"); | |
| 321 | \\fn a() bogus {} | |
| 322 | \\export fn entry() void { _ = a(); } | |
| 323 | , ".tmp_source.zig:1:8: error: use of undeclared identifier 'bogus'"); | |
| 278 | 324 | |
| 279 | 325 | cases.add("pointer to unreachable", |
| 280 | \\fn a() -> &noreturn {} | |
| 281 | \\export fn entry() { _ = a(); } | |
| 282 | , ".tmp_source.zig:1:12: error: pointer to unreachable not allowed"); | |
| 326 | \\fn a() &noreturn {} | |
| 327 | \\export fn entry() void { _ = a(); } | |
| 328 | , ".tmp_source.zig:1:9: error: pointer to unreachable not allowed"); | |
| 283 | 329 | |
| 284 | 330 | cases.add("unreachable code", |
| 285 | \\export fn a() { | |
| 331 | \\export fn a() void { | |
| 286 | 332 | \\ return; |
| 287 | 333 | \\ b(); |
| 288 | 334 | \\} |
| 289 | 335 | \\ |
| 290 | \\fn b() {} | |
| 336 | \\fn b() void {} | |
| 291 | 337 | , ".tmp_source.zig:3:5: error: unreachable code"); |
| 292 | 338 | |
| 293 | 339 | cases.add("bad import", |
| 294 | 340 | \\const bogus = @import("bogus-does-not-exist.zig"); |
| 295 | \\export fn entry() { bogus.bogo(); } | |
| 341 | \\export fn entry() void { bogus.bogo(); } | |
| 296 | 342 | , ".tmp_source.zig:1:15: error: unable to find 'bogus-does-not-exist.zig'"); |
| 297 | 343 | |
| 298 | 344 | cases.add("undeclared identifier", |
| 299 | \\export fn a() { | |
| 345 | \\export fn a() void { | |
| 300 | 346 | \\ return |
| 301 | 347 | \\ b + |
| 302 | 348 | \\ c; |
| ... | ... | @@ -306,89 +352,89 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 306 | 352 | ".tmp_source.zig:4:5: error: use of undeclared identifier 'c'"); |
| 307 | 353 | |
| 308 | 354 | cases.add("parameter redeclaration", |
| 309 | \\fn f(a : i32, a : i32) { | |
| 355 | \\fn f(a : i32, a : i32) void { | |
| 310 | 356 | \\} |
| 311 | \\export fn entry() { f(1, 2); } | |
| 357 | \\export fn entry() void { f(1, 2); } | |
| 312 | 358 | , ".tmp_source.zig:1:15: error: redeclaration of variable 'a'"); |
| 313 | 359 | |
| 314 | 360 | cases.add("local variable redeclaration", |
| 315 | \\export fn f() { | |
| 361 | \\export fn f() void { | |
| 316 | 362 | \\ const a : i32 = 0; |
| 317 | 363 | \\ const a = 0; |
| 318 | 364 | \\} |
| 319 | 365 | , ".tmp_source.zig:3:5: error: redeclaration of variable 'a'"); |
| 320 | 366 | |
| 321 | 367 | cases.add("local variable redeclares parameter", |
| 322 | \\fn f(a : i32) { | |
| 368 | \\fn f(a : i32) void { | |
| 323 | 369 | \\ const a = 0; |
| 324 | 370 | \\} |
| 325 | \\export fn entry() { f(1); } | |
| 371 | \\export fn entry() void { f(1); } | |
| 326 | 372 | , ".tmp_source.zig:2:5: error: redeclaration of variable 'a'"); |
| 327 | 373 | |
| 328 | 374 | cases.add("variable has wrong type", |
| 329 | \\export fn f() -> i32 { | |
| 375 | \\export fn f() i32 { | |
| 330 | 376 | \\ const a = c"a"; |
| 331 | 377 | \\ return a; |
| 332 | 378 | \\} |
| 333 | 379 | , ".tmp_source.zig:3:12: error: expected type 'i32', found '&const u8'"); |
| 334 | 380 | |
| 335 | 381 | cases.add("if condition is bool, not int", |
| 336 | \\export fn f() { | |
| 382 | \\export fn f() void { | |
| 337 | 383 | \\ if (0) {} |
| 338 | 384 | \\} |
| 339 | 385 | , ".tmp_source.zig:2:9: error: integer value 0 cannot be implicitly casted to type 'bool'"); |
| 340 | 386 | |
| 341 | 387 | cases.add("assign unreachable", |
| 342 | \\export fn f() { | |
| 388 | \\export fn f() void { | |
| 343 | 389 | \\ const a = return; |
| 344 | 390 | \\} |
| 345 | 391 | , ".tmp_source.zig:2:5: error: unreachable code"); |
| 346 | 392 | |
| 347 | 393 | cases.add("unreachable variable", |
| 348 | \\export fn f() { | |
| 394 | \\export fn f() void { | |
| 349 | 395 | \\ const a: noreturn = {}; |
| 350 | 396 | \\} |
| 351 | 397 | , ".tmp_source.zig:2:14: error: variable of type 'noreturn' not allowed"); |
| 352 | 398 | |
| 353 | 399 | cases.add("unreachable parameter", |
| 354 | \\fn f(a: noreturn) {} | |
| 355 | \\export fn entry() { f(); } | |
| 400 | \\fn f(a: noreturn) void {} | |
| 401 | \\export fn entry() void { f(); } | |
| 356 | 402 | , ".tmp_source.zig:1:9: error: parameter of type 'noreturn' not allowed"); |
| 357 | 403 | |
| 358 | 404 | cases.add("bad assignment target", |
| 359 | \\export fn f() { | |
| 405 | \\export fn f() void { | |
| 360 | 406 | \\ 3 = 3; |
| 361 | 407 | \\} |
| 362 | 408 | , ".tmp_source.zig:2:7: error: cannot assign to constant"); |
| 363 | 409 | |
| 364 | 410 | cases.add("assign to constant variable", |
| 365 | \\export fn f() { | |
| 411 | \\export fn f() void { | |
| 366 | 412 | \\ const a = 3; |
| 367 | 413 | \\ a = 4; |
| 368 | 414 | \\} |
| 369 | 415 | , ".tmp_source.zig:3:7: error: cannot assign to constant"); |
| 370 | 416 | |
| 371 | 417 | cases.add("use of undeclared identifier", |
| 372 | \\export fn f() { | |
| 418 | \\export fn f() void { | |
| 373 | 419 | \\ b = 3; |
| 374 | 420 | \\} |
| 375 | 421 | , ".tmp_source.zig:2:5: error: use of undeclared identifier 'b'"); |
| 376 | 422 | |
| 377 | 423 | cases.add("const is a statement, not an expression", |
| 378 | \\export fn f() { | |
| 424 | \\export fn f() void { | |
| 379 | 425 | \\ (const a = 0); |
| 380 | 426 | \\} |
| 381 | 427 | , ".tmp_source.zig:2:6: error: invalid token: 'const'"); |
| 382 | 428 | |
| 383 | 429 | cases.add("array access of undeclared identifier", |
| 384 | \\export fn f() { | |
| 430 | \\export fn f() void { | |
| 385 | 431 | \\ i[i] = i[i]; |
| 386 | 432 | \\} |
| 387 | 433 | , ".tmp_source.zig:2:5: error: use of undeclared identifier 'i'", |
| 388 | 434 | ".tmp_source.zig:2:12: error: use of undeclared identifier 'i'"); |
| 389 | 435 | |
| 390 | 436 | cases.add("array access of non array", |
| 391 | \\export fn f() { | |
| 437 | \\export fn f() void { | |
| 392 | 438 | \\ var bad : bool = undefined; |
| 393 | 439 | \\ bad[bad] = bad[bad]; |
| 394 | 440 | \\} |
| ... | ... | @@ -396,7 +442,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 396 | 442 | ".tmp_source.zig:3:19: error: array access of non-array type 'bool'"); |
| 397 | 443 | |
| 398 | 444 | cases.add("array access with non integer index", |
| 399 | \\export fn f() { | |
| 445 | \\export fn f() void { | |
| 400 | 446 | \\ var array = "aoeu"; |
| 401 | 447 | \\ var bad = false; |
| 402 | 448 | \\ array[bad] = array[bad]; |
| ... | ... | @@ -406,37 +452,37 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 406 | 452 | |
| 407 | 453 | cases.add("write to const global variable", |
| 408 | 454 | \\const x : i32 = 99; |
| 409 | \\fn f() { | |
| 455 | \\fn f() void { | |
| 410 | 456 | \\ x = 1; |
| 411 | 457 | \\} |
| 412 | \\export fn entry() { f(); } | |
| 458 | \\export fn entry() void { f(); } | |
| 413 | 459 | , ".tmp_source.zig:3:7: error: cannot assign to constant"); |
| 414 | 460 | |
| 415 | 461 | |
| 416 | 462 | cases.add("missing else clause", |
| 417 | \\fn f(b: bool) { | |
| 463 | \\fn f(b: bool) void { | |
| 418 | 464 | \\ const x : i32 = if (b) h: { break :h 1; }; |
| 419 | 465 | \\ const y = if (b) h: { break :h i32(1); }; |
| 420 | 466 | \\} |
| 421 | \\export fn entry() { f(true); } | |
| 467 | \\export fn entry() void { f(true); } | |
| 422 | 468 | , ".tmp_source.zig:2:42: error: integer value 1 cannot be implicitly casted to type 'void'", |
| 423 | 469 | ".tmp_source.zig:3:15: error: incompatible types: 'i32' and 'void'"); |
| 424 | 470 | |
| 425 | 471 | cases.add("direct struct loop", |
| 426 | 472 | \\const A = struct { a : A, }; |
| 427 | \\export fn entry() -> usize { return @sizeOf(A); } | |
| 473 | \\export fn entry() usize { return @sizeOf(A); } | |
| 428 | 474 | , ".tmp_source.zig:1:11: error: struct 'A' contains itself"); |
| 429 | 475 | |
| 430 | 476 | cases.add("indirect struct loop", |
| 431 | 477 | \\const A = struct { b : B, }; |
| 432 | 478 | \\const B = struct { c : C, }; |
| 433 | 479 | \\const C = struct { a : A, }; |
| 434 | \\export fn entry() -> usize { return @sizeOf(A); } | |
| 480 | \\export fn entry() usize { return @sizeOf(A); } | |
| 435 | 481 | , ".tmp_source.zig:1:11: error: struct 'A' contains itself"); |
| 436 | 482 | |
| 437 | 483 | cases.add("invalid struct field", |
| 438 | 484 | \\const A = struct { x : i32, }; |
| 439 | \\export fn f() { | |
| 485 | \\export fn f() void { | |
| 440 | 486 | \\ var a : A = undefined; |
| 441 | 487 | \\ a.foo = 1; |
| 442 | 488 | \\ const y = a.bar; |
| ... | ... | @@ -468,7 +514,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 468 | 514 | \\ y : i32, |
| 469 | 515 | \\ z : i32, |
| 470 | 516 | \\}; |
| 471 | \\export fn f() { | |
| 517 | \\export fn f() void { | |
| 472 | 518 | \\ const a = A { |
| 473 | 519 | \\ .z = 1, |
| 474 | 520 | \\ .y = 2, |
| ... | ... | @@ -484,7 +530,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 484 | 530 | \\ y : i32, |
| 485 | 531 | \\ z : i32, |
| 486 | 532 | \\}; |
| 487 | \\export fn f() { | |
| 533 | \\export fn f() void { | |
| 488 | 534 | \\ // we want the error on the '{' not the 'A' because |
| 489 | 535 | \\ // the A could be a complicated expression |
| 490 | 536 | \\ const a = A { |
| ... | ... | @@ -500,7 +546,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 500 | 546 | \\ y : i32, |
| 501 | 547 | \\ z : i32, |
| 502 | 548 | \\}; |
| 503 | \\export fn f() { | |
| 549 | \\export fn f() void { | |
| 504 | 550 | \\ const a = A { |
| 505 | 551 | \\ .z = 4, |
| 506 | 552 | \\ .y = 2, |
| ... | ... | @@ -510,57 +556,57 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 510 | 556 | , ".tmp_source.zig:10:9: error: no member named 'foo' in struct 'A'"); |
| 511 | 557 | |
| 512 | 558 | cases.add("invalid break expression", |
| 513 | \\export fn f() { | |
| 559 | \\export fn f() void { | |
| 514 | 560 | \\ break; |
| 515 | 561 | \\} |
| 516 | 562 | , ".tmp_source.zig:2:5: error: break expression outside loop"); |
| 517 | 563 | |
| 518 | 564 | cases.add("invalid continue expression", |
| 519 | \\export fn f() { | |
| 565 | \\export fn f() void { | |
| 520 | 566 | \\ continue; |
| 521 | 567 | \\} |
| 522 | 568 | , ".tmp_source.zig:2:5: error: continue expression outside loop"); |
| 523 | 569 | |
| 524 | 570 | cases.add("invalid maybe type", |
| 525 | \\export fn f() { | |
| 571 | \\export fn f() void { | |
| 526 | 572 | \\ if (true) |x| { } |
| 527 | 573 | \\} |
| 528 | 574 | , ".tmp_source.zig:2:9: error: expected nullable type, found 'bool'"); |
| 529 | 575 | |
| 530 | 576 | cases.add("cast unreachable", |
| 531 | \\fn f() -> i32 { | |
| 577 | \\fn f() i32 { | |
| 532 | 578 | \\ return i32(return 1); |
| 533 | 579 | \\} |
| 534 | \\export fn entry() { _ = f(); } | |
| 580 | \\export fn entry() void { _ = f(); } | |
| 535 | 581 | , ".tmp_source.zig:2:15: error: unreachable code"); |
| 536 | 582 | |
| 537 | 583 | cases.add("invalid builtin fn", |
| 538 | \\fn f() -> @bogus(foo) { | |
| 584 | \\fn f() @bogus(foo) { | |
| 539 | 585 | \\} |
| 540 | \\export fn entry() { _ = f(); } | |
| 541 | , ".tmp_source.zig:1:11: error: invalid builtin function: 'bogus'"); | |
| 586 | \\export fn entry() void { _ = f(); } | |
| 587 | , ".tmp_source.zig:1:8: error: invalid builtin function: 'bogus'"); | |
| 542 | 588 | |
| 543 | 589 | cases.add("top level decl dependency loop", |
| 544 | 590 | \\const a : @typeOf(b) = 0; |
| 545 | 591 | \\const b : @typeOf(a) = 0; |
| 546 | \\export fn entry() { | |
| 592 | \\export fn entry() void { | |
| 547 | 593 | \\ const c = a + b; |
| 548 | 594 | \\} |
| 549 | 595 | , ".tmp_source.zig:1:1: error: 'a' depends on itself"); |
| 550 | 596 | |
| 551 | 597 | cases.add("noalias on non pointer param", |
| 552 | \\fn f(noalias x: i32) {} | |
| 553 | \\export fn entry() { f(1234); } | |
| 598 | \\fn f(noalias x: i32) void {} | |
| 599 | \\export fn entry() void { f(1234); } | |
| 554 | 600 | , ".tmp_source.zig:1:6: error: noalias on non-pointer parameter"); |
| 555 | 601 | |
| 556 | 602 | cases.add("struct init syntax for array", |
| 557 | 603 | \\const foo = []u16{.x = 1024,}; |
| 558 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 604 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 559 | 605 | , ".tmp_source.zig:1:18: error: type '[]u16' does not support struct initialization syntax"); |
| 560 | 606 | |
| 561 | 607 | cases.add("type variables must be constant", |
| 562 | 608 | \\var foo = u8; |
| 563 | \\export fn entry() -> foo { | |
| 609 | \\export fn entry() foo { | |
| 564 | 610 | \\ return 1; |
| 565 | 611 | \\} |
| 566 | 612 | , ".tmp_source.zig:1:1: error: variable of type 'type' must be constant"); |
| ... | ... | @@ -570,11 +616,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 570 | 616 | \\const Foo = struct {}; |
| 571 | 617 | \\const Bar = struct {}; |
| 572 | 618 | \\ |
| 573 | \\fn f(Foo: i32) { | |
| 619 | \\fn f(Foo: i32) void { | |
| 574 | 620 | \\ var Bar : i32 = undefined; |
| 575 | 621 | \\} |
| 576 | 622 | \\ |
| 577 | \\export fn entry() { | |
| 623 | \\export fn entry() void { | |
| 578 | 624 | \\ f(1234); |
| 579 | 625 | \\} |
| 580 | 626 | , |
| ... | ... | @@ -590,7 +636,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 590 | 636 | \\ Three, |
| 591 | 637 | \\ Four, |
| 592 | 638 | \\}; |
| 593 | \\fn f(n: Number) -> i32 { | |
| 639 | \\fn f(n: Number) i32 { | |
| 594 | 640 | \\ switch (n) { |
| 595 | 641 | \\ Number.One => 1, |
| 596 | 642 | \\ Number.Two => 2, |
| ... | ... | @@ -598,7 +644,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 598 | 644 | \\ } |
| 599 | 645 | \\} |
| 600 | 646 | \\ |
| 601 | \\export fn entry() -> usize { return @sizeOf(@typeOf(f)); } | |
| 647 | \\export fn entry() usize { return @sizeOf(@typeOf(f)); } | |
| 602 | 648 | , ".tmp_source.zig:8:5: error: enumeration value 'Number.Four' not handled in switch"); |
| 603 | 649 | |
| 604 | 650 | cases.add("switch expression - duplicate enumeration prong", |
| ... | ... | @@ -608,7 +654,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 608 | 654 | \\ Three, |
| 609 | 655 | \\ Four, |
| 610 | 656 | \\}; |
| 611 | \\fn f(n: Number) -> i32 { | |
| 657 | \\fn f(n: Number) i32 { | |
| 612 | 658 | \\ switch (n) { |
| 613 | 659 | \\ Number.One => 1, |
| 614 | 660 | \\ Number.Two => 2, |
| ... | ... | @@ -618,7 +664,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 618 | 664 | \\ } |
| 619 | 665 | \\} |
| 620 | 666 | \\ |
| 621 | \\export fn entry() -> usize { return @sizeOf(@typeOf(f)); } | |
| 667 | \\export fn entry() usize { return @sizeOf(@typeOf(f)); } | |
| 622 | 668 | , ".tmp_source.zig:13:15: error: duplicate switch value", |
| 623 | 669 | ".tmp_source.zig:10:15: note: other value is here"); |
| 624 | 670 | |
| ... | ... | @@ -629,7 +675,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 629 | 675 | \\ Three, |
| 630 | 676 | \\ Four, |
| 631 | 677 | \\}; |
| 632 | \\fn f(n: Number) -> i32 { | |
| 678 | \\fn f(n: Number) i32 { | |
| 633 | 679 | \\ switch (n) { |
| 634 | 680 | \\ Number.One => 1, |
| 635 | 681 | \\ Number.Two => 2, |
| ... | ... | @@ -640,35 +686,35 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 640 | 686 | \\ } |
| 641 | 687 | \\} |
| 642 | 688 | \\ |
| 643 | \\export fn entry() -> usize { return @sizeOf(@typeOf(f)); } | |
| 689 | \\export fn entry() usize { return @sizeOf(@typeOf(f)); } | |
| 644 | 690 | , ".tmp_source.zig:13:15: error: duplicate switch value", |
| 645 | 691 | ".tmp_source.zig:10:15: note: other value is here"); |
| 646 | 692 | |
| 647 | 693 | cases.add("switch expression - multiple else prongs", |
| 648 | \\fn f(x: u32) { | |
| 694 | \\fn f(x: u32) void { | |
| 649 | 695 | \\ const value: bool = switch (x) { |
| 650 | 696 | \\ 1234 => false, |
| 651 | 697 | \\ else => true, |
| 652 | 698 | \\ else => true, |
| 653 | 699 | \\ }; |
| 654 | 700 | \\} |
| 655 | \\export fn entry() { | |
| 701 | \\export fn entry() void { | |
| 656 | 702 | \\ f(1234); |
| 657 | 703 | \\} |
| 658 | 704 | , ".tmp_source.zig:5:9: error: multiple else prongs in switch expression"); |
| 659 | 705 | |
| 660 | 706 | cases.add("switch expression - non exhaustive integer prongs", |
| 661 | \\fn foo(x: u8) { | |
| 707 | \\fn foo(x: u8) void { | |
| 662 | 708 | \\ switch (x) { |
| 663 | 709 | \\ 0 => {}, |
| 664 | 710 | \\ } |
| 665 | 711 | \\} |
| 666 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 712 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 667 | 713 | , |
| 668 | 714 | ".tmp_source.zig:2:5: error: switch must handle all possibilities"); |
| 669 | 715 | |
| 670 | 716 | cases.add("switch expression - duplicate or overlapping integer value", |
| 671 | \\fn foo(x: u8) -> u8 { | |
| 717 | \\fn foo(x: u8) u8 { | |
| 672 | 718 | \\ return switch (x) { |
| 673 | 719 | \\ 0 ... 100 => u8(0), |
| 674 | 720 | \\ 101 ... 200 => 1, |
| ... | ... | @@ -676,26 +722,26 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 676 | 722 | \\ 206 ... 255 => 3, |
| 677 | 723 | \\ }; |
| 678 | 724 | \\} |
| 679 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 725 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 680 | 726 | , |
| 681 | 727 | ".tmp_source.zig:6:9: error: duplicate switch value", |
| 682 | 728 | ".tmp_source.zig:5:14: note: previous value is here"); |
| 683 | 729 | |
| 684 | 730 | cases.add("switch expression - switch on pointer type with no else", |
| 685 | \\fn foo(x: &u8) { | |
| 731 | \\fn foo(x: &u8) void { | |
| 686 | 732 | \\ switch (x) { |
| 687 | 733 | \\ &y => {}, |
| 688 | 734 | \\ } |
| 689 | 735 | \\} |
| 690 | 736 | \\const y: u8 = 100; |
| 691 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 737 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 692 | 738 | , |
| 693 | 739 | ".tmp_source.zig:2:5: error: else prong required when switching on type '&u8'"); |
| 694 | 740 | |
| 695 | 741 | cases.add("global variable initializer must be constant expression", |
| 696 | \\extern fn foo() -> i32; | |
| 742 | \\extern fn foo() i32; | |
| 697 | 743 | \\const x = foo(); |
| 698 | \\export fn entry() -> i32 { return x; } | |
| 744 | \\export fn entry() i32 { return x; } | |
| 699 | 745 | , ".tmp_source.zig:2:11: error: unable to evaluate constant expression"); |
| 700 | 746 | |
| 701 | 747 | cases.add("array concatenation with wrong type", |
| ... | ... | @@ -703,38 +749,38 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 703 | 749 | \\const derp = usize(1234); |
| 704 | 750 | \\const a = derp ++ "foo"; |
| 705 | 751 | \\ |
| 706 | \\export fn entry() -> usize { return @sizeOf(@typeOf(a)); } | |
| 752 | \\export fn entry() usize { return @sizeOf(@typeOf(a)); } | |
| 707 | 753 | , ".tmp_source.zig:3:11: error: expected array or C string literal, found 'usize'"); |
| 708 | 754 | |
| 709 | 755 | cases.add("non compile time array concatenation", |
| 710 | \\fn f() -> []u8 { | |
| 756 | \\fn f() []u8 { | |
| 711 | 757 | \\ return s ++ "foo"; |
| 712 | 758 | \\} |
| 713 | 759 | \\var s: [10]u8 = undefined; |
| 714 | \\export fn entry() -> usize { return @sizeOf(@typeOf(f)); } | |
| 760 | \\export fn entry() usize { return @sizeOf(@typeOf(f)); } | |
| 715 | 761 | , ".tmp_source.zig:2:12: error: unable to evaluate constant expression"); |
| 716 | 762 | |
| 717 | 763 | cases.add("@cImport with bogus include", |
| 718 | 764 | \\const c = @cImport(@cInclude("bogus.h")); |
| 719 | \\export fn entry() -> usize { return @sizeOf(@typeOf(c.bogo)); } | |
| 765 | \\export fn entry() usize { return @sizeOf(@typeOf(c.bogo)); } | |
| 720 | 766 | , ".tmp_source.zig:1:11: error: C import failed", |
| 721 | 767 | ".h:1:10: note: 'bogus.h' file not found"); |
| 722 | 768 | |
| 723 | 769 | cases.add("address of number literal", |
| 724 | 770 | \\const x = 3; |
| 725 | 771 | \\const y = &x; |
| 726 | \\fn foo() -> &const i32 { return y; } | |
| 727 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 728 | , ".tmp_source.zig:3:33: error: expected type '&const i32', found '&const (integer literal)'"); | |
| 772 | \\fn foo() &const i32 { return y; } | |
| 773 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 774 | , ".tmp_source.zig:3:30: error: expected type '&const i32', found '&const (integer literal)'"); | |
| 729 | 775 | |
| 730 | 776 | cases.add("integer overflow error", |
| 731 | 777 | \\const x : u8 = 300; |
| 732 | \\export fn entry() -> usize { return @sizeOf(@typeOf(x)); } | |
| 778 | \\export fn entry() usize { return @sizeOf(@typeOf(x)); } | |
| 733 | 779 | , ".tmp_source.zig:1:16: error: integer value 300 cannot be implicitly casted to type 'u8'"); |
| 734 | 780 | |
| 735 | 781 | cases.add("incompatible number literals", |
| 736 | 782 | \\const x = 2 == 2.0; |
| 737 | \\export fn entry() -> usize { return @sizeOf(@typeOf(x)); } | |
| 783 | \\export fn entry() usize { return @sizeOf(@typeOf(x)); } | |
| 738 | 784 | , ".tmp_source.zig:1:11: error: integer value 2 cannot be implicitly casted to type '(float literal)'"); |
| 739 | 785 | |
| 740 | 786 | cases.add("missing function call param", |
| ... | ... | @@ -742,10 +788,10 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 742 | 788 | \\ a: i32, |
| 743 | 789 | \\ b: i32, |
| 744 | 790 | \\ |
| 745 | \\ fn member_a(foo: &const Foo) -> i32 { | |
| 791 | \\ fn member_a(foo: &const Foo) i32 { | |
| 746 | 792 | \\ return foo.a; |
| 747 | 793 | \\ } |
| 748 | \\ fn member_b(foo: &const Foo) -> i32 { | |
| 794 | \\ fn member_b(foo: &const Foo) i32 { | |
| 749 | 795 | \\ return foo.b; |
| 750 | 796 | \\ } |
| 751 | 797 | \\}; |
| ... | ... | @@ -756,59 +802,59 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 756 | 802 | \\ Foo.member_b, |
| 757 | 803 | \\}; |
| 758 | 804 | \\ |
| 759 | \\fn f(foo: &const Foo, index: usize) { | |
| 805 | \\fn f(foo: &const Foo, index: usize) void { | |
| 760 | 806 | \\ const result = members[index](); |
| 761 | 807 | \\} |
| 762 | 808 | \\ |
| 763 | \\export fn entry() -> usize { return @sizeOf(@typeOf(f)); } | |
| 809 | \\export fn entry() usize { return @sizeOf(@typeOf(f)); } | |
| 764 | 810 | , ".tmp_source.zig:20:34: error: expected 1 arguments, found 0"); |
| 765 | 811 | |
| 766 | 812 | cases.add("missing function name and param name", |
| 767 | \\fn () {} | |
| 768 | \\fn f(i32) {} | |
| 769 | \\export fn entry() -> usize { return @sizeOf(@typeOf(f)); } | |
| 813 | \\fn () void {} | |
| 814 | \\fn f(i32) void {} | |
| 815 | \\export fn entry() usize { return @sizeOf(@typeOf(f)); } | |
| 770 | 816 | , |
| 771 | 817 | ".tmp_source.zig:1:1: error: missing function name", |
| 772 | 818 | ".tmp_source.zig:2:6: error: missing parameter name"); |
| 773 | 819 | |
| 774 | 820 | cases.add("wrong function type", |
| 775 | \\const fns = []fn(){ a, b, c }; | |
| 776 | \\fn a() -> i32 {return 0;} | |
| 777 | \\fn b() -> i32 {return 1;} | |
| 778 | \\fn c() -> i32 {return 2;} | |
| 779 | \\export fn entry() -> usize { return @sizeOf(@typeOf(fns)); } | |
| 780 | , ".tmp_source.zig:1:21: error: expected type 'fn()', found 'fn() -> i32'"); | |
| 821 | \\const fns = []fn() void { a, b, c }; | |
| 822 | \\fn a() i32 {return 0;} | |
| 823 | \\fn b() i32 {return 1;} | |
| 824 | \\fn c() i32 {return 2;} | |
| 825 | \\export fn entry() usize { return @sizeOf(@typeOf(fns)); } | |
| 826 | , ".tmp_source.zig:1:27: error: expected type 'fn() void', found 'fn() i32'"); | |
| 781 | 827 | |
| 782 | 828 | cases.add("extern function pointer mismatch", |
| 783 | \\const fns = [](fn(i32)->i32){ a, b, c }; | |
| 784 | \\pub fn a(x: i32) -> i32 {return x + 0;} | |
| 785 | \\pub fn b(x: i32) -> i32 {return x + 1;} | |
| 786 | \\export fn c(x: i32) -> i32 {return x + 2;} | |
| 829 | \\const fns = [](fn(i32)i32) { a, b, c }; | |
| 830 | \\pub fn a(x: i32) i32 {return x + 0;} | |
| 831 | \\pub fn b(x: i32) i32 {return x + 1;} | |
| 832 | \\export fn c(x: i32) i32 {return x + 2;} | |
| 787 | 833 | \\ |
| 788 | \\export fn entry() -> usize { return @sizeOf(@typeOf(fns)); } | |
| 789 | , ".tmp_source.zig:1:37: error: expected type 'fn(i32) -> i32', found 'extern fn(i32) -> i32'"); | |
| 834 | \\export fn entry() usize { return @sizeOf(@typeOf(fns)); } | |
| 835 | , ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'"); | |
| 790 | 836 | |
| 791 | 837 | |
| 792 | 838 | cases.add("implicit cast from f64 to f32", |
| 793 | 839 | \\const x : f64 = 1.0; |
| 794 | 840 | \\const y : f32 = x; |
| 795 | 841 | \\ |
| 796 | \\export fn entry() -> usize { return @sizeOf(@typeOf(y)); } | |
| 842 | \\export fn entry() usize { return @sizeOf(@typeOf(y)); } | |
| 797 | 843 | , ".tmp_source.zig:2:17: error: expected type 'f32', found 'f64'"); |
| 798 | 844 | |
| 799 | 845 | |
| 800 | 846 | cases.add("colliding invalid top level functions", |
| 801 | \\fn func() -> bogus {} | |
| 802 | \\fn func() -> bogus {} | |
| 803 | \\export fn entry() -> usize { return @sizeOf(@typeOf(func)); } | |
| 847 | \\fn func() bogus {} | |
| 848 | \\fn func() bogus {} | |
| 849 | \\export fn entry() usize { return @sizeOf(@typeOf(func)); } | |
| 804 | 850 | , |
| 805 | 851 | ".tmp_source.zig:2:1: error: redefinition of 'func'", |
| 806 | ".tmp_source.zig:1:14: error: use of undeclared identifier 'bogus'"); | |
| 852 | ".tmp_source.zig:1:11: error: use of undeclared identifier 'bogus'"); | |
| 807 | 853 | |
| 808 | 854 | |
| 809 | 855 | cases.add("bogus compile var", |
| 810 | 856 | \\const x = @import("builtin").bogus; |
| 811 | \\export fn entry() -> usize { return @sizeOf(@typeOf(x)); } | |
| 857 | \\export fn entry() usize { return @sizeOf(@typeOf(x)); } | |
| 812 | 858 | , ".tmp_source.zig:1:29: error: no member named 'bogus' in '"); |
| 813 | 859 | |
| 814 | 860 | |
| ... | ... | @@ -817,11 +863,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 817 | 863 | \\ y: [get()]u8, |
| 818 | 864 | \\}; |
| 819 | 865 | \\var global_var: usize = 1; |
| 820 | \\fn get() -> usize { return global_var; } | |
| 866 | \\fn get() usize { return global_var; } | |
| 821 | 867 | \\ |
| 822 | \\export fn entry() -> usize { return @sizeOf(@typeOf(Foo)); } | |
| 868 | \\export fn entry() usize { return @sizeOf(@typeOf(Foo)); } | |
| 823 | 869 | , |
| 824 | ".tmp_source.zig:5:28: error: unable to evaluate constant expression", | |
| 870 | ".tmp_source.zig:5:25: error: unable to evaluate constant expression", | |
| 825 | 871 | ".tmp_source.zig:2:12: note: called from here", |
| 826 | 872 | ".tmp_source.zig:2:8: note: called from here"); |
| 827 | 873 | |
| ... | ... | @@ -832,7 +878,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 832 | 878 | \\}; |
| 833 | 879 | \\const x = Foo {.field = 1} + Foo {.field = 2}; |
| 834 | 880 | \\ |
| 835 | \\export fn entry() -> usize { return @sizeOf(@typeOf(x)); } | |
| 881 | \\export fn entry() usize { return @sizeOf(@typeOf(x)); } | |
| 836 | 882 | , ".tmp_source.zig:4:28: error: invalid operands to binary expression: 'Foo' and 'Foo'"); |
| 837 | 883 | |
| 838 | 884 | |
| ... | ... | @@ -842,78 +888,78 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 842 | 888 | \\const int_x = u32(1) / u32(0); |
| 843 | 889 | \\const float_x = f32(1.0) / f32(0.0); |
| 844 | 890 | \\ |
| 845 | \\export fn entry1() -> usize { return @sizeOf(@typeOf(lit_int_x)); } | |
| 846 | \\export fn entry2() -> usize { return @sizeOf(@typeOf(lit_float_x)); } | |
| 847 | \\export fn entry3() -> usize { return @sizeOf(@typeOf(int_x)); } | |
| 848 | \\export fn entry4() -> usize { return @sizeOf(@typeOf(float_x)); } | |
| 891 | \\export fn entry1() usize { return @sizeOf(@typeOf(lit_int_x)); } | |
| 892 | \\export fn entry2() usize { return @sizeOf(@typeOf(lit_float_x)); } | |
| 893 | \\export fn entry3() usize { return @sizeOf(@typeOf(int_x)); } | |
| 894 | \\export fn entry4() usize { return @sizeOf(@typeOf(float_x)); } | |
| 849 | 895 | , |
| 850 | ".tmp_source.zig:1:21: error: division by zero is undefined", | |
| 851 | ".tmp_source.zig:2:25: error: division by zero is undefined", | |
| 852 | ".tmp_source.zig:3:22: error: division by zero is undefined", | |
| 853 | ".tmp_source.zig:4:26: error: division by zero is undefined"); | |
| 896 | ".tmp_source.zig:1:21: error: division by zero", | |
| 897 | ".tmp_source.zig:2:25: error: division by zero", | |
| 898 | ".tmp_source.zig:3:22: error: division by zero", | |
| 899 | ".tmp_source.zig:4:26: error: division by zero"); | |
| 854 | 900 | |
| 855 | 901 | |
| 856 | 902 | cases.add("normal string with newline", |
| 857 | 903 | \\const foo = "a |
| 858 | 904 | \\b"; |
| 859 | 905 | \\ |
| 860 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 906 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 861 | 907 | , ".tmp_source.zig:1:13: error: newline not allowed in string literal"); |
| 862 | 908 | |
| 863 | 909 | cases.add("invalid comparison for function pointers", |
| 864 | \\fn foo() {} | |
| 910 | \\fn foo() void {} | |
| 865 | 911 | \\const invalid = foo > foo; |
| 866 | 912 | \\ |
| 867 | \\export fn entry() -> usize { return @sizeOf(@typeOf(invalid)); } | |
| 868 | , ".tmp_source.zig:2:21: error: operator not allowed for type 'fn()'"); | |
| 913 | \\export fn entry() usize { return @sizeOf(@typeOf(invalid)); } | |
| 914 | , ".tmp_source.zig:2:21: error: operator not allowed for type 'fn() void'"); | |
| 869 | 915 | |
| 870 | 916 | cases.add("generic function instance with non-constant expression", |
| 871 | \\fn foo(comptime x: i32, y: i32) -> i32 { return x + y; } | |
| 872 | \\fn test1(a: i32, b: i32) -> i32 { | |
| 917 | \\fn foo(comptime x: i32, y: i32) i32 { return x + y; } | |
| 918 | \\fn test1(a: i32, b: i32) i32 { | |
| 873 | 919 | \\ return foo(a, b); |
| 874 | 920 | \\} |
| 875 | 921 | \\ |
| 876 | \\export fn entry() -> usize { return @sizeOf(@typeOf(test1)); } | |
| 922 | \\export fn entry() usize { return @sizeOf(@typeOf(test1)); } | |
| 877 | 923 | , ".tmp_source.zig:3:16: error: unable to evaluate constant expression"); |
| 878 | 924 | |
| 879 | 925 | cases.add("assign null to non-nullable pointer", |
| 880 | 926 | \\const a: &u8 = null; |
| 881 | 927 | \\ |
| 882 | \\export fn entry() -> usize { return @sizeOf(@typeOf(a)); } | |
| 928 | \\export fn entry() usize { return @sizeOf(@typeOf(a)); } | |
| 883 | 929 | , ".tmp_source.zig:1:16: error: expected type '&u8', found '(null)'"); |
| 884 | 930 | |
| 885 | 931 | cases.add("indexing an array of size zero", |
| 886 | 932 | \\const array = []u8{}; |
| 887 | \\export fn foo() { | |
| 933 | \\export fn foo() void { | |
| 888 | 934 | \\ const pointer = &array[0]; |
| 889 | 935 | \\} |
| 890 | 936 | , ".tmp_source.zig:3:27: error: index 0 outside array of size 0"); |
| 891 | 937 | |
| 892 | 938 | cases.add("compile time division by zero", |
| 893 | 939 | \\const y = foo(0); |
| 894 | \\fn foo(x: u32) -> u32 { | |
| 940 | \\fn foo(x: u32) u32 { | |
| 895 | 941 | \\ return 1 / x; |
| 896 | 942 | \\} |
| 897 | 943 | \\ |
| 898 | \\export fn entry() -> usize { return @sizeOf(@typeOf(y)); } | |
| 944 | \\export fn entry() usize { return @sizeOf(@typeOf(y)); } | |
| 899 | 945 | , |
| 900 | ".tmp_source.zig:3:14: error: division by zero is undefined", | |
| 946 | ".tmp_source.zig:3:14: error: division by zero", | |
| 901 | 947 | ".tmp_source.zig:1:14: note: called from here"); |
| 902 | 948 | |
| 903 | 949 | cases.add("branch on undefined value", |
| 904 | 950 | \\const x = if (undefined) true else false; |
| 905 | 951 | \\ |
| 906 | \\export fn entry() -> usize { return @sizeOf(@typeOf(x)); } | |
| 952 | \\export fn entry() usize { return @sizeOf(@typeOf(x)); } | |
| 907 | 953 | , ".tmp_source.zig:1:15: error: use of undefined value"); |
| 908 | 954 | |
| 909 | 955 | |
| 910 | 956 | cases.add("endless loop in function evaluation", |
| 911 | 957 | \\const seventh_fib_number = fibbonaci(7); |
| 912 | \\fn fibbonaci(x: i32) -> i32 { | |
| 958 | \\fn fibbonaci(x: i32) i32 { | |
| 913 | 959 | \\ return fibbonaci(x - 1) + fibbonaci(x - 2); |
| 914 | 960 | \\} |
| 915 | 961 | \\ |
| 916 | \\export fn entry() -> usize { return @sizeOf(@typeOf(seventh_fib_number)); } | |
| 962 | \\export fn entry() usize { return @sizeOf(@typeOf(seventh_fib_number)); } | |
| 917 | 963 | , |
| 918 | 964 | ".tmp_source.zig:3:21: error: evaluation exceeded 1000 backwards branches", |
| 919 | 965 | ".tmp_source.zig:3:21: note: called from here"); |
| ... | ... | @@ -921,7 +967,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 921 | 967 | cases.add("@embedFile with bogus file", |
| 922 | 968 | \\const resource = @embedFile("bogus.txt"); |
| 923 | 969 | \\ |
| 924 | \\export fn entry() -> usize { return @sizeOf(@typeOf(resource)); } | |
| 970 | \\export fn entry() usize { return @sizeOf(@typeOf(resource)); } | |
| 925 | 971 | , ".tmp_source.zig:1:29: error: unable to find '", "bogus.txt'"); |
| 926 | 972 | |
| 927 | 973 | cases.add("non-const expression in struct literal outside function", |
| ... | ... | @@ -929,9 +975,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 929 | 975 | \\ x: i32, |
| 930 | 976 | \\}; |
| 931 | 977 | \\const a = Foo {.x = get_it()}; |
| 932 | \\extern fn get_it() -> i32; | |
| 978 | \\extern fn get_it() i32; | |
| 933 | 979 | \\ |
| 934 | \\export fn entry() -> usize { return @sizeOf(@typeOf(a)); } | |
| 980 | \\export fn entry() usize { return @sizeOf(@typeOf(a)); } | |
| 935 | 981 | , ".tmp_source.zig:4:21: error: unable to evaluate constant expression"); |
| 936 | 982 | |
| 937 | 983 | cases.add("non-const expression function call with struct return value outside function", |
| ... | ... | @@ -939,60 +985,60 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 939 | 985 | \\ x: i32, |
| 940 | 986 | \\}; |
| 941 | 987 | \\const a = get_it(); |
| 942 | \\fn get_it() -> Foo { | |
| 988 | \\fn get_it() Foo { | |
| 943 | 989 | \\ global_side_effect = true; |
| 944 | 990 | \\ return Foo {.x = 13}; |
| 945 | 991 | \\} |
| 946 | 992 | \\var global_side_effect = false; |
| 947 | 993 | \\ |
| 948 | \\export fn entry() -> usize { return @sizeOf(@typeOf(a)); } | |
| 994 | \\export fn entry() usize { return @sizeOf(@typeOf(a)); } | |
| 949 | 995 | , |
| 950 | 996 | ".tmp_source.zig:6:24: error: unable to evaluate constant expression", |
| 951 | 997 | ".tmp_source.zig:4:17: note: called from here"); |
| 952 | 998 | |
| 953 | 999 | cases.add("undeclared identifier error should mark fn as impure", |
| 954 | \\export fn foo() { | |
| 1000 | \\export fn foo() void { | |
| 955 | 1001 | \\ test_a_thing(); |
| 956 | 1002 | \\} |
| 957 | \\fn test_a_thing() { | |
| 1003 | \\fn test_a_thing() void { | |
| 958 | 1004 | \\ bad_fn_call(); |
| 959 | 1005 | \\} |
| 960 | 1006 | , ".tmp_source.zig:5:5: error: use of undeclared identifier 'bad_fn_call'"); |
| 961 | 1007 | |
| 962 | 1008 | cases.add("illegal comparison of types", |
| 963 | \\fn bad_eql_1(a: []u8, b: []u8) -> bool { | |
| 1009 | \\fn bad_eql_1(a: []u8, b: []u8) bool { | |
| 964 | 1010 | \\ return a == b; |
| 965 | 1011 | \\} |
| 966 | 1012 | \\const EnumWithData = union(enum) { |
| 967 | 1013 | \\ One: void, |
| 968 | 1014 | \\ Two: i32, |
| 969 | 1015 | \\}; |
| 970 | \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) -> bool { | |
| 1016 | \\fn bad_eql_2(a: &const EnumWithData, b: &const EnumWithData) bool { | |
| 971 | 1017 | \\ return *a == *b; |
| 972 | 1018 | \\} |
| 973 | 1019 | \\ |
| 974 | \\export fn entry1() -> usize { return @sizeOf(@typeOf(bad_eql_1)); } | |
| 975 | \\export fn entry2() -> usize { return @sizeOf(@typeOf(bad_eql_2)); } | |
| 1020 | \\export fn entry1() usize { return @sizeOf(@typeOf(bad_eql_1)); } | |
| 1021 | \\export fn entry2() usize { return @sizeOf(@typeOf(bad_eql_2)); } | |
| 976 | 1022 | , |
| 977 | 1023 | ".tmp_source.zig:2:14: error: operator not allowed for type '[]u8'", |
| 978 | 1024 | ".tmp_source.zig:9:15: error: operator not allowed for type 'EnumWithData'"); |
| 979 | 1025 | |
| 980 | 1026 | cases.add("non-const switch number literal", |
| 981 | \\export fn foo() { | |
| 1027 | \\export fn foo() void { | |
| 982 | 1028 | \\ const x = switch (bar()) { |
| 983 | 1029 | \\ 1, 2 => 1, |
| 984 | 1030 | \\ 3, 4 => 2, |
| 985 | 1031 | \\ else => 3, |
| 986 | 1032 | \\ }; |
| 987 | 1033 | \\} |
| 988 | \\fn bar() -> i32 { | |
| 1034 | \\fn bar() i32 { | |
| 989 | 1035 | \\ return 2; |
| 990 | 1036 | \\} |
| 991 | 1037 | , ".tmp_source.zig:2:15: error: unable to infer expression type"); |
| 992 | 1038 | |
| 993 | 1039 | cases.add("atomic orderings of cmpxchg - failure stricter than success", |
| 994 | 1040 | \\const AtomicOrder = @import("builtin").AtomicOrder; |
| 995 | \\export fn f() { | |
| 1041 | \\export fn f() void { | |
| 996 | 1042 | \\ var x: i32 = 1234; |
| 997 | 1043 | \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {} |
| 998 | 1044 | \\} |
| ... | ... | @@ -1000,7 +1046,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1000 | 1046 | |
| 1001 | 1047 | cases.add("atomic orderings of cmpxchg - success Monotonic or stricter", |
| 1002 | 1048 | \\const AtomicOrder = @import("builtin").AtomicOrder; |
| 1003 | \\export fn f() { | |
| 1049 | \\export fn f() void { | |
| 1004 | 1050 | \\ var x: i32 = 1234; |
| 1005 | 1051 | \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {} |
| 1006 | 1052 | \\} |
| ... | ... | @@ -1008,22 +1054,22 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1008 | 1054 | |
| 1009 | 1055 | cases.add("negation overflow in function evaluation", |
| 1010 | 1056 | \\const y = neg(-128); |
| 1011 | \\fn neg(x: i8) -> i8 { | |
| 1057 | \\fn neg(x: i8) i8 { | |
| 1012 | 1058 | \\ return -x; |
| 1013 | 1059 | \\} |
| 1014 | 1060 | \\ |
| 1015 | \\export fn entry() -> usize { return @sizeOf(@typeOf(y)); } | |
| 1061 | \\export fn entry() usize { return @sizeOf(@typeOf(y)); } | |
| 1016 | 1062 | , |
| 1017 | 1063 | ".tmp_source.zig:3:12: error: negation caused overflow", |
| 1018 | 1064 | ".tmp_source.zig:1:14: note: called from here"); |
| 1019 | 1065 | |
| 1020 | 1066 | cases.add("add overflow in function evaluation", |
| 1021 | 1067 | \\const y = add(65530, 10); |
| 1022 | \\fn add(a: u16, b: u16) -> u16 { | |
| 1068 | \\fn add(a: u16, b: u16) u16 { | |
| 1023 | 1069 | \\ return a + b; |
| 1024 | 1070 | \\} |
| 1025 | 1071 | \\ |
| 1026 | \\export fn entry() -> usize { return @sizeOf(@typeOf(y)); } | |
| 1072 | \\export fn entry() usize { return @sizeOf(@typeOf(y)); } | |
| 1027 | 1073 | , |
| 1028 | 1074 | ".tmp_source.zig:3:14: error: operation caused overflow", |
| 1029 | 1075 | ".tmp_source.zig:1:14: note: called from here"); |
| ... | ... | @@ -1031,47 +1077,47 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1031 | 1077 | |
| 1032 | 1078 | cases.add("sub overflow in function evaluation", |
| 1033 | 1079 | \\const y = sub(10, 20); |
| 1034 | \\fn sub(a: u16, b: u16) -> u16 { | |
| 1080 | \\fn sub(a: u16, b: u16) u16 { | |
| 1035 | 1081 | \\ return a - b; |
| 1036 | 1082 | \\} |
| 1037 | 1083 | \\ |
| 1038 | \\export fn entry() -> usize { return @sizeOf(@typeOf(y)); } | |
| 1084 | \\export fn entry() usize { return @sizeOf(@typeOf(y)); } | |
| 1039 | 1085 | , |
| 1040 | 1086 | ".tmp_source.zig:3:14: error: operation caused overflow", |
| 1041 | 1087 | ".tmp_source.zig:1:14: note: called from here"); |
| 1042 | 1088 | |
| 1043 | 1089 | cases.add("mul overflow in function evaluation", |
| 1044 | 1090 | \\const y = mul(300, 6000); |
| 1045 | \\fn mul(a: u16, b: u16) -> u16 { | |
| 1091 | \\fn mul(a: u16, b: u16) u16 { | |
| 1046 | 1092 | \\ return a * b; |
| 1047 | 1093 | \\} |
| 1048 | 1094 | \\ |
| 1049 | \\export fn entry() -> usize { return @sizeOf(@typeOf(y)); } | |
| 1095 | \\export fn entry() usize { return @sizeOf(@typeOf(y)); } | |
| 1050 | 1096 | , |
| 1051 | 1097 | ".tmp_source.zig:3:14: error: operation caused overflow", |
| 1052 | 1098 | ".tmp_source.zig:1:14: note: called from here"); |
| 1053 | 1099 | |
| 1054 | 1100 | cases.add("truncate sign mismatch", |
| 1055 | \\fn f() -> i8 { | |
| 1101 | \\fn f() i8 { | |
| 1056 | 1102 | \\ const x: u32 = 10; |
| 1057 | 1103 | \\ return @truncate(i8, x); |
| 1058 | 1104 | \\} |
| 1059 | 1105 | \\ |
| 1060 | \\export fn entry() -> usize { return @sizeOf(@typeOf(f)); } | |
| 1106 | \\export fn entry() usize { return @sizeOf(@typeOf(f)); } | |
| 1061 | 1107 | , ".tmp_source.zig:3:26: error: expected signed integer type, found 'u32'"); |
| 1062 | 1108 | |
| 1063 | 1109 | cases.add("try in function with non error return type", |
| 1064 | \\export fn f() { | |
| 1110 | \\export fn f() void { | |
| 1065 | 1111 | \\ try something(); |
| 1066 | 1112 | \\} |
| 1067 | \\fn something() -> %void { } | |
| 1113 | \\fn something() %void { } | |
| 1068 | 1114 | , |
| 1069 | 1115 | ".tmp_source.zig:2:5: error: expected type 'void', found 'error'"); |
| 1070 | 1116 | |
| 1071 | 1117 | cases.add("invalid pointer for var type", |
| 1072 | \\extern fn ext() -> usize; | |
| 1118 | \\extern fn ext() usize; | |
| 1073 | 1119 | \\var bytes: [ext()]u8 = undefined; |
| 1074 | \\export fn f() { | |
| 1120 | \\export fn f() void { | |
| 1075 | 1121 | \\ for (bytes) |*b, i| { |
| 1076 | 1122 | \\ *b = u8(i); |
| 1077 | 1123 | \\ } |
| ... | ... | @@ -1079,21 +1125,21 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1079 | 1125 | , ".tmp_source.zig:2:13: error: unable to evaluate constant expression"); |
| 1080 | 1126 | |
| 1081 | 1127 | cases.add("export function with comptime parameter", |
| 1082 | \\export fn foo(comptime x: i32, y: i32) -> i32{ | |
| 1128 | \\export fn foo(comptime x: i32, y: i32) i32{ | |
| 1083 | 1129 | \\ return x + y; |
| 1084 | 1130 | \\} |
| 1085 | 1131 | , ".tmp_source.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'"); |
| 1086 | 1132 | |
| 1087 | 1133 | cases.add("extern function with comptime parameter", |
| 1088 | \\extern fn foo(comptime x: i32, y: i32) -> i32; | |
| 1089 | \\fn f() -> i32 { | |
| 1134 | \\extern fn foo(comptime x: i32, y: i32) i32; | |
| 1135 | \\fn f() i32 { | |
| 1090 | 1136 | \\ return foo(1, 2); |
| 1091 | 1137 | \\} |
| 1092 | \\export fn entry() -> usize { return @sizeOf(@typeOf(f)); } | |
| 1138 | \\export fn entry() usize { return @sizeOf(@typeOf(f)); } | |
| 1093 | 1139 | , ".tmp_source.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'"); |
| 1094 | 1140 | |
| 1095 | 1141 | cases.add("convert fixed size array to slice with invalid size", |
| 1096 | \\export fn f() { | |
| 1142 | \\export fn f() void { | |
| 1097 | 1143 | \\ var array: [5]u8 = undefined; |
| 1098 | 1144 | \\ var foo = ([]const u32)(array)[0]; |
| 1099 | 1145 | \\} |
| ... | ... | @@ -1101,12 +1147,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1101 | 1147 | |
| 1102 | 1148 | cases.add("non-pure function returns type", |
| 1103 | 1149 | \\var a: u32 = 0; |
| 1104 | \\pub fn List(comptime T: type) -> type { | |
| 1150 | \\pub fn List(comptime T: type) type { | |
| 1105 | 1151 | \\ a += 1; |
| 1106 | 1152 | \\ return SmallList(T, 8); |
| 1107 | 1153 | \\} |
| 1108 | 1154 | \\ |
| 1109 | \\pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type { | |
| 1155 | \\pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type { | |
| 1110 | 1156 | \\ return struct { |
| 1111 | 1157 | \\ items: []T, |
| 1112 | 1158 | \\ length: usize, |
| ... | ... | @@ -1114,7 +1160,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1114 | 1160 | \\ }; |
| 1115 | 1161 | \\} |
| 1116 | 1162 | \\ |
| 1117 | \\export fn function_with_return_type_type() { | |
| 1163 | \\export fn function_with_return_type_type() void { | |
| 1118 | 1164 | \\ var list: List(i32) = undefined; |
| 1119 | 1165 | \\ list.length = 10; |
| 1120 | 1166 | \\} |
| ... | ... | @@ -1123,46 +1169,46 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1123 | 1169 | |
| 1124 | 1170 | cases.add("bogus method call on slice", |
| 1125 | 1171 | \\var self = "aoeu"; |
| 1126 | \\fn f(m: []const u8) { | |
| 1172 | \\fn f(m: []const u8) void { | |
| 1127 | 1173 | \\ m.copy(u8, self[0..], m); |
| 1128 | 1174 | \\} |
| 1129 | \\export fn entry() -> usize { return @sizeOf(@typeOf(f)); } | |
| 1175 | \\export fn entry() usize { return @sizeOf(@typeOf(f)); } | |
| 1130 | 1176 | , ".tmp_source.zig:3:6: error: no member named 'copy' in '[]const u8'"); |
| 1131 | 1177 | |
| 1132 | 1178 | cases.add("wrong number of arguments for method fn call", |
| 1133 | 1179 | \\const Foo = struct { |
| 1134 | \\ fn method(self: &const Foo, a: i32) {} | |
| 1180 | \\ fn method(self: &const Foo, a: i32) void {} | |
| 1135 | 1181 | \\}; |
| 1136 | \\fn f(foo: &const Foo) { | |
| 1182 | \\fn f(foo: &const Foo) void { | |
| 1137 | 1183 | \\ |
| 1138 | 1184 | \\ foo.method(1, 2); |
| 1139 | 1185 | \\} |
| 1140 | \\export fn entry() -> usize { return @sizeOf(@typeOf(f)); } | |
| 1186 | \\export fn entry() usize { return @sizeOf(@typeOf(f)); } | |
| 1141 | 1187 | , ".tmp_source.zig:6:15: error: expected 2 arguments, found 3"); |
| 1142 | 1188 | |
| 1143 | 1189 | cases.add("assign through constant pointer", |
| 1144 | \\export fn f() { | |
| 1190 | \\export fn f() void { | |
| 1145 | 1191 | \\ var cstr = c"Hat"; |
| 1146 | 1192 | \\ cstr[0] = 'W'; |
| 1147 | 1193 | \\} |
| 1148 | 1194 | , ".tmp_source.zig:3:11: error: cannot assign to constant"); |
| 1149 | 1195 | |
| 1150 | 1196 | cases.add("assign through constant slice", |
| 1151 | \\export fn f() { | |
| 1197 | \\export fn f() void { | |
| 1152 | 1198 | \\ var cstr: []const u8 = "Hat"; |
| 1153 | 1199 | \\ cstr[0] = 'W'; |
| 1154 | 1200 | \\} |
| 1155 | 1201 | , ".tmp_source.zig:3:11: error: cannot assign to constant"); |
| 1156 | 1202 | |
| 1157 | 1203 | cases.add("main function with bogus args type", |
| 1158 | \\pub fn main(args: [][]bogus) -> %void {} | |
| 1204 | \\pub fn main(args: [][]bogus) %void {} | |
| 1159 | 1205 | , ".tmp_source.zig:1:23: error: use of undeclared identifier 'bogus'"); |
| 1160 | 1206 | |
| 1161 | 1207 | cases.add("for loop missing element param", |
| 1162 | \\fn foo(blah: []u8) { | |
| 1208 | \\fn foo(blah: []u8) void { | |
| 1163 | 1209 | \\ for (blah) { } |
| 1164 | 1210 | \\} |
| 1165 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 1211 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 1166 | 1212 | , ".tmp_source.zig:2:5: error: for loop expression missing element parameter"); |
| 1167 | 1213 | |
| 1168 | 1214 | cases.add("misspelled type with pointer only reference", |
| ... | ... | @@ -1189,27 +1235,27 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1189 | 1235 | \\ jobject: ?JsonOA, |
| 1190 | 1236 | \\}; |
| 1191 | 1237 | \\ |
| 1192 | \\fn foo() { | |
| 1238 | \\fn foo() void { | |
| 1193 | 1239 | \\ var jll: JasonList = undefined; |
| 1194 | 1240 | \\ jll.init(1234); |
| 1195 | 1241 | \\ var jd = JsonNode {.kind = JsonType.JSONArray , .jobject = JsonOA.JSONArray {jll} }; |
| 1196 | 1242 | \\} |
| 1197 | 1243 | \\ |
| 1198 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 1244 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 1199 | 1245 | , ".tmp_source.zig:5:16: error: use of undeclared identifier 'JsonList'"); |
| 1200 | 1246 | |
| 1201 | 1247 | cases.add("method call with first arg type primitive", |
| 1202 | 1248 | \\const Foo = struct { |
| 1203 | 1249 | \\ x: i32, |
| 1204 | 1250 | \\ |
| 1205 | \\ fn init(x: i32) -> Foo { | |
| 1251 | \\ fn init(x: i32) Foo { | |
| 1206 | 1252 | \\ return Foo { |
| 1207 | 1253 | \\ .x = x, |
| 1208 | 1254 | \\ }; |
| 1209 | 1255 | \\ } |
| 1210 | 1256 | \\}; |
| 1211 | 1257 | \\ |
| 1212 | \\export fn f() { | |
| 1258 | \\export fn f() void { | |
| 1213 | 1259 | \\ const derp = Foo.init(3); |
| 1214 | 1260 | \\ |
| 1215 | 1261 | \\ derp.init(); |
| ... | ... | @@ -1221,7 +1267,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1221 | 1267 | \\ len: usize, |
| 1222 | 1268 | \\ allocator: &Allocator, |
| 1223 | 1269 | \\ |
| 1224 | \\ pub fn init(allocator: &Allocator) -> List { | |
| 1270 | \\ pub fn init(allocator: &Allocator) List { | |
| 1225 | 1271 | \\ return List { |
| 1226 | 1272 | \\ .len = 0, |
| 1227 | 1273 | \\ .allocator = allocator, |
| ... | ... | @@ -1237,7 +1283,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1237 | 1283 | \\ field: i32, |
| 1238 | 1284 | \\}; |
| 1239 | 1285 | \\ |
| 1240 | \\export fn foo() { | |
| 1286 | \\export fn foo() void { | |
| 1241 | 1287 | \\ var x = List.init(&global_allocator); |
| 1242 | 1288 | \\ x.init(); |
| 1243 | 1289 | \\} |
| ... | ... | @@ -1248,14 +1294,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1248 | 1294 | \\const TINY_QUANTUM_SIZE = 1 << TINY_QUANTUM_SHIFT; |
| 1249 | 1295 | \\var block_aligned_stuff: usize = (4 + TINY_QUANTUM_SIZE) & ~(TINY_QUANTUM_SIZE - 1); |
| 1250 | 1296 | \\ |
| 1251 | \\export fn entry() -> usize { return @sizeOf(@typeOf(block_aligned_stuff)); } | |
| 1297 | \\export fn entry() usize { return @sizeOf(@typeOf(block_aligned_stuff)); } | |
| 1252 | 1298 | , ".tmp_source.zig:3:60: error: unable to perform binary not operation on type '(integer literal)'"); |
| 1253 | 1299 | |
| 1254 | 1300 | cases.addCase(x: { |
| 1255 | 1301 | const tc = cases.create("multiple files with private function error", |
| 1256 | 1302 | \\const foo = @import("foo.zig"); |
| 1257 | 1303 | \\ |
| 1258 | \\export fn callPrivFunction() { | |
| 1304 | \\export fn callPrivFunction() void { | |
| 1259 | 1305 | \\ foo.privateFunction(); |
| 1260 | 1306 | \\} |
| 1261 | 1307 | , |
| ... | ... | @@ -1263,7 +1309,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1263 | 1309 | "foo.zig:1:1: note: declared here"); |
| 1264 | 1310 | |
| 1265 | 1311 | tc.addSourceFile("foo.zig", |
| 1266 | \\fn privateFunction() { } | |
| 1312 | \\fn privateFunction() void { } | |
| 1267 | 1313 | ); |
| 1268 | 1314 | |
| 1269 | 1315 | break :x tc; |
| ... | ... | @@ -1273,21 +1319,21 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1273 | 1319 | \\const zero: i32 = 0; |
| 1274 | 1320 | \\const a = zero{1}; |
| 1275 | 1321 | \\ |
| 1276 | \\export fn entry() -> usize { return @sizeOf(@typeOf(a)); } | |
| 1322 | \\export fn entry() usize { return @sizeOf(@typeOf(a)); } | |
| 1277 | 1323 | , ".tmp_source.zig:2:11: error: expected type, found 'i32'"); |
| 1278 | 1324 | |
| 1279 | 1325 | cases.add("assign to constant field", |
| 1280 | 1326 | \\const Foo = struct { |
| 1281 | 1327 | \\ field: i32, |
| 1282 | 1328 | \\}; |
| 1283 | \\export fn derp() { | |
| 1329 | \\export fn derp() void { | |
| 1284 | 1330 | \\ const f = Foo {.field = 1234,}; |
| 1285 | 1331 | \\ f.field = 0; |
| 1286 | 1332 | \\} |
| 1287 | 1333 | , ".tmp_source.zig:6:13: error: cannot assign to constant"); |
| 1288 | 1334 | |
| 1289 | 1335 | cases.add("return from defer expression", |
| 1290 | \\pub fn testTrickyDefer() -> %void { | |
| 1336 | \\pub fn testTrickyDefer() %void { | |
| 1291 | 1337 | \\ defer canFail() catch {}; |
| 1292 | 1338 | \\ |
| 1293 | 1339 | \\ defer try canFail(); |
| ... | ... | @@ -1295,31 +1341,31 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1295 | 1341 | \\ const a = maybeInt() ?? return; |
| 1296 | 1342 | \\} |
| 1297 | 1343 | \\ |
| 1298 | \\fn canFail() -> %void { } | |
| 1344 | \\fn canFail() %void { } | |
| 1299 | 1345 | \\ |
| 1300 | \\pub fn maybeInt() -> ?i32 { | |
| 1346 | \\pub fn maybeInt() ?i32 { | |
| 1301 | 1347 | \\ return 0; |
| 1302 | 1348 | \\} |
| 1303 | 1349 | \\ |
| 1304 | \\export fn entry() -> usize { return @sizeOf(@typeOf(testTrickyDefer)); } | |
| 1350 | \\export fn entry() usize { return @sizeOf(@typeOf(testTrickyDefer)); } | |
| 1305 | 1351 | , ".tmp_source.zig:4:11: error: cannot return from defer expression"); |
| 1306 | 1352 | |
| 1307 | 1353 | cases.add("attempt to access var args out of bounds", |
| 1308 | \\fn add(args: ...) -> i32 { | |
| 1354 | \\fn add(args: ...) i32 { | |
| 1309 | 1355 | \\ return args[0] + args[1]; |
| 1310 | 1356 | \\} |
| 1311 | 1357 | \\ |
| 1312 | \\fn foo() -> i32 { | |
| 1358 | \\fn foo() i32 { | |
| 1313 | 1359 | \\ return add(i32(1234)); |
| 1314 | 1360 | \\} |
| 1315 | 1361 | \\ |
| 1316 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 1362 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 1317 | 1363 | , |
| 1318 | 1364 | ".tmp_source.zig:2:26: error: index 1 outside argument list of size 1", |
| 1319 | 1365 | ".tmp_source.zig:6:15: note: called from here"); |
| 1320 | 1366 | |
| 1321 | 1367 | cases.add("pass integer literal to var args", |
| 1322 | \\fn add(args: ...) -> i32 { | |
| 1368 | \\fn add(args: ...) i32 { | |
| 1323 | 1369 | \\ var sum = i32(0); |
| 1324 | 1370 | \\ {comptime var i: usize = 0; inline while (i < args.len) : (i += 1) { |
| 1325 | 1371 | \\ sum += args[i]; |
| ... | ... | @@ -1327,34 +1373,34 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1327 | 1373 | \\ return sum; |
| 1328 | 1374 | \\} |
| 1329 | 1375 | \\ |
| 1330 | \\fn bar() -> i32 { | |
| 1376 | \\fn bar() i32 { | |
| 1331 | 1377 | \\ return add(1, 2, 3, 4); |
| 1332 | 1378 | \\} |
| 1333 | 1379 | \\ |
| 1334 | \\export fn entry() -> usize { return @sizeOf(@typeOf(bar)); } | |
| 1380 | \\export fn entry() usize { return @sizeOf(@typeOf(bar)); } | |
| 1335 | 1381 | , ".tmp_source.zig:10:16: error: parameter of type '(integer literal)' requires comptime"); |
| 1336 | 1382 | |
| 1337 | 1383 | cases.add("assign too big number to u16", |
| 1338 | \\export fn foo() { | |
| 1384 | \\export fn foo() void { | |
| 1339 | 1385 | \\ var vga_mem: u16 = 0xB8000; |
| 1340 | 1386 | \\} |
| 1341 | 1387 | , ".tmp_source.zig:2:24: error: integer value 753664 cannot be implicitly casted to type 'u16'"); |
| 1342 | 1388 | |
| 1343 | 1389 | cases.add("global variable alignment non power of 2", |
| 1344 | 1390 | \\const some_data: [100]u8 align(3) = undefined; |
| 1345 | \\export fn entry() -> usize { return @sizeOf(@typeOf(some_data)); } | |
| 1391 | \\export fn entry() usize { return @sizeOf(@typeOf(some_data)); } | |
| 1346 | 1392 | , ".tmp_source.zig:1:32: error: alignment value 3 is not a power of 2"); |
| 1347 | 1393 | |
| 1348 | 1394 | cases.add("function alignment non power of 2", |
| 1349 | \\extern fn foo() align(3); | |
| 1350 | \\export fn entry() { return foo(); } | |
| 1395 | \\extern fn foo() align(3) void; | |
| 1396 | \\export fn entry() void { return foo(); } | |
| 1351 | 1397 | , ".tmp_source.zig:1:23: error: alignment value 3 is not a power of 2"); |
| 1352 | 1398 | |
| 1353 | 1399 | cases.add("compile log", |
| 1354 | \\export fn foo() { | |
| 1400 | \\export fn foo() void { | |
| 1355 | 1401 | \\ comptime bar(12, "hi"); |
| 1356 | 1402 | \\} |
| 1357 | \\fn bar(a: i32, b: []const u8) { | |
| 1403 | \\fn bar(a: i32, b: []const u8) void { | |
| 1358 | 1404 | \\ @compileLog("begin"); |
| 1359 | 1405 | \\ @compileLog("a", a, "b", b); |
| 1360 | 1406 | \\ @compileLog("end"); |
| ... | ... | @@ -1374,15 +1420,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1374 | 1420 | \\ c: u2, |
| 1375 | 1421 | \\}; |
| 1376 | 1422 | \\ |
| 1377 | \\fn foo(bit_field: &const BitField) -> u3 { | |
| 1423 | \\fn foo(bit_field: &const BitField) u3 { | |
| 1378 | 1424 | \\ return bar(&bit_field.b); |
| 1379 | 1425 | \\} |
| 1380 | 1426 | \\ |
| 1381 | \\fn bar(x: &const u3) -> u3 { | |
| 1427 | \\fn bar(x: &const u3) u3 { | |
| 1382 | 1428 | \\ return *x; |
| 1383 | 1429 | \\} |
| 1384 | 1430 | \\ |
| 1385 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 1431 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 1386 | 1432 | , ".tmp_source.zig:8:26: error: expected type '&const u3', found '&align(1:3:6) const u3'"); |
| 1387 | 1433 | |
| 1388 | 1434 | cases.add("referring to a struct that is invalid", |
| ... | ... | @@ -1390,11 +1436,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1390 | 1436 | \\ Type: u8, |
| 1391 | 1437 | \\}; |
| 1392 | 1438 | \\ |
| 1393 | \\export fn foo() { | |
| 1439 | \\export fn foo() void { | |
| 1394 | 1440 | \\ comptime assert(@sizeOf(UsbDeviceRequest) == 0x8); |
| 1395 | 1441 | \\} |
| 1396 | 1442 | \\ |
| 1397 | \\fn assert(ok: bool) { | |
| 1443 | \\fn assert(ok: bool) void { | |
| 1398 | 1444 | \\ if (!ok) unreachable; |
| 1399 | 1445 | \\} |
| 1400 | 1446 | , |
| ... | ... | @@ -1402,92 +1448,92 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1402 | 1448 | ".tmp_source.zig:6:20: note: called from here"); |
| 1403 | 1449 | |
| 1404 | 1450 | cases.add("control flow uses comptime var at runtime", |
| 1405 | \\export fn foo() { | |
| 1451 | \\export fn foo() void { | |
| 1406 | 1452 | \\ comptime var i = 0; |
| 1407 | 1453 | \\ while (i < 5) : (i += 1) { |
| 1408 | 1454 | \\ bar(); |
| 1409 | 1455 | \\ } |
| 1410 | 1456 | \\} |
| 1411 | 1457 | \\ |
| 1412 | \\fn bar() { } | |
| 1458 | \\fn bar() void { } | |
| 1413 | 1459 | , |
| 1414 | 1460 | ".tmp_source.zig:3:5: error: control flow attempts to use compile-time variable at runtime", |
| 1415 | 1461 | ".tmp_source.zig:3:24: note: compile-time variable assigned here"); |
| 1416 | 1462 | |
| 1417 | 1463 | cases.add("ignored return value", |
| 1418 | \\export fn foo() { | |
| 1464 | \\export fn foo() void { | |
| 1419 | 1465 | \\ bar(); |
| 1420 | 1466 | \\} |
| 1421 | \\fn bar() -> i32 { return 0; } | |
| 1467 | \\fn bar() i32 { return 0; } | |
| 1422 | 1468 | , ".tmp_source.zig:2:8: error: expression value is ignored"); |
| 1423 | 1469 | |
| 1424 | 1470 | cases.add("ignored assert-err-ok return value", |
| 1425 | \\export fn foo() { | |
| 1471 | \\export fn foo() void { | |
| 1426 | 1472 | \\ bar() catch unreachable; |
| 1427 | 1473 | \\} |
| 1428 | \\fn bar() -> %i32 { return 0; } | |
| 1474 | \\fn bar() %i32 { return 0; } | |
| 1429 | 1475 | , ".tmp_source.zig:2:11: error: expression value is ignored"); |
| 1430 | 1476 | |
| 1431 | 1477 | cases.add("ignored statement value", |
| 1432 | \\export fn foo() { | |
| 1478 | \\export fn foo() void { | |
| 1433 | 1479 | \\ 1; |
| 1434 | 1480 | \\} |
| 1435 | 1481 | , ".tmp_source.zig:2:5: error: expression value is ignored"); |
| 1436 | 1482 | |
| 1437 | 1483 | cases.add("ignored comptime statement value", |
| 1438 | \\export fn foo() { | |
| 1484 | \\export fn foo() void { | |
| 1439 | 1485 | \\ comptime {1;} |
| 1440 | 1486 | \\} |
| 1441 | 1487 | , ".tmp_source.zig:2:15: error: expression value is ignored"); |
| 1442 | 1488 | |
| 1443 | 1489 | cases.add("ignored comptime value", |
| 1444 | \\export fn foo() { | |
| 1490 | \\export fn foo() void { | |
| 1445 | 1491 | \\ comptime 1; |
| 1446 | 1492 | \\} |
| 1447 | 1493 | , ".tmp_source.zig:2:5: error: expression value is ignored"); |
| 1448 | 1494 | |
| 1449 | 1495 | cases.add("ignored defered statement value", |
| 1450 | \\export fn foo() { | |
| 1496 | \\export fn foo() void { | |
| 1451 | 1497 | \\ defer {1;} |
| 1452 | 1498 | \\} |
| 1453 | 1499 | , ".tmp_source.zig:2:12: error: expression value is ignored"); |
| 1454 | 1500 | |
| 1455 | 1501 | cases.add("ignored defered function call", |
| 1456 | \\export fn foo() { | |
| 1502 | \\export fn foo() void { | |
| 1457 | 1503 | \\ defer bar(); |
| 1458 | 1504 | \\} |
| 1459 | \\fn bar() -> %i32 { return 0; } | |
| 1505 | \\fn bar() %i32 { return 0; } | |
| 1460 | 1506 | , ".tmp_source.zig:2:14: error: expression value is ignored"); |
| 1461 | 1507 | |
| 1462 | 1508 | cases.add("dereference an array", |
| 1463 | 1509 | \\var s_buffer: [10]u8 = undefined; |
| 1464 | \\pub fn pass(in: []u8) -> []u8 { | |
| 1510 | \\pub fn pass(in: []u8) []u8 { | |
| 1465 | 1511 | \\ var out = &s_buffer; |
| 1466 | 1512 | \\ *out[0] = in[0]; |
| 1467 | 1513 | \\ return (*out)[0..1]; |
| 1468 | 1514 | \\} |
| 1469 | 1515 | \\ |
| 1470 | \\export fn entry() -> usize { return @sizeOf(@typeOf(pass)); } | |
| 1516 | \\export fn entry() usize { return @sizeOf(@typeOf(pass)); } | |
| 1471 | 1517 | , ".tmp_source.zig:4:5: error: attempt to dereference non pointer type '[10]u8'"); |
| 1472 | 1518 | |
| 1473 | 1519 | cases.add("pass const ptr to mutable ptr fn", |
| 1474 | \\fn foo() -> bool { | |
| 1520 | \\fn foo() bool { | |
| 1475 | 1521 | \\ const a = ([]const u8)("a"); |
| 1476 | 1522 | \\ const b = &a; |
| 1477 | 1523 | \\ return ptrEql(b, b); |
| 1478 | 1524 | \\} |
| 1479 | \\fn ptrEql(a: &[]const u8, b: &[]const u8) -> bool { | |
| 1525 | \\fn ptrEql(a: &[]const u8, b: &[]const u8) bool { | |
| 1480 | 1526 | \\ return true; |
| 1481 | 1527 | \\} |
| 1482 | 1528 | \\ |
| 1483 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 1529 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 1484 | 1530 | , ".tmp_source.zig:4:19: error: expected type '&[]const u8', found '&const []const u8'"); |
| 1485 | 1531 | |
| 1486 | 1532 | cases.addCase(x: { |
| 1487 | 1533 | const tc = cases.create("export collision", |
| 1488 | 1534 | \\const foo = @import("foo.zig"); |
| 1489 | 1535 | \\ |
| 1490 | \\export fn bar() -> usize { | |
| 1536 | \\export fn bar() usize { | |
| 1491 | 1537 | \\ return foo.baz; |
| 1492 | 1538 | \\} |
| 1493 | 1539 | , |
| ... | ... | @@ -1495,7 +1541,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1495 | 1541 | ".tmp_source.zig:3:8: note: other symbol here"); |
| 1496 | 1542 | |
| 1497 | 1543 | tc.addSourceFile("foo.zig", |
| 1498 | \\export fn bar() {} | |
| 1544 | \\export fn bar() void {} | |
| 1499 | 1545 | \\pub const baz = 1234; |
| 1500 | 1546 | ); |
| 1501 | 1547 | |
| ... | ... | @@ -1504,20 +1550,20 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1504 | 1550 | |
| 1505 | 1551 | cases.add("pass non-copyable type by value to function", |
| 1506 | 1552 | \\const Point = struct { x: i32, y: i32, }; |
| 1507 | \\fn foo(p: Point) { } | |
| 1508 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 1553 | \\fn foo(p: Point) void { } | |
| 1554 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 1509 | 1555 | , ".tmp_source.zig:2:11: error: type 'Point' is not copyable; cannot pass by value"); |
| 1510 | 1556 | |
| 1511 | 1557 | cases.add("implicit cast from array to mutable slice", |
| 1512 | 1558 | \\var global_array: [10]i32 = undefined; |
| 1513 | \\fn foo(param: []i32) {} | |
| 1514 | \\export fn entry() { | |
| 1559 | \\fn foo(param: []i32) void {} | |
| 1560 | \\export fn entry() void { | |
| 1515 | 1561 | \\ foo(global_array); |
| 1516 | 1562 | \\} |
| 1517 | 1563 | , ".tmp_source.zig:4:9: error: expected type '[]i32', found '[10]i32'"); |
| 1518 | 1564 | |
| 1519 | 1565 | cases.add("ptrcast to non-pointer", |
| 1520 | \\export fn entry(a: &i32) -> usize { | |
| 1566 | \\export fn entry(a: &i32) usize { | |
| 1521 | 1567 | \\ return @ptrCast(usize, a); |
| 1522 | 1568 | \\} |
| 1523 | 1569 | , ".tmp_source.zig:2:21: error: expected pointer, found 'usize'"); |
| ... | ... | @@ -1525,10 +1571,10 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1525 | 1571 | cases.add("too many error values to cast to small integer", |
| 1526 | 1572 | \\error A; error B; error C; error D; error E; error F; error G; error H; |
| 1527 | 1573 | \\const u2 = @IntType(false, 2); |
| 1528 | \\fn foo(e: error) -> u2 { | |
| 1574 | \\fn foo(e: error) u2 { | |
| 1529 | 1575 | \\ return u2(e); |
| 1530 | 1576 | \\} |
| 1531 | \\export fn entry() -> usize { return @sizeOf(@typeOf(foo)); } | |
| 1577 | \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } | |
| 1532 | 1578 | , ".tmp_source.zig:4:14: error: too many error values to fit in 'u2'"); |
| 1533 | 1579 | |
| 1534 | 1580 | cases.add("asm at compile time", |
| ... | ... | @@ -1536,7 +1582,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1536 | 1582 | \\ doSomeAsm(); |
| 1537 | 1583 | \\} |
| 1538 | 1584 | \\ |
| 1539 | \\fn doSomeAsm() { | |
| 1585 | \\fn doSomeAsm() void { | |
| 1540 | 1586 | \\ asm volatile ( |
| 1541 | 1587 | \\ \\.globl aoeu; |
| 1542 | 1588 | \\ \\.type aoeu, @function; |
| ... | ... | @@ -1547,13 +1593,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1547 | 1593 | |
| 1548 | 1594 | cases.add("invalid member of builtin enum", |
| 1549 | 1595 | \\const builtin = @import("builtin"); |
| 1550 | \\export fn entry() { | |
| 1596 | \\export fn entry() void { | |
| 1551 | 1597 | \\ const foo = builtin.Arch.x86; |
| 1552 | 1598 | \\} |
| 1553 | 1599 | , ".tmp_source.zig:3:29: error: container 'Arch' has no member called 'x86'"); |
| 1554 | 1600 | |
| 1555 | 1601 | cases.add("int to ptr of 0 bits", |
| 1556 | \\export fn foo() { | |
| 1602 | \\export fn foo() void { | |
| 1557 | 1603 | \\ var x: usize = 0x1000; |
| 1558 | 1604 | \\ var y: &void = @intToPtr(&void, x); |
| 1559 | 1605 | \\} |
| ... | ... | @@ -1561,25 +1607,25 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1561 | 1607 | |
| 1562 | 1608 | cases.add("@fieldParentPtr - non struct", |
| 1563 | 1609 | \\const Foo = i32; |
| 1564 | \\export fn foo(a: &i32) -> &Foo { | |
| 1610 | \\export fn foo(a: &i32) &Foo { | |
| 1565 | 1611 | \\ return @fieldParentPtr(Foo, "a", a); |
| 1566 | 1612 | \\} |
| 1567 | 1613 | , ".tmp_source.zig:3:28: error: expected struct type, found 'i32'"); |
| 1568 | 1614 | |
| 1569 | 1615 | cases.add("@fieldParentPtr - bad field name", |
| 1570 | \\const Foo = struct { | |
| 1616 | \\const Foo = extern struct { | |
| 1571 | 1617 | \\ derp: i32, |
| 1572 | 1618 | \\}; |
| 1573 | \\export fn foo(a: &i32) -> &Foo { | |
| 1619 | \\export fn foo(a: &i32) &Foo { | |
| 1574 | 1620 | \\ return @fieldParentPtr(Foo, "a", a); |
| 1575 | 1621 | \\} |
| 1576 | 1622 | , ".tmp_source.zig:5:33: error: struct 'Foo' has no field 'a'"); |
| 1577 | 1623 | |
| 1578 | 1624 | cases.add("@fieldParentPtr - field pointer is not pointer", |
| 1579 | \\const Foo = struct { | |
| 1625 | \\const Foo = extern struct { | |
| 1580 | 1626 | \\ a: i32, |
| 1581 | 1627 | \\}; |
| 1582 | \\export fn foo(a: i32) -> &Foo { | |
| 1628 | \\export fn foo(a: i32) &Foo { | |
| 1583 | 1629 | \\ return @fieldParentPtr(Foo, "a", a); |
| 1584 | 1630 | \\} |
| 1585 | 1631 | , ".tmp_source.zig:5:38: error: expected pointer, found 'i32'"); |
| ... | ... | @@ -1611,7 +1657,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1611 | 1657 | |
| 1612 | 1658 | cases.add("@offsetOf - non struct", |
| 1613 | 1659 | \\const Foo = i32; |
| 1614 | \\export fn foo() -> usize { | |
| 1660 | \\export fn foo() usize { | |
| 1615 | 1661 | \\ return @offsetOf(Foo, "a"); |
| 1616 | 1662 | \\} |
| 1617 | 1663 | , ".tmp_source.zig:3:22: error: expected struct type, found 'i32'"); |
| ... | ... | @@ -1620,7 +1666,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1620 | 1666 | \\const Foo = struct { |
| 1621 | 1667 | \\ derp: i32, |
| 1622 | 1668 | \\}; |
| 1623 | \\export fn foo() -> usize { | |
| 1669 | \\export fn foo() usize { | |
| 1624 | 1670 | \\ return @offsetOf(Foo, "a"); |
| 1625 | 1671 | \\} |
| 1626 | 1672 | , ".tmp_source.zig:5:27: error: struct 'Foo' has no field 'a'"); |
| ... | ... | @@ -1630,21 +1676,21 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1630 | 1676 | , "error: no member named 'main' in '"); |
| 1631 | 1677 | |
| 1632 | 1678 | cases.addExe("private main fn", |
| 1633 | \\fn main() {} | |
| 1679 | \\fn main() void {} | |
| 1634 | 1680 | , |
| 1635 | 1681 | "error: 'main' is private", |
| 1636 | 1682 | ".tmp_source.zig:1:1: note: declared here"); |
| 1637 | 1683 | |
| 1638 | 1684 | cases.add("setting a section on an extern variable", |
| 1639 | 1685 | \\extern var foo: i32 section(".text2"); |
| 1640 | \\export fn entry() -> i32 { | |
| 1686 | \\export fn entry() i32 { | |
| 1641 | 1687 | \\ return foo; |
| 1642 | 1688 | \\} |
| 1643 | 1689 | , |
| 1644 | 1690 | ".tmp_source.zig:1:29: error: cannot set section of external variable 'foo'"); |
| 1645 | 1691 | |
| 1646 | 1692 | cases.add("setting a section on a local variable", |
| 1647 | \\export fn entry() -> i32 { | |
| 1693 | \\export fn entry() i32 { | |
| 1648 | 1694 | \\ var foo: i32 section(".text2") = 1234; |
| 1649 | 1695 | \\ return foo; |
| 1650 | 1696 | \\} |
| ... | ... | @@ -1652,15 +1698,15 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1652 | 1698 | ".tmp_source.zig:2:26: error: cannot set section of local variable 'foo'"); |
| 1653 | 1699 | |
| 1654 | 1700 | cases.add("setting a section on an extern fn", |
| 1655 | \\extern fn foo() section(".text2"); | |
| 1656 | \\export fn entry() { | |
| 1701 | \\extern fn foo() section(".text2") void; | |
| 1702 | \\export fn entry() void { | |
| 1657 | 1703 | \\ foo(); |
| 1658 | 1704 | \\} |
| 1659 | 1705 | , |
| 1660 | 1706 | ".tmp_source.zig:1:25: error: cannot set section of external function 'foo'"); |
| 1661 | 1707 | |
| 1662 | 1708 | cases.add("returning address of local variable - simple", |
| 1663 | \\export fn foo() -> &i32 { | |
| 1709 | \\export fn foo() &i32 { | |
| 1664 | 1710 | \\ var a: i32 = undefined; |
| 1665 | 1711 | \\ return &a; |
| 1666 | 1712 | \\} |
| ... | ... | @@ -1668,7 +1714,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1668 | 1714 | ".tmp_source.zig:3:13: error: function returns address of local variable"); |
| 1669 | 1715 | |
| 1670 | 1716 | cases.add("returning address of local variable - phi", |
| 1671 | \\export fn foo(c: bool) -> &i32 { | |
| 1717 | \\export fn foo(c: bool) &i32 { | |
| 1672 | 1718 | \\ var a: i32 = undefined; |
| 1673 | 1719 | \\ var b: i32 = undefined; |
| 1674 | 1720 | \\ return if (c) &a else &b; |
| ... | ... | @@ -1677,13 +1723,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1677 | 1723 | ".tmp_source.zig:4:12: error: function returns address of local variable"); |
| 1678 | 1724 | |
| 1679 | 1725 | cases.add("inner struct member shadowing outer struct member", |
| 1680 | \\fn A() -> type { | |
| 1726 | \\fn A() type { | |
| 1681 | 1727 | \\ return struct { |
| 1682 | 1728 | \\ b: B(), |
| 1683 | 1729 | \\ |
| 1684 | 1730 | \\ const Self = this; |
| 1685 | 1731 | \\ |
| 1686 | \\ fn B() -> type { | |
| 1732 | \\ fn B() type { | |
| 1687 | 1733 | \\ return struct { |
| 1688 | 1734 | \\ const Self = this; |
| 1689 | 1735 | \\ }; |
| ... | ... | @@ -1693,7 +1739,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1693 | 1739 | \\comptime { |
| 1694 | 1740 | \\ assert(A().B().Self != A().Self); |
| 1695 | 1741 | \\} |
| 1696 | \\fn assert(ok: bool) { | |
| 1742 | \\fn assert(ok: bool) void { | |
| 1697 | 1743 | \\ if (!ok) unreachable; |
| 1698 | 1744 | \\} |
| 1699 | 1745 | , |
| ... | ... | @@ -1701,87 +1747,87 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1701 | 1747 | ".tmp_source.zig:5:9: note: previous definition is here"); |
| 1702 | 1748 | |
| 1703 | 1749 | cases.add("while expected bool, got nullable", |
| 1704 | \\export fn foo() { | |
| 1750 | \\export fn foo() void { | |
| 1705 | 1751 | \\ while (bar()) {} |
| 1706 | 1752 | \\} |
| 1707 | \\fn bar() -> ?i32 { return 1; } | |
| 1753 | \\fn bar() ?i32 { return 1; } | |
| 1708 | 1754 | , |
| 1709 | 1755 | ".tmp_source.zig:2:15: error: expected type 'bool', found '?i32'"); |
| 1710 | 1756 | |
| 1711 | 1757 | cases.add("while expected bool, got error union", |
| 1712 | \\export fn foo() { | |
| 1758 | \\export fn foo() void { | |
| 1713 | 1759 | \\ while (bar()) {} |
| 1714 | 1760 | \\} |
| 1715 | \\fn bar() -> %i32 { return 1; } | |
| 1761 | \\fn bar() %i32 { return 1; } | |
| 1716 | 1762 | , |
| 1717 | 1763 | ".tmp_source.zig:2:15: error: expected type 'bool', found '%i32'"); |
| 1718 | 1764 | |
| 1719 | 1765 | cases.add("while expected nullable, got bool", |
| 1720 | \\export fn foo() { | |
| 1766 | \\export fn foo() void { | |
| 1721 | 1767 | \\ while (bar()) |x| {} |
| 1722 | 1768 | \\} |
| 1723 | \\fn bar() -> bool { return true; } | |
| 1769 | \\fn bar() bool { return true; } | |
| 1724 | 1770 | , |
| 1725 | 1771 | ".tmp_source.zig:2:15: error: expected nullable type, found 'bool'"); |
| 1726 | 1772 | |
| 1727 | 1773 | cases.add("while expected nullable, got error union", |
| 1728 | \\export fn foo() { | |
| 1774 | \\export fn foo() void { | |
| 1729 | 1775 | \\ while (bar()) |x| {} |
| 1730 | 1776 | \\} |
| 1731 | \\fn bar() -> %i32 { return 1; } | |
| 1777 | \\fn bar() %i32 { return 1; } | |
| 1732 | 1778 | , |
| 1733 | 1779 | ".tmp_source.zig:2:15: error: expected nullable type, found '%i32'"); |
| 1734 | 1780 | |
| 1735 | 1781 | cases.add("while expected error union, got bool", |
| 1736 | \\export fn foo() { | |
| 1782 | \\export fn foo() void { | |
| 1737 | 1783 | \\ while (bar()) |x| {} else |err| {} |
| 1738 | 1784 | \\} |
| 1739 | \\fn bar() -> bool { return true; } | |
| 1785 | \\fn bar() bool { return true; } | |
| 1740 | 1786 | , |
| 1741 | 1787 | ".tmp_source.zig:2:15: error: expected error union type, found 'bool'"); |
| 1742 | 1788 | |
| 1743 | 1789 | cases.add("while expected error union, got nullable", |
| 1744 | \\export fn foo() { | |
| 1790 | \\export fn foo() void { | |
| 1745 | 1791 | \\ while (bar()) |x| {} else |err| {} |
| 1746 | 1792 | \\} |
| 1747 | \\fn bar() -> ?i32 { return 1; } | |
| 1793 | \\fn bar() ?i32 { return 1; } | |
| 1748 | 1794 | , |
| 1749 | 1795 | ".tmp_source.zig:2:15: error: expected error union type, found '?i32'"); |
| 1750 | 1796 | |
| 1751 | 1797 | cases.add("inline fn calls itself indirectly", |
| 1752 | \\export fn foo() { | |
| 1798 | \\export fn foo() void { | |
| 1753 | 1799 | \\ bar(); |
| 1754 | 1800 | \\} |
| 1755 | \\inline fn bar() { | |
| 1801 | \\inline fn bar() void { | |
| 1756 | 1802 | \\ baz(); |
| 1757 | 1803 | \\ quux(); |
| 1758 | 1804 | \\} |
| 1759 | \\inline fn baz() { | |
| 1805 | \\inline fn baz() void { | |
| 1760 | 1806 | \\ bar(); |
| 1761 | 1807 | \\ quux(); |
| 1762 | 1808 | \\} |
| 1763 | \\extern fn quux(); | |
| 1809 | \\extern fn quux() void; | |
| 1764 | 1810 | , |
| 1765 | 1811 | ".tmp_source.zig:4:8: error: unable to inline function"); |
| 1766 | 1812 | |
| 1767 | 1813 | cases.add("save reference to inline function", |
| 1768 | \\export fn foo() { | |
| 1814 | \\export fn foo() void { | |
| 1769 | 1815 | \\ quux(@ptrToInt(bar)); |
| 1770 | 1816 | \\} |
| 1771 | \\inline fn bar() { } | |
| 1772 | \\extern fn quux(usize); | |
| 1817 | \\inline fn bar() void { } | |
| 1818 | \\extern fn quux(usize) void; | |
| 1773 | 1819 | , |
| 1774 | 1820 | ".tmp_source.zig:4:8: error: unable to inline function"); |
| 1775 | 1821 | |
| 1776 | 1822 | cases.add("signed integer division", |
| 1777 | \\export fn foo(a: i32, b: i32) -> i32 { | |
| 1823 | \\export fn foo(a: i32, b: i32) i32 { | |
| 1778 | 1824 | \\ return a / b; |
| 1779 | 1825 | \\} |
| 1780 | 1826 | , |
| 1781 | 1827 | ".tmp_source.zig:2:14: error: division with 'i32' and 'i32': signed integers must use @divTrunc, @divFloor, or @divExact"); |
| 1782 | 1828 | |
| 1783 | 1829 | cases.add("signed integer remainder division", |
| 1784 | \\export fn foo(a: i32, b: i32) -> i32 { | |
| 1830 | \\export fn foo(a: i32, b: i32) i32 { | |
| 1785 | 1831 | \\ return a % b; |
| 1786 | 1832 | \\} |
| 1787 | 1833 | , |
| ... | ... | @@ -1802,7 +1848,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1802 | 1848 | \\ const c = a / b; |
| 1803 | 1849 | \\} |
| 1804 | 1850 | , |
| 1805 | ".tmp_source.zig:4:17: error: division by zero is undefined"); | |
| 1851 | ".tmp_source.zig:4:17: error: division by zero"); | |
| 1806 | 1852 | |
| 1807 | 1853 | cases.add("compile-time remainder division by zero", |
| 1808 | 1854 | \\comptime { |
| ... | ... | @@ -1811,7 +1857,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1811 | 1857 | \\ const c = a % b; |
| 1812 | 1858 | \\} |
| 1813 | 1859 | , |
| 1814 | ".tmp_source.zig:4:17: error: division by zero is undefined"); | |
| 1860 | ".tmp_source.zig:4:17: error: division by zero"); | |
| 1815 | 1861 | |
| 1816 | 1862 | cases.add("compile-time integer cast truncates bits", |
| 1817 | 1863 | \\comptime { |
| ... | ... | @@ -1821,17 +1867,17 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1821 | 1867 | , |
| 1822 | 1868 | ".tmp_source.zig:3:20: error: cast from 'u16' to 'u8' truncates bits"); |
| 1823 | 1869 | |
| 1824 | cases.add("@setDebugSafety twice for same scope", | |
| 1825 | \\export fn foo() { | |
| 1826 | \\ @setDebugSafety(this, false); | |
| 1827 | \\ @setDebugSafety(this, false); | |
| 1870 | cases.add("@setRuntimeSafety twice for same scope", | |
| 1871 | \\export fn foo() void { | |
| 1872 | \\ @setRuntimeSafety(false); | |
| 1873 | \\ @setRuntimeSafety(false); | |
| 1828 | 1874 | \\} |
| 1829 | 1875 | , |
| 1830 | ".tmp_source.zig:3:5: error: debug safety set twice for same scope", | |
| 1876 | ".tmp_source.zig:3:5: error: runtime safety set twice for same scope", | |
| 1831 | 1877 | ".tmp_source.zig:2:5: note: first set here"); |
| 1832 | 1878 | |
| 1833 | 1879 | cases.add("@setFloatMode twice for same scope", |
| 1834 | \\export fn foo() { | |
| 1880 | \\export fn foo() void { | |
| 1835 | 1881 | \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized); |
| 1836 | 1882 | \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized); |
| 1837 | 1883 | \\} |
| ... | ... | @@ -1840,14 +1886,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1840 | 1886 | ".tmp_source.zig:2:5: note: first set here"); |
| 1841 | 1887 | |
| 1842 | 1888 | cases.add("array access of type", |
| 1843 | \\export fn foo() { | |
| 1889 | \\export fn foo() void { | |
| 1844 | 1890 | \\ var b: u8[40] = undefined; |
| 1845 | 1891 | \\} |
| 1846 | 1892 | , |
| 1847 | 1893 | ".tmp_source.zig:2:14: error: array access of non-array type 'type'"); |
| 1848 | 1894 | |
| 1849 | 1895 | cases.add("cannot break out of defer expression", |
| 1850 | \\export fn foo() { | |
| 1896 | \\export fn foo() void { | |
| 1851 | 1897 | \\ while (true) { |
| 1852 | 1898 | \\ defer { |
| 1853 | 1899 | \\ break; |
| ... | ... | @@ -1858,7 +1904,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1858 | 1904 | ".tmp_source.zig:4:13: error: cannot break out of defer expression"); |
| 1859 | 1905 | |
| 1860 | 1906 | cases.add("cannot continue out of defer expression", |
| 1861 | \\export fn foo() { | |
| 1907 | \\export fn foo() void { | |
| 1862 | 1908 | \\ while (true) { |
| 1863 | 1909 | \\ defer { |
| 1864 | 1910 | \\ continue; |
| ... | ... | @@ -1869,24 +1915,24 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1869 | 1915 | ".tmp_source.zig:4:13: error: cannot continue out of defer expression"); |
| 1870 | 1916 | |
| 1871 | 1917 | cases.add("calling a var args function only known at runtime", |
| 1872 | \\var foos = []fn(...) { foo1, foo2 }; | |
| 1918 | \\var foos = []fn(...) void { foo1, foo2 }; | |
| 1873 | 1919 | \\ |
| 1874 | \\fn foo1(args: ...) {} | |
| 1875 | \\fn foo2(args: ...) {} | |
| 1920 | \\fn foo1(args: ...) void {} | |
| 1921 | \\fn foo2(args: ...) void {} | |
| 1876 | 1922 | \\ |
| 1877 | \\pub fn main() -> %void { | |
| 1923 | \\pub fn main() %void { | |
| 1878 | 1924 | \\ foos[0](); |
| 1879 | 1925 | \\} |
| 1880 | 1926 | , |
| 1881 | 1927 | ".tmp_source.zig:7:9: error: calling a generic function requires compile-time known function value"); |
| 1882 | 1928 | |
| 1883 | 1929 | cases.add("calling a generic function only known at runtime", |
| 1884 | \\var foos = []fn(var) { foo1, foo2 }; | |
| 1930 | \\var foos = []fn(var) void { foo1, foo2 }; | |
| 1885 | 1931 | \\ |
| 1886 | \\fn foo1(arg: var) {} | |
| 1887 | \\fn foo2(arg: var) {} | |
| 1932 | \\fn foo1(arg: var) void {} | |
| 1933 | \\fn foo2(arg: var) void {} | |
| 1888 | 1934 | \\ |
| 1889 | \\pub fn main() -> %void { | |
| 1935 | \\pub fn main() %void { | |
| 1890 | 1936 | \\ foos[0](true); |
| 1891 | 1937 | \\} |
| 1892 | 1938 | , |
| ... | ... | @@ -1898,7 +1944,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1898 | 1944 | \\const bar = baz + foo; |
| 1899 | 1945 | \\const baz = 1; |
| 1900 | 1946 | \\ |
| 1901 | \\export fn entry() -> i32 { | |
| 1947 | \\export fn entry() i32 { | |
| 1902 | 1948 | \\ return bar; |
| 1903 | 1949 | \\} |
| 1904 | 1950 | , |
| ... | ... | @@ -1913,7 +1959,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1913 | 1959 | \\ |
| 1914 | 1960 | \\var foo: Foo = undefined; |
| 1915 | 1961 | \\ |
| 1916 | \\export fn entry() -> usize { | |
| 1962 | \\export fn entry() usize { | |
| 1917 | 1963 | \\ return @sizeOf(@typeOf(foo.x)); |
| 1918 | 1964 | \\} |
| 1919 | 1965 | , |
| ... | ... | @@ -1934,14 +1980,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1934 | 1980 | ".tmp_source.zig:2:15: error: float literal out of range of any type"); |
| 1935 | 1981 | |
| 1936 | 1982 | cases.add("explicit cast float literal to integer when there is a fraction component", |
| 1937 | \\export fn entry() -> i32 { | |
| 1983 | \\export fn entry() i32 { | |
| 1938 | 1984 | \\ return i32(12.34); |
| 1939 | 1985 | \\} |
| 1940 | 1986 | , |
| 1941 | 1987 | ".tmp_source.zig:2:16: error: fractional component prevents float value 12.340000 from being casted to type 'i32'"); |
| 1942 | 1988 | |
| 1943 | 1989 | cases.add("non pointer given to @ptrToInt", |
| 1944 | \\export fn entry(x: i32) -> usize { | |
| 1990 | \\export fn entry(x: i32) usize { | |
| 1945 | 1991 | \\ return @ptrToInt(x); |
| 1946 | 1992 | \\} |
| 1947 | 1993 | , |
| ... | ... | @@ -1962,14 +2008,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1962 | 2008 | ".tmp_source.zig:2:15: error: exact shift shifted out 1 bits"); |
| 1963 | 2009 | |
| 1964 | 2010 | cases.add("shifting without int type or comptime known", |
| 1965 | \\export fn entry(x: u8) -> u8 { | |
| 2011 | \\export fn entry(x: u8) u8 { | |
| 1966 | 2012 | \\ return 0x11 << x; |
| 1967 | 2013 | \\} |
| 1968 | 2014 | , |
| 1969 | 2015 | ".tmp_source.zig:2:17: error: LHS of shift must be an integer type, or RHS must be compile-time known"); |
| 1970 | 2016 | |
| 1971 | 2017 | cases.add("shifting RHS is log2 of LHS int bit width", |
| 1972 | \\export fn entry(x: u8, y: u8) -> u8 { | |
| 2018 | \\export fn entry(x: u8, y: u8) u8 { | |
| 1973 | 2019 | \\ return x << y; |
| 1974 | 2020 | \\} |
| 1975 | 2021 | , |
| ... | ... | @@ -1977,7 +2023,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1977 | 2023 | |
| 1978 | 2024 | cases.add("globally shadowing a primitive type", |
| 1979 | 2025 | \\const u16 = @intType(false, 8); |
| 1980 | \\export fn entry() { | |
| 2026 | \\export fn entry() void { | |
| 1981 | 2027 | \\ const a: u16 = 300; |
| 1982 | 2028 | \\} |
| 1983 | 2029 | , |
| ... | ... | @@ -1989,12 +2035,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1989 | 2035 | \\ b: u32, |
| 1990 | 2036 | \\}; |
| 1991 | 2037 | \\ |
| 1992 | \\export fn entry() { | |
| 2038 | \\export fn entry() void { | |
| 1993 | 2039 | \\ var foo = Foo { .a = 1, .b = 10 }; |
| 1994 | 2040 | \\ bar(&foo.b); |
| 1995 | 2041 | \\} |
| 1996 | 2042 | \\ |
| 1997 | \\fn bar(x: &u32) { | |
| 2043 | \\fn bar(x: &u32) void { | |
| 1998 | 2044 | \\ *x += 1; |
| 1999 | 2045 | \\} |
| 2000 | 2046 | , |
| ... | ... | @@ -2006,20 +2052,20 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2006 | 2052 | \\ b: u32, |
| 2007 | 2053 | \\}; |
| 2008 | 2054 | \\ |
| 2009 | \\export fn entry() { | |
| 2055 | \\export fn entry() void { | |
| 2010 | 2056 | \\ var foo = Foo { .a = 1, .b = 10 }; |
| 2011 | 2057 | \\ foo.b += 1; |
| 2012 | 2058 | \\ bar((&foo.b)[0..1]); |
| 2013 | 2059 | \\} |
| 2014 | 2060 | \\ |
| 2015 | \\fn bar(x: []u32) { | |
| 2061 | \\fn bar(x: []u32) void { | |
| 2016 | 2062 | \\ x[0] += 1; |
| 2017 | 2063 | \\} |
| 2018 | 2064 | , |
| 2019 | 2065 | ".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align(1) u32'"); |
| 2020 | 2066 | |
| 2021 | 2067 | cases.add("increase pointer alignment in @ptrCast", |
| 2022 | \\export fn entry() -> u32 { | |
| 2068 | \\export fn entry() u32 { | |
| 2023 | 2069 | \\ var bytes: [4]u8 = []u8{0x01, 0x02, 0x03, 0x04}; |
| 2024 | 2070 | \\ const ptr = @ptrCast(&u32, &bytes[0]); |
| 2025 | 2071 | \\ return *ptr; |
| ... | ... | @@ -2030,7 +2076,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2030 | 2076 | ".tmp_source.zig:3:27: note: '&u32' has alignment 4"); |
| 2031 | 2077 | |
| 2032 | 2078 | cases.add("increase pointer alignment in slice resize", |
| 2033 | \\export fn entry() -> u32 { | |
| 2079 | \\export fn entry() u32 { | |
| 2034 | 2080 | \\ var bytes = []u8{0x01, 0x02, 0x03, 0x04}; |
| 2035 | 2081 | \\ return ([]u32)(bytes[0..])[0]; |
| 2036 | 2082 | \\} |
| ... | ... | @@ -2040,26 +2086,26 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2040 | 2086 | ".tmp_source.zig:3:19: note: '[]u32' has alignment 4"); |
| 2041 | 2087 | |
| 2042 | 2088 | cases.add("@alignCast expects pointer or slice", |
| 2043 | \\export fn entry() { | |
| 2089 | \\export fn entry() void { | |
| 2044 | 2090 | \\ @alignCast(4, u32(3)); |
| 2045 | 2091 | \\} |
| 2046 | 2092 | , |
| 2047 | 2093 | ".tmp_source.zig:2:22: error: expected pointer or slice, found 'u32'"); |
| 2048 | 2094 | |
| 2049 | 2095 | cases.add("passing an under-aligned function pointer", |
| 2050 | \\export fn entry() { | |
| 2096 | \\export fn entry() void { | |
| 2051 | 2097 | \\ testImplicitlyDecreaseFnAlign(alignedSmall, 1234); |
| 2052 | 2098 | \\} |
| 2053 | \\fn testImplicitlyDecreaseFnAlign(ptr: fn () align(8) -> i32, answer: i32) { | |
| 2099 | \\fn testImplicitlyDecreaseFnAlign(ptr: fn () align(8) i32, answer: i32) void { | |
| 2054 | 2100 | \\ if (ptr() != answer) unreachable; |
| 2055 | 2101 | \\} |
| 2056 | \\fn alignedSmall() align(4) -> i32 { return 1234; } | |
| 2102 | \\fn alignedSmall() align(4) i32 { return 1234; } | |
| 2057 | 2103 | , |
| 2058 | ".tmp_source.zig:2:35: error: expected type 'fn() align(8) -> i32', found 'fn() align(4) -> i32'"); | |
| 2104 | ".tmp_source.zig:2:35: error: expected type 'fn() align(8) i32', found 'fn() align(4) i32'"); | |
| 2059 | 2105 | |
| 2060 | 2106 | cases.add("passing a not-aligned-enough pointer to cmpxchg", |
| 2061 | 2107 | \\const AtomicOrder = @import("builtin").AtomicOrder; |
| 2062 | \\export fn entry() -> bool { | |
| 2108 | \\export fn entry() bool { | |
| 2063 | 2109 | \\ var x: i32 align(1) = 1234; |
| 2064 | 2110 | \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {} |
| 2065 | 2111 | \\ return x == 5678; |
| ... | ... | @@ -2078,7 +2124,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2078 | 2124 | \\comptime { |
| 2079 | 2125 | \\ foo(); |
| 2080 | 2126 | \\} |
| 2081 | \\fn foo() { | |
| 2127 | \\fn foo() void { | |
| 2082 | 2128 | \\ @setEvalBranchQuota(1001); |
| 2083 | 2129 | \\} |
| 2084 | 2130 | , |
| ... | ... | @@ -2088,8 +2134,8 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2088 | 2134 | |
| 2089 | 2135 | cases.add("wrong pointer implicitly casted to pointer to @OpaqueType()", |
| 2090 | 2136 | \\const Derp = @OpaqueType(); |
| 2091 | \\extern fn bar(d: &Derp); | |
| 2092 | \\export fn foo() { | |
| 2137 | \\extern fn bar(d: &Derp) void; | |
| 2138 | \\export fn foo() void { | |
| 2093 | 2139 | \\ const x = u8(1); |
| 2094 | 2140 | \\ bar(@ptrCast(&c_void, &x)); |
| 2095 | 2141 | \\} |
| ... | ... | @@ -2099,7 +2145,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2099 | 2145 | cases.add("non-const variables of things that require const variables", |
| 2100 | 2146 | \\const Opaque = @OpaqueType(); |
| 2101 | 2147 | \\ |
| 2102 | \\export fn entry(opaque: &Opaque) { | |
| 2148 | \\export fn entry(opaque: &Opaque) void { | |
| 2103 | 2149 | \\ var m2 = &2; |
| 2104 | 2150 | \\ const y: u32 = *m2; |
| 2105 | 2151 | \\ |
| ... | ... | @@ -2117,7 +2163,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2117 | 2163 | \\} |
| 2118 | 2164 | \\ |
| 2119 | 2165 | \\const Foo = struct { |
| 2120 | \\ fn bar(self: &const Foo) {} | |
| 2166 | \\ fn bar(self: &const Foo) void {} | |
| 2121 | 2167 | \\}; |
| 2122 | 2168 | , |
| 2123 | 2169 | ".tmp_source.zig:4:4: error: variable of type '&const (integer literal)' must be const or comptime", |
| ... | ... | @@ -2129,11 +2175,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2129 | 2175 | ".tmp_source.zig:12:4: error: variable of type 'Opaque' must be const or comptime", |
| 2130 | 2176 | ".tmp_source.zig:13:4: error: variable of type 'type' must be const or comptime", |
| 2131 | 2177 | ".tmp_source.zig:14:4: error: variable of type '(namespace)' must be const or comptime", |
| 2132 | ".tmp_source.zig:15:4: error: variable of type '(bound fn(&const Foo))' must be const or comptime", | |
| 2178 | ".tmp_source.zig:15:4: error: variable of type '(bound fn(&const Foo) void)' must be const or comptime", | |
| 2133 | 2179 | ".tmp_source.zig:17:4: error: unreachable code"); |
| 2134 | 2180 | |
| 2135 | 2181 | cases.add("wrong types given to atomic order args in cmpxchg", |
| 2136 | \\export fn entry() { | |
| 2182 | \\export fn entry() void { | |
| 2137 | 2183 | \\ var x: i32 = 1234; |
| 2138 | 2184 | \\ while (!@cmpxchg(&x, 1234, 5678, u32(1234), u32(1234))) {} |
| 2139 | 2185 | \\} |
| ... | ... | @@ -2141,7 +2187,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2141 | 2187 | ".tmp_source.zig:3:41: error: expected type 'AtomicOrder', found 'u32'"); |
| 2142 | 2188 | |
| 2143 | 2189 | cases.add("wrong types given to @export", |
| 2144 | \\extern fn entry() { } | |
| 2190 | \\extern fn entry() void { } | |
| 2145 | 2191 | \\comptime { |
| 2146 | 2192 | \\ @export("entry", entry, u32(1234)); |
| 2147 | 2193 | \\} |
| ... | ... | @@ -2166,7 +2212,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2166 | 2212 | \\ }, |
| 2167 | 2213 | \\}; |
| 2168 | 2214 | \\ |
| 2169 | \\export fn entry() { | |
| 2215 | \\export fn entry() void { | |
| 2170 | 2216 | \\ const a = MdNode.Header { |
| 2171 | 2217 | \\ .text = MdText.init(&std.debug.global_allocator), |
| 2172 | 2218 | \\ .weight = HeaderWeight.H1, |
| ... | ... | @@ -2183,24 +2229,24 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2183 | 2229 | ".tmp_source.zig:2:5: error: @setAlignStack outside function"); |
| 2184 | 2230 | |
| 2185 | 2231 | cases.add("@setAlignStack in naked function", |
| 2186 | \\export nakedcc fn entry() { | |
| 2232 | \\export nakedcc fn entry() void { | |
| 2187 | 2233 | \\ @setAlignStack(16); |
| 2188 | 2234 | \\} |
| 2189 | 2235 | , |
| 2190 | 2236 | ".tmp_source.zig:2:5: error: @setAlignStack in naked function"); |
| 2191 | 2237 | |
| 2192 | 2238 | cases.add("@setAlignStack in inline function", |
| 2193 | \\export fn entry() { | |
| 2239 | \\export fn entry() void { | |
| 2194 | 2240 | \\ foo(); |
| 2195 | 2241 | \\} |
| 2196 | \\inline fn foo() { | |
| 2242 | \\inline fn foo() void { | |
| 2197 | 2243 | \\ @setAlignStack(16); |
| 2198 | 2244 | \\} |
| 2199 | 2245 | , |
| 2200 | 2246 | ".tmp_source.zig:5:5: error: @setAlignStack in inline function"); |
| 2201 | 2247 | |
| 2202 | 2248 | cases.add("@setAlignStack set twice", |
| 2203 | \\export fn entry() { | |
| 2249 | \\export fn entry() void { | |
| 2204 | 2250 | \\ @setAlignStack(16); |
| 2205 | 2251 | \\ @setAlignStack(16); |
| 2206 | 2252 | \\} |
| ... | ... | @@ -2209,7 +2255,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2209 | 2255 | ".tmp_source.zig:2:5: note: first set here"); |
| 2210 | 2256 | |
| 2211 | 2257 | cases.add("@setAlignStack too big", |
| 2212 | \\export fn entry() { | |
| 2258 | \\export fn entry() void { | |
| 2213 | 2259 | \\ @setAlignStack(511 + 1); |
| 2214 | 2260 | \\} |
| 2215 | 2261 | , |
| ... | ... | @@ -2218,14 +2264,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2218 | 2264 | cases.add("storing runtime value in compile time variable then using it", |
| 2219 | 2265 | \\const Mode = @import("builtin").Mode; |
| 2220 | 2266 | \\ |
| 2221 | \\fn Free(comptime filename: []const u8) -> TestCase { | |
| 2267 | \\fn Free(comptime filename: []const u8) TestCase { | |
| 2222 | 2268 | \\ return TestCase { |
| 2223 | 2269 | \\ .filename = filename, |
| 2224 | 2270 | \\ .problem_type = ProblemType.Free, |
| 2225 | 2271 | \\ }; |
| 2226 | 2272 | \\} |
| 2227 | 2273 | \\ |
| 2228 | \\fn LibC(comptime filename: []const u8) -> TestCase { | |
| 2274 | \\fn LibC(comptime filename: []const u8) TestCase { | |
| 2229 | 2275 | \\ return TestCase { |
| 2230 | 2276 | \\ .filename = filename, |
| 2231 | 2277 | \\ .problem_type = ProblemType.LinkLibC, |
| ... | ... | @@ -2242,7 +2288,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2242 | 2288 | \\ LinkLibC, |
| 2243 | 2289 | \\}; |
| 2244 | 2290 | \\ |
| 2245 | \\export fn entry() { | |
| 2291 | \\export fn entry() void { | |
| 2246 | 2292 | \\ const tests = []TestCase { |
| 2247 | 2293 | \\ Free("001"), |
| 2248 | 2294 | \\ Free("002"), |
| ... | ... | @@ -2263,34 +2309,34 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2263 | 2309 | cases.add("field access of opaque type", |
| 2264 | 2310 | \\const MyType = @OpaqueType(); |
| 2265 | 2311 | \\ |
| 2266 | \\export fn entry() -> bool { | |
| 2312 | \\export fn entry() bool { | |
| 2267 | 2313 | \\ var x: i32 = 1; |
| 2268 | 2314 | \\ return bar(@ptrCast(&MyType, &x)); |
| 2269 | 2315 | \\} |
| 2270 | 2316 | \\ |
| 2271 | \\fn bar(x: &MyType) -> bool { | |
| 2317 | \\fn bar(x: &MyType) bool { | |
| 2272 | 2318 | \\ return x.blah; |
| 2273 | 2319 | \\} |
| 2274 | 2320 | , |
| 2275 | 2321 | ".tmp_source.zig:9:13: error: type '&MyType' does not support field access"); |
| 2276 | 2322 | |
| 2277 | 2323 | cases.add("carriage return special case", |
| 2278 | "fn test() -> bool {\r\n" ++ | |
| 2324 | "fn test() bool {\r\n" ++ | |
| 2279 | 2325 | " true\r\n" ++ |
| 2280 | 2326 | "}\r\n" |
| 2281 | 2327 | , |
| 2282 | ".tmp_source.zig:1:20: error: invalid carriage return, only '\\n' line endings are supported"); | |
| 2328 | ".tmp_source.zig:1:17: error: invalid carriage return, only '\\n' line endings are supported"); | |
| 2283 | 2329 | |
| 2284 | 2330 | cases.add("non-printable invalid character", |
| 2285 | 2331 | "\xff\xfe" ++ |
| 2286 | \\fn test() -> bool {\r | |
| 2332 | \\fn test() bool {\r | |
| 2287 | 2333 | \\ true\r |
| 2288 | 2334 | \\} |
| 2289 | 2335 | , |
| 2290 | 2336 | ".tmp_source.zig:1:1: error: invalid character: '\\xff'"); |
| 2291 | 2337 | |
| 2292 | 2338 | cases.add("non-printable invalid character with escape alternative", |
| 2293 | "fn test() -> bool {\n" ++ | |
| 2339 | "fn test() bool {\n" ++ | |
| 2294 | 2340 | "\ttrue\n" ++ |
| 2295 | 2341 | "}\n" |
| 2296 | 2342 | , |
| ... | ... | @@ -2307,9 +2353,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2307 | 2353 | \\comptime { |
| 2308 | 2354 | \\ _ = @ArgType(@typeOf(add), 2); |
| 2309 | 2355 | \\} |
| 2310 | \\fn add(a: i32, b: i32) -> i32 { return a + b; } | |
| 2356 | \\fn add(a: i32, b: i32) i32 { return a + b; } | |
| 2311 | 2357 | , |
| 2312 | ".tmp_source.zig:2:32: error: arg index 2 out of bounds; 'fn(i32, i32) -> i32' has 2 arguments"); | |
| 2358 | ".tmp_source.zig:2:32: error: arg index 2 out of bounds; 'fn(i32, i32) i32' has 2 arguments"); | |
| 2313 | 2359 | |
| 2314 | 2360 | cases.add("@memberType on unsupported type", |
| 2315 | 2361 | \\comptime { |
| ... | ... | @@ -2374,17 +2420,17 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2374 | 2420 | ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); |
| 2375 | 2421 | |
| 2376 | 2422 | cases.add("calling var args extern function, passing array instead of pointer", |
| 2377 | \\export fn entry() { | |
| 2423 | \\export fn entry() void { | |
| 2378 | 2424 | \\ foo("hello"); |
| 2379 | 2425 | \\} |
| 2380 | \\pub extern fn foo(format: &const u8, ...); | |
| 2426 | \\pub extern fn foo(format: &const u8, ...) void; | |
| 2381 | 2427 | , |
| 2382 | 2428 | ".tmp_source.zig:2:9: error: expected type '&const u8', found '[5]u8'"); |
| 2383 | 2429 | |
| 2384 | 2430 | cases.add("constant inside comptime function has compile error", |
| 2385 | 2431 | \\const ContextAllocator = MemoryPool(usize); |
| 2386 | 2432 | \\ |
| 2387 | \\pub fn MemoryPool(comptime T: type) -> type { | |
| 2433 | \\pub fn MemoryPool(comptime T: type) type { | |
| 2388 | 2434 | \\ const free_list_t = @compileError("aoeu"); |
| 2389 | 2435 | \\ |
| 2390 | 2436 | \\ return struct { |
| ... | ... | @@ -2392,7 +2438,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2392 | 2438 | \\ }; |
| 2393 | 2439 | \\} |
| 2394 | 2440 | \\ |
| 2395 | \\export fn entry() { | |
| 2441 | \\export fn entry() void { | |
| 2396 | 2442 | \\ var allocator: ContextAllocator = undefined; |
| 2397 | 2443 | \\} |
| 2398 | 2444 | , |
| ... | ... | @@ -2409,7 +2455,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2409 | 2455 | \\ Five, |
| 2410 | 2456 | \\}; |
| 2411 | 2457 | \\ |
| 2412 | \\export fn entry() { | |
| 2458 | \\export fn entry() void { | |
| 2413 | 2459 | \\ var x = Small.One; |
| 2414 | 2460 | \\} |
| 2415 | 2461 | , |
| ... | ... | @@ -2422,7 +2468,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2422 | 2468 | \\ Three, |
| 2423 | 2469 | \\}; |
| 2424 | 2470 | \\ |
| 2425 | \\export fn entry() { | |
| 2471 | \\export fn entry() void { | |
| 2426 | 2472 | \\ var x = Small.One; |
| 2427 | 2473 | \\} |
| 2428 | 2474 | , |
| ... | ... | @@ -2436,7 +2482,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2436 | 2482 | \\ Four, |
| 2437 | 2483 | \\}; |
| 2438 | 2484 | \\ |
| 2439 | \\export fn entry() { | |
| 2485 | \\export fn entry() void { | |
| 2440 | 2486 | \\ var x: u2 = Small.Two; |
| 2441 | 2487 | \\} |
| 2442 | 2488 | , |
| ... | ... | @@ -2450,7 +2496,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2450 | 2496 | \\ Four, |
| 2451 | 2497 | \\}; |
| 2452 | 2498 | \\ |
| 2453 | \\export fn entry() { | |
| 2499 | \\export fn entry() void { | |
| 2454 | 2500 | \\ var x = u3(Small.Two); |
| 2455 | 2501 | \\} |
| 2456 | 2502 | , |
| ... | ... | @@ -2464,7 +2510,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2464 | 2510 | \\ Four, |
| 2465 | 2511 | \\}; |
| 2466 | 2512 | \\ |
| 2467 | \\export fn entry() { | |
| 2513 | \\export fn entry() void { | |
| 2468 | 2514 | \\ var y = u3(3); |
| 2469 | 2515 | \\ var x = Small(y); |
| 2470 | 2516 | \\} |
| ... | ... | @@ -2479,7 +2525,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2479 | 2525 | \\ Four, |
| 2480 | 2526 | \\}; |
| 2481 | 2527 | \\ |
| 2482 | \\export fn entry() { | |
| 2528 | \\export fn entry() void { | |
| 2483 | 2529 | \\ var y = Small.Two; |
| 2484 | 2530 | \\} |
| 2485 | 2531 | , |
| ... | ... | @@ -2489,7 +2535,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2489 | 2535 | \\const MultipleChoice = struct { |
| 2490 | 2536 | \\ A: i32 = 20, |
| 2491 | 2537 | \\}; |
| 2492 | \\export fn entry() { | |
| 2538 | \\export fn entry() void { | |
| 2493 | 2539 | \\ var x: MultipleChoice = undefined; |
| 2494 | 2540 | \\} |
| 2495 | 2541 | , |
| ... | ... | @@ -2499,7 +2545,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2499 | 2545 | \\const MultipleChoice = union { |
| 2500 | 2546 | \\ A: i32 = 20, |
| 2501 | 2547 | \\}; |
| 2502 | \\export fn entry() { | |
| 2548 | \\export fn entry() void { | |
| 2503 | 2549 | \\ var x: MultipleChoice = undefined; |
| 2504 | 2550 | \\} |
| 2505 | 2551 | , |
| ... | ... | @@ -2508,7 +2554,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2508 | 2554 | |
| 2509 | 2555 | cases.add("enum with 0 fields", |
| 2510 | 2556 | \\const Foo = enum {}; |
| 2511 | \\export fn entry() -> usize { | |
| 2557 | \\export fn entry() usize { | |
| 2512 | 2558 | \\ return @sizeOf(Foo); |
| 2513 | 2559 | \\} |
| 2514 | 2560 | , |
| ... | ... | @@ -2516,7 +2562,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2516 | 2562 | |
| 2517 | 2563 | cases.add("union with 0 fields", |
| 2518 | 2564 | \\const Foo = union {}; |
| 2519 | \\export fn entry() -> usize { | |
| 2565 | \\export fn entry() usize { | |
| 2520 | 2566 | \\ return @sizeOf(Foo); |
| 2521 | 2567 | \\} |
| 2522 | 2568 | , |
| ... | ... | @@ -2530,7 +2576,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2530 | 2576 | \\ D = 1000, |
| 2531 | 2577 | \\ E = 60, |
| 2532 | 2578 | \\}; |
| 2533 | \\export fn entry() { | |
| 2579 | \\export fn entry() void { | |
| 2534 | 2580 | \\ var x = MultipleChoice.C; |
| 2535 | 2581 | \\} |
| 2536 | 2582 | , |
| ... | ... | @@ -2547,7 +2593,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2547 | 2593 | \\ A: i32, |
| 2548 | 2594 | \\ B: f64, |
| 2549 | 2595 | \\}; |
| 2550 | \\export fn entry() -> usize { | |
| 2596 | \\export fn entry() usize { | |
| 2551 | 2597 | \\ return @sizeOf(Payload); |
| 2552 | 2598 | \\} |
| 2553 | 2599 | , |
| ... | ... | @@ -2558,7 +2604,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2558 | 2604 | \\const Foo = union { |
| 2559 | 2605 | \\ A: i32, |
| 2560 | 2606 | \\}; |
| 2561 | \\export fn entry() { | |
| 2607 | \\export fn entry() void { | |
| 2562 | 2608 | \\ const x = @TagType(Foo); |
| 2563 | 2609 | \\} |
| 2564 | 2610 | , |
| ... | ... | @@ -2569,7 +2615,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2569 | 2615 | \\const Foo = union(enum(f32)) { |
| 2570 | 2616 | \\ A: i32, |
| 2571 | 2617 | \\}; |
| 2572 | \\export fn entry() { | |
| 2618 | \\export fn entry() void { | |
| 2573 | 2619 | \\ const x = @TagType(Foo); |
| 2574 | 2620 | \\} |
| 2575 | 2621 | , |
| ... | ... | @@ -2579,7 +2625,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2579 | 2625 | \\const Foo = union(u32) { |
| 2580 | 2626 | \\ A: i32, |
| 2581 | 2627 | \\}; |
| 2582 | \\export fn entry() { | |
| 2628 | \\export fn entry() void { | |
| 2583 | 2629 | \\ const x = @TagType(Foo); |
| 2584 | 2630 | \\} |
| 2585 | 2631 | , |
| ... | ... | @@ -2593,7 +2639,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2593 | 2639 | \\ D = 1000, |
| 2594 | 2640 | \\ E = 60, |
| 2595 | 2641 | \\}; |
| 2596 | \\export fn entry() { | |
| 2642 | \\export fn entry() void { | |
| 2597 | 2643 | \\ var x = MultipleChoice { .C = {} }; |
| 2598 | 2644 | \\} |
| 2599 | 2645 | , |
| ... | ... | @@ -2612,7 +2658,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2612 | 2658 | \\ C: bool, |
| 2613 | 2659 | \\ D: bool, |
| 2614 | 2660 | \\}; |
| 2615 | \\export fn entry() { | |
| 2661 | \\export fn entry() void { | |
| 2616 | 2662 | \\ var a = Payload {.A = 1234}; |
| 2617 | 2663 | \\} |
| 2618 | 2664 | , |
| ... | ... | @@ -2625,7 +2671,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2625 | 2671 | \\ B, |
| 2626 | 2672 | \\ C, |
| 2627 | 2673 | \\}; |
| 2628 | \\export fn entry() { | |
| 2674 | \\export fn entry() void { | |
| 2629 | 2675 | \\ var b = Letter.B; |
| 2630 | 2676 | \\} |
| 2631 | 2677 | , |
| ... | ... | @@ -2636,7 +2682,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2636 | 2682 | \\const Letter = struct { |
| 2637 | 2683 | \\ A, |
| 2638 | 2684 | \\}; |
| 2639 | \\export fn entry() { | |
| 2685 | \\export fn entry() void { | |
| 2640 | 2686 | \\ var a = Letter { .A = {} }; |
| 2641 | 2687 | \\} |
| 2642 | 2688 | , |
| ... | ... | @@ -2646,7 +2692,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2646 | 2692 | \\const Letter = extern union { |
| 2647 | 2693 | \\ A, |
| 2648 | 2694 | \\}; |
| 2649 | \\export fn entry() { | |
| 2695 | \\export fn entry() void { | |
| 2650 | 2696 | \\ var a = Letter { .A = {} }; |
| 2651 | 2697 | \\} |
| 2652 | 2698 | , |
| ... | ... | @@ -2663,7 +2709,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2663 | 2709 | \\ B: f64, |
| 2664 | 2710 | \\ C: bool, |
| 2665 | 2711 | \\}; |
| 2666 | \\export fn entry() { | |
| 2712 | \\export fn entry() void { | |
| 2667 | 2713 | \\ var a = Payload { .A = 1234 }; |
| 2668 | 2714 | \\} |
| 2669 | 2715 | , |
| ... | ... | @@ -2680,7 +2726,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2680 | 2726 | \\ B: f64, |
| 2681 | 2727 | \\ C: bool, |
| 2682 | 2728 | \\}; |
| 2683 | \\export fn entry() { | |
| 2729 | \\export fn entry() void { | |
| 2684 | 2730 | \\ var a = Payload { .A = 1234 }; |
| 2685 | 2731 | \\} |
| 2686 | 2732 | , |
| ... | ... | @@ -2692,11 +2738,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2692 | 2738 | \\ B: f64, |
| 2693 | 2739 | \\ C: bool, |
| 2694 | 2740 | \\}; |
| 2695 | \\export fn entry() { | |
| 2741 | \\export fn entry() void { | |
| 2696 | 2742 | \\ const a = Payload { .A = 1234 }; |
| 2697 | 2743 | \\ foo(a); |
| 2698 | 2744 | \\} |
| 2699 | \\fn foo(a: &const Payload) { | |
| 2745 | \\fn foo(a: &const Payload) void { | |
| 2700 | 2746 | \\ switch (*a) { |
| 2701 | 2747 | \\ Payload.A => {}, |
| 2702 | 2748 | \\ else => unreachable, |
| ... | ... | @@ -2711,7 +2757,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2711 | 2757 | \\ A = 10, |
| 2712 | 2758 | \\ B = 11, |
| 2713 | 2759 | \\}; |
| 2714 | \\export fn entry() { | |
| 2760 | \\export fn entry() void { | |
| 2715 | 2761 | \\ var x = Foo(0); |
| 2716 | 2762 | \\} |
| 2717 | 2763 | , |
| ... | ... | @@ -2725,7 +2771,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2725 | 2771 | \\ B, |
| 2726 | 2772 | \\ C, |
| 2727 | 2773 | \\}; |
| 2728 | \\export fn entry() { | |
| 2774 | \\export fn entry() void { | |
| 2729 | 2775 | \\ var x: Value = Letter.A; |
| 2730 | 2776 | \\} |
| 2731 | 2777 | , |
| ... | ... | @@ -2739,10 +2785,10 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2739 | 2785 | \\ B, |
| 2740 | 2786 | \\ C, |
| 2741 | 2787 | \\}; |
| 2742 | \\export fn entry() { | |
| 2788 | \\export fn entry() void { | |
| 2743 | 2789 | \\ foo(Letter.A); |
| 2744 | 2790 | \\} |
| 2745 | \\fn foo(l: Letter) { | |
| 2791 | \\fn foo(l: Letter) void { | |
| 2746 | 2792 | \\ var x: Value = l; |
| 2747 | 2793 | \\} |
| 2748 | 2794 | , |
test/debug_safety.zig deleted-286| ... | ... | @@ -1,286 +0,0 @@ |
| 1 | const tests = @import("tests.zig"); | |
| 2 | ||
| 3 | pub fn addCases(cases: &tests.CompareOutputContext) { | |
| 4 | cases.addDebugSafety("calling panic", | |
| 5 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 6 | \\ @import("std").os.exit(126); | |
| 7 | \\} | |
| 8 | \\pub fn main() -> %void { | |
| 9 | \\ @panic("oh no"); | |
| 10 | \\} | |
| 11 | ); | |
| 12 | ||
| 13 | cases.addDebugSafety("out of bounds slice access", | |
| 14 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 15 | \\ @import("std").os.exit(126); | |
| 16 | \\} | |
| 17 | \\pub fn main() -> %void { | |
| 18 | \\ const a = []i32{1, 2, 3, 4}; | |
| 19 | \\ baz(bar(a)); | |
| 20 | \\} | |
| 21 | \\fn bar(a: []const i32) -> i32 { | |
| 22 | \\ return a[4]; | |
| 23 | \\} | |
| 24 | \\fn baz(a: i32) { } | |
| 25 | ); | |
| 26 | ||
| 27 | cases.addDebugSafety("integer addition overflow", | |
| 28 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 29 | \\ @import("std").os.exit(126); | |
| 30 | \\} | |
| 31 | \\error Whatever; | |
| 32 | \\pub fn main() -> %void { | |
| 33 | \\ const x = add(65530, 10); | |
| 34 | \\ if (x == 0) return error.Whatever; | |
| 35 | \\} | |
| 36 | \\fn add(a: u16, b: u16) -> u16 { | |
| 37 | \\ return a + b; | |
| 38 | \\} | |
| 39 | ); | |
| 40 | ||
| 41 | cases.addDebugSafety("integer subtraction overflow", | |
| 42 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 43 | \\ @import("std").os.exit(126); | |
| 44 | \\} | |
| 45 | \\error Whatever; | |
| 46 | \\pub fn main() -> %void { | |
| 47 | \\ const x = sub(10, 20); | |
| 48 | \\ if (x == 0) return error.Whatever; | |
| 49 | \\} | |
| 50 | \\fn sub(a: u16, b: u16) -> u16 { | |
| 51 | \\ return a - b; | |
| 52 | \\} | |
| 53 | ); | |
| 54 | ||
| 55 | cases.addDebugSafety("integer multiplication overflow", | |
| 56 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 57 | \\ @import("std").os.exit(126); | |
| 58 | \\} | |
| 59 | \\error Whatever; | |
| 60 | \\pub fn main() -> %void { | |
| 61 | \\ const x = mul(300, 6000); | |
| 62 | \\ if (x == 0) return error.Whatever; | |
| 63 | \\} | |
| 64 | \\fn mul(a: u16, b: u16) -> u16 { | |
| 65 | \\ return a * b; | |
| 66 | \\} | |
| 67 | ); | |
| 68 | ||
| 69 | cases.addDebugSafety("integer negation overflow", | |
| 70 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 71 | \\ @import("std").os.exit(126); | |
| 72 | \\} | |
| 73 | \\error Whatever; | |
| 74 | \\pub fn main() -> %void { | |
| 75 | \\ const x = neg(-32768); | |
| 76 | \\ if (x == 32767) return error.Whatever; | |
| 77 | \\} | |
| 78 | \\fn neg(a: i16) -> i16 { | |
| 79 | \\ return -a; | |
| 80 | \\} | |
| 81 | ); | |
| 82 | ||
| 83 | cases.addDebugSafety("signed integer division overflow", | |
| 84 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 85 | \\ @import("std").os.exit(126); | |
| 86 | \\} | |
| 87 | \\error Whatever; | |
| 88 | \\pub fn main() -> %void { | |
| 89 | \\ const x = div(-32768, -1); | |
| 90 | \\ if (x == 32767) return error.Whatever; | |
| 91 | \\} | |
| 92 | \\fn div(a: i16, b: i16) -> i16 { | |
| 93 | \\ return @divTrunc(a, b); | |
| 94 | \\} | |
| 95 | ); | |
| 96 | ||
| 97 | cases.addDebugSafety("signed shift left overflow", | |
| 98 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 99 | \\ @import("std").os.exit(126); | |
| 100 | \\} | |
| 101 | \\error Whatever; | |
| 102 | \\pub fn main() -> %void { | |
| 103 | \\ const x = shl(-16385, 1); | |
| 104 | \\ if (x == 0) return error.Whatever; | |
| 105 | \\} | |
| 106 | \\fn shl(a: i16, b: u4) -> i16 { | |
| 107 | \\ return @shlExact(a, b); | |
| 108 | \\} | |
| 109 | ); | |
| 110 | ||
| 111 | cases.addDebugSafety("unsigned shift left overflow", | |
| 112 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 113 | \\ @import("std").os.exit(126); | |
| 114 | \\} | |
| 115 | \\error Whatever; | |
| 116 | \\pub fn main() -> %void { | |
| 117 | \\ const x = shl(0b0010111111111111, 3); | |
| 118 | \\ if (x == 0) return error.Whatever; | |
| 119 | \\} | |
| 120 | \\fn shl(a: u16, b: u4) -> u16 { | |
| 121 | \\ return @shlExact(a, b); | |
| 122 | \\} | |
| 123 | ); | |
| 124 | ||
| 125 | cases.addDebugSafety("signed shift right overflow", | |
| 126 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 127 | \\ @import("std").os.exit(126); | |
| 128 | \\} | |
| 129 | \\error Whatever; | |
| 130 | \\pub fn main() -> %void { | |
| 131 | \\ const x = shr(-16385, 1); | |
| 132 | \\ if (x == 0) return error.Whatever; | |
| 133 | \\} | |
| 134 | \\fn shr(a: i16, b: u4) -> i16 { | |
| 135 | \\ return @shrExact(a, b); | |
| 136 | \\} | |
| 137 | ); | |
| 138 | ||
| 139 | cases.addDebugSafety("unsigned shift right overflow", | |
| 140 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 141 | \\ @import("std").os.exit(126); | |
| 142 | \\} | |
| 143 | \\error Whatever; | |
| 144 | \\pub fn main() -> %void { | |
| 145 | \\ const x = shr(0b0010111111111111, 3); | |
| 146 | \\ if (x == 0) return error.Whatever; | |
| 147 | \\} | |
| 148 | \\fn shr(a: u16, b: u4) -> u16 { | |
| 149 | \\ return @shrExact(a, b); | |
| 150 | \\} | |
| 151 | ); | |
| 152 | ||
| 153 | cases.addDebugSafety("integer division by zero", | |
| 154 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 155 | \\ @import("std").os.exit(126); | |
| 156 | \\} | |
| 157 | \\error Whatever; | |
| 158 | \\pub fn main() -> %void { | |
| 159 | \\ const x = div0(999, 0); | |
| 160 | \\} | |
| 161 | \\fn div0(a: i32, b: i32) -> i32 { | |
| 162 | \\ return @divTrunc(a, b); | |
| 163 | \\} | |
| 164 | ); | |
| 165 | ||
| 166 | cases.addDebugSafety("exact division failure", | |
| 167 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 168 | \\ @import("std").os.exit(126); | |
| 169 | \\} | |
| 170 | \\error Whatever; | |
| 171 | \\pub fn main() -> %void { | |
| 172 | \\ const x = divExact(10, 3); | |
| 173 | \\ if (x == 0) return error.Whatever; | |
| 174 | \\} | |
| 175 | \\fn divExact(a: i32, b: i32) -> i32 { | |
| 176 | \\ return @divExact(a, b); | |
| 177 | \\} | |
| 178 | ); | |
| 179 | ||
| 180 | cases.addDebugSafety("cast []u8 to bigger slice of wrong size", | |
| 181 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 182 | \\ @import("std").os.exit(126); | |
| 183 | \\} | |
| 184 | \\error Whatever; | |
| 185 | \\pub fn main() -> %void { | |
| 186 | \\ const x = widenSlice([]u8{1, 2, 3, 4, 5}); | |
| 187 | \\ if (x.len == 0) return error.Whatever; | |
| 188 | \\} | |
| 189 | \\fn widenSlice(slice: []align(1) const u8) -> []align(1) const i32 { | |
| 190 | \\ return ([]align(1) const i32)(slice); | |
| 191 | \\} | |
| 192 | ); | |
| 193 | ||
| 194 | cases.addDebugSafety("value does not fit in shortening cast", | |
| 195 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 196 | \\ @import("std").os.exit(126); | |
| 197 | \\} | |
| 198 | \\error Whatever; | |
| 199 | \\pub fn main() -> %void { | |
| 200 | \\ const x = shorten_cast(200); | |
| 201 | \\ if (x == 0) return error.Whatever; | |
| 202 | \\} | |
| 203 | \\fn shorten_cast(x: i32) -> i8 { | |
| 204 | \\ return i8(x); | |
| 205 | \\} | |
| 206 | ); | |
| 207 | ||
| 208 | cases.addDebugSafety("signed integer not fitting in cast to unsigned integer", | |
| 209 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 210 | \\ @import("std").os.exit(126); | |
| 211 | \\} | |
| 212 | \\error Whatever; | |
| 213 | \\pub fn main() -> %void { | |
| 214 | \\ const x = unsigned_cast(-10); | |
| 215 | \\ if (x == 0) return error.Whatever; | |
| 216 | \\} | |
| 217 | \\fn unsigned_cast(x: i32) -> u32 { | |
| 218 | \\ return u32(x); | |
| 219 | \\} | |
| 220 | ); | |
| 221 | ||
| 222 | cases.addDebugSafety("unwrap error", | |
| 223 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 224 | \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { | |
| 225 | \\ @import("std").os.exit(126); // good | |
| 226 | \\ } | |
| 227 | \\ @import("std").os.exit(0); // test failed | |
| 228 | \\} | |
| 229 | \\error Whatever; | |
| 230 | \\pub fn main() -> %void { | |
| 231 | \\ bar() catch unreachable; | |
| 232 | \\} | |
| 233 | \\fn bar() -> %void { | |
| 234 | \\ return error.Whatever; | |
| 235 | \\} | |
| 236 | ); | |
| 237 | ||
| 238 | cases.addDebugSafety("cast integer to error and no code matches", | |
| 239 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 240 | \\ @import("std").os.exit(126); | |
| 241 | \\} | |
| 242 | \\pub fn main() -> %void { | |
| 243 | \\ _ = bar(9999); | |
| 244 | \\} | |
| 245 | \\fn bar(x: u32) -> error { | |
| 246 | \\ return error(x); | |
| 247 | \\} | |
| 248 | ); | |
| 249 | ||
| 250 | cases.addDebugSafety("@alignCast misaligned", | |
| 251 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 252 | \\ @import("std").os.exit(126); | |
| 253 | \\} | |
| 254 | \\error Wrong; | |
| 255 | \\pub fn main() -> %void { | |
| 256 | \\ var array align(4) = []u32{0x11111111, 0x11111111}; | |
| 257 | \\ const bytes = ([]u8)(array[0..]); | |
| 258 | \\ if (foo(bytes) != 0x11111111) return error.Wrong; | |
| 259 | \\} | |
| 260 | \\fn foo(bytes: []u8) -> u32 { | |
| 261 | \\ const slice4 = bytes[1..5]; | |
| 262 | \\ const int_slice = ([]u32)(@alignCast(4, slice4)); | |
| 263 | \\ return int_slice[0]; | |
| 264 | \\} | |
| 265 | ); | |
| 266 | ||
| 267 | cases.addDebugSafety("bad union field access", | |
| 268 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { | |
| 269 | \\ @import("std").os.exit(126); | |
| 270 | \\} | |
| 271 | \\ | |
| 272 | \\const Foo = union { | |
| 273 | \\ float: f32, | |
| 274 | \\ int: u32, | |
| 275 | \\}; | |
| 276 | \\ | |
| 277 | \\pub fn main() -> %void { | |
| 278 | \\ var f = Foo { .int = 42 }; | |
| 279 | \\ bar(&f); | |
| 280 | \\} | |
| 281 | \\ | |
| 282 | \\fn bar(f: &Foo) { | |
| 283 | \\ f.float = 12.34; | |
| 284 | \\} | |
| 285 | ); | |
| 286 | } |
test/gen_h.zig created+69| ... | ... | @@ -0,0 +1,69 @@ |
| 1 | const tests = @import("tests.zig"); | |
| 2 | ||
| 3 | pub fn addCases(cases: &tests.GenHContext) void { | |
| 4 | cases.add("declare enum", | |
| 5 | \\const Foo = extern enum { A, B, C }; | |
| 6 | \\export fn entry(foo: Foo) void { } | |
| 7 | , | |
| 8 | \\enum Foo { | |
| 9 | \\ A = 0, | |
| 10 | \\ B = 1, | |
| 11 | \\ C = 2 | |
| 12 | \\}; | |
| 13 | \\ | |
| 14 | \\TEST_EXPORT void entry(enum Foo foo); | |
| 15 | \\ | |
| 16 | ); | |
| 17 | ||
| 18 | cases.add("declare struct", | |
| 19 | \\const Foo = extern struct { | |
| 20 | \\ A: i32, | |
| 21 | \\ B: f32, | |
| 22 | \\ C: bool, | |
| 23 | \\}; | |
| 24 | \\export fn entry(foo: Foo) void { } | |
| 25 | , | |
| 26 | \\struct Foo { | |
| 27 | \\ int32_t A; | |
| 28 | \\ float B; | |
| 29 | \\ bool C; | |
| 30 | \\}; | |
| 31 | \\ | |
| 32 | \\TEST_EXPORT void entry(struct Foo foo); | |
| 33 | \\ | |
| 34 | ); | |
| 35 | ||
| 36 | cases.add("declare union", | |
| 37 | \\const Foo = extern union { | |
| 38 | \\ A: i32, | |
| 39 | \\ B: f32, | |
| 40 | \\ C: bool, | |
| 41 | \\}; | |
| 42 | \\export fn entry(foo: Foo) void { } | |
| 43 | , | |
| 44 | \\union Foo { | |
| 45 | \\ int32_t A; | |
| 46 | \\ float B; | |
| 47 | \\ bool C; | |
| 48 | \\}; | |
| 49 | \\ | |
| 50 | \\TEST_EXPORT void entry(union Foo foo); | |
| 51 | \\ | |
| 52 | ); | |
| 53 | ||
| 54 | cases.add("array field-type", | |
| 55 | \\const Foo = extern struct { | |
| 56 | \\ A: [2]i32, | |
| 57 | \\ B: [4]&u32, | |
| 58 | \\}; | |
| 59 | \\export fn entry(foo: Foo, bar: [3]u8) void { } | |
| 60 | , | |
| 61 | \\struct Foo { | |
| 62 | \\ int32_t A[2]; | |
| 63 | \\ uint32_t * B[4]; | |
| 64 | \\}; | |
| 65 | \\ | |
| 66 | \\TEST_EXPORT void entry(struct Foo foo, uint8_t bar[]); | |
| 67 | \\ | |
| 68 | ); | |
| 69 | } |
test/runtime_safety.zig created+286| ... | ... | @@ -0,0 +1,286 @@ |
| 1 | const tests = @import("tests.zig"); | |
| 2 | ||
| 3 | pub fn addCases(cases: &tests.CompareOutputContext) void { | |
| 4 | cases.addRuntimeSafety("calling panic", | |
| 5 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 6 | \\ @import("std").os.exit(126); | |
| 7 | \\} | |
| 8 | \\pub fn main() %void { | |
| 9 | \\ @panic("oh no"); | |
| 10 | \\} | |
| 11 | ); | |
| 12 | ||
| 13 | cases.addRuntimeSafety("out of bounds slice access", | |
| 14 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 15 | \\ @import("std").os.exit(126); | |
| 16 | \\} | |
| 17 | \\pub fn main() %void { | |
| 18 | \\ const a = []i32{1, 2, 3, 4}; | |
| 19 | \\ baz(bar(a)); | |
| 20 | \\} | |
| 21 | \\fn bar(a: []const i32) i32 { | |
| 22 | \\ return a[4]; | |
| 23 | \\} | |
| 24 | \\fn baz(a: i32) void { } | |
| 25 | ); | |
| 26 | ||
| 27 | cases.addRuntimeSafety("integer addition overflow", | |
| 28 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 29 | \\ @import("std").os.exit(126); | |
| 30 | \\} | |
| 31 | \\error Whatever; | |
| 32 | \\pub fn main() %void { | |
| 33 | \\ const x = add(65530, 10); | |
| 34 | \\ if (x == 0) return error.Whatever; | |
| 35 | \\} | |
| 36 | \\fn add(a: u16, b: u16) u16 { | |
| 37 | \\ return a + b; | |
| 38 | \\} | |
| 39 | ); | |
| 40 | ||
| 41 | cases.addRuntimeSafety("integer subtraction overflow", | |
| 42 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 43 | \\ @import("std").os.exit(126); | |
| 44 | \\} | |
| 45 | \\error Whatever; | |
| 46 | \\pub fn main() %void { | |
| 47 | \\ const x = sub(10, 20); | |
| 48 | \\ if (x == 0) return error.Whatever; | |
| 49 | \\} | |
| 50 | \\fn sub(a: u16, b: u16) u16 { | |
| 51 | \\ return a - b; | |
| 52 | \\} | |
| 53 | ); | |
| 54 | ||
| 55 | cases.addRuntimeSafety("integer multiplication overflow", | |
| 56 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 57 | \\ @import("std").os.exit(126); | |
| 58 | \\} | |
| 59 | \\error Whatever; | |
| 60 | \\pub fn main() %void { | |
| 61 | \\ const x = mul(300, 6000); | |
| 62 | \\ if (x == 0) return error.Whatever; | |
| 63 | \\} | |
| 64 | \\fn mul(a: u16, b: u16) u16 { | |
| 65 | \\ return a * b; | |
| 66 | \\} | |
| 67 | ); | |
| 68 | ||
| 69 | cases.addRuntimeSafety("integer negation overflow", | |
| 70 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 71 | \\ @import("std").os.exit(126); | |
| 72 | \\} | |
| 73 | \\error Whatever; | |
| 74 | \\pub fn main() %void { | |
| 75 | \\ const x = neg(-32768); | |
| 76 | \\ if (x == 32767) return error.Whatever; | |
| 77 | \\} | |
| 78 | \\fn neg(a: i16) i16 { | |
| 79 | \\ return -a; | |
| 80 | \\} | |
| 81 | ); | |
| 82 | ||
| 83 | cases.addRuntimeSafety("signed integer division overflow", | |
| 84 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 85 | \\ @import("std").os.exit(126); | |
| 86 | \\} | |
| 87 | \\error Whatever; | |
| 88 | \\pub fn main() %void { | |
| 89 | \\ const x = div(-32768, -1); | |
| 90 | \\ if (x == 32767) return error.Whatever; | |
| 91 | \\} | |
| 92 | \\fn div(a: i16, b: i16) i16 { | |
| 93 | \\ return @divTrunc(a, b); | |
| 94 | \\} | |
| 95 | ); | |
| 96 | ||
| 97 | cases.addRuntimeSafety("signed shift left overflow", | |
| 98 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 99 | \\ @import("std").os.exit(126); | |
| 100 | \\} | |
| 101 | \\error Whatever; | |
| 102 | \\pub fn main() %void { | |
| 103 | \\ const x = shl(-16385, 1); | |
| 104 | \\ if (x == 0) return error.Whatever; | |
| 105 | \\} | |
| 106 | \\fn shl(a: i16, b: u4) i16 { | |
| 107 | \\ return @shlExact(a, b); | |
| 108 | \\} | |
| 109 | ); | |
| 110 | ||
| 111 | cases.addRuntimeSafety("unsigned shift left overflow", | |
| 112 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 113 | \\ @import("std").os.exit(126); | |
| 114 | \\} | |
| 115 | \\error Whatever; | |
| 116 | \\pub fn main() %void { | |
| 117 | \\ const x = shl(0b0010111111111111, 3); | |
| 118 | \\ if (x == 0) return error.Whatever; | |
| 119 | \\} | |
| 120 | \\fn shl(a: u16, b: u4) u16 { | |
| 121 | \\ return @shlExact(a, b); | |
| 122 | \\} | |
| 123 | ); | |
| 124 | ||
| 125 | cases.addRuntimeSafety("signed shift right overflow", | |
| 126 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 127 | \\ @import("std").os.exit(126); | |
| 128 | \\} | |
| 129 | \\error Whatever; | |
| 130 | \\pub fn main() %void { | |
| 131 | \\ const x = shr(-16385, 1); | |
| 132 | \\ if (x == 0) return error.Whatever; | |
| 133 | \\} | |
| 134 | \\fn shr(a: i16, b: u4) i16 { | |
| 135 | \\ return @shrExact(a, b); | |
| 136 | \\} | |
| 137 | ); | |
| 138 | ||
| 139 | cases.addRuntimeSafety("unsigned shift right overflow", | |
| 140 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 141 | \\ @import("std").os.exit(126); | |
| 142 | \\} | |
| 143 | \\error Whatever; | |
| 144 | \\pub fn main() %void { | |
| 145 | \\ const x = shr(0b0010111111111111, 3); | |
| 146 | \\ if (x == 0) return error.Whatever; | |
| 147 | \\} | |
| 148 | \\fn shr(a: u16, b: u4) u16 { | |
| 149 | \\ return @shrExact(a, b); | |
| 150 | \\} | |
| 151 | ); | |
| 152 | ||
| 153 | cases.addRuntimeSafety("integer division by zero", | |
| 154 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 155 | \\ @import("std").os.exit(126); | |
| 156 | \\} | |
| 157 | \\error Whatever; | |
| 158 | \\pub fn main() %void { | |
| 159 | \\ const x = div0(999, 0); | |
| 160 | \\} | |
| 161 | \\fn div0(a: i32, b: i32) i32 { | |
| 162 | \\ return @divTrunc(a, b); | |
| 163 | \\} | |
| 164 | ); | |
| 165 | ||
| 166 | cases.addRuntimeSafety("exact division failure", | |
| 167 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 168 | \\ @import("std").os.exit(126); | |
| 169 | \\} | |
| 170 | \\error Whatever; | |
| 171 | \\pub fn main() %void { | |
| 172 | \\ const x = divExact(10, 3); | |
| 173 | \\ if (x == 0) return error.Whatever; | |
| 174 | \\} | |
| 175 | \\fn divExact(a: i32, b: i32) i32 { | |
| 176 | \\ return @divExact(a, b); | |
| 177 | \\} | |
| 178 | ); | |
| 179 | ||
| 180 | cases.addRuntimeSafety("cast []u8 to bigger slice of wrong size", | |
| 181 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 182 | \\ @import("std").os.exit(126); | |
| 183 | \\} | |
| 184 | \\error Whatever; | |
| 185 | \\pub fn main() %void { | |
| 186 | \\ const x = widenSlice([]u8{1, 2, 3, 4, 5}); | |
| 187 | \\ if (x.len == 0) return error.Whatever; | |
| 188 | \\} | |
| 189 | \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { | |
| 190 | \\ return ([]align(1) const i32)(slice); | |
| 191 | \\} | |
| 192 | ); | |
| 193 | ||
| 194 | cases.addRuntimeSafety("value does not fit in shortening cast", | |
| 195 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 196 | \\ @import("std").os.exit(126); | |
| 197 | \\} | |
| 198 | \\error Whatever; | |
| 199 | \\pub fn main() %void { | |
| 200 | \\ const x = shorten_cast(200); | |
| 201 | \\ if (x == 0) return error.Whatever; | |
| 202 | \\} | |
| 203 | \\fn shorten_cast(x: i32) i8 { | |
| 204 | \\ return i8(x); | |
| 205 | \\} | |
| 206 | ); | |
| 207 | ||
| 208 | cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer", | |
| 209 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 210 | \\ @import("std").os.exit(126); | |
| 211 | \\} | |
| 212 | \\error Whatever; | |
| 213 | \\pub fn main() %void { | |
| 214 | \\ const x = unsigned_cast(-10); | |
| 215 | \\ if (x == 0) return error.Whatever; | |
| 216 | \\} | |
| 217 | \\fn unsigned_cast(x: i32) u32 { | |
| 218 | \\ return u32(x); | |
| 219 | \\} | |
| 220 | ); | |
| 221 | ||
| 222 | cases.addRuntimeSafety("unwrap error", | |
| 223 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 224 | \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { | |
| 225 | \\ @import("std").os.exit(126); // good | |
| 226 | \\ } | |
| 227 | \\ @import("std").os.exit(0); // test failed | |
| 228 | \\} | |
| 229 | \\error Whatever; | |
| 230 | \\pub fn main() %void { | |
| 231 | \\ bar() catch unreachable; | |
| 232 | \\} | |
| 233 | \\fn bar() %void { | |
| 234 | \\ return error.Whatever; | |
| 235 | \\} | |
| 236 | ); | |
| 237 | ||
| 238 | cases.addRuntimeSafety("cast integer to error and no code matches", | |
| 239 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 240 | \\ @import("std").os.exit(126); | |
| 241 | \\} | |
| 242 | \\pub fn main() %void { | |
| 243 | \\ _ = bar(9999); | |
| 244 | \\} | |
| 245 | \\fn bar(x: u32) error { | |
| 246 | \\ return error(x); | |
| 247 | \\} | |
| 248 | ); | |
| 249 | ||
| 250 | cases.addRuntimeSafety("@alignCast misaligned", | |
| 251 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 252 | \\ @import("std").os.exit(126); | |
| 253 | \\} | |
| 254 | \\error Wrong; | |
| 255 | \\pub fn main() %void { | |
| 256 | \\ var array align(4) = []u32{0x11111111, 0x11111111}; | |
| 257 | \\ const bytes = ([]u8)(array[0..]); | |
| 258 | \\ if (foo(bytes) != 0x11111111) return error.Wrong; | |
| 259 | \\} | |
| 260 | \\fn foo(bytes: []u8) u32 { | |
| 261 | \\ const slice4 = bytes[1..5]; | |
| 262 | \\ const int_slice = ([]u32)(@alignCast(4, slice4)); | |
| 263 | \\ return int_slice[0]; | |
| 264 | \\} | |
| 265 | ); | |
| 266 | ||
| 267 | cases.addRuntimeSafety("bad union field access", | |
| 268 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) noreturn { | |
| 269 | \\ @import("std").os.exit(126); | |
| 270 | \\} | |
| 271 | \\ | |
| 272 | \\const Foo = union { | |
| 273 | \\ float: f32, | |
| 274 | \\ int: u32, | |
| 275 | \\}; | |
| 276 | \\ | |
| 277 | \\pub fn main() %void { | |
| 278 | \\ var f = Foo { .int = 42 }; | |
| 279 | \\ bar(&f); | |
| 280 | \\} | |
| 281 | \\ | |
| 282 | \\fn bar(f: &Foo) void { | |
| 283 | \\ f.float = 12.34; | |
| 284 | \\} | |
| 285 | ); | |
| 286 | } |
test/standalone/brace_expansion/build.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | |
| 3 | pub fn build(b: &Builder) -> %void { | |
| 3 | pub fn build(b: &Builder) %void { | |
| 4 | 4 | const main = b.addTest("main.zig"); |
| 5 | 5 | main.setBuildMode(b.standardReleaseOptions()); |
| 6 | 6 |
test/standalone/brace_expansion/main.zig+8-10| ... | ... | @@ -19,7 +19,7 @@ const Token = union(enum) { |
| 19 | 19 | |
| 20 | 20 | var global_allocator: &mem.Allocator = undefined; |
| 21 | 21 | |
| 22 | fn tokenize(input:[] const u8) -> %ArrayList(Token) { | |
| 22 | fn tokenize(input:[] const u8) %ArrayList(Token) { | |
| 23 | 23 | const State = enum { |
| 24 | 24 | Start, |
| 25 | 25 | Word, |
| ... | ... | @@ -71,7 +71,7 @@ const Node = union(enum) { |
| 71 | 71 | Combine: []Node, |
| 72 | 72 | }; |
| 73 | 73 | |
| 74 | fn parse(tokens: &const ArrayList(Token), token_index: &usize) -> %Node { | |
| 74 | fn parse(tokens: &const ArrayList(Token), token_index: &usize) %Node { | |
| 75 | 75 | const first_token = tokens.items[*token_index]; |
| 76 | 76 | *token_index += 1; |
| 77 | 77 | |
| ... | ... | @@ -107,7 +107,7 @@ fn parse(tokens: &const ArrayList(Token), token_index: &usize) -> %Node { |
| 107 | 107 | } |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | fn expandString(input: []const u8, output: &Buffer) -> %void { | |
| 110 | fn expandString(input: []const u8, output: &Buffer) %void { | |
| 111 | 111 | const tokens = try tokenize(input); |
| 112 | 112 | if (tokens.len == 1) { |
| 113 | 113 | return output.resize(0); |
| ... | ... | @@ -135,9 +135,7 @@ fn expandString(input: []const u8, output: &Buffer) -> %void { |
| 135 | 135 | } |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | const ListOfBuffer0 = ArrayList(Buffer); // TODO this is working around a compiler bug, fix and delete this | |
| 139 | ||
| 140 | fn expandNode(node: &const Node, output: &ListOfBuffer0) -> %void { | |
| 138 | fn expandNode(node: &const Node, output: &ArrayList(Buffer)) %void { | |
| 141 | 139 | assert(output.len == 0); |
| 142 | 140 | switch (*node) { |
| 143 | 141 | Node.Scalar => |scalar| { |
| ... | ... | @@ -174,7 +172,7 @@ fn expandNode(node: &const Node, output: &ListOfBuffer0) -> %void { |
| 174 | 172 | } |
| 175 | 173 | } |
| 176 | 174 | |
| 177 | pub fn main() -> %void { | |
| 175 | pub fn main() %void { | |
| 178 | 176 | var stdin_file = try io.getStdIn(); |
| 179 | 177 | var stdout_file = try io.getStdOut(); |
| 180 | 178 | |
| ... | ... | @@ -210,11 +208,11 @@ test "invalid inputs" { |
| 210 | 208 | expectError("\n", error.InvalidInput); |
| 211 | 209 | } |
| 212 | 210 | |
| 213 | fn expectError(test_input: []const u8, expected_err: error) { | |
| 211 | fn expectError(test_input: []const u8, expected_err: error) void { | |
| 214 | 212 | var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable; |
| 215 | 213 | defer output_buf.deinit(); |
| 216 | 214 | |
| 217 | if (expandString("}ABC", &output_buf)) { | |
| 215 | if (expandString(test_input, &output_buf)) { | |
| 218 | 216 | unreachable; |
| 219 | 217 | } else |err| { |
| 220 | 218 | assert(expected_err == err); |
| ... | ... | @@ -244,7 +242,7 @@ test "valid inputs" { |
| 244 | 242 | expectExpansion("a{b}", "ab"); |
| 245 | 243 | } |
| 246 | 244 | |
| 247 | fn expectExpansion(test_input: []const u8, expected_result: []const u8) { | |
| 245 | fn expectExpansion(test_input: []const u8, expected_result: []const u8) void { | |
| 248 | 246 | var result = Buffer.initSize(global_allocator, 0) catch unreachable; |
| 249 | 247 | defer result.deinit(); |
| 250 | 248 |
test/standalone/issue_339/build.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | |
| 3 | pub fn build(b: &Builder) -> %void { | |
| 3 | pub fn build(b: &Builder) %void { | |
| 4 | 4 | const obj = b.addObject("test", "test.zig"); |
| 5 | 5 | |
| 6 | 6 | const test_step = b.step("test", "Test the program"); |
test/standalone/issue_339/test.zig+3-3| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | const StackTrace = @import("builtin").StackTrace; |
| 2 | pub fn panic(msg: []const u8, stack_trace: ?&StackTrace) -> noreturn { @breakpoint(); while (true) {} } | |
| 2 | pub fn panic(msg: []const u8, stack_trace: ?&StackTrace) noreturn { @breakpoint(); while (true) {} } | |
| 3 | 3 | |
| 4 | fn bar() -> %void {} | |
| 4 | fn bar() %void {} | |
| 5 | 5 | |
| 6 | export fn foo() { | |
| 6 | export fn foo() void { | |
| 7 | 7 | bar() catch unreachable; |
| 8 | 8 | } |
test/standalone/pkg_import/build.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | |
| 3 | pub fn build(b: &Builder) -> %void { | |
| 3 | pub fn build(b: &Builder) %void { | |
| 4 | 4 | const exe = b.addExecutable("test", "test.zig"); |
| 5 | 5 | exe.addPackagePath("my_pkg", "pkg.zig"); |
| 6 | 6 |
test/standalone/pkg_import/pkg.zig+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | pub fn add(a: i32, b: i32) -> i32 { return a + b; } | |
| 1 | pub fn add(a: i32, b: i32) i32 { return a + b; } |
test/standalone/pkg_import/test.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const my_pkg = @import("my_pkg"); |
| 2 | 2 | const assert = @import("std").debug.assert; |
| 3 | 3 | |
| 4 | pub fn main() -> %void { | |
| 4 | pub fn main() %void { | |
| 5 | 5 | assert(my_pkg.add(10, 20) == 30); |
| 6 | 6 | } |
test/standalone/use_alias/build.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | |
| 3 | pub fn build(b: &Builder) -> %void { | |
| 3 | pub fn build(b: &Builder) %void { | |
| 4 | 4 | b.addCIncludePath("."); |
| 5 | 5 | |
| 6 | 6 | const main = b.addTest("main.zig"); |
test/tests.zig+206-57| ... | ... | @@ -17,8 +17,9 @@ const compare_output = @import("compare_output.zig"); |
| 17 | 17 | const build_examples = @import("build_examples.zig"); |
| 18 | 18 | const compile_errors = @import("compile_errors.zig"); |
| 19 | 19 | const assemble_and_link = @import("assemble_and_link.zig"); |
| 20 | const debug_safety = @import("debug_safety.zig"); | |
| 20 | const runtime_safety = @import("runtime_safety.zig"); | |
| 21 | 21 | const translate_c = @import("translate_c.zig"); |
| 22 | const gen_h = @import("gen_h.zig"); | |
| 22 | 23 | |
| 23 | 24 | const TestTarget = struct { |
| 24 | 25 | os: builtin.Os, |
| ... | ... | @@ -49,7 +50,7 @@ error CompilationIncorrectlySucceeded; |
| 49 | 50 | |
| 50 | 51 | const max_stdout_size = 1 * 1024 * 1024; // 1 MB |
| 51 | 52 | |
| 52 | pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { | |
| 53 | pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { | |
| 53 | 54 | const cases = b.allocator.create(CompareOutputContext) catch unreachable; |
| 54 | 55 | *cases = CompareOutputContext { |
| 55 | 56 | .b = b, |
| ... | ... | @@ -63,21 +64,21 @@ pub fn addCompareOutputTests(b: &build.Builder, test_filter: ?[]const u8) -> &bu |
| 63 | 64 | return cases.step; |
| 64 | 65 | } |
| 65 | 66 | |
| 66 | pub fn addDebugSafetyTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { | |
| 67 | pub fn addRuntimeSafetyTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { | |
| 67 | 68 | const cases = b.allocator.create(CompareOutputContext) catch unreachable; |
| 68 | 69 | *cases = CompareOutputContext { |
| 69 | 70 | .b = b, |
| 70 | .step = b.step("test-debug-safety", "Run the debug safety tests"), | |
| 71 | .step = b.step("test-runtime-safety", "Run the runtime safety tests"), | |
| 71 | 72 | .test_index = 0, |
| 72 | 73 | .test_filter = test_filter, |
| 73 | 74 | }; |
| 74 | 75 | |
| 75 | debug_safety.addCases(cases); | |
| 76 | runtime_safety.addCases(cases); | |
| 76 | 77 | |
| 77 | 78 | return cases.step; |
| 78 | 79 | } |
| 79 | 80 | |
| 80 | pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { | |
| 81 | pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { | |
| 81 | 82 | const cases = b.allocator.create(CompileErrorContext) catch unreachable; |
| 82 | 83 | *cases = CompileErrorContext { |
| 83 | 84 | .b = b, |
| ... | ... | @@ -91,7 +92,7 @@ pub fn addCompileErrorTests(b: &build.Builder, test_filter: ?[]const u8) -> &bui |
| 91 | 92 | return cases.step; |
| 92 | 93 | } |
| 93 | 94 | |
| 94 | pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { | |
| 95 | pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { | |
| 95 | 96 | const cases = b.allocator.create(BuildExamplesContext) catch unreachable; |
| 96 | 97 | *cases = BuildExamplesContext { |
| 97 | 98 | .b = b, |
| ... | ... | @@ -105,7 +106,7 @@ pub fn addBuildExampleTests(b: &build.Builder, test_filter: ?[]const u8) -> &bui |
| 105 | 106 | return cases.step; |
| 106 | 107 | } |
| 107 | 108 | |
| 108 | pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { | |
| 109 | pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { | |
| 109 | 110 | const cases = b.allocator.create(CompareOutputContext) catch unreachable; |
| 110 | 111 | *cases = CompareOutputContext { |
| 111 | 112 | .b = b, |
| ... | ... | @@ -119,11 +120,11 @@ pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) -> & |
| 119 | 120 | return cases.step; |
| 120 | 121 | } |
| 121 | 122 | |
| 122 | pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { | |
| 123 | pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { | |
| 123 | 124 | const cases = b.allocator.create(TranslateCContext) catch unreachable; |
| 124 | 125 | *cases = TranslateCContext { |
| 125 | 126 | .b = b, |
| 126 | .step = b.step("test-translate-c", "Run the C header file parsing tests"), | |
| 127 | .step = b.step("test-translate-c", "Run the C transation tests"), | |
| 127 | 128 | .test_index = 0, |
| 128 | 129 | .test_filter = test_filter, |
| 129 | 130 | }; |
| ... | ... | @@ -133,8 +134,23 @@ pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) -> &build |
| 133 | 134 | return cases.step; |
| 134 | 135 | } |
| 135 | 136 | |
| 137 | pub fn addGenHTests(b: &build.Builder, test_filter: ?[]const u8) &build.Step { | |
| 138 | const cases = b.allocator.create(GenHContext) catch unreachable; | |
| 139 | *cases = GenHContext { | |
| 140 | .b = b, | |
| 141 | .step = b.step("test-gen-h", "Run the C header file generation tests"), | |
| 142 | .test_index = 0, | |
| 143 | .test_filter = test_filter, | |
| 144 | }; | |
| 145 | ||
| 146 | gen_h.addCases(cases); | |
| 147 | ||
| 148 | return cases.step; | |
| 149 | } | |
| 150 | ||
| 151 | ||
| 136 | 152 | pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []const u8, |
| 137 | name:[] const u8, desc: []const u8, with_lldb: bool) -> &build.Step | |
| 153 | name:[] const u8, desc: []const u8, with_lldb: bool) &build.Step | |
| 138 | 154 | { |
| 139 | 155 | const step = b.step(b.fmt("test-{}", name), desc); |
| 140 | 156 | for (test_targets) |test_target| { |
| ... | ... | @@ -176,7 +192,7 @@ pub const CompareOutputContext = struct { |
| 176 | 192 | const Special = enum { |
| 177 | 193 | None, |
| 178 | 194 | Asm, |
| 179 | DebugSafety, | |
| 195 | RuntimeSafety, | |
| 180 | 196 | }; |
| 181 | 197 | |
| 182 | 198 | const TestCase = struct { |
| ... | ... | @@ -192,14 +208,14 @@ pub const CompareOutputContext = struct { |
| 192 | 208 | source: []const u8, |
| 193 | 209 | }; |
| 194 | 210 | |
| 195 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) { | |
| 211 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { | |
| 196 | 212 | self.sources.append(SourceFile { |
| 197 | 213 | .filename = filename, |
| 198 | 214 | .source = source, |
| 199 | 215 | }) catch unreachable; |
| 200 | 216 | } |
| 201 | 217 | |
| 202 | pub fn setCommandLineArgs(self: &TestCase, args: []const []const u8) { | |
| 218 | pub fn setCommandLineArgs(self: &TestCase, args: []const []const u8) void { | |
| 203 | 219 | self.cli_args = args; |
| 204 | 220 | } |
| 205 | 221 | }; |
| ... | ... | @@ -215,7 +231,7 @@ pub const CompareOutputContext = struct { |
| 215 | 231 | |
| 216 | 232 | pub fn create(context: &CompareOutputContext, exe_path: []const u8, |
| 217 | 233 | name: []const u8, expected_output: []const u8, |
| 218 | cli_args: []const []const u8) -> &RunCompareOutputStep | |
| 234 | cli_args: []const []const u8) &RunCompareOutputStep | |
| 219 | 235 | { |
| 220 | 236 | const allocator = context.b.allocator; |
| 221 | 237 | const ptr = allocator.create(RunCompareOutputStep) catch unreachable; |
| ... | ... | @@ -232,7 +248,7 @@ pub const CompareOutputContext = struct { |
| 232 | 248 | return ptr; |
| 233 | 249 | } |
| 234 | 250 | |
| 235 | fn make(step: &build.Step) -> %void { | |
| 251 | fn make(step: &build.Step) %void { | |
| 236 | 252 | const self = @fieldParentPtr(RunCompareOutputStep, "step", step); |
| 237 | 253 | const b = self.context.b; |
| 238 | 254 | |
| ... | ... | @@ -298,7 +314,7 @@ pub const CompareOutputContext = struct { |
| 298 | 314 | } |
| 299 | 315 | }; |
| 300 | 316 | |
| 301 | const DebugSafetyRunStep = struct { | |
| 317 | const RuntimeSafetyRunStep = struct { | |
| 302 | 318 | step: build.Step, |
| 303 | 319 | context: &CompareOutputContext, |
| 304 | 320 | exe_path: []const u8, |
| ... | ... | @@ -306,23 +322,23 @@ pub const CompareOutputContext = struct { |
| 306 | 322 | test_index: usize, |
| 307 | 323 | |
| 308 | 324 | pub fn create(context: &CompareOutputContext, exe_path: []const u8, |
| 309 | name: []const u8) -> &DebugSafetyRunStep | |
| 325 | name: []const u8) &RuntimeSafetyRunStep | |
| 310 | 326 | { |
| 311 | 327 | const allocator = context.b.allocator; |
| 312 | const ptr = allocator.create(DebugSafetyRunStep) catch unreachable; | |
| 313 | *ptr = DebugSafetyRunStep { | |
| 328 | const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable; | |
| 329 | *ptr = RuntimeSafetyRunStep { | |
| 314 | 330 | .context = context, |
| 315 | 331 | .exe_path = exe_path, |
| 316 | 332 | .name = name, |
| 317 | 333 | .test_index = context.test_index, |
| 318 | .step = build.Step.init("DebugSafetyRun", allocator, make), | |
| 334 | .step = build.Step.init("RuntimeSafetyRun", allocator, make), | |
| 319 | 335 | }; |
| 320 | 336 | context.test_index += 1; |
| 321 | 337 | return ptr; |
| 322 | 338 | } |
| 323 | 339 | |
| 324 | fn make(step: &build.Step) -> %void { | |
| 325 | const self = @fieldParentPtr(DebugSafetyRunStep, "step", step); | |
| 340 | fn make(step: &build.Step) %void { | |
| 341 | const self = @fieldParentPtr(RuntimeSafetyRunStep, "step", step); | |
| 326 | 342 | const b = self.context.b; |
| 327 | 343 | |
| 328 | 344 | const full_exe_path = b.pathFromRoot(self.exe_path); |
| ... | ... | @@ -367,7 +383,7 @@ pub const CompareOutputContext = struct { |
| 367 | 383 | }; |
| 368 | 384 | |
| 369 | 385 | pub fn createExtra(self: &CompareOutputContext, name: []const u8, source: []const u8, |
| 370 | expected_output: []const u8, special: Special) -> TestCase | |
| 386 | expected_output: []const u8, special: Special) TestCase | |
| 371 | 387 | { |
| 372 | 388 | var tc = TestCase { |
| 373 | 389 | .name = name, |
| ... | ... | @@ -383,33 +399,33 @@ pub const CompareOutputContext = struct { |
| 383 | 399 | } |
| 384 | 400 | |
| 385 | 401 | pub fn create(self: &CompareOutputContext, name: []const u8, source: []const u8, |
| 386 | expected_output: []const u8) -> TestCase | |
| 402 | expected_output: []const u8) TestCase | |
| 387 | 403 | { |
| 388 | 404 | return createExtra(self, name, source, expected_output, Special.None); |
| 389 | 405 | } |
| 390 | 406 | |
| 391 | pub fn addC(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) { | |
| 407 | pub fn addC(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void { | |
| 392 | 408 | var tc = self.create(name, source, expected_output); |
| 393 | 409 | tc.link_libc = true; |
| 394 | 410 | self.addCase(tc); |
| 395 | 411 | } |
| 396 | 412 | |
| 397 | pub fn add(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) { | |
| 413 | pub fn add(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void { | |
| 398 | 414 | const tc = self.create(name, source, expected_output); |
| 399 | 415 | self.addCase(tc); |
| 400 | 416 | } |
| 401 | 417 | |
| 402 | pub fn addAsm(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) { | |
| 418 | pub fn addAsm(self: &CompareOutputContext, name: []const u8, source: []const u8, expected_output: []const u8) void { | |
| 403 | 419 | const tc = self.createExtra(name, source, expected_output, Special.Asm); |
| 404 | 420 | self.addCase(tc); |
| 405 | 421 | } |
| 406 | 422 | |
| 407 | pub fn addDebugSafety(self: &CompareOutputContext, name: []const u8, source: []const u8) { | |
| 408 | const tc = self.createExtra(name, source, undefined, Special.DebugSafety); | |
| 423 | pub fn addRuntimeSafety(self: &CompareOutputContext, name: []const u8, source: []const u8) void { | |
| 424 | const tc = self.createExtra(name, source, undefined, Special.RuntimeSafety); | |
| 409 | 425 | self.addCase(tc); |
| 410 | 426 | } |
| 411 | 427 | |
| 412 | pub fn addCase(self: &CompareOutputContext, case: &const TestCase) { | |
| 428 | pub fn addCase(self: &CompareOutputContext, case: &const TestCase) void { | |
| 413 | 429 | const b = self.b; |
| 414 | 430 | |
| 415 | 431 | const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable; |
| ... | ... | @@ -465,7 +481,7 @@ pub const CompareOutputContext = struct { |
| 465 | 481 | self.step.dependOn(&run_and_cmp_output.step); |
| 466 | 482 | } |
| 467 | 483 | }, |
| 468 | Special.DebugSafety => { | |
| 484 | Special.RuntimeSafety => { | |
| 469 | 485 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {}", case.name) catch unreachable; |
| 470 | 486 | if (self.test_filter) |filter| { |
| 471 | 487 | if (mem.indexOf(u8, annotated_case_name, filter) == null) |
| ... | ... | @@ -483,7 +499,7 @@ pub const CompareOutputContext = struct { |
| 483 | 499 | exe.step.dependOn(&write_src.step); |
| 484 | 500 | } |
| 485 | 501 | |
| 486 | const run_and_cmp_output = DebugSafetyRunStep.create(self, exe.getOutputPath(), annotated_case_name); | |
| 502 | const run_and_cmp_output = RuntimeSafetyRunStep.create(self, exe.getOutputPath(), annotated_case_name); | |
| 487 | 503 | run_and_cmp_output.step.dependOn(&exe.step); |
| 488 | 504 | |
| 489 | 505 | self.step.dependOn(&run_and_cmp_output.step); |
| ... | ... | @@ -510,14 +526,14 @@ pub const CompileErrorContext = struct { |
| 510 | 526 | source: []const u8, |
| 511 | 527 | }; |
| 512 | 528 | |
| 513 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) { | |
| 529 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { | |
| 514 | 530 | self.sources.append(SourceFile { |
| 515 | 531 | .filename = filename, |
| 516 | 532 | .source = source, |
| 517 | 533 | }) catch unreachable; |
| 518 | 534 | } |
| 519 | 535 | |
| 520 | pub fn addExpectedError(self: &TestCase, text: []const u8) { | |
| 536 | pub fn addExpectedError(self: &TestCase, text: []const u8) void { | |
| 521 | 537 | self.expected_errors.append(text) catch unreachable; |
| 522 | 538 | } |
| 523 | 539 | }; |
| ... | ... | @@ -531,7 +547,7 @@ pub const CompileErrorContext = struct { |
| 531 | 547 | build_mode: Mode, |
| 532 | 548 | |
| 533 | 549 | pub fn create(context: &CompileErrorContext, name: []const u8, |
| 534 | case: &const TestCase, build_mode: Mode) -> &CompileCmpOutputStep | |
| 550 | case: &const TestCase, build_mode: Mode) &CompileCmpOutputStep | |
| 535 | 551 | { |
| 536 | 552 | const allocator = context.b.allocator; |
| 537 | 553 | const ptr = allocator.create(CompileCmpOutputStep) catch unreachable; |
| ... | ... | @@ -547,7 +563,7 @@ pub const CompileErrorContext = struct { |
| 547 | 563 | return ptr; |
| 548 | 564 | } |
| 549 | 565 | |
| 550 | fn make(step: &build.Step) -> %void { | |
| 566 | fn make(step: &build.Step) %void { | |
| 551 | 567 | const self = @fieldParentPtr(CompileCmpOutputStep, "step", step); |
| 552 | 568 | const b = self.context.b; |
| 553 | 569 | |
| ... | ... | @@ -645,7 +661,7 @@ pub const CompileErrorContext = struct { |
| 645 | 661 | } |
| 646 | 662 | }; |
| 647 | 663 | |
| 648 | fn printInvocation(args: []const []const u8) { | |
| 664 | fn printInvocation(args: []const []const u8) void { | |
| 649 | 665 | for (args) |arg| { |
| 650 | 666 | warn("{} ", arg); |
| 651 | 667 | } |
| ... | ... | @@ -653,7 +669,7 @@ pub const CompileErrorContext = struct { |
| 653 | 669 | } |
| 654 | 670 | |
| 655 | 671 | pub fn create(self: &CompileErrorContext, name: []const u8, source: []const u8, |
| 656 | expected_lines: ...) -> &TestCase | |
| 672 | expected_lines: ...) &TestCase | |
| 657 | 673 | { |
| 658 | 674 | const tc = self.b.allocator.create(TestCase) catch unreachable; |
| 659 | 675 | *tc = TestCase { |
| ... | ... | @@ -671,24 +687,24 @@ pub const CompileErrorContext = struct { |
| 671 | 687 | return tc; |
| 672 | 688 | } |
| 673 | 689 | |
| 674 | pub fn addC(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) { | |
| 690 | pub fn addC(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void { | |
| 675 | 691 | var tc = self.create(name, source, expected_lines); |
| 676 | 692 | tc.link_libc = true; |
| 677 | 693 | self.addCase(tc); |
| 678 | 694 | } |
| 679 | 695 | |
| 680 | pub fn addExe(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) { | |
| 696 | pub fn addExe(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void { | |
| 681 | 697 | var tc = self.create(name, source, expected_lines); |
| 682 | 698 | tc.is_exe = true; |
| 683 | 699 | self.addCase(tc); |
| 684 | 700 | } |
| 685 | 701 | |
| 686 | pub fn add(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) { | |
| 702 | pub fn add(self: &CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void { | |
| 687 | 703 | const tc = self.create(name, source, expected_lines); |
| 688 | 704 | self.addCase(tc); |
| 689 | 705 | } |
| 690 | 706 | |
| 691 | pub fn addCase(self: &CompileErrorContext, case: &const TestCase) { | |
| 707 | pub fn addCase(self: &CompileErrorContext, case: &const TestCase) void { | |
| 692 | 708 | const b = self.b; |
| 693 | 709 | |
| 694 | 710 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { |
| ... | ... | @@ -717,15 +733,15 @@ pub const BuildExamplesContext = struct { |
| 717 | 733 | test_index: usize, |
| 718 | 734 | test_filter: ?[]const u8, |
| 719 | 735 | |
| 720 | pub fn addC(self: &BuildExamplesContext, root_src: []const u8) { | |
| 736 | pub fn addC(self: &BuildExamplesContext, root_src: []const u8) void { | |
| 721 | 737 | self.addAllArgs(root_src, true); |
| 722 | 738 | } |
| 723 | 739 | |
| 724 | pub fn add(self: &BuildExamplesContext, root_src: []const u8) { | |
| 740 | pub fn add(self: &BuildExamplesContext, root_src: []const u8) void { | |
| 725 | 741 | self.addAllArgs(root_src, false); |
| 726 | 742 | } |
| 727 | 743 | |
| 728 | pub fn addBuildFile(self: &BuildExamplesContext, build_file: []const u8) { | |
| 744 | pub fn addBuildFile(self: &BuildExamplesContext, build_file: []const u8) void { | |
| 729 | 745 | const b = self.b; |
| 730 | 746 | |
| 731 | 747 | const annotated_case_name = b.fmt("build {} (Debug)", build_file); |
| ... | ... | @@ -756,7 +772,7 @@ pub const BuildExamplesContext = struct { |
| 756 | 772 | self.step.dependOn(&log_step.step); |
| 757 | 773 | } |
| 758 | 774 | |
| 759 | pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) { | |
| 775 | pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) void { | |
| 760 | 776 | const b = self.b; |
| 761 | 777 | |
| 762 | 778 | for ([]Mode{Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast}) |mode| { |
| ... | ... | @@ -798,14 +814,14 @@ pub const TranslateCContext = struct { |
| 798 | 814 | source: []const u8, |
| 799 | 815 | }; |
| 800 | 816 | |
| 801 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) { | |
| 817 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { | |
| 802 | 818 | self.sources.append(SourceFile { |
| 803 | 819 | .filename = filename, |
| 804 | 820 | .source = source, |
| 805 | 821 | }) catch unreachable; |
| 806 | 822 | } |
| 807 | 823 | |
| 808 | pub fn addExpectedLine(self: &TestCase, text: []const u8) { | |
| 824 | pub fn addExpectedLine(self: &TestCase, text: []const u8) void { | |
| 809 | 825 | self.expected_lines.append(text) catch unreachable; |
| 810 | 826 | } |
| 811 | 827 | }; |
| ... | ... | @@ -817,7 +833,7 @@ pub const TranslateCContext = struct { |
| 817 | 833 | test_index: usize, |
| 818 | 834 | case: &const TestCase, |
| 819 | 835 | |
| 820 | pub fn create(context: &TranslateCContext, name: []const u8, case: &const TestCase) -> &TranslateCCmpOutputStep { | |
| 836 | pub fn create(context: &TranslateCContext, name: []const u8, case: &const TestCase) &TranslateCCmpOutputStep { | |
| 821 | 837 | const allocator = context.b.allocator; |
| 822 | 838 | const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable; |
| 823 | 839 | *ptr = TranslateCCmpOutputStep { |
| ... | ... | @@ -831,7 +847,7 @@ pub const TranslateCContext = struct { |
| 831 | 847 | return ptr; |
| 832 | 848 | } |
| 833 | 849 | |
| 834 | fn make(step: &build.Step) -> %void { | |
| 850 | fn make(step: &build.Step) %void { | |
| 835 | 851 | const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step); |
| 836 | 852 | const b = self.context.b; |
| 837 | 853 | |
| ... | ... | @@ -918,7 +934,7 @@ pub const TranslateCContext = struct { |
| 918 | 934 | } |
| 919 | 935 | }; |
| 920 | 936 | |
| 921 | fn printInvocation(args: []const []const u8) { | |
| 937 | fn printInvocation(args: []const []const u8) void { | |
| 922 | 938 | for (args) |arg| { |
| 923 | 939 | warn("{} ", arg); |
| 924 | 940 | } |
| ... | ... | @@ -926,7 +942,7 @@ pub const TranslateCContext = struct { |
| 926 | 942 | } |
| 927 | 943 | |
| 928 | 944 | pub fn create(self: &TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, |
| 929 | source: []const u8, expected_lines: ...) -> &TestCase | |
| 945 | source: []const u8, expected_lines: ...) &TestCase | |
| 930 | 946 | { |
| 931 | 947 | const tc = self.b.allocator.create(TestCase) catch unreachable; |
| 932 | 948 | *tc = TestCase { |
| ... | ... | @@ -943,22 +959,22 @@ pub const TranslateCContext = struct { |
| 943 | 959 | return tc; |
| 944 | 960 | } |
| 945 | 961 | |
| 946 | pub fn add(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) { | |
| 962 | pub fn add(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { | |
| 947 | 963 | const tc = self.create(false, "source.h", name, source, expected_lines); |
| 948 | 964 | self.addCase(tc); |
| 949 | 965 | } |
| 950 | 966 | |
| 951 | pub fn addC(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) { | |
| 967 | pub fn addC(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { | |
| 952 | 968 | const tc = self.create(false, "source.c", name, source, expected_lines); |
| 953 | 969 | self.addCase(tc); |
| 954 | 970 | } |
| 955 | 971 | |
| 956 | pub fn addAllowWarnings(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) { | |
| 972 | pub fn addAllowWarnings(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void { | |
| 957 | 973 | const tc = self.create(true, "source.h", name, source, expected_lines); |
| 958 | 974 | self.addCase(tc); |
| 959 | 975 | } |
| 960 | 976 | |
| 961 | pub fn addCase(self: &TranslateCContext, case: &const TestCase) { | |
| 977 | pub fn addCase(self: &TranslateCContext, case: &const TestCase) void { | |
| 962 | 978 | const b = self.b; |
| 963 | 979 | |
| 964 | 980 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable; |
| ... | ... | @@ -977,3 +993,136 @@ pub const TranslateCContext = struct { |
| 977 | 993 | } |
| 978 | 994 | } |
| 979 | 995 | }; |
| 996 | ||
| 997 | pub const GenHContext = struct { | |
| 998 | b: &build.Builder, | |
| 999 | step: &build.Step, | |
| 1000 | test_index: usize, | |
| 1001 | test_filter: ?[]const u8, | |
| 1002 | ||
| 1003 | const TestCase = struct { | |
| 1004 | name: []const u8, | |
| 1005 | sources: ArrayList(SourceFile), | |
| 1006 | expected_lines: ArrayList([]const u8), | |
| 1007 | ||
| 1008 | const SourceFile = struct { | |
| 1009 | filename: []const u8, | |
| 1010 | source: []const u8, | |
| 1011 | }; | |
| 1012 | ||
| 1013 | pub fn addSourceFile(self: &TestCase, filename: []const u8, source: []const u8) void { | |
| 1014 | self.sources.append(SourceFile { | |
| 1015 | .filename = filename, | |
| 1016 | .source = source, | |
| 1017 | }) catch unreachable; | |
| 1018 | } | |
| 1019 | ||
| 1020 | pub fn addExpectedLine(self: &TestCase, text: []const u8) void { | |
| 1021 | self.expected_lines.append(text) catch unreachable; | |
| 1022 | } | |
| 1023 | }; | |
| 1024 | ||
| 1025 | const GenHCmpOutputStep = struct { | |
| 1026 | step: build.Step, | |
| 1027 | context: &GenHContext, | |
| 1028 | h_path: []const u8, | |
| 1029 | name: []const u8, | |
| 1030 | test_index: usize, | |
| 1031 | case: &const TestCase, | |
| 1032 | ||
| 1033 | pub fn create(context: &GenHContext, h_path: []const u8, name: []const u8, case: &const TestCase) &GenHCmpOutputStep { | |
| 1034 | const allocator = context.b.allocator; | |
| 1035 | const ptr = allocator.create(GenHCmpOutputStep) catch unreachable; | |
| 1036 | *ptr = GenHCmpOutputStep { | |
| 1037 | .step = build.Step.init("ParseCCmpOutput", allocator, make), | |
| 1038 | .context = context, | |
| 1039 | .h_path = h_path, | |
| 1040 | .name = name, | |
| 1041 | .test_index = context.test_index, | |
| 1042 | .case = case, | |
| 1043 | }; | |
| 1044 | context.test_index += 1; | |
| 1045 | return ptr; | |
| 1046 | } | |
| 1047 | ||
| 1048 | fn make(step: &build.Step) %void { | |
| 1049 | const self = @fieldParentPtr(GenHCmpOutputStep, "step", step); | |
| 1050 | const b = self.context.b; | |
| 1051 | ||
| 1052 | warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); | |
| 1053 | ||
| 1054 | const full_h_path = b.pathFromRoot(self.h_path); | |
| 1055 | const actual_h = try io.readFileAlloc(full_h_path, b.allocator); | |
| 1056 | ||
| 1057 | for (self.case.expected_lines.toSliceConst()) |expected_line| { | |
| 1058 | if (mem.indexOf(u8, actual_h, expected_line) == null) { | |
| 1059 | warn( | |
| 1060 | \\ | |
| 1061 | \\========= Expected this output: ================ | |
| 1062 | \\{} | |
| 1063 | \\================================================ | |
| 1064 | \\{} | |
| 1065 | \\ | |
| 1066 | , expected_line, actual_h); | |
| 1067 | return error.TestFailed; | |
| 1068 | } | |
| 1069 | } | |
| 1070 | warn("OK\n"); | |
| 1071 | } | |
| 1072 | }; | |
| 1073 | ||
| 1074 | fn printInvocation(args: []const []const u8) void { | |
| 1075 | for (args) |arg| { | |
| 1076 | warn("{} ", arg); | |
| 1077 | } | |
| 1078 | warn("\n"); | |
| 1079 | } | |
| 1080 | ||
| 1081 | pub fn create(self: &GenHContext, filename: []const u8, name: []const u8, | |
| 1082 | source: []const u8, expected_lines: ...) &TestCase | |
| 1083 | { | |
| 1084 | const tc = self.b.allocator.create(TestCase) catch unreachable; | |
| 1085 | *tc = TestCase { | |
| 1086 | .name = name, | |
| 1087 | .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator), | |
| 1088 | .expected_lines = ArrayList([]const u8).init(self.b.allocator), | |
| 1089 | }; | |
| 1090 | tc.addSourceFile(filename, source); | |
| 1091 | comptime var arg_i = 0; | |
| 1092 | inline while (arg_i < expected_lines.len) : (arg_i += 1) { | |
| 1093 | tc.addExpectedLine(expected_lines[arg_i]); | |
| 1094 | } | |
| 1095 | return tc; | |
| 1096 | } | |
| 1097 | ||
| 1098 | pub fn add(self: &GenHContext, name: []const u8, source: []const u8, expected_lines: ...) void { | |
| 1099 | const tc = self.create("test.zig", name, source, expected_lines); | |
| 1100 | self.addCase(tc); | |
| 1101 | } | |
| 1102 | ||
| 1103 | pub fn addCase(self: &GenHContext, case: &const TestCase) void { | |
| 1104 | const b = self.b; | |
| 1105 | const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable; | |
| 1106 | ||
| 1107 | const mode = builtin.Mode.Debug; | |
| 1108 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable; | |
| 1109 | if (self.test_filter) |filter| { | |
| 1110 | if (mem.indexOf(u8, annotated_case_name, filter) == null) | |
| 1111 | return; | |
| 1112 | } | |
| 1113 | ||
| 1114 | const obj = b.addObject("test", root_src); | |
| 1115 | obj.setBuildMode(mode); | |
| 1116 | ||
| 1117 | for (case.sources.toSliceConst()) |src_file| { | |
| 1118 | const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable; | |
| 1119 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); | |
| 1120 | obj.step.dependOn(&write_src.step); | |
| 1121 | } | |
| 1122 | ||
| 1123 | const cmp_h = GenHCmpOutputStep.create(self, obj.getOutputHPath(), annotated_case_name, case); | |
| 1124 | cmp_h.step.dependOn(&obj.step); | |
| 1125 | ||
| 1126 | self.step.dependOn(&cmp_h.step); | |
| 1127 | } | |
| 1128 | }; |
test/translate_c.zig+66-66| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | |
| 3 | pub fn addCases(cases: &tests.TranslateCContext) { | |
| 3 | pub fn addCases(cases: &tests.TranslateCContext) void { | |
| 4 | 4 | cases.addAllowWarnings("simple data types", |
| 5 | 5 | \\#include <stdint.h> |
| 6 | 6 | \\int foo(char a, unsigned char b, signed char c); |
| ... | ... | @@ -8,17 +8,17 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 8 | 8 | \\void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); |
| 9 | 9 | \\void baz(int8_t a, int16_t b, int32_t c, int64_t d); |
| 10 | 10 | , |
| 11 | \\pub extern fn foo(a: u8, b: u8, c: i8) -> c_int; | |
| 11 | \\pub extern fn foo(a: u8, b: u8, c: i8) c_int; | |
| 12 | 12 | , |
| 13 | \\pub extern fn bar(a: u8, b: u16, c: u32, d: u64); | |
| 13 | \\pub extern fn bar(a: u8, b: u16, c: u32, d: u64) void; | |
| 14 | 14 | , |
| 15 | \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64); | |
| 15 | \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64) void; | |
| 16 | 16 | ); |
| 17 | 17 | |
| 18 | 18 | cases.add("noreturn attribute", |
| 19 | 19 | \\void foo(void) __attribute__((noreturn)); |
| 20 | 20 | , |
| 21 | \\pub extern fn foo() -> noreturn; | |
| 21 | \\pub extern fn foo() noreturn; | |
| 22 | 22 | ); |
| 23 | 23 | |
| 24 | 24 | cases.addC("simple function", |
| ... | ... | @@ -26,7 +26,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 26 | 26 | \\ return a < 0 ? -a : a; |
| 27 | 27 | \\} |
| 28 | 28 | , |
| 29 | \\export fn abs(a: c_int) -> c_int { | |
| 29 | \\export fn abs(a: c_int) c_int { | |
| 30 | 30 | \\ return if (a < 0) -a else a; |
| 31 | 31 | \\} |
| 32 | 32 | ); |
| ... | ... | @@ -56,7 +56,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 56 | 56 | cases.add("restrict -> noalias", |
| 57 | 57 | \\void foo(void *restrict bar, void *restrict); |
| 58 | 58 | , |
| 59 | \\pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void); | |
| 59 | \\pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void) void; | |
| 60 | 60 | ); |
| 61 | 61 | |
| 62 | 62 | cases.add("simple struct", |
| ... | ... | @@ -98,7 +98,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 98 | 98 | , |
| 99 | 99 | \\pub const BarB = enum_Bar.B; |
| 100 | 100 | , |
| 101 | \\pub extern fn func(a: ?&struct_Foo, b: ?&(?&enum_Bar)); | |
| 101 | \\pub extern fn func(a: ?&struct_Foo, b: ?&(?&enum_Bar)) void; | |
| 102 | 102 | , |
| 103 | 103 | \\pub const Foo = struct_Foo; |
| 104 | 104 | , |
| ... | ... | @@ -108,7 +108,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 108 | 108 | cases.add("constant size array", |
| 109 | 109 | \\void func(int array[20]); |
| 110 | 110 | , |
| 111 | \\pub extern fn func(array: ?&c_int); | |
| 111 | \\pub extern fn func(array: ?&c_int) void; | |
| 112 | 112 | ); |
| 113 | 113 | |
| 114 | 114 | cases.add("self referential struct with function pointer", |
| ... | ... | @@ -117,7 +117,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 117 | 117 | \\}; |
| 118 | 118 | , |
| 119 | 119 | \\pub const struct_Foo = extern struct { |
| 120 | \\ derp: ?extern fn(?&struct_Foo), | |
| 120 | \\ derp: ?extern fn(?&struct_Foo) void, | |
| 121 | 121 | \\}; |
| 122 | 122 | , |
| 123 | 123 | \\pub const Foo = struct_Foo; |
| ... | ... | @@ -129,7 +129,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 129 | 129 | , |
| 130 | 130 | \\pub const struct_Foo = @OpaqueType(); |
| 131 | 131 | , |
| 132 | \\pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo; | |
| 132 | \\pub extern fn some_func(foo: ?&struct_Foo, x: c_int) ?&struct_Foo; | |
| 133 | 133 | , |
| 134 | 134 | \\pub const Foo = struct_Foo; |
| 135 | 135 | ); |
| ... | ... | @@ -190,7 +190,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 190 | 190 | , |
| 191 | 191 | \\pub const Foo = c_void; |
| 192 | 192 | , |
| 193 | \\pub extern fn fun(a: ?&Foo) -> Foo; | |
| 193 | \\pub extern fn fun(a: ?&Foo) Foo; | |
| 194 | 194 | ); |
| 195 | 195 | |
| 196 | 196 | cases.add("generate inline func for #define global extern fn", |
| ... | ... | @@ -200,15 +200,15 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 200 | 200 | \\extern char (*fn_ptr2)(int, float); |
| 201 | 201 | \\#define bar fn_ptr2 |
| 202 | 202 | , |
| 203 | \\pub extern var fn_ptr: ?extern fn(); | |
| 203 | \\pub extern var fn_ptr: ?extern fn() void; | |
| 204 | 204 | , |
| 205 | \\pub inline fn foo() { | |
| 205 | \\pub inline fn foo() void { | |
| 206 | 206 | \\ return (??fn_ptr)(); |
| 207 | 207 | \\} |
| 208 | 208 | , |
| 209 | \\pub extern var fn_ptr2: ?extern fn(c_int, f32) -> u8; | |
| 209 | \\pub extern var fn_ptr2: ?extern fn(c_int, f32) u8; | |
| 210 | 210 | , |
| 211 | \\pub inline fn bar(arg0: c_int, arg1: f32) -> u8 { | |
| 211 | \\pub inline fn bar(arg0: c_int, arg1: f32) u8 { | |
| 212 | 212 | \\ return (??fn_ptr2)(arg0, arg1); |
| 213 | 213 | \\} |
| 214 | 214 | ); |
| ... | ... | @@ -222,7 +222,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 222 | 222 | cases.add("__cdecl doesn't mess up function pointers", |
| 223 | 223 | \\void foo(void (__cdecl *fn_ptr)(void)); |
| 224 | 224 | , |
| 225 | \\pub extern fn foo(fn_ptr: ?extern fn()); | |
| 225 | \\pub extern fn foo(fn_ptr: ?extern fn() void) void; | |
| 226 | 226 | ); |
| 227 | 227 | |
| 228 | 228 | cases.add("comment after integer literal", |
| ... | ... | @@ -325,12 +325,12 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 325 | 325 | \\ return a; |
| 326 | 326 | \\} |
| 327 | 327 | , |
| 328 | \\pub export fn foo1(_arg_a: c_uint) -> c_uint { | |
| 328 | \\pub export fn foo1(_arg_a: c_uint) c_uint { | |
| 329 | 329 | \\ var a = _arg_a; |
| 330 | 330 | \\ a +%= 1; |
| 331 | 331 | \\ return a; |
| 332 | 332 | \\} |
| 333 | \\pub export fn foo2(_arg_a: c_int) -> c_int { | |
| 333 | \\pub export fn foo2(_arg_a: c_int) c_int { | |
| 334 | 334 | \\ var a = _arg_a; |
| 335 | 335 | \\ a += 1; |
| 336 | 336 | \\ return a; |
| ... | ... | @@ -346,7 +346,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 346 | 346 | \\ return i; |
| 347 | 347 | \\} |
| 348 | 348 | , |
| 349 | \\pub export fn log2(_arg_a: c_uint) -> c_int { | |
| 349 | \\pub export fn log2(_arg_a: c_uint) c_int { | |
| 350 | 350 | \\ var a = _arg_a; |
| 351 | 351 | \\ var i: c_int = 0; |
| 352 | 352 | \\ while (a > c_uint(0)) { |
| ... | ... | @@ -367,7 +367,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 367 | 367 | \\ return a; |
| 368 | 368 | \\} |
| 369 | 369 | , |
| 370 | \\pub export fn max(a: c_int, b: c_int) -> c_int { | |
| 370 | \\pub export fn max(a: c_int, b: c_int) c_int { | |
| 371 | 371 | \\ if (a < b) return b; |
| 372 | 372 | \\ if (a < b) return b else return a; |
| 373 | 373 | \\} |
| ... | ... | @@ -382,7 +382,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 382 | 382 | \\ return a; |
| 383 | 383 | \\} |
| 384 | 384 | , |
| 385 | \\pub export fn max(a: c_int, b: c_int) -> c_int { | |
| 385 | \\pub export fn max(a: c_int, b: c_int) c_int { | |
| 386 | 386 | \\ if (a == b) return a; |
| 387 | 387 | \\ if (a != b) return b; |
| 388 | 388 | \\ return a; |
| ... | ... | @@ -407,7 +407,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 407 | 407 | \\ c = a % b; |
| 408 | 408 | \\} |
| 409 | 409 | , |
| 410 | \\pub export fn s(a: c_int, b: c_int) -> c_int { | |
| 410 | \\pub export fn s(a: c_int, b: c_int) c_int { | |
| 411 | 411 | \\ var c: c_int = undefined; |
| 412 | 412 | \\ c = (a + b); |
| 413 | 413 | \\ c = (a - b); |
| ... | ... | @@ -415,7 +415,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 415 | 415 | \\ c = @divTrunc(a, b); |
| 416 | 416 | \\ c = @rem(a, b); |
| 417 | 417 | \\} |
| 418 | \\pub export fn u(a: c_uint, b: c_uint) -> c_uint { | |
| 418 | \\pub export fn u(a: c_uint, b: c_uint) c_uint { | |
| 419 | 419 | \\ var c: c_uint = undefined; |
| 420 | 420 | \\ c = (a +% b); |
| 421 | 421 | \\ c = (a -% b); |
| ... | ... | @@ -430,7 +430,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 430 | 430 | \\ return (a & b) ^ (a | b); |
| 431 | 431 | \\} |
| 432 | 432 | , |
| 433 | \\pub export fn max(a: c_int, b: c_int) -> c_int { | |
| 433 | \\pub export fn max(a: c_int, b: c_int) c_int { | |
| 434 | 434 | \\ return (a & b) ^ (a | b); |
| 435 | 435 | \\} |
| 436 | 436 | ); |
| ... | ... | @@ -444,7 +444,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 444 | 444 | \\ return a; |
| 445 | 445 | \\} |
| 446 | 446 | , |
| 447 | \\pub export fn max(a: c_int, b: c_int) -> c_int { | |
| 447 | \\pub export fn max(a: c_int, b: c_int) c_int { | |
| 448 | 448 | \\ if ((a < b) or (a == b)) return b; |
| 449 | 449 | \\ if ((a >= b) and (a == b)) return a; |
| 450 | 450 | \\ return a; |
| ... | ... | @@ -458,7 +458,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 458 | 458 | \\ a = tmp; |
| 459 | 459 | \\} |
| 460 | 460 | , |
| 461 | \\pub export fn max(_arg_a: c_int) -> c_int { | |
| 461 | \\pub export fn max(_arg_a: c_int) c_int { | |
| 462 | 462 | \\ var a = _arg_a; |
| 463 | 463 | \\ var tmp: c_int = undefined; |
| 464 | 464 | \\ tmp = a; |
| ... | ... | @@ -472,7 +472,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 472 | 472 | \\ c = b = a; |
| 473 | 473 | \\} |
| 474 | 474 | , |
| 475 | \\pub export fn max(a: c_int) { | |
| 475 | \\pub export fn max(a: c_int) void { | |
| 476 | 476 | \\ var b: c_int = undefined; |
| 477 | 477 | \\ var c: c_int = undefined; |
| 478 | 478 | \\ c = x: { |
| ... | ... | @@ -493,7 +493,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 493 | 493 | \\ return i; |
| 494 | 494 | \\} |
| 495 | 495 | , |
| 496 | \\pub export fn log2(_arg_a: u32) -> c_int { | |
| 496 | \\pub export fn log2(_arg_a: u32) c_int { | |
| 497 | 497 | \\ var a = _arg_a; |
| 498 | 498 | \\ var i: c_int = 0; |
| 499 | 499 | \\ while (a > c_uint(0)) { |
| ... | ... | @@ -517,8 +517,8 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 517 | 517 | \\static void bar(void) { } |
| 518 | 518 | \\void foo(void) { bar(); } |
| 519 | 519 | , |
| 520 | \\pub fn bar() {} | |
| 521 | \\pub export fn foo() { | |
| 520 | \\pub fn bar() void {} | |
| 521 | \\pub export fn foo() void { | |
| 522 | 522 | \\ bar(); |
| 523 | 523 | \\} |
| 524 | 524 | ); |
| ... | ... | @@ -534,7 +534,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 534 | 534 | \\pub const struct_Foo = extern struct { |
| 535 | 535 | \\ field: c_int, |
| 536 | 536 | \\}; |
| 537 | \\pub export fn read_field(foo: ?&struct_Foo) -> c_int { | |
| 537 | \\pub export fn read_field(foo: ?&struct_Foo) c_int { | |
| 538 | 538 | \\ return (??foo).field; |
| 539 | 539 | \\} |
| 540 | 540 | ); |
| ... | ... | @@ -544,7 +544,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 544 | 544 | \\ ;;;;; |
| 545 | 545 | \\} |
| 546 | 546 | , |
| 547 | \\pub export fn foo() {} | |
| 547 | \\pub export fn foo() void {} | |
| 548 | 548 | ); |
| 549 | 549 | |
| 550 | 550 | cases.add("undefined array global", |
| ... | ... | @@ -560,7 +560,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 560 | 560 | \\} |
| 561 | 561 | , |
| 562 | 562 | \\pub var array: [100]c_int = undefined; |
| 563 | \\pub export fn foo(index: c_int) -> c_int { | |
| 563 | \\pub export fn foo(index: c_int) c_int { | |
| 564 | 564 | \\ return array[index]; |
| 565 | 565 | \\} |
| 566 | 566 | ); |
| ... | ... | @@ -571,7 +571,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 571 | 571 | \\ return (int)a; |
| 572 | 572 | \\} |
| 573 | 573 | , |
| 574 | \\pub export fn float_to_int(a: f32) -> c_int { | |
| 574 | \\pub export fn float_to_int(a: f32) c_int { | |
| 575 | 575 | \\ return c_int(a); |
| 576 | 576 | \\} |
| 577 | 577 | ); |
| ... | ... | @@ -581,7 +581,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 581 | 581 | \\ return x; |
| 582 | 582 | \\} |
| 583 | 583 | , |
| 584 | \\pub export fn foo(x: ?&c_ushort) -> ?&c_void { | |
| 584 | \\pub export fn foo(x: ?&c_ushort) ?&c_void { | |
| 585 | 585 | \\ return @ptrCast(?&c_void, x); |
| 586 | 586 | \\} |
| 587 | 587 | ); |
| ... | ... | @@ -592,7 +592,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 592 | 592 | \\ return sizeof(int); |
| 593 | 593 | \\} |
| 594 | 594 | , |
| 595 | \\pub export fn size_of() -> usize { | |
| 595 | \\pub export fn size_of() usize { | |
| 596 | 596 | \\ return @sizeOf(c_int); |
| 597 | 597 | \\} |
| 598 | 598 | ); |
| ... | ... | @@ -602,7 +602,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 602 | 602 | \\ return 0; |
| 603 | 603 | \\} |
| 604 | 604 | , |
| 605 | \\pub export fn foo() -> ?&c_int { | |
| 605 | \\pub export fn foo() ?&c_int { | |
| 606 | 606 | \\ return null; |
| 607 | 607 | \\} |
| 608 | 608 | ); |
| ... | ... | @@ -612,7 +612,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 612 | 612 | \\ return 1, 2; |
| 613 | 613 | \\} |
| 614 | 614 | , |
| 615 | \\pub export fn foo() -> c_int { | |
| 615 | \\pub export fn foo() c_int { | |
| 616 | 616 | \\ return x: { |
| 617 | 617 | \\ _ = 1; |
| 618 | 618 | \\ break :x 2; |
| ... | ... | @@ -625,7 +625,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 625 | 625 | \\ return (1 << 2) >> 1; |
| 626 | 626 | \\} |
| 627 | 627 | , |
| 628 | \\pub export fn foo() -> c_int { | |
| 628 | \\pub export fn foo() c_int { | |
| 629 | 629 | \\ return (1 << @import("std").math.Log2Int(c_int)(2)) >> @import("std").math.Log2Int(c_int)(1); |
| 630 | 630 | \\} |
| 631 | 631 | ); |
| ... | ... | @@ -643,7 +643,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 643 | 643 | \\ a <<= (a <<= 1); |
| 644 | 644 | \\} |
| 645 | 645 | , |
| 646 | \\pub export fn foo() { | |
| 646 | \\pub export fn foo() void { | |
| 647 | 647 | \\ var a: c_int = 0; |
| 648 | 648 | \\ a += x: { |
| 649 | 649 | \\ const _ref = &a; |
| ... | ... | @@ -701,7 +701,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 701 | 701 | \\ a <<= (a <<= 1); |
| 702 | 702 | \\} |
| 703 | 703 | , |
| 704 | \\pub export fn foo() { | |
| 704 | \\pub export fn foo() void { | |
| 705 | 705 | \\ var a: c_uint = c_uint(0); |
| 706 | 706 | \\ a +%= x: { |
| 707 | 707 | \\ const _ref = &a; |
| ... | ... | @@ -771,7 +771,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 771 | 771 | \\ u = u--; |
| 772 | 772 | \\} |
| 773 | 773 | , |
| 774 | \\pub export fn foo() { | |
| 774 | \\pub export fn foo() void { | |
| 775 | 775 | \\ var i: c_int = 0; |
| 776 | 776 | \\ var u: c_uint = c_uint(0); |
| 777 | 777 | \\ i += 1; |
| ... | ... | @@ -819,7 +819,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 819 | 819 | \\ u = --u; |
| 820 | 820 | \\} |
| 821 | 821 | , |
| 822 | \\pub export fn foo() { | |
| 822 | \\pub export fn foo() void { | |
| 823 | 823 | \\ var i: c_int = 0; |
| 824 | 824 | \\ var u: c_uint = c_uint(0); |
| 825 | 825 | \\ i += 1; |
| ... | ... | @@ -862,7 +862,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 862 | 862 | \\ while (b != 0); |
| 863 | 863 | \\} |
| 864 | 864 | , |
| 865 | \\pub export fn foo() { | |
| 865 | \\pub export fn foo() void { | |
| 866 | 866 | \\ var a: c_int = 2; |
| 867 | 867 | \\ while (true) { |
| 868 | 868 | \\ a -= 1; |
| ... | ... | @@ -886,10 +886,10 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 886 | 886 | \\ baz(); |
| 887 | 887 | \\} |
| 888 | 888 | , |
| 889 | \\pub export fn foo() {} | |
| 890 | \\pub export fn baz() {} | |
| 891 | \\pub export fn bar() { | |
| 892 | \\ var f: ?extern fn() = foo; | |
| 889 | \\pub export fn foo() void {} | |
| 890 | \\pub export fn baz() void {} | |
| 891 | \\pub export fn bar() void { | |
| 892 | \\ var f: ?extern fn() void = foo; | |
| 893 | 893 | \\ (??f)(); |
| 894 | 894 | \\ (??f)(); |
| 895 | 895 | \\ baz(); |
| ... | ... | @@ -901,7 +901,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 901 | 901 | \\ *x = 1; |
| 902 | 902 | \\} |
| 903 | 903 | , |
| 904 | \\pub export fn foo(x: ?&c_int) { | |
| 904 | \\pub export fn foo(x: ?&c_int) void { | |
| 905 | 905 | \\ (*??x) = 1; |
| 906 | 906 | \\} |
| 907 | 907 | ); |
| ... | ... | @@ -927,7 +927,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 927 | 927 | \\ return *ptr; |
| 928 | 928 | \\} |
| 929 | 929 | , |
| 930 | \\pub fn foo() -> c_int { | |
| 930 | \\pub fn foo() c_int { | |
| 931 | 931 | \\ var x: c_int = 1234; |
| 932 | 932 | \\ var ptr: ?&c_int = &x; |
| 933 | 933 | \\ return *??ptr; |
| ... | ... | @@ -939,7 +939,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 939 | 939 | \\ return "bar"; |
| 940 | 940 | \\} |
| 941 | 941 | , |
| 942 | \\pub fn foo() -> ?&const u8 { | |
| 942 | \\pub fn foo() ?&const u8 { | |
| 943 | 943 | \\ return c"bar"; |
| 944 | 944 | \\} |
| 945 | 945 | ); |
| ... | ... | @@ -949,7 +949,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 949 | 949 | \\ return; |
| 950 | 950 | \\} |
| 951 | 951 | , |
| 952 | \\pub fn foo() { | |
| 952 | \\pub fn foo() void { | |
| 953 | 953 | \\ return; |
| 954 | 954 | \\} |
| 955 | 955 | ); |
| ... | ... | @@ -959,7 +959,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 959 | 959 | \\ for (int i = 0; i < 10; i += 1) { } |
| 960 | 960 | \\} |
| 961 | 961 | , |
| 962 | \\pub fn foo() { | |
| 962 | \\pub fn foo() void { | |
| 963 | 963 | \\ { |
| 964 | 964 | \\ var i: c_int = 0; |
| 965 | 965 | \\ while (i < 10) : (i += 1) {}; |
| ... | ... | @@ -972,7 +972,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 972 | 972 | \\ for (;;) { } |
| 973 | 973 | \\} |
| 974 | 974 | , |
| 975 | \\pub fn foo() { | |
| 975 | \\pub fn foo() void { | |
| 976 | 976 | \\ while (true) {}; |
| 977 | 977 | \\} |
| 978 | 978 | ); |
| ... | ... | @@ -984,7 +984,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 984 | 984 | \\ } |
| 985 | 985 | \\} |
| 986 | 986 | , |
| 987 | \\pub fn foo() { | |
| 987 | \\pub fn foo() void { | |
| 988 | 988 | \\ while (true) { |
| 989 | 989 | \\ break; |
| 990 | 990 | \\ }; |
| ... | ... | @@ -998,7 +998,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 998 | 998 | \\ } |
| 999 | 999 | \\} |
| 1000 | 1000 | , |
| 1001 | \\pub fn foo() { | |
| 1001 | \\pub fn foo() void { | |
| 1002 | 1002 | \\ while (true) { |
| 1003 | 1003 | \\ continue; |
| 1004 | 1004 | \\ }; |
| ... | ... | @@ -1021,9 +1021,9 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 1021 | 1021 | , |
| 1022 | 1022 | \\pub const GLbitfield = c_uint; |
| 1023 | 1023 | , |
| 1024 | \\pub const PFNGLCLEARPROC = ?extern fn(GLbitfield); | |
| 1024 | \\pub const PFNGLCLEARPROC = ?extern fn(GLbitfield) void; | |
| 1025 | 1025 | , |
| 1026 | \\pub const OpenGLProc = ?extern fn(); | |
| 1026 | \\pub const OpenGLProc = ?extern fn() void; | |
| 1027 | 1027 | , |
| 1028 | 1028 | \\pub const union_OpenGLProcs = extern union { |
| 1029 | 1029 | \\ ptr: [1]OpenGLProc, |
| ... | ... | @@ -1036,7 +1036,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 1036 | 1036 | , |
| 1037 | 1037 | \\pub const glClearPFN = PFNGLCLEARPROC; |
| 1038 | 1038 | , |
| 1039 | \\pub inline fn glClearUnion(arg0: GLbitfield) { | |
| 1039 | \\pub inline fn glClearUnion(arg0: GLbitfield) void { | |
| 1040 | 1040 | \\ return (??glProcs.gl.Clear)(arg0); |
| 1041 | 1041 | \\} |
| 1042 | 1042 | , |
| ... | ... | @@ -1053,7 +1053,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 1053 | 1053 | \\ return x; |
| 1054 | 1054 | \\} |
| 1055 | 1055 | , |
| 1056 | \\pub fn foo() -> c_int { | |
| 1056 | \\pub fn foo() c_int { | |
| 1057 | 1057 | \\ var x: c_int = 1; |
| 1058 | 1058 | \\ { |
| 1059 | 1059 | \\ var x_0: c_int = 2; |
| ... | ... | @@ -1068,7 +1068,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 1068 | 1068 | \\ return (float *)a; |
| 1069 | 1069 | \\} |
| 1070 | 1070 | , |
| 1071 | \\fn ptrcast(a: ?&c_int) -> ?&f32 { | |
| 1071 | \\fn ptrcast(a: ?&c_int) ?&f32 { | |
| 1072 | 1072 | \\ return @ptrCast(?&f32, a); |
| 1073 | 1073 | \\} |
| 1074 | 1074 | ); |
| ... | ... | @@ -1078,7 +1078,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 1078 | 1078 | \\ return ~x; |
| 1079 | 1079 | \\} |
| 1080 | 1080 | , |
| 1081 | \\pub fn foo(x: c_int) -> c_int { | |
| 1081 | \\pub fn foo(x: c_int) c_int { | |
| 1082 | 1082 | \\ return ~x; |
| 1083 | 1083 | \\} |
| 1084 | 1084 | ); |
| ... | ... | @@ -1088,7 +1088,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 1088 | 1088 | \\ return u32; |
| 1089 | 1089 | \\} |
| 1090 | 1090 | , |
| 1091 | \\pub fn foo(u32_0: c_int) -> c_int { | |
| 1091 | \\pub fn foo(u32_0: c_int) c_int { | |
| 1092 | 1092 | \\ return u32_0; |
| 1093 | 1093 | \\} |
| 1094 | 1094 | ); |
| ... | ... | @@ -1104,7 +1104,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 1104 | 1104 | \\ static const char v2[] = "2.2.2"; |
| 1105 | 1105 | \\} |
| 1106 | 1106 | , |
| 1107 | \\pub fn foo() { | |
| 1107 | \\pub fn foo() void { | |
| 1108 | 1108 | \\ const v2: &const u8 = c"2.2.2"; |
| 1109 | 1109 | \\} |
| 1110 | 1110 | ); |
| ... | ... | @@ -1124,7 +1124,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 1124 | 1124 | \\ } |
| 1125 | 1125 | \\} |
| 1126 | 1126 | , |
| 1127 | \\pub fn if_int(i: c_int) -> c_int { | |
| 1127 | \\pub fn if_int(i: c_int) c_int { | |
| 1128 | 1128 | \\ { |
| 1129 | 1129 | \\ const _tmp = i; |
| 1130 | 1130 | \\ if (@bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0) { |