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}")...@@ -225,7 +225,6 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/panic.zig" DESTINATION "${ZIG_STD_DEST}")
225install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")225install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
226install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}")226install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}")
227install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")227install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
228install(FILES "${CMAKE_SOURCE_DIR}/std/str.zig" DESTINATION "${ZIG_STD_DEST}")
229install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner.zig" DESTINATION "${ZIG_STD_DEST}")228install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner.zig" DESTINATION "${ZIG_STD_DEST}")
230install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig" DESTINATION "${ZIG_STD_DEST}")229install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig" DESTINATION "${ZIG_STD_DEST}")
231install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_nolibc.zig" DESTINATION "${ZIG_STD_DEST}")230install(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...@@ -8536,14 +8536,6 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
8536 if (!ir_resolve_bool(ira, condition, &cond_is_true))8536 if (!ir_resolve_bool(ira, condition, &cond_is_true))
8537 return ir_unreach_error(ira);8537 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
8547 IrBasicBlock *old_dest_block = cond_is_true ?8539 IrBasicBlock *old_dest_block = cond_is_true ?
8548 cond_br_instruction->then_block : cond_br_instruction->else_block;8540 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...@@ -9060,7 +9052,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
9060 bool ptr_is_const = true;9052 bool ptr_is_const = true;
9061 bool ptr_is_volatile = false;9053 bool ptr_is_volatile = false;
9062 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,9054 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);
9064 } else {9056 } else {
9065 ir_add_error_node(ira, source_node,9057 ir_add_error_node(ira, source_node,
9066 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),9058 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...@@ -9084,7 +9076,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
9084 bool ptr_is_const = true;9076 bool ptr_is_const = true;
9085 bool ptr_is_volatile = false;9077 bool ptr_is_volatile = false;
9086 return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,9078 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);
9088 } else {9080 } else {
9089 ir_add_error_node(ira, source_node,9081 ir_add_error_node(ira, source_node,
9090 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),9082 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
std/elf.zig+1-2
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const io = @import("io.zig");1const io = @import("io.zig");
2const str = @import("str.zig");
3const math = @import("math.zig");2const math = @import("math.zig");
4const mem = @import("mem.zig");3const mem = @import("mem.zig");
5const debug = @import("debug.zig");4const debug = @import("debug.zig");
...@@ -95,7 +94,7 @@ pub const Elf = struct {...@@ -95,7 +94,7 @@ pub const Elf = struct {
9594
96 var magic: [4]u8 = undefined;95 var magic: [4]u8 = undefined;
97 %return elf.in_stream.readNoEof(magic);96 %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
100 elf.is_64 = switch (%return elf.in_stream.readByte()) {99 elf.is_64 = switch (%return elf.in_stream.readByte()) {
101 1 => false,100 1 => false,
std/index.zig-1
...@@ -2,7 +2,6 @@ pub const rand = @import("rand.zig");...@@ -2,7 +2,6 @@ pub const rand = @import("rand.zig");
2pub const io = @import("io.zig");2pub const io = @import("io.zig");
3pub const os = @import("os.zig");3pub const os = @import("os.zig");
4pub const math = @import("math.zig");4pub const math = @import("math.zig");
5pub const str = @import("str.zig");
6pub const cstr = @import("cstr.zig");5pub const cstr = @import("cstr.zig");
7pub const sort = @import("sort.zig");6pub const sort = @import("sort.zig");
8pub const net = @import("net.zig");7pub const net = @import("net.zig");
std/io.zig+69-24
...@@ -61,8 +61,8 @@ error Unseekable;...@@ -61,8 +61,8 @@ error Unseekable;
61error Eof;61error Eof;
6262
63const buffer_size = 4 * 1024;63const buffer_size = 4 * 1024;
64const max_u64_base10_digits = 20;
65const max_f64_digits = 65;64const max_f64_digits = 65;
65const max_int_digits = 65;
6666
67pub const OpenRead = 0b0001;67pub const OpenRead = 0b0001;
68pub const OpenWrite = 0b0010;68pub const OpenWrite = 0b0010;
...@@ -100,6 +100,7 @@ pub const OutStream = struct {...@@ -100,6 +100,7 @@ pub const OutStream = struct {
100 Start,100 Start,
101 OpenBrace,101 OpenBrace,
102 CloseBrace,102 CloseBrace,
103 Hex: bool,
103 };104 };
104105
105 /// Calls print and then flushes the buffer.106 /// Calls print and then flushes the buffer.
...@@ -131,6 +132,12 @@ pub const OutStream = struct {...@@ -131,6 +132,12 @@ pub const OutStream = struct {
131 state = State.Start;132 state = State.Start;
132 start_index = i + 1;133 start_index = i + 1;
133 },134 },
135 'x' => {
136 state = State.Hex { false };
137 },
138 'X' => {
139 state = State.Hex { true };
140 },
134 else => @compileError("Unknown format character: " ++ c),141 else => @compileError("Unknown format character: " ++ c),
135 },142 },
136 State.CloseBrace => switch (c) {143 State.CloseBrace => switch (c) {
...@@ -140,14 +147,25 @@ pub const OutStream = struct {...@@ -140,14 +147,25 @@ pub const OutStream = struct {
140 },147 },
141 else => @compileError("Single '}' encountered in format string"),148 else => @compileError("Single '}' encountered in format string"),
142 },149 },
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 },
143 }159 }
144 }160 }
145 comptime {161 comptime {
146 if (args.len != next_arg) {162 if (args.len != next_arg) {
147 @compileError("Unused arguments");163 @compileError("Unused arguments");
148 }164 }
149 if (state != State.Start) {165 // TODO https://github.com/andrewrk/zig/issues/253
150 @compileError("Incomplete format string: " ++ format);166 switch (state) {
167 State.Start => {},
168 else => @compileError("Incomplete format string: " ++ format),
151 }169 }
152 }170 }
153 if (start_index < format.len) {171 if (start_index < format.len) {
...@@ -159,7 +177,7 @@ pub const OutStream = struct {...@@ -159,7 +177,7 @@ pub const OutStream = struct {
159 pub fn printValue(self: &OutStream, value: var) -> %void {177 pub fn printValue(self: &OutStream, value: var) -> %void {
160 const T = @typeOf(value);178 const T = @typeOf(value);
161 if (@isInteger(T)) {179 if (@isInteger(T)) {
162 return self.printInt(T, value);180 return self.printInt(value, 10, false);
163 } else if (@isFloat(T)) {181 } else if (@isFloat(T)) {
164 return self.printFloat(T, value);182 return self.printFloat(T, value);
165 } else if (@canImplicitCast([]const u8, value)) {183 } else if (@canImplicitCast([]const u8, value)) {
...@@ -172,12 +190,11 @@ pub const OutStream = struct {...@@ -172,12 +190,11 @@ pub const OutStream = struct {
172 }190 }
173 }191 }
174192
175 pub fn printInt(self: &OutStream, comptime T: type, x: T) -> %void {193 pub fn printInt(self: &OutStream, x: var, base: u8, uppercase: bool) -> %void {
176 // TODO replace max_u64_base10_digits with math.log10(math.pow(2, @sizeOf(T)))194 if (self.index + max_int_digits >= self.buffer.len) {
177 if (self.index + max_u64_base10_digits >= self.buffer.len) {
178 %return self.flush();195 %return self.flush();
179 }196 }
180 const amt_printed = bufPrintInt(T, self.buffer[self.index...], x);197 const amt_printed = bufPrintInt(self.buffer[self.index...], x, base, uppercase);
181 self.index += amt_printed;198 self.index += amt_printed;
182 }199 }
183200
...@@ -448,39 +465,51 @@ fn charToDigit(c: u8, radix: u8) -> %u8 {...@@ -448,39 +465,51 @@ fn charToDigit(c: u8, radix: u8) -> %u8 {
448 return value;465 return value;
449}466}
450467
451pub fn bufPrintInt(comptime T: type, out_buf: []u8, x: T) -> usize {468fn digitToChar(digit: u8, uppercase: bool) -> u8 {
452 if (T.is_signed) bufPrintSigned(T, out_buf, x) else bufPrintUnsigned(T, out_buf, x)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 };
453}474}
454475
455fn bufPrintSigned(comptime T: type, out_buf: []u8, x: T) -> usize {476/// Guaranteed to not use more than max_int_digits
456 const uint = @intType(false, T.bit_count);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);
457 if (x < 0) {486 if (x < 0) {
458 out_buf[0] = '-';487 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);
460 } else {489 } else {
461 return bufPrintUnsigned(uint, out_buf, uint(x));490 return bufPrintUnsigned(out_buf, uint(x), base, uppercase);
462 }491 }
463}492}
464493
465fn bufPrintUnsigned(comptime T: type, out_buf: []u8, x: T) -> usize {494fn bufPrintUnsigned(out_buf: []u8, x: var, base: u8, uppercase: bool) -> usize {
466 var buf: [max_u64_base10_digits]u8 = undefined;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;
467 var a = x;498 var a = x;
468 var index: usize = buf.len;499 var index: usize = buf.len;
469500
470 while (true) {501 while (true) {
471 const digit = a % 10;502 const digit = a % base;
472 index -= 1;503 index -= 1;
473 buf[index] = '0' + u8(digit);504 buf[index] = digitToChar(u8(digit), uppercase);
474 a /= 10;505 a /= base;
475 if (a == 0)506 if (a == 0)
476 break;507 break;
477 }508 }
478509
479 const len = buf.len - index;510 const src_buf = buf[index...];
480511 mem.copy(u8, out_buf, src_buf);
481 @memcpy(&out_buf[0], &buf[index], len);512 return src_buf.len;
482
483 return len;
484}513}
485514
486fn parseU64DigitTooBig() {515fn parseU64DigitTooBig() {
...@@ -505,3 +534,19 @@ pub fn openSelfExe(stream: &InStream) -> %void {...@@ -505,3 +534,19 @@ pub fn openSelfExe(stream: &InStream) -> %void {
505 else => @compileError("unsupported os"),534 else => @compileError("unsupported os"),
506 }535 }
507}536}
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 {...@@ -29,3 +29,40 @@ pub fn shlOverflow(comptime T: type, a: T, b: T) -> %T {
29 var answer: T = undefined;29 var answer: T = undefined;
30 if (@shlWithOverflow(T, a, b, &answer)) error.Overflow else answer30 if (@shlWithOverflow(T, a, b, &answer)) error.Overflow else answer
31}31}
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 {...@@ -43,6 +43,9 @@ pub const Allocator = struct {
43/// Copy all of source into dest at position 0.43/// Copy all of source into dest at position 0.
44/// dest.len must be >= source.len.44/// dest.len must be >= source.len.
45pub fn copy(comptime T: type, dest: []T, source: []const T) {45pub 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
46 @setDebugSafety(this, false);49 @setDebugSafety(this, false);
47 assert(dest.len >= source.len);50 assert(dest.len >= source.len);
48 for (source) |s, i| dest[i] = s;51 for (source) |s, i| dest[i] = s;
...@@ -82,6 +85,23 @@ pub fn sliceAsInt(buf: []u8, is_be: bool, comptime T: type) -> T {...@@ -82,6 +85,23 @@ pub fn sliceAsInt(buf: []u8, is_be: bool, comptime T: type) -> T {
82 return result;85 return result;
83}86}
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
85fn testSliceAsInt() {105fn testSliceAsInt() {
86 @setFnTest(this);106 @setFnTest(this);
87 {107 {
std/sort.zig+3-4
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const assert = @import("debug.zig").assert;1const assert = @import("debug.zig").assert;
2const str = @import("str.zig");
3const mem = @import("mem.zig");2const mem = @import("mem.zig");
4const math = @import("math.zig");3const math = @import("math.zig");
54
...@@ -76,7 +75,7 @@ fn testSort() {...@@ -76,7 +75,7 @@ fn testSort() {
76 const slice = buf[0...case[0].len];75 const slice = buf[0...case[0].len];
77 mem.copy(u8, slice, case[0]);76 mem.copy(u8, slice, case[0]);
78 sort(u8, slice, u8asc);77 sort(u8, slice, u8asc);
79 assert(str.eql(slice, case[1]));78 assert(mem.eql(slice, case[1]));
80 }79 }
8180
82 const i32cases = [][][]i32 {81 const i32cases = [][][]i32 {
...@@ -93,7 +92,7 @@ fn testSort() {...@@ -93,7 +92,7 @@ fn testSort() {
93 const slice = buf[0...case[0].len];92 const slice = buf[0...case[0].len];
94 mem.copy(i32, slice, case[0]);93 mem.copy(i32, slice, case[0]);
95 sort(i32, slice, i32asc);94 sort(i32, slice, i32asc);
96 assert(str.sliceEql(i32, slice, case[1]));95 assert(mem.eql(slice, case[1]));
97 }96 }
98}97}
9998
...@@ -114,6 +113,6 @@ fn testSortDesc() {...@@ -114,6 +113,6 @@ fn testSortDesc() {
114 const slice = buf[0...case[0].len];113 const slice = buf[0...case[0].len];
115 mem.copy(i32, slice, case[0]);114 mem.copy(i32, slice, case[0]);
116 sort(i32, slice, i32desc);115 sort(i32, slice, i32desc);
117 assert(str.sliceEql(i32, slice, case[1]));116 assert(mem.eql(slice, case[1]));
118 }117 }
119}118}
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 @@...@@ -1,5 +1,5 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
2const str = @import("std").str;2const mem = @import("std").mem;
33
4fn arrays() {4fn arrays() {
5 @setFnTest(this);5 @setFnTest(this);
...@@ -63,10 +63,10 @@ fn nestedArrays() {...@@ -63,10 +63,10 @@ fn nestedArrays() {
6363
64 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};64 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};
65 for (array_of_strings) |s, i| {65 for (array_of_strings) |s, i| {
66 if (i == 0) assert(str.eql(s, "hello"));66 if (i == 0) assert(mem.eql(s, "hello"));
67 if (i == 1) assert(str.eql(s, "this"));67 if (i == 1) assert(mem.eql(s, "this"));
68 if (i == 2) assert(str.eql(s, "is"));68 if (i == 2) assert(mem.eql(s, "is"));
69 if (i == 3) assert(str.eql(s, "my"));69 if (i == 3) assert(mem.eql(s, "my"));
70 if (i == 4) assert(str.eql(s, "thing"));70 if (i == 4) assert(mem.eql(s, "thing"));
71 }71 }
72}72}
test/cases/enum_with_members.zig+5-5
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
2const str = @import("std").str;2const mem = @import("std").mem;
3const io = @import("std").io;3const io = @import("std").io;
44
5const ET = enum {5const ET = enum {
...@@ -8,8 +8,8 @@ const ET = enum {...@@ -8,8 +8,8 @@ const ET = enum {
88
9 pub fn print(a: &const ET, buf: []u8) -> %usize {9 pub fn print(a: &const ET, buf: []u8) -> %usize {
10 return switch (*a) {10 return switch (*a) {
11 ET.SINT => |x| { io.bufPrintInt(i32, buf, x) },11 ET.SINT => |x| { io.bufPrintInt(buf, x, 10, false) },
12 ET.UINT => |x| { io.bufPrintInt(u32, buf, x) },12 ET.UINT => |x| { io.bufPrintInt(buf, x, 10, false) },
13 }13 }
14 }14 }
15};15};
...@@ -22,8 +22,8 @@ fn enumWithMembers() {...@@ -22,8 +22,8 @@ fn enumWithMembers() {
22 var buf: [20]u8 = undefined;22 var buf: [20]u8 = undefined;
2323
24 assert(%%a.print(buf) == 3);24 assert(%%a.print(buf) == 3);
25 assert(str.eql(buf[0...3], "-42"));25 assert(mem.eql(buf[0...3], "-42"));
2626
27 assert(%%b.print(buf) == 2);27 assert(%%b.print(buf) == 2);
28 assert(str.eql(buf[0...2], "42"));28 assert(mem.eql(buf[0...2], "42"));
29}29}
test/cases/error.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
2const str = @import("std").str;2const mem = @import("std").mem;
33
4pub fn foo() -> %i32 {4pub fn foo() -> %i32 {
5 const x = %return bar();5 const x = %return bar();
...@@ -28,8 +28,8 @@ fn gimmeItBroke() -> []const u8 {...@@ -28,8 +28,8 @@ fn gimmeItBroke() -> []const u8 {
2828
29fn errorName() {29fn errorName() {
30 @setFnTest(this);30 @setFnTest(this);
31 assert(str.eql(@errorName(error.AnError), "AnError"));31 assert(mem.eql(@errorName(error.AnError), "AnError"));
32 assert(str.eql(@errorName(error.ALongerErrorName), "ALongerErrorName"));32 assert(mem.eql(@errorName(error.ALongerErrorName), "ALongerErrorName"));
33}33}
34error AnError;34error AnError;
35error ALongerErrorName;35error ALongerErrorName;
test/cases/eval.zig-1
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
2const str = @import("std").str;
32
4fn compileTimeRecursion() {3fn compileTimeRecursion() {
5 @setFnTest(this);4 @setFnTest(this);
test/cases/for.zig+2-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const str = std.str;3const mem = std.mem;
44
5fn continueInForLoop() {5fn continueInForLoop() {
6 @setFnTest(this);6 @setFnTest(this);
...@@ -24,7 +24,7 @@ fn forLoopWithPointerElemVar() {...@@ -24,7 +24,7 @@ fn forLoopWithPointerElemVar() {
24 var target: [source.len]u8 = undefined;24 var target: [source.len]u8 = undefined;
25 @memcpy(&target[0], &source[0], source.len);25 @memcpy(&target[0], &source[0], source.len);
26 mangleString(target);26 mangleString(target);
27 assert(str.eql(target, "bcdefgh"));27 assert(mem.eql(target, "bcdefgh"));
28}28}
29fn mangleString(s: []u8) {29fn mangleString(s: []u8) {
30 for (s) |*c| {30 for (s) |*c| {
test/cases/misc.zig+18-18
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const assert = @import("std").debug.assert;1const assert = @import("std").debug.assert;
2const str = @import("std").str;2const mem = @import("std").mem;
3const cstr = @import("std").cstr;3const cstr = @import("std").cstr;
44
5// normal comment5// normal comment
...@@ -144,7 +144,7 @@ fn first4KeysOfHomeRow() -> []const u8 {...@@ -144,7 +144,7 @@ fn first4KeysOfHomeRow() -> []const u8 {
144fn ReturnStringFromFunction() {144fn ReturnStringFromFunction() {
145 @setFnTest(this);145 @setFnTest(this);
146146
147 assert(str.eql(first4KeysOfHomeRow(), "aoeu"));147 assert(mem.eql(first4KeysOfHomeRow(), "aoeu"));
148}148}
149149
150const g1 : i32 = 1233 + 1;150const g1 : i32 = 1233 + 1;
...@@ -210,31 +210,31 @@ fn emptyFn() {}...@@ -210,31 +210,31 @@ fn emptyFn() {}
210fn hexEscape() {210fn hexEscape() {
211 @setFnTest(this);211 @setFnTest(this);
212212
213 assert(str.eql("\x68\x65\x6c\x6c\x6f", "hello"));213 assert(mem.eql("\x68\x65\x6c\x6c\x6f", "hello"));
214}214}
215215
216fn stringConcatenation() {216fn stringConcatenation() {
217 @setFnTest(this);217 @setFnTest(this);
218218
219 assert(str.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));219 assert(mem.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
220}220}
221221
222fn arrayMultOperator() {222fn arrayMultOperator() {
223 @setFnTest(this);223 @setFnTest(this);
224224
225 assert(str.eql("ab" ** 5, "ababababab"));225 assert(mem.eql("ab" ** 5, "ababababab"));
226}226}
227227
228fn stringEscapes() {228fn stringEscapes() {
229 @setFnTest(this);229 @setFnTest(this);
230230
231 assert(str.eql("\"", "\x22"));231 assert(mem.eql("\"", "\x22"));
232 assert(str.eql("\'", "\x27"));232 assert(mem.eql("\'", "\x27"));
233 assert(str.eql("\n", "\x0a"));233 assert(mem.eql("\n", "\x0a"));
234 assert(str.eql("\r", "\x0d"));234 assert(mem.eql("\r", "\x0d"));
235 assert(str.eql("\t", "\x09"));235 assert(mem.eql("\t", "\x09"));
236 assert(str.eql("\\", "\x5c"));236 assert(mem.eql("\\", "\x5c"));
237 assert(str.eql("\u1234\u0069", "\xe1\x88\xb4\x69"));237 assert(mem.eql("\u1234\u0069", "\xe1\x88\xb4\x69"));
238}238}
239239
240fn multilineString() {240fn multilineString() {
...@@ -246,7 +246,7 @@ fn multilineString() {...@@ -246,7 +246,7 @@ fn multilineString() {
246 \\three246 \\three
247 ;247 ;
248 const s2 = "one\ntwo)\nthree";248 const s2 = "one\ntwo)\nthree";
249 assert(str.eql(s1, s2));249 assert(mem.eql(s1, s2));
250}250}
251251
252fn multilineCString() {252fn multilineCString() {
...@@ -295,7 +295,7 @@ const some_mem : [100]u8 = undefined;...@@ -295,7 +295,7 @@ const some_mem : [100]u8 = undefined;
295fn memAlloc(comptime T: type, n: usize) -> %[]T {295fn memAlloc(comptime T: type, n: usize) -> %[]T {
296 return (&T)(&some_mem[0])[0...n];296 return (&T)(&some_mem[0])[0...n];
297}297}
298fn memFree(comptime T: type, mem: []T) { }298fn memFree(comptime T: type, memory: []T) { }
299299
300300
301fn castUndefined() {301fn castUndefined() {
...@@ -344,8 +344,8 @@ fn pointerDereferencing() {...@@ -344,8 +344,8 @@ fn pointerDereferencing() {
344fn callResultOfIfElseExpression() {344fn callResultOfIfElseExpression() {
345 @setFnTest(this);345 @setFnTest(this);
346346
347 assert(str.eql(f2(true), "a"));347 assert(mem.eql(f2(true), "a"));
348 assert(str.eql(f2(false), "b"));348 assert(mem.eql(f2(false), "b"));
349}349}
350fn f2(x: bool) -> []u8 {350fn f2(x: bool) -> []u8 {
351 return (if (x) fA else fB)();351 return (if (x) fA else fB)();
...@@ -562,8 +562,8 @@ fn typeName() {...@@ -562,8 +562,8 @@ fn typeName() {
562 @setFnTest(this);562 @setFnTest(this);
563563
564 comptime {564 comptime {
565 assert(str.eql(@typeName(i64), "i64"));565 assert(mem.eql(@typeName(i64), "i64"));
566 assert(str.eql(@typeName(&usize), "&usize"));566 assert(mem.eql(@typeName(&usize), "&usize"));
567 }567 }
568}568}
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;...@@ -471,21 +471,17 @@ const io = @import("std").io;
471pub fn main(args: [][]u8) -> %void {471pub fn main(args: [][]u8) -> %void {
472 const array = []u8 {9, 8, 7, 6};472 const array = []u8 {9, 8, 7, 6};
473 for (array) |item| {473 for (array) |item| {
474 %%io.stdout.printInt(@typeOf(item), item);474 %%io.stdout.printf("{}\n", item);
475 %%io.stdout.printf("\n");
476 }475 }
477 for (array) |item, index| {476 for (array) |item, index| {
478 %%io.stdout.printInt(@typeOf(index), index);477 %%io.stdout.printf("{}\n", index);
479 %%io.stdout.printf("\n");
480 }478 }
481 const unknown_size: []u8 = array;479 const unknown_size: []u8 = array;
482 for (unknown_size) |item| {480 for (unknown_size) |item| {
483 %%io.stdout.printInt(@typeOf(item), item);481 %%io.stdout.printf("{}\n", item);
484 %%io.stdout.printf("\n");
485 }482 }
486 for (unknown_size) |item, index| {483 for (unknown_size) |item, index| {
487 %%io.stdout.printInt(@typeOf(index), index);484 %%io.stdout.printf("{}\n", index);
488 %%io.stdout.printf("\n");
489 }485 }
490}486}
491 )SOURCE", "9\n8\n7\n6\n0\n1\n2\n3\n9\n8\n7\n6\n0\n1\n2\n3\n");487 )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 }...@@ -1124,13 +1120,6 @@ fn get() -> usize { global_var }
1124 ".tmp_source.zig:3:8: note: called from here");1120 ".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
1134 add_compile_fail_case("addition with non numbers", R"SOURCE(1123 add_compile_fail_case("addition with non numbers", R"SOURCE(
1135const Foo = struct {1124const Foo = struct {
1136 field: i32,1125 field: i32,
...@@ -1588,25 +1577,6 @@ fn derp() {...@@ -1588,25 +1577,6 @@ fn derp() {
1588}1577}
1589 )SOURCE", 1, ".tmp_source.zig:7:13: error: cannot assign to constant");1578 )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
1610 add_compile_fail_case("return from defer expression", R"SOURCE(1580 add_compile_fail_case("return from defer expression", R"SOURCE(
1611pub fn testTrickyDefer() -> %void {1581pub fn testTrickyDefer() -> %void {
1612 defer canFail() %% {};1582 defer canFail() %% {};
test/self_hosted.zig+1
...@@ -32,4 +32,5 @@ const test_try = @import("cases/try.zig");...@@ -32,4 +32,5 @@ const test_try = @import("cases/try.zig");
32const test_typedef = @import("cases/typedef.zig");32const test_typedef = @import("cases/typedef.zig");
33const test_undefined = @import("cases/undefined.zig");33const test_undefined = @import("cases/undefined.zig");
34const test_var_args = @import("cases/var_args.zig");34const test_var_args = @import("cases/var_args.zig");
35const test_void = @import("cases/void.zig");
35const test_while = @import("cases/while.zig");36const test_while = @import("cases/while.zig");