| author | |
| committer | |
| log | b5d07297dec61a3993dfe91ceee2c87672db1e8e |
| tree | 519d097fcdfe121e38814a080868a85f5b1f9e64 |
| parent | 9665cfe027c70a84cb6351ea6ecb833a728736aa |
| parent | 8c39cdc89f2ae7fc25c3856e7c4c6b4662ac8a80 |
13 files changed, 168 insertions(+), 75 deletions(-)
.gitattributes+1| ... | ... | @@ -1 +1,2 @@ |
| 1 | 1 | *.zig text eol=lf |
| 2 | langref.html.in text eol=lf |
doc/langref.html.in+95-32| ... | ... | @@ -616,6 +616,17 @@ test "init with undefined" { |
| 616 | 616 | assert(x == 1); |
| 617 | 617 | } |
| 618 | 618 | {#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> | |
| 619 | 630 | {#header_close#} |
| 620 | 631 | {#header_close#} |
| 621 | 632 | {#header_close#} |
| ... | ... | @@ -2237,21 +2248,28 @@ test "switch inside function" { |
| 2237 | 2248 | {#see_also|comptime|enum|@compileError|Compile Variables#} |
| 2238 | 2249 | {#header_close#} |
| 2239 | 2250 | {#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> | |
| 2240 | 2255 | {#code_begin|test|while#} |
| 2241 | 2256 | const assert = @import("std").debug.assert; |
| 2242 | 2257 | |
| 2243 | 2258 | test "while basic" { |
| 2244 | // A while loop is used to repeatedly execute an expression until | |
| 2245 | // some condition is no longer true. | |
| 2246 | 2259 | var i: usize = 0; |
| 2247 | 2260 | while (i < 10) { |
| 2248 | 2261 | i += 1; |
| 2249 | 2262 | } |
| 2250 | 2263 | assert(i == 10); |
| 2251 | 2264 | } |
| 2265 | {#code_end#} | |
| 2266 | <p> | |
| 2267 | Use <code>break</code> to exit a while loop early. | |
| 2268 | </p> | |
| 2269 | {#code_begin|test|while#} | |
| 2270 | const assert = @import("std").debug.assert; | |
| 2252 | 2271 | |
| 2253 | 2272 | test "while break" { |
| 2254 | // You can use break to exit a while loop early. | |
| 2255 | 2273 | var i: usize = 0; |
| 2256 | 2274 | while (true) { |
| 2257 | 2275 | if (i == 10) |
| ... | ... | @@ -2260,9 +2278,14 @@ test "while break" { |
| 2260 | 2278 | } |
| 2261 | 2279 | assert(i == 10); |
| 2262 | 2280 | } |
| 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#} | |
| 2286 | const assert = @import("std").debug.assert; | |
| 2263 | 2287 | |
| 2264 | 2288 | test "while continue" { |
| 2265 | // You can use continue to jump back to the beginning of the loop. | |
| 2266 | 2289 | var i: usize = 0; |
| 2267 | 2290 | while (true) { |
| 2268 | 2291 | i += 1; |
| ... | ... | @@ -2272,18 +2295,21 @@ test "while continue" { |
| 2272 | 2295 | } |
| 2273 | 2296 | assert(i == 10); |
| 2274 | 2297 | } |
| 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#} | |
| 2304 | const assert = @import("std").debug.assert; | |
| 2275 | 2305 | |
| 2276 | 2306 | test "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. | |
| 2279 | 2307 | var i: usize = 0; |
| 2280 | 2308 | while (i < 10) : (i += 1) {} |
| 2281 | 2309 | assert(i == 10); |
| 2282 | 2310 | } |
| 2283 | 2311 | |
| 2284 | 2312 | test "while loop continuation expression, more complicated" { |
| 2285 | // More complex blocks can be used as an expression in the loop continue | |
| 2286 | // expression. | |
| 2287 | 2313 | var i1: usize = 1; |
| 2288 | 2314 | var j1: usize = 1; |
| 2289 | 2315 | while (i1 * j1 < 2000) : ({ i1 *= 2; j1 *= 3; }) { |
| ... | ... | @@ -2291,6 +2317,20 @@ test "while loop continuation expression, more complicated" { |
| 2291 | 2317 | assert(my_ij1 < 2000); |
| 2292 | 2318 | } |
| 2293 | 2319 | } |
| 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#} | |
| 2333 | const assert = @import("std").debug.assert; | |
| 2294 | 2334 | |
| 2295 | 2335 | test "while else" { |
| 2296 | 2336 | assert(rangeHasNumber(0, 10, 5)); |
| ... | ... | @@ -2299,24 +2339,31 @@ test "while else" { |
| 2299 | 2339 | |
| 2300 | 2340 | fn rangeHasNumber(begin: usize, end: usize, number: usize) bool { |
| 2301 | 2341 | 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. | |
| 2305 | 2342 | return while (i < end) : (i += 1) { |
| 2306 | 2343 | 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. | |
| 2311 | 2344 | break true; |
| 2312 | 2345 | } |
| 2313 | 2346 | } else false; |
| 2314 | 2347 | } |
| 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#} | |
| 2364 | const assert = @import("std").debug.assert; | |
| 2315 | 2365 | |
| 2316 | 2366 | test "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. | |
| 2320 | 2367 | var sum1: u32 = 0; |
| 2321 | 2368 | numbers_left = 3; |
| 2322 | 2369 | while (eventuallyNullSequence()) |value| { |
| ... | ... | @@ -2324,8 +2371,6 @@ test "while null capture" { |
| 2324 | 2371 | } |
| 2325 | 2372 | assert(sum1 == 3); |
| 2326 | 2373 | |
| 2327 | // The else branch is allowed on optional iteration. In this case, it will | |
| 2328 | // be executed on the first null value encountered. | |
| 2329 | 2374 | var sum2: u32 = 0; |
| 2330 | 2375 | numbers_left = 3; |
| 2331 | 2376 | while (eventuallyNullSequence()) |value| { |
| ... | ... | @@ -2333,18 +2378,6 @@ test "while null capture" { |
| 2333 | 2378 | } else { |
| 2334 | 2379 | assert(sum1 == 3); |
| 2335 | 2380 | } |
| 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 | } | |
| 2348 | 2381 | } |
| 2349 | 2382 | |
| 2350 | 2383 | var numbers_left: u32 = undefined; |
| ... | ... | @@ -2355,6 +2388,35 @@ fn eventuallyNullSequence() ?u32 { |
| 2355 | 2388 | }; |
| 2356 | 2389 | } |
| 2357 | 2390 | |
| 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#} | |
| 2406 | const assert = @import("std").debug.assert; | |
| 2407 | ||
| 2408 | test "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 | ||
| 2418 | var numbers_left: u32 = undefined; | |
| 2419 | ||
| 2358 | 2420 | fn eventuallyErrorSequence() error!u32 { |
| 2359 | 2421 | return if (numbers_left == 0) error.ReachedZero else blk: { |
| 2360 | 2422 | numbers_left -= 1; |
| ... | ... | @@ -2362,6 +2424,7 @@ fn eventuallyErrorSequence() error!u32 { |
| 2362 | 2424 | }; |
| 2363 | 2425 | } |
| 2364 | 2426 | {#code_end#} |
| 2427 | {#header_close#} | |
| 2365 | 2428 | |
| 2366 | 2429 | {#header_open|inline while#} |
| 2367 | 2430 | <p> |
src/analyze.cpp+2-10| ... | ... | @@ -4417,22 +4417,14 @@ Buf *get_linux_libc_include_path(void) { |
| 4417 | 4417 | } |
| 4418 | 4418 | char *prev_newline = buf_ptr(out_stderr); |
| 4419 | 4419 | ZigList<const char *> search_paths = {}; |
| 4420 | bool found_search_paths = false; | |
| 4421 | 4420 | for (;;) { |
| 4422 | 4421 | char *newline = strchr(prev_newline, '\n'); |
| 4423 | 4422 | if (newline == nullptr) { |
| 4424 | zig_panic("unable to determine libc include path: bad output from C compiler command"); | |
| 4423 | break; | |
| 4425 | 4424 | } |
| 4426 | 4425 | *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] == ' ') { | |
| 4431 | 4427 | search_paths.append(prev_newline); |
| 4432 | } else { | |
| 4433 | if (strcmp(prev_newline, "#include <...> search starts here:") == 0) { | |
| 4434 | found_search_paths = true; | |
| 4435 | } | |
| 4436 | 4428 | } |
| 4437 | 4429 | prev_newline = newline + 1; |
| 4438 | 4430 | } |
src/ir.cpp+4-8| ... | ... | @@ -6674,7 +6674,10 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast |
| 6674 | 6674 | } |
| 6675 | 6675 | Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME); |
| 6676 | 6676 | 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. | |
| 6677 | 6679 | 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); | |
| 6678 | 6681 | ir_build_cancel(irb, parent_scope, node, target_inst); |
| 6679 | 6682 | ir_build_br(irb, parent_scope, node, merge_block, const_bool_false); |
| 6680 | 6683 | |
| ... | ... | @@ -6696,17 +6699,10 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast |
| 6696 | 6699 | ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false)); |
| 6697 | 6700 | |
| 6698 | 6701 | 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); | |
| 6700 | 6702 | ir_build_br(irb, parent_scope, node, merge_block, const_bool_false); |
| 6701 | 6703 | |
| 6702 | 6704 | 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); | |
| 6710 | 6706 | } |
| 6711 | 6707 | |
| 6712 | 6708 | static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) { |
std/mem.zig+1-1| ... | ... | @@ -34,7 +34,7 @@ pub const Allocator = struct { |
| 34 | 34 | /// Call `destroy` with the result |
| 35 | 35 | pub fn create(self: *Allocator, init: var) Error!*@typeOf(init) { |
| 36 | 36 | const T = @typeOf(init); |
| 37 | if (@sizeOf(T) == 0) return &{}; | |
| 37 | if (@sizeOf(T) == 0) return &(T{}); | |
| 38 | 38 | const slice = try self.alloc(T, 1); |
| 39 | 39 | const ptr = &slice[0]; |
| 40 | 40 | 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 | |
| 2 | 2 | // and then make the return types of some of these functions the enum instead of c_int |
| 3 | 3 | const LE_LESS = c_int(-1); |
| 4 | 4 | const LE_EQUAL = c_int(0); |
| ... | ... | @@ -56,7 +56,7 @@ pub extern fn __letf2(a: f128, b: f128) c_int { |
| 56 | 56 | LE_GREATER; |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | // TODO https://github.com/ziglang/zig/issues/305 | |
| 59 | // TODO https://github.com/ziglang/zig/issues/641 | |
| 60 | 60 | // and then make the return types of some of these functions the enum instead of c_int |
| 61 | 61 | const GE_LESS = c_int(-1); |
| 62 | 62 | const 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 |
| 44 | 44 | // If 0 <= exponent < significandBits, right shift to get the result. |
| 45 | 45 | // Otherwise, shift left. |
| 46 | 46 | 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); | |
| 50 | 47 | return @intCast(fixuint_t, significand >> @intCast(Log2Int(rep_t), significandBits - exponent)); |
| 51 | 48 | } else { |
| 52 | // TODO this is a workaround for the mysterious "integer cast truncated bits" | |
| 53 | // happening on the next line | |
| 54 | @setRuntimeSafety(false); | |
| 55 | 49 | return @intCast(fixuint_t, significand) << @intCast(Log2Int(fixuint_t), exponent - significandBits); |
| 56 | 50 | } |
| 57 | 51 | } |
std/special/compiler_rt/fixunstfdi_test.zig+10-11| ... | ... | @@ -36,15 +36,14 @@ test "fixunstfdi" { |
| 36 | 36 | test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0); |
| 37 | 37 | test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0); |
| 38 | 38 | |
| 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); | |
| 50 | 49 | } |
std/special/compiler_rt/fixunstfsi_test.zig+2-2| ... | ... | @@ -11,9 +11,9 @@ const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000)); |
| 11 | 11 | test "fixunstfsi" { |
| 12 | 12 | test__fixunstfsi(inf128, 0xffffffff); |
| 13 | 13 | test__fixunstfsi(0, 0x0); |
| 14 | //TODO test__fixunstfsi(0x1.23456789abcdefp+5, 0x24); | |
| 14 | test__fixunstfsi(0x1.23456789abcdefp+5, 0x24); | |
| 15 | 15 | test__fixunstfsi(0x1.23456789abcdefp-3, 0x0); |
| 16 | //TODO test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456); | |
| 16 | test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456); | |
| 17 | 17 | test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff); |
| 18 | 18 | test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff); |
| 19 | 19 | 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 { |
| 17 | 17 | const exp = (u64.bit_count - 1) - @clz(a); |
| 18 | 18 | const shift = mantissa_bits - @intCast(u7, exp); |
| 19 | 19 | |
| 20 | // TODO: @bitCast alignment error | |
| 20 | // TODO(#1148): @bitCast alignment error | |
| 21 | 21 | var result align(16) = (@intCast(u128, a) << shift) ^ implicit_bit; |
| 22 | 22 | result += (@intCast(u128, exp) + exponent_bias) << mantissa_bits; |
| 23 | 23 |
test/behavior.zig+1| ... | ... | @@ -18,6 +18,7 @@ comptime { |
| 18 | 18 | _ = @import("cases/cast.zig"); |
| 19 | 19 | _ = @import("cases/const_slice_child.zig"); |
| 20 | 20 | _ = @import("cases/coroutines.zig"); |
| 21 | _ = @import("cases/coroutine_await_struct.zig"); | |
| 21 | 22 | _ = @import("cases/defer.zig"); |
| 22 | 23 | _ = @import("cases/enum.zig"); |
| 23 | 24 | _ = @import("cases/enum_with_members.zig"); |
test/cases/coroutine_await_struct.zig created+47| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const assert = std.debug.assert; | |
| 4 | ||
| 5 | const Foo = struct { | |
| 6 | x: i32, | |
| 7 | }; | |
| 8 | ||
| 9 | var await_a_promise: promise = undefined; | |
| 10 | var await_final_result = Foo{ .x = 0 }; | |
| 11 | ||
| 12 | test "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 | } | |
| 24 | async 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 | } | |
| 31 | async 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 | ||
| 41 | var await_points = []u8{0} ** "abcdefghi".len; | |
| 42 | var await_seq_index: usize = 0; | |
| 43 | ||
| 44 | fn 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" { |
| 116 | 116 | defer da.deinit(); |
| 117 | 117 | |
| 118 | 118 | 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"); | |
| 120 | 120 | early_seq('f'); |
| 121 | 121 | assert(early_final_result == 1234); |
| 122 | 122 | assert(std.mem.eql(u8, early_points, "abcdef")); |
| 123 | 123 | } |
| 124 | 124 | async fn early_amain() void { |
| 125 | 125 | early_seq('b'); |
| 126 | const p = async early_another() catch unreachable; | |
| 126 | const p = async early_another() catch @panic("out of memory"); | |
| 127 | 127 | early_seq('d'); |
| 128 | 128 | early_final_result = await p; |
| 129 | 129 | early_seq('e'); |