[breaking] delete ptr deref prefix op

start using zig-fmt-pointer-reform branch build of zig fmt
to fix code to use the new syntax

all of test/cases/* are processed, but there are more left
to be done - all the std lib used by the behavior tests
This commit is contained in:
Andrew Kelley 2018-04-30 20:35:54 -04:00
parent 76ab1d2b6c
commit a35b366eb6
49 changed files with 1694 additions and 880 deletions

View File

@ -614,7 +614,6 @@ enum PrefixOp {
PrefixOpBinNot,
PrefixOpNegation,
PrefixOpNegationWrap,
PrefixOpDereference,
PrefixOpMaybe,
PrefixOpUnwrapMaybe,
};

View File

@ -66,7 +66,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
case PrefixOpNegationWrap: return "-%";
case PrefixOpBoolNot: return "!";
case PrefixOpBinNot: return "~";
case PrefixOpDereference: return "*";
case PrefixOpMaybe: return "?";
case PrefixOpUnwrapMaybe: return "??";
}

View File

@ -4696,8 +4696,6 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval);
case PrefixOpNegationWrap:
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval);
case PrefixOpDereference:
return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
case PrefixOpMaybe:
return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval);
case PrefixOpUnwrapMaybe:

View File

@ -1165,10 +1165,8 @@ static PrefixOp tok_to_prefix_op(Token *token) {
case TokenIdDash: return PrefixOpNegation;
case TokenIdMinusPercent: return PrefixOpNegationWrap;
case TokenIdTilde: return PrefixOpBinNot;
case TokenIdStar: return PrefixOpDereference;
case TokenIdMaybe: return PrefixOpMaybe;
case TokenIdDoubleQuestion: return PrefixOpUnwrapMaybe;
case TokenIdStarStar: return PrefixOpDereference;
default: return PrefixOpInvalid;
}
}
@ -1214,7 +1212,7 @@ static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) {
/*
PrefixOpExpression = PrefixOp ErrorSetExpr | SuffixOpExpression
PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
PrefixOp = "!" | "-" | "~" | ("*" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
*/
static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@ -1237,15 +1235,6 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index,
AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
AstNode *parent_node = node;
if (token->id == TokenIdStarStar) {
// pretend that we got 2 star tokens
parent_node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
parent_node->data.prefix_op_expr.primary_expr = node;
parent_node->data.prefix_op_expr.prefix_op = PrefixOpDereference;
node->column += 1;
}
AstNode *prefix_op_expr = ast_parse_error_set_expr(pc, token_index, true);
node->data.prefix_op_expr.primary_expr = prefix_op_expr;

View File

