| author | |
| committer | |
| log | 8a859afd580f438f549ee69a3e3487eb5d119fad |
| tree | cbbd2d01bdd73a160b90dc280e7fbc05e7d963a8 |
| parent | 92793252ad43c4119902506f95e726de3492c128 |
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}") |
| 225 | install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}") | 225 | install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}") |
| 226 | install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}") | 226 | install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}") |
| 227 | install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}") | 227 | install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}") |
| 228 | install(FILES "${CMAKE_SOURCE_DIR}/std/str.zig" DESTINATION "${ZIG_STD_DEST}") | ||
| 229 | install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner.zig" DESTINATION "${ZIG_STD_DEST}") | 228 | install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner.zig" DESTINATION "${ZIG_STD_DEST}") |
| 230 | install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig" DESTINATION "${ZIG_STD_DEST}") | 229 | install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig" DESTINATION "${ZIG_STD_DEST}") |
| 231 | install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_nolibc.zig" DESTINATION "${ZIG_STD_DEST}") | 230 | install(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); |
| 8538 | 8538 | ||
| 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; |
| 8549 | 8541 | ||
| ... | @@ -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 @@ |
| 1 | const io = @import("io.zig"); | 1 | const io = @import("io.zig"); |
| 2 | const str = @import("str.zig"); | ||
| 3 | const math = @import("math.zig"); | 2 | const math = @import("math.zig"); |
| 4 | const mem = @import("mem.zig"); | 3 | const mem = @import("mem.zig"); |
| 5 | const debug = @import("debug.zig"); | 4 | const debug = @import("debug.zig"); |
| ... | @@ -95,7 +94,7 @@ pub const Elf = struct { | ... | @@ -95,7 +94,7 @@ pub const Elf = struct { |
| 95 | 94 | ||
| 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; |
| 99 | 98 | ||
| 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"); |
| 2 | pub const io = @import("io.zig"); | 2 | pub const io = @import("io.zig"); |
| 3 | pub const os = @import("os.zig"); | 3 | pub const os = @import("os.zig"); |
| 4 | pub const math = @import("math.zig"); | 4 | pub const math = @import("math.zig"); |
| 5 | pub const str = @import("str.zig"); | ||
| 6 | pub const cstr = @import("cstr.zig"); | 5 | pub const cstr = @import("cstr.zig"); |
| 7 | pub const sort = @import("sort.zig"); | 6 | pub const sort = @import("sort.zig"); |
| 8 | pub const net = @import("net.zig"); | 7 | pub const net = @import("net.zig"); |
std/io.zig+69-24| ... | @@ -61,8 +61,8 @@ error Unseekable; | ... | @@ -61,8 +61,8 @@ error Unseekable; |
| 61 | error Eof; | 61 | error Eof; |
| 62 | 62 | ||
| 63 | const buffer_size = 4 * 1024; | 63 | const buffer_size = 4 * 1024; |
| 64 | const max_u64_base10_digits = 20; | ||
| 65 | const max_f64_digits = 65; | 64 | const max_f64_digits = 65; |
| 65 | const max_int_digits = 65; | ||
| 66 | 66 | ||
| 67 | pub const OpenRead = 0b0001; | 67 | pub const OpenRead = 0b0001; |
| 68 | pub const OpenWrite = 0b0010; | 68 | pub 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 | }; |
| 104 | 105 | ||
| 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 | } |
| 174 | 192 | ||
| 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 | } |
| 183 | 200 | ||
| ... | @@ -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 | } |
| 450 | 467 | ||
| 451 | pub fn bufPrintInt(comptime T: type, out_buf: []u8, x: T) -> usize { | 468 | fn 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 | } |
| 454 | 475 | ||
| 455 | fn 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); | 477 | pub 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 | |||
| 484 | fn 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 | } |
| 464 | 493 | ||
| 465 | fn bufPrintUnsigned(comptime T: type, out_buf: []u8, x: T) -> usize { | 494 | fn 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; |
| 469 | 500 | ||
| 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 | } |
| 478 | 509 | ||
| 479 | const len = buf.len - index; | 510 | const src_buf = buf[index...]; |
| 480 | 511 | 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 | } |
| 485 | 514 | ||
| 486 | fn parseU64DigitTooBig() { | 515 | fn 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 | |||
| 538 | fn bufPrintIntToSlice(buf: []u8, x: var, base: u8, uppercase: bool) -> []u8 { | ||
| 539 | return buf[0...bufPrintInt(buf, x, base, uppercase)]; | ||
| 540 | } | ||
| 541 | |||
| 542 | fn 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 answer | 30 | if (@shlWithOverflow(T, a, b, &answer)) error.Overflow else answer |
| 31 | } | 31 | } |
| 32 | |||
| 33 | pub 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)). | ||
| 51 | pub 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 | } | ||
| 61 | fn 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. |
| 45 | pub fn copy(comptime T: type, dest: []T, source: []const T) { | 45 | pub 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 | } |
| 84 | 87 | ||
| 88 | /// Compares two slices and returns whether they are equal. | ||
| 89 | pub 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 | |||
| 97 | fn testStringEquality() { | ||
| 98 | @setFnTest(this); | ||
| 99 | |||
| 100 | assert(eql("abcd", "abcd")); | ||
| 101 | assert(!eql("abcdef", "abZdef")); | ||
| 102 | assert(!eql("abcdefg", "abcdef")); | ||
| 103 | } | ||
| 104 | |||
| 85 | fn testSliceAsInt() { | 105 | fn testSliceAsInt() { |
| 86 | @setFnTest(this); | 106 | @setFnTest(this); |
| 87 | { | 107 | { |
std/sort.zig+3-4| ... | @@ -1,5 +1,4 @@ | ... | @@ -1,5 +1,4 @@ |
| 1 | const assert = @import("debug.zig").assert; | 1 | const assert = @import("debug.zig").assert; |
| 2 | const str = @import("str.zig"); | ||
| 3 | const mem = @import("mem.zig"); | 2 | const mem = @import("mem.zig"); |
| 4 | const math = @import("math.zig"); | 3 | const math = @import("math.zig"); |
| 5 | 4 | ||
| ... | @@ -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 | } |
| 81 | 80 | ||
| 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 | } |
| 99 | 98 | ||
| ... | @@ -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 @@ | ||
| 1 | const assert = @import("debug.zig").assert; | ||
| 2 | |||
| 3 | pub fn eql(a: []const u8, b: []const u8) -> bool { | ||
| 4 | sliceEql(u8, a, b) | ||
| 5 | } | ||
| 6 | |||
| 7 | pub 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 | |||
| 15 | fn 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 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | const str = @import("std").str; | 2 | const mem = @import("std").mem; |
| 3 | 3 | ||
| 4 | fn arrays() { | 4 | fn arrays() { |
| 5 | @setFnTest(this); | 5 | @setFnTest(this); |
| ... | @@ -63,10 +63,10 @@ fn nestedArrays() { | ... | @@ -63,10 +63,10 @@ fn nestedArrays() { |
| 63 | 63 | ||
| 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 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | const str = @import("std").str; | 2 | const mem = @import("std").mem; |
| 3 | const io = @import("std").io; | 3 | const io = @import("std").io; |
| 4 | 4 | ||
| 5 | const ET = enum { | 5 | const ET = enum { |
| ... | @@ -8,8 +8,8 @@ const ET = enum { | ... | @@ -8,8 +8,8 @@ const ET = enum { |
| 8 | 8 | ||
| 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; |
| 23 | 23 | ||
| 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")); |
| 26 | 26 | ||
| 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 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | const str = @import("std").str; | 2 | const mem = @import("std").mem; |
| 3 | 3 | ||
| 4 | pub fn foo() -> %i32 { | 4 | pub 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 { |
| 28 | 28 | ||
| 29 | fn errorName() { | 29 | fn 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 | } |
| 34 | error AnError; | 34 | error AnError; |
| 35 | error ALongerErrorName; | 35 | error ALongerErrorName; |
test/cases/eval.zig-1| ... | @@ -1,5 +1,4 @@ | ... | @@ -1,5 +1,4 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | const str = @import("std").str; | ||
| 3 | 2 | ||
| 4 | fn compileTimeRecursion() { | 3 | fn compileTimeRecursion() { |
| 5 | @setFnTest(this); | 4 | @setFnTest(this); |
test/cases/for.zig+2-2| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const assert = std.debug.assert; | 2 | const assert = std.debug.assert; |
| 3 | const str = std.str; | 3 | const mem = std.mem; |
| 4 | 4 | ||
| 5 | fn continueInForLoop() { | 5 | fn 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 | } |
| 29 | fn mangleString(s: []u8) { | 29 | fn 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 @@ |
| 1 | const assert = @import("std").debug.assert; | 1 | const assert = @import("std").debug.assert; |
| 2 | const str = @import("std").str; | 2 | const mem = @import("std").mem; |
| 3 | const cstr = @import("std").cstr; | 3 | const cstr = @import("std").cstr; |
| 4 | 4 | ||
| 5 | // normal comment | 5 | // normal comment |
| ... | @@ -144,7 +144,7 @@ fn first4KeysOfHomeRow() -> []const u8 { | ... | @@ -144,7 +144,7 @@ fn first4KeysOfHomeRow() -> []const u8 { |
| 144 | fn ReturnStringFromFunction() { | 144 | fn ReturnStringFromFunction() { |
| 145 | @setFnTest(this); | 145 | @setFnTest(this); |
| 146 | 146 | ||
| 147 | assert(str.eql(first4KeysOfHomeRow(), "aoeu")); | 147 | assert(mem.eql(first4KeysOfHomeRow(), "aoeu")); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | const g1 : i32 = 1233 + 1; | 150 | const g1 : i32 = 1233 + 1; |
| ... | @@ -210,31 +210,31 @@ fn emptyFn() {} | ... | @@ -210,31 +210,31 @@ fn emptyFn() {} |
| 210 | fn hexEscape() { | 210 | fn hexEscape() { |
| 211 | @setFnTest(this); | 211 | @setFnTest(this); |
| 212 | 212 | ||
| 213 | assert(str.eql("\x68\x65\x6c\x6c\x6f", "hello")); | 213 | assert(mem.eql("\x68\x65\x6c\x6c\x6f", "hello")); |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | fn stringConcatenation() { | 216 | fn stringConcatenation() { |
| 217 | @setFnTest(this); | 217 | @setFnTest(this); |
| 218 | 218 | ||
| 219 | assert(str.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); | 219 | assert(mem.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | fn arrayMultOperator() { | 222 | fn arrayMultOperator() { |
| 223 | @setFnTest(this); | 223 | @setFnTest(this); |
| 224 | 224 | ||
| 225 | assert(str.eql("ab" ** 5, "ababababab")); | 225 | assert(mem.eql("ab" ** 5, "ababababab")); |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | fn stringEscapes() { | 228 | fn stringEscapes() { |
| 229 | @setFnTest(this); | 229 | @setFnTest(this); |
| 230 | 230 | ||
| 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 | } |
| 239 | 239 | ||
| 240 | fn multilineString() { | 240 | fn multilineString() { |
| ... | @@ -246,7 +246,7 @@ fn multilineString() { | ... | @@ -246,7 +246,7 @@ fn multilineString() { |
| 246 | \\three | 246 | \\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 | } |
| 251 | 251 | ||
| 252 | fn multilineCString() { | 252 | fn multilineCString() { |
| ... | @@ -295,7 +295,7 @@ const some_mem : [100]u8 = undefined; | ... | @@ -295,7 +295,7 @@ const some_mem : [100]u8 = undefined; |
| 295 | fn memAlloc(comptime T: type, n: usize) -> %[]T { | 295 | fn 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 | } |
| 298 | fn memFree(comptime T: type, mem: []T) { } | 298 | fn memFree(comptime T: type, memory: []T) { } |
| 299 | 299 | ||
| 300 | 300 | ||
| 301 | fn castUndefined() { | 301 | fn castUndefined() { |
| ... | @@ -344,8 +344,8 @@ fn pointerDereferencing() { | ... | @@ -344,8 +344,8 @@ fn pointerDereferencing() { |
| 344 | fn callResultOfIfElseExpression() { | 344 | fn callResultOfIfElseExpression() { |
| 345 | @setFnTest(this); | 345 | @setFnTest(this); |
| 346 | 346 | ||
| 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 | } |
| 350 | fn f2(x: bool) -> []u8 { | 350 | fn 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); |
| 563 | 563 | ||
| 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 | } |
| 569 | 569 |
test/cases/void.zig created+20| ... | @@ -0,0 +1,20 @@ | ||
| 1 | const assert = @import("std").debug.assert; | ||
| 2 | |||
| 3 | const Foo = struct { | ||
| 4 | a: void, | ||
| 5 | b: i32, | ||
| 6 | c: void, | ||
| 7 | }; | ||
| 8 | |||
| 9 | fn 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; |
| 471 | pub fn main(args: [][]u8) -> %void { | 471 | pub 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"); |
| 1125 | 1121 | ||
| 1126 | 1122 | ||
| 1127 | add_compile_fail_case("unnecessary if statement", R"SOURCE( | ||
| 1128 | fn 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( |
| 1135 | const Foo = struct { | 1124 | const 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"); |
| 1590 | 1579 | ||
| 1591 | add_compile_fail_case("compare void with void is compile time known", R"SOURCE( | ||
| 1592 | const Foo = struct { | ||
| 1593 | a: void, | ||
| 1594 | b: i32, | ||
| 1595 | c: void, | ||
| 1596 | }; | ||
| 1597 | |||
| 1598 | fn 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( |
| 1611 | pub fn testTrickyDefer() -> %void { | 1581 | pub 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"); |
| 32 | const test_typedef = @import("cases/typedef.zig"); | 32 | const test_typedef = @import("cases/typedef.zig"); |
| 33 | const test_undefined = @import("cases/undefined.zig"); | 33 | const test_undefined = @import("cases/undefined.zig"); |
| 34 | const test_var_args = @import("cases/var_args.zig"); | 34 | const test_var_args = @import("cases/var_args.zig"); |
| 35 | const test_void = @import("cases/void.zig"); | ||
| 35 | const test_while = @import("cases/while.zig"); | 36 | const test_while = @import("cases/while.zig"); |