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.master
parent
92793252ad
commit
8a859afd58
|
@ -225,7 +225,6 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/panic.zig" DESTINATION "${ZIG_STD_DEST}")
|
|||
install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/str.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_nolibc.zig" DESTINATION "${ZIG_STD_DEST}")
|
||||
|
|
12
src/ir.cpp
12
src/ir.cpp
|
@ -8536,14 +8536,6 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
|
|||
if (!ir_resolve_bool(ira, condition, &cond_is_true))
|
||||
return ir_unreach_error(ira);
|
||||
|
||||
if (!cond_br_instruction->base.is_gen && !condition->value.depends_on_compile_var &&
|
||||
!ir_should_inline(ira->new_irb.exec, cond_br_instruction->base.scope))
|
||||
{
|
||||
const char *true_or_false = cond_is_true ? "true" : "false";
|
||||
ir_add_error(ira, &cond_br_instruction->base,
|
||||
buf_sprintf("condition is always %s; unnecessary if statement", true_or_false));
|
||||
}
|
||||
|
||||
IrBasicBlock *old_dest_block = cond_is_true ?
|
||||
cond_br_instruction->then_block : cond_br_instruction->else_block;
|
||||
|
||||
|
@ -9060,7 +9052,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
|
|||
bool ptr_is_const = true;
|
||||
bool ptr_is_volatile = false;
|
||||
return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,
|
||||
usize, false, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);
|
||||
usize, depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);
|
||||
} else {
|
||||
ir_add_error_node(ira, source_node,
|
||||
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
|
|||
bool ptr_is_const = true;
|
||||
bool ptr_is_volatile = false;
|
||||
return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val,
|
||||
usize, false, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);
|
||||
usize, depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const, ptr_is_volatile);
|
||||
} else {
|
||||
ir_add_error_node(ira, source_node,
|
||||
buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const io = @import("io.zig");
|
||||
const str = @import("str.zig");
|
||||
const math = @import("math.zig");
|
||||
const mem = @import("mem.zig");
|
||||
const debug = @import("debug.zig");
|
||||
|
@ -95,7 +94,7 @@ pub const Elf = struct {
|
|||
|
||||
var magic: [4]u8 = undefined;
|
||||
%return elf.in_stream.readNoEof(magic);
|
||||
if (!str.eql(magic, "\x7fELF")) return error.InvalidFormat;
|
||||
if (!mem.eql(magic, "\x7fELF")) return error.InvalidFormat;
|
||||
|
||||
elf.is_64 = switch (%return elf.in_stream.readByte()) {
|
||||
1 => false,
|
||||
|
|
|
@ -2,7 +2,6 @@ pub const rand = @import("rand.zig");
|
|||
pub const io = @import("io.zig");
|
||||
pub const os = @import("os.zig");
|
||||
pub const math = @import("math.zig");
|
||||
pub const str = @import("str.zig");
|
||||
pub const cstr = @import("cstr.zig");
|
||||
pub const sort = @import("sort.zig");
|
||||
pub const net = @import("net.zig");
|
||||
|
|
93
std/io.zig
93
std/io.zig
|
@ -61,8 +61,8 @@ error Unseekable;
|
|||
error Eof;
|
||||
|
||||
const buffer_size = 4 * 1024;
|
||||
const max_u64_base10_digits = 20;
|
||||
const max_f64_digits = 65;
|
||||
const max_int_digits = 65;
|
||||
|
||||
pub const OpenRead = 0b0001;
|
||||
pub const OpenWrite = 0b0010;
|
||||
|
@ -100,6 +100,7 @@ pub const OutStream = struct {
|
|||
Start,
|
||||
OpenBrace,
|
||||
CloseBrace,
|
||||
Hex: bool,
|
||||
};
|
||||
|
||||
/// Calls print and then flushes the buffer.
|
||||
|
@ -131,6 +132,12 @@ pub const OutStream = struct {
|
|||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
'x' => {
|
||||
state = State.Hex { false };
|
||||
},
|
||||
'X' => {
|
||||
state = State.Hex { true };
|
||||
},
|
||||
else => @compileError("Unknown format character: " ++ c),
|
||||
},
|
||||
State.CloseBrace => switch (c) {
|
||||
|
@ -140,14 +147,25 @@ pub const OutStream = struct {
|
|||
},
|
||||
else => @compileError("Single '}' encountered in format string"),
|
||||
},
|
||||
State.Hex => |uppercase| switch (c) {
|
||||
'}' => {
|
||||
self.printInt(args[next_arg], 16, uppercase);
|
||||
next_arg += 1;
|
||||
state = State.Start;
|
||||
start_index = i + 1;
|
||||
},
|
||||
else => @compileError("Expected '}' after 'x'/'X' in format string"),
|
||||
},
|
||||
}
|
||||
}
|
||||
comptime {
|
||||
if (args.len != next_arg) {
|
||||
@compileError("Unused arguments");
|
||||
}
|
||||
if (state != State.Start) {
|
||||
@compileError("Incomplete format string: " ++ format);
|
||||
// TODO https://github.com/andrewrk/zig/issues/253
|
||||
switch (state) {
|
||||
State.Start => {},
|
||||
else => @compileError("Incomplete format string: " ++ format),
|
||||
}
|
||||
}
|
||||
if (start_index < format.len) {
|
||||
|
@ -159,7 +177,7 @@ pub const OutStream = struct {
|
|||
pub fn printValue(self: &OutStream, value: var) -> %void {
|
||||
const T = @typeOf(value);
|
||||
if (@isInteger(T)) {
|
||||
return self.printInt(T, value);
|
||||
return self.printInt(value, 10, false);
|
||||
} else if (@isFloat(T)) {
|
||||
return self.printFloat(T, value);
|
||||
} else if (@canImplicitCast([]const u8, value)) {
|
||||
|
@ -172,12 +190,11 @@ pub const OutStream = struct {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn printInt(self: &OutStream, comptime T: type, x: T) -> %void {
|
||||
// TODO replace max_u64_base10_digits with math.log10(math.pow(2, @sizeOf(T)))
|
||||
if (self.index + max_u64_base10_digits >= self.buffer.len) {
|
||||
pub fn printInt(self: &OutStream, x: var, base: u8, uppercase: bool) -> %void {
|
||||
if (self.index + max_int_digits >= self.buffer.len) {
|
||||
%return self.flush();
|
||||
}
|
||||
const amt_printed = bufPrintInt(T, self.buffer[self.index...], x);
|
||||
const amt_printed = bufPrintInt(self.buffer[self.index...], x, base, uppercase);
|
||||
self.index += amt_printed;
|
||||
}
|
||||
|
||||
|
@ -448,39 +465,51 @@ fn charToDigit(c: u8, radix: u8) -> %u8 {
|
|||
return value;
|
||||
}
|
||||
|
||||
pub fn bufPrintInt(comptime T: type, out_buf: []u8, x: T) -> usize {
|
||||
if (T.is_signed) bufPrintSigned(T, out_buf, x) else bufPrintUnsigned(T, out_buf, x)
|
||||
fn digitToChar(digit: u8, uppercase: bool) -> u8 {
|
||||
return switch (digit) {
|
||||
0 ... 9 => digit + '0',
|
||||
10 ... 35 => digit + ((if (uppercase) u8('A') else u8('a')) - 10),
|
||||
else => @unreachable(),
|
||||
};
|
||||
}
|
||||
|
||||
fn bufPrintSigned(comptime T: type, out_buf: []u8, x: T) -> usize {
|
||||
const uint = @intType(false, T.bit_count);
|
||||
/// Guaranteed to not use more than max_int_digits
|
||||
pub fn bufPrintInt(out_buf: []u8, x: var, base: u8, uppercase: bool) -> usize {
|
||||
if (@typeOf(x).is_signed)
|
||||
bufPrintSigned(out_buf, x, base, uppercase)
|
||||
else
|
||||
bufPrintUnsigned(out_buf, x, base, uppercase)
|
||||
}
|
||||
|
||||
fn bufPrintSigned(out_buf: []u8, x: var, base: u8, uppercase: bool) -> usize {
|
||||
const uint = @intType(false, @typeOf(x).bit_count);
|
||||
if (x < 0) {
|
||||
out_buf[0] = '-';
|
||||
return 1 + bufPrintUnsigned(uint, out_buf[1...], uint(-(x + 1)) + 1);
|
||||
return 1 + bufPrintUnsigned(out_buf[1...], uint(-(x + 1)) + 1, base, uppercase);
|
||||
} else {
|
||||
return bufPrintUnsigned(uint, out_buf, uint(x));
|
||||
return bufPrintUnsigned(out_buf, uint(x), base, uppercase);
|
||||
}
|
||||
}
|
||||
|
||||
fn bufPrintUnsigned(comptime T: type, out_buf: []u8, x: T) -> usize {
|
||||
var buf: [max_u64_base10_digits]u8 = undefined;
|
||||
fn bufPrintUnsigned(out_buf: []u8, x: var, base: u8, uppercase: bool) -> usize {
|
||||
// max_int_digits accounts for the minus sign. when printing an unsigned
|
||||
// number we don't need to do that.
|
||||
var buf: [max_int_digits - 1]u8 = undefined;
|
||||
var a = x;
|
||||
var index: usize = buf.len;
|
||||
|
||||
while (true) {
|
||||
const digit = a % 10;
|
||||
const digit = a % base;
|
||||
index -= 1;
|
||||
buf[index] = '0' + u8(digit);
|
||||
a /= 10;
|
||||
buf[index] = digitToChar(u8(digit), uppercase);
|
||||
a /= base;
|
||||
if (a == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
const len = buf.len - index;
|
||||
|
||||
@memcpy(&out_buf[0], &buf[index], len);
|
||||
|
||||
return len;
|
||||
const src_buf = buf[index...];
|
||||
mem.copy(u8, out_buf, src_buf);
|
||||
return src_buf.len;
|
||||
}
|
||||
|
||||
fn parseU64DigitTooBig() {
|
||||
|
@ -505,3 +534,19 @@ pub fn openSelfExe(stream: &InStream) -> %void {
|
|||
else => @compileError("unsupported os"),
|
||||
}
|
||||
}
|
||||
|
||||
fn bufPrintIntToSlice(buf: []u8, x: var, base: u8, uppercase: bool) -> []u8 {
|
||||
return buf[0...bufPrintInt(buf, x, base, uppercase)];
|
||||
}
|
||||
|
||||
fn testBufPrintInt() {
|
||||
@setFnTest(this);
|
||||
|
||||
var buf: [max_int_digits]u8 = undefined;
|
||||
assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 2, false), "-101111000110000101001110"));
|
||||
assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 10, false), "-12345678"));
|
||||
assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 16, false), "-bc614e"));
|
||||
assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 16, true), "-BC614E"));
|
||||
|
||||
assert(mem.eql(bufPrintIntToSlice(buf, u32(12345678), 10, true), "12345678"));
|
||||
}
|
||||
|
|
37
std/math.zig
37
std/math.zig
|
@ -29,3 +29,40 @@ pub fn shlOverflow(comptime T: type, a: T, b: T) -> %T {
|
|||
var answer: T = undefined;
|
||||
if (@shlWithOverflow(T, a, b, &answer)) error.Overflow else answer
|
||||
}
|
||||
|
||||
pub fn log(comptime base: usize, value: var) -> @typeOf(value) {
|
||||
const T = @typeOf(value);
|
||||
if (@isInteger(T)) {
|
||||
if (base == 2) {
|
||||
return T.bit_count - 1 - @clz(value);
|
||||
} else {
|
||||
@compileError("TODO implement log for non base 2 integers");
|
||||
}
|
||||
} else if (@isFloat(T)) {
|
||||
@compileError("TODO implement log for floats");
|
||||
} else {
|
||||
@compileError("log expects integer or float, found '" ++ @typeName(T) ++ "'");
|
||||
}
|
||||
}
|
||||
|
||||
/// x must be an integer or a float
|
||||
/// Note that this causes undefined behavior if
|
||||
/// @typeOf(x).is_signed && x == @minValue(@typeOf(x)).
|
||||
pub fn abs(x: var) -> @typeOf(x) {
|
||||
const T = @typeOf(x);
|
||||
if (@isInteger(T)) {
|
||||
return if (x < 0) -x else x;
|
||||
} else if (@isFloat(T)) {
|
||||
@compileError("TODO implement abs for floats");
|
||||
} else {
|
||||
@unreachable();
|
||||
}
|
||||
}
|
||||
fn getReturnTypeForAbs(comptime T: type) -> type {
|
||||
if (@isInteger(T)) {
|
||||
return @intType(false, T.bit_count);
|
||||
} else {
|
||||
return T;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
20
std/mem.zig
20
std/mem.zig
|
@ -43,6 +43,9 @@ pub const Allocator = struct {
|
|||
/// Copy all of source into dest at position 0.
|
||||
/// dest.len must be >= source.len.
|
||||
pub fn copy(comptime T: type, dest: []T, source: []const T) {
|
||||
// TODO instead of manually doing this check for the whole array
|
||||
// and turning off debug safety, the compiler should detect loops like
|
||||
// this and automatically omit safety checks for loops
|
||||
@setDebugSafety(this, false);
|
||||
assert(dest.len >= source.len);
|
||||
for (source) |s, i| dest[i] = s;
|
||||
|
@ -82,6 +85,23 @@ pub fn sliceAsInt(buf: []u8, is_be: bool, comptime T: type) -> T {
|
|||
return result;
|
||||
}
|
||||
|
||||
/// Compares two slices and returns whether they are equal.
|
||||
pub fn eql(a: var, b: var) -> bool {
|
||||
if (a.len != b.len) return false;
|
||||
for (a) |item, index| {
|
||||
if (b[index] != item) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn testStringEquality() {
|
||||
@setFnTest(this);
|
||||
|
||||
assert(eql("abcd", "abcd"));
|
||||
assert(!eql("abcdef", "abZdef"));
|
||||
assert(!eql("abcdefg", "abcdef"));
|
||||
}
|
||||
|
||||
fn testSliceAsInt() {
|
||||
@setFnTest(this);
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const assert = @import("debug.zig").assert;
|
||||
const str = @import("str.zig");
|
||||
const mem = @import("mem.zig");
|
||||
const math = @import("math.zig");
|
||||
|
||||
|
@ -76,7 +75,7 @@ fn testSort() {
|
|||
const slice = buf[0...case[0].len];
|
||||
mem.copy(u8, slice, case[0]);
|
||||
sort(u8, slice, u8asc);
|
||||
assert(str.eql(slice, case[1]));
|
||||
assert(mem.eql(slice, case[1]));
|
||||
}
|
||||
|
||||
const i32cases = [][][]i32 {
|
||||
|
@ -93,7 +92,7 @@ fn testSort() {
|
|||
const slice = buf[0...case[0].len];
|
||||
mem.copy(i32, slice, case[0]);
|
||||
sort(i32, slice, i32asc);
|
||||
assert(str.sliceEql(i32, slice, case[1]));
|
||||
assert(mem.eql(slice, case[1]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +113,6 @@ fn testSortDesc() {
|
|||
const slice = buf[0...case[0].len];
|
||||
mem.copy(i32, slice, case[0]);
|
||||
sort(i32, slice, i32desc);
|
||||
assert(str.sliceEql(i32, slice, case[1]));
|
||||
assert(mem.eql(slice, case[1]));
|
||||
}
|
||||
}
|
||||
|
|
21
std/str.zig
21
std/str.zig
|
@ -1,21 +0,0 @@
|
|||
const assert = @import("debug.zig").assert;
|
||||
|
||||
pub fn eql(a: []const u8, b: []const u8) -> bool {
|
||||
sliceEql(u8, a, b)
|
||||
}
|
||||
|
||||
pub fn sliceEql(comptime T: type, a: []const T, b: []const T) -> bool {
|
||||
if (a.len != b.len) return false;
|
||||
for (a) |item, index| {
|
||||
if (b[index] != item) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn testStringEquality() {
|
||||
@setFnTest(this);
|
||||
|
||||
assert(eql("abcd", "abcd"));
|
||||
assert(!eql("abcdef", "abZdef"));
|
||||
assert(!eql("abcdefg", "abcdef"));
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
const str = @import("std").str;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
fn arrays() {
|
||||
@setFnTest(this);
|
||||
|
@ -63,10 +63,10 @@ fn nestedArrays() {
|
|||
|
||||
const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};
|
||||
for (array_of_strings) |s, i| {
|
||||
if (i == 0) assert(str.eql(s, "hello"));
|
||||
if (i == 1) assert(str.eql(s, "this"));
|
||||
if (i == 2) assert(str.eql(s, "is"));
|
||||
if (i == 3) assert(str.eql(s, "my"));
|
||||
if (i == 4) assert(str.eql(s, "thing"));
|
||||
if (i == 0) assert(mem.eql(s, "hello"));
|
||||
if (i == 1) assert(mem.eql(s, "this"));
|
||||
if (i == 2) assert(mem.eql(s, "is"));
|
||||
if (i == 3) assert(mem.eql(s, "my"));
|
||||
if (i == 4) assert(mem.eql(s, "thing"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
const str = @import("std").str;
|
||||
const mem = @import("std").mem;
|
||||
const io = @import("std").io;
|
||||
|
||||
const ET = enum {
|
||||
|
@ -8,8 +8,8 @@ const ET = enum {
|
|||
|
||||
pub fn print(a: &const ET, buf: []u8) -> %usize {
|
||||
return switch (*a) {
|
||||
ET.SINT => |x| { io.bufPrintInt(i32, buf, x) },
|
||||
ET.UINT => |x| { io.bufPrintInt(u32, buf, x) },
|
||||
ET.SINT => |x| { io.bufPrintInt(buf, x, 10, false) },
|
||||
ET.UINT => |x| { io.bufPrintInt(buf, x, 10, false) },
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -22,8 +22,8 @@ fn enumWithMembers() {
|
|||
var buf: [20]u8 = undefined;
|
||||
|
||||
assert(%%a.print(buf) == 3);
|
||||
assert(str.eql(buf[0...3], "-42"));
|
||||
assert(mem.eql(buf[0...3], "-42"));
|
||||
|
||||
assert(%%b.print(buf) == 2);
|
||||
assert(str.eql(buf[0...2], "42"));
|
||||
assert(mem.eql(buf[0...2], "42"));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
const str = @import("std").str;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
pub fn foo() -> %i32 {
|
||||
const x = %return bar();
|
||||
|
@ -28,8 +28,8 @@ fn gimmeItBroke() -> []const u8 {
|
|||
|
||||
fn errorName() {
|
||||
@setFnTest(this);
|
||||
assert(str.eql(@errorName(error.AnError), "AnError"));
|
||||
assert(str.eql(@errorName(error.ALongerErrorName), "ALongerErrorName"));
|
||||
assert(mem.eql(@errorName(error.AnError), "AnError"));
|
||||
assert(mem.eql(@errorName(error.ALongerErrorName), "ALongerErrorName"));
|
||||
}
|
||||
error AnError;
|
||||
error ALongerErrorName;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
const str = @import("std").str;
|
||||
|
||||
fn compileTimeRecursion() {
|
||||
@setFnTest(this);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const str = std.str;
|
||||
const mem = std.mem;
|
||||
|
||||
fn continueInForLoop() {
|
||||
@setFnTest(this);
|
||||
|
@ -24,7 +24,7 @@ fn forLoopWithPointerElemVar() {
|
|||
var target: [source.len]u8 = undefined;
|
||||
@memcpy(&target[0], &source[0], source.len);
|
||||
mangleString(target);
|
||||
assert(str.eql(target, "bcdefgh"));
|
||||
assert(mem.eql(target, "bcdefgh"));
|
||||
}
|
||||
fn mangleString(s: []u8) {
|
||||
for (s) |*c| {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
const str = @import("std").str;
|
||||
const mem = @import("std").mem;
|
||||
const cstr = @import("std").cstr;
|
||||
|
||||
// normal comment
|
||||
|
@ -144,7 +144,7 @@ fn first4KeysOfHomeRow() -> []const u8 {
|
|||
fn ReturnStringFromFunction() {
|
||||
@setFnTest(this);
|
||||
|
||||
assert(str.eql(first4KeysOfHomeRow(), "aoeu"));
|
||||
assert(mem.eql(first4KeysOfHomeRow(), "aoeu"));
|
||||
}
|
||||
|
||||
const g1 : i32 = 1233 + 1;
|
||||
|
@ -210,31 +210,31 @@ fn emptyFn() {}
|
|||
fn hexEscape() {
|
||||
@setFnTest(this);
|
||||
|
||||
assert(str.eql("\x68\x65\x6c\x6c\x6f", "hello"));
|
||||
assert(mem.eql("\x68\x65\x6c\x6c\x6f", "hello"));
|
||||
}
|
||||
|
||||
fn stringConcatenation() {
|
||||
@setFnTest(this);
|
||||
|
||||
assert(str.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
|
||||
assert(mem.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
|
||||
}
|
||||
|
||||
fn arrayMultOperator() {
|
||||
@setFnTest(this);
|
||||
|
||||
assert(str.eql("ab" ** 5, "ababababab"));
|
||||
assert(mem.eql("ab" ** 5, "ababababab"));
|
||||
}
|
||||
|
||||
fn stringEscapes() {
|
||||
@setFnTest(this);
|
||||
|
||||
assert(str.eql("\"", "\x22"));
|
||||
assert(str.eql("\'", "\x27"));
|
||||
assert(str.eql("\n", "\x0a"));
|
||||
assert(str.eql("\r", "\x0d"));
|
||||
assert(str.eql("\t", "\x09"));
|
||||
assert(str.eql("\\", "\x5c"));
|
||||
assert(str.eql("\u1234\u0069", "\xe1\x88\xb4\x69"));
|
||||
assert(mem.eql("\"", "\x22"));
|
||||
assert(mem.eql("\'", "\x27"));
|
||||
assert(mem.eql("\n", "\x0a"));
|
||||
assert(mem.eql("\r", "\x0d"));
|
||||
assert(mem.eql("\t", "\x09"));
|
||||
assert(mem.eql("\\", "\x5c"));
|
||||
assert(mem.eql("\u1234\u0069", "\xe1\x88\xb4\x69"));
|
||||
}
|
||||
|
||||
fn multilineString() {
|
||||
|
@ -246,7 +246,7 @@ fn multilineString() {
|
|||
\\three
|
||||
;
|
||||
const s2 = "one\ntwo)\nthree";
|
||||
assert(str.eql(s1, s2));
|
||||
assert(mem.eql(s1, s2));
|
||||
}
|
||||
|
||||
fn multilineCString() {
|
||||
|
@ -295,7 +295,7 @@ const some_mem : [100]u8 = undefined;
|
|||
fn memAlloc(comptime T: type, n: usize) -> %[]T {
|
||||
return (&T)(&some_mem[0])[0...n];
|
||||
}
|
||||
fn memFree(comptime T: type, mem: []T) { }
|
||||
fn memFree(comptime T: type, memory: []T) { }
|
||||
|
||||
|
||||
fn castUndefined() {
|
||||
|
@ -344,8 +344,8 @@ fn pointerDereferencing() {
|
|||
fn callResultOfIfElseExpression() {
|
||||
@setFnTest(this);
|
||||
|
||||
assert(str.eql(f2(true), "a"));
|
||||
assert(str.eql(f2(false), "b"));
|
||||
assert(mem.eql(f2(true), "a"));
|
||||
assert(mem.eql(f2(false), "b"));
|
||||
}
|
||||
fn f2(x: bool) -> []u8 {
|
||||
return (if (x) fA else fB)();
|
||||
|
@ -562,8 +562,8 @@ fn typeName() {
|
|||
@setFnTest(this);
|
||||
|
||||
comptime {
|
||||
assert(str.eql(@typeName(i64), "i64"));
|
||||
assert(str.eql(@typeName(&usize), "&usize"));
|
||||
assert(mem.eql(@typeName(i64), "i64"));
|
||||
assert(mem.eql(@typeName(&usize), "&usize"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
const assert = @import("std").debug.assert;
|
||||
|
||||
const Foo = struct {
|
||||
a: void,
|
||||
b: i32,
|
||||
c: void,
|
||||
};
|
||||
|
||||
fn compareVoidWithVoidCompileTimeKnown() {
|
||||
@setFnTest(this);
|
||||
|
||||
comptime {
|
||||
const foo = Foo {
|
||||
.a = {},
|
||||
.b = 1,
|
||||
.c = {},
|
||||
};
|
||||
assert(foo.a == {});
|
||||
}
|
||||
}
|
|
@ -471,21 +471,17 @@ const io = @import("std").io;
|
|||
pub fn main(args: [][]u8) -> %void {
|
||||
const array = []u8 {9, 8, 7, 6};
|
||||
for (array) |item| {
|
||||
%%io.stdout.printInt(@typeOf(item), item);
|
||||
%%io.stdout.printf("\n");
|
||||
%%io.stdout.printf("{}\n", item);
|
||||
}
|
||||
for (array) |item, index| {
|
||||
%%io.stdout.printInt(@typeOf(index), index);
|
||||
%%io.stdout.printf("\n");
|
||||
%%io.stdout.printf("{}\n", index);
|
||||
}
|
||||
const unknown_size: []u8 = array;
|
||||
for (unknown_size) |item| {
|
||||
%%io.stdout.printInt(@typeOf(item), item);
|
||||
%%io.stdout.printf("\n");
|
||||
%%io.stdout.printf("{}\n", item);
|
||||
}
|
||||
for (unknown_size) |item, index| {
|
||||
%%io.stdout.printInt(@typeOf(index), index);
|
||||
%%io.stdout.printf("\n");
|
||||
%%io.stdout.printf("{}\n", index);
|
||||
}
|
||||
}
|
||||
)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 }
|
|||
".tmp_source.zig:3:8: note: called from here");
|
||||
|
||||
|
||||
add_compile_fail_case("unnecessary if statement", R"SOURCE(
|
||||
fn f() {
|
||||
if (true) { }
|
||||
}
|
||||
)SOURCE", 1, ".tmp_source.zig:3:9: error: condition is always true; unnecessary if statement");
|
||||
|
||||
|
||||
add_compile_fail_case("addition with non numbers", R"SOURCE(
|
||||
const Foo = struct {
|
||||
field: i32,
|
||||
|
@ -1588,25 +1577,6 @@ fn derp() {
|
|||
}
|
||||
)SOURCE", 1, ".tmp_source.zig:7:13: error: cannot assign to constant");
|
||||
|
||||
add_compile_fail_case("compare void with void is compile time known", R"SOURCE(
|
||||
const Foo = struct {
|
||||
a: void,
|
||||
b: i32,
|
||||
c: void,
|
||||
};
|
||||
|
||||
fn f() {
|
||||
const foo = Foo {
|
||||
.a = {},
|
||||
.b = 1,
|
||||
.c = {},
|
||||
};
|
||||
if (foo.a != {}) {
|
||||
@unreachable();
|
||||
}
|
||||
}
|
||||
)SOURCE", 1, ".tmp_source.zig:14:15: error: condition is always false; unnecessary if statement");
|
||||
|
||||
add_compile_fail_case("return from defer expression", R"SOURCE(
|
||||
pub fn testTrickyDefer() -> %void {
|
||||
defer canFail() %% {};
|
||||
|
|
|
@ -32,4 +32,5 @@ const test_try = @import("cases/try.zig");
|
|||
const test_typedef = @import("cases/typedef.zig");
|
||||
const test_undefined = @import("cases/undefined.zig");
|
||||
const test_var_args = @import("cases/var_args.zig");
|
||||
const test_void = @import("cases/void.zig");
|
||||
const test_while = @import("cases/while.zig");
|
||||
|
|
Loading…
Reference in New Issue