mirror of
https://github.com/ziglang/zig.git
synced 2026-01-10 17:35:12 +00:00
Merge remote-tracking branch 'origin/master' into llvm7
This commit is contained in:
commit
b5d07297de
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1 +1,2 @@
|
||||
*.zig text eol=lf
|
||||
langref.html.in text eol=lf
|
||||
|
||||
@ -616,6 +616,17 @@ test "init with undefined" {
|
||||
assert(x == 1);
|
||||
}
|
||||
{#code_end#}
|
||||
<p>
|
||||
<code>undefined</code> can be {#link|implicitly cast|Implicit Casts#} to any type.
|
||||
Once this happens, it is no longer possible to detect that the value is <code>undefined</code>.
|
||||
<code>undefined</code> means the value could be anything, even something that is nonsense
|
||||
according to the type. Translated into English, <code>undefined</code> means "Not a meaningful
|
||||
value. Using this value would be a bug. The value will be unused, or overwritten before being used."
|
||||
</p>
|
||||
<p>
|
||||
In {#link|Debug#} mode, Zig writes <code>0xaa</code> bytes to undefined memory. This is to catch
|
||||
bugs early, and to help detect use of undefined memory in a debugger.
|
||||
</p>
|
||||
{#header_close#}
|
||||
{#header_close#}
|
||||
{#header_close#}
|
||||
@ -2237,21 +2248,28 @@ test "switch inside function" {
|
||||
{#see_also|comptime|enum|@compileError|Compile Variables#}
|
||||
{#header_close#}
|
||||
{#header_open|while#}
|
||||
<p>
|
||||
A while loop is used to repeatedly execute an expression until
|
||||
some condition is no longer true.
|
||||
</p>
|
||||
{#code_begin|test|while#}
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "while basic" {
|
||||
// A while loop is used to repeatedly execute an expression until
|
||||
// some condition is no longer true.
|
||||
var i: usize = 0;
|
||||
while (i < 10) {
|
||||
i += 1;
|
||||
}
|
||||
assert(i == 10);
|
||||
}
|
||||
{#code_end#}
|
||||
<p>
|
||||
Use <code>break</code> to exit a while loop early.
|
||||
</p>
|
||||
{#code_begin|test|while#}
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "while break" {
|
||||
// You can use break to exit a while loop early.
|
||||
var i: usize = 0;
|
||||
while (true) {
|
||||
if (i == 10)
|
||||
@ -2260,9 +2278,14 @@ test "while break" {
|
||||
}
|
||||
assert(i == 10);
|
||||
}
|
||||
{#code_end#}
|
||||
<p>
|
||||
Use <code>continue</code> to jump back to the beginning of the loop.
|
||||
</p>
|
||||
{#code_begin|test|while#}
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "while continue" {
|
||||
// You can use continue to jump back to the beginning of the loop.
|
||||
var i: usize = 0;
|
||||
while (true) {
|
||||
i += 1;
|
||||
@ -2272,18 +2295,21 @@ test "while continue" {
|
||||
}
|
||||
assert(i == 10);
|
||||
}
|
||||
{#code_end#}
|
||||
<p>
|
||||
While loops support a continue expression which is executed when the loop
|
||||
is continued. The <code>continue</code> keyword respects this expression.
|
||||
</p>
|
||||
{#code_begin|test|while#}
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "while loop continuation expression" {
|
||||
// You can give an expression to the while loop to execute when
|
||||
// the loop is continued. This is respected by the continue control flow.
|
||||
var i: usize = 0;
|
||||
while (i < 10) : (i += 1) {}
|
||||
assert(i == 10);
|
||||
}
|
||||
|
||||
test "while loop continuation expression, more complicated" {
|
||||
// More complex blocks can be used as an expression in the loop continue
|
||||
// expression.
|
||||
var i1: usize = 1;
|
||||
var j1: usize = 1;
|
||||
while (i1 * j1 < 2000) : ({ i1 *= 2; j1 *= 3; }) {
|
||||
@ -2291,6 +2317,20 @@ test "while loop continuation expression, more complicated" {
|
||||
assert(my_ij1 < 2000);
|
||||
}
|
||||
}
|
||||
{#code_end#}
|
||||
<p>
|
||||
While loops are expressions. The result of the expression is the
|
||||
result of the <code>else</code> clause of a while loop, which is executed when
|
||||
the condition of the while loop is tested as false.
|
||||
</p>
|
||||
<p>
|
||||
<code>break</code>, like <code>return</code>, accepts a value
|
||||
parameter. This is the result of the <code>while</code> expression.
|
||||
When you <code>break</code> from a while loop, the <code>else</code> branch is not
|
||||
evaluated.
|
||||
</p>
|
||||
{#code_begin|test|while#}
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "while else" {
|
||||
assert(rangeHasNumber(0, 10, 5));
|
||||
@ -2299,24 +2339,31 @@ test "while else" {
|
||||
|
||||
fn rangeHasNumber(begin: usize, end: usize, number: usize) bool {
|
||||
var i = begin;
|
||||
// While loops are expressions. The result of the expression is the
|
||||
// result of the else clause of a while loop, which is executed when
|
||||
// the condition of the while loop is tested as false.
|
||||
return while (i < end) : (i += 1) {
|
||||
if (i == number) {
|
||||
// break expressions, like return expressions, accept a value
|
||||
// parameter. This is the result of the while expression.
|
||||
// When you break from a while loop, the else branch is not
|
||||
// evaluated.
|
||||
break true;
|
||||
}
|
||||
} else false;
|
||||
}
|
||||
{#code_end#}
|
||||
{#header_open|while with Optionals#}
|
||||
<p>
|
||||
Just like {#link|if#} expressions, while loops can take an optional as the
|
||||
condition and capture the payload. When {#link|null#} is encountered the loop
|
||||
exits.
|
||||
</p>
|
||||
<p>
|
||||
When the <code>|x|</code> syntax is present on a <code>while</code> expression,
|
||||
the while condition must have an {#link|Optional Type#}.
|
||||
</p>
|
||||
<p>
|
||||
The <code>else</code> branch is allowed on optional iteration. In this case, it will
|
||||
be executed on the first null value encountered.
|
||||
</p>
|
||||
{#code_begin|test|while#}
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "while null capture" {
|
||||
// Just like if expressions, while loops can take an optional as the
|
||||
// condition and capture the payload. When null is encountered the loop
|
||||
// exits.
|
||||
var sum1: u32 = 0;
|
||||
numbers_left = 3;
|
||||
while (eventuallyNullSequence()) |value| {
|
||||
@ -2324,8 +2371,6 @@ test "while null capture" {
|
||||
}
|
||||
assert(sum1 == 3);
|
||||
|
||||
// The else branch is allowed on optional iteration. In this case, it will
|
||||
// be executed on the first null value encountered.
|
||||
var sum2: u32 = 0;
|
||||
numbers_left = 3;
|
||||
while (eventuallyNullSequence()) |value| {
|
||||
@ -2333,18 +2378,6 @@ test "while null capture" {
|
||||
} else {
|
||||
assert(sum1 == 3);
|
||||
}
|
||||
|
||||
// Just like if expressions, while loops can also take an error union as
|
||||
// the condition and capture the payload or the error code. When the
|
||||
// condition results in an error code the else branch is evaluated and
|
||||
// the loop is finished.
|
||||
var sum3: u32 = 0;
|
||||
numbers_left = 3;
|
||||
while (eventuallyErrorSequence()) |value| {
|
||||
sum3 += value;
|
||||
} else |err| {
|
||||
assert(err == error.ReachedZero);
|
||||
}
|
||||
}
|
||||
|
||||
var numbers_left: u32 = undefined;
|
||||
@ -2355,6 +2388,35 @@ fn eventuallyNullSequence() ?u32 {
|
||||
};
|
||||
}
|
||||
|
||||
{#code_end#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|while with Error Unions#}
|
||||
<p>
|
||||
Just like {#link|if#} expressions, while loops can take an error union as
|
||||
the condition and capture the payload or the error code. When the
|
||||
condition results in an error code the else branch is evaluated and
|
||||
the loop is finished.
|
||||
</p>
|
||||
<p>
|
||||
When the <code>else |x|</code> syntax is present on a <code>while</code> expression,
|
||||
the while condition must have an {#link|Error Union Type#}.
|
||||
</p>
|
||||
{#code_begin|test|while#}
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "while error union capture" {
|
||||
var sum1: u32 = 0;
|
||||
numbers_left = 3;
|
||||
while (eventuallyErrorSequence()) |value| {
|
||||
sum1 += value;
|
||||
} else |err| {
|
||||
assert(err == error.ReachedZero);
|
||||
}
|
||||
}
|
||||
|
||||
var numbers_left: u32 = undefined;
|
||||
|
||||
fn eventuallyErrorSequence() error!u32 {
|
||||
return if (numbers_left == 0) error.ReachedZero else blk: {
|
||||
numbers_left -= 1;
|
||||
@ -2362,6 +2424,7 @@ fn eventuallyErrorSequence() error!u32 {
|
||||
};
|
||||
}
|
||||
{#code_end#}
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|inline while#}
|
||||
<p>
|
||||
|
||||
@ -4417,22 +4417,14 @@ Buf *get_linux_libc_include_path(void) {
|
||||
}
|
||||
char *prev_newline = buf_ptr(out_stderr);
|
||||
ZigList<const char *> search_paths = {};
|
||||
bool found_search_paths = false;
|
||||
for (;;) {
|
||||
char *newline = strchr(prev_newline, '\n');
|
||||
if (newline == nullptr) {
|
||||
zig_panic("unable to determine libc include path: bad output from C compiler command");
|
||||
break;
|
||||
}
|
||||
*newline = 0;
|
||||
if (found_search_paths) {
|
||||
if (strcmp(prev_newline, "End of search list.") == 0) {
|
||||
break;
|
||||
}
|
||||
if (prev_newline[0] == ' ') {
|
||||
search_paths.append(prev_newline);
|
||||
} else {
|
||||
if (strcmp(prev_newline, "#include <...> search starts here:") == 0) {
|
||||
found_search_paths = true;
|
||||
}
|
||||
}
|
||||
prev_newline = newline + 1;
|
||||
}
|
||||
|
||||
12
src/ir.cpp
12
src/ir.cpp
@ -6674,7 +6674,10 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
|
||||
}
|
||||
Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
|
||||
IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_field_name);
|
||||
// If the type of the result handle_is_ptr then this does not actually perform a load. But we need it to,
|
||||
// because we're about to destroy the memory. So we store it into our result variable.
|
||||
IrInstruction *no_suspend_result = ir_build_load_ptr(irb, parent_scope, node, promise_result_ptr);
|
||||
ir_build_store_ptr(irb, parent_scope, node, my_result_var_ptr, no_suspend_result);
|
||||
ir_build_cancel(irb, parent_scope, node, target_inst);
|
||||
ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);
|
||||
|
||||
@ -6696,17 +6699,10 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
|
||||
ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, resume_block);
|
||||
IrInstruction *yes_suspend_result = ir_build_load_ptr(irb, parent_scope, node, my_result_var_ptr);
|
||||
ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, merge_block);
|
||||
IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
|
||||
IrInstruction **incoming_values = allocate<IrInstruction *>(2);
|
||||
incoming_blocks[0] = resume_block;
|
||||
incoming_values[0] = yes_suspend_result;
|
||||
incoming_blocks[1] = no_suspend_block;
|
||||
incoming_values[1] = no_suspend_result;
|
||||
return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);
|
||||
return ir_build_load_ptr(irb, parent_scope, node, my_result_var_ptr);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
|
||||
|
||||
@ -34,7 +34,7 @@ pub const Allocator = struct {
|
||||
/// Call `destroy` with the result
|
||||
pub fn create(self: *Allocator, init: var) Error!*@typeOf(init) {
|
||||
const T = @typeOf(init);
|
||||
if (@sizeOf(T) == 0) return &{};
|
||||
if (@sizeOf(T) == 0) return &(T{});
|
||||
const slice = try self.alloc(T, 1);
|
||||
const ptr = &slice[0];
|
||||
ptr.* = init;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// TODO https://github.com/ziglang/zig/issues/305
|
||||
// TODO https://github.com/ziglang/zig/issues/641
|
||||
// and then make the return types of some of these functions the enum instead of c_int
|
||||
const LE_LESS = c_int(-1);
|
||||
const LE_EQUAL = c_int(0);
|
||||
@ -56,7 +56,7 @@ pub extern fn __letf2(a: f128, b: f128) c_int {
|
||||
LE_GREATER;
|
||||
}
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/305
|
||||
// TODO https://github.com/ziglang/zig/issues/641
|
||||
// and then make the return types of some of these functions the enum instead of c_int
|
||||
const GE_LESS = c_int(-1);
|
||||
const GE_EQUAL = c_int(0);
|
||||
|
||||
@ -44,14 +44,8 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t
|
||||
// If 0 <= exponent < significandBits, right shift to get the result.
|
||||
// Otherwise, shift left.
|
||||
if (exponent < significandBits) {
|
||||
// TODO this is a workaround for the mysterious "integer cast truncated bits"
|
||||
// happening on the next line
|
||||
@setRuntimeSafety(false);
|
||||
return @intCast(fixuint_t, significand >> @intCast(Log2Int(rep_t), significandBits - exponent));
|
||||
} else {
|
||||
// TODO this is a workaround for the mysterious "integer cast truncated bits"
|
||||
// happening on the next line
|
||||
@setRuntimeSafety(false);
|
||||
return @intCast(fixuint_t, significand) << @intCast(Log2Int(fixuint_t), exponent - significandBits);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,15 +36,14 @@ test "fixunstfdi" {
|
||||
test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0);
|
||||
test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0);
|
||||
|
||||
// TODO enable these tests when we can parse f128 float literals
|
||||
//test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);
|
||||
//test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001);
|
||||
//test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000);
|
||||
//test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);
|
||||
//test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);
|
||||
//test__fixunstfdi(0x1.p+64, 0xFFFFFFFFFFFFFFFF);
|
||||
test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF);
|
||||
test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001);
|
||||
test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000);
|
||||
test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF);
|
||||
test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE);
|
||||
test__fixunstfdi(0x1.p+64, 0xFFFFFFFFFFFFFFFF);
|
||||
|
||||
//test__fixunstfdi(-0x1.0000000000000000p+63, 0);
|
||||
//test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0);
|
||||
//test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0);
|
||||
test__fixunstfdi(-0x1.0000000000000000p+63, 0);
|
||||
test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0);
|
||||
test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0);
|
||||
}
|
||||
|
||||
@ -11,9 +11,9 @@ const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000));
|
||||
test "fixunstfsi" {
|
||||
test__fixunstfsi(inf128, 0xffffffff);
|
||||
test__fixunstfsi(0, 0x0);
|
||||
//TODO test__fixunstfsi(0x1.23456789abcdefp+5, 0x24);
|
||||
test__fixunstfsi(0x1.23456789abcdefp+5, 0x24);
|
||||
test__fixunstfsi(0x1.23456789abcdefp-3, 0x0);
|
||||
//TODO test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456);
|
||||
test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456);
|
||||
test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff);
|
||||
test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff);
|
||||
test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0);
|
||||
|
||||
@ -17,7 +17,7 @@ pub extern fn __floatunsitf(a: u64) f128 {
|
||||
const exp = (u64.bit_count - 1) - @clz(a);
|
||||
const shift = mantissa_bits - @intCast(u7, exp);
|
||||
|
||||
// TODO: @bitCast alignment error
|
||||
// TODO(#1148): @bitCast alignment error
|
||||
var result align(16) = (@intCast(u128, a) << shift) ^ implicit_bit;
|
||||
result += (@intCast(u128, exp) + exponent_bias) << mantissa_bits;
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ comptime {
|
||||
_ = @import("cases/cast.zig");
|
||||
_ = @import("cases/const_slice_child.zig");
|
||||
_ = @import("cases/coroutines.zig");
|
||||
_ = @import("cases/coroutine_await_struct.zig");
|
||||
_ = @import("cases/defer.zig");
|
||||
_ = @import("cases/enum.zig");
|
||||
_ = @import("cases/enum_with_members.zig");
|
||||
|
||||
47
test/cases/coroutine_await_struct.zig
Normal file
47
test/cases/coroutine_await_struct.zig
Normal file
@ -0,0 +1,47 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const Foo = struct {
|
||||
x: i32,
|
||||
};
|
||||
|
||||
var await_a_promise: promise = undefined;
|
||||
var await_final_result = Foo{ .x = 0 };
|
||||
|
||||
test "coroutine await struct" {
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
|
||||
await_seq('a');
|
||||
const p = async<&da.allocator> await_amain() catch unreachable;
|
||||
await_seq('f');
|
||||
resume await_a_promise;
|
||||
await_seq('i');
|
||||
assert(await_final_result.x == 1234);
|
||||
assert(std.mem.eql(u8, await_points, "abcdefghi"));
|
||||
}
|
||||
async fn await_amain() void {
|
||||
await_seq('b');
|
||||
const p = async await_another() catch unreachable;
|
||||
await_seq('e');
|
||||
await_final_result = await p;
|
||||
await_seq('h');
|
||||
}
|
||||
async fn await_another() Foo {
|
||||
await_seq('c');
|
||||
suspend |p| {
|
||||
await_seq('d');
|
||||
await_a_promise = p;
|
||||
}
|
||||
await_seq('g');
|
||||
return Foo{ .x = 1234 };
|
||||
}
|
||||
|
||||
var await_points = []u8{0} ** "abcdefghi".len;
|
||||
var await_seq_index: usize = 0;
|
||||
|
||||
fn await_seq(c: u8) void {
|
||||
await_points[await_seq_index] = c;
|
||||
await_seq_index += 1;
|
||||
}
|
||||
@ -116,14 +116,14 @@ test "coroutine await early return" {
|
||||
defer da.deinit();
|
||||
|
||||
early_seq('a');
|
||||
const p = async<&da.allocator> early_amain() catch unreachable;
|
||||
const p = async<&da.allocator> early_amain() catch @panic("out of memory");
|
||||
early_seq('f');
|
||||
assert(early_final_result == 1234);
|
||||
assert(std.mem.eql(u8, early_points, "abcdef"));
|
||||
}
|
||||
async fn early_amain() void {
|
||||
early_seq('b');
|
||||
const p = async early_another() catch unreachable;
|
||||
const p = async early_another() catch @panic("out of memory");
|
||||
early_seq('d');
|
||||
early_final_result = await p;
|
||||
early_seq('e');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user