authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-07 17:19:51-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-07 17:23:50-05:00
log8a859afd580f438f549ee69a3e3487eb5d119fad
treecbbd2d01bdd73a160b90dc280e7fbc05e7d963a8
parent92793252ad43c4119902506f95e726de3492c128

std.io supports printing integers as hex values

remove "unnecessary if statement" error this "depends on compile variable" code is too hard to validate, and has false negatives. not worth it right now. std.str removed, instead use std.mem. std.mem.eql and std.mem.sliceEql merged and do not require explicit type argument.

18 files changed, 191 insertions(+), 132 deletions(-)

CMakeLists.txt-1
......@@ -225,7 +225,6 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/panic.zig" DESTINATION "${ZIG_STD_DEST}")
225225install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
226226install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}")
227227install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
228install(FILES "${CMAKE_SOURCE_DIR}/std/str.zig" DESTINATION "${ZIG_STD_DEST}")
229228install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner.zig" DESTINATION "${ZIG_STD_DEST}")
230229install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig" DESTINATION "${ZIG_STD_DEST}")
231230install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_nolibc.zig" DESTINATION "${ZIG_STD_DEST}")
src/ir.cpp+2-10
......@@ -8536,14 +8536,6 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
85368536 if (!ir_resolve_bool(ira, condition, &cond_is_true))
85378537 return ir_unreach_error(ira);
85388538
8539 if (!cond_br_instruction->base.is_gen && !condition->value.depends_on_compile_var &&
8540 !ir_should_inline(ira->new_irb.exec, cond_br_instruction->base.scope))
8541 {
8542 const char *true_or_false = cond_is_true ? "true" : "false";
8543 ir_add_error(ira, &cond_br_instruction->base,
8544 buf_sprintf("condition is always %s; unnecessary if statement", true_or_false));
8545 }
8546
85478539 IrBasicBlock *old_dest_block = cond_is_true ?
85488540 cond_br_instruction->then_block : cond_br_instruction->else_block;
85498541
......@@ -9060,7 +9052,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
90609052 bool ptr_is_const = true;
90619053 bool ptr_is_volatile = false;
90629054 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,
9063 usize, false, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);
9055 usize, depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);
90649056 } else {
90659057 ir_add_error_node(ira, source_node,
90669058 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
......@@ -9084,7 +9076,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
90849076 bool ptr_is_const = true;
90859077 bool ptr_is_volatile = false;
90869078 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,
9087 usize, false, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);
9079 usize, depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);
90889080 } else {
90899081 ir_add_error_node(ira, source_node,
90909082 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
std/elf.zig+1-2
......@@ -1,5 +1,4 @@
11const io = @import("io.zig");
2const str = @import("str.zig");
32const math = @import("math.zig");
43const mem = @import("mem.zig");
54const debug = @import("debug.zig");
......@@ -95,7 +94,7 @@ pub const Elf = struct {
9594
9695 var magic: [4]u8 = undefined;
9796 %return elf.in_stream.readNoEof(magic);
98 if (!str.eql(magic, "\x7fELF")) return error.InvalidFormat;
97 if (!mem.eql(magic, "\x7fELF")) return error.InvalidFormat;
9998
10099 elf.is_64 = switch (%return elf.in_stream.readByte()) {
101100 1 => false,
std/index.zig-1
......@@ -2,7 +2,6 @@ pub const rand = @import("rand.zig");
22pub const io = @import("io.zig");
33pub const os = @import("os.zig");
44pub const math = @import("math.zig");
5pub const str = @import("str.zig");
65pub const cstr = @import("cstr.zig");
76pub const sort = @import("sort.zig");
87pub const net = @import("net.zig");
std/io.zig+69-24
......@@ -61,8 +61,8 @@ error Unseekable;
6161error Eof;
6262
6363const buffer_size = 4 * 1024;
64const max_u64_base10_digits = 20;
6564const max_f64_digits = 65;
65const max_int_digits = 65;
6666
6767pub const OpenRead = 0b0001;
6868pub const OpenWrite = 0b0010;
......@@ -100,6 +100,7 @@ pub const OutStream = struct {
100100 Start,
101101 OpenBrace,
102102 CloseBrace,
103 Hex: bool,
103104 };
104105
105106 /// Calls print and then flushes the buffer.
......@@ -131,6 +132,12 @@ pub const OutStream = struct {
131132 state = State.Start;
132133 start_index = i + 1;
133134 },
135 'x' => {
136 state = State.Hex { false };
137 },
138 'X' => {
139 state = State.Hex { true };
140 },
134141 else => @compileError("Unknown format character: " ++ c),
135142 },
136143 State.CloseBrace => switch (c) {
......@@ -140,14 +147,25 @@ pub const OutStream = struct {
140147 },
141148 else => @compileError("Single '}' encountered in format string"),
142149 },
150 State.Hex => |uppercase| switch (c) {
151 '}' => {
152 self.printInt(args[next_arg], 16, uppercase);
153 next_arg += 1;
154 state = State.Start;
155 start_index = i + 1;
156 },
157 else => @compileError("Expected '}' after 'x'/'X' in format string"),
158 },
143159 }
144160 }
145161 comptime {
146162 if (args.len != next_arg) {
147163 @compileError("Unused arguments");
148164 }
149 if (state != State.Start) {
150 @compileError("Incomplete format string: " ++ format);
165 // TODO https://github.com/andrewrk/zig/issues/253
166 switch (state) {
167 State.Start => {},
168 else => @compileError("Incomplete format string: " ++ format),
151169 }
152170 }
153171 if (start_index < format.len) {
......@@ -159,7 +177,7 @@ pub const OutStream = struct {
159177 pub fn printValue(self: &OutStream, value: var) -> %void {
160178 const T = @typeOf(value);
161179 if (@isInteger(T)) {
162 return self.printInt(T, value);
180 return self.printInt(value, 10, false);
163181 } else if (@isFloat(T)) {
164182 return self.printFloat(T, value);
165183 } else if (@canImplicitCast([]const u8, value)) {
......@@ -172,12 +190,11 @@ pub const OutStream = struct {
172190 }
173191 }
174192
175 pub fn printInt(self: &OutStream, comptime T: type, x: T) -> %void {
176 // TODO replace max_u64_base10_digits with math.log10(math.pow(2, @sizeOf(T)))
177 if (self.index + max_u64_base10_digits >= self.buffer.len) {
193 pub fn printInt(self: &OutStream, x: var, base: u8, uppercase: bool) -> %void {
194 if (self.index + max_int_digits >= self.buffer.len) {
178195 %return self.flush();
179196 }
180 const amt_printed = bufPrintInt(T, self.buffer[self.index...], x);
197 const amt_printed = bufPrintInt(self.buffer[self.index...], x, base, uppercase);
181198 self.index += amt_printed;
182199 }
183200
......@@ -448,39 +465,51 @@ fn charToDigit(c: u8, radix: u8) -> %u8 {
448465 return value;
449466}
450467
451pub fn bufPrintInt(comptime T: type, out_buf: []u8, x: T) -> usize {
452 if (T.is_signed) bufPrintSigned(T, out_buf, x) else bufPrintUnsigned(T, out_buf, x)
468fn digitToChar(digit: u8, uppercase: bool) -> u8 {
469 return switch (digit) {
470 0 ... 9 => digit + '0',
471 10 ... 35 => digit + ((if (uppercase) u8('A') else u8('a')) - 10),
472 else => @unreachable(),
473 };
453474}
454475
455fn bufPrintSigned(comptime T: type, out_buf: []u8, x: T) -> usize {
456 const uint = @intType(false, T.bit_count);
476/// Guaranteed to not use more than max_int_digits
477pub fn bufPrintInt(out_buf: []u8, x: var, base: u8, uppercase: bool) -> usize {
478 if (@typeOf(x).is_signed)
479 bufPrintSigned(out_buf, x, base, uppercase)
480 else
481 bufPrintUnsigned(out_buf, x, base, uppercase)
482}
483
484fn bufPrintSigned(out_buf: []u8, x: var, base: u8, uppercase: bool) -> usize {
485 const uint = @intType(false, @typeOf(x).bit_count);
457486 if (x < 0) {
458487 out_buf[0] = '-';
459 return 1 + bufPrintUnsigned(uint, out_buf[1...], uint(-(x + 1)) + 1);
488 return 1 + bufPrintUnsigned(out_buf[1...], uint(-(x + 1)) + 1, base, uppercase);
460489 } else {
461 return bufPrintUnsigned(uint, out_buf, uint(x));
490 return bufPrintUnsigned(out_buf, uint(x), base, uppercase);
462491 }
463492}
464493
465fn bufPrintUnsigned(comptime T: type, out_buf: []u8, x: T) -> usize {
466 var buf: [max_u64_base10_digits]u8 = undefined;
494fn bufPrintUnsigned(out_buf: []u8, x: var, base: u8, uppercase: bool) -> usize {
495 // max_int_digits accounts for the minus sign. when printing an unsigned
496 // number we don't need to do that.
497 var buf: [max_int_digits - 1]u8 = undefined;
467498 var a = x;
468499 var index: usize = buf.len;
469500
470501 while (true) {
471 const digit = a % 10;
502 const digit = a % base;
472503 index -= 1;
473 buf[index] = '0' + u8(digit);
474 a /= 10;
504 buf[index] = digitToChar(u8(digit), uppercase);
505 a /= base;
475506 if (a == 0)
476507 break;
477508 }
478509
479 const len = buf.len - index;
480
481 @memcpy(&out_buf[0], &buf[index], len);
482
483 return len;
510 const src_buf = buf[index...];
511 mem.copy(u8, out_buf, src_buf);
512 return src_buf.len;
484513}
485514
486515fn parseU64DigitTooBig() {
......@@ -505,3 +534,19 @@ pub fn openSelfExe(stream: &InStream) -> %void {
505534 else => @compileError("unsupported os"),
506535 }
507536}
537
538fn bufPrintIntToSlice(buf: []u8, x: var, base: u8, uppercase: bool) -> []u8 {
539 return buf[0...bufPrintInt(buf, x, base, uppercase)];
540}
541
542fn testBufPrintInt() {
543 @setFnTest(this);
544
545 var buf: [max_int_digits]u8 = undefined;
546 assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 2, false), "-101111000110000101001110"));
547 assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 10, false), "-12345678"));
548 assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 16, false), "-bc614e"));
549 assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 16, true), "-BC614E"));
550
551 assert(mem.eql(bufPrintIntToSlice(buf, u32(12345678), 10, true), "12345678"));
552}
std/math.zig+37
......@@ -29,3 +29,40 @@ pub fn shlOverflow(comptime T: type, a: T, b: T) -> %T {
2929 var answer: T = undefined;
3030 if (@shlWithOverflow(T, a, b, &answer)) error.Overflow else answer
3131}
32
33pub fn log(comptime base: usize, value: var) -> @typeOf(value) {
34 const T = @typeOf(value);
35 if (@isInteger(T)) {
36 if (base == 2) {
37 return T.bit_count - 1 - @clz(value);
38 } else {
39 @compileError("TODO implement log for non base 2 integers");
40 }
41 } else if (@isFloat(T)) {
42 @compileError("TODO implement log for floats");
43 } else {
44 @compileError("log expects integer or float, found '" ++ @typeName(T) ++ "'");
45 }
46}
47
48/// x must be an integer or a float
49/// Note that this causes undefined behavior if
50/// @typeOf(x).is_signed && x == @minValue(@typeOf(x)).
51pub fn abs(x: var) -> @typeOf(x) {
52 const T = @typeOf(x);
53 if (@isInteger(T)) {
54 return if (x < 0) -x else x;
55 } else if (@isFloat(T)) {
56 @compileError("TODO implement abs for floats");
57 } else {
58 @unreachable();
59 }
60}
61fn getReturnTypeForAbs(comptime T: type) -> type {
62 if (@isInteger(T)) {
63 return @intType(false, T.bit_count);
64 } else {
65 return T;
66 }
67}
68
std/mem.zig+20
......@@ -43,6 +43,9 @@ pub const Allocator = struct {
4343/// Copy all of source into dest at position 0.
4444/// dest.len must be >= source.len.
4545pub fn copy(comptime T: type, dest: []T, source: []const T) {
46 // TODO instead of manually doing this check for the whole array
47 // and turning off debug safety, the compiler should detect loops like
48 // this and automatically omit safety checks for loops
4649 @setDebugSafety(this, false);
4750 assert(dest.len >= source.len);
4851 for (source) |s, i| dest[i] = s;
......@@ -82,6 +85,23 @@ pub fn sliceAsInt(buf: []u8, is_be: bool, comptime T: type) -> T {
8285 return result;
8386}
8487
88/// Compares two slices and returns whether they are equal.
89pub fn eql(a: var, b: var) -> bool {
90 if (a.len != b.len) return false;
91 for (a) |item, index| {
92 if (b[index] != item) return false;
93 }
94 return true;
95}
96
97fn testStringEquality() {
98 @setFnTest(this);
99
100 assert(eql("abcd", "abcd"));
101 assert(!eql("abcdef", "abZdef"));
102 assert(!eql("abcdefg", "abcdef"));
103}
104
85105fn testSliceAsInt() {
86106 @setFnTest(this);
87107 {
std/sort.zig+3-4
......@@ -1,5 +1,4 @@
11const assert = @import("debug.zig").assert;
2const str = @import("str.zig");
32const mem = @import("mem.zig");
43const math = @import("math.zig");
54
......@@ -76,7 +75,7 @@ fn testSort() {
7675 const slice = buf[0...case[0].len];
7776 mem.copy(u8, slice, case[0]);
7877 sort(u8, slice, u8asc);
79 assert(str.eql(slice, case[1]));
78 assert(mem.eql(slice, case[1]));
8079 }
8180
8281 const i32cases = [][][]i32 {
......@@ -93,7 +92,7 @@ fn testSort() {
9392 const slice = buf[0...case[0].len];
9493 mem.copy(i32, slice, case[0]);
9594 sort(i32, slice, i32asc);
96 assert(str.sliceEql(i32, slice, case[1]));
95 assert(mem.eql(slice, case[1]));
9796 }
9897}
9998
......@@ -114,6 +113,6 @@ fn testSortDesc() {
114113 const slice = buf[0...case[0].len];
115114 mem.copy(i32, slice, case[0]);
116115 sort(i32, slice, i32desc);
117 assert(str.sliceEql(i32, slice, case[1]));
116 assert(mem.eql(slice, case[1]));
118117 }
119118}
std/str.zig deleted-21
......@@ -1,21 +0,0 @@
1const assert = @import("debug.zig").assert;
2
3pub fn eql(a: []const u8, b: []const u8) -> bool {
4 sliceEql(u8, a, b)
5}
6
7pub fn sliceEql(comptime T: type, a: []const T, b: []const T) -> bool {
8 if (a.len != b.len) return false;
9 for (a) |item, index| {
10 if (b[index] != item) return false;
11 }
12 return true;
13}
14
15fn testStringEquality() {
16 @setFnTest(this);
17
18 assert(eql("abcd", "abcd"));
19 assert(!eql("abcdef", "abZdef"));
20 assert(!eql("abcdefg", "abcdef"));
21}
test/cases/array.zig+6-6
......@@ -1,5 +1,5 @@
11const assert = @import("std").debug.assert;
2const str = @import("std").str;
2const mem = @import("std").mem;
33
44fn arrays() {
55 @setFnTest(this);
......@@ -63,10 +63,10 @@ fn nestedArrays() {
6363
6464 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};
6565 for (array_of_strings) |s, i| {
66 if (i == 0) assert(str.eql(s, "hello"));
67 if (i == 1) assert(str.eql(s, "this"));
68 if (i == 2) assert(str.eql(s, "is"));
69 if (i == 3) assert(str.eql(s, "my"));
70 if (i == 4) assert(str.eql(s, "thing"));
66 if (i == 0) assert(mem.eql(s, "hello"));
67 if (i == 1) assert(mem.eql(s, "this"));
68 if (i == 2) assert(mem.eql(s, "is"));
69 if (i == 3) assert(mem.eql(s, "my"));
70 if (i == 4) assert(mem.eql(s, "thing"));
7171 }
7272}
test/cases/enum_with_members.zig+5-5
......@@ -1,5 +1,5 @@
11const assert = @import("std").debug.assert;
2const str = @import("std").str;
2const mem = @import("std").mem;
33const io = @import("std").io;
44
55const ET = enum {
......@@ -8,8 +8,8 @@ const ET = enum {
88
99 pub fn print(a: &const ET, buf: []u8) -> %usize {
1010 return switch (*a) {
11 ET.SINT => |x| { io.bufPrintInt(i32, buf, x) },
12 ET.UINT => |x| { io.bufPrintInt(u32, buf, x) },
11 ET.SINT => |x| { io.bufPrintInt(buf, x, 10, false) },
12 ET.UINT => |x| { io.bufPrintInt(buf, x, 10, false) },
1313 }
1414 }
1515};
......@@ -22,8 +22,8 @@ fn enumWithMembers() {
2222 var buf: [20]u8 = undefined;
2323
2424 assert(%%a.print(buf) == 3);
25 assert(str.eql(buf[0...3], "-42"));
25 assert(mem.eql(buf[0...3], "-42"));
2626
2727 assert(%%b.print(buf) == 2);
28 assert(str.eql(buf[0...2], "42"));
28 assert(mem.eql(buf[0...2], "42"));
2929}
test/cases/error.zig+3-3
......@@ -1,5 +1,5 @@
11const assert = @import("std").debug.assert;
2const str = @import("std").str;
2const mem = @import("std").mem;
33
44pub fn foo() -> %i32 {
55 const x = %return bar();
......@@ -28,8 +28,8 @@ fn gimmeItBroke() -> []const u8 {
2828
2929fn errorName() {
3030 @setFnTest(this);
31 assert(str.eql(@errorName(error.AnError), "AnError"));
32 assert(str.eql(@errorName(error.ALongerErrorName), "ALongerErrorName"));
31 assert(mem.eql(@errorName(error.AnError), "AnError"));
32 assert(mem.eql(@errorName(error.ALongerErrorName), "ALongerErrorName"));
3333}
3434error AnError;
3535error ALongerErrorName;
test/cases/eval.zig-1
......@@ -1,5 +1,4 @@
11const assert = @import("std").debug.assert;
2const str = @import("std").str;
32
43fn compileTimeRecursion() {
54 @setFnTest(this);
test/cases/for.zig+2-2
......@@ -1,6 +1,6 @@
11const std = @import("std");
22const assert = std.debug.assert;
3const str = std.str;
3const mem = std.mem;
44
55fn continueInForLoop() {
66 @setFnTest(this);
......@@ -24,7 +24,7 @@ fn forLoopWithPointerElemVar() {
2424 var target: [source.len]u8 = undefined;
2525 @memcpy(&target[0], &source[0], source.len);
2626 mangleString(target);
27 assert(str.eql(target, "bcdefgh"));
27 assert(mem.eql(target, "bcdefgh"));
2828}
2929fn mangleString(s: []u8) {
3030 for (s) |*c| {
test/cases/misc.zig+18-18
......@@ -1,5 +1,5 @@
11const assert = @import("std").debug.assert;
2const str = @import("std").str;
2const mem = @import("std").mem;
33const cstr = @import("std").cstr;
44
55// normal comment
......@@ -144,7 +144,7 @@ fn first4KeysOfHomeRow() -> []const u8 {
144144fn ReturnStringFromFunction() {
145145 @setFnTest(this);
146146
147 assert(str.eql(first4KeysOfHomeRow(), "aoeu"));
147 assert(mem.eql(first4KeysOfHomeRow(), "aoeu"));
148148}
149149
150150const g1 : i32 = 1233 + 1;
......@@ -210,31 +210,31 @@ fn emptyFn() {}
210210fn hexEscape() {
211211 @setFnTest(this);
212212
213 assert(str.eql("\x68\x65\x6c\x6c\x6f", "hello"));
213 assert(mem.eql("\x68\x65\x6c\x6c\x6f", "hello"));
214214}
215215
216216fn stringConcatenation() {
217217 @setFnTest(this);
218218
219 assert(str.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
219 assert(mem.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
220220}
221221
222222fn arrayMultOperator() {
223223 @setFnTest(this);
224224
225 assert(str.eql("ab" ** 5, "ababababab"));
225 assert(mem.eql("ab" ** 5, "ababababab"));
226226}
227227
228228fn stringEscapes() {
229229 @setFnTest(this);
230230
231 assert(str.eql("\"", "\x22"));
232 assert(str.eql("\'", "\x27"));
233 assert(str.eql("\n", "\x0a"));
234 assert(str.eql("\r", "\x0d"));
235 assert(str.eql("\t", "\x09"));
236 assert(str.eql("\\", "\x5c"));
237 assert(str.eql("\u1234\u0069", "\xe1\x88\xb4\x69"));
231 assert(mem.eql("\"", "\x22"));
232 assert(mem.eql("\'", "\x27"));
233 assert(mem.eql("\n", "\x0a"));
234 assert(mem.eql("\r", "\x0d"));
235 assert(mem.eql("\t", "\x09"));
236 assert(mem.eql("\\", "\x5c"));
237 assert(mem.eql("\u1234\u0069", "\xe1\x88\xb4\x69"));
238238}
239239
240240fn multilineString() {
......@@ -246,7 +246,7 @@ fn multilineString() {
246246 \\three
247247 ;
248248 const s2 = "one\ntwo)\nthree";
249 assert(str.eql(s1, s2));
249 assert(mem.eql(s1, s2));
250250}
251251
252252fn multilineCString() {
......@@ -295,7 +295,7 @@ const some_mem : [100]u8 = undefined;
295295fn memAlloc(comptime T: type, n: usize) -> %[]T {
296296 return (&T)(&some_mem[0])[0...n];
297297}
298fn memFree(comptime T: type, mem: []T) { }
298fn memFree(comptime T: type, memory: []T) { }
299299
300300
301301fn castUndefined() {
......@@ -344,8 +344,8 @@ fn pointerDereferencing() {
344344fn callResultOfIfElseExpression() {
345345 @setFnTest(this);
346346
347 assert(str.eql(f2(true), "a"));
348 assert(str.eql(f2(false), "b"));
347 assert(mem.eql(f2(true), "a"));
348 assert(mem.eql(f2(false), "b"));
349349}
350350fn f2(x: bool) -> []u8 {
351351 return (if (x) fA else fB)();
......@@ -562,8 +562,8 @@ fn typeName() {
562562 @setFnTest(this);
563563
564564 comptime {
565 assert(str.eql(@typeName(i64), "i64"));
566 assert(str.eql(@typeName(&usize), "&usize"));
565 assert(mem.eql(@typeName(i64), "i64"));
566 assert(mem.eql(@typeName(&usize), "&usize"));
567567 }
568568}
569569
test/cases/void.zig created+20
......@@ -0,0 +1,20 @@
1const assert = @import("std").debug.assert;
2
3const Foo = struct {
4 a: void,
5 b: i32,
6 c: void,
7};
8
9fn compareVoidWithVoidCompileTimeKnown() {
10 @setFnTest(this);
11
12 comptime {
13 const foo = Foo {
14 .a = {},
15 .b = 1,
16 .c = {},
17 };
18 assert(foo.a == {});
19 }
20}
test/run_tests.cpp+4-34
......@@ -471,21 +471,17 @@ const io = @import("std").io;
471471pub fn main(args: [][]u8) -> %void {
472472 const array = []u8 {9, 8, 7, 6};
473473 for (array) |item| {
474 %%io.stdout.printInt(@typeOf(item), item);
475 %%io.stdout.printf("\n");
474 %%io.stdout.printf("{}\n", item);
476475 }
477476 for (array) |item, index| {
478 %%io.stdout.printInt(@typeOf(index), index);
479 %%io.stdout.printf("\n");
477 %%io.stdout.printf("{}\n", index);
480478 }
481479 const unknown_size: []u8 = array;
482480 for (unknown_size) |item| {
483 %%io.stdout.printInt(@typeOf(item), item);
484 %%io.stdout.printf("\n");
481 %%io.stdout.printf("{}\n", item);
485482 }
486483 for (unknown_size) |item, index| {
487 %%io.stdout.printInt(@typeOf(index), index);
488 %%io.stdout.printf("\n");
484 %%io.stdout.printf("{}\n", index);
489485 }
490486}
491487 )SOURCE", "9\n8\n7\n6\n0\n1\n2\n3\n9\n8\n7\n6\n0\n1\n2\n3\n");
......@@ -1124,13 +1120,6 @@ fn get() -> usize { global_var }
11241120 ".tmp_source.zig:3:8: note: called from here");
11251121
11261122
1127 add_compile_fail_case("unnecessary if statement", R"SOURCE(
1128fn f() {
1129 if (true) { }
1130}
1131 )SOURCE", 1, ".tmp_source.zig:3:9: error: condition is always true; unnecessary if statement");
1132
1133
11341123 add_compile_fail_case("addition with non numbers", R"SOURCE(
11351124const Foo = struct {
11361125 field: i32,
......@@ -1588,25 +1577,6 @@ fn derp() {
15881577}
15891578 )SOURCE", 1, ".tmp_source.zig:7:13: error: cannot assign to constant");
15901579
1591 add_compile_fail_case("compare void with void is compile time known", R"SOURCE(
1592const Foo = struct {
1593 a: void,
1594 b: i32,
1595 c: void,
1596};
1597
1598fn f() {
1599 const foo = Foo {
1600 .a = {},
1601 .b = 1,
1602 .c = {},
1603 };
1604 if (foo.a != {}) {
1605 @unreachable();
1606 }
1607}
1608 )SOURCE", 1, ".tmp_source.zig:14:15: error: condition is always false; unnecessary if statement");
1609
16101580 add_compile_fail_case("return from defer expression", R"SOURCE(
16111581pub fn testTrickyDefer() -> %void {
16121582 defer canFail() %% {};
test/self_hosted.zig+1
......@@ -32,4 +32,5 @@ const test_try = @import("cases/try.zig");
3232const test_typedef = @import("cases/typedef.zig");
3333const test_undefined = @import("cases/undefined.zig");
3434const test_var_args = @import("cases/var_args.zig");
35const test_void = @import("cases/void.zig");
3536const test_while = @import("cases/while.zig");