authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-04 20:43:49-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-04 20:43:49-04:00
logb5d07297dec61a3993dfe91ceee2c87672db1e8e
tree519d097fcdfe121e38814a080868a85f5b1f9e64
parent9665cfe027c70a84cb6351ea6ecb833a728736aa
parent8c39cdc89f2ae7fc25c3856e7c4c6b4662ac8a80

Merge remote-tracking branch 'origin/master' into llvm7


13 files changed, 168 insertions(+), 75 deletions(-)

.gitattributes+1
......@@ -1 +1,2 @@
11*.zig text eol=lf
2langref.html.in text eol=lf
doc/langref.html.in+95-32
......@@ -616,6 +616,17 @@ test "init with undefined" {
616616 assert(x == 1);
617617}
618618 {#code_end#}
619 <p>
620 <code>undefined</code> can be {#link|implicitly cast|Implicit Casts#} to any type.
621 Once this happens, it is no longer possible to detect that the value is <code>undefined</code>.
622 <code>undefined</code> means the value could be anything, even something that is nonsense
623 according to the type. Translated into English, <code>undefined</code> means "Not a meaningful
624 value. Using this value would be a bug. The value will be unused, or overwritten before being used."
625 </p>
626 <p>
627 In {#link|Debug#} mode, Zig writes <code>0xaa</code> bytes to undefined memory. This is to catch
628 bugs early, and to help detect use of undefined memory in a debugger.
629 </p>
619630 {#header_close#}
620631 {#header_close#}
621632 {#header_close#}
......@@ -2237,21 +2248,28 @@ test "switch inside function" {
22372248 {#see_also|comptime|enum|@compileError|Compile Variables#}
22382249 {#header_close#}
22392250 {#header_open|while#}
2251 <p>
2252 A while loop is used to repeatedly execute an expression until
2253 some condition is no longer true.
2254 </p>
22402255 {#code_begin|test|while#}
22412256const assert = @import("std").debug.assert;
22422257
22432258test "while basic" {
2244 // A while loop is used to repeatedly execute an expression until
2245 // some condition is no longer true.
22462259 var i: usize = 0;
22472260 while (i < 10) {
22482261 i += 1;
22492262 }
22502263 assert(i == 10);
22512264}
2265 {#code_end#}
2266 <p>
2267 Use <code>break</code> to exit a while loop early.
2268 </p>
2269 {#code_begin|test|while#}
2270const assert = @import("std").debug.assert;
22522271
22532272test "while break" {
2254 // You can use break to exit a while loop early.
22552273 var i: usize = 0;
22562274 while (true) {
22572275 if (i == 10)
......@@ -2260,9 +2278,14 @@ test "while break" {
22602278 }
22612279 assert(i == 10);
22622280}
2281 {#code_end#}
2282 <p>
2283 Use <code>continue</code> to jump back to the beginning of the loop.
2284 </p>
2285 {#code_begin|test|while#}
2286const assert = @import("std").debug.assert;
22632287
22642288test "while continue" {
2265 // You can use continue to jump back to the beginning of the loop.
22662289 var i: usize = 0;
22672290 while (true) {
22682291 i += 1;
......@@ -2272,18 +2295,21 @@ test "while continue" {
22722295 }
22732296 assert(i == 10);
22742297}
2298 {#code_end#}
2299 <p>
2300 While loops support a continue expression which is executed when the loop
2301 is continued. The <code>continue</code> keyword respects this expression.
2302 </p>
2303 {#code_begin|test|while#}
2304const assert = @import("std").debug.assert;
22752305
22762306test "while loop continuation expression" {
2277 // You can give an expression to the while loop to execute when
2278 // the loop is continued. This is respected by the continue control flow.
22792307 var i: usize = 0;
22802308 while (i < 10) : (i += 1) {}
22812309 assert(i == 10);
22822310}
22832311
22842312test "while loop continuation expression, more complicated" {
2285 // More complex blocks can be used as an expression in the loop continue
2286 // expression.
22872313 var i1: usize = 1;
22882314 var j1: usize = 1;
22892315 while (i1 * j1 < 2000) : ({ i1 *= 2; j1 *= 3; }) {
......@@ -2291,6 +2317,20 @@ test "while loop continuation expression, more complicated" {
22912317 assert(my_ij1 < 2000);
22922318 }
22932319}
2320 {#code_end#}
2321 <p>
2322 While loops are expressions. The result of the expression is the
2323 result of the <code>else</code> clause of a while loop, which is executed when
2324 the condition of the while loop is tested as false.
2325 </p>
2326 <p>
2327 <code>break</code>, like <code>return</code>, accepts a value
2328 parameter. This is the result of the <code>while</code> expression.
2329 When you <code>break</code> from a while loop, the <code>else</code> branch is not
2330 evaluated.
2331 </p>
2332 {#code_begin|test|while#}
2333const assert = @import("std").debug.assert;
22942334
22952335test "while else" {
22962336 assert(rangeHasNumber(0, 10, 5));
......@@ -2299,24 +2339,31 @@ test "while else" {
22992339
23002340fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {
23012341 var i = begin;
2302 // While loops are expressions. The result of the expression is the
2303 // result of the else clause of a while loop, which is executed when
2304 // the condition of the while loop is tested as false.
23052342 return while (i < end) : (i += 1) {
23062343 if (i == number) {
2307 // break expressions, like return expressions, accept a value
2308 // parameter. This is the result of the while expression.
2309 // When you break from a while loop, the else branch is not
2310 // evaluated.
23112344 break true;
23122345 }
23132346 } else false;
23142347}
2348 {#code_end#}
2349 {#header_open|while with Optionals#}
2350 <p>
2351 Just like {#link|if#} expressions, while loops can take an optional as the
2352 condition and capture the payload. When {#link|null#} is encountered the loop
2353 exits.
2354 </p>
2355 <p>
2356 When the <code>|x|</code> syntax is present on a <code>while</code> expression,
2357 the while condition must have an {#link|Optional Type#}.
2358 </p>
2359 <p>
2360 The <code>else</code> branch is allowed on optional iteration. In this case, it will
2361 be executed on the first null value encountered.
2362 </p>
2363 {#code_begin|test|while#}
2364const assert = @import("std").debug.assert;
23152365
23162366test "while null capture" {
2317 // Just like if expressions, while loops can take an optional as the
2318 // condition and capture the payload. When null is encountered the loop
2319 // exits.
23202367 var sum1: u32 = 0;
23212368 numbers_left = 3;
23222369 while (eventuallyNullSequence()) |value| {
......@@ -2324,8 +2371,6 @@ test "while null capture" {
23242371 }
23252372 assert(sum1 == 3);
23262373
2327 // The else branch is allowed on optional iteration. In this case, it will
2328 // be executed on the first null value encountered.
23292374 var sum2: u32 = 0;
23302375 numbers_left = 3;
23312376 while (eventuallyNullSequence()) |value| {
......@@ -2333,18 +2378,6 @@ test "while null capture" {
23332378 } else {
23342379 assert(sum1 == 3);
23352380 }
2336
2337 // Just like if expressions, while loops can also take an error union as
2338 // the condition and capture the payload or the error code. When the
2339 // condition results in an error code the else branch is evaluated and
2340 // the loop is finished.
2341 var sum3: u32 = 0;
2342 numbers_left = 3;
2343 while (eventuallyErrorSequence()) |value| {
2344 sum3 += value;
2345 } else |err| {
2346 assert(err == error.ReachedZero);
2347 }
23482381}
23492382
23502383var numbers_left: u32 = undefined;
......@@ -2355,6 +2388,35 @@ fn eventuallyNullSequence() ?u32 {
23552388 };
23562389}
23572390
2391 {#code_end#}
2392 {#header_close#}
2393
2394 {#header_open|while with Error Unions#}
2395 <p>
2396 Just like {#link|if#} expressions, while loops can take an error union as
2397 the condition and capture the payload or the error code. When the
2398 condition results in an error code the else branch is evaluated and
2399 the loop is finished.
2400 </p>
2401 <p>
2402 When the <code>else |x|</code> syntax is present on a <code>while</code> expression,
2403 the while condition must have an {#link|Error Union Type#}.
2404 </p>
2405 {#code_begin|test|while#}
2406const assert = @import("std").debug.assert;
2407
2408test "while error union capture" {
2409 var sum1: u32 = 0;
2410 numbers_left = 3;
2411 while (eventuallyErrorSequence()) |value| {
2412 sum1 += value;
2413 } else |err| {
2414 assert(err == error.ReachedZero);
2415 }
2416}
2417
2418var numbers_left: u32 = undefined;
2419
23582420fn eventuallyErrorSequence() error!u32 {
23592421 return if (numbers_left == 0) error.ReachedZero else blk: {
23602422 numbers_left -= 1;
......@@ -2362,6 +2424,7 @@ fn eventuallyErrorSequence() error!u32 {
23622424 };
23632425}
23642426 {#code_end#}
2427 {#header_close#}
23652428
23662429 {#header_open|inline while#}
23672430 <p>
src/analyze.cpp+2-10
......@@ -4417,22 +4417,14 @@ Buf *get_linux_libc_include_path(void) {
44174417 }
44184418 char *prev_newline = buf_ptr(out_stderr);
44194419 ZigList<const char *> search_paths = {};
4420 bool found_search_paths = false;
44214420 for (;;) {
44224421 char *newline = strchr(prev_newline, '\n');
44234422 if (newline == nullptr) {
4424 zig_panic("unable to determine libc include path: bad output from C compiler command");
4423 break;
44254424 }
44264425 *newline = 0;
4427 if (found_search_paths) {
4428 if (strcmp(prev_newline, "End of search list.") == 0) {
4429 break;
4430 }
4426 if (prev_newline[0] == ' ') {
44314427 search_paths.append(prev_newline);
4432 } else {
4433 if (strcmp(prev_newline, "#include <...> search starts here:") == 0) {
4434 found_search_paths = true;
4435 }
44364428 }
44374429 prev_newline = newline + 1;
44384430 }
src/ir.cpp+4-8
......@@ -6674,7 +6674,10 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
66746674 }
66756675 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
66766676 IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_field_name);
6677 // If the type of the result handle_is_ptr then this does not actually perform a load. But we need it to,
6678 // because we're about to destroy the memory. So we store it into our result variable.
66776679 IrInstruction *no_suspend_result = ir_build_load_ptr(irb, parent_scope, node, promise_result_ptr);
6680 ir_build_store_ptr(irb, parent_scope, node, my_result_var_ptr, no_suspend_result);
66786681 ir_build_cancel(irb, parent_scope, node, target_inst);
66796682 ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);
66806683
......@@ -6696,17 +6699,10 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
66966699 ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));
66976700
66986701 ir_set_cursor_at_end_and_append_block(irb, resume_block);
6699 IrInstruction *yes_suspend_result = ir_build_load_ptr(irb, parent_scope, node, my_result_var_ptr);
67006702 ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);
67016703
67026704 ir_set_cursor_at_end_and_append_block(irb, merge_block);
6703 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
6704 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
6705 incoming_blocks[0] = resume_block;
6706 incoming_values[0] = yes_suspend_result;
6707 incoming_blocks[1] = no_suspend_block;
6708 incoming_values[1] = no_suspend_result;
6709 return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);
6705 return ir_build_load_ptr(irb, parent_scope, node, my_result_var_ptr);
67106706}
67116707
67126708static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
std/mem.zig+1-1
......@@ -34,7 +34,7 @@ pub const Allocator = struct {
3434 /// Call `destroy` with the result
3535 pub fn create(self: *Allocator, init: var) Error!*@typeOf(init) {
3636 const T = @typeOf(init);
37 if (@sizeOf(T) == 0) return &{};
37 if (@sizeOf(T) == 0) return &(T{});
3838 const slice = try self.alloc(T, 1);
3939 const ptr = &slice[0];
4040 ptr.* = init;
std/special/compiler_rt/comparetf2.zig+2-2
......@@ -1,4 +1,4 @@
1// TODO https://github.com/ziglang/zig/issues/305
1// TODO https://github.com/ziglang/zig/issues/641
22// and then make the return types of some of these functions the enum instead of c_int
33const LE_LESS = c_int(-1);
44const LE_EQUAL = c_int(0);
......@@ -56,7 +56,7 @@ pub extern fn __letf2(a: f128, b: f128) c_int {
5656 LE_GREATER;
5757}
5858
59// TODO https://github.com/ziglang/zig/issues/305
59// TODO https://github.com/ziglang/zig/issues/641
6060// and then make the return types of some of these functions the enum instead of c_int
6161const GE_LESS = c_int(-1);
6262const GE_EQUAL = c_int(0);
std/special/compiler_rt/fixuint.zig-6
......@@ -44,14 +44,8 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t
4444 // If 0 <= exponent < significandBits, right shift to get the result.
4545 // Otherwise, shift left.
4646 if (exponent < significandBits) {
47 // TODO this is a workaround for the mysterious "integer cast truncated bits"
48 // happening on the next line
49 @setRuntimeSafety(false);
5047 return @intCast(fixuint_t, significand >> @intCast(Log2Int(rep_t), significandBits - exponent));
5148 } else {
52 // TODO this is a workaround for the mysterious "integer cast truncated bits"
53 // happening on the next line
54 @setRuntimeSafety(false);
5549 return @intCast(fixuint_t, significand) << @intCast(Log2Int(fixuint_t), exponent - significandBits);
5650 }
5751}
std/special/compiler_rt/fixunstfdi_test.zig+10-11
......@@ -36,15 +36,14 @@ test "fixunstfdi" {
3636 test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0);
3737 test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0);
3838
39 // TODO enable these tests when we can parse f128 float literals
40 //test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);
41 //test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001);
42 //test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000);
43 //test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);
44 //test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);
45 //test__fixunstfdi(0x1.p+64, 0xFFFFFFFFFFFFFFFF);
46
47 //test__fixunstfdi(-0x1.0000000000000000p+63, 0);
48 //test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0);
49 //test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0);
39 test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);
40 test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001);
41 test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000);
42 test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);
43 test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);
44 test__fixunstfdi(0x1.p+64, 0xFFFFFFFFFFFFFFFF);
45
46 test__fixunstfdi(-0x1.0000000000000000p+63, 0);
47 test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0);
48 test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0);
5049}
std/special/compiler_rt/fixunstfsi_test.zig+2-2
......@@ -11,9 +11,9 @@ const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000));
1111test "fixunstfsi" {
1212 test__fixunstfsi(inf128, 0xffffffff);
1313 test__fixunstfsi(0, 0x0);
14 //TODO test__fixunstfsi(0x1.23456789abcdefp+5, 0x24);
14 test__fixunstfsi(0x1.23456789abcdefp+5, 0x24);
1515 test__fixunstfsi(0x1.23456789abcdefp-3, 0x0);
16 //TODO test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456);
16 test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456);
1717 test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff);
1818 test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff);
1919 test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0);
std/special/compiler_rt/floatunsitf.zig+1-1
......@@ -17,7 +17,7 @@ pub extern fn __floatunsitf(a: u64) f128 {
1717 const exp = (u64.bit_count - 1) - @clz(a);
1818 const shift = mantissa_bits - @intCast(u7, exp);
1919
20 // TODO: @bitCast alignment error
20 // TODO(#1148): @bitCast alignment error
2121 var result align(16) = (@intCast(u128, a) << shift) ^ implicit_bit;
2222 result += (@intCast(u128, exp) + exponent_bias) << mantissa_bits;
2323
test/behavior.zig+1
......@@ -18,6 +18,7 @@ comptime {
1818 _ = @import("cases/cast.zig");
1919 _ = @import("cases/const_slice_child.zig");
2020 _ = @import("cases/coroutines.zig");
21 _ = @import("cases/coroutine_await_struct.zig");
2122 _ = @import("cases/defer.zig");
2223 _ = @import("cases/enum.zig");
2324 _ = @import("cases/enum_with_members.zig");
test/cases/coroutine_await_struct.zig created+47
......@@ -0,0 +1,47 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4
5const Foo = struct {
6 x: i32,
7};
8
9var await_a_promise: promise = undefined;
10var await_final_result = Foo{ .x = 0 };
11
12test "coroutine await struct" {
13 var da = std.heap.DirectAllocator.init();
14 defer da.deinit();
15
16 await_seq('a');
17 const p = async<&da.allocator> await_amain() catch unreachable;
18 await_seq('f');
19 resume await_a_promise;
20 await_seq('i');
21 assert(await_final_result.x == 1234);
22 assert(std.mem.eql(u8, await_points, "abcdefghi"));
23}
24async fn await_amain() void {
25 await_seq('b');
26 const p = async await_another() catch unreachable;
27 await_seq('e');
28 await_final_result = await p;
29 await_seq('h');
30}
31async fn await_another() Foo {
32 await_seq('c');
33 suspend |p| {
34 await_seq('d');
35 await_a_promise = p;
36 }
37 await_seq('g');
38 return Foo{ .x = 1234 };
39}
40
41var await_points = []u8{0} ** "abcdefghi".len;
42var await_seq_index: usize = 0;
43
44fn await_seq(c: u8) void {
45 await_points[await_seq_index] = c;
46 await_seq_index += 1;
47}
test/cases/coroutines.zig+2-2
......@@ -116,14 +116,14 @@ test "coroutine await early return" {
116116 defer da.deinit();
117117
118118 early_seq('a');
119 const p = async<&da.allocator> early_amain() catch unreachable;
119 const p = async<&da.allocator> early_amain() catch @panic("out of memory");
120120 early_seq('f');
121121 assert(early_final_result == 1234);
122122 assert(std.mem.eql(u8, early_points, "abcdef"));
123123}
124124async fn early_amain() void {
125125 early_seq('b');
126 const p = async early_another() catch unreachable;
126 const p = async early_another() catch @panic("out of memory");
127127 early_seq('d');
128128 early_final_result = await p;
129129 early_seq('e');