@ -247,6 +247,12 @@ static AstNode *trans_create_node_field_access_str(Context *c, AstNode *containe
return trans_create_node_field_access(c, container, buf_create_from_str(field_name));
}
static AstNode *trans_create_node_ptr_deref(Context *c, AstNode *child_node) {
AstNode *node = trans_create_node(c, NodeTypePtrDeref);
node->data.ptr_deref_expr.target = child_node;
return node;
}
static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) {
AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
node->data.prefix_op_expr.prefix_op = op;
@ -1412,8 +1418,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
AstNode *operation_type_cast = trans_c_cast(c, rhs_location,
stmt->getComputationLHSType(),
stmt->getLHS()->getType(),
trans_create_node_prefix_op(c, PrefixOpDereference,
trans_create_node_symbol(c, tmp_var_name)));
trans_create_node_ptr_deref(c, trans_create_node_symbol(c, tmp_var_name)));
// result_type(... >> u5(rhs))
AstNode *result_type_cast = trans_c_cast(c, rhs_location,
@ -1426,7 +1431,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
// *_ref = ...
AstNode *assign_statement = trans_create_node_bin_op(c,
trans_create_node_prefix_op(c, PrefixOpDereference,
trans_create_node_ptr_deref(c,
trans_create_node_symbol(c, tmp_var_name)),
BinOpTypeAssign, result_type_cast);
@ -1436,7 +1441,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
// break :x *_ref
child_scope->node->data.block.statements.append(
trans_create_node_break(c, label_name,
trans_create_node_prefix_op(c, PrefixOpDereference,
trans_create_node_ptr_deref(c,
trans_create_node_symbol(c, tmp_var_name))));
}
@ -1483,11 +1488,11 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
if (rhs == nullptr) return nullptr;
AstNode *assign_statement = trans_create_node_bin_op(c,
trans_create_node_prefix_op(c, PrefixOpDereference,
trans_create_node_ptr_deref(c,
trans_create_node_symbol(c, tmp_var_name)),
BinOpTypeAssign,
trans_create_node_bin_op(c,
trans_create_node_prefix_op(c, PrefixOpDereference,
trans_create_node_ptr_deref(c,
trans_create_node_symbol(c, tmp_var_name)),
bin_op,
rhs));
@ -1496,7 +1501,7 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
// break :x *_ref
child_scope->node->data.block.statements.append(
trans_create_node_break(c, label_name,
trans_create_node_prefix_op(c, PrefixOpDereference,
trans_create_node_ptr_deref(c,
trans_create_node_symbol(c, tmp_var_name))));
return child_scope->node;
@ -1817,13 +1822,13 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
// const _tmp = *_ref;
Buf* tmp_var_name = buf_create_from_str("_tmp");
AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr,
trans_create_node_prefix_op(c, PrefixOpDereference,
trans_create_node_ptr_deref(c,
trans_create_node_symbol(c, ref_var_name)));
child_scope->node->data.block.statements.append(tmp_var_decl);
// *_ref += 1;
AstNode *assign_statement = trans_create_node_bin_op(c,
trans_create_node_prefix_op(c, PrefixOpDereference,
trans_create_node_ptr_deref(c,
trans_create_node_symbol(c, ref_var_name)),
assign_op,
trans_create_node_unsigned(c, 1));
@ -1871,14 +1876,14 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
// *_ref += 1;
AstNode *assign_statement = trans_create_node_bin_op(c,
trans_create_node_prefix_op(c, PrefixOpDereference,
trans_create_node_ptr_deref(c,
trans_create_node_symbol(c, ref_var_name)),
assign_op,
trans_create_node_unsigned(c, 1));
child_scope->node->data.block.statements.append(assign_statement);
// break :x *_ref
AstNode *deref_expr = trans_create_node_prefix_op(c, PrefixOpDereference,
AstNode *deref_expr = trans_create_node_ptr_deref(c,
trans_create_node_symbol(c, ref_var_name));
child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, deref_expr));
@ -1923,7 +1928,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
if (is_fn_ptr)
return value_node;
AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node);
return trans_create_node_prefix_op(c, PrefixOpDereference, unwrapped);
return trans_create_node_ptr_deref(c, unwrapped);
}
case UO_Plus:
emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus");
@ -4469,27 +4474,45 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
}
}
static PrefixOp ctok_to_prefix_op(CTok *token) {
switch (token->id) {
case CTokIdBang: return PrefixOpBoolNot;
case CTokIdMinus: return PrefixOpNegation;
case CTokIdTilde: return PrefixOpBinNot;
case CTokIdAsterisk: return PrefixOpDereference;
default: return PrefixOpInvalid;
}
}
static AstNode *parse_ctok_prefix_op_expr(Context *c, CTokenize *ctok, size_t *tok_i) {
CTok *op_tok = &ctok->tokens.at(*tok_i);
PrefixOp prefix_op = ctok_to_prefix_op(op_tok);
if (prefix_op == PrefixOpInvalid) {
return parse_ctok_suffix_op_expr(c, ctok, tok_i);
}
*tok_i += 1;
AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
if (prefix_op_expr == nullptr)
return nullptr;
return trans_create_node_prefix_op(c, prefix_op, prefix_op_expr);
switch (op_tok->id) {
case CTokIdBang:
{
*tok_i += 1;
AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
if (prefix_op_expr == nullptr)
return nullptr;
return trans_create_node_prefix_op(c, PrefixOpBoolNot, prefix_op_expr);
}
case CTokIdMinus:
{
*tok_i += 1;
AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
if (prefix_op_expr == nullptr)
return nullptr;
return trans_create_node_prefix_op(c, PrefixOpNegation, prefix_op_expr);
}
case CTokIdTilde:
{
*tok_i += 1;
AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
if (prefix_op_expr == nullptr)
return nullptr;
return trans_create_node_prefix_op(c, PrefixOpBinNot, prefix_op_expr);
}
case CTokIdAsterisk:
{
*tok_i += 1;
AstNode *prefix_op_expr = parse_ctok_prefix_op_expr(c, ctok, tok_i);
if (prefix_op_expr == nullptr)
return nullptr;
return trans_create_node_ptr_deref(c, prefix_op_expr);
}
default:
return parse_ctok_suffix_op_expr(c, ctok, tok_i);
}
}
static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) {

View File

@ -104,9 +104,7 @@ pub fn panic(comptime format: []const u8, args: ...) noreturn {
var panicking: u8 = 0; // TODO make this a bool
pub fn panicExtra(trace: ?&const builtin.StackTrace, first_trace_addr: ?usize,
comptime format: []const u8, args: ...) noreturn
{
pub fn panicExtra(trace: ?&const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: ...) noreturn {
@setCold(true);
if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) {
@ -132,9 +130,7 @@ const WHITE = "\x1b[37;1m";
const DIM = "\x1b[2m";
const RESET = "\x1b[0m";
pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, allocator: &mem.Allocator,
debug_info: &ElfStackTrace, tty_color: bool) !void
{
pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var, allocator: &mem.Allocator, debug_info: &ElfStackTrace, tty_color: bool) !void {
var frame_index: usize = undefined;
var frames_left: usize = undefined;
if (stack_trace.index < stack_trace.instruction_addresses.len) {
@ -154,9 +150,7 @@ pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: var,
}
}
pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator,
debug_info: &ElfStackTrace, tty_color: bool, start_addr: ?usize) !void
{
pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator, debug_info: &ElfStackTrace, tty_color: bool, start_addr: ?usize) !void {
const AddressState = union(enum) {
NotLookingForStartAddress,
LookingForStartAddress: usize,
@ -166,14 +160,14 @@ pub fn writeCurrentStackTrace(out_stream: var, allocator: &mem.Allocator,
// else AddressState.NotLookingForStartAddress;
var addr_state: AddressState = undefined;
if (start_addr) |addr| {
addr_state = AddressState { .LookingForStartAddress = addr };
addr_state = AddressState{ .LookingForStartAddress = addr };
} else {
addr_state = AddressState.NotLookingForStartAddress;
}
var fp = @ptrToInt(@frameAddress());
while (fp != 0) : (fp = *@intToPtr(&const usize, fp)) {
const return_address = *@intToPtr(&const usize, fp + @sizeOf(usize));
while (fp != 0) : (fp = @intToPtr(&const usize, fp).*) {
const return_address = @intToPtr(&const usize, fp + @sizeOf(usize)).*;
switch (addr_state) {
AddressState.NotLookingForStartAddress => {},
@ -200,32 +194,32 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us
// in practice because the compiler dumps everything in a single
// object file. Future improvement: use external dSYM data when
// available.
const unknown = macho.Symbol { .name = "???", .address = address };
const unknown = macho.Symbol{
.name = "???",
.address = address,
};
const symbol = debug_info.symbol_table.search(address) ?? &unknown;
try out_stream.print(WHITE ++ "{}" ++ RESET ++ ": " ++
DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n",
symbol.name, address);
try out_stream.print(WHITE ++ "{}" ++ RESET ++ ": " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n", symbol.name, address);
},
else => {
const compile_unit = findCompileUnit(debug_info, address) catch {
try out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n",
address);
try out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", address);
return;
};
const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);
if (getLineNumberInfo(debug_info, compile_unit, address - 1)) |line_info| {
defer line_info.deinit();
try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++
DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n",
line_info.file_name, line_info.line, line_info.column,
address, compile_unit_name);
try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", line_info.file_name, line_info.line, line_info.column, address, compile_unit_name);
if (printLineFromFile(debug_info.allocator(), out_stream, line_info)) {
if (line_info.column == 0) {
try out_stream.write("\n");
} else {
{var col_i: usize = 1; while (col_i < line_info.column) : (col_i += 1) {
try out_stream.writeByte(' ');
}}
{
var col_i: usize = 1;
while (col_i < line_info.column) : (col_i += 1) {
try out_stream.writeByte(' ');
}
}
try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n");
}
} else |err| switch (err) {
@ -233,7 +227,8 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us
else => return err,
}
} else |err| switch (err) {
error.MissingDebugInfo, error.InvalidDebugInfo => {
error.MissingDebugInfo,
error.InvalidDebugInfo => {
try out_stream.print(ptr_hex ++ " in ??? ({})\n", address, compile_unit_name);
},
else => return err,
@ -247,7 +242,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) !&ElfStackTrace {
builtin.ObjectFormat.elf => {
const st = try allocator.create(ElfStackTrace);
errdefer allocator.destroy(st);
*st = ElfStackTrace {
st.* = ElfStackTrace{
.self_exe_file = undefined,
.elf = undefined,
.debug_info = undefined,
@ -279,9 +274,7 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) !&ElfStackTrace {
const st = try allocator.create(ElfStackTrace);
errdefer allocator.destroy(st);
*st = ElfStackTrace {
.symbol_table = try macho.loadSymbols(allocator, &io.FileInStream.init(&exe_file)),
};
st.* = ElfStackTrace{ .symbol_table = try macho.loadSymbols(allocator, &io.FileInStream.init(&exe_file)) };
return st;
},
@ -325,8 +318,7 @@ fn printLineFromFile(allocator: &mem.Allocator, out_stream: var, line_info: &con
}
}
if (amt_read < buf.len)
return error.EndOfFile;
if (amt_read < buf.len) return error.EndOfFile;
}
}
@ -418,10 +410,8 @@ const Constant = struct {
signed: bool,
fn asUnsignedLe(self: &const Constant) !u64 {
if (self.payload.len > @sizeOf(u64))
return error.InvalidDebugInfo;
if (self.signed)
return error.InvalidDebugInfo;
if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
if (self.signed) return error.InvalidDebugInfo;
return mem.readInt(self.payload, u64, builtin.Endian.Little);
}
};
@ -438,15 +428,14 @@ const Die = struct {
fn getAttr(self: &const Die, id: u64) ?&const FormValue {
for (self.attrs.toSliceConst()) |*attr| {
if (attr.id == id)
return &attr.value;
if (attr.id == id) return &attr.value;
}
return null;
}
fn getAttrAddr(self: &const Die, id: u64) !u64 {
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
return switch (*form_value) {
return switch (form_value.*) {
FormValue.Address => |value| value,
else => error.InvalidDebugInfo,
};
@ -454,7 +443,7 @@ const Die = struct {
fn getAttrSecOffset(self: &const Die, id: u64) !u64 {
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
return switch (*form_value) {
return switch (form_value.*) {
FormValue.Const => |value| value.asUnsignedLe(),
FormValue.SecOffset => |value| value,
else => error.InvalidDebugInfo,
@ -463,7 +452,7 @@ const Die = struct {
fn getAttrUnsignedLe(self: &const Die, id: u64) !u64 {
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
return switch (*form_value) {
return switch (form_value.*) {
FormValue.Const => |value| value.asUnsignedLe(),
else => error.InvalidDebugInfo,
};
@ -471,7 +460,7 @@ const Die = struct {
fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) ![]u8 {
const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
return switch (*form_value) {
return switch (form_value.*) {
FormValue.String => |value| value,
FormValue.StrPtr => |offset| getString(st, offset),
else => error.InvalidDebugInfo,
@ -518,10 +507,8 @@ const LineNumberProgram = struct {
prev_basic_block: bool,
prev_end_sequence: bool,
pub fn init(is_stmt: bool, include_dirs: []const []const u8,
file_entries: &ArrayList(FileEntry), target_address: usize) LineNumberProgram
{
return LineNumberProgram {
pub fn init(is_stmt: bool, include_dirs: []const []const u8, file_entries: &ArrayList(FileEntry), target_address: usize) LineNumberProgram {
return LineNumberProgram{
.address = 0,
.file = 1,
.line = 1,
@ -548,14 +535,16 @@ const LineNumberProgram = struct {
return error.MissingDebugInfo;
} else if (self.prev_file - 1 >= self.file_entries.len) {
return error.InvalidDebugInfo;
} else &self.file_entries.items[self.prev_file - 1];
} else
&self.file_entries.items[self.prev_file - 1];
const dir_name = if (file_entry.dir_index >= self.include_dirs.len) {
return error.InvalidDebugInfo;
} else self.include_dirs[file_entry.dir_index];
} else
self.include_dirs[file_entry.dir_index];
const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name);
errdefer self.file_entries.allocator.free(file_name);
return LineInfo {
return LineInfo{
.line = if (self.prev_line >= 0) usize(self.prev_line) else 0,
.column = self.prev_column,
.file_name = file_name,
@ -578,8 +567,7 @@ fn readStringRaw(allocator: &mem.Allocator, in_stream: var) ![]u8 {
var buf = ArrayList(u8).init(allocator);
while (true) {
const byte = try in_stream.readByte();
if (byte == 0)
break;
if (byte == 0) break;
try buf.append(byte);
}
return buf.toSlice();
@ -600,7 +588,7 @@ fn readAllocBytes(allocator: &mem.Allocator, in_stream: var, size: usize) ![]u8
fn parseFormValueBlockLen(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue {
const buf = try readAllocBytes(allocator, in_stream, size);
return FormValue { .Block = buf };
return FormValue{ .Block = buf };
}
fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue {
@ -609,26 +597,23 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) !
}
fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue {
return FormValue { .Const = Constant {
return FormValue{ .Const = Constant{
.signed = signed,
.payload = try readAllocBytes(allocator, in_stream, size),
}};
} };
}
fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
return if (is_64) try in_stream.readIntLe(u64)
else u64(try in_stream.readIntLe(u32)) ;
return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32));
}
fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32))
else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64)
else unreachable;
return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable;
}
fn parseFormValueRefLen(allocator: &mem.Allocator, in_stream: var, size: usize) !FormValue {
const buf = try readAllocBytes(allocator, in_stream, size);
return FormValue { .Ref = buf };
return FormValue{ .Ref = buf };
}
fn parseFormValueRef(allocator: &mem.Allocator, in_stream: var, comptime T: type) !FormValue {
@ -646,11 +631,9 @@ const ParseFormValueError = error {
OutOfMemory,
};
fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64: bool)
ParseFormValueError!FormValue
{
fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue {
return switch (form_id) {
DW.FORM_addr => FormValue { .Address = try parseFormValueTargetAddrSize(in_stream) },
DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },
DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
@ -662,7 +645,8 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64
DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2),
DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4),
DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8),
DW.FORM_udata, DW.FORM_sdata => {
DW.FORM_udata,
DW.FORM_sdata => {
const block_len = try readULeb128(in_stream);
const signed = form_id == DW.FORM_sdata;
return parseFormValueConstant(allocator, in_stream, signed, block_len);
@ -670,11 +654,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64
DW.FORM_exprloc => {
const size = try readULeb128(in_stream);
const buf = try readAllocBytes(allocator, in_stream, size);
return FormValue { .ExprLoc = buf };
return FormValue{ .ExprLoc = buf };
},
DW.FORM_flag => FormValue { .Flag = (try in_stream.readByte()) != 0 },
DW.FORM_flag_present => FormValue { .Flag = true },
DW.FORM_sec_offset => FormValue { .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_flag => FormValue{ .Flag = (try in_stream.readByte()) != 0 },
DW.FORM_flag_present => FormValue{ .Flag = true },
DW.FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8),
DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16),
@ -685,11 +669,11 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64
return parseFormValueRefLen(allocator, in_stream, ref_len);
},
DW.FORM_ref_addr => FormValue { .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_ref_sig8 => FormValue { .RefSig8 = try in_stream.readIntLe(u64) },
DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) },
DW.FORM_string => FormValue { .String = try readStringRaw(allocator, in_stream) },
DW.FORM_strp => FormValue { .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
DW.FORM_indirect => {
const child_form_id = try readULeb128(in_stream);
return parseFormValue(allocator, in_stream, child_form_id, is_64);
@ -705,9 +689,8 @@ fn parseAbbrevTable(st: &ElfStackTrace) !AbbrevTable {
var result = AbbrevTable.init(st.allocator());
while (true) {
const abbrev_code = try readULeb128(in_stream);
if (abbrev_code == 0)
return result;
try result.append(AbbrevTableEntry {
if (abbrev_code == 0) return result;
try result.append(AbbrevTableEntry{
.abbrev_code = abbrev_code,
.tag_id = try readULeb128(in_stream),
.has_children = (try in_stream.readByte()) == DW.CHILDREN_yes,
@ -718,9 +701,8 @@ fn parseAbbrevTable(st: &ElfStackTrace) !AbbrevTable {
while (true) {
const attr_id = try readULeb128(in_stream);
const form_id = try readULeb128(in_stream);
if (attr_id == 0 and form_id == 0)
break;
try attrs.append(AbbrevAttr {
if (attr_id == 0 and form_id == 0) break;
try attrs.append(AbbrevAttr{
.attr_id = attr_id,
.form_id = form_id,
});
@ -737,7 +719,7 @@ fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) !&const AbbrevTable {
}
}
try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset);
try st.abbrev_table_list.append(AbbrevTableHeader {
try st.abbrev_table_list.append(AbbrevTableHeader{
.offset = abbrev_offset,
.table = try parseAbbrevTable(st),
});
@ -746,8 +728,7 @@ fn getAbbrevTable(st: &ElfStackTrace, abbrev_offset: u64) !&const AbbrevTable {
fn getAbbrevTableEntry(abbrev_table: &const AbbrevTable, abbrev_code: u64) ?&const AbbrevTableEntry {
for (abbrev_table.toSliceConst()) |*table_entry| {
if (table_entry.abbrev_code == abbrev_code)
return table_entry;
if (table_entry.abbrev_code == abbrev_code) return table_entry;
}
return null;
}
@ -759,14 +740,14 @@ fn parseDie(st: &ElfStackTrace, abbrev_table: &const AbbrevTable, is_64: bool) !
const abbrev_code = try readULeb128(in_stream);
const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) ?? return error.InvalidDebugInfo;
var result = Die {
var result = Die{
.tag_id = table_entry.tag_id,
.has_children = table_entry.has_children,
.attrs = ArrayList(Die.Attr).init(st.allocator()),
};
try result.attrs.resize(table_entry.attrs.len);
for (table_entry.attrs.toSliceConst()) |attr, i| {
result.attrs.items[i] = Die.Attr {
result.attrs.items[i] = Die.Attr{
.id = attr.attr_id,
.value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64),
};
@ -790,8 +771,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
var is_64: bool = undefined;
const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);
if (unit_length == 0)
return error.MissingDebugInfo;
if (unit_length == 0) return error.MissingDebugInfo;
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
if (compile_unit.index != this_index) {
@ -803,8 +783,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
// TODO support 3 and 5
if (version != 2 and version != 4) return error.InvalidDebugInfo;
const prologue_length = if (is_64) try in_stream.readInt(st.elf.endian, u64)
else try in_stream.readInt(st.elf.endian, u32);
const prologue_length = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32);
const prog_start_offset = (try in_file.getPos()) + prologue_length;
const minimum_instruction_length = try in_stream.readByte();
@ -819,38 +798,37 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
const line_base = try in_stream.readByteSigned();
const line_range = try in_stream.readByte();
if (line_range == 0)
return error.InvalidDebugInfo;
if (line_range == 0) return error.InvalidDebugInfo;
const opcode_base = try in_stream.readByte();
const standard_opcode_lengths = try st.allocator().alloc(u8, opcode_base - 1);
{var i: usize = 0; while (i < opcode_base - 1) : (i += 1) {
standard_opcode_lengths[i] = try in_stream.readByte();
}}
{
var i: usize = 0;
while (i < opcode_base - 1) : (i += 1) {
standard_opcode_lengths[i] = try in_stream.readByte();
}
}
var include_directories = ArrayList([]u8).init(st.allocator());
try include_directories.append(compile_unit_cwd);
while (true) {
const dir = try st.readString();
if (dir.len == 0)
break;
if (dir.len == 0) break;
try include_directories.append(dir);
}
var file_entries = ArrayList(FileEntry).init(st.allocator());
var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(),
&file_entries, target_address);
var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address);
while (true) {
const file_name = try st.readString();
if (file_name.len == 0)
break;
if (file_name.len == 0) break;
const dir_index = try readULeb128(in_stream);
const mtime = try readULeb128(in_stream);
const len_bytes = try readULeb128(in_stream);
try file_entries.append(FileEntry {
try file_entries.append(FileEntry{
.file_name = file_name,
.dir_index = dir_index,
.mtime = mtime,
@ -866,8 +844,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
var sub_op: u8 = undefined; // TODO move this to the correct scope and fix the compiler crash
if (opcode == DW.LNS_extended_op) {
const op_size = try readULeb128(in_stream);
if (op_size < 1)
return error.InvalidDebugInfo;
if (op_size < 1) return error.InvalidDebugInfo;
sub_op = try in_stream.readByte();
switch (sub_op) {
DW.LNE_end_sequence => {
@ -884,7 +861,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
const dir_index = try readULeb128(in_stream);
const mtime = try readULeb128(in_stream);
const len_bytes = try readULeb128(in_stream);
try file_entries.append(FileEntry {
try file_entries.append(FileEntry{
.file_name = file_name,
.dir_index = dir_index,
.mtime = mtime,
@ -941,11 +918,9 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
const arg = try in_stream.readInt(st.elf.endian, u16);
prog.address += arg;
},
DW.LNS_set_prologue_end => {
},
DW.LNS_set_prologue_end => {},
else => {
if (opcode - 1 >= standard_opcode_lengths.len)
return error.InvalidDebugInfo;
if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
const len_bytes = standard_opcode_lengths[opcode - 1];
try in_file.seekForward(len_bytes);
},
@ -972,16 +947,13 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void {
var is_64: bool = undefined;
const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);
if (unit_length == 0)
return;
if (unit_length == 0) return;
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
const version = try in_stream.readInt(st.elf.endian, u16);
if (version < 2 or version > 5) return error.InvalidDebugInfo;
const debug_abbrev_offset =
if (is_64) try in_stream.readInt(st.elf.endian, u64)
else try in_stream.readInt(st.elf.endian, u32);
const debug_abbrev_offset = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32);
const address_size = try in_stream.readByte();
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
@ -992,15 +964,14 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void {
try st.self_exe_file.seekTo(compile_unit_pos);
const compile_unit_die = try st.allocator().create(Die);
*compile_unit_die = try parseDie(st, abbrev_table, is_64);
compile_unit_die.* = try parseDie(st, abbrev_table, is_64);
if (compile_unit_die.tag_id != DW.TAG_compile_unit)
return error.InvalidDebugInfo;
if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
const pc_range = x: {
if (compile_unit_die.getAttrAddr(DW.AT_low_pc)) |low_pc| {
if (compile_unit_die.getAttr(DW.AT_high_pc)) |high_pc_value| {
const pc_end = switch (*high_pc_value) {
const pc_end = switch (high_pc_value.*) {
FormValue.Address => |value| value,
FormValue.Const => |value| b: {
const offset = try value.asUnsignedLe();
@ -1008,7 +979,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void {
},
else => return error.InvalidDebugInfo,
};
break :x PcRange {
break :x PcRange{
.start = low_pc,
.end = pc_end,
};
@ -1016,13 +987,12 @@ fn scanAllCompileUnits(st: &ElfStackTrace) !void {
break :x null;
}
} else |err| {
if (err != error.MissingDebugInfo)
return err;
if (err != error.MissingDebugInfo) return err;
break :x null;
}
};
try st.compile_unit_list.append(CompileUnit {
try st.compile_unit_list.append(CompileUnit{
.version = version,
.is_64 = is_64,
.pc_range = pc_range,
@ -1040,8 +1010,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit
const in_stream = &in_file_stream.stream;
for (st.compile_unit_list.toSlice()) |*compile_unit| {
if (compile_unit.pc_range) |range| {
if (target_address >= range.start and target_address < range.end)
return compile_unit;
if (target_address >= range.start and target_address < range.end) return compile_unit;
}
if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
var base_address: usize = 0;
@ -1063,8 +1032,7 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit
}
}
} else |err| {
if (err != error.MissingDebugInfo)
return err;
if (err != error.MissingDebugInfo) return err;
continue;
}
}
@ -1073,8 +1041,8 @@ fn findCompileUnit(st: &ElfStackTrace, target_address: u64) !&const CompileUnit
fn readInitialLength(comptime E: type, in_stream: &io.InStream(E), is_64: &bool) !u64 {
const first_32_bits = try in_stream.readIntLe(u32);
*is_64 = (first_32_bits == 0xffffffff);
if (*is_64) {
is_64.* = (first_32_bits == 0xffffffff);
if (is_64.*) {
return in_stream.readIntLe(u64);
} else {
if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
@ -1091,13 +1059,11 @@ fn readULeb128(in_stream: var) !u64 {
var operand: u64 = undefined;
if (@shlWithOverflow(u64, byte & 0b01111111, u6(shift), &operand))
return error.InvalidDebugInfo;
if (@shlWithOverflow(u64, byte & 0b01111111, u6(shift), &operand)) return error.InvalidDebugInfo;
result |= operand;
if ((byte & 0b10000000) == 0)
return result;
if ((byte & 0b10000000) == 0) return result;
shift += 7;
}
@ -1112,15 +1078,13 @@ fn readILeb128(in_stream: var) !i64 {
var operand: i64 = undefined;
if (@shlWithOverflow(i64, byte & 0b01111111, u6(shift), &operand))
return error.InvalidDebugInfo;
if (@shlWithOverflow(i64, byte & 0b01111111, u6(shift), &operand)) return error.InvalidDebugInfo;
result |= operand;
shift += 7;
if ((byte & 0b10000000) == 0) {
if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0)
result |= -(i64(1) << u6(shift));
if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) result |= -(i64(1) << u6(shift));
return result;
}
}
@ -1131,7 +1095,6 @@ pub const global_allocator = &global_fixed_allocator.allocator;
var global_fixed_allocator = std.heap.FixedBufferAllocator.init(global_allocator_mem[0..]);
var global_allocator_mem: [100 * 1024]u8 = undefined;
// TODO make thread safe
var debug_info_allocator: ?&mem.Allocator = null;
var debug_info_direct_allocator: std.heap.DirectAllocator = undefined;

View File

@ -47,12 +47,12 @@ pub fn forceEval(value: var) void {
f32 => {
var x: f32 = undefined;
const p = @ptrCast(&volatile f32, &x);
*p = x;
p.* = x;
},
f64 => {
var x: f64 = undefined;
const p = @ptrCast(&volatile f64, &x);
*p = x;
p.* = x;
},
else => {
@compileError("forceEval not implemented for " ++ @typeName(T));
@ -179,7 +179,6 @@ test "math" {
_ = @import("complex/index.zig");
}
pub fn min(x: var, y: var) @typeOf(x + y) {
return if (x < y) x else y;
}
@ -280,10 +279,10 @@ pub fn rotr(comptime T: type, x: T, r: var) T {
}
test "math.rotr" {
assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001);
assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000);
assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001);
assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000);
assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001);
assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000);
assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001);
assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000);
assert(rotr(u8, 0b00000001, isize(-1)) == 0b00000010);
}
@ -299,14 +298,13 @@ pub fn rotl(comptime T: type, x: T, r: var) T {
}
test "math.rotl" {
assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001);
assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010);
assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001);
assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000);
assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001);
assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010);
assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001);
assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000);
assert(rotl(u8, 0b00000001, isize(-1)) == 0b10000000);
}
pub fn Log2Int(comptime T: type) type {
return @IntType(false, log2(T.bit_count));
}
@ -323,14 +321,14 @@ fn testOverflow() void {
assert((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);
}
pub fn absInt(x: var) !@typeOf(x) {
const T = @typeOf(x);
comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt
comptime assert(T.is_signed); // must pass a signed integer to absInt
if (x == @minValue(@typeOf(x)))
if (x == @minValue(@typeOf(x))) {
return error.Overflow;
{
} else {
@setRuntimeSafety(false);
return if (x < 0) -x else x;
}
@ -349,10 +347,8 @@ pub const absFloat = @import("fabs.zig").fabs;
pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
@setRuntimeSafety(false);
if (denominator == 0)
return error.DivisionByZero;
if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)
return error.Overflow;
if (denominator == 0) return error.DivisionByZero;
if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow;
return @divTrunc(numerator, denominator);
}
@ -372,10 +368,8 @@ fn testDivTrunc() void {
pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
@setRuntimeSafety(false);
if (denominator == 0)
return error.DivisionByZero;
if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)
return error.Overflow;
if (denominator == 0) return error.DivisionByZero;
if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow;
return @divFloor(numerator, denominator);
}
@ -395,13 +389,10 @@ fn testDivFloor() void {
pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
@setRuntimeSafety(false);
if (denominator == 0)
return error.DivisionByZero;
if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1)
return error.Overflow;
if (denominator == 0) return error.DivisionByZero;
if (@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == @minValue(T) and denominator == -1) return error.Overflow;
const result = @divTrunc(numerator, denominator);
if (result * denominator != numerator)
return error.UnexpectedRemainder;
if (result * denominator != numerator) return error.UnexpectedRemainder;
return result;
}
@ -423,10 +414,8 @@ fn testDivExact() void {
pub fn mod(comptime T: type, numerator: T, denominator: T) !T {
@setRuntimeSafety(false);
if (denominator == 0)
return error.DivisionByZero;
if (denominator < 0)
return error.NegativeDenominator;
if (denominator == 0) return error.DivisionByZero;
if (denominator < 0) return error.NegativeDenominator;
return @mod(numerator, denominator);
}
@ -448,10 +437,8 @@ fn testMod() void {
pub fn rem(comptime T: type, numerator: T, denominator: T) !T {
@setRuntimeSafety(false);
if (denominator == 0)
return error.DivisionByZero;
if (denominator < 0)
return error.NegativeDenominator;
if (denominator == 0) return error.DivisionByZero;
if (denominator < 0) return error.NegativeDenominator;
return @rem(numerator, denominator);
}
@ -475,8 +462,7 @@ fn testRem() void {
/// Result is an unsigned integer.
pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) {
const uint = @IntType(false, @typeOf(x).bit_count);
if (x >= 0)
return uint(x);
if (x >= 0) return uint(x);
return uint(-(x + 1)) + 1;
}
@ -495,15 +481,12 @@ test "math.absCast" {
/// Returns the negation of the integer parameter.
/// Result is a signed integer.
pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) {
if (@typeOf(x).is_signed)
return negate(x);
if (@typeOf(x).is_signed) return negate(x);
const int = @IntType(true, @typeOf(x).bit_count);
if (x > -@minValue(int))
return error.Overflow;
if (x > -@minValue(int)) return error.Overflow;
if (x == -@minValue(int))
return @minValue(int);
if (x == -@minValue(int)) return @minValue(int);
return -int(x);
}
@ -546,7 +529,7 @@ pub fn floorPowerOfTwo(comptime T: type, value: T) T {
var x = value;
comptime var i = 1;
inline while(T.bit_count > i) : (i *= 2) {
inline while (T.bit_count > i) : (i *= 2) {
x |= (x >> i);
}

View File

@ -6,14 +6,14 @@ const builtin = @import("builtin");
const mem = this;
pub const Allocator = struct {
const Error = error {OutOfMemory};
const Error = error{OutOfMemory};
/// Allocate byte_count bytes and return them in a slice, with the
/// slice's pointer aligned at least to alignment bytes.
/// The returned newly allocated memory is undefined.
/// `alignment` is guaranteed to be >= 1
/// `alignment` is guaranteed to be a power of 2
allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) Error![]u8,
allocFn: fn(self: &Allocator, byte_count: usize, alignment: u29) Error![]u8,
/// If `new_byte_count > old_mem.len`:
/// * `old_mem.len` is the same as what was returned from allocFn or reallocFn.
@ -26,10 +26,10 @@ pub const Allocator = struct {
/// The returned newly allocated memory is undefined.
/// `alignment` is guaranteed to be >= 1
/// `alignment` is guaranteed to be a power of 2
reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) Error![]u8,
reallocFn: fn(self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: u29) Error![]u8,
/// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
freeFn: fn (self: &Allocator, old_mem: []u8) void,
freeFn: fn(self: &Allocator, old_mem: []u8) void,
fn create(self: &Allocator, comptime T: type) !&T {
if (@sizeOf(T) == 0) return &{};
@ -47,7 +47,7 @@ pub const Allocator = struct {
if (@sizeOf(T) == 0) return &{};
const slice = try self.alloc(T, 1);
const ptr = &slice[0];
*ptr = *init;
ptr.* = init.*;
return ptr;
}
@ -59,9 +59,7 @@ pub const Allocator = struct {
return self.alignedAlloc(T, @alignOf(T), n);
}
fn alignedAlloc(self: &Allocator, comptime T: type, comptime alignment: u29,
n: usize) ![]align(alignment) T
{
fn alignedAlloc(self: &Allocator, comptime T: type, comptime alignment: u29, n: usize) ![]align(alignment) T {
if (n == 0) {
return (&align(alignment) T)(undefined)[0..0];
}
@ -70,7 +68,7 @@ pub const Allocator = struct {
assert(byte_slice.len == byte_count);
// This loop gets optimized out in ReleaseFast mode
for (byte_slice) |*byte| {
*byte = undefined;
byte.* = undefined;
}
return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
}
@ -79,9 +77,7 @@ pub const Allocator = struct {
return self.alignedRealloc(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
}
fn alignedRealloc(self: &Allocator, comptime T: type, comptime alignment: u29,
old_mem: []align(alignment) T, n: usize) ![]align(alignment) T
{
fn alignedRealloc(self: &Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) ![]align(alignment) T {
if (old_mem.len == 0) {
return self.alloc(T, n);
}
@ -97,7 +93,7 @@ pub const Allocator = struct {
if (n > old_mem.len) {
// This loop gets optimized out in ReleaseFast mode
for (byte_slice[old_byte_slice.len..]) |*byte| {
*byte = undefined;
byte.* = undefined;
}
}
return ([]T)(@alignCast(alignment, byte_slice));
@ -110,9 +106,7 @@ pub const Allocator = struct {
return self.alignedShrink(T, @alignOf(T), @alignCast(@alignOf(T), old_mem), n);
}
fn alignedShrink(self: &Allocator, comptime T: type, comptime alignment: u29,
old_mem: []align(alignment) T, n: usize) []align(alignment) T
{
fn alignedShrink(self: &Allocator, comptime T: type, comptime alignment: u29, old_mem: []align(alignment) T, n: usize) []align(alignment) T {
if (n == 0) {
self.free(old_mem);
return old_mem[0..0];
@ -131,8 +125,7 @@ pub const Allocator = struct {
fn free(self: &Allocator, memory: var) void {
const bytes = ([]const u8)(memory);
if (bytes.len == 0)
return;
if (bytes.len == 0) return;
const non_const_ptr = @intToPtr(&u8, @ptrToInt(bytes.ptr));
self.freeFn(self, non_const_ptr[0..bytes.len]);
}
@ -146,11 +139,13 @@ pub fn copy(comptime T: type, dest: []T, source: []const T) void {
// this and automatically omit safety checks for loops
@setRuntimeSafety(false);
assert(dest.len >= source.len);
for (source) |s, i| dest[i] = s;
for (source) |s, i|
dest[i] = s;
}
pub fn set(comptime T: type, dest: []T, value: T) void {
for (dest) |*d| *d = value;
for (dest) |*d|
d.* = value;
}
/// Returns true if lhs < rhs, false otherwise
@ -229,8 +224,7 @@ pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
var i: usize = slice.len;
while (i != 0) {
i -= 1;
if (slice[i] == value)
return i;
if (slice[i] == value) return i;
}
return null;
}
@ -238,8 +232,7 @@ pub fn lastIndexOfScalar(comptime T: type, slice: []const T, value: T) ?usize {
pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize, value: T) ?usize {
var i: usize = start_index;
while (i < slice.len) : (i += 1) {
if (slice[i] == value)
return i;
if (slice[i] == value) return i;
}
return null;
}
@ -253,8 +246,7 @@ pub fn lastIndexOfAny(comptime T: type, slice: []const T, values: []const T) ?us
while (i != 0) {
i -= 1;
for (values) |value| {
if (slice[i] == value)
return i;
if (slice[i] == value) return i;
}
}
return null;
@ -264,8 +256,7 @@ pub fn indexOfAnyPos(comptime T: type, slice: []const T, start_index: usize, val
var i: usize = start_index;
while (i < slice.len) : (i += 1) {
for (values) |value| {
if (slice[i] == value)
return i;
if (slice[i] == value) return i;
}
}
return null;
@ -279,28 +270,23 @@ pub fn indexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize
/// To start looking at a different index, slice the haystack first.
/// TODO is there even a better algorithm for this?
pub fn lastIndexOf(comptime T: type, haystack: []const T, needle: []const T) ?usize {
if (needle.len > haystack.len)
return null;
if (needle.len > haystack.len) return null;
var i: usize = haystack.len - needle.len;
while (true) : (i -= 1) {
if (mem.eql(T, haystack[i..i+needle.len], needle))
return i;
if (i == 0)
return null;
if (mem.eql(T, haystack[i..i + needle.len], needle)) return i;
if (i == 0) return null;
}
}
// TODO boyer-moore algorithm
pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, needle: []const T) ?usize {
if (needle.len > haystack.len)
return null;
if (needle.len > haystack.len) return null;
var i: usize = start_index;
const end = haystack.len - needle.len;
while (i <= end) : (i += 1) {
if (eql(T, haystack[i .. i + needle.len], needle))
return i;
if (eql(T, haystack[i..i + needle.len], needle)) return i;
}
return null;
}
@ -355,9 +341,12 @@ pub fn readIntBE(comptime T: type, bytes: []const u8) T {
}
assert(bytes.len == @sizeOf(T));
var result: T = 0;
{comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) {
result = (result << 8) | T(bytes[i]);
}}
{
comptime var i = 0;
inline while (i < @sizeOf(T)) : (i += 1) {
result = (result << 8) | T(bytes[i]);
}
}
return result;
}
@ -369,9 +358,12 @@ pub fn readIntLE(comptime T: type, bytes: []const u8) T {
}
assert(bytes.len == @sizeOf(T));
var result: T = 0;
{comptime var i = 0; inline while (i < @sizeOf(T)) : (i += 1) {
result |= T(bytes[i]) << i * 8;
}}
{
comptime var i = 0;
inline while (i < @sizeOf(T)) : (i += 1) {
result |= T(bytes[i]) << i * 8;
}
}
return result;
}
@ -393,7 +385,7 @@ pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {
},
builtin.Endian.Little => {
for (buf) |*b| {
*b = @truncate(u8, bits);
b.* = @truncate(u8, bits);
bits >>= 8;
}
},
@ -401,7 +393,6 @@ pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {
assert(bits == 0);
}
pub fn hash_slice_u8(k: []const u8) u32 {
// FNV 32-bit hash
var h: u32 = 2166136261;
@ -420,7 +411,7 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {
/// split(" abc def ghi ", " ")
/// Will return slices for "abc", "def", "ghi", null, in that order.
pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator {
return SplitIterator {
return SplitIterator{
.index = 0,
.buffer = buffer,
.split_bytes = split_bytes,
@ -436,7 +427,7 @@ test "mem.split" {
}
pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
return if (needle.len > haystack.len) false else eql(T, haystack[0 .. needle.len], needle);
return if (needle.len > haystack.len) false else eql(T, haystack[0..needle.len], needle);
}
test "mem.startsWith" {
@ -445,10 +436,9 @@ test "mem.startsWith" {
}
pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
return if (needle.len > haystack.len) false else eql(T, haystack[haystack.len - needle.len ..], needle);
return if (needle.len > haystack.len) false else eql(T, haystack[haystack.len - needle.len..], needle);
}
test "mem.endsWith" {
assert(endsWith(u8, "Needle in haystack", "haystack"));
assert(!endsWith(u8, "Bob", "Bo"));
@ -542,29 +532,47 @@ test "testReadInt" {
}
fn testReadIntImpl() void {
{
const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 };
assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
assert(readIntBE(u32, bytes) == 0x12345678);
assert(readIntBE(i32, bytes) == 0x12345678);
const bytes = []u8{
0x12,
0x34,
0x56,
0x78,
};
assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
assert(readIntBE(u32, bytes) == 0x12345678);
assert(readIntBE(i32, bytes) == 0x12345678);
assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412);
assert(readIntLE(u32, bytes) == 0x78563412);
assert(readIntLE(i32, bytes) == 0x78563412);
assert(readIntLE(u32, bytes) == 0x78563412);
assert(readIntLE(i32, bytes) == 0x78563412);
}
{
const buf = []u8{0x00, 0x00, 0x12, 0x34};
const buf = []u8{
0x00,
0x00,
0x12,
0x34,
};
const answer = readInt(buf, u64, builtin.Endian.Big);
assert(answer == 0x00001234);
}
{
const buf = []u8{0x12, 0x34, 0x00, 0x00};
const buf = []u8{
0x12,
0x34,
0x00,
0x00,
};
const answer = readInt(buf, u64, builtin.Endian.Little);
assert(answer == 0x00003412);
}
{
const bytes = []u8{0xff, 0xfe};
assert(readIntBE(u16, bytes) == 0xfffe);
const bytes = []u8{
0xff,
0xfe,
};
assert(readIntBE(u16, bytes) == 0xfffe);
assert(readIntBE(i16, bytes) == -0x0002);
assert(readIntLE(u16, bytes) == 0xfeff);
assert(readIntLE(u16, bytes) == 0xfeff);
assert(readIntLE(i16, bytes) == -0x0101);
}
}
@ -577,19 +585,38 @@ fn testWriteIntImpl() void {
var bytes: [4]u8 = undefined;
writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 }));
assert(eql(u8, bytes, []u8{
0x12,
0x34,
0x56,
0x78,
}));
writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);
assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 }));
assert(eql(u8, bytes, []u8{
0x12,
0x34,
0x56,
0x78,
}));
writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);
assert(eql(u8, bytes, []u8{ 0x00, 0x00, 0x12, 0x34 }));
assert(eql(u8, bytes, []u8{
0x00,
0x00,
0x12,
0x34,
}));
writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);
assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 }));
assert(eql(u8, bytes, []u8{
0x34,
0x12,
0x00,
0x00,
}));
}
pub fn min(comptime T: type, slice: []const T) T {
var best = slice[0];
for (slice[1..]) |item| {
@ -615,9 +642,9 @@ test "mem.max" {
}
pub fn swap(comptime T: type, a: &T, b: &T) void {
const tmp = *a;
*a = *b;
*b = tmp;
const tmp = a.*;
a.* = b.*;
b.* = tmp;
}
/// In-place order reversal of a slice
@ -630,10 +657,22 @@ pub fn reverse(comptime T: type, items: []T) void {
}
test "std.mem.reverse" {
var arr = []i32{ 5, 3, 1, 2, 4 };
var arr = []i32{
5,
3,
1,
2,
4,
};
reverse(i32, arr[0..]);
assert(eql(i32, arr, []i32{ 4, 2, 1, 3, 5 }));
assert(eql(i32, arr, []i32{
4,
2,
1,
3,
5,
}));
}
/// In-place rotation of the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1)
@ -645,10 +684,22 @@ pub fn rotate(comptime T: type, items: []T, amount: usize) void {
}
test "std.mem.rotate" {
var arr = []i32{ 5, 3, 1, 2, 4 };
var arr = []i32{
5,
3,
1,
2,
4,
};
rotate(i32, arr[0..], 2);
assert(eql(i32, arr, []i32{ 1, 2, 4, 5, 3 }));
assert(eql(i32, arr, []i32{
1,
2,
4,
5,
3,
}));
}
// TODO: When https://github.com/zig-lang/zig/issues/649 is solved these can be done by

View File

@ -3705,7 +3705,9 @@ pub const Parser = struct {
},
ast.Node.Id.PrefixOp => {
const prefix_op_node = @fieldParentPtr(ast.Node.PrefixOp, "base", base);
try stack.append(RenderState { .Expression = prefix_op_node.rhs });
if (prefix_op_node.op != ast.Node.PrefixOp.Op.Deref) {
try stack.append(RenderState { .Expression = prefix_op_node.rhs });
}
switch (prefix_op_node.op) {
ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {
try stream.write("&");
@ -3742,7 +3744,10 @@ pub const Parser = struct {
},
ast.Node.PrefixOp.Op.BitNot => try stream.write("~"),
ast.Node.PrefixOp.Op.BoolNot => try stream.write("!"),
ast.Node.PrefixOp.Op.Deref => try stream.write("*"),
ast.Node.PrefixOp.Op.Deref => {
try stack.append(RenderState { .Text = ".*" });
try stack.append(RenderState { .Expression = prefix_op_node.rhs });
},
ast.Node.PrefixOp.Op.Negation => try stream.write("-"),
ast.Node.PrefixOp.Op.NegationWrap => try stream.write("-%"),
ast.Node.PrefixOp.Op.Try => try stream.write("try "),

View File

@ -10,7 +10,9 @@ test "global variable alignment" {
assert(@typeOf(slice) == []align(4) u8);
}
fn derp() align(@sizeOf(usize) * 2) i32 { return 1234; }
fn derp() align(@sizeOf(usize) * 2) i32 {
return 1234;
}
fn noop1() align(1) void {}
fn noop4() align(4) void {}
@ -22,7 +24,6 @@ test "function alignment" {
noop4();
}
var baz: packed struct {
a: u32,
b: u32,
@ -32,7 +33,6 @@ test "packed struct alignment" {
assert(@typeOf(&baz.b) == &align(1) u32);
}
const blah: packed struct {
a: u3,
b: u3,
@ -53,29 +53,43 @@ test "implicitly decreasing pointer alignment" {
assert(addUnaligned(&a, &b) == 7);
}
fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) u32 { return *a + *b; }
fn addUnaligned(a: &align(1) const u32, b: &align(1) const u32) u32 {
return a.* + b.*;
}
test "implicitly decreasing slice alignment" {
const a: u32 align(4) = 3;
const b: u32 align(8) = 4;
assert(addUnalignedSlice((&a)[0..1], (&b)[0..1]) == 7);
}
fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { return a[0] + b[0]; }
fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
return a[0] + b[0];
}
test "specifying alignment allows pointer cast" {
testBytesAlign(0x33);
}
fn testBytesAlign(b: u8) void {
var bytes align(4) = []u8{b, b, b, b};
var bytes align(4) = []u8 {
b,
b,
b,
b,
};
const ptr = @ptrCast(&u32, &bytes[0]);
assert(*ptr == 0x33333333);
assert(ptr.* == 0x33333333);
}
test "specifying alignment allows slice cast" {
testBytesAlignSlice(0x33);
}
fn testBytesAlignSlice(b: u8) void {
var bytes align(4) = []u8{b, b, b, b};
var bytes align(4) = []u8 {
b,
b,
b,
b,
};
const slice = ([]u32)(bytes[0..]);
assert(slice[0] == 0x33333333);
}
@ -89,11 +103,14 @@ fn expectsOnly1(x: &align(1) u32) void {
expects4(@alignCast(4, x));
}
fn expects4(x: &align(4) u32) void {
*x += 1;
x.* += 1;
}
test "@alignCast slices" {
var array align(4) = []u32{1, 1};
var array align(4) = []u32 {
1,
1,
};
const slice = array[0..];
sliceExpectsOnly1(slice);
assert(slice[0] == 2);
@ -105,31 +122,34 @@ fn sliceExpects4(slice: []align(4) u32) void {
slice[0] += 1;
}
test "implicitly decreasing fn alignment" {
testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
testImplicitlyDecreaseFnAlign(alignedBig, 5678);
}
fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void {
fn testImplicitlyDecreaseFnAlign(ptr: fn() align(1) i32, answer: i32) void {
assert(ptr() == answer);
}
fn alignedSmall() align(8) i32 { return 1234; }
fn alignedBig() align(16) i32 { return 5678; }
fn alignedSmall() align(8) i32 {
return 1234;
}
fn alignedBig() align(16) i32 {
return 5678;
}
test "@alignCast functions" {
assert(fnExpectsOnly1(simple4) == 0x19);
}
fn fnExpectsOnly1(ptr: fn()align(1) i32) i32 {
fn fnExpectsOnly1(ptr: fn() align(1) i32) i32 {
return fnExpects4(@alignCast(4, ptr));
}
fn fnExpects4(ptr: fn()align(4) i32) i32 {
fn fnExpects4(ptr: fn() align(4) i32) i32 {
return ptr();
}
fn simple4() align(4) i32 { return 0x19; }
fn simple4() align(4) i32 {
return 0x19;
}
test "generic function with align param" {
assert(whyWouldYouEverDoThis(1) == 0x1);
@ -137,8 +157,9 @@ test "generic function with align param" {
assert(whyWouldYouEverDoThis(8) == 0x1);
}
fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { return 0x1; }
fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
return 0x1;
}
test "@ptrCast preserves alignment of bigger source" {
var x: u32 align(16) = 1234;
@ -146,24 +167,38 @@ test "@ptrCast preserves alignment of bigger source" {
assert(@typeOf(ptr) == &align(16) u8);
}
test "compile-time known array index has best alignment possible" {
// take full advantage of over-alignment
var array align(4) = []u8 {1, 2, 3, 4};
var array align(4) = []u8 {
1,
2,
3,
4,
};
assert(@typeOf(&array[0]) == &align(4) u8);
assert(@typeOf(&array[1]) == &u8);
assert(@typeOf(&array[2]) == &align(2) u8);
assert(@typeOf(&array[3]) == &u8);
// because align is too small but we still figure out to use 2
var bigger align(2) = []u64{1, 2, 3, 4};
var bigger align(2) = []u64 {
1,
2,
3,
4,
};
assert(@typeOf(&bigger[0]) == &align(2) u64);
assert(@typeOf(&bigger[1]) == &align(2) u64);
assert(@typeOf(&bigger[2]) == &align(2) u64);
assert(@typeOf(&bigger[3]) == &align(2) u64);
// because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
var smaller align(2) = []u32{1, 2, 3, 4};
var smaller align(2) = []u32 {
1,
2,
3,
4,
};
testIndex(&smaller[0], 0, &align(2) u32);
testIndex(&smaller[0], 1, &align(2) u32);
testIndex(&smaller[0], 2, &align(2) u32);
@ -182,7 +217,6 @@ fn testIndex2(ptr: &align(4) u8, index: usize, comptime T: type) void {
assert(@typeOf(&ptr[index]) == T);
}
test "alignstack" {
assert(fnWithAlignedStack() == 1234);
}

View File

@ -1,7 +1,11 @@
const assert = @import("std").debug.assert;
const builtin = @import("builtin");
const Foo = struct { x: u32, y: u32, z: u32, };
const Foo = struct {
x: u32,
y: u32,
z: u32,
};
test "@alignOf(T) before referencing T" {
comptime assert(@alignOf(Foo) != @maxValue(usize));

View File

@ -2,9 +2,9 @@ const assert = @import("std").debug.assert;
const mem = @import("std").mem;
test "arrays" {
var array : [5]u32 = undefined;
var array: [5]u32 = undefined;
var i : u32 = 0;
var i: u32 = 0;
while (i < 5) {
array[i] = i + 1;
i = array[i];
@ -34,24 +34,41 @@ test "void arrays" {
}
test "array literal" {
const hex_mult = []u16{4096, 256, 16, 1};
const hex_mult = []u16 {
4096,
256,
16,
1,
};
assert(hex_mult.len == 4);
assert(hex_mult[1] == 256);
}
test "array dot len const expr" {
assert(comptime x: {break :x some_array.len == 4;});
assert(comptime x: {
break :x some_array.len == 4;
});
}
const ArrayDotLenConstExpr = struct {
y: [some_array.len]u8,
};
const some_array = []u8 {0, 1, 2, 3};
const some_array = []u8 {
0,
1,
2,
3,
};
test "nested arrays" {
const array_of_strings = [][]const u8 {"hello", "this", "is", "my", "thing"};
const array_of_strings = [][]const u8 {
"hello",
"this",
"is",
"my",
"thing",
};
for (array_of_strings) |s, i| {
if (i == 0) assert(mem.eql(u8, s, "hello"));
if (i == 1) assert(mem.eql(u8, s, "this"));
@ -61,7 +78,6 @@ test "nested arrays" {
}
}
var s_array: [8]Sub = undefined;
const Sub = struct {
b: u8,
@ -70,7 +86,9 @@ const Str = struct {
a: []Sub,
};
test "set global var array via slice embedded in struct" {
var s = Str { .a = s_array[0..]};
var s = Str {
.a = s_array[0..],
};
s.a[0].b = 1;
s.a[1].b = 2;
@ -82,7 +100,10 @@ test "set global var array via slice embedded in struct" {
}
test "array literal with specified size" {
var array = [2]u8{1, 2};
var array = [2]u8 {
1,
2,
};
assert(array[0] == 1);
assert(array[1] == 2);
}

View File

@ -10,5 +10,9 @@ fn testBitCast_i32_u32() void {
assert(conv2(@maxValue(u32)) == -1);
}
fn conv(x: i32) u32 { return @bitCast(u32, x); }
fn conv2(x: u32) i32 { return @bitCast(i32, x); }
fn conv(x: i32) u32 {
return @bitCast(u32, x);
}
fn conv2(x: u32) i32 {
return @bitCast(i32, x);
}

View File

@ -1,9 +1,20 @@
const E = union(enum) { A: [9]u8, B: u64, };
const S = struct { x: u8, y: E, };
const E = union(enum) {
A: [9]u8,
B: u64,
};
const S = struct {
x: u8,
y: E,
};
const assert = @import("std").debug.assert;
test "bug 394 fixed" {
const x = S { .x = 3, .y = E {.B = 1 } };
const x = S {
.x = 3,
.y = E {
.B = 1,
},
};
assert(x.x == 3);
}

View File

@ -8,5 +8,5 @@ test "function with &const parameter with type dereferenced by namespace" {
}
fn foo(x: &const other_file.Integer) void {
std.debug.assert(*x == 1234);
std.debug.assert(x.* == 1234);
}

View File

@ -14,12 +14,15 @@ test "nullable if after an if in a switch prong of a switch with 2 prongs in an
}
fn foo(a: bool, b: bool) void {
var prefix_op = PrefixOp { .AddrOf = Value { .align_expr = 1234 } };
if (a) {
} else {
var prefix_op = PrefixOp {
.AddrOf = Value {
.align_expr = 1234,
},
};
if (a) {} else {
switch (prefix_op) {
PrefixOp.AddrOf => |addr_of_info| {
if (b) { }
if (b) {}
if (addr_of_info.align_expr) |align_expr| {
assert(align_expr == 1234);
}

View File

@ -24,8 +24,8 @@ const Counter = struct {
fn constCount(comptime cb: &const CountBy, comptime unused: u32) void {
comptime {
var cnt = cb.counter();
if(cnt.i != 0) @compileError("Counter instance reused!");
while(cnt.count()){}
if (cnt.i != 0) @compileError("Counter instance reused!");
while (cnt.count()) {}
}
}

View File

@ -12,8 +12,7 @@ const ZigTable = struct {
zero_case: fn(&Random, f64) f64,
};
fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn(f64) f64,
comptime f_inv: fn(f64) f64, comptime zero_case: fn(&Random, f64) f64) ZigTable {
fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn(f64) f64, comptime f_inv: fn(f64) f64, comptime zero_case: fn(&Random, f64) f64) ZigTable {
var tables: ZigTable = undefined;
tables.is_symmetric = is_symmetric;
@ -26,12 +25,12 @@ fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, co
for (tables.x[2..256]) |*entry, i| {
const last = tables.x[2 + i - 1];
*entry = f_inv(v / last + f(last));
entry.* = f_inv(v / last + f(last));
}
tables.x[256] = 0;
for (tables.f[0..]) |*entry, i| {
*entry = f(tables.x[i]);
entry.* = f(tables.x[i]);
}
return tables;
@ -40,9 +39,15 @@ fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, co
const norm_r = 3.6541528853610088;
const norm_v = 0.00492867323399;
fn norm_f(x: f64) f64 { return math.exp(-x * x / 2.0); }
fn norm_f_inv(y: f64) f64 { return math.sqrt(-2.0 * math.ln(y)); }
fn norm_zero_case(random: &Random, u: f64) f64 { return 0.0; }
fn norm_f(x: f64) f64 {
return math.exp(-x * x / 2.0);
}
fn norm_f_inv(y: f64) f64 {
return math.sqrt(-2.0 * math.ln(y));
}
fn norm_zero_case(random: &Random, u: f64) f64 {
return 0.0;
}
const NormalDist = blk: {
@setEvalBranchQuota(30000);

View File

@ -14,10 +14,10 @@ test "integer literal to pointer cast" {
}
test "pointer reinterpret const float to int" {
const float: f64 = 5.99999999999994648725e-01;
const float: f64 = 5.99999999999994648725e - 01;
const float_ptr = &float;
const int_ptr = @ptrCast(&const i32, float_ptr);
const int_val = *int_ptr;
const int_val = int_ptr.*;
assert(int_val == 858993411);
}
@ -29,25 +29,31 @@ test "implicitly cast a pointer to a const pointer of it" {
}
fn funcWithConstPtrPtr(x: &const &i32) void {
**x += 1;
x.*.* += 1;
}
test "implicitly cast a container to a const pointer of it" {
const z = Struct(void) { .x = void{} };
const z = Struct(void) {
.x = void{},
};
assert(0 == @sizeOf(@typeOf(z)));
assert(void{} == Struct(void).pointer(z).x);
assert(void{} == Struct(void).pointer(&z).x);
assert(void{} == Struct(void).maybePointer(z).x);
assert(void{} == Struct(void).maybePointer(&z).x);
assert(void{} == Struct(void).maybePointer(null).x);
const s = Struct(u8) { .x = 42 };
const s = Struct(u8) {
.x = 42,
};
assert(0 != @sizeOf(@typeOf(s)));
assert(42 == Struct(u8).pointer(s).x);
assert(42 == Struct(u8).pointer(&s).x);
assert(42 == Struct(u8).maybePointer(s).x);
assert(42 == Struct(u8).maybePointer(&s).x);
assert(0 == Struct(u8).maybePointer(null).x);
const u = Union { .x = 42 };
const u = Union {
.x = 42,
};
assert(42 == Union.pointer(u).x);
assert(42 == Union.pointer(&u).x);
assert(42 == Union.maybePointer(u).x);
@ -67,12 +73,14 @@ fn Struct(comptime T: type) type {
x: T,
fn pointer(self: &const Self) Self {
return *self;
return self.*;
}
fn maybePointer(self: ?&const Self) Self {
const none = Self { .x = if (T == void) void{} else 0 };
return *(self ?? &none);
const none = Self {
.x = if (T == void) void{} else 0,
};
return (self ?? &none).*;
}
};
}
@ -81,12 +89,14 @@ const Union = union {
x: u8,
fn pointer(self: &const Union) Union {
return *self;
return self.*;
}
fn maybePointer(self: ?&const Union) Union {
const none = Union { .x = 0 };
return *(self ?? &none);
const none = Union {
.x = 0,
};
return (self ?? &none).*;
}
};
@ -95,11 +105,11 @@ const Enum = enum {
Some,
fn pointer(self: &const Enum) Enum {
return *self;
return self.*;
}
fn maybePointer(self: ?&const Enum) Enum {
return *(self ?? &Enum.None);
return (self ?? &Enum.None).*;
}
};
@ -108,19 +118,21 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" {
const Self = this;
x: u8,
fn constConst(p: &const &const Self) u8 {
return (*p).x;
return (p.*).x;
}
fn maybeConstConst(p: ?&const &const Self) u8 {
return (*??p).x;
return (??p.*).x;
}
fn constConstConst(p: &const &const &const Self) u8 {
return (**p).x;
return (p.*.*).x;
}
fn maybeConstConstConst(p: ?&const &const &const Self) u8 {
return (**??p).x;
return (??p.*.*).x;
}
};
const s = S { .x = 42 };
const s = S {
.x = 42,
};
const p = &s;
const q = &p;
const r = &q;
@ -154,7 +166,6 @@ fn boolToStr(b: bool) []const u8 {
return if (b) "true" else "false";
}
test "peer resolve array and const slice" {
testPeerResolveArrayConstSlice(true);
comptime testPeerResolveArrayConstSlice(true);
@ -168,12 +179,12 @@ fn testPeerResolveArrayConstSlice(b: bool) void {
test "integer literal to &const int" {
const x: &const i32 = 3;
assert(*x == 3);
assert(x.* == 3);
}
test "string literal to &const []const u8" {
const x: &const []const u8 = "hello";
assert(mem.eql(u8, *x, "hello"));
assert(mem.eql(u8, x.*, "hello"));
}
test "implicitly cast from T to error!?T" {
@ -191,7 +202,9 @@ fn castToMaybeTypeError(z: i32) void {
const f = z;
const g: error!?i32 = f;
const a = A{ .a = z };
const a = A {
.a = z,
};
const b: error!?A = a;
assert((??(b catch unreachable)).a == 1);
}
@ -205,7 +218,6 @@ fn implicitIntLitToMaybe() void {
const g: error!?i32 = 1;
}
test "return null from fn() error!?&T" {
const a = returnNullFromMaybeTypeErrorRef();
const b = returnNullLitFromMaybeTypeErrorRef();
@ -235,7 +247,6 @@ fn peerTypeTAndMaybeT(c: bool, b: bool) ?usize {
return usize(3);
}
test "peer type resolution: [0]u8 and []const u8" {
assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
@ -246,7 +257,7 @@ test "peer type resolution: [0]u8 and []const u8" {
}
fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
if (a) {
return []const u8 {};
return []const u8{};
}
return slice[0..1];
@ -261,7 +272,6 @@ fn castToMaybeSlice() ?[]const u8 {
return "hi";
}
test "implicitly cast from [0]T to error![]T" {
testCastZeroArrayToErrSliceMut();
comptime testCastZeroArrayToErrSliceMut();
@ -329,7 +339,6 @@ fn foo(args: ...) void {
assert(@typeOf(args[0]) == &const [5]u8);
}
test "peer type resolution: error and [N]T" {
// TODO: implicit error!T to error!U where T can implicitly cast to U
//assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
@ -378,7 +387,12 @@ fn cast128Float(x: u128) f128 {
}
test "const slice widen cast" {
const bytes align(4) = []u8{0x12, 0x12, 0x12, 0x12};
const bytes align(4) = []u8 {
0x12,
0x12,
0x12,
0x12,
};
const u32_value = ([]const u32)(bytes[0..])[0];
assert(u32_value == 0x12121212);

View File

@ -36,7 +36,7 @@ async fn testAsyncSeq() void {
suspend;
seq('d');
}
var points = []u8{0} ** "abcdefg".len;
var points = []u8 {0} ** "abcdefg".len;
var index: usize = 0;
fn seq(c: u8) void {
@ -94,7 +94,7 @@ async fn await_another() i32 {
return 1234;
}
var await_points = []u8{0} ** "abcdefghi".len;
var await_points = []u8 {0} ** "abcdefghi".len;
var await_seq_index: usize = 0;
fn await_seq(c: u8) void {
@ -102,7 +102,6 @@ fn await_seq(c: u8) void {
await_seq_index += 1;
}
var early_final_result: i32 = 0;
test "coroutine await early return" {
@ -126,7 +125,7 @@ async fn early_another() i32 {
return 1234;
}
var early_points = []u8{0} ** "abcdef".len;
var early_points = []u8 {0} ** "abcdef".len;
var early_seq_index: usize = 0;
fn early_seq(c: u8) void {
@ -175,8 +174,8 @@ test "async fn pointer in a struct field" {
}
async<&std.mem.Allocator> fn simpleAsyncFn2(y: &i32) void {
defer *y += 2;
*y += 1;
defer y.* += 2;
y.* += 1;
suspend;
}
@ -205,7 +204,8 @@ test "error return trace across suspend points - async return" {
cancel p2;
}
fn nonFailing() promise->error!void {
// TODO https://github.com/zig-lang/zig/issues/760
fn nonFailing() (promise->error!void) {
return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
}
@ -238,7 +238,7 @@ async fn testBreakFromSuspend(my_result: &i32) void {
s: suspend |p| {
break :s;
}
*my_result += 1;
my_result.* += 1;
suspend;
*my_result += 1;
my_result.* += 1;
}

View File

@ -5,9 +5,18 @@ var index: usize = undefined;
fn runSomeErrorDefers(x: bool) !bool {
index = 0;
defer {result[index] = 'a'; index += 1;}
errdefer {result[index] = 'b'; index += 1;}
defer {result[index] = 'c'; index += 1;}
defer {
result[index] = 'a';
index += 1;
}
errdefer {
result[index] = 'b';
index += 1;
}
defer {
result[index] = 'c';
index += 1;
}
return if (x) x else error.FalseNotAllowed;
}

View File

@ -2,8 +2,15 @@ const assert = @import("std").debug.assert;
const mem = @import("std").mem;
test "enum type" {
const foo1 = Foo{ .One = 13};
const foo2 = Foo{. Two = Point { .x = 1234, .y = 5678, }};
const foo1 = Foo {
.One = 13,
};
const foo2 = Foo {
.Two = Point {
.x = 1234,
.y = 5678,
},
};
const bar = Bar.B;
assert(bar == Bar.B);
@ -41,26 +48,31 @@ const Bar = enum {
};
fn returnAnInt(x: i32) Foo {
return Foo { .One = x };
return Foo {
.One = x,
};
}
test "constant enum with payload" {
var empty = AnEnumWithPayload {.Empty = {}};
var full = AnEnumWithPayload {.Full = 13};
var empty = AnEnumWithPayload {
.Empty = {},
};
var full = AnEnumWithPayload {
.Full = 13,
};
shouldBeEmpty(empty);
shouldBeNotEmpty(full);
}
fn shouldBeEmpty(x: &const AnEnumWithPayload) void {
switch (*x) {
switch (x.*) {
AnEnumWithPayload.Empty => {},
else => unreachable,
}
}
fn shouldBeNotEmpty(x: &const AnEnumWithPayload) void {
switch (*x) {
switch (x.*) {
AnEnumWithPayload.Empty => unreachable,
else => {},
}
@ -71,8 +83,6 @@ const AnEnumWithPayload = union(enum) {
Full: i32,
};
const Number = enum {
Zero,
One,
@ -93,7 +103,6 @@ fn shouldEqual(n: Number, expected: u3) void {
assert(u3(n) == expected);
}
test "int to enum" {
testIntToEnumEval(3);
}
@ -108,7 +117,6 @@ const IntToEnumNumber = enum {
Four,
};
test "@tagName" {
assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
@ -124,7 +132,6 @@ const BareNumber = enum {
Three,
};
test "enum alignment" {
comptime {
assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
@ -137,47 +144,529 @@ const AlignTestEnum = union(enum) {
B: u64,
};
const ValueCount1 = enum { I0 };
const ValueCount2 = enum { I0, I1 };
const ValueCount1 = enum {
I0,
};
const ValueCount2 = enum {
I0,
I1,
};
const ValueCount256 = enum {
I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15,
I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31,
I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, I45, I46, I47,
I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63,
I64, I65, I66, I67, I68, I69, I70, I71, I72, I73, I74, I75, I76, I77, I78, I79,
I80, I81, I82, I83, I84, I85, I86, I87, I88, I89, I90, I91, I92, I93, I94, I95,
I96, I97, I98, I99, I100, I101, I102, I103, I104, I105, I106, I107, I108, I109,
I110, I111, I112, I113, I114, I115, I116, I117, I118, I119, I120, I121, I122, I123,
I124, I125, I126, I127, I128, I129, I130, I131, I132, I133, I134, I135, I136, I137,
I138, I139, I140, I141, I142, I143, I144, I145, I146, I147, I148, I149, I150, I151,
I152, I153, I154, I155, I156, I157, I158, I159, I160, I161, I162, I163, I164, I165,
I166, I167, I168, I169, I170, I171, I172, I173, I174, I175, I176, I177, I178, I179,
I180, I181, I182, I183, I184, I185, I186, I187, I188, I189, I190, I191, I192, I193,
I194, I195, I196, I197, I198, I199, I200, I201, I202, I203, I204, I205, I206, I207,
I208, I209, I210, I211, I212, I213, I214, I215, I216, I217, I218, I219, I220, I221,
I222, I223, I224, I225, I226, I227, I228, I229, I230, I231, I232, I233, I234, I235,
I236, I237, I238, I239, I240, I241, I242, I243, I244, I245, I246, I247, I248, I249,
I250, I251, I252, I253, I254, I255
I0,
I1,
I2,
I3,
I4,
I5,
I6,
I7,
I8,
I9,
I10,
I11,
I12,
I13,
I14,
I15,
I16,
I17,
I18,
I19,
I20,
I21,
I22,
I23,
I24,
I25,
I26,
I27,
I28,
I29,
I30,
I31,
I32,
I33,
I34,
I35,
I36,
I37,
I38,
I39,
I40,
I41,
I42,
I43,
I44,
I45,
I46,
I47,
I48,
I49,
I50,
I51,
I52,
I53,
I54,
I55,
I56,
I57,
I58,
I59,
I60,
I61,
I62,
I63,
I64,
I65,
I66,
I67,
I68,
I69,
I70,
I71,
I72,
I73,
I74,
I75,
I76,
I77,
I78,
I79,
I80,
I81,
I82,
I83,
I84,
I85,
I86,
I87,
I88,
I89,
I90,
I91,
I92,
I93,
I94,
I95,
I96,
I97,
I98,
I99,
I100,
I101,
I102,
I103,
I104,
I105,
I106,
I107,
I108,
I109,
I110,
I111,
I112,
I113,
I114,
I115,
I116,
I117,
I118,
I119,
I120,
I121,
I122,
I123,
I124,
I125,
I126,
I127,
I128,
I129,
I130,
I131,
I132,
I133,
I134,
I135,
I136,
I137,
I138,
I139,
I140,
I141,
I142,
I143,
I144,
I145,
I146,
I147,
I148,
I149,
I150,
I151,
I152,
I153,
I154,
I155,
I156,
I157,
I158,
I159,
I160,
I161,
I162,
I163,
I164,
I165,
I166,
I167,
I168,
I169,
I170,
I171,
I172,
I173,
I174,
I175,
I176,
I177,
I178,
I179,
I180,
I181,
I182,
I183,
I184,
I185,
I186,
I187,
I188,
I189,
I190,
I191,
I192,
I193,
I194,
I195,
I196,
I197,
I198,
I199,
I200,
I201,
I202,
I203,
I204,
I205,
I206,
I207,
I208,
I209,
I210,
I211,
I212,
I213,
I214,
I215,
I216,
I217,
I218,
I219,
I220,
I221,
I222,
I223,
I224,
I225,
I226,
I227,
I228,
I229,
I230,
I231,
I232,
I233,
I234,
I235,
I236,
I237,
I238,
I239,
I240,
I241,
I242,
I243,
I244,
I245,
I246,
I247,
I248,
I249,
I250,
I251,
I252,
I253,
I254,
I255,
};
const ValueCount257 = enum {
I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15,
I16, I17, I18, I19, I20, I21, I22, I23, I24, I25, I26, I27, I28, I29, I30, I31,
I32, I33, I34, I35, I36, I37, I38, I39, I40, I41, I42, I43, I44, I45, I46, I47,
I48, I49, I50, I51, I52, I53, I54, I55, I56, I57, I58, I59, I60, I61, I62, I63,
I64, I65, I66, I67, I68, I69, I70, I71, I72, I73, I74, I75, I76, I77, I78, I79,
I80, I81, I82, I83, I84, I85, I86, I87, I88, I89, I90, I91, I92, I93, I94, I95,
I96, I97, I98, I99, I100, I101, I102, I103, I104, I105, I106, I107, I108, I109,
I110, I111, I112, I113, I114, I115, I116, I117, I118, I119, I120, I121, I122, I123,
I124, I125, I126, I127, I128, I129, I130, I131, I132, I133, I134, I135, I136, I137,
I138, I139, I140, I141, I142, I143, I144, I145, I146, I147, I148, I149, I150, I151,
I152, I153, I154, I155, I156, I157, I158, I159, I160, I161, I162, I163, I164, I165,
I166, I167, I168, I169, I170, I171, I172, I173, I174, I175, I176, I177, I178, I179,
I180, I181, I182, I183, I184, I185, I186, I187, I188, I189, I190, I191, I192, I193,
I194, I195, I196, I197, I198, I199, I200, I201, I202, I203, I204, I205, I206, I207,
I208, I209, I210, I211, I212, I213, I214, I215, I216, I217, I218, I219, I220, I221,
I222, I223, I224, I225, I226, I227, I228, I229, I230, I231, I232, I233, I234, I235,
I236, I237, I238, I239, I240, I241, I242, I243, I244, I245, I246, I247, I248, I249,
I250, I251, I252, I253, I254, I255, I256
I0,
I1,
I2,
I3,
I4,
I5,
I6,
I7,
I8,
I9,
I10,
I11,
I12,
I13,
I14,
I15,
I16,
I17,
I18,
I19,
I20,
I21,
I22,
I23,
I24,
I25,
I26,
I27,
I28,
I29,
I30,
I31,
I32,
I33,
I34,
I35,
I36,
I37,
I38,
I39,
I40,
I41,
I42,
I43,
I44,
I45,
I46,
I47,
I48,
I49,
I50,
I51,
I52,
I53,
I54,
I55,
I56,
I57,
I58,
I59,
I60,
I61,
I62,
I63,
I64,
I65,
I66,
I67,
I68,
I69,
I70,
I71,
I72,
I73,
I74,
I75,
I76,
I77,
I78,
I79,
I80,
I81,
I82,
I83,
I84,
I85,
I86,
I87,
I88,
I89,
I90,
I91,
I92,
I93,
I94,
I95,
I96,
I97,
I98,
I99,
I100,
I101,
I102,
I103,
I104,
I105,
I106,
I107,
I108,
I109,
I110,
I111,
I112,
I113,
I114,
I115,
I116,
I117,
I118,
I119,
I120,
I121,
I122,
I123,
I124,
I125,
I126,
I127,
I128,
I129,
I130,
I131,
I132,
I133,
I134,
I135,
I136,
I137,
I138,
I139,
I140,
I141,
I142,
I143,
I144,
I145,
I146,
I147,
I148,
I149,
I150,
I151,
I152,
I153,
I154,
I155,
I156,
I157,
I158,
I159,
I160,
I161,
I162,
I163,
I164,
I165,
I166,
I167,
I168,
I169,
I170,
I171,
I172,
I173,
I174,
I175,
I176,
I177,
I178,
I179,
I180,
I181,
I182,
I183,
I184,
I185,
I186,
I187,
I188,
I189,
I190,
I191,
I192,
I193,
I194,
I195,
I196,
I197,
I198,
I199,
I200,
I201,
I202,
I203,
I204,
I205,
I206,
I207,
I208,
I209,
I210,
I211,
I212,
I213,
I214,
I215,
I216,
I217,
I218,
I219,
I220,
I221,
I222,
I223,
I224,
I225,
I226,
I227,
I228,
I229,
I230,
I231,
I232,
I233,
I234,
I235,
I236,
I237,
I238,
I239,
I240,
I241,
I242,
I243,
I244,
I245,
I246,
I247,
I248,
I249,
I250,
I251,
I252,
I253,
I254,
I255,
I256,
};
test "enum sizes" {
@ -189,11 +678,11 @@ test "enum sizes" {
}
}
const Small2 = enum (u2) {
const Small2 = enum(u2) {
One,
Two,
};
const Small = enum (u2) {
const Small = enum(u2) {
One,
Two,
Three,
@ -213,8 +702,7 @@ test "set enum tag type" {
}
}
const A = enum (u3) {
const A = enum(u3) {
One,
Two,
Three,
@ -225,7 +713,7 @@ const A = enum (u3) {
Four2,
};
const B = enum (u3) {
const B = enum(u3) {
One3,
Two3,
Three3,
@ -236,7 +724,7 @@ const B = enum (u3) {
Four23,
};
const C = enum (u2) {
const C = enum(u2) {
One4,
Two4,
Three4,
@ -389,6 +877,8 @@ test "enum with tag values don't require parens" {
}
test "enum with 1 field but explicit tag type should still have the tag type" {
const Enum = enum(u8) { B = 2 };
const Enum = enum(u8) {
B = 2,
};
comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8));
}

View File

@ -7,7 +7,7 @@ const ET = union(enum) {
UINT: u32,
pub fn print(a: &const ET, buf: []u8) error!usize {
return switch (*a) {
return switch (a.*) {
ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
};
@ -15,8 +15,12 @@ const ET = union(enum) {
};
test "enum with members" {
const a = ET { .SINT = -42 };
const b = ET { .UINT = 42 };
const a = ET {
.SINT = -42,
};
const b = ET {
.UINT = 42,
};
var buf: [20]u8 = undefined;
assert((a.print(buf[0..]) catch unreachable) == 3);

View File

@ -30,14 +30,12 @@ test "@errorName" {
assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
}
test "error values" {
const a = i32(error.err1);
const b = i32(error.err2);
assert(a != b);
}
test "redefinition of error values allowed" {
shouldBeNotEqual(error.AnError, error.SecondError);
}
@ -45,7 +43,6 @@ fn shouldBeNotEqual(a: error, b: error) void {
if (a == b) unreachable;
}
test "error binary operator" {
const a = errBinaryOperatorG(true) catch 3;
const b = errBinaryOperatorG(false) catch 3;
@ -56,20 +53,20 @@ fn errBinaryOperatorG(x: bool) error!isize {
return if (x) error.ItBroke else isize(10);
}
test "unwrap simple value from error" {
const i = unwrapSimpleValueFromErrorDo() catch unreachable;
assert(i == 13);
}
fn unwrapSimpleValueFromErrorDo() error!isize { return 13; }
fn unwrapSimpleValueFromErrorDo() error!isize {
return 13;
}
test "error return in assignment" {
doErrReturnInAssignment() catch unreachable;
}
fn doErrReturnInAssignment() error!void {
var x : i32 = undefined;
var x: i32 = undefined;
x = try makeANonErr();
}
@ -95,7 +92,10 @@ test "error set type " {
comptime testErrorSetType();
}
const MyErrSet = error {OutOfMemory, FileNotFound};
const MyErrSet = error {
OutOfMemory,
FileNotFound,
};
fn testErrorSetType() void {
assert(@memberCount(MyErrSet) == 2);
@ -109,14 +109,19 @@ fn testErrorSetType() void {
}
}
test "explicit error set cast" {
testExplicitErrorSetCast(Set1.A);
comptime testExplicitErrorSetCast(Set1.A);
}
const Set1 = error{A, B};
const Set2 = error{A, C};
const Set1 = error {
A,
B,
};
const Set2 = error {
A,
C,
};
fn testExplicitErrorSetCast(set1: Set1) void {
var x = Set2(set1);
@ -129,7 +134,8 @@ test "comptime test error for empty error set" {
comptime testComptimeTestErrorEmptySet(1234);
}
const EmptyErrorSet = error {};
const EmptyErrorSet = error {
};
fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
if (x) |v| assert(v == 1234) else |err| @compileError("bad");
@ -145,7 +151,9 @@ test "comptime err to int of error set with only 1 possible value" {
testErrToIntWithOnePossibleValue(error.A, u32(error.A));
comptime testErrToIntWithOnePossibleValue(error.A, u32(error.A));
}
fn testErrToIntWithOnePossibleValue(x: error{A}, comptime value: u32) void {
fn testErrToIntWithOnePossibleValue(x: error {
A,
}, comptime value: u32) void {
if (u32(x) != value) {
@compileError("bad");
}
@ -176,7 +184,6 @@ fn quux_1() !i32 {
return error.C;
}
test "error: fn returning empty error set can be passed as fn returning any error" {
entry();
comptime entry();
@ -186,24 +193,24 @@ fn entry() void {
foo2(bar2);
}
fn foo2(f: fn()error!void) void {
fn foo2(f: fn() error!void) void {
const x = f();
}
fn bar2() (error{}!void) { }
fn bar2() (error {
}!void) {}
test "error: Zero sized error set returned with value payload crash" {
_ = foo3(0);
_ = comptime foo3(0);
}
const Error = error{};
const Error = error {
};
fn foo3(b: usize) Error!usize {
return b;
}
test "error: Infer error set from literals" {
_ = nullLiteral("n") catch |err| handleErrors(err);
_ = floatLiteral("n") catch |err| handleErrors(err);
@ -215,29 +222,26 @@ test "error: Infer error set from literals" {
fn handleErrors(err: var) noreturn {
switch (err) {
error.T => {}
error.T => {},
}
unreachable;
}
fn nullLiteral(str: []const u8) !?i64 {
if (str[0] == 'n')
return null;
if (str[0] == 'n') return null;
return error.T;
}
fn floatLiteral(str: []const u8) !?f64 {
if (str[0] == 'n')
return 1.0;
if (str[0] == 'n') return 1.0;
return error.T;
}
fn intLiteral(str: []const u8) !?i64 {
if (str[0] == 'n')
return 1;
if (str[0] == 'n') return 1;
return error.T;
}

View File

@ -11,8 +11,6 @@ fn fibonacci(x: i32) i32 {
return fibonacci(x - 1) + fibonacci(x - 2);
}
fn unwrapAndAddOne(blah: ?i32) i32 {
return ??blah + 1;
}
@ -40,13 +38,13 @@ test "inline variable gets result of const if" {
assert(gimme1or2(false) == 2);
}
test "static function evaluation" {
assert(statically_added_number == 3);
}
const statically_added_number = staticAdd(1, 2);
fn staticAdd(a: i32, b: i32) i32 { return a + b; }
fn staticAdd(a: i32, b: i32) i32 {
return a + b;
}
test "const expr eval on single expr blocks" {
assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
@ -64,9 +62,6 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
return result;
}
test "statically initialized list" {
assert(static_point_list[0].x == 1);
assert(static_point_list[0].y == 2);
@ -77,7 +72,10 @@ const Point = struct {
x: i32,
y: i32,
};
const static_point_list = []Point { makePoint(1, 2), makePoint(3, 4) };
const static_point_list = []Point {
makePoint(1, 2),
makePoint(3, 4),
};
fn makePoint(x: i32, y: i32) Point {
return Point {
.x = x,
@ -85,7 +83,6 @@ fn makePoint(x: i32, y: i32) Point {
};
}
test "static eval list init" {
assert(static_vec3.data[2] == 1.0);
assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
@ -96,17 +93,19 @@ pub const Vec3 = struct {
};
pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
return Vec3 {
.data = []f32 { x, y, z, },
.data = []f32 {
x,
y,
z,
},
};
}
test "constant expressions" {
var array : [array_size]u8 = undefined;
var array: [array_size]u8 = undefined;
assert(@sizeOf(@typeOf(array)) == 20);
}
const array_size : u8 = 20;
const array_size: u8 = 20;
test "constant struct with negation" {
assert(vertices[0].x == -0.6);
@ -119,12 +118,29 @@ const Vertex = struct {
b: f32,
};
const vertices = []Vertex {
Vertex { .x = -0.6, .y = -0.4, .r = 1.0, .g = 0.0, .b = 0.0 },
Vertex { .x = 0.6, .y = -0.4, .r = 0.0, .g = 1.0, .b = 0.0 },
Vertex { .x = 0.0, .y = 0.6, .r = 0.0, .g = 0.0, .b = 1.0 },
Vertex {
.x = -0.6,
.y = -0.4,
.r = 1.0,
.g = 0.0,
.b = 0.0,
},
Vertex {
.x = 0.6,
.y = -0.4,
.r = 0.0,
.g = 1.0,
.b = 0.0,
},
Vertex {
.x = 0.0,
.y = 0.6,
.r = 0.0,
.g = 0.0,
.b = 1.0,
},
};
test "statically initialized struct" {
st_init_str_foo.x += 1;
assert(st_init_str_foo.x == 14);
@ -133,15 +149,21 @@ const StInitStrFoo = struct {
x: i32,
y: bool,
};
var st_init_str_foo = StInitStrFoo { .x = 13, .y = true, };
var st_init_str_foo = StInitStrFoo {
.x = 13,
.y = true,
};
test "statically initalized array literal" {
const y : [4]u8 = st_init_arr_lit_x;
const y: [4]u8 = st_init_arr_lit_x;
assert(y[3] == 4);
}
const st_init_arr_lit_x = []u8{1,2,3,4};
const st_init_arr_lit_x = []u8 {
1,
2,
3,
4,
};
test "const slice" {
comptime {
@ -198,14 +220,29 @@ const CmdFn = struct {
func: fn(i32) i32,
};
const cmd_fns = []CmdFn{
CmdFn {.name = "one", .func = one},
CmdFn {.name = "two", .func = two},
CmdFn {.name = "three", .func = three},
const cmd_fns = []CmdFn {
CmdFn {
.name = "one",
.func = one,
},
CmdFn {
.name = "two",
.func = two,
},
CmdFn {
.name = "three",
.func = three,
},
};
fn one(value: i32) i32 { return value + 1; }
fn two(value: i32) i32 { return value + 2; }
fn three(value: i32) i32 { return value + 3; }
fn one(value: i32) i32 {
return value + 1;
}
fn two(value: i32) i32 {
return value + 2;
}
fn three(value: i32) i32 {
return value + 3;
}
fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
var result: i32 = start_value;
@ -229,7 +266,7 @@ test "eval @setRuntimeSafety at compile-time" {
assert(result == 1234);
}
fn fnWithSetRuntimeSafety() i32{
fn fnWithSetRuntimeSafety() i32 {
@setRuntimeSafety(true);
return 1234;
}
@ -244,7 +281,6 @@ fn fnWithFloatMode() f32 {
return 1234.0;
}
const SimpleStruct = struct {
field: i32,
@ -253,7 +289,9 @@ const SimpleStruct = struct {
}
};
var simple_struct = SimpleStruct{ .field = 1234, };
var simple_struct = SimpleStruct {
.field = 1234,
};
const bound_fn = simple_struct.method;
@ -261,8 +299,6 @@ test "call method on bound fn referring to var instance" {
assert(bound_fn() == 1237);
}
test "ptr to local array argument at comptime" {
comptime {
var bytes: [10]u8 = undefined;
@ -277,7 +313,6 @@ fn modifySomeBytes(bytes: []u8) void {
bytes[9] = 'b';
}
test "comparisons 0 <= uint and 0 > uint should be comptime" {
testCompTimeUIntComparisons(1234);
}
@ -296,8 +331,6 @@ fn testCompTimeUIntComparisons(x: u32) void {
}
}
test "const ptr to variable data changes at runtime" {
assert(foo_ref.name[0] == 'a');
foo_ref.name = "b";
@ -308,11 +341,11 @@ const Foo = struct {
name: []const u8,
};
var foo_contents = Foo { .name = "a", };
var foo_contents = Foo {
.name = "a",
};
const foo_ref = &foo_contents;
test "create global array with for loop" {
assert(global_array[5] == 5 * 5);
assert(global_array[9] == 9 * 9);
@ -321,7 +354,7 @@ test "create global array with for loop" {
const global_array = x: {
var result: [10]usize = undefined;
for (result) |*item, index| {
*item = index * index;
item.* = index * index;
}
break :x result;
};
@ -379,7 +412,7 @@ test "f128 at compile time is lossy" {
pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
return struct {
pub const Node = struct { };
pub const Node = struct {};
};
}
@ -401,10 +434,10 @@ fn copyWithPartialInline(s: []u32, b: []u8) void {
comptime var i: usize = 0;
inline while (i < 4) : (i += 1) {
s[i] = 0;
s[i] |= u32(b[i*4+0]) << 24;
s[i] |= u32(b[i*4+1]) << 16;
s[i] |= u32(b[i*4+2]) << 8;
s[i] |= u32(b[i*4+3]) << 0;
s[i] |= u32(b[i * 4 + 0]) << 24;
s[i] |= u32(b[i * 4 + 1]) << 16;
s[i] |= u32(b[i * 4 + 2]) << 8;
s[i] |= u32(b[i * 4 + 3]) << 0;
}
}
@ -413,7 +446,7 @@ test "binary math operator in partially inlined function" {
var b: [16]u8 = undefined;
for (b) |*r, i|
*r = u8(i + 1);
r.* = u8(i + 1);
copyWithPartialInline(s[0..], b[0..]);
assert(s[0] == 0x1020304);
@ -422,7 +455,6 @@ test "binary math operator in partially inlined function" {
assert(s[3] == 0xd0e0f10);
}
test "comptime function with the same args is memoized" {
comptime {
assert(MakeType(i32) == MakeType(i32));
@ -447,12 +479,12 @@ test "comptime function with mutable pointer is not memoized" {
}
fn increment(value: &i32) void {
*value += 1;
value.* += 1;
}
fn generateTable(comptime T: type) [1010]T {
var res : [1010]T = undefined;
var i : usize = 0;
var res: [1010]T = undefined;
var i: usize = 0;
while (i < 1010) : (i += 1) {
res[i] = T(i);
}
@ -496,9 +528,10 @@ const SingleFieldStruct = struct {
}
};
test "const ptr to comptime mutable data is not memoized" {
comptime {
var foo = SingleFieldStruct {.x = 1};
var foo = SingleFieldStruct {
.x = 1,
};
assert(foo.read_x() == 1);
foo.x = 2;
assert(foo.read_x() == 2);

View File

@ -7,7 +7,6 @@ fn testParamsAdd(a: i32, b: i32) i32 {
return a + b;
}
test "local variables" {
testLocVars(2);
}
@ -16,7 +15,6 @@ fn testLocVars(b: i32) void {
if (a + b != 3) unreachable;
}
test "void parameters" {
voidFun(1, void{}, 2, {});
}
@ -27,9 +25,8 @@ fn voidFun(a: i32, b: void, c: i32, d: void) void {
return vv;
}
test "mutable local variables" {
var zero : i32 = 0;
var zero: i32 = 0;
assert(zero == 0);
var i = i32(0);
@ -41,7 +38,7 @@ test "mutable local variables" {
test "separate block scopes" {
{
const no_conflict : i32 = 5;
const no_conflict: i32 = 5;
assert(no_conflict == 5);
}
@ -56,8 +53,7 @@ test "call function with empty string" {
acceptsString("");
}
fn acceptsString(foo: []u8) void { }
fn acceptsString(foo: []u8) void {}
fn @"weird function name"() i32 {
return 1234;
@ -70,31 +66,43 @@ test "implicit cast function unreachable return" {
wantsFnWithVoid(fnWithUnreachable);
}
fn wantsFnWithVoid(f: fn() void) void { }
fn wantsFnWithVoid(f: fn() void) void {}
fn fnWithUnreachable() noreturn {
unreachable;
}
test "function pointers" {
const fns = []@typeOf(fn1) { fn1, fn2, fn3, fn4, };
const fns = []@typeOf(fn1) {
fn1,
fn2,
fn3,
fn4,
};
for (fns) |f, i| {
assert(f() == u32(i) + 5);
}
}
fn fn1() u32 {return 5;}
fn fn2() u32 {return 6;}
fn fn3() u32 {return 7;}
fn fn4() u32 {return 8;}
fn fn1() u32 {
return 5;
}
fn fn2() u32 {
return 6;
}
fn fn3() u32 {
return 7;
}
fn fn4() u32 {
return 8;
}
test "inline function call" {
assert(@inlineCall(add, 3, 9) == 12);
}
fn add(a: i32, b: i32) i32 { return a + b; }
fn add(a: i32, b: i32) i32 {
return a + b;
}
test "number literal as an argument" {
numberLiteralArg(3);
@ -110,4 +118,4 @@ test "assign inline fn to const variable" {
a();
}
inline fn inlineFn() void { }
inline fn inlineFn() void {}

View File

@ -3,8 +3,14 @@ const assert = std.debug.assert;
const mem = std.mem;
test "continue in for loop" {
const array = []i32 {1, 2, 3, 4, 5};
var sum : i32 = 0;
const array = []i32 {
1,
2,
3,
4,
5,
};
var sum: i32 = 0;
for (array) |x| {
sum += x;
if (x < 3) {
@ -24,17 +30,39 @@ test "for loop with pointer elem var" {
}
fn mangleString(s: []u8) void {
for (s) |*c| {
*c += 1;
c.* += 1;
}
}
test "basic for loop" {
const expected_result = []u8{9, 8, 7, 6, 0, 1, 2, 3, 9, 8, 7, 6, 0, 1, 2, 3 };
const expected_result = []u8 {
9,
8,
7,
6,
0,
1,
2,
3,
9,
8,
7,
6,
0,
1,
2,
3,
};
var buffer: [expected_result.len]u8 = undefined;
var buf_index: usize = 0;
const array = []u8 {9, 8, 7, 6};
const array = []u8 {
9,
8,
7,
6,
};
for (array) |item| {
buffer[buf_index] = item;
buf_index += 1;
@ -65,7 +93,8 @@ fn testBreakOuter() void {
var array = "aoeu";
var count: usize = 0;
outer: for (array) |_| {
for (array) |_2| { // TODO shouldn't get error for redeclaring "_"
// TODO shouldn't get error for redeclaring "_"
for (array) |_2| {
count += 1;
break :outer;
}
@ -82,7 +111,8 @@ fn testContinueOuter() void {
var array = "aoeu";
var counter: usize = 0;
outer: for (array) |_| {
for (array) |_2| { // TODO shouldn't get error for redeclaring "_"
// TODO shouldn't get error for redeclaring "_"
for (array) |_2| {
counter += 1;
continue :outer;
}

View File

@ -37,7 +37,6 @@ test "fn with comptime args" {
assert(sameButWithFloats(0.43, 0.49) == 0.49);
}
test "var params" {
assert(max_i32(12, 34) == 34);
assert(max_f64(1.2, 3.4) == 3.4);
@ -60,7 +59,6 @@ fn max_f64(a: f64, b: f64) f64 {
return max_var(a, b);
}
pub fn List(comptime T: type) type {
return SmallList(T, 8);
}
@ -82,10 +80,15 @@ test "function with return type type" {
assert(list2.prealloc_items.len == 8);
}
test "generic struct" {
var a1 = GenNode(i32) {.value = 13, .next = null,};
var b1 = GenNode(bool) {.value = true, .next = null,};
var a1 = GenNode(i32) {
.value = 13,
.next = null,
};
var b1 = GenNode(bool) {
.value = true,
.next = null,
};
assert(a1.value == 13);
assert(a1.value == a1.getVal());
assert(b1.getVal());
@ -94,7 +97,9 @@ fn GenNode(comptime T: type) type {
return struct {
value: T,
next: ?&GenNode(T),
fn getVal(n: &const GenNode(T)) T { return n.value; }
fn getVal(n: &const GenNode(T)) T {
return n.value;
}
};
}
@ -107,7 +112,6 @@ fn GenericDataThing(comptime count: isize) type {
};
}
test "use generic param in generic param" {
assert(aGenericFn(i32, 3, 4) == 7);
}
@ -115,21 +119,31 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
return a + b;
}
test "generic fn with implicit cast" {
assert(getFirstByte(u8, []u8 {13}) == 13);
assert(getFirstByte(u16, []u16 {0, 13}) == 0);
assert(getFirstByte(u16, []u16 {
0,
13,
}) == 0);
}
fn getByte(ptr: ?&const u8) u8 {
return ??ptr.*;
}
fn getByte(ptr: ?&const u8) u8 {return *??ptr;}
fn getFirstByte(comptime T: type, mem: []const T) u8 {
return getByte(@ptrCast(&const u8, &mem[0]));
}
const foos = []fn(var) bool {
foo1,
foo2,
};
const foos = []fn(var) bool { foo1, foo2 };
fn foo1(arg: var) bool { return arg; }
fn foo2(arg: var) bool { return !arg; }
fn foo1(arg: var) bool {
return arg;
}
fn foo2(arg: var) bool {
return !arg;
}
test "array of generic fns" {
assert(foos[0](true));

View File

@ -23,7 +23,6 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void {
}
}
test "else if expression" {
assert(elseIfExpressionF(1) == 1);
}

View File

@ -1 +1,3 @@
pub fn foo() i32 { return 1234; }
pub fn foo() i32 {
return 1234;
}

View File

@ -11,7 +11,9 @@ fn foo(id: u64) !i32 {
};
}
fn getErrInt() error!i32 { return 0; }
fn getErrInt() error!i32 {
return 0;
}
test "ir block deps" {
assert((foo(1) catch unreachable) == 0);

View File

@ -28,25 +28,12 @@ fn testDivision() void {
assert(divTrunc(f32, -5.0, 3.0) == -1.0);
comptime {
assert(
1194735857077236777412821811143690633098347576 %
508740759824825164163191790951174292733114988 ==
177254337427586449086438229241342047632117600);
assert(@rem(-1194735857077236777412821811143690633098347576,
508740759824825164163191790951174292733114988) ==
-177254337427586449086438229241342047632117600);
assert(1194735857077236777412821811143690633098347576 /
508740759824825164163191790951174292733114988 ==
2);
assert(@divTrunc(-1194735857077236777412821811143690633098347576,
508740759824825164163191790951174292733114988) ==
-2);
assert(@divTrunc(1194735857077236777412821811143690633098347576,
-508740759824825164163191790951174292733114988) ==
-2);
assert(@divTrunc(-1194735857077236777412821811143690633098347576,
-508740759824825164163191790951174292733114988) ==
2);
assert(1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600);
assert(@rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600);
assert(1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2);
assert(@divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2);
assert(@divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2);
assert(@divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2);
assert(4126227191251978491697987544882340798050766755606969681711 % 10 == 1);
}
}
@ -114,18 +101,28 @@ fn ctz(x: var) usize {
test "assignment operators" {
var i: u32 = 0;
i += 5; assert(i == 5);
i -= 2; assert(i == 3);
i *= 20; assert(i == 60);
i /= 3; assert(i == 20);
i %= 11; assert(i == 9);
i <<= 1; assert(i == 18);
i >>= 2; assert(i == 4);
i += 5;
assert(i == 5);
i -= 2;
assert(i == 3);
i *= 20;
assert(i == 60);
i /= 3;
assert(i == 20);
i %= 11;
assert(i == 9);
i <<= 1;
assert(i == 18);
i >>= 2;
assert(i == 4);
i = 6;
i &= 5; assert(i == 4);
i ^= 6; assert(i == 2);
i &= 5;
assert(i == 4);
i ^= 6;
assert(i == 2);
i = 6;
i |= 3; assert(i == 7);
i |= 3;
assert(i == 7);
}
test "three expr in a row" {
@ -138,7 +135,7 @@ fn testThreeExprInARow(f: bool, t: bool) void {
assertFalse(1 | 2 | 4 != 7);
assertFalse(3 ^ 6 ^ 8 != 13);
assertFalse(7 & 14 & 28 != 4);
assertFalse(9 << 1 << 2 != 9 << 3);
assertFalse(9 << 1 << 2 != 9 << 3);
assertFalse(90 >> 1 >> 2 != 90 >> 3);
assertFalse(100 - 1 + 1000 != 1099);
assertFalse(5 * 4 / 2 % 3 != 1);
@ -150,7 +147,6 @@ fn assertFalse(b: bool) void {
assert(!b);
}
test "const number literal" {
const one = 1;
const eleven = ten + one;
@ -159,8 +155,6 @@ test "const number literal" {
}
const ten = 10;
test "unsigned wrapping" {
testUnsignedWrappingEval(@maxValue(u32));
comptime testUnsignedWrappingEval(@maxValue(u32));
@ -214,8 +208,12 @@ const DivResult = struct {
};
test "binary not" {
assert(comptime x: {break :x ~u16(0b1010101010101010) == 0b0101010101010101;});
assert(comptime x: {break :x ~u64(2147483647) == 18446744071562067968;});
assert(comptime x: {
break :x ~u16(0b1010101010101010) == 0b0101010101010101;
});
assert(comptime x: {
break :x ~u64(2147483647) == 18446744071562067968;
});
testBinaryNot(0b1010101010101010);
}
@ -319,27 +317,15 @@ fn testShrExact(x: u8) void {
test "big number addition" {
comptime {
assert(
35361831660712422535336160538497375248 +
101752735581729509668353361206450473702 ==
137114567242441932203689521744947848950);
assert(
594491908217841670578297176641415611445982232488944558774612 +
390603545391089362063884922208143568023166603618446395589768 ==
985095453608931032642182098849559179469148836107390954364380);
assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
}
}
test "big number multiplication" {
comptime {
assert(
45960427431263824329884196484953148229 *
128339149605334697009938835852565949723 ==
5898522172026096622534201617172456926982464453350084962781392314016180490567);
assert(
594491908217841670578297176641415611445982232488944558774612 *
390603545391089362063884922208143568023166603618446395589768 ==
232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016);
assert(45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567);
assert(594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016);
}
}
@ -380,7 +366,9 @@ test "f128" {
comptime test_f128();
}
fn make_f128(x: f128) f128 { return x; }
fn make_f128(x: f128) f128 {
return x;
}
fn test_f128() void {
assert(@sizeOf(f128) == 16);

View File

@ -4,6 +4,7 @@ const cstr = @import("std").cstr;
const builtin = @import("builtin");
// normal comment
/// this is a documentation comment
/// doc comment line 2
fn emptyFunctionWithComments() void {}
@ -16,8 +17,7 @@ comptime {
@export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal);
}
extern fn disabledExternFn() void {
}
extern fn disabledExternFn() void {}
test "call disabled extern fn" {
disabledExternFn();
@ -110,17 +110,29 @@ fn testShortCircuit(f: bool, t: bool) void {
var hit_3 = f;
var hit_4 = f;
if (t or x: {assert(f); break :x f;}) {
if (t or x: {
assert(f);
break :x f;
}) {
hit_1 = t;
}
if (f or x: { hit_2 = t; break :x f; }) {
if (f or x: {
hit_2 = t;
break :x f;
}) {
assert(f);
}
if (t and x: { hit_3 = t; break :x f; }) {
if (t and x: {
hit_3 = t;
break :x f;
}) {
assert(f);
}
if (f and x: {assert(f); break :x f;}) {
if (f and x: {
assert(f);
break :x f;
}) {
assert(f);
} else {
hit_4 = t;
@ -146,8 +158,8 @@ test "return string from function" {
assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
}
const g1 : i32 = 1233 + 1;
var g2 : i32 = 0;
const g1: i32 = 1233 + 1;
var g2: i32 = 0;
test "global variables" {
assert(g2 == 0);
@ -155,10 +167,9 @@ test "global variables" {
assert(g2 == 1234);
}
test "memcpy and memset intrinsics" {
var foo : [20]u8 = undefined;
var bar : [20]u8 = undefined;
var foo: [20]u8 = undefined;
var bar: [20]u8 = undefined;
@memset(&foo[0], 'A', foo.len);
@memcpy(&bar[0], &foo[0], bar.len);
@ -167,12 +178,14 @@ test "memcpy and memset intrinsics" {
}
test "builtin static eval" {
const x : i32 = comptime x: {break :x 1 + 2 + 3;};
const x: i32 = comptime x: {
break :x 1 + 2 + 3;
};
assert(x == comptime 6);
}
test "slicing" {
var array : [20]i32 = undefined;
var array: [20]i32 = undefined;
array[5] = 1234;
@ -187,15 +200,15 @@ test "slicing" {
if (slice_rest.len != 10) unreachable;
}
test "constant equal function pointers" {
const alias = emptyFn;
assert(comptime x: {break :x emptyFn == alias;});
assert(comptime x: {
break :x emptyFn == alias;
});
}
fn emptyFn() void {}
test "hex escape" {
assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
}
@ -238,18 +251,16 @@ test "multiline C string" {
assert(cstr.cmp(s1, s2) == 0);
}
test "type equality" {
assert(&const u8 != &u8);
}
const global_a: i32 = 1234;
const global_b: &const i32 = &global_a;
const global_c: &const f32 = @ptrCast(&const f32, global_b);
test "compile time global reinterpret" {
const d = @ptrCast(&const i32, global_c);
assert(*d == 1234);
assert(d.* == 1234);
}
test "explicit cast maybe pointers" {
@ -261,12 +272,11 @@ test "generic malloc free" {
const a = memAlloc(u8, 10) catch unreachable;
memFree(u8, a);
}
var some_mem : [100]u8 = undefined;
var some_mem: [100]u8 = undefined;
fn memAlloc(comptime T: type, n: usize) error![]T {
return @ptrCast(&T, &some_mem[0])[0..n];
}
fn memFree(comptime T: type, memory: []T) void { }
fn memFree(comptime T: type, memory: []T) void {}
test "cast undefined" {
const array: [100]u8 = undefined;
@ -275,32 +285,35 @@ test "cast undefined" {
}
fn testCastUndefined(x: []const u8) void {}
test "cast small unsigned to larger signed" {
assert(castSmallUnsignedToLargerSigned1(200) == i16(200));
assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
}
fn castSmallUnsignedToLargerSigned1(x: u8) i16 { return x; }
fn castSmallUnsignedToLargerSigned2(x: u16) i64 { return x; }
fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
return x;
}
fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
return x;
}
test "implicit cast after unreachable" {
assert(outer() == 1234);
}
fn inner() i32 { return 1234; }
fn inner() i32 {
return 1234;
}
fn outer() i64 {
return inner();
}
test "pointer dereferencing" {
var x = i32(3);
const y = &x;
*y += 1;
y.* += 1;
assert(x == 4);
assert(*y == 4);
assert(y.* == 4);
}
test "call result of if else expression" {
@ -310,9 +323,12 @@ test "call result of if else expression" {
fn f2(x: bool) []const u8 {
return (if (x) fA else fB)();
}
fn fA() []const u8 { return "a"; }
fn fB() []const u8 { return "b"; }
fn fA() []const u8 {
return "a";
}
fn fB() []const u8 {
return "b";
}
test "const expression eval handling of variables" {
var x = true;
@ -321,8 +337,6 @@ test "const expression eval handling of variables" {
}
}
test "constant enum initialization with differing sizes" {
test3_1(test3_foo);
test3_2(test3_bar);
@ -336,10 +350,17 @@ const Test3Point = struct {
x: i32,
y: i32,
};
const test3_foo = Test3Foo { .Three = Test3Point {.x = 3, .y = 4}};
const test3_bar = Test3Foo { .Two = 13};
const test3_foo = Test3Foo {
.Three = Test3Point {
.x = 3,
.y = 4,
},
};
const test3_bar = Test3Foo {
.Two = 13,
};
fn test3_1(f: &const Test3Foo) void {
switch (*f) {
switch (f.*) {
Test3Foo.Three => |pt| {
assert(pt.x == 3);
assert(pt.y == 4);
@ -348,7 +369,7 @@ fn test3_1(f: &const Test3Foo) void {
}
}
fn test3_2(f: &const Test3Foo) void {
switch (*f) {
switch (f.*) {
Test3Foo.Two => |x| {
assert(x == 13);
},
@ -356,23 +377,19 @@ fn test3_2(f: &const Test3Foo) void {
}
}
test "character literals" {
assert('\'' == single_quote);
}
const single_quote = '\'';
test "take address of parameter" {
testTakeAddressOfParameter(12.34);
}
fn testTakeAddressOfParameter(f: f32) void {
const f_ptr = &f;
assert(*f_ptr == 12.34);
assert(f_ptr.* == 12.34);
}
test "pointer comparison" {
const a = ([]const u8)("a");
const b = &a;
@ -382,23 +399,30 @@ fn ptrEql(a: &const []const u8, b: &const []const u8) bool {
return a == b;
}
test "C string concatenation" {
const a = c"OK" ++ c" IT " ++ c"WORKED";
const b = c"OK IT WORKED";
const len = cstr.len(b);
const len_with_null = len + 1;
{var i: u32 = 0; while (i < len_with_null) : (i += 1) {
assert(a[i] == b[i]);
}}
{
var i: u32 = 0;
while (i < len_with_null) : (i += 1) {
assert(a[i] == b[i]);
}
}
assert(a[len] == 0);
assert(b[len] == 0);
}
test "cast slice to u8 slice" {
assert(@sizeOf(i32) == 4);
var big_thing_array = []i32{1, 2, 3, 4};
var big_thing_array = []i32 {
1,
2,
3,
4,
};
const big_thing_slice: []i32 = big_thing_array[0..];
const bytes = ([]u8)(big_thing_slice);
assert(bytes.len == 4 * 4);
@ -421,25 +445,22 @@ test "pointer to void return type" {
}
fn testPointerToVoidReturnType() error!void {
const a = testPointerToVoidReturnType2();
return *a;
return a.*;
}
const test_pointer_to_void_return_type_x = void{};
fn testPointerToVoidReturnType2() &const void {
return &test_pointer_to_void_return_type_x;
}
test "non const ptr to aliased type" {
const int = i32;
assert(?&int == ?&i32);
}
test "array 2D const double ptr" {
const rect_2d_vertexes = [][1]f32 {
[]f32{1.0},
[]f32{2.0},
[]f32 {1.0},
[]f32 {2.0},
};
testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
}
@ -450,10 +471,21 @@ fn testArray2DConstDoublePtr(ptr: &const f32) void {
}
const Tid = builtin.TypeId;
const AStruct = struct { x: i32, };
const AnEnum = enum { One, Two, };
const AUnionEnum = union(enum) { One: i32, Two: void, };
const AUnion = union { One: void, Two: void };
const AStruct = struct {
x: i32,
};
const AnEnum = enum {
One,
Two,
};
const AUnionEnum = union(enum) {
One: i32,
Two: void,
};
const AUnion = union {
One: void,
Two: void,
};
test "@typeId" {
comptime {
@ -481,9 +513,11 @@ test "@typeId" {
assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
assert(@typeId(AUnionEnum) == Tid.Union);
assert(@typeId(AUnion) == Tid.Union);
assert(@typeId(fn()void) == Tid.Fn);
assert(@typeId(fn() void) == Tid.Fn);
assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
assert(@typeId(@typeOf(x: {break :x this;})) == Tid.Block);
assert(@typeId(@typeOf(x: {
break :x this;
})) == Tid.Block);
// TODO bound fn
// TODO arg tuple
// TODO opaque
@ -499,8 +533,7 @@ test "@canImplicitCast" {
}
test "@typeName" {
const Struct = struct {
};
const Struct = struct {};
const Union = union {
unused: u8,
};
@ -525,14 +558,19 @@ fn TypeFromFn(comptime T: type) type {
test "volatile load and store" {
var number: i32 = 1234;
const ptr = (&volatile i32)(&number);
*ptr += 1;
assert(*ptr == 1235);
ptr.* += 1;
assert(ptr.* == 1235);
}
test "slice string literal has type []const u8" {
comptime {
assert(@typeOf("aoeu"[0..]) == []const u8);
const array = []i32{1, 2, 3, 4};
const array = []i32 {
1,
2,
3,
4,
};
assert(@typeOf(array[0..]) == []const i32);
}
}
@ -544,12 +582,15 @@ const GDTEntry = struct {
field: i32,
};
var gdt = []GDTEntry {
GDTEntry {.field = 1},
GDTEntry {.field = 2},
GDTEntry {
.field = 1,
},
GDTEntry {
.field = 2,
},
};
var global_ptr = &gdt[0];
// can't really run this test but we can make sure it has no compile error
// and generates code
const vram = @intToPtr(&volatile u8, 0x20000000)[0..0x8000];
@ -584,7 +625,7 @@ test "comptime if inside runtime while which unconditionally breaks" {
}
fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
while (cond) {
if (false) { }
if (false) {}
break;
}
}
@ -607,7 +648,9 @@ fn testStructInFn() void {
kind: BlockKind,
};
var block = Block { .kind = 1234 };
var block = Block {
.kind = 1234,
};
block.kind += 1;
@ -617,7 +660,9 @@ fn testStructInFn() void {
fn fnThatClosesOverLocalConst() type {
const c = 1;
return struct {
fn g() i32 { return c; }
fn g() i32 {
return c;
}
};
}
@ -635,22 +680,29 @@ fn thisIsAColdFn() void {
@setCold(true);
}
const PackedStruct = packed struct { a: u8, b: u8, };
const PackedUnion = packed union { a: u8, b: u32, };
const PackedEnum = packed enum { A, B, };
const PackedStruct = packed struct {
a: u8,
b: u8,
};
const PackedUnion = packed union {
a: u8,
b: u32,
};
const PackedEnum = packed enum {
A,
B,
};
test "packed struct, enum, union parameters in extern function" {
testPackedStuff(
PackedStruct{.a = 1, .b = 2},
PackedUnion{.a = 1},
PackedEnum.A,
);
}
export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void {
testPackedStuff(PackedStruct {
.a = 1,
.b = 2,
}, PackedUnion {
.a = 1,
}, PackedEnum.A);
}
export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void {}
test "slicing zero length array" {
const s1 = ""[0..];
@ -661,7 +713,6 @@ test "slicing zero length array" {
assert(mem.eql(u32, s2, []u32{}));
}
const addr1 = @ptrCast(&const u8, emptyFn);
test "comptime cast fn to ptr" {
const addr2 = @ptrCast(&const u8, emptyFn);

View File

@ -8,7 +8,7 @@ test "namespace depends on compile var" {
assert(!some_namespace.a_bool);
}
}
const some_namespace = switch(builtin.os) {
const some_namespace = switch (builtin.os) {
builtin.Os.linux => @import("a.zig"),
else => @import("b.zig"),
};

View File

@ -1,7 +1,7 @@
const assert = @import("std").debug.assert;
test "nullable type" {
const x : ?bool = true;
const x: ?bool = true;
if (x) |y| {
if (y) {
@ -13,13 +13,13 @@ test "nullable type" {
unreachable;
}
const next_x : ?i32 = null;
const next_x: ?i32 = null;
const z = next_x ?? 1234;
assert(z == 1234);
const final_x : ?i32 = 13;
const final_x: ?i32 = 13;
const num = final_x ?? unreachable;
@ -30,19 +30,17 @@ test "test maybe object and get a pointer to the inner value" {
var maybe_bool: ?bool = true;
if (maybe_bool) |*b| {
*b = false;
b.* = false;
}
assert(??maybe_bool == false);
}
test "rhs maybe unwrap return" {
const x: ?bool = true;
const y = x ?? return;
}
test "maybe return" {
maybeReturnImpl();
comptime maybeReturnImpl();
@ -50,8 +48,7 @@ test "maybe return" {
fn maybeReturnImpl() void {
assert(??foo(1235));
if (foo(null) != null)
unreachable;
if (foo(null) != null) unreachable;
assert(!??foo(1234));
}
@ -60,12 +57,16 @@ fn foo(x: ?i32) ?bool {
return value > 1234;
}
test "if var maybe pointer" {
assert(shouldBeAPlus1(Particle {.a = 14, .b = 1, .c = 1, .d = 1}) == 15);
assert(shouldBeAPlus1(Particle {
.a = 14,
.b = 1,
.c = 1,
.d = 1,
}) == 15);
}
fn shouldBeAPlus1(p: &const Particle) u64 {
var maybe_particle: ?Particle = *p;
var maybe_particle: ?Particle = p.*;
if (maybe_particle) |*particle| {
particle.a += 1;
}
@ -81,7 +82,6 @@ const Particle = struct {
d: u64,
};
test "null literal outside function" {
const is_null = here_is_a_null_literal.context == null;
assert(is_null);
@ -96,7 +96,6 @@ const here_is_a_null_literal = SillyStruct {
.context = null,
};
test "test null runtime" {
testTestNullRuntime(null);
}
@ -123,8 +122,6 @@ fn bar(x: ?void) ?void {
}
}
const StructWithNullable = struct {
field: ?i32,
};

View File

@ -23,7 +23,7 @@ fn foo(c: bool, k: Num, c2: bool, b: []const u8) void {
if (c) {
const output_path = b;
if (c2) { }
if (c2) {}
a(output_path);
}

View File

@ -23,7 +23,9 @@ test "reflection: function return type, var args, and param types" {
}
}
fn dummy(a: bool, b: i32, c: f32) i32 { return 1234; }
fn dummy(a: bool, b: i32, c: f32) i32 {
return 1234;
}
fn dummy_varargs(args: ...) void {}
test "reflection: struct member types and names" {
@ -54,7 +56,6 @@ test "reflection: enum member types and names" {
assert(mem.eql(u8, @memberName(Bar, 2), "Three"));
assert(mem.eql(u8, @memberName(Bar, 3), "Four"));
}
}
test "reflection: @field" {

View File

@ -18,7 +18,11 @@ test "slice child property" {
}
test "runtime safety lets us slice from len..len" {
var an_array = []u8{1, 2, 3};
var an_array = []u8 {
1,
2,
3,
};
assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
}
@ -27,7 +31,7 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
}
test "implicitly cast array of size 0 to slice" {
var msg = []u8 {};
var msg = []u8{};
assertLenIsZero(msg);
}

View File

@ -2,9 +2,11 @@ const assert = @import("std").debug.assert;
const builtin = @import("builtin");
const StructWithNoFields = struct {
fn add(a: i32, b: i32) i32 { return a + b; }
fn add(a: i32, b: i32) i32 {
return a + b;
}
};
const empty_global_instance = StructWithNoFields {};
const empty_global_instance = StructWithNoFields{};
test "call struct static method" {
const result = StructWithNoFields.add(3, 4);
@ -34,12 +36,11 @@ test "void struct fields" {
assert(@sizeOf(VoidStructFieldsFoo) == 4);
}
const VoidStructFieldsFoo = struct {
a : void,
b : i32,
c : void,
a: void,
b: i32,
c: void,
};
test "structs" {
var foo: StructFoo = undefined;
@memset(@ptrCast(&u8, &foo), 0, @sizeOf(StructFoo));
@ -50,9 +51,9 @@ test "structs" {
assert(foo.c == 100);
}
const StructFoo = struct {
a : i32,
b : bool,
c : f32,
a: i32,
b: bool,
c: f32,
};
fn testFoo(foo: &const StructFoo) void {
assert(foo.b);
@ -61,7 +62,6 @@ fn testMutation(foo: &StructFoo) void {
foo.c = 100;
}
const Node = struct {
val: Val,
next: &Node,
@ -72,10 +72,10 @@ const Val = struct {
};
test "struct point to self" {
var root : Node = undefined;
var root: Node = undefined;
root.val.x = 1;
var node : Node = undefined;
var node: Node = undefined;
node.next = &root;
node.val.x = 2;
@ -85,8 +85,8 @@ test "struct point to self" {
}
test "struct byval assign" {
var foo1 : StructFoo = undefined;
var foo2 : StructFoo = undefined;
var foo1: StructFoo = undefined;
var foo2: StructFoo = undefined;
foo1.a = 1234;
foo2.a = 0;
@ -96,46 +96,57 @@ test "struct byval assign" {
}
fn structInitializer() void {
const val = Val { .x = 42 };
const val = Val {
.x = 42,
};
assert(val.x == 42);
}
test "fn call of struct field" {
assert(callStructField(Foo {.ptr = aFunc,}) == 13);
assert(callStructField(Foo {
.ptr = aFunc,
}) == 13);
}
const Foo = struct {
ptr: fn() i32,
};
fn aFunc() i32 { return 13; }
fn aFunc() i32 {
return 13;
}
fn callStructField(foo: &const Foo) i32 {
return foo.ptr();
}
test "store member function in variable" {
const instance = MemberFnTestFoo { .x = 1234, };
const instance = MemberFnTestFoo {
.x = 1234,
};
const memberFn = MemberFnTestFoo.member;
const result = memberFn(instance);
assert(result == 1234);
}
const MemberFnTestFoo = struct {
x: i32,
fn member(foo: &const MemberFnTestFoo) i32 { return foo.x; }
fn member(foo: &const MemberFnTestFoo) i32 {
return foo.x;
}
};
test "call member function directly" {
const instance = MemberFnTestFoo { .x = 1234, };
const instance = MemberFnTestFoo {
.x = 1234,
};
const result = MemberFnTestFoo.member(instance);
assert(result == 1234);
}
test "member functions" {
const r = MemberFnRand {.seed = 1234};
const r = MemberFnRand {
.seed = 1234,
};
assert(r.getSeed() == 1234);
}
const MemberFnRand = struct {
@ -170,17 +181,16 @@ const EmptyStruct = struct {
}
};
test "return empty struct from fn" {
_ = testReturnEmptyStructFromFn();
}
const EmptyStruct2 = struct {};
fn testReturnEmptyStructFromFn() EmptyStruct2 {
return EmptyStruct2 {};
return EmptyStruct2{};
}
test "pass slice of empty struct to fn" {
assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1);
assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2 {EmptyStruct2{}}) == 1);
}
fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
return slice.len;
@ -201,7 +211,6 @@ test "packed struct" {
assert(four == 4);
}
const BitField1 = packed struct {
a: u3,
b: u3,
@ -301,7 +310,7 @@ test "packed array 24bits" {
assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
}
var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
var bytes = []u8 {0} ** (@sizeOf(FooArray24Bits) + 1);
bytes[bytes.len - 1] = 0xaa;
const ptr = &([]FooArray24Bits)(bytes[0..bytes.len - 1])[0];
assert(ptr.a == 0);
@ -351,7 +360,7 @@ test "aligned array of packed struct" {
assert(@sizeOf(FooArrayOfAligned) == 2 * 2);
}
var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
var bytes = []u8 {0xbb} ** @sizeOf(FooArrayOfAligned);
const ptr = &([]FooArrayOfAligned)(bytes[0..bytes.len])[0];
assert(ptr.a[0].a == 0xbb);
@ -360,11 +369,15 @@ test "aligned array of packed struct" {
assert(ptr.a[1].b == 0xbb);
}
test "runtime struct initialization of bitfield" {
const s1 = Nibbles { .x = x1, .y = x1 };
const s2 = Nibbles { .x = u4(x2), .y = u4(x2) };
const s1 = Nibbles {
.x = x1,
.y = x1,
};
const s2 = Nibbles {
.x = u4(x2),
.y = u4(x2),
};
assert(s1.x == x1);
assert(s1.y == x1);
@ -394,7 +407,7 @@ test "native bit field understands endianness" {
var all: u64 = 0x7765443322221111;
var bytes: [8]u8 = undefined;
@memcpy(&bytes[0], @ptrCast(&u8, &all), 8);
var bitfields = *@ptrCast(&Bitfields, &bytes[0]);
var bitfields = @ptrCast(&Bitfields, &bytes[0]).*;
assert(bitfields.f1 == 0x1111);
assert(bitfields.f2 == 0x2222);

View File

@ -19,4 +19,3 @@ pub const Node = struct {
pub const NodeLineComment = struct {
base: Node,
};

View File

@ -6,7 +6,7 @@ const Node = struct {
};
test "struct contains slice of itself" {
var other_nodes = []Node{
var other_nodes = []Node {
Node {
.payload = 31,
.children = []Node{},

View File

@ -6,7 +6,10 @@ test "switch with numbers" {
fn testSwitchWithNumbers(x: u32) void {
const result = switch (x) {
1, 2, 3, 4 ... 8 => false,
1,
2,
3,
4 ... 8 => false,
13 => true,
else => false,
};
@ -34,8 +37,10 @@ test "implicit comptime switch" {
const result = switch (x) {
3 => 10,
4 => 11,
5, 6 => 12,
7, 8 => 13,
5,
6 => 12,
7,
8 => 13,
else => 14,
};
@ -61,7 +66,6 @@ fn nonConstSwitchOnEnum(fruit: Fruit) void {
}
}
test "switch statement" {
nonConstSwitch(SwitchStatmentFoo.C);
}
@ -81,11 +85,16 @@ const SwitchStatmentFoo = enum {
D,
};
test "switch prong with variable" {
switchProngWithVarFn(SwitchProngWithVarEnum { .One = 13});
switchProngWithVarFn(SwitchProngWithVarEnum { .Two = 13.0});
switchProngWithVarFn(SwitchProngWithVarEnum { .Meh = {}});
switchProngWithVarFn(SwitchProngWithVarEnum {
.One = 13,
});
switchProngWithVarFn(SwitchProngWithVarEnum {
.Two = 13.0,
});
switchProngWithVarFn(SwitchProngWithVarEnum {
.Meh = {},
});
}
const SwitchProngWithVarEnum = union(enum) {
One: i32,
@ -93,7 +102,7 @@ const SwitchProngWithVarEnum = union(enum) {
Meh: void,
};
fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) void {
switch(*a) {
switch (a.*) {
SwitchProngWithVarEnum.One => |x| {
assert(x == 13);
},
@ -112,9 +121,11 @@ test "switch on enum using pointer capture" {
}
fn testSwitchEnumPtrCapture() void {
var value = SwitchProngWithVarEnum { .One = 1234 };
var value = SwitchProngWithVarEnum {
.One = 1234,
};
switch (value) {
SwitchProngWithVarEnum.One => |*x| *x += 1,
SwitchProngWithVarEnum.One => |*x| x.* += 1,
else => unreachable,
}
switch (value) {
@ -125,8 +136,12 @@ fn testSwitchEnumPtrCapture() void {
test "switch with multiple expressions" {
const x = switch (returnsFive()) {
1, 2, 3 => 1,
4, 5, 6 => 2,
1,
2,
3 => 1,
4,
5,
6 => 2,
else => i32(3),
};
assert(x == 2);
@ -135,14 +150,15 @@ fn returnsFive() i32 {
return 5;
}
const Number = union(enum) {
One: u64,
Two: u8,
Three: f32,
};
const number = Number { .Three = 1.23 };
const number = Number {
.Three = 1.23,
};
fn returnsFalse() bool {
switch (number) {
@ -198,7 +214,8 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {
return switch (x) {
0 ... 100 => u8(0),
101 ... 200 => 1,
201, 203 => 2,
201,
203 => 2,
202 => 4,
204 ... 255 => 3,
};

View File

@ -14,14 +14,18 @@ const FormValue = union(enum) {
fn doThing(form_id: u64) error!FormValue {
return switch (form_id) {
17 => FormValue { .Address = try readOnce() },
17 => FormValue {
.Address = try readOnce(),
},
else => error.InvalidDebugInfo,
};
}
test "switch prong returns error enum" {
switch (doThing(17) catch unreachable) {
FormValue.Address => |payload| { assert(payload == 1); },
FormValue.Address => |payload| {
assert(payload == 1);
},
else => unreachable,
}
assert(read_count == 1);

View File

@ -7,8 +7,12 @@ const FormValue = union(enum) {
fn foo(id: u64) !FormValue {
return switch (id) {
2 => FormValue { .Two = true },
1 => FormValue { .One = {} },
2 => FormValue {
.Two = true,
},
1 => FormValue {
.One = {},
},
else => return error.Whatever,
};
}

View File

@ -3,14 +3,12 @@ const assert = @import("std").debug.assert;
test "try on error union" {
tryOnErrorUnionImpl();
comptime tryOnErrorUnionImpl();
}
fn tryOnErrorUnionImpl() void {
const x = if (returnsTen()) |val|
val + 1
else |err| switch (err) {
error.ItBroke, error.NoMem => 1,
const x = if (returnsTen()) |val| val + 1 else |err| switch (err) {
error.ItBroke,
error.NoMem => 1,
error.CrappedOut => i32(2),
else => unreachable,
};

View File

@ -63,6 +63,6 @@ test "assign undefined to struct with method" {
}
test "type name of undefined" {
const x = undefined;
assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
const x = undefined;
assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
}

View File

@ -10,38 +10,41 @@ const Agg = struct {
val2: Value,
};
const v1 = Value { .Int = 1234 };
const v2 = Value { .Array = []u8{3} ** 9 };
const v1 = Value{ .Int = 1234 };
const v2 = Value{ .Array = []u8{3} ** 9 };
const err = (error!Agg)(Agg {
const err = (error!Agg)(Agg{
.val1 = v1,
.val2 = v2,
});
const array = []Value { v1, v2, v1, v2};
const array = []Value{
v1,
v2,
v1,
v2,
};
test "unions embedded in aggregate types" {
switch (array[1]) {
Value.Array => |arr| assert(arr[4] == 3),
else => unreachable,
}
switch((err catch unreachable).val1) {
switch ((err catch unreachable).val1) {
Value.Int => |x| assert(x == 1234),
else => unreachable,
}
}
const Foo = union {
float: f64,
int: i32,
};
test "basic unions" {
var foo = Foo { .int = 1 };
var foo = Foo{ .int = 1 };
assert(foo.int == 1);
foo = Foo {.float = 12.34};
foo = Foo{ .float = 12.34 };
assert(foo.float == 12.34);
}
@ -56,11 +59,11 @@ test "init union with runtime value" {
}
fn setFloat(foo: &Foo, x: f64) void {
*foo = Foo { .float = x };
foo.* = Foo{ .float = x };
}
fn setInt(foo: &Foo, x: i32) void {
*foo = Foo { .int = x };
foo.* = Foo{ .int = x };
}
const FooExtern = extern union {
@ -69,13 +72,12 @@ const FooExtern = extern union {
};
test "basic extern unions" {
var foo = FooExtern { .int = 1 };
var foo = FooExtern{ .int = 1 };
assert(foo.int == 1);
foo.float = 12.34;
assert(foo.float == 12.34);
}
const Letter = enum {
A,
B,
@ -93,12 +95,12 @@ test "union with specified enum tag" {
}
fn doTest() void {
assert(bar(Payload {.A = 1234}) == -10);
assert(bar(Payload{ .A = 1234 }) == -10);
}
fn bar(value: &const Payload) i32 {
assert(Letter(*value) == Letter.A);
return switch (*value) {
assert(Letter(value.*) == Letter.A);
return switch (value.*) {
Payload.A => |x| return x - 1244,
Payload.B => |x| if (x == 12.34) i32(20) else 21,
Payload.C => |x| if (x) i32(30) else 31,
@ -131,13 +133,13 @@ const MultipleChoice2 = union(enum(u32)) {
test "union(enum(u32)) with specified and unspecified tag values" {
comptime assert(@TagType(@TagType(MultipleChoice2)) == u32);
testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 {.C = 123});
comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2 { .C = 123} );
testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
}
fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) void {
assert(u32(@TagType(MultipleChoice2)(*x)) == 60);
assert(1123 == switch (*x) {
assert(u32(@TagType(MultipleChoice2)(x.*)) == 60);
assert(1123 == switch (x.*) {
MultipleChoice2.A => 1,
MultipleChoice2.B => 2,
MultipleChoice2.C => |v| i32(1000) + v,
@ -150,10 +152,9 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: &const MultipleChoice2) void
});
}
const ExternPtrOrInt = extern union {
ptr: &u8,
int: u64
int: u64,
};
test "extern union size" {
comptime assert(@sizeOf(ExternPtrOrInt) == 8);
@ -161,7 +162,7 @@ test "extern union size" {
const PackedPtrOrInt = packed union {
ptr: &u8,
int: u64
int: u64,
};
test "extern union size" {
comptime assert(@sizeOf(PackedPtrOrInt) == 8);
@ -174,8 +175,16 @@ test "union with only 1 field which is void should be zero bits" {
comptime assert(@sizeOf(ZeroBits) == 0);
}
const TheTag = enum {A, B, C};
const TheUnion = union(TheTag) { A: i32, B: i32, C: i32 };
const TheTag = enum {
A,
B,
C,
};
const TheUnion = union(TheTag) {
A: i32,
B: i32,
C: i32,
};
test "union field access gives the enum values" {
assert(TheUnion.A == TheTag.A);
assert(TheUnion.B == TheTag.B);
@ -183,20 +192,28 @@ test "union field access gives the enum values" {
}
test "cast union to tag type of union" {
testCastUnionToTagType(TheUnion {.B = 1234});
comptime testCastUnionToTagType(TheUnion {.B = 1234});
testCastUnionToTagType(TheUnion{ .B = 1234 });
comptime testCastUnionToTagType(TheUnion{ .B = 1234 });
}
fn testCastUnionToTagType(x: &const TheUnion) void {
assert(TheTag(*x) == TheTag.B);
assert(TheTag(x.*) == TheTag.B);
}
test "cast tag type of union to union" {
var x: Value2 = Letter2.B;
assert(Letter2(x) == Letter2.B);
}
const Letter2 = enum { A, B, C };
const Value2 = union(Letter2) { A: i32, B, C, };
const Letter2 = enum {
A,
B,
C,
};
const Value2 = union(Letter2) {
A: i32,
B,
C,
};
test "implicit cast union to its tag type" {
var x: Value2 = Letter2.B;
@ -217,19 +234,16 @@ const TheUnion2 = union(enum) {
};
fn assertIsTheUnion2Item1(value: &const TheUnion2) void {
assert(*value == TheUnion2.Item1);
assert(value.* == TheUnion2.Item1);
}
pub const PackThis = union(enum) {
Invalid: bool,
StringLiteral: u2,
};
test "constant packed union" {
testConstPackedUnion([]PackThis {
PackThis { .StringLiteral = 1 },
});
testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }});
}
fn testConstPackedUnion(expected_tokens: []const PackThis) void {
@ -242,7 +256,7 @@ test "switch on union with only 1 field" {
switch (r) {
PartialInst.Compiled => {
var z: PartialInstWithPayload = undefined;
z = PartialInstWithPayload { .Compiled = 1234 };
z = PartialInstWithPayload{ .Compiled = 1234 };
switch (z) {
PartialInstWithPayload.Compiled => |x| {
assert(x == 1234);
@ -261,4 +275,3 @@ const PartialInst = union(enum) {
const PartialInstWithPayload = union(enum) {
Compiled: i32,
};

View File

@ -2,9 +2,12 @@ const assert = @import("std").debug.assert;
fn add(args: ...) i32 {
var sum = i32(0);
{comptime var i: usize = 0; inline while (i < args.len) : (i += 1) {
sum += args[i];
}}
{
comptime var i: usize = 0;
inline while (i < args.len) : (i += 1) {
sum += args[i];
}
}
return sum;
}
@ -55,18 +58,23 @@ fn extraFn(extra: u32, args: ...) usize {
return args.len;
}
const foos = []fn(...) bool {
foo1,
foo2,
};
const foos = []fn(...) bool { foo1, foo2 };
fn foo1(args: ...) bool { return true; }
fn foo2(args: ...) bool { return false; }
fn foo1(args: ...) bool {
return true;
}
fn foo2(args: ...) bool {
return false;
}
test "array of var args functions" {
assert(foos[0]());
assert(!foos[1]());
}
test "pass array and slice of same array to var args should have same pointers" {
const array = "hi";
const slice: []const u8 = array;
@ -79,7 +87,6 @@ fn assertSlicePtrsEql(args: ...) void {
assert(s1.ptr == s2.ptr);
}
test "pass zero length array to var args param" {
doNothingWithFirstArg("");
}

View File

@ -1,7 +1,7 @@
const assert = @import("std").debug.assert;
test "while loop" {
var i : i32 = 0;
var i: i32 = 0;
while (i < 4) {
i += 1;
}
@ -35,7 +35,7 @@ test "continue and break" {
}
var continue_and_break_counter: i32 = 0;
fn runContinueAndBreakTest() void {
var i : i32 = 0;
var i: i32 = 0;
while (true) {
continue_and_break_counter += 2;
i += 1;
@ -58,10 +58,13 @@ fn returnWithImplicitCastFromWhileLoopTest() error!void {
test "while with continue expression" {
var sum: i32 = 0;
{var i: i32 = 0; while (i < 10) : (i += 1) {
if (i == 5) continue;
sum += i;
}}
{
var i: i32 = 0;
while (i < 10) : (i += 1) {
if (i == 5) continue;
sum += i;
}
}
assert(sum == 40);
}
@ -117,17 +120,13 @@ test "while with error union condition" {
var numbers_left: i32 = undefined;
fn getNumberOrErr() error!i32 {
return if (numbers_left == 0)
error.OutOfNumbers
else x: {
return if (numbers_left == 0) error.OutOfNumbers else x: {
numbers_left -= 1;
break :x numbers_left;
};
}
fn getNumberOrNull() ?i32 {
return if (numbers_left == 0)
null
else x: {
return if (numbers_left == 0) null else x: {
numbers_left -= 1;
break :x numbers_left;
};
@ -136,42 +135,48 @@ fn getNumberOrNull() ?i32 {
test "while on nullable with else result follow else prong" {
const result = while (returnNull()) |value| {
break value;
} else i32(2);
} else
i32(2);
assert(result == 2);
}
test "while on nullable with else result follow break prong" {
const result = while (returnMaybe(10)) |value| {
break value;
} else i32(2);
} else
i32(2);
assert(result == 10);
}
test "while on error union with else result follow else prong" {
const result = while (returnError()) |value| {
break value;
} else |err| i32(2);
} else|err|
i32(2);
assert(result == 2);
}
test "while on error union with else result follow break prong" {
const result = while (returnSuccess(10)) |value| {
break value;
} else |err| i32(2);
} else|err|
i32(2);
assert(result == 10);
}
test "while on bool with else result follow else prong" {
const result = while (returnFalse()) {
break i32(10);
} else i32(2);
} else
i32(2);
assert(result == 2);
}
test "while on bool with else result follow break prong" {
const result = while (returnTrue()) {
break i32(10);
} else i32(2);
} else
i32(2);
assert(result == 10);
}
@ -202,9 +207,21 @@ fn testContinueOuter() void {
}
}
fn returnNull() ?i32 { return null; }
fn returnMaybe(x: i32) ?i32 { return x; }
fn returnError() error!i32 { return error.YouWantedAnError; }
fn returnSuccess(x: i32) error!i32 { return x; }
fn returnFalse() bool { return false; }
fn returnTrue() bool { return true; }
fn returnNull() ?i32 {
return null;
}
fn returnMaybe(x: i32) ?i32 {
return x;
}
fn returnError() error!i32 {
return error.YouWantedAnError;
}
fn returnSuccess(x: i32) error!i32 {
return x;
}
fn returnFalse() bool {
return false;
}
fn returnTrue() bool {
return true;
}