diff --git a/CMakeLists.txt b/CMakeLists.txt index f7c990794c..12b7efb06a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -463,11 +463,14 @@ set(ZIG_STD_FILES "empty.zig" "event.zig" "event/channel.zig" + "event/fs.zig" "event/future.zig" "event/group.zig" "event/lock.zig" "event/locked.zig" "event/loop.zig" + "event/rwlock.zig" + "event/rwlocked.zig" "event/tcp.zig" "fmt/errol/enum3.zig" "fmt/errol/index.zig" @@ -556,6 +559,7 @@ set(ZIG_STD_FILES "math/tanh.zig" "math/trunc.zig" "mem.zig" + "mutex.zig" "net.zig" "os/child_process.zig" "os/darwin.zig" diff --git a/build.zig b/build.zig index dd939365a2..6584e5ab1f 100644 --- a/build.zig +++ b/build.zig @@ -19,7 +19,7 @@ pub fn build(b: *Builder) !void { var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{ docgen_exe.getOutputPath(), rel_zig_exe, - "doc/langref.html.in", + "doc" ++ os.path.sep_str ++ "langref.html.in", os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable, }); docgen_cmd.step.dependOn(&docgen_exe.step); diff --git a/cmake/Findllvm.cmake b/cmake/Findllvm.cmake index 788e57a644..a554fc21d6 100644 --- a/cmake/Findllvm.cmake +++ b/cmake/Findllvm.cmake @@ -8,7 +8,7 @@ # LLVM_LIBDIRS find_program(LLVM_CONFIG_EXE - NAMES llvm-config-7.0 llvm-config + NAMES llvm-config llvm-config-7.0 PATHS "/mingw64/bin" "/c/msys64/mingw64/bin" diff --git a/doc/docgen.zig b/doc/docgen.zig index e2da1fe6cc..3145c4483e 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -34,10 +34,10 @@ pub fn main() !void { const out_file_name = try (args_it.next(allocator) orelse @panic("expected output arg")); defer allocator.free(out_file_name); - var in_file = try os.File.openRead(allocator, in_file_name); + var in_file = try os.File.openRead(in_file_name); defer in_file.close(); - var out_file = try os.File.openWrite(allocator, out_file_name); + var out_file = try os.File.openWrite(out_file_name); defer out_file.close(); var file_in_stream = io.FileInStream.init(&in_file); @@ -370,9 +370,9 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { .n = header_stack_size, }, }); - if (try urls.put(urlized, tag_token)) |other_tag_token| { + if (try urls.put(urlized, tag_token)) |entry| { parseError(tokenizer, tag_token, "duplicate header url: #{}", urlized) catch {}; - parseError(tokenizer, other_tag_token, "other tag here") catch {}; + parseError(tokenizer, entry.value, "other tag here") catch {}; return error.ParseError; } if (last_action == Action.Open) { @@ -738,7 +738,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var try out.print("
{}
", escaped_source); const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name); const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext); - try io.writeFile(allocator, tmp_source_file_name, trimmed_raw_source); + try io.writeFile(tmp_source_file_name, trimmed_raw_source); switch (code.id) { Code.Id.Exe => |expected_outcome| { diff --git a/doc/langref.html.in b/doc/langref.html.in index 54677bc5b5..465f3c56a7 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -247,66 +247,6 @@ pub fn main() void { Description - - i2 - (none) - signed 2-bit integer - - - u2 - (none) - unsigned 2-bit integer - - - i3 - (none) - signed 3-bit integer - - - u3 - (none) - unsigned 3-bit integer - - - i4 - (none) - signed 4-bit integer - - - u4 - (none) - unsigned 4-bit integer - - - i5 - (none) - signed 5-bit integer - - - u5 - (none) - unsigned 5-bit integer - - - i6 - (none) - signed 6-bit integer - - - u6 - (none) - unsigned 6-bit integer - - - i7 - (none) - signed 7-bit integer - - - u7 - (none) - unsigned 7-bit integer - i8 int8_t @@ -476,6 +416,11 @@ pub fn main() void { +

+ In addition to the integer types above, arbitrary bit-width integers can be referenced by using + an identifier of i or u followed by digits. For example, the identifier + i7 refers to a signed 7-bit integer. +

{#see_also|Integers|Floats|void|Errors#} {#header_close#} {#header_open|Primitive Values#} @@ -744,19 +689,19 @@ const yet_another_hex_float = 0x103.70P-5; {#code_end#} {#header_close#} {#header_open|Floating Point Operations#} -

By default floating point operations use Optimized mode, - but you can switch to Strict mode on a per-block basis:

+

By default floating point operations use Strict mode, + but you can switch to Optimized mode on a per-block basis:

{#code_begin|obj|foo#} {#code_release_fast#} const builtin = @import("builtin"); const big = f64(1 << 40); export fn foo_strict(x: f64) f64 { - @setFloatMode(this, builtin.FloatMode.Strict); return x + big - big; } export fn foo_optimized(x: f64) f64 { + @setFloatMode(this, builtin.FloatMode.Optimized); return x + big - big; } {#code_end#} @@ -809,6 +754,8 @@ a += b Addition. @@ -826,6 +773,8 @@ a +%= b Wrapping Addition. @@ -844,6 +793,8 @@ a -= b Subtraction. @@ -861,6 +812,8 @@ a -%= b Wrapping Subtraction. @@ -914,6 +867,8 @@ a *= b Multiplication. @@ -931,6 +886,8 @@ a *%= b Wrapping Multiplication. @@ -956,6 +913,7 @@ a /= b {#link|@divFloor#}, or {#link|@divExact#} instead of /. +
  • Invokes {#link|Peer Type Resolution#} for the operands.
  • @@ -979,6 +937,7 @@ a %= b {#link|@rem#} or {#link|@mod#} instead of %. +
  • Invokes {#link|Peer Type Resolution#} for the operands.
  • @@ -995,6 +954,7 @@ a <<= b Bit Shift Left. @@ -1013,6 +973,7 @@ a >>= b Bit Shift Right. @@ -1029,6 +990,9 @@ a &= b Bitwise AND. +
    0b011 & 0b101 == 0b001
    @@ -1043,6 +1007,9 @@ a |= b Bitwise OR. +
    0b010 | 0b100 == 0b110
    @@ -1057,6 +1024,9 @@ a ^= b Bitwise XOR. +
    0b011 ^ 0b101 == 0b110
    @@ -1186,6 +1156,7 @@ unwrapped == 1234 Returns true if a and b are equal, otherwise returns false. + Invokes {#link|Peer Type Resolution#} for the operands.
    (1 == 1) == true
    @@ -1218,6 +1189,7 @@ value == null Returns false if a and b are equal, otherwise returns true. + Invokes {#link|Peer Type Resolution#} for the operands.
    (1 != 1) == false
    @@ -1233,6 +1205,7 @@ value == null Returns true if a is greater than b, otherwise returns false. + Invokes {#link|Peer Type Resolution#} for the operands.
    (2 > 1) == true
    @@ -1248,6 +1221,7 @@ value == null Returns true if a is greater than or equal to b, otherwise returns false. + Invokes {#link|Peer Type Resolution#} for the operands.
    (2 >= 1) == true
    @@ -1263,6 +1237,7 @@ value == null Returns true if a is less than b, otherwise returns false. + Invokes {#link|Peer Type Resolution#} for the operands.
    (1 < 2) == true
    @@ -1278,6 +1253,7 @@ value == null Returns true if a is less than or equal to b, otherwise returns false. + Invokes {#link|Peer Type Resolution#} for the operands.
    (1 <= 2) == true
    @@ -3807,6 +3783,7 @@ test "float widening" {

    TODO: [N]T to ?[]const T

    TODO: *[N]T to []T

    TODO: *[N]T to [*]T

    +

    TODO: *[N]T to ?[*]T

    TODO: *T to *[1]T

    TODO: [N]T to E![]const T

    {#header_close#} @@ -3877,7 +3854,106 @@ test "float widening" { {#header_close#} {#header_open|Peer Type Resolution#} -

    TODO

    +

    Peer Type Resolution occurs in these places:

    + +

    + This kind of type resolution chooses a type that all peer types can implicitly cast into. Here are + some examples: +

    + {#code_begin|test#} +const std = @import("std"); +const assert = std.debug.assert; +const mem = std.mem; + +test "peer resolve int widening" { + var a: i8 = 12; + var b: i16 = 34; + var c = a + b; + assert(c == 46); + assert(@typeOf(c) == i16); +} + +test "peer resolve arrays of different size to const slice" { + assert(mem.eql(u8, boolToStr(true), "true")); + assert(mem.eql(u8, boolToStr(false), "false")); + comptime assert(mem.eql(u8, boolToStr(true), "true")); + comptime assert(mem.eql(u8, boolToStr(false), "false")); +} +fn boolToStr(b: bool) []const u8 { + return if (b) "true" else "false"; +} + +test "peer resolve array and const slice" { + testPeerResolveArrayConstSlice(true); + comptime testPeerResolveArrayConstSlice(true); +} +fn testPeerResolveArrayConstSlice(b: bool) void { + const value1 = if (b) "aoeu" else ([]const u8)("zz"); + const value2 = if (b) ([]const u8)("zz") else "aoeu"; + assert(mem.eql(u8, value1, "aoeu")); + assert(mem.eql(u8, value2, "zz")); +} + +test "peer type resolution: ?T and T" { + assert(peerTypeTAndOptionalT(true, false).? == 0); + assert(peerTypeTAndOptionalT(false, false).? == 3); + comptime { + assert(peerTypeTAndOptionalT(true, false).? == 0); + assert(peerTypeTAndOptionalT(false, false).? == 3); + } +} +fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { + if (c) { + return if (b) null else usize(0); + } + + return usize(3); +} + +test "peer type resolution: [0]u8 and []const u8" { + assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); + assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); + comptime { + assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); + assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); + } +} +fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { + if (a) { + return []const u8{}; + } + + return slice[0..1]; +} +test "peer type resolution: [0]u8, []const u8, and error![]u8" { + { + var data = "hi"; + const slice = data[0..]; + assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); + assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); + } + comptime { + var data = "hi"; + const slice = data[0..]; + assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); + assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); + } +} +fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) error![]u8 { + if (a) { + return []u8{}; + } + + return slice[0..1]; +} + {#code_end#} {#header_close#} {#header_close#} @@ -4705,10 +4781,7 @@ async fn testSuspendBlock() void {

    {#link|Await#} counts as a suspend point.

    - {#header_open|Breaking from Suspend Blocks#} -

    - Suspend blocks support labeled break, just like {#link|while#} and {#link|for#}. -

    + {#header_open|Resuming from Suspend Blocks#}

    Upon entering a suspend block, the coroutine is already considered suspended, and can be resumed. For example, if you started another kernel thread, @@ -4741,6 +4814,9 @@ async fn testResumeFromSuspend(my_result: *i32) void { my_result.* += 1; } {#code_end#} +

    + This is guaranteed to be a tail call, and therefore will not cause a new stack frame. +

    {#header_close#} {#header_close#} {#header_open|Await#} @@ -5527,7 +5603,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }

    Returns the field type of a struct or union.

    {#header_close#} {#header_open|@memcpy#} -
    @memcpy(noalias dest: *u8, noalias source: *const u8, byte_count: usize)
    +
    @memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize)

    This function copies bytes from one region of memory to another. dest and source are both pointers and must not overlap. @@ -5545,7 +5621,7 @@ fn add(a: i32, b: i32) i32 { return a + b; } mem.copy(u8, dest[0...byte_count], source[0...byte_count]); {#header_close#} {#header_open|@memset#} -

    @memset(dest: *u8, c: u8, byte_count: usize)
    +
    @memset(dest: [*]u8, c: u8, byte_count: usize)

    This function sets a region of memory to c. dest is a pointer.

    @@ -5817,7 +5893,7 @@ pub const FloatMode = enum { {#code_end#}