backport copy elision changes
This commit contains everything from the copy-elision-2 branch that does not have to do with copy elision directly, but is generally useful for master branch. * All const values know their parents, when applicable, not just structs and unions. * Null pointers in const values are represented explicitly, rather than as a HardCodedAddr value of 0. * Rename "maybe" to "optional" in various code locations. * Separate DeclVarSrc and DeclVarGen * Separate PtrCastSrc and PtrCastGen * Separate CmpxchgSrc and CmpxchgGen * Represent optional error set as an integer, using the 0 value. In a const value, it uses nullptr. * Introduce type_has_one_possible_value and use it where applicable. * Fix debug builds not setting memory to 0xaa when storing undefined. * Separate the type of a variable from the const value of a variable. * Use copy_const_val where appropriate. * Rearrange structs to pack data more efficiently. * Move test/cases/* to test/behavior/* * Use `std.debug.assertOrPanic` in behavior tests instead of `std.debug.assert`. * Fix outdated slice syntax in docs.
This commit is contained in:
@@ -104,7 +104,7 @@ pub fn build(b: *Builder) !void {
|
||||
}
|
||||
const modes = chosen_modes[0..chosen_mode_index];
|
||||
|
||||
test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes));
|
||||
test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes));
|
||||
|
||||
test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes));
|
||||
|
||||
@@ -299,8 +299,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
|
||||
} else if (exe.target.isFreeBSD()) {
|
||||
try addCxxKnownPath(b, ctx, exe, "libc++.a", null);
|
||||
exe.linkSystemLibrary("pthread");
|
||||
}
|
||||
else if (exe.target.isDarwin()) {
|
||||
} else if (exe.target.isDarwin()) {
|
||||
if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
|
||||
// Compiler is GCC.
|
||||
try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
|
||||
|
||||
@@ -4327,7 +4327,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
|
||||
<p>
|
||||
For example, if we were to introduce another function to the above snippet:
|
||||
</p>
|
||||
{#code_begin|test_err|unable to evaluate constant expression#}
|
||||
{#code_begin|test_err|values of type 'type' must be comptime known#}
|
||||
fn max(comptime T: type, a: T, b: T) T {
|
||||
return if (a > b) a else b;
|
||||
}
|
||||
@@ -5905,13 +5905,13 @@ fn add(a: i32, b: i32) i32 { return a + b; }
|
||||
This function is a low level intrinsic with no safety mechanisms. Most code
|
||||
should not use this function, instead using something like this:
|
||||
</p>
|
||||
<pre>{#syntax#}for (source[0...byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>
|
||||
<pre>{#syntax#}for (source[0..byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>
|
||||
<p>
|
||||
The optimizer is intelligent enough to turn the above snippet into a memcpy.
|
||||
</p>
|
||||
<p>There is also a standard library function for this:</p>
|
||||
<pre>{#syntax#}const mem = @import("std").mem;
|
||||
mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
|
||||
mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#}</pre>
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@memset#}
|
||||
@@ -5923,7 +5923,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
|
||||
This function is a low level intrinsic with no safety mechanisms. Most
|
||||
code should not use this function, instead using something like this:
|
||||
</p>
|
||||
<pre>{#syntax#}for (dest[0...byte_count]) |*b| b.* = c;{#endsyntax#}</pre>
|
||||
<pre>{#syntax#}for (dest[0..byte_count]) |*b| b.* = c;{#endsyntax#}</pre>
|
||||
<p>
|
||||
The optimizer is intelligent enough to turn the above snippet into a memset.
|
||||
</p>
|
||||
@@ -6592,9 +6592,10 @@ pub const TypeInfo = union(TypeId) {
|
||||
{#header_close#}
|
||||
|
||||
{#header_open|@typeName#}
|
||||
<pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>
|
||||
<pre>{#syntax#}@typeName(T: type) [N]u8{#endsyntax#}</pre>
|
||||
<p>
|
||||
This function returns the string representation of a type.
|
||||
This function returns the string representation of a type, as
|
||||
an array. It is equivalent to a string literal of the type name.
|
||||
</p>
|
||||
|
||||
{#header_close#}
|
||||
|
||||
@@ -56,9 +56,6 @@ struct IrExecutable {
|
||||
size_t next_debug_id;
|
||||
size_t *backward_branch_count;
|
||||
size_t backward_branch_quota;
|
||||
bool invalid;
|
||||
bool is_inline;
|
||||
bool is_generic_instantiation;
|
||||
ZigFn *fn_entry;
|
||||
Buf *c_import_buf;
|
||||
AstNode *source_node;
|
||||
@@ -78,6 +75,10 @@ struct IrExecutable {
|
||||
IrBasicBlock *coro_suspend_block;
|
||||
IrBasicBlock *coro_final_cleanup_block;
|
||||
ZigVar *coro_allocator_var;
|
||||
|
||||
bool invalid;
|
||||
bool is_inline;
|
||||
bool is_generic_instantiation;
|
||||
};
|
||||
|
||||
enum OutType {
|
||||
@@ -90,6 +91,9 @@ enum OutType {
|
||||
enum ConstParentId {
|
||||
ConstParentIdNone,
|
||||
ConstParentIdStruct,
|
||||
ConstParentIdErrUnionCode,
|
||||
ConstParentIdErrUnionPayload,
|
||||
ConstParentIdOptionalPayload,
|
||||
ConstParentIdArray,
|
||||
ConstParentIdUnion,
|
||||
ConstParentIdScalar,
|
||||
@@ -107,6 +111,15 @@ struct ConstParent {
|
||||
ConstExprValue *struct_val;
|
||||
size_t field_index;
|
||||
} p_struct;
|
||||
struct {
|
||||
ConstExprValue *err_union_val;
|
||||
} p_err_union_code;
|
||||
struct {
|
||||
ConstExprValue *err_union_val;
|
||||
} p_err_union_payload;
|
||||
struct {
|
||||
ConstExprValue *optional_val;
|
||||
} p_optional_payload;
|
||||
struct {
|
||||
ConstExprValue *union_val;
|
||||
} p_union;
|
||||
@@ -118,13 +131,11 @@ struct ConstParent {
|
||||
|
||||
struct ConstStructValue {
|
||||
ConstExprValue *fields;
|
||||
ConstParent parent;
|
||||
};
|
||||
|
||||
struct ConstUnionValue {
|
||||
BigInt tag;
|
||||
ConstExprValue *payload;
|
||||
ConstParent parent;
|
||||
};
|
||||
|
||||
enum ConstArraySpecial {
|
||||
@@ -138,7 +149,6 @@ struct ConstArrayValue {
|
||||
union {
|
||||
struct {
|
||||
ConstExprValue *elements;
|
||||
ConstParent parent;
|
||||
} s_none;
|
||||
Buf *s_buf;
|
||||
} data;
|
||||
@@ -153,19 +163,29 @@ enum ConstPtrSpecial {
|
||||
ConstPtrSpecialBaseArray,
|
||||
// The pointer points to a field in an underlying struct.
|
||||
ConstPtrSpecialBaseStruct,
|
||||
// The pointer points to the error set field of an error union
|
||||
ConstPtrSpecialBaseErrorUnionCode,
|
||||
// The pointer points to the payload field of an error union
|
||||
ConstPtrSpecialBaseErrorUnionPayload,
|
||||
// The pointer points to the payload field of an optional
|
||||
ConstPtrSpecialBaseOptionalPayload,
|
||||
// This means that we did a compile-time pointer reinterpret and we cannot
|
||||
// understand the value of pointee at compile time. However, we will still
|
||||
// emit a binary with a compile time known address.
|
||||
// In this case index is the numeric address value.
|
||||
// We also use this for null pointer. We need the data layout for ConstCastOnly == true
|
||||
// types to be the same, so all optionals of pointer types use x_ptr
|
||||
// instead of x_optional
|
||||
ConstPtrSpecialHardCodedAddr,
|
||||
// This means that the pointer represents memory of assigning to _.
|
||||
// That is, storing discards the data, and loading is invalid.
|
||||
ConstPtrSpecialDiscard,
|
||||
// This is actually a function.
|
||||
ConstPtrSpecialFunction,
|
||||
// This means the pointer is null. This is only allowed when the type is ?*T.
|
||||
// We use this instead of ConstPtrSpecialHardCodedAddr because often we check
|
||||
// for that value to avoid doing comptime work.
|
||||
// We need the data layout for ConstCastOnly == true
|
||||
// types to be the same, so all optionals of pointer types use x_ptr
|
||||
// instead of x_optional.
|
||||
ConstPtrSpecialNull,
|
||||
};
|
||||
|
||||
enum ConstPtrMut {
|
||||
@@ -199,6 +219,15 @@ struct ConstPtrValue {
|
||||
ConstExprValue *struct_val;
|
||||
size_t field_index;
|
||||
} base_struct;
|
||||
struct {
|
||||
ConstExprValue *err_union_val;
|
||||
} base_err_union_code;
|
||||
struct {
|
||||
ConstExprValue *err_union_val;
|
||||
} base_err_union_payload;
|
||||
struct {
|
||||
ConstExprValue *optional_val;
|
||||
} base_optional_payload;
|
||||
struct {
|
||||
uint64_t addr;
|
||||
} hard_coded_addr;
|
||||
@@ -209,7 +238,7 @@ struct ConstPtrValue {
|
||||
};
|
||||
|
||||
struct ConstErrValue {
|
||||
ErrorTableEntry *err;
|
||||
ConstExprValue *error_set;
|
||||
ConstExprValue *payload;
|
||||
};
|
||||
|
||||
@@ -265,6 +294,7 @@ struct ConstGlobalRefs {
|
||||
struct ConstExprValue {
|
||||
ZigType *type;
|
||||
ConstValSpecial special;
|
||||
ConstParent parent;
|
||||
ConstGlobalRefs *global_refs;
|
||||
|
||||
union {
|
||||
@@ -433,7 +463,7 @@ enum NodeType {
|
||||
NodeTypeArrayType,
|
||||
NodeTypeErrorType,
|
||||
NodeTypeIfErrorExpr,
|
||||
NodeTypeTestExpr,
|
||||
NodeTypeIfOptional,
|
||||
NodeTypeErrorSetDecl,
|
||||
NodeTypeCancel,
|
||||
NodeTypeResume,
|
||||
@@ -677,7 +707,7 @@ struct AstNodeUse {
|
||||
AstNode *expr;
|
||||
|
||||
TldResolution resolution;
|
||||
IrInstruction *value;
|
||||
ConstExprValue *value;
|
||||
};
|
||||
|
||||
struct AstNodeIfBoolExpr {
|
||||
@@ -1610,7 +1640,7 @@ struct CodeGen {
|
||||
HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
|
||||
HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
|
||||
HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
|
||||
HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
|
||||
HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
|
||||
HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
|
||||
HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
|
||||
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
|
||||
@@ -1802,10 +1832,9 @@ enum VarLinkage {
|
||||
|
||||
struct ZigVar {
|
||||
Buf name;
|
||||
ConstExprValue *value;
|
||||
ConstExprValue *const_value;
|
||||
ZigType *var_type;
|
||||
LLVMValueRef value_ref;
|
||||
bool src_is_const;
|
||||
bool gen_is_const;
|
||||
IrInstruction *is_comptime;
|
||||
// which node is the declaration of the variable
|
||||
AstNode *decl_node;
|
||||
@@ -1815,17 +1844,21 @@ struct ZigVar {
|
||||
Scope *parent_scope;
|
||||
Scope *child_scope;
|
||||
LLVMValueRef param_value_ref;
|
||||
bool shadowable;
|
||||
size_t mem_slot_index;
|
||||
IrExecutable *owner_exec;
|
||||
size_t ref_count;
|
||||
VarLinkage linkage;
|
||||
uint32_t align_bytes;
|
||||
|
||||
// In an inline loop, multiple variables may be created,
|
||||
// In this case, a reference to a variable should follow
|
||||
// this pointer to the redefined variable.
|
||||
ZigVar *next_var;
|
||||
|
||||
uint32_t align_bytes;
|
||||
VarLinkage linkage;
|
||||
|
||||
bool shadowable;
|
||||
bool src_is_const;
|
||||
bool gen_is_const;
|
||||
};
|
||||
|
||||
struct ErrorTableEntry {
|
||||
@@ -1891,10 +1924,11 @@ struct ScopeBlock {
|
||||
ZigList<IrInstruction *> *incoming_values;
|
||||
ZigList<IrBasicBlock *> *incoming_blocks;
|
||||
|
||||
bool safety_off;
|
||||
AstNode *safety_set_node;
|
||||
bool fast_math_on;
|
||||
AstNode *fast_math_set_node;
|
||||
|
||||
bool safety_off;
|
||||
bool fast_math_on;
|
||||
};
|
||||
|
||||
// This scope is created from every defer expression.
|
||||
@@ -2030,8 +2064,19 @@ struct IrBasicBlock {
|
||||
IrInstruction *must_be_comptime_source_instr;
|
||||
};
|
||||
|
||||
// These instructions are in transition to having "pass 1" instructions
|
||||
// and "pass 2" instructions. The pass 1 instructions are suffixed with Src
|
||||
// and pass 2 are suffixed with Gen.
|
||||
// Once all instructions are separated in this way, they'll have different
|
||||
// base types for better type safety.
|
||||
// Src instructions are generated by ir_gen_* functions in ir.cpp from AST.
|
||||
// ir_analyze_* functions consume Src instructions and produce Gen instructions.
|
||||
// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
|
||||
// Src instructions do not have type information; Gen instructions do.
|
||||
enum IrInstructionId {
|
||||
IrInstructionIdInvalid,
|
||||
IrInstructionIdDeclVarSrc,
|
||||
IrInstructionIdDeclVarGen,
|
||||
IrInstructionIdBr,
|
||||
IrInstructionIdCondBr,
|
||||
IrInstructionIdSwitchBr,
|
||||
@@ -2040,7 +2085,6 @@ enum IrInstructionId {
|
||||
IrInstructionIdPhi,
|
||||
IrInstructionIdUnOp,
|
||||
IrInstructionIdBinOp,
|
||||
IrInstructionIdDeclVar,
|
||||
IrInstructionIdLoadPtr,
|
||||
IrInstructionIdStorePtr,
|
||||
IrInstructionIdFieldPtr,
|
||||
@@ -2069,7 +2113,7 @@ enum IrInstructionId {
|
||||
IrInstructionIdAsm,
|
||||
IrInstructionIdSizeOf,
|
||||
IrInstructionIdTestNonNull,
|
||||
IrInstructionIdUnwrapOptional,
|
||||
IrInstructionIdOptionalUnwrapPtr,
|
||||
IrInstructionIdOptionalWrap,
|
||||
IrInstructionIdUnionTag,
|
||||
IrInstructionIdClz,
|
||||
@@ -2085,7 +2129,8 @@ enum IrInstructionId {
|
||||
IrInstructionIdCompileLog,
|
||||
IrInstructionIdErrName,
|
||||
IrInstructionIdEmbedFile,
|
||||
IrInstructionIdCmpxchg,
|
||||
IrInstructionIdCmpxchgSrc,
|
||||
IrInstructionIdCmpxchgGen,
|
||||
IrInstructionIdFence,
|
||||
IrInstructionIdTruncate,
|
||||
IrInstructionIdIntCast,
|
||||
@@ -2114,7 +2159,8 @@ enum IrInstructionId {
|
||||
IrInstructionIdErrWrapPayload,
|
||||
IrInstructionIdFnProto,
|
||||
IrInstructionIdTestComptime,
|
||||
IrInstructionIdPtrCast,
|
||||
IrInstructionIdPtrCastSrc,
|
||||
IrInstructionIdPtrCastGen,
|
||||
IrInstructionIdBitCast,
|
||||
IrInstructionIdWidenOrShorten,
|
||||
IrInstructionIdIntToPtr,
|
||||
@@ -2194,6 +2240,22 @@ struct IrInstruction {
|
||||
bool is_gen;
|
||||
};
|
||||
|
||||
struct IrInstructionDeclVarSrc {
|
||||
IrInstruction base;
|
||||
|
||||
ZigVar *var;
|
||||
IrInstruction *var_type;
|
||||
IrInstruction *align_value;
|
||||
IrInstruction *init_value;
|
||||
};
|
||||
|
||||
struct IrInstructionDeclVarGen {
|
||||
IrInstruction base;
|
||||
|
||||
ZigVar *var;
|
||||
IrInstruction *init_value;
|
||||
};
|
||||
|
||||
struct IrInstructionCondBr {
|
||||
IrInstruction base;
|
||||
|
||||
@@ -2302,20 +2364,11 @@ struct IrInstructionBinOp {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *op1;
|
||||
IrBinOp op_id;
|
||||
IrInstruction *op2;
|
||||
IrBinOp op_id;
|
||||
bool safety_check_on;
|
||||
};
|
||||
|
||||
struct IrInstructionDeclVar {
|
||||
IrInstruction base;
|
||||
|
||||
ZigVar *var;
|
||||
IrInstruction *var_type;
|
||||
IrInstruction *align_value;
|
||||
IrInstruction *init_value;
|
||||
};
|
||||
|
||||
struct IrInstructionLoadPtr {
|
||||
IrInstruction base;
|
||||
|
||||
@@ -2335,7 +2388,6 @@ struct IrInstructionFieldPtr {
|
||||
IrInstruction *container_ptr;
|
||||
Buf *field_name_buffer;
|
||||
IrInstruction *field_name_expr;
|
||||
bool is_const;
|
||||
};
|
||||
|
||||
struct IrInstructionStructFieldPtr {
|
||||
@@ -2378,13 +2430,13 @@ struct IrInstructionCall {
|
||||
ZigFn *fn_entry;
|
||||
size_t arg_count;
|
||||
IrInstruction **args;
|
||||
bool is_comptime;
|
||||
LLVMValueRef tmp_ptr;
|
||||
FnInline fn_inline;
|
||||
bool is_async;
|
||||
|
||||
IrInstruction *async_allocator;
|
||||
IrInstruction *new_stack;
|
||||
FnInline fn_inline;
|
||||
bool is_async;
|
||||
bool is_comptime;
|
||||
};
|
||||
|
||||
struct IrInstructionConst {
|
||||
@@ -2527,9 +2579,9 @@ struct IrInstructionSliceType {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *align_value;
|
||||
IrInstruction *child_type;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
IrInstruction *child_type;
|
||||
};
|
||||
|
||||
struct IrInstructionAsm {
|
||||
@@ -2557,10 +2609,12 @@ struct IrInstructionTestNonNull {
|
||||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct IrInstructionUnwrapOptional {
|
||||
// Takes a pointer to an optional value, returns a pointer
|
||||
// to the payload.
|
||||
struct IrInstructionOptionalUnwrapPtr {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *value;
|
||||
IrInstruction *base_ptr;
|
||||
bool safety_check_on;
|
||||
};
|
||||
|
||||
@@ -2651,7 +2705,7 @@ struct IrInstructionEmbedFile {
|
||||
IrInstruction *name;
|
||||
};
|
||||
|
||||
struct IrInstructionCmpxchg {
|
||||
struct IrInstructionCmpxchgSrc {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *type_value;
|
||||
@@ -2661,14 +2715,19 @@ struct IrInstructionCmpxchg {
|
||||
IrInstruction *success_order_value;
|
||||
IrInstruction *failure_order_value;
|
||||
|
||||
// if this instruction gets to runtime then we know these values:
|
||||
ZigType *type;
|
||||
bool is_weak;
|
||||
};
|
||||
|
||||
struct IrInstructionCmpxchgGen {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *ptr;
|
||||
IrInstruction *cmp_value;
|
||||
IrInstruction *new_value;
|
||||
LLVMValueRef tmp_ptr;
|
||||
AtomicOrder success_order;
|
||||
AtomicOrder failure_order;
|
||||
|
||||
bool is_weak;
|
||||
|
||||
LLVMValueRef tmp_ptr;
|
||||
};
|
||||
|
||||
struct IrInstructionFence {
|
||||
@@ -2851,7 +2910,7 @@ struct IrInstructionTestErr {
|
||||
struct IrInstructionUnwrapErrCode {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *value;
|
||||
IrInstruction *err_union;
|
||||
};
|
||||
|
||||
struct IrInstructionUnwrapErrPayload {
|
||||
@@ -2899,13 +2958,19 @@ struct IrInstructionTestComptime {
|
||||
IrInstruction *value;
|
||||
};
|
||||
|
||||
struct IrInstructionPtrCast {
|
||||
struct IrInstructionPtrCastSrc {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *dest_type;
|
||||
IrInstruction *ptr;
|
||||
};
|
||||
|
||||
struct IrInstructionPtrCastGen {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *ptr;
|
||||
};
|
||||
|
||||
struct IrInstructionBitCast {
|
||||
IrInstruction base;
|
||||
|
||||
|
||||
297
src/analyze.cpp
297
src/analyze.cpp
@@ -570,7 +570,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
|
||||
if (child_type->zero_bits) {
|
||||
entry->type_ref = LLVMInt1Type();
|
||||
entry->di_type = g->builtin_types.entry_bool->di_type;
|
||||
} else if (type_is_codegen_pointer(child_type)) {
|
||||
} else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
|
||||
assert(child_type->di_type);
|
||||
// this is an optimization but also is necessary for calling C
|
||||
// functions where all pointers are maybe pointers
|
||||
@@ -1278,7 +1278,9 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
|
||||
return entry;
|
||||
}
|
||||
|
||||
static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {
|
||||
static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
|
||||
Buf *type_name)
|
||||
{
|
||||
size_t backward_branch_count = 0;
|
||||
return ir_eval_const_value(g, scope, node, type_entry,
|
||||
&backward_branch_count, default_backward_branch_quota,
|
||||
@@ -1286,12 +1288,12 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod
|
||||
}
|
||||
|
||||
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
|
||||
IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
|
||||
if (result->value.type->id == ZigTypeIdInvalid)
|
||||
ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
|
||||
if (type_is_invalid(result->type))
|
||||
return g->builtin_types.entry_invalid;
|
||||
|
||||
assert(result->value.special != ConstValSpecialRuntime);
|
||||
return result->value.data.x_type;
|
||||
assert(result->special != ConstValSpecialRuntime);
|
||||
return result->data.x_type;
|
||||
}
|
||||
|
||||
ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
|
||||
@@ -1342,11 +1344,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
|
||||
}
|
||||
|
||||
static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
|
||||
IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
|
||||
if (type_is_invalid(align_result->value.type))
|
||||
ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
|
||||
if (type_is_invalid(align_result->type))
|
||||
return false;
|
||||
|
||||
uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint);
|
||||
uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint);
|
||||
if (align_bytes == 0) {
|
||||
add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
|
||||
return false;
|
||||
@@ -1364,12 +1366,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
|
||||
ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
|
||||
PtrLenUnknown, 0, 0, 0);
|
||||
ZigType *str_type = get_slice_type(g, ptr_type);
|
||||
IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);
|
||||
if (type_is_invalid(instr->value.type))
|
||||
ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
|
||||
if (type_is_invalid(result_val->type))
|
||||
return false;
|
||||
|
||||
ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index];
|
||||
ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index];
|
||||
ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index];
|
||||
ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index];
|
||||
|
||||
assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
|
||||
ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
|
||||
@@ -2504,20 +2506,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||
// In this first pass we resolve explicit tag values.
|
||||
// In a second pass we will fill in the unspecified ones.
|
||||
if (tag_value != nullptr) {
|
||||
IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
|
||||
if (result_inst->value.type->id == ZigTypeIdInvalid) {
|
||||
ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
|
||||
if (type_is_invalid(result->type)) {
|
||||
enum_type->data.enumeration.is_invalid = true;
|
||||
continue;
|
||||
}
|
||||
assert(result_inst->value.special != ConstValSpecialRuntime);
|
||||
assert(result_inst->value.type->id == ZigTypeIdInt ||
|
||||
result_inst->value.type->id == ZigTypeIdComptimeInt);
|
||||
auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
|
||||
assert(result->special != ConstValSpecialRuntime);
|
||||
assert(result->type->id == ZigTypeIdInt ||
|
||||
result->type->id == ZigTypeIdComptimeInt);
|
||||
auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
|
||||
if (entry == nullptr) {
|
||||
bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint);
|
||||
bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
|
||||
} else {
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);
|
||||
bigint_append_buf(val_buf, &result->data.x_bigint, 10);
|
||||
|
||||
ErrorMsg *msg = add_node_error(g, tag_value,
|
||||
buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
|
||||
@@ -2944,19 +2946,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
|
||||
// In a second pass we will fill in the unspecified ones.
|
||||
if (tag_value != nullptr) {
|
||||
ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;
|
||||
IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
|
||||
if (result_inst->value.type->id == ZigTypeIdInvalid) {
|
||||
ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
|
||||
if (type_is_invalid(result->type)) {
|
||||
union_type->data.unionation.is_invalid = true;
|
||||
continue;
|
||||
}
|
||||
assert(result_inst->value.special != ConstValSpecialRuntime);
|
||||
assert(result_inst->value.type->id == ZigTypeIdInt);
|
||||
auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
|
||||
assert(result->special != ConstValSpecialRuntime);
|
||||
assert(result->type->id == ZigTypeIdInt);
|
||||
auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
|
||||
if (entry == nullptr) {
|
||||
bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint);
|
||||
bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint);
|
||||
} else {
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);
|
||||
bigint_append_buf(val_buf, &result->data.x_bigint, 10);
|
||||
|
||||
ErrorMsg *msg = add_node_error(g, tag_value,
|
||||
buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
|
||||
@@ -3419,7 +3421,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
|
||||
resolve_top_level_decl(g, tld, false, tld->source_node);
|
||||
assert(tld->id == TldIdVar);
|
||||
TldVar *tld_var = (TldVar *)tld;
|
||||
tld_var->var->value = value;
|
||||
tld_var->var->const_value = value;
|
||||
tld_var->var->var_type = value->type;
|
||||
tld_var->var->align_bytes = get_abi_alignment(g, value->type);
|
||||
}
|
||||
|
||||
@@ -3513,7 +3516,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
|
||||
case NodeTypeArrayType:
|
||||
case NodeTypeErrorType:
|
||||
case NodeTypeIfErrorExpr:
|
||||
case NodeTypeTestExpr:
|
||||
case NodeTypeIfOptional:
|
||||
case NodeTypeErrorSetDecl:
|
||||
case NodeTypeCancel:
|
||||
case NodeTypeResume:
|
||||
@@ -3582,13 +3585,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
|
||||
// Set name to nullptr to make the variable anonymous (not visible to programmer).
|
||||
// TODO merge with definition of add_local_var in ir.cpp
|
||||
ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
|
||||
bool is_const, ConstExprValue *value, Tld *src_tld)
|
||||
bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type)
|
||||
{
|
||||
Error err;
|
||||
assert(value);
|
||||
assert(const_value != nullptr);
|
||||
assert(var_type != nullptr);
|
||||
|
||||
ZigVar *variable_entry = allocate<ZigVar>(1);
|
||||
variable_entry->value = value;
|
||||
variable_entry->const_value = const_value;
|
||||
variable_entry->var_type = var_type;
|
||||
variable_entry->parent_scope = parent_scope;
|
||||
variable_entry->shadowable = false;
|
||||
variable_entry->mem_slot_index = SIZE_MAX;
|
||||
@@ -3597,23 +3602,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
|
||||
assert(name);
|
||||
buf_init_from_buf(&variable_entry->name, name);
|
||||
|
||||
if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) {
|
||||
variable_entry->value->type = g->builtin_types.entry_invalid;
|
||||
if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) {
|
||||
variable_entry->var_type = g->builtin_types.entry_invalid;
|
||||
} else {
|
||||
variable_entry->align_bytes = get_abi_alignment(g, value->type);
|
||||
variable_entry->align_bytes = get_abi_alignment(g, var_type);
|
||||
|
||||
ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);
|
||||
if (existing_var && !existing_var->shadowable) {
|
||||
ErrorMsg *msg = add_node_error(g, source_node,
|
||||
buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
|
||||
add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
|
||||
variable_entry->value->type = g->builtin_types.entry_invalid;
|
||||
variable_entry->var_type = g->builtin_types.entry_invalid;
|
||||
} else {
|
||||
ZigType *type;
|
||||
if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
|
||||
add_node_error(g, source_node,
|
||||
buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
|
||||
variable_entry->value->type = g->builtin_types.entry_invalid;
|
||||
variable_entry->var_type = g->builtin_types.entry_invalid;
|
||||
} else {
|
||||
Scope *search_scope = nullptr;
|
||||
if (src_tld == nullptr) {
|
||||
@@ -3627,7 +3632,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
|
||||
ErrorMsg *msg = add_node_error(g, source_node,
|
||||
buf_sprintf("redefinition of '%s'", buf_ptr(name)));
|
||||
add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
|
||||
variable_entry->value->type = g->builtin_types.entry_invalid;
|
||||
variable_entry->var_type = g->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3677,7 +3682,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
|
||||
linkage = VarLinkageInternal;
|
||||
}
|
||||
|
||||
IrInstruction *init_value = nullptr;
|
||||
ConstExprValue *init_value = nullptr;
|
||||
|
||||
// TODO more validation for types that can't be used for export/extern variables
|
||||
ZigType *implicit_type = nullptr;
|
||||
@@ -3686,7 +3691,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
|
||||
} else if (var_decl->expr) {
|
||||
init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
|
||||
assert(init_value);
|
||||
implicit_type = init_value->value.type;
|
||||
implicit_type = init_value->type;
|
||||
|
||||
if (implicit_type->id == ZigTypeIdUnreachable) {
|
||||
add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
|
||||
@@ -3704,7 +3709,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
|
||||
add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
|
||||
implicit_type = g->builtin_types.entry_invalid;
|
||||
}
|
||||
assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime);
|
||||
assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
|
||||
} else if (linkage != VarLinkageExternal) {
|
||||
add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
|
||||
implicit_type = g->builtin_types.entry_invalid;
|
||||
@@ -3713,19 +3718,19 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
|
||||
ZigType *type = explicit_type ? explicit_type : implicit_type;
|
||||
assert(type != nullptr); // should have been caught by the parser
|
||||
|
||||
ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type);
|
||||
ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type);
|
||||
|
||||
tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
|
||||
is_const, init_val, &tld_var->base);
|
||||
is_const, init_val, &tld_var->base, type);
|
||||
tld_var->var->linkage = linkage;
|
||||
|
||||
if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
|
||||
tld_var->var->value->type = g->builtin_types.entry_invalid;
|
||||
tld_var->var->var_type = g->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
if (var_decl->align_expr != nullptr) {
|
||||
if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {
|
||||
tld_var->var->value->type = g->builtin_types.entry_invalid;
|
||||
tld_var->var->var_type = g->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4090,7 +4095,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
|
||||
}
|
||||
|
||||
ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
|
||||
param_name, true, create_const_runtime(param_type), nullptr);
|
||||
param_name, true, create_const_runtime(param_type), nullptr, param_type);
|
||||
var->src_arg_index = i;
|
||||
fn_table_entry->child_scope = var->child_scope;
|
||||
var->shadowable = var->shadowable || is_var_args;
|
||||
@@ -4228,18 +4233,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
|
||||
preview_use_decl(g, src_use_node);
|
||||
}
|
||||
|
||||
IrInstruction *use_target_value = src_use_node->data.use.value;
|
||||
if (use_target_value->value.type->id == ZigTypeIdInvalid) {
|
||||
ConstExprValue *use_target_value = src_use_node->data.use.value;
|
||||
if (type_is_invalid(use_target_value->type)) {
|
||||
dst_use_node->owner->any_imports_failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
dst_use_node->data.use.resolution = TldResolutionOk;
|
||||
|
||||
ConstExprValue *const_val = &use_target_value->value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
assert(use_target_value->special != ConstValSpecialRuntime);
|
||||
|
||||
ImportTableEntry *target_import = const_val->data.x_import;
|
||||
ImportTableEntry *target_import = use_target_value->data.x_import;
|
||||
assert(target_import);
|
||||
|
||||
if (target_import->any_imports_failed) {
|
||||
@@ -4302,10 +4306,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
|
||||
}
|
||||
|
||||
node->data.use.resolution = TldResolutionResolving;
|
||||
IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base,
|
||||
ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base,
|
||||
node->data.use.expr, g->builtin_types.entry_namespace, nullptr);
|
||||
|
||||
if (result->value.type->id == ZigTypeIdInvalid)
|
||||
if (type_is_invalid(result->type))
|
||||
node->owner->any_imports_failed = true;
|
||||
|
||||
node->data.use.value = result;
|
||||
@@ -4486,7 +4490,8 @@ bool handle_is_ptr(ZigType *type_entry) {
|
||||
return type_has_bits(type_entry->data.error_union.payload_type);
|
||||
case ZigTypeIdOptional:
|
||||
return type_has_bits(type_entry->data.maybe.child_type) &&
|
||||
!type_is_codegen_pointer(type_entry->data.maybe.child_type);
|
||||
!type_is_codegen_pointer(type_entry->data.maybe.child_type) &&
|
||||
type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet;
|
||||
case ZigTypeIdUnion:
|
||||
assert(type_entry->data.unionation.zero_bits_known);
|
||||
if (type_entry->data.unionation.gen_field_count == 0)
|
||||
@@ -4732,6 +4737,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t hash_const_val_error_set(ConstExprValue *const_val) {
|
||||
assert(const_val->data.x_err_set != nullptr);
|
||||
return const_val->data.x_err_set->value ^ 2630160122;
|
||||
}
|
||||
|
||||
static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
|
||||
uint32_t hash_val = 0;
|
||||
switch (const_val->data.x_ptr.mut) {
|
||||
@@ -4763,6 +4773,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
|
||||
hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
|
||||
hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);
|
||||
return hash_val;
|
||||
case ConstPtrSpecialBaseErrorUnionCode:
|
||||
hash_val += (uint32_t)2994743799;
|
||||
hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val);
|
||||
return hash_val;
|
||||
case ConstPtrSpecialBaseErrorUnionPayload:
|
||||
hash_val += (uint32_t)3456080131;
|
||||
hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val);
|
||||
return hash_val;
|
||||
case ConstPtrSpecialBaseOptionalPayload:
|
||||
hash_val += (uint32_t)3163140517;
|
||||
hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val);
|
||||
return hash_val;
|
||||
case ConstPtrSpecialHardCodedAddr:
|
||||
hash_val += (uint32_t)4048518294;
|
||||
hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);
|
||||
@@ -4774,6 +4796,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
|
||||
hash_val += (uint32_t)2590901619;
|
||||
hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);
|
||||
return hash_val;
|
||||
case ConstPtrSpecialNull:
|
||||
hash_val += (uint32_t)1486246455;
|
||||
return hash_val;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@@ -4872,7 +4897,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
|
||||
return 2709806591;
|
||||
case ZigTypeIdOptional:
|
||||
if (get_codegen_ptr_type(const_val->type) != nullptr) {
|
||||
return hash_const_val(const_val) * 1992916303;
|
||||
return hash_const_val_ptr(const_val) * 1992916303;
|
||||
} else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
|
||||
return hash_const_val_error_set(const_val) * 3147031929;
|
||||
} else {
|
||||
if (const_val->data.x_optional) {
|
||||
return hash_const_val(const_val->data.x_optional) * 1992916303;
|
||||
@@ -4884,8 +4911,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
|
||||
// TODO better hashing algorithm
|
||||
return 3415065496;
|
||||
case ZigTypeIdErrorSet:
|
||||
assert(const_val->data.x_err_set != nullptr);
|
||||
return const_val->data.x_err_set->value ^ 2630160122;
|
||||
return hash_const_val_error_set(const_val);
|
||||
case ZigTypeIdNamespace:
|
||||
return hash_ptr(const_val->data.x_import);
|
||||
case ZigTypeIdBoundFn:
|
||||
@@ -4987,7 +5013,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
|
||||
return can_mutate_comptime_var_state(value->data.x_optional);
|
||||
|
||||
case ZigTypeIdErrorUnion:
|
||||
if (value->data.x_err_union.err != nullptr)
|
||||
if (value->data.x_err_union.error_set->data.x_err_set != nullptr)
|
||||
return false;
|
||||
assert(value->data.x_err_union.payload != nullptr);
|
||||
return can_mutate_comptime_var_state(value->data.x_err_union.payload);
|
||||
@@ -5048,9 +5074,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
|
||||
while (scope) {
|
||||
if (scope->id == ScopeIdVarDecl) {
|
||||
ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
|
||||
if (type_is_invalid(var_scope->var->value->type))
|
||||
if (type_is_invalid(var_scope->var->var_type))
|
||||
return false;
|
||||
if (can_mutate_comptime_var_state(var_scope->var->value))
|
||||
if (can_mutate_comptime_var_state(var_scope->var->const_value))
|
||||
return false;
|
||||
} else if (scope->id == ScopeIdFnDef) {
|
||||
return true;
|
||||
@@ -5068,7 +5094,7 @@ uint32_t fn_eval_hash(Scope* scope) {
|
||||
while (scope) {
|
||||
if (scope->id == ScopeIdVarDecl) {
|
||||
ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
|
||||
result += hash_const_val(var_scope->var->value);
|
||||
result += hash_const_val(var_scope->var->const_value);
|
||||
} else if (scope->id == ScopeIdFnDef) {
|
||||
ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
|
||||
result += hash_ptr(fn_scope->fn_entry);
|
||||
@@ -5092,10 +5118,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {
|
||||
if (a->id == ScopeIdVarDecl) {
|
||||
ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;
|
||||
ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;
|
||||
if (a_var_scope->var->value->type != b_var_scope->var->value->type)
|
||||
return false;
|
||||
if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value))
|
||||
if (a_var_scope->var->var_type != b_var_scope->var->var_type)
|
||||
return false;
|
||||
if (a_var_scope->var->var_type == a_var_scope->var->const_value->type &&
|
||||
b_var_scope->var->var_type == b_var_scope->var->const_value->type)
|
||||
{
|
||||
if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value))
|
||||
return false;
|
||||
} else {
|
||||
zig_panic("TODO comptime ptr reinterpret for fn_eval_eql");
|
||||
}
|
||||
} else if (a->id == ScopeIdFnDef) {
|
||||
ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
|
||||
ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;
|
||||
@@ -5113,6 +5145,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Whether the type has bits at runtime.
|
||||
bool type_has_bits(ZigType *type_entry) {
|
||||
assert(type_entry);
|
||||
assert(!type_is_invalid(type_entry));
|
||||
@@ -5120,6 +5153,65 @@ bool type_has_bits(ZigType *type_entry) {
|
||||
return !type_entry->zero_bits;
|
||||
}
|
||||
|
||||
// Whether you can infer the value based solely on the type.
|
||||
OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
|
||||
assert(type_entry != nullptr);
|
||||
Error err;
|
||||
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
|
||||
return OnePossibleValueInvalid;
|
||||
switch (type_entry->id) {
|
||||
case ZigTypeIdInvalid:
|
||||
zig_unreachable();
|
||||
case ZigTypeIdOpaque:
|
||||
case ZigTypeIdComptimeFloat:
|
||||
case ZigTypeIdComptimeInt:
|
||||
case ZigTypeIdMetaType:
|
||||
case ZigTypeIdNamespace:
|
||||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdArgTuple:
|
||||
case ZigTypeIdOptional:
|
||||
case ZigTypeIdFn:
|
||||
case ZigTypeIdBool:
|
||||
case ZigTypeIdFloat:
|
||||
case ZigTypeIdPromise:
|
||||
case ZigTypeIdErrorUnion:
|
||||
return OnePossibleValueNo;
|
||||
case ZigTypeIdUndefined:
|
||||
case ZigTypeIdNull:
|
||||
case ZigTypeIdVoid:
|
||||
case ZigTypeIdUnreachable:
|
||||
return OnePossibleValueYes;
|
||||
case ZigTypeIdArray:
|
||||
if (type_entry->data.array.len == 0)
|
||||
return OnePossibleValueYes;
|
||||
return type_has_one_possible_value(g, type_entry->data.array.child_type);
|
||||
case ZigTypeIdStruct:
|
||||
for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
|
||||
TypeStructField *field = &type_entry->data.structure.fields[i];
|
||||
switch (type_has_one_possible_value(g, field->type_entry)) {
|
||||
case OnePossibleValueInvalid:
|
||||
return OnePossibleValueInvalid;
|
||||
case OnePossibleValueNo:
|
||||
return OnePossibleValueNo;
|
||||
case OnePossibleValueYes:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return OnePossibleValueYes;
|
||||
case ZigTypeIdErrorSet:
|
||||
case ZigTypeIdEnum:
|
||||
case ZigTypeIdInt:
|
||||
return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
|
||||
case ZigTypeIdPointer:
|
||||
return type_has_one_possible_value(g, type_entry->data.pointer.child_type);
|
||||
case ZigTypeIdUnion:
|
||||
if (type_entry->data.unionation.src_field_count > 1)
|
||||
return OnePossibleValueNo;
|
||||
return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
|
||||
Error err;
|
||||
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
|
||||
@@ -5574,6 +5666,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
|
||||
if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
|
||||
return false;
|
||||
return true;
|
||||
case ConstPtrSpecialBaseErrorUnionCode:
|
||||
if (a->data.x_ptr.data.base_err_union_code.err_union_val !=
|
||||
b->data.x_ptr.data.base_err_union_code.err_union_val &&
|
||||
a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs !=
|
||||
b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case ConstPtrSpecialBaseErrorUnionPayload:
|
||||
if (a->data.x_ptr.data.base_err_union_payload.err_union_val !=
|
||||
b->data.x_ptr.data.base_err_union_payload.err_union_val &&
|
||||
a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs !=
|
||||
b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case ConstPtrSpecialBaseOptionalPayload:
|
||||
if (a->data.x_ptr.data.base_optional_payload.optional_val !=
|
||||
b->data.x_ptr.data.base_optional_payload.optional_val &&
|
||||
a->data.x_ptr.data.base_optional_payload.optional_val->global_refs !=
|
||||
b->data.x_ptr.data.base_optional_payload.optional_val->global_refs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case ConstPtrSpecialHardCodedAddr:
|
||||
if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
|
||||
return false;
|
||||
@@ -5582,6 +5701,8 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
|
||||
return true;
|
||||
case ConstPtrSpecialFunction:
|
||||
return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
|
||||
case ConstPtrSpecialNull:
|
||||
return true;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
@@ -5750,7 +5871,7 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v
|
||||
}
|
||||
}
|
||||
|
||||
void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
|
||||
static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
|
||||
assert(type_entry->id == ZigTypeIdPointer);
|
||||
|
||||
if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
|
||||
@@ -5763,6 +5884,9 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
|
||||
zig_unreachable();
|
||||
case ConstPtrSpecialRef:
|
||||
case ConstPtrSpecialBaseStruct:
|
||||
case ConstPtrSpecialBaseErrorUnionCode:
|
||||
case ConstPtrSpecialBaseErrorUnionPayload:
|
||||
case ConstPtrSpecialBaseOptionalPayload:
|
||||
buf_appendf(buf, "*");
|
||||
// TODO we need a source node for const_ptr_pointee because it can generate compile errors
|
||||
render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
|
||||
@@ -5790,10 +5914,21 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
|
||||
buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));
|
||||
return;
|
||||
}
|
||||
case ConstPtrSpecialNull:
|
||||
buf_append_str(buf, "null");
|
||||
return;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
|
||||
if (const_val->data.x_err_set == nullptr) {
|
||||
buf_append_str(buf, "null");
|
||||
} else {
|
||||
buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
|
||||
}
|
||||
}
|
||||
|
||||
void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||
switch (const_val->special) {
|
||||
case ConstValSpecialRuntime:
|
||||
@@ -5921,6 +6056,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||
{
|
||||
if (get_codegen_ptr_type(const_val->type) != nullptr)
|
||||
return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);
|
||||
if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet)
|
||||
return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type);
|
||||
if (const_val->data.x_optional) {
|
||||
render_const_value(g, buf, const_val->data.x_optional);
|
||||
} else {
|
||||
@@ -5958,11 +6095,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||
case ZigTypeIdErrorUnion:
|
||||
{
|
||||
buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
|
||||
if (const_val->data.x_err_union.err == nullptr) {
|
||||
ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
|
||||
if (err_set == nullptr) {
|
||||
render_const_value(g, buf, const_val->data.x_err_union.payload);
|
||||
} else {
|
||||
buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
|
||||
buf_ptr(&const_val->data.x_err_union.err->name));
|
||||
buf_ptr(&err_set->name));
|
||||
}
|
||||
buf_appendf(buf, ")");
|
||||
return;
|
||||
@@ -5977,10 +6115,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||
return;
|
||||
}
|
||||
case ZigTypeIdErrorSet:
|
||||
{
|
||||
buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
|
||||
return;
|
||||
}
|
||||
return render_const_val_err_set(g, buf, const_val, type_entry);
|
||||
case ZigTypeIdArgTuple:
|
||||
{
|
||||
buf_appendf(buf, "(args value)");
|
||||
@@ -6172,6 +6307,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
|
||||
// Canonicalize the array value as ConstArraySpecialNone
|
||||
void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
|
||||
assert(const_val->type->id == ZigTypeIdArray);
|
||||
if (const_val->special == ConstValSpecialUndef) {
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->data.x_array.special = ConstArraySpecialUndef;
|
||||
}
|
||||
switch (const_val->data.x_array.special) {
|
||||
case ConstArraySpecialNone:
|
||||
return;
|
||||
@@ -6215,17 +6354,7 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
|
||||
}
|
||||
|
||||
ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
|
||||
assert(value->type);
|
||||
ZigType *type_entry = value->type;
|
||||
if (type_entry->id == ZigTypeIdArray) {
|
||||
expand_undef_array(g, value);
|
||||
return &value->data.x_array.data.s_none.parent;
|
||||
} else if (type_entry->id == ZigTypeIdStruct) {
|
||||
return &value->data.x_struct.parent;
|
||||
} else if (type_entry->id == ZigTypeIdUnion) {
|
||||
return &value->data.x_union.parent;
|
||||
}
|
||||
return nullptr;
|
||||
return &value->parent;
|
||||
}
|
||||
|
||||
static const ZigTypeId all_type_ids[] = {
|
||||
@@ -6453,7 +6582,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
|
||||
resolve_top_level_decl(codegen, tld, false, nullptr);
|
||||
assert(tld->id == TldIdVar);
|
||||
TldVar *tld_var = (TldVar *)tld;
|
||||
ConstExprValue *var_value = tld_var->var->value;
|
||||
ConstExprValue *var_value = tld_var->var->const_value;
|
||||
assert(var_value != nullptr);
|
||||
return var_value;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ ZigFn *scope_fn_entry(Scope *scope);
|
||||
ImportTableEntry *get_scope_import(Scope *scope);
|
||||
void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
|
||||
ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
|
||||
bool is_const, ConstExprValue *init_value, Tld *src_tld);
|
||||
bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type);
|
||||
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
|
||||
ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
|
||||
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
|
||||
@@ -222,6 +222,13 @@ enum ReqCompTime {
|
||||
};
|
||||
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
|
||||
|
||||
enum OnePossibleValue {
|
||||
OnePossibleValueInvalid,
|
||||
OnePossibleValueNo,
|
||||
OnePossibleValueYes,
|
||||
};
|
||||
OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
|
||||
|
||||
Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
|
||||
ConstExprValue *const_val, ZigType *wanted_type);
|
||||
|
||||
|
||||
@@ -233,8 +233,8 @@ static const char *node_type_str(NodeType node_type) {
|
||||
return "ErrorType";
|
||||
case NodeTypeIfErrorExpr:
|
||||
return "IfErrorExpr";
|
||||
case NodeTypeTestExpr:
|
||||
return "TestExpr";
|
||||
case NodeTypeIfOptional:
|
||||
return "IfOptional";
|
||||
case NodeTypeErrorSetDecl:
|
||||
return "ErrorSetDecl";
|
||||
case NodeTypeCancel:
|
||||
@@ -387,7 +387,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
|
||||
if (node->data.if_err_expr.else_node)
|
||||
return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);
|
||||
return node->data.if_err_expr.then_node->type == NodeTypeBlock;
|
||||
case NodeTypeTestExpr:
|
||||
case NodeTypeIfOptional:
|
||||
if (node->data.test_expr.else_node)
|
||||
return statement_terminates_without_semicolon(node->data.test_expr.else_node);
|
||||
return node->data.test_expr.then_node->type == NodeTypeBlock;
|
||||
@@ -974,7 +974,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NodeTypeTestExpr:
|
||||
case NodeTypeIfOptional:
|
||||
{
|
||||
fprintf(ar->f, "if (");
|
||||
render_node_grouped(ar, node->data.test_expr.target_node);
|
||||
|
||||
385
src/codegen.cpp
385
src/codegen.cpp
@@ -313,6 +313,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *
|
||||
static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
|
||||
static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);
|
||||
static void generate_error_name_table(CodeGen *g);
|
||||
static bool value_is_all_undef(ConstExprValue *const_val);
|
||||
static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr);
|
||||
|
||||
static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
|
||||
unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
|
||||
@@ -461,6 +463,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag
|
||||
}
|
||||
}
|
||||
|
||||
static bool cc_want_sret_attr(CallingConvention cc) {
|
||||
switch (cc) {
|
||||
case CallingConventionNaked:
|
||||
zig_unreachable();
|
||||
case CallingConventionC:
|
||||
case CallingConventionCold:
|
||||
case CallingConventionStdcall:
|
||||
return true;
|
||||
case CallingConventionAsync:
|
||||
case CallingConventionUnspecified:
|
||||
return false;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
|
||||
if (fn_table_entry->llvm_value)
|
||||
return fn_table_entry->llvm_value;
|
||||
@@ -598,9 +615,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
|
||||
} else if (type_is_codegen_pointer(return_type)) {
|
||||
addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
|
||||
} else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
|
||||
if (cc == CallingConventionC) {
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
|
||||
if (cc_want_sret_attr(cc)) {
|
||||
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");
|
||||
}
|
||||
init_gen_i = 1;
|
||||
@@ -2200,10 +2217,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
|
||||
assert(variable);
|
||||
assert(variable->value_ref);
|
||||
|
||||
if (!handle_is_ptr(variable->value->type)) {
|
||||
if (!handle_is_ptr(variable->var_type)) {
|
||||
clear_debug_source_node(g);
|
||||
gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref,
|
||||
variable->align_bytes, false);
|
||||
gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index),
|
||||
variable->value_ref, variable->align_bytes, false);
|
||||
}
|
||||
|
||||
if (variable->decl_node) {
|
||||
@@ -2961,7 +2978,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionPtrCast *instruction)
|
||||
IrInstructionPtrCastGen *instruction)
|
||||
{
|
||||
ZigType *wanted_type = instruction->base.value.type;
|
||||
if (!type_has_bits(wanted_type)) {
|
||||
@@ -3149,11 +3166,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionDeclVar *decl_var_instruction)
|
||||
IrInstructionDeclVarGen *decl_var_instruction)
|
||||
{
|
||||
ZigVar *var = decl_var_instruction->var;
|
||||
|
||||
if (!type_has_bits(var->value->type))
|
||||
if (!type_has_bits(var->var_type))
|
||||
return nullptr;
|
||||
|
||||
if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
|
||||
@@ -3161,34 +3178,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
|
||||
|
||||
IrInstruction *init_value = decl_var_instruction->init_value;
|
||||
|
||||
bool have_init_expr = false;
|
||||
|
||||
ConstExprValue *const_val = &init_value->value;
|
||||
if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
|
||||
have_init_expr = true;
|
||||
bool have_init_expr = !value_is_all_undef(&init_value->value);
|
||||
|
||||
if (have_init_expr) {
|
||||
assert(var->value->type == init_value->value.type);
|
||||
ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
|
||||
ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
|
||||
PtrLenSingle, var->align_bytes, 0, 0);
|
||||
LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
|
||||
gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
|
||||
} else {
|
||||
bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
|
||||
if (want_safe) {
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref);
|
||||
assert(size_bytes > 0);
|
||||
|
||||
assert(var->align_bytes > 0);
|
||||
|
||||
// memset uninitialized memory to 0xa
|
||||
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
|
||||
LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
|
||||
LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, "");
|
||||
LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
|
||||
ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false);
|
||||
}
|
||||
} else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
|
||||
uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes;
|
||||
gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
|
||||
}
|
||||
|
||||
gen_var_debug_decl(g, var);
|
||||
@@ -3225,21 +3224,75 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
|
||||
return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
|
||||
}
|
||||
|
||||
static bool value_is_all_undef(ConstExprValue *const_val) {
|
||||
switch (const_val->special) {
|
||||
case ConstValSpecialRuntime:
|
||||
return false;
|
||||
case ConstValSpecialUndef:
|
||||
return true;
|
||||
case ConstValSpecialStatic:
|
||||
if (const_val->type->id == ZigTypeIdStruct) {
|
||||
for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) {
|
||||
if (!value_is_all_undef(&const_val->data.x_struct.fields[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else if (const_val->type->id == ZigTypeIdArray) {
|
||||
switch (const_val->data.x_array.special) {
|
||||
case ConstArraySpecialUndef:
|
||||
return true;
|
||||
case ConstArraySpecialBuf:
|
||||
return false;
|
||||
case ConstArraySpecialNone:
|
||||
for (size_t i = 0; i < const_val->type->data.array.len; i += 1) {
|
||||
if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
zig_unreachable();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
|
||||
assert(type_has_bits(value_type));
|
||||
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref);
|
||||
assert(size_bytes > 0);
|
||||
assert(ptr_align_bytes > 0);
|
||||
// memset uninitialized memory to 0xaa
|
||||
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
|
||||
LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
|
||||
LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
|
||||
ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
|
||||
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
|
||||
LLVMValueRef value = ir_llvm_value(g, instruction->value);
|
||||
|
||||
assert(instruction->ptr->value.type->id == ZigTypeIdPointer);
|
||||
ZigType *ptr_type = instruction->ptr->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
if (!type_has_bits(ptr_type))
|
||||
return nullptr;
|
||||
|
||||
gen_assign_raw(g, ptr, ptr_type, value);
|
||||
|
||||
bool have_init_expr = !value_is_all_undef(&instruction->value->value);
|
||||
if (have_init_expr) {
|
||||
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
|
||||
LLVMValueRef value = ir_llvm_value(g, instruction->value);
|
||||
gen_assign_raw(g, ptr, ptr_type, value);
|
||||
} else if (ir_want_runtime_safety(g, &instruction->base)) {
|
||||
gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,
|
||||
ir_llvm_value(g, instruction->ptr));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
|
||||
ZigVar *var = instruction->var;
|
||||
if (type_has_bits(var->value->type)) {
|
||||
if (type_has_bits(var->var_type)) {
|
||||
assert(var->value_ref);
|
||||
return var->value_ref;
|
||||
} else {
|
||||
@@ -3553,7 +3606,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
|
||||
LLVMPositionBuilderAtEnd(g->builder, ok_block);
|
||||
}
|
||||
|
||||
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, "");
|
||||
LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
|
||||
union_type->data.unionation.gen_union_index, "");
|
||||
LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
|
||||
return bitcasted_union_field_ptr;
|
||||
}
|
||||
@@ -3715,8 +3769,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR
|
||||
if (child_type->zero_bits) {
|
||||
return maybe_handle;
|
||||
} else {
|
||||
bool maybe_is_ptr = type_is_codegen_pointer(child_type);
|
||||
if (maybe_is_ptr) {
|
||||
bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
|
||||
if (is_scalar) {
|
||||
return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
|
||||
} else {
|
||||
LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
|
||||
@@ -3731,17 +3785,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
|
||||
return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionUnwrapOptional *instruction)
|
||||
static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionOptionalUnwrapPtr *instruction)
|
||||
{
|
||||
ZigType *ptr_type = instruction->value->value.type;
|
||||
ZigType *ptr_type = instruction->base_ptr->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *maybe_type = ptr_type->data.pointer.child_type;
|
||||
assert(maybe_type->id == ZigTypeIdOptional);
|
||||
ZigType *child_type = maybe_type->data.maybe.child_type;
|
||||
LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
|
||||
LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
|
||||
if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
|
||||
LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
|
||||
LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
|
||||
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
|
||||
LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
|
||||
@@ -3755,8 +3809,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
|
||||
if (child_type->zero_bits) {
|
||||
return nullptr;
|
||||
} else {
|
||||
bool maybe_is_ptr = type_is_codegen_pointer(child_type);
|
||||
if (maybe_is_ptr) {
|
||||
bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
|
||||
if (is_scalar) {
|
||||
return maybe_ptr;
|
||||
} else {
|
||||
LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
|
||||
@@ -4174,7 +4228,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) {
|
||||
static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) {
|
||||
LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
|
||||
LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
|
||||
LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
|
||||
@@ -4189,18 +4243,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
|
||||
assert(maybe_type->id == ZigTypeIdOptional);
|
||||
ZigType *child_type = maybe_type->data.maybe.child_type;
|
||||
|
||||
if (type_is_codegen_pointer(child_type)) {
|
||||
if (!handle_is_ptr(maybe_type)) {
|
||||
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
|
||||
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
|
||||
return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");
|
||||
}
|
||||
|
||||
assert(instruction->tmp_ptr != nullptr);
|
||||
assert(type_has_bits(instruction->type));
|
||||
assert(type_has_bits(child_type));
|
||||
|
||||
LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
|
||||
LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
|
||||
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, instruction->type, false), payload_val);
|
||||
gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
|
||||
|
||||
LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
|
||||
LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
|
||||
@@ -4351,6 +4405,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
|
||||
assert(array_type->data.structure.is_slice);
|
||||
assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
|
||||
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
|
||||
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
|
||||
|
||||
size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
|
||||
assert(ptr_index != SIZE_MAX);
|
||||
@@ -4540,12 +4595,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
|
||||
return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {
|
||||
ZigType *ptr_type = instruction->value->value.type;
|
||||
static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionUnwrapErrCode *instruction)
|
||||
{
|
||||
ZigType *ptr_type = instruction->err_union->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *err_union_type = ptr_type->data.pointer.child_type;
|
||||
ZigType *payload_type = err_union_type->data.error_union.payload_type;
|
||||
LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);
|
||||
LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union);
|
||||
LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
|
||||
|
||||
if (type_has_bits(payload_type)) {
|
||||
@@ -4556,7 +4613,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {
|
||||
static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionUnwrapErrPayload *instruction)
|
||||
{
|
||||
bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on &&
|
||||
g->errors_by_index.length > 1;
|
||||
if (!want_safety && !type_has_bits(instruction->base.value.type))
|
||||
return nullptr;
|
||||
ZigType *ptr_type = instruction->value->value.type;
|
||||
assert(ptr_type->id == ZigTypeIdPointer);
|
||||
ZigType *err_union_type = ptr_type->data.pointer.child_type;
|
||||
@@ -4568,7 +4631,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
|
||||
return err_union_handle;
|
||||
}
|
||||
|
||||
if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) {
|
||||
if (want_safety) {
|
||||
LLVMValueRef err_val;
|
||||
if (type_has_bits(payload_type)) {
|
||||
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
|
||||
@@ -4607,7 +4670,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
|
||||
}
|
||||
|
||||
LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
|
||||
if (type_is_codegen_pointer(child_type)) {
|
||||
if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
|
||||
return payload_val;
|
||||
}
|
||||
|
||||
@@ -5184,12 +5247,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
case IrInstructionIdToBytes:
|
||||
case IrInstructionIdEnumToInt:
|
||||
case IrInstructionIdCheckRuntimeScope:
|
||||
case IrInstructionIdDeclVarSrc:
|
||||
case IrInstructionIdPtrCastSrc:
|
||||
case IrInstructionIdCmpxchgSrc:
|
||||
zig_unreachable();
|
||||
|
||||
case IrInstructionIdDeclVarGen:
|
||||
return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
|
||||
case IrInstructionIdReturn:
|
||||
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
|
||||
case IrInstructionIdDeclVar:
|
||||
return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
|
||||
case IrInstructionIdBinOp:
|
||||
return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
|
||||
case IrInstructionIdCast:
|
||||
@@ -5220,8 +5286,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
|
||||
case IrInstructionIdTestNonNull:
|
||||
return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
|
||||
case IrInstructionIdUnwrapOptional:
|
||||
return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction);
|
||||
case IrInstructionIdOptionalUnwrapPtr:
|
||||
return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction);
|
||||
case IrInstructionIdClz:
|
||||
return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
|
||||
case IrInstructionIdCtz:
|
||||
@@ -5236,8 +5302,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
|
||||
case IrInstructionIdErrName:
|
||||
return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
|
||||
case IrInstructionIdCmpxchg:
|
||||
return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction);
|
||||
case IrInstructionIdCmpxchgGen:
|
||||
return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction);
|
||||
case IrInstructionIdFence:
|
||||
return ir_render_fence(g, executable, (IrInstructionFence *)instruction);
|
||||
case IrInstructionIdTruncate:
|
||||
@@ -5278,8 +5344,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||
return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
|
||||
case IrInstructionIdUnionInit:
|
||||
return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
|
||||
case IrInstructionIdPtrCast:
|
||||
return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);
|
||||
case IrInstructionIdPtrCastGen:
|
||||
return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
|
||||
case IrInstructionIdBitCast:
|
||||
return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
|
||||
case IrInstructionIdWidenOrShorten:
|
||||
@@ -5377,6 +5443,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
|
||||
static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
|
||||
static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
|
||||
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);
|
||||
static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
|
||||
static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
|
||||
static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val);
|
||||
|
||||
static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
|
||||
switch (parent->id) {
|
||||
@@ -5387,6 +5456,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
|
||||
case ConstParentIdStruct:
|
||||
return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
|
||||
parent->data.p_struct.field_index);
|
||||
case ConstParentIdErrUnionCode:
|
||||
return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val);
|
||||
case ConstParentIdErrUnionPayload:
|
||||
return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val);
|
||||
case ConstParentIdOptionalPayload:
|
||||
return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val);
|
||||
case ConstParentIdArray:
|
||||
return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
|
||||
parent->data.p_array.elem_index);
|
||||
@@ -5402,7 +5477,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
|
||||
|
||||
static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
|
||||
expand_undef_array(g, array_const_val);
|
||||
ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent;
|
||||
ConstParent *parent = &array_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
|
||||
|
||||
LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
|
||||
@@ -5427,7 +5502,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {
|
||||
ConstParent *parent = &struct_const_val->data.x_struct.parent;
|
||||
ConstParent *parent = &struct_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
|
||||
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
@@ -5438,8 +5513,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
|
||||
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
|
||||
ConstParent *parent = &err_union_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
|
||||
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(u32->type_ref),
|
||||
LLVMConstInt(u32->type_ref, err_union_err_index, false),
|
||||
};
|
||||
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
|
||||
ConstParent *parent = &err_union_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
|
||||
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(u32->type_ref),
|
||||
LLVMConstInt(u32->type_ref, err_union_payload_index, false),
|
||||
};
|
||||
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val) {
|
||||
ConstParent *parent = &optional_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent);
|
||||
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
LLVMValueRef indices[] = {
|
||||
LLVMConstNull(u32->type_ref),
|
||||
LLVMConstInt(u32->type_ref, maybe_child_index, false),
|
||||
};
|
||||
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {
|
||||
ConstParent *parent = &union_const_val->data.x_union.parent;
|
||||
ConstParent *parent = &union_const_val->parent;
|
||||
LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
|
||||
|
||||
ZigType *u32 = g->builtin_types.entry_u32;
|
||||
@@ -5609,6 +5720,63 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
|
||||
render_const_val_global(g, const_val, "");
|
||||
return ptr_val;
|
||||
}
|
||||
case ConstPtrSpecialBaseErrorUnionCode:
|
||||
{
|
||||
render_const_val_global(g, const_val, name);
|
||||
ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val;
|
||||
assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
|
||||
if (err_union_const_val->type->zero_bits) {
|
||||
// make this a null pointer
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
|
||||
const_val->type->type_ref);
|
||||
render_const_val_global(g, const_val, "");
|
||||
return const_val->global_refs->llvm_value;
|
||||
}
|
||||
LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val);
|
||||
LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
|
||||
const_val->global_refs->llvm_value = ptr_val;
|
||||
render_const_val_global(g, const_val, "");
|
||||
return ptr_val;
|
||||
}
|
||||
case ConstPtrSpecialBaseErrorUnionPayload:
|
||||
{
|
||||
render_const_val_global(g, const_val, name);
|
||||
ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val;
|
||||
assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
|
||||
if (err_union_const_val->type->zero_bits) {
|
||||
// make this a null pointer
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
|
||||
const_val->type->type_ref);
|
||||
render_const_val_global(g, const_val, "");
|
||||
return const_val->global_refs->llvm_value;
|
||||
}
|
||||
LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val);
|
||||
LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
|
||||
const_val->global_refs->llvm_value = ptr_val;
|
||||
render_const_val_global(g, const_val, "");
|
||||
return ptr_val;
|
||||
}
|
||||
case ConstPtrSpecialBaseOptionalPayload:
|
||||
{
|
||||
render_const_val_global(g, const_val, name);
|
||||
ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val;
|
||||
assert(optional_const_val->type->id == ZigTypeIdOptional);
|
||||
if (optional_const_val->type->zero_bits) {
|
||||
// make this a null pointer
|
||||
ZigType *usize = g->builtin_types.entry_usize;
|
||||
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
|
||||
const_val->type->type_ref);
|
||||
render_const_val_global(g, const_val, "");
|
||||
return const_val->global_refs->llvm_value;
|
||||
}
|
||||
LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val);
|
||||
LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
|
||||
const_val->global_refs->llvm_value = ptr_val;
|
||||
render_const_val_global(g, const_val, "");
|
||||
return ptr_val;
|
||||
}
|
||||
case ConstPtrSpecialHardCodedAddr:
|
||||
{
|
||||
render_const_val_global(g, const_val, name);
|
||||
@@ -5621,10 +5789,17 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
|
||||
}
|
||||
case ConstPtrSpecialFunction:
|
||||
return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);
|
||||
case ConstPtrSpecialNull:
|
||||
return LLVMConstNull(const_val->type->type_ref);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) {
|
||||
uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value;
|
||||
return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false);
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
|
||||
Error err;
|
||||
|
||||
@@ -5644,9 +5819,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
case ZigTypeIdInt:
|
||||
return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
|
||||
case ZigTypeIdErrorSet:
|
||||
assert(const_val->data.x_err_set != nullptr);
|
||||
return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref,
|
||||
const_val->data.x_err_set->value, false);
|
||||
return gen_const_val_err_set(g, const_val, name);
|
||||
case ZigTypeIdFloat:
|
||||
switch (type_entry->data.floating.bit_count) {
|
||||
case 16:
|
||||
@@ -5680,6 +5853,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
|
||||
} else if (type_is_codegen_pointer(child_type)) {
|
||||
return gen_const_val_ptr(g, const_val, name);
|
||||
} else if (child_type->id == ZigTypeIdErrorSet) {
|
||||
return gen_const_val_err_set(g, const_val, name);
|
||||
} else {
|
||||
LLVMValueRef child_val;
|
||||
LLVMValueRef maybe_val;
|
||||
@@ -5914,7 +6089,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
ZigType *err_set_type = type_entry->data.error_union.err_set_type;
|
||||
if (!type_has_bits(payload_type)) {
|
||||
assert(type_has_bits(err_set_type));
|
||||
uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0;
|
||||
ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
|
||||
uint64_t value = (err_set == nullptr) ? 0 : err_set->value;
|
||||
return LLVMConstInt(g->err_tag_type->type_ref, value, false);
|
||||
} else if (!type_has_bits(err_set_type)) {
|
||||
assert(type_has_bits(payload_type));
|
||||
@@ -5923,8 +6099,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
LLVMValueRef err_tag_value;
|
||||
LLVMValueRef err_payload_value;
|
||||
bool make_unnamed_struct;
|
||||
if (const_val->data.x_err_union.err) {
|
||||
err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);
|
||||
ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
|
||||
if (err_set != nullptr) {
|
||||
err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false);
|
||||
err_payload_value = LLVMConstNull(payload_type->type_ref);
|
||||
make_unnamed_struct = false;
|
||||
} else {
|
||||
@@ -6130,10 +6307,13 @@ static void do_code_gen(CodeGen *g) {
|
||||
TldVar *tld_var = g->global_vars.at(i);
|
||||
ZigVar *var = tld_var->var;
|
||||
|
||||
if (var->value->type->id == ZigTypeIdComptimeFloat) {
|
||||
if (var->var_type->id == ZigTypeIdComptimeFloat) {
|
||||
// Generate debug info for it but that's it.
|
||||
ConstExprValue *const_val = var->value;
|
||||
ConstExprValue *const_val = var->const_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
if (const_val->type != var->var_type) {
|
||||
zig_panic("TODO debug info for var with ptr casted value");
|
||||
}
|
||||
ZigType *var_type = g->builtin_types.entry_f128;
|
||||
ConstExprValue coerced_value;
|
||||
coerced_value.special = ConstValSpecialStatic;
|
||||
@@ -6144,10 +6324,13 @@ static void do_code_gen(CodeGen *g) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (var->value->type->id == ZigTypeIdComptimeInt) {
|
||||
if (var->var_type->id == ZigTypeIdComptimeInt) {
|
||||
// Generate debug info for it but that's it.
|
||||
ConstExprValue *const_val = var->value;
|
||||
ConstExprValue *const_val = var->const_value;
|
||||
assert(const_val->special != ConstValSpecialRuntime);
|
||||
if (const_val->type != var->var_type) {
|
||||
zig_panic("TODO debug info for var with ptr casted value");
|
||||
}
|
||||
size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
|
||||
if (bits_needed < 8) {
|
||||
bits_needed = 8;
|
||||
@@ -6158,7 +6341,7 @@ static void do_code_gen(CodeGen *g) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!type_has_bits(var->value->type))
|
||||
if (!type_has_bits(var->var_type))
|
||||
continue;
|
||||
|
||||
assert(var->decl_node);
|
||||
@@ -6167,9 +6350,9 @@ static void do_code_gen(CodeGen *g) {
|
||||
if (var->linkage == VarLinkageExternal) {
|
||||
LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
|
||||
if (existing_llvm_var) {
|
||||
global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->value->type->type_ref, 0));
|
||||
global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0));
|
||||
} else {
|
||||
global_value = LLVMAddGlobal(g->module, var->value->type->type_ref, buf_ptr(&var->name));
|
||||
global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));
|
||||
// TODO debug info for the extern variable
|
||||
|
||||
LLVMSetLinkage(global_value, LLVMExternalLinkage);
|
||||
@@ -6180,9 +6363,9 @@ static void do_code_gen(CodeGen *g) {
|
||||
} else {
|
||||
bool exported = (var->linkage == VarLinkageExport);
|
||||
const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
|
||||
render_const_val(g, var->value, mangled_name);
|
||||
render_const_val_global(g, var->value, mangled_name);
|
||||
global_value = var->value->global_refs->llvm_global;
|
||||
render_const_val(g, var->const_value, mangled_name);
|
||||
render_const_val_global(g, var->const_value, mangled_name);
|
||||
global_value = var->const_value->global_refs->llvm_global;
|
||||
|
||||
if (exported) {
|
||||
LLVMSetLinkage(global_value, LLVMExternalLinkage);
|
||||
@@ -6194,8 +6377,10 @@ static void do_code_gen(CodeGen *g) {
|
||||
LLVMSetAlignment(global_value, var->align_bytes);
|
||||
|
||||
// TODO debug info for function pointers
|
||||
if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) {
|
||||
gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);
|
||||
// Here we use const_value->type because that's the type of the llvm global,
|
||||
// which we const ptr cast upon use to whatever it needs to be.
|
||||
if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) {
|
||||
gen_global_var(g, var, var->const_value->global_refs->llvm_value, var->const_value->type);
|
||||
}
|
||||
|
||||
LLVMSetGlobalConstant(global_value, var->gen_is_const);
|
||||
@@ -6281,8 +6466,8 @@ static void do_code_gen(CodeGen *g) {
|
||||
} else if (instruction->id == IrInstructionIdErrWrapCode) {
|
||||
IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
|
||||
slot = &err_wrap_code_instruction->tmp_ptr;
|
||||
} else if (instruction->id == IrInstructionIdCmpxchg) {
|
||||
IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction;
|
||||
} else if (instruction->id == IrInstructionIdCmpxchgGen) {
|
||||
IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
|
||||
slot = &cmpxchg_instruction->tmp_ptr;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
@@ -6304,12 +6489,12 @@ static void do_code_gen(CodeGen *g) {
|
||||
for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
|
||||
ZigVar *var = fn_table_entry->variable_list.at(var_i);
|
||||
|
||||
if (!type_has_bits(var->value->type)) {
|
||||
if (!type_has_bits(var->var_type)) {
|
||||
continue;
|
||||
}
|
||||
if (ir_get_var_is_comptime(var))
|
||||
continue;
|
||||
switch (type_requires_comptime(g, var->value->type)) {
|
||||
switch (type_requires_comptime(g, var->var_type)) {
|
||||
case ReqCompTimeInvalid:
|
||||
zig_unreachable();
|
||||
case ReqCompTimeYes:
|
||||
@@ -6319,11 +6504,11 @@ static void do_code_gen(CodeGen *g) {
|
||||
}
|
||||
|
||||
if (var->src_arg_index == SIZE_MAX) {
|
||||
var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
|
||||
var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
|
||||
|
||||
var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
|
||||
buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),
|
||||
var->value->type->di_type, !g->strip_debug_symbols, 0);
|
||||
var->var_type->di_type, !g->strip_debug_symbols, 0);
|
||||
|
||||
} else if (is_c_abi) {
|
||||
fn_walk_var.data.vars.var = var;
|
||||
@@ -6333,16 +6518,16 @@ static void do_code_gen(CodeGen *g) {
|
||||
ZigType *gen_type;
|
||||
FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
|
||||
|
||||
if (handle_is_ptr(var->value->type)) {
|
||||
if (handle_is_ptr(var->var_type)) {
|
||||
if (gen_info->is_byval) {
|
||||
gen_type = var->value->type;
|
||||
gen_type = var->var_type;
|
||||
} else {
|
||||
gen_type = gen_info->type;
|
||||
}
|
||||
var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);
|
||||
} else {
|
||||
gen_type = var->value->type;
|
||||
var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
|
||||
gen_type = var->var_type;
|
||||
var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
|
||||
}
|
||||
if (var->decl_node) {
|
||||
var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
|
||||
@@ -7458,9 +7643,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
|
||||
ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
|
||||
this_val->special = ConstValSpecialStatic;
|
||||
this_val->type = struct_type;
|
||||
this_val->data.x_struct.parent.id = ConstParentIdArray;
|
||||
this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array;
|
||||
this_val->data.x_struct.parent.data.p_array.elem_index = i;
|
||||
this_val->parent.id = ConstParentIdArray;
|
||||
this_val->parent.data.p_array.array_val = test_fn_array;
|
||||
this_val->parent.data.p_array.elem_index = i;
|
||||
this_val->data.x_struct.fields = create_const_vals(2);
|
||||
|
||||
ConstExprValue *name_field = &this_val->data.x_struct.fields[0];
|
||||
|
||||
1483
src/ir.cpp
1483
src/ir.cpp
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@
|
||||
bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
|
||||
bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
|
||||
|
||||
IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
|
||||
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
|
||||
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
|
||||
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
|
||||
IrExecutable *parent_exec);
|
||||
|
||||
@@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {
|
||||
static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) {
|
||||
const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
|
||||
const char *name = buf_ptr(&decl_var_instruction->var->name);
|
||||
if (decl_var_instruction->var_type) {
|
||||
@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
|
||||
}
|
||||
|
||||
static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
|
||||
fprintf(irp->f, "*");
|
||||
ir_print_other_instruction(irp, instruction->ptr);
|
||||
fprintf(irp->f, ".*");
|
||||
}
|
||||
|
||||
static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
|
||||
@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
|
||||
fprintf(irp->f, "*");
|
||||
static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
fprintf(irp->f, " != null");
|
||||
}
|
||||
|
||||
static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) {
|
||||
fprintf(irp->f, "&??*");
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) {
|
||||
fprintf(irp->f, "&");
|
||||
ir_print_other_instruction(irp, instruction->base_ptr);
|
||||
fprintf(irp->f, ".*.?");
|
||||
if (!instruction->safety_check_on) {
|
||||
fprintf(irp->f, " // no safety");
|
||||
}
|
||||
@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
|
||||
static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) {
|
||||
fprintf(irp->f, "@cmpxchg(");
|
||||
ir_print_other_instruction(irp, instruction->ptr);
|
||||
fprintf(irp->f, ", ");
|
||||
@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
|
||||
fprintf(irp->f, "@cmpxchg(");
|
||||
ir_print_other_instruction(irp, instruction->ptr);
|
||||
fprintf(irp->f, ", ");
|
||||
ir_print_other_instruction(irp, instruction->cmp_value);
|
||||
fprintf(irp->f, ", ");
|
||||
ir_print_other_instruction(irp, instruction->new_value);
|
||||
fprintf(irp->f, ", TODO print atomic orders)");
|
||||
}
|
||||
|
||||
static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
|
||||
fprintf(irp->f, "@fence(");
|
||||
ir_print_other_instruction(irp, instruction->order_value);
|
||||
@@ -820,13 +830,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
|
||||
}
|
||||
|
||||
static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
|
||||
fprintf(irp->f, "@unwrapErrorCode(");
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
fprintf(irp->f, "UnwrapErrorCode(");
|
||||
ir_print_other_instruction(irp, instruction->err_union);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
|
||||
fprintf(irp->f, "@unwrapErrorPayload(");
|
||||
fprintf(irp->f, "ErrorUnionFieldPayload(");
|
||||
ir_print_other_instruction(irp, instruction->value);
|
||||
fprintf(irp->f, ")");
|
||||
if (!instruction->safety_check_on) {
|
||||
@@ -879,7 +889,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
|
||||
static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) {
|
||||
fprintf(irp->f, "@ptrCast(");
|
||||
if (instruction->dest_type) {
|
||||
ir_print_other_instruction(irp, instruction->dest_type);
|
||||
@@ -889,6 +899,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) {
|
||||
fprintf(irp->f, "@ptrCast(");
|
||||
ir_print_other_instruction(irp, instruction->ptr);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
|
||||
fprintf(irp->f, "@bitCast(");
|
||||
if (instruction->dest_type) {
|
||||
@@ -900,7 +916,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
|
||||
}
|
||||
|
||||
static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
|
||||
fprintf(irp->f, "@widenOrShorten(");
|
||||
fprintf(irp->f, "WidenOrShorten(");
|
||||
ir_print_other_instruction(irp, instruction->target);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
@@ -1323,6 +1339,20 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) {
|
||||
ZigVar *var = decl_var_instruction->var;
|
||||
const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
|
||||
const char *name = buf_ptr(&decl_var_instruction->var->name);
|
||||
fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),
|
||||
var->align_bytes);
|
||||
|
||||
ir_print_other_instruction(irp, decl_var_instruction->init_value);
|
||||
if (decl_var_instruction->var->is_comptime != nullptr) {
|
||||
fprintf(irp->f, " // comptime = ");
|
||||
ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
|
||||
fprintf(irp->f, "@bswap(");
|
||||
if (instruction->type != nullptr) {
|
||||
@@ -1361,8 +1391,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdBinOp:
|
||||
ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
|
||||
break;
|
||||
case IrInstructionIdDeclVar:
|
||||
ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction);
|
||||
case IrInstructionIdDeclVarSrc:
|
||||
ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCast:
|
||||
ir_print_cast(irp, (IrInstructionCast *)instruction);
|
||||
@@ -1452,10 +1482,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
|
||||
break;
|
||||
case IrInstructionIdTestNonNull:
|
||||
ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction);
|
||||
ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction);
|
||||
break;
|
||||
case IrInstructionIdUnwrapOptional:
|
||||
ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction);
|
||||
case IrInstructionIdOptionalUnwrapPtr:
|
||||
ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCtz:
|
||||
ir_print_ctz(irp, (IrInstructionCtz *)instruction);
|
||||
@@ -1508,8 +1538,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdEmbedFile:
|
||||
ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCmpxchg:
|
||||
ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction);
|
||||
case IrInstructionIdCmpxchgSrc:
|
||||
ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCmpxchgGen:
|
||||
ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction);
|
||||
break;
|
||||
case IrInstructionIdFence:
|
||||
ir_print_fence(irp, (IrInstructionFence *)instruction);
|
||||
@@ -1607,8 +1640,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdTestComptime:
|
||||
ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
|
||||
break;
|
||||
case IrInstructionIdPtrCast:
|
||||
ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);
|
||||
case IrInstructionIdPtrCastSrc:
|
||||
ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction);
|
||||
break;
|
||||
case IrInstructionIdPtrCastGen:
|
||||
ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
|
||||
break;
|
||||
case IrInstructionIdBitCast:
|
||||
ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
|
||||
@@ -1775,6 +1811,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdCheckRuntimeScope:
|
||||
ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);
|
||||
break;
|
||||
case IrInstructionIdDeclVarGen:
|
||||
ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse
|
||||
else_body = ast_expect(pc, body_parser);
|
||||
}
|
||||
|
||||
assert(res->type == NodeTypeTestExpr);
|
||||
assert(res->type == NodeTypeIfOptional);
|
||||
if (err_payload != nullptr) {
|
||||
AstNodeTestExpr old = res->data.test_expr;
|
||||
res->type = NodeTypeIfErrorExpr;
|
||||
@@ -990,7 +990,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {
|
||||
if (requires_semi && else_body == nullptr)
|
||||
expect_token(pc, TokenIdSemicolon);
|
||||
|
||||
assert(res->type == NodeTypeTestExpr);
|
||||
assert(res->type == NodeTypeIfOptional);
|
||||
if (err_payload != nullptr) {
|
||||
AstNodeTestExpr old = res->data.test_expr;
|
||||
res->type = NodeTypeIfErrorExpr;
|
||||
@@ -2204,7 +2204,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {
|
||||
Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
|
||||
|
||||
PtrPayload payload;
|
||||
AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first);
|
||||
AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first);
|
||||
res->data.test_expr.target_node = condition;
|
||||
if (opt_payload.unwrap(&payload)) {
|
||||
res->data.test_expr.var_symbol = token_buf(payload.payload);
|
||||
@@ -2999,7 +2999,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
|
||||
visit_field(&node->data.if_err_expr.then_node, visit, context);
|
||||
visit_field(&node->data.if_err_expr.else_node, visit, context);
|
||||
break;
|
||||
case NodeTypeTestExpr:
|
||||
case NodeTypeIfOptional:
|
||||
visit_field(&node->data.test_expr.target_node, visit, context);
|
||||
visit_field(&node->data.test_expr.then_node, visit, context);
|
||||
visit_field(&node->data.test_expr.else_node, visit, context);
|
||||
|
||||
@@ -1307,32 +1307,29 @@ pub fn Watch(comptime V: type) type {
|
||||
|
||||
const test_tmp_dir = "std_event_fs_test";
|
||||
|
||||
test "write a file, watch it, write it again" {
|
||||
if (builtin.os == builtin.Os.windows) {
|
||||
// TODO this test is disabled on windows until the coroutine rewrite is finished.
|
||||
// https://github.com/ziglang/zig/issues/1363
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
|
||||
const allocator = &da.allocator;
|
||||
|
||||
// TODO move this into event loop too
|
||||
try os.makePath(allocator, test_tmp_dir);
|
||||
defer os.deleteTree(allocator, test_tmp_dir) catch {};
|
||||
|
||||
var loop: Loop = undefined;
|
||||
try loop.initMultiThreaded(allocator);
|
||||
defer loop.deinit();
|
||||
|
||||
var result: anyerror!void = error.ResultNeverWritten;
|
||||
const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
|
||||
defer cancel handle;
|
||||
|
||||
loop.run();
|
||||
return result;
|
||||
}
|
||||
// TODO this test is disabled until the coroutine rewrite is finished.
|
||||
//test "write a file, watch it, write it again" {
|
||||
// return error.SkipZigTest;
|
||||
// var da = std.heap.DirectAllocator.init();
|
||||
// defer da.deinit();
|
||||
//
|
||||
// const allocator = &da.allocator;
|
||||
//
|
||||
// // TODO move this into event loop too
|
||||
// try os.makePath(allocator, test_tmp_dir);
|
||||
// defer os.deleteTree(allocator, test_tmp_dir) catch {};
|
||||
//
|
||||
// var loop: Loop = undefined;
|
||||
// try loop.initMultiThreaded(allocator);
|
||||
// defer loop.deinit();
|
||||
//
|
||||
// var result: anyerror!void = error.ResultNeverWritten;
|
||||
// const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
|
||||
// defer cancel handle;
|
||||
//
|
||||
// loop.run();
|
||||
// return result;
|
||||
//}
|
||||
|
||||
async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {
|
||||
result.* = await (async testFsWatch(loop) catch unreachable);
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
const builtin = @import("builtin");
|
||||
|
||||
comptime {
|
||||
_ = @import("cases/align.zig");
|
||||
_ = @import("cases/alignof.zig");
|
||||
_ = @import("cases/array.zig");
|
||||
_ = @import("cases/asm.zig");
|
||||
_ = @import("cases/atomics.zig");
|
||||
_ = @import("cases/bitcast.zig");
|
||||
_ = @import("cases/bool.zig");
|
||||
_ = @import("cases/bswap.zig");
|
||||
_ = @import("cases/bitreverse.zig");
|
||||
_ = @import("cases/bugs/1076.zig");
|
||||
_ = @import("cases/bugs/1111.zig");
|
||||
_ = @import("cases/bugs/1277.zig");
|
||||
_ = @import("cases/bugs/1322.zig");
|
||||
_ = @import("cases/bugs/1381.zig");
|
||||
_ = @import("cases/bugs/1421.zig");
|
||||
_ = @import("cases/bugs/1442.zig");
|
||||
_ = @import("cases/bugs/1486.zig");
|
||||
_ = @import("cases/bugs/394.zig");
|
||||
_ = @import("cases/bugs/655.zig");
|
||||
_ = @import("cases/bugs/656.zig");
|
||||
_ = @import("cases/bugs/726.zig");
|
||||
_ = @import("cases/bugs/828.zig");
|
||||
_ = @import("cases/bugs/920.zig");
|
||||
_ = @import("cases/byval_arg_var.zig");
|
||||
_ = @import("cases/cancel.zig");
|
||||
_ = @import("cases/cast.zig");
|
||||
_ = @import("cases/const_slice_child.zig");
|
||||
_ = @import("cases/coroutine_await_struct.zig");
|
||||
_ = @import("cases/coroutines.zig");
|
||||
_ = @import("cases/defer.zig");
|
||||
_ = @import("cases/enum.zig");
|
||||
_ = @import("cases/enum_with_members.zig");
|
||||
_ = @import("cases/error.zig");
|
||||
_ = @import("cases/eval.zig");
|
||||
_ = @import("cases/field_parent_ptr.zig");
|
||||
_ = @import("cases/fn.zig");
|
||||
_ = @import("cases/fn_in_struct_in_comptime.zig");
|
||||
_ = @import("cases/for.zig");
|
||||
_ = @import("cases/generics.zig");
|
||||
_ = @import("cases/if.zig");
|
||||
_ = @import("cases/import.zig");
|
||||
_ = @import("cases/incomplete_struct_param_tld.zig");
|
||||
_ = @import("cases/inttoptr.zig");
|
||||
_ = @import("cases/ir_block_deps.zig");
|
||||
_ = @import("cases/math.zig");
|
||||
_ = @import("cases/merge_error_sets.zig");
|
||||
_ = @import("cases/misc.zig");
|
||||
_ = @import("cases/namespace_depends_on_compile_var/index.zig");
|
||||
_ = @import("cases/new_stack_call.zig");
|
||||
_ = @import("cases/null.zig");
|
||||
_ = @import("cases/optional.zig");
|
||||
_ = @import("cases/pointers.zig");
|
||||
_ = @import("cases/popcount.zig");
|
||||
_ = @import("cases/ptrcast.zig");
|
||||
_ = @import("cases/pub_enum/index.zig");
|
||||
_ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
|
||||
_ = @import("cases/reflection.zig");
|
||||
_ = @import("cases/sizeof_and_typeof.zig");
|
||||
_ = @import("cases/slice.zig");
|
||||
_ = @import("cases/struct.zig");
|
||||
_ = @import("cases/struct_contains_null_ptr_itself.zig");
|
||||
_ = @import("cases/struct_contains_slice_of_itself.zig");
|
||||
_ = @import("cases/switch.zig");
|
||||
_ = @import("cases/switch_prong_err_enum.zig");
|
||||
_ = @import("cases/switch_prong_implicit_cast.zig");
|
||||
_ = @import("cases/syntax.zig");
|
||||
_ = @import("cases/this.zig");
|
||||
_ = @import("cases/truncate.zig");
|
||||
_ = @import("cases/try.zig");
|
||||
_ = @import("cases/type_info.zig");
|
||||
_ = @import("cases/undefined.zig");
|
||||
_ = @import("cases/underscore.zig");
|
||||
_ = @import("cases/union.zig");
|
||||
_ = @import("cases/var_args.zig");
|
||||
_ = @import("cases/void.zig");
|
||||
_ = @import("cases/while.zig");
|
||||
_ = @import("cases/widening.zig");
|
||||
_ = @import("cases/bit_shifting.zig");
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
test "arrays" {
|
||||
var array: [5]u32 = undefined;
|
||||
|
||||
var i: u32 = 0;
|
||||
while (i < 5) {
|
||||
array[i] = i + 1;
|
||||
i = array[i];
|
||||
}
|
||||
|
||||
i = 0;
|
||||
var accumulator = u32(0);
|
||||
while (i < 5) {
|
||||
accumulator += array[i];
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
assert(accumulator == 15);
|
||||
assert(getArrayLen(array) == 5);
|
||||
}
|
||||
fn getArrayLen(a: []const u32) usize {
|
||||
return a.len;
|
||||
}
|
||||
|
||||
test "void arrays" {
|
||||
var array: [4]void = undefined;
|
||||
array[0] = void{};
|
||||
array[1] = array[2];
|
||||
assert(@sizeOf(@typeOf(array)) == 0);
|
||||
assert(array.len == 4);
|
||||
}
|
||||
|
||||
test "array literal" {
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
const ArrayDotLenConstExpr = struct {
|
||||
y: [some_array.len]u8,
|
||||
};
|
||||
const some_array = []u8{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
};
|
||||
|
||||
test "nested arrays" {
|
||||
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"));
|
||||
if (i == 2) assert(mem.eql(u8, s, "is"));
|
||||
if (i == 3) assert(mem.eql(u8, s, "my"));
|
||||
if (i == 4) assert(mem.eql(u8, s, "thing"));
|
||||
}
|
||||
}
|
||||
|
||||
var s_array: [8]Sub = undefined;
|
||||
const Sub = struct {
|
||||
b: u8,
|
||||
};
|
||||
const Str = struct {
|
||||
a: []Sub,
|
||||
};
|
||||
test "set global var array via slice embedded in struct" {
|
||||
var s = Str{ .a = s_array[0..] };
|
||||
|
||||
s.a[0].b = 1;
|
||||
s.a[1].b = 2;
|
||||
s.a[2].b = 3;
|
||||
|
||||
assert(s_array[0].b == 1);
|
||||
assert(s_array[1].b == 2);
|
||||
assert(s_array[2].b == 3);
|
||||
}
|
||||
|
||||
test "array literal with specified size" {
|
||||
var array = [2]u8{
|
||||
1,
|
||||
2,
|
||||
};
|
||||
assert(array[0] == 1);
|
||||
assert(array[1] == 2);
|
||||
}
|
||||
|
||||
test "array child property" {
|
||||
var x: [5]i32 = undefined;
|
||||
assert(@typeOf(x).Child == i32);
|
||||
}
|
||||
|
||||
test "array len property" {
|
||||
var x: [5]i32 = undefined;
|
||||
assert(@typeOf(x).len == 5);
|
||||
}
|
||||
|
||||
test "array len field" {
|
||||
var arr = [4]u8{ 0, 0, 0, 0 };
|
||||
var ptr = &arr;
|
||||
assert(arr.len == 4);
|
||||
comptime assert(arr.len == 4);
|
||||
assert(ptr.len == 4);
|
||||
comptime assert(ptr.len == 4);
|
||||
}
|
||||
|
||||
test "single-item pointer to array indexing and slicing" {
|
||||
testSingleItemPtrArrayIndexSlice();
|
||||
comptime testSingleItemPtrArrayIndexSlice();
|
||||
}
|
||||
|
||||
fn testSingleItemPtrArrayIndexSlice() void {
|
||||
var array = "aaaa";
|
||||
doSomeMangling(&array);
|
||||
assert(mem.eql(u8, "azya", array));
|
||||
}
|
||||
|
||||
fn doSomeMangling(array: *[4]u8) void {
|
||||
array[1] = 'z';
|
||||
array[2..3][0] = 'y';
|
||||
}
|
||||
|
||||
test "implicit cast single-item pointer" {
|
||||
testImplicitCastSingleItemPtr();
|
||||
comptime testImplicitCastSingleItemPtr();
|
||||
}
|
||||
|
||||
fn testImplicitCastSingleItemPtr() void {
|
||||
var byte: u8 = 100;
|
||||
const slice = (*[1]u8)(&byte)[0..];
|
||||
slice[0] += 1;
|
||||
assert(byte == 101);
|
||||
}
|
||||
|
||||
fn testArrayByValAtComptime(b: [2]u8) u8 {
|
||||
return b[0];
|
||||
}
|
||||
|
||||
test "comptime evalutating function that takes array by value" {
|
||||
const arr = []u8{ 0, 1 };
|
||||
_ = comptime testArrayByValAtComptime(arr);
|
||||
_ = comptime testArrayByValAtComptime(arr);
|
||||
}
|
||||
|
||||
test "implicit comptime in array type size" {
|
||||
var arr: [plusOne(10)]bool = undefined;
|
||||
assert(arr.len == 11);
|
||||
}
|
||||
|
||||
fn plusOne(x: u32) u32 {
|
||||
return x + 1;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
const config = @import("builtin");
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
comptime {
|
||||
if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
|
||||
asm volatile (
|
||||
\\.globl aoeu;
|
||||
\\.type aoeu, @function;
|
||||
\\.set aoeu, derp;
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
test "module level assembly" {
|
||||
if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
|
||||
assert(aoeu() == 1234);
|
||||
}
|
||||
}
|
||||
|
||||
test "output constraint modifiers" {
|
||||
// This is only testing compilation.
|
||||
var a: u32 = 3;
|
||||
asm volatile ("" : [_]"=m,r"(a) : : "");
|
||||
asm volatile ("" : [_]"=r,m"(a) : : "");
|
||||
}
|
||||
|
||||
test "alternative constraints" {
|
||||
// Make sure we allow commas as a separator for alternative constraints.
|
||||
var a: u32 = 3;
|
||||
asm volatile ("" : [_]"=r,m"(a) : [_]"r,m"(a) : "");
|
||||
}
|
||||
|
||||
test "sized integer/float in asm input" {
|
||||
asm volatile ("" : : [_]"m"(usize(3)) : "");
|
||||
asm volatile ("" : : [_]"m"(i15(-3)) : "");
|
||||
asm volatile ("" : : [_]"m"(u3(3)) : "");
|
||||
asm volatile ("" : : [_]"m"(i3(3)) : "");
|
||||
asm volatile ("" : : [_]"m"(u121(3)) : "");
|
||||
asm volatile ("" : : [_]"m"(i121(3)) : "");
|
||||
asm volatile ("" : : [_]"m"(f32(3.17)) : "");
|
||||
asm volatile ("" : : [_]"m"(f64(3.17)) : "");
|
||||
}
|
||||
|
||||
extern fn aoeu() i32;
|
||||
|
||||
export fn derp() i32 {
|
||||
return 1234;
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const minInt = std.math.minInt;
|
||||
|
||||
test "@bitreverse" {
|
||||
comptime testBitReverse();
|
||||
testBitReverse();
|
||||
}
|
||||
|
||||
fn testBitReverse() void {
|
||||
// using comptime_ints, unsigned
|
||||
assert(@bitreverse(u0, 0) == 0);
|
||||
assert(@bitreverse(u5, 0x12) == 0x9);
|
||||
assert(@bitreverse(u8, 0x12) == 0x48);
|
||||
assert(@bitreverse(u16, 0x1234) == 0x2c48);
|
||||
assert(@bitreverse(u24, 0x123456) == 0x6a2c48);
|
||||
assert(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
|
||||
assert(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
|
||||
assert(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
|
||||
assert(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
|
||||
assert(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
|
||||
assert(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
|
||||
|
||||
// using runtime uints, unsigned
|
||||
var num0: u0 = 0;
|
||||
assert(@bitreverse(u0, num0) == 0);
|
||||
var num5: u5 = 0x12;
|
||||
assert(@bitreverse(u5, num5) == 0x9);
|
||||
var num8: u8 = 0x12;
|
||||
assert(@bitreverse(u8, num8) == 0x48);
|
||||
var num16: u16 = 0x1234;
|
||||
assert(@bitreverse(u16, num16) == 0x2c48);
|
||||
var num24: u24 = 0x123456;
|
||||
assert(@bitreverse(u24, num24) == 0x6a2c48);
|
||||
var num32: u32 = 0x12345678;
|
||||
assert(@bitreverse(u32, num32) == 0x1e6a2c48);
|
||||
var num40: u40 = 0x123456789a;
|
||||
assert(@bitreverse(u40, num40) == 0x591e6a2c48);
|
||||
var num48: u48 = 0x123456789abc;
|
||||
assert(@bitreverse(u48, num48) == 0x3d591e6a2c48);
|
||||
var num56: u56 = 0x123456789abcde;
|
||||
assert(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
|
||||
var num64: u64 = 0x123456789abcdef1;
|
||||
assert(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
|
||||
var num128: u128 = 0x123456789abcdef11121314151617181;
|
||||
assert(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
|
||||
|
||||
// using comptime_ints, signed, positive
|
||||
assert(@bitreverse(i0, 0) == 0);
|
||||
assert(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8( 0x49)));
|
||||
assert(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16( 0x2c48)));
|
||||
assert(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24( 0x6a2c48)));
|
||||
assert(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32( 0x1e6a2c48)));
|
||||
assert(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40( 0x591e6a2c48)));
|
||||
assert(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48( 0x3d591e6a2c48)));
|
||||
assert(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56( 0x7b3d591e6a2c48)));
|
||||
assert(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64,u64(0x8f7b3d591e6a2c48)));
|
||||
assert(@bitreverse(i128, @bitCast(i128,u128(0x123456789abcdef11121314151617181))) == @bitCast(i128,u128(0x818e868a828c84888f7b3d591e6a2c48)));
|
||||
|
||||
// using comptime_ints, signed, negative. Compare to runtime ints returned from llvm.
|
||||
var neg5: i5 = minInt(i5) + 1;
|
||||
assert(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
|
||||
var neg8: i8 = -18;
|
||||
assert(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
|
||||
var neg16: i16 = -32694;
|
||||
assert(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
|
||||
var neg24: i24 = -6773785;
|
||||
assert(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
|
||||
var neg32: i32 = -16773785;
|
||||
assert(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
|
||||
var neg40: i40 = minInt(i40) + 12345;
|
||||
assert(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
|
||||
var neg48: i48 = minInt(i48) + 12345;
|
||||
assert(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
|
||||
var neg56: i56 = minInt(i56) + 12345;
|
||||
assert(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
|
||||
var neg64: i64 = minInt(i64) + 12345;
|
||||
assert(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
|
||||
var neg128: i128 = minInt(i128) + 12345;
|
||||
assert(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
test "@bswap" {
|
||||
comptime testByteSwap();
|
||||
testByteSwap();
|
||||
}
|
||||
|
||||
fn testByteSwap() void {
|
||||
assert(@bswap(u0, 0) == 0);
|
||||
assert(@bswap(u8, 0x12) == 0x12);
|
||||
assert(@bswap(u16, 0x1234) == 0x3412);
|
||||
assert(@bswap(u24, 0x123456) == 0x563412);
|
||||
assert(@bswap(u32, 0x12345678) == 0x78563412);
|
||||
assert(@bswap(u40, 0x123456789a) == 0x9a78563412);
|
||||
assert(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
|
||||
assert(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
|
||||
assert(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
|
||||
assert(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
|
||||
|
||||
assert(@bswap(i0, 0) == 0);
|
||||
assert(@bswap(i8, -50) == -50);
|
||||
assert(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
|
||||
assert(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
|
||||
assert(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
|
||||
assert(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
|
||||
assert(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
|
||||
assert(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
|
||||
assert(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
|
||||
assert(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
|
||||
@bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const a_namespace = @import("import/a_namespace.zig");
|
||||
|
||||
test "call fn via namespace lookup" {
|
||||
assert(a_namespace.foo() == 1234);
|
||||
}
|
||||
|
||||
test "importing the same thing gives the same import" {
|
||||
assert(@import("std") == @import("std"));
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
pub const EmptyStruct = struct {};
|
||||
|
||||
test "optional pointer to size zero struct" {
|
||||
var e = EmptyStruct{};
|
||||
var o: ?*EmptyStruct = &e;
|
||||
assert(o != null);
|
||||
}
|
||||
|
||||
test "equality compare nullable pointers" {
|
||||
testNullPtrsEql();
|
||||
comptime testNullPtrsEql();
|
||||
}
|
||||
|
||||
fn testNullPtrsEql() void {
|
||||
var number: i32 = 1234;
|
||||
|
||||
var x: ?*i32 = null;
|
||||
var y: ?*i32 = null;
|
||||
assert(x == y);
|
||||
y = &number;
|
||||
assert(x != y);
|
||||
assert(x != &number);
|
||||
assert(&number != x);
|
||||
x = &number;
|
||||
assert(x == y);
|
||||
assert(x == &number);
|
||||
assert(&number == x);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "@popCount" {
|
||||
comptime testPopCount();
|
||||
testPopCount();
|
||||
}
|
||||
|
||||
fn testPopCount() void {
|
||||
{
|
||||
var x: u32 = 0xaa;
|
||||
assert(@popCount(x) == 4);
|
||||
}
|
||||
{
|
||||
var x: u32 = 0xaaaaaaaa;
|
||||
assert(@popCount(x) == 16);
|
||||
}
|
||||
{
|
||||
var x: i16 = -1;
|
||||
assert(@popCount(x) == 16);
|
||||
}
|
||||
comptime {
|
||||
assert(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const mem = @import("std").mem;
|
||||
const reflection = @This();
|
||||
|
||||
test "reflection: array, pointer, optional, error union type child" {
|
||||
comptime {
|
||||
assert(([10]u8).Child == u8);
|
||||
assert((*u8).Child == u8);
|
||||
assert((anyerror!u8).Payload == u8);
|
||||
assert((?u8).Child == u8);
|
||||
}
|
||||
}
|
||||
|
||||
test "reflection: function return type, var args, and param types" {
|
||||
comptime {
|
||||
assert(@typeOf(dummy).ReturnType == i32);
|
||||
assert(!@typeOf(dummy).is_var_args);
|
||||
assert(@typeOf(dummy_varargs).is_var_args);
|
||||
assert(@typeOf(dummy).arg_count == 3);
|
||||
assert(@ArgType(@typeOf(dummy), 0) == bool);
|
||||
assert(@ArgType(@typeOf(dummy), 1) == i32);
|
||||
assert(@ArgType(@typeOf(dummy), 2) == f32);
|
||||
}
|
||||
}
|
||||
|
||||
fn dummy(a: bool, b: i32, c: f32) i32 {
|
||||
return 1234;
|
||||
}
|
||||
fn dummy_varargs(args: ...) void {}
|
||||
|
||||
test "reflection: struct member types and names" {
|
||||
comptime {
|
||||
assert(@memberCount(Foo) == 3);
|
||||
|
||||
assert(@memberType(Foo, 0) == i32);
|
||||
assert(@memberType(Foo, 1) == bool);
|
||||
assert(@memberType(Foo, 2) == void);
|
||||
|
||||
assert(mem.eql(u8, @memberName(Foo, 0), "one"));
|
||||
assert(mem.eql(u8, @memberName(Foo, 1), "two"));
|
||||
assert(mem.eql(u8, @memberName(Foo, 2), "three"));
|
||||
}
|
||||
}
|
||||
|
||||
test "reflection: enum member types and names" {
|
||||
comptime {
|
||||
assert(@memberCount(Bar) == 4);
|
||||
|
||||
assert(@memberType(Bar, 0) == void);
|
||||
assert(@memberType(Bar, 1) == i32);
|
||||
assert(@memberType(Bar, 2) == bool);
|
||||
assert(@memberType(Bar, 3) == f64);
|
||||
|
||||
assert(mem.eql(u8, @memberName(Bar, 0), "One"));
|
||||
assert(mem.eql(u8, @memberName(Bar, 1), "Two"));
|
||||
assert(mem.eql(u8, @memberName(Bar, 2), "Three"));
|
||||
assert(mem.eql(u8, @memberName(Bar, 3), "Four"));
|
||||
}
|
||||
}
|
||||
|
||||
test "reflection: @field" {
|
||||
var f = Foo{
|
||||
.one = 42,
|
||||
.two = true,
|
||||
.three = void{},
|
||||
};
|
||||
|
||||
assert(f.one == f.one);
|
||||
assert(@field(f, "o" ++ "ne") == f.one);
|
||||
assert(@field(f, "t" ++ "wo") == f.two);
|
||||
assert(@field(f, "th" ++ "ree") == f.three);
|
||||
assert(@field(Foo, "const" ++ "ant") == Foo.constant);
|
||||
assert(@field(Bar, "O" ++ "ne") == Bar.One);
|
||||
assert(@field(Bar, "T" ++ "wo") == Bar.Two);
|
||||
assert(@field(Bar, "Th" ++ "ree") == Bar.Three);
|
||||
assert(@field(Bar, "F" ++ "our") == Bar.Four);
|
||||
assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
|
||||
@field(f, "o" ++ "ne") = 4;
|
||||
assert(f.one == 4);
|
||||
}
|
||||
|
||||
const Foo = struct {
|
||||
const constant = 52;
|
||||
|
||||
one: i32,
|
||||
two: bool,
|
||||
three: void,
|
||||
};
|
||||
|
||||
const Bar = union(enum) {
|
||||
One: void,
|
||||
Two: i32,
|
||||
Three: bool,
|
||||
Four: f64,
|
||||
};
|
||||
@@ -1,69 +0,0 @@
|
||||
const builtin = @import("builtin");
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "@sizeOf and @typeOf" {
|
||||
const y: @typeOf(x) = 120;
|
||||
assert(@sizeOf(@typeOf(y)) == 2);
|
||||
}
|
||||
const x: u16 = 13;
|
||||
const z: @typeOf(x) = 19;
|
||||
|
||||
const A = struct {
|
||||
a: u8,
|
||||
b: u32,
|
||||
c: u8,
|
||||
d: u3,
|
||||
e: u5,
|
||||
f: u16,
|
||||
g: u16,
|
||||
};
|
||||
|
||||
const P = packed struct {
|
||||
a: u8,
|
||||
b: u32,
|
||||
c: u8,
|
||||
d: u3,
|
||||
e: u5,
|
||||
f: u16,
|
||||
g: u16,
|
||||
};
|
||||
|
||||
test "@byteOffsetOf" {
|
||||
// Packed structs have fixed memory layout
|
||||
assert(@byteOffsetOf(P, "a") == 0);
|
||||
assert(@byteOffsetOf(P, "b") == 1);
|
||||
assert(@byteOffsetOf(P, "c") == 5);
|
||||
assert(@byteOffsetOf(P, "d") == 6);
|
||||
assert(@byteOffsetOf(P, "e") == 6);
|
||||
assert(@byteOffsetOf(P, "f") == 7);
|
||||
assert(@byteOffsetOf(P, "g") == 9);
|
||||
|
||||
// Normal struct fields can be moved/padded
|
||||
var a: A = undefined;
|
||||
assert(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
|
||||
assert(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
|
||||
assert(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
|
||||
assert(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
|
||||
assert(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
|
||||
assert(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
|
||||
assert(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
|
||||
}
|
||||
|
||||
test "@bitOffsetOf" {
|
||||
// Packed structs have fixed memory layout
|
||||
assert(@bitOffsetOf(P, "a") == 0);
|
||||
assert(@bitOffsetOf(P, "b") == 8);
|
||||
assert(@bitOffsetOf(P, "c") == 40);
|
||||
assert(@bitOffsetOf(P, "d") == 48);
|
||||
assert(@bitOffsetOf(P, "e") == 51);
|
||||
assert(@bitOffsetOf(P, "f") == 56);
|
||||
assert(@bitOffsetOf(P, "g") == 72);
|
||||
|
||||
assert(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
|
||||
assert(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
|
||||
assert(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
|
||||
assert(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
|
||||
assert(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
|
||||
assert(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
|
||||
assert(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
|
||||
}
|
||||
@@ -1,264 +0,0 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const mem = @import("std").mem;
|
||||
const TypeInfo = @import("builtin").TypeInfo;
|
||||
const TypeId = @import("builtin").TypeId;
|
||||
|
||||
test "type info: tag type, void info" {
|
||||
testBasic();
|
||||
comptime testBasic();
|
||||
}
|
||||
|
||||
fn testBasic() void {
|
||||
assert(@TagType(TypeInfo) == TypeId);
|
||||
const void_info = @typeInfo(void);
|
||||
assert(TypeId(void_info) == TypeId.Void);
|
||||
assert(void_info.Void == {});
|
||||
}
|
||||
|
||||
test "type info: integer, floating point type info" {
|
||||
testIntFloat();
|
||||
comptime testIntFloat();
|
||||
}
|
||||
|
||||
fn testIntFloat() void {
|
||||
const u8_info = @typeInfo(u8);
|
||||
assert(TypeId(u8_info) == TypeId.Int);
|
||||
assert(!u8_info.Int.is_signed);
|
||||
assert(u8_info.Int.bits == 8);
|
||||
|
||||
const f64_info = @typeInfo(f64);
|
||||
assert(TypeId(f64_info) == TypeId.Float);
|
||||
assert(f64_info.Float.bits == 64);
|
||||
}
|
||||
|
||||
test "type info: pointer type info" {
|
||||
testPointer();
|
||||
comptime testPointer();
|
||||
}
|
||||
|
||||
fn testPointer() void {
|
||||
const u32_ptr_info = @typeInfo(*u32);
|
||||
assert(TypeId(u32_ptr_info) == TypeId.Pointer);
|
||||
assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
|
||||
assert(u32_ptr_info.Pointer.is_const == false);
|
||||
assert(u32_ptr_info.Pointer.is_volatile == false);
|
||||
assert(u32_ptr_info.Pointer.alignment == @alignOf(u32));
|
||||
assert(u32_ptr_info.Pointer.child == u32);
|
||||
}
|
||||
|
||||
test "type info: unknown length pointer type info" {
|
||||
testUnknownLenPtr();
|
||||
comptime testUnknownLenPtr();
|
||||
}
|
||||
|
||||
fn testUnknownLenPtr() void {
|
||||
const u32_ptr_info = @typeInfo([*]const volatile f64);
|
||||
assert(TypeId(u32_ptr_info) == TypeId.Pointer);
|
||||
assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
|
||||
assert(u32_ptr_info.Pointer.is_const == true);
|
||||
assert(u32_ptr_info.Pointer.is_volatile == true);
|
||||
assert(u32_ptr_info.Pointer.alignment == @alignOf(f64));
|
||||
assert(u32_ptr_info.Pointer.child == f64);
|
||||
}
|
||||
|
||||
test "type info: slice type info" {
|
||||
testSlice();
|
||||
comptime testSlice();
|
||||
}
|
||||
|
||||
fn testSlice() void {
|
||||
const u32_slice_info = @typeInfo([]u32);
|
||||
assert(TypeId(u32_slice_info) == TypeId.Pointer);
|
||||
assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
|
||||
assert(u32_slice_info.Pointer.is_const == false);
|
||||
assert(u32_slice_info.Pointer.is_volatile == false);
|
||||
assert(u32_slice_info.Pointer.alignment == 4);
|
||||
assert(u32_slice_info.Pointer.child == u32);
|
||||
}
|
||||
|
||||
test "type info: array type info" {
|
||||
testArray();
|
||||
comptime testArray();
|
||||
}
|
||||
|
||||
fn testArray() void {
|
||||
const arr_info = @typeInfo([42]bool);
|
||||
assert(TypeId(arr_info) == TypeId.Array);
|
||||
assert(arr_info.Array.len == 42);
|
||||
assert(arr_info.Array.child == bool);
|
||||
}
|
||||
|
||||
test "type info: optional type info" {
|
||||
testOptional();
|
||||
comptime testOptional();
|
||||
}
|
||||
|
||||
fn testOptional() void {
|
||||
const null_info = @typeInfo(?void);
|
||||
assert(TypeId(null_info) == TypeId.Optional);
|
||||
assert(null_info.Optional.child == void);
|
||||
}
|
||||
|
||||
test "type info: promise info" {
|
||||
testPromise();
|
||||
comptime testPromise();
|
||||
}
|
||||
|
||||
fn testPromise() void {
|
||||
const null_promise_info = @typeInfo(promise);
|
||||
assert(TypeId(null_promise_info) == TypeId.Promise);
|
||||
assert(null_promise_info.Promise.child == null);
|
||||
|
||||
const promise_info = @typeInfo(promise->usize);
|
||||
assert(TypeId(promise_info) == TypeId.Promise);
|
||||
assert(promise_info.Promise.child.? == usize);
|
||||
}
|
||||
|
||||
test "type info: error set, error union info" {
|
||||
testErrorSet();
|
||||
comptime testErrorSet();
|
||||
}
|
||||
|
||||
fn testErrorSet() void {
|
||||
const TestErrorSet = error{
|
||||
First,
|
||||
Second,
|
||||
Third,
|
||||
};
|
||||
|
||||
const error_set_info = @typeInfo(TestErrorSet);
|
||||
assert(TypeId(error_set_info) == TypeId.ErrorSet);
|
||||
assert(error_set_info.ErrorSet.errors.len == 3);
|
||||
assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
|
||||
assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
|
||||
|
||||
const error_union_info = @typeInfo(TestErrorSet!usize);
|
||||
assert(TypeId(error_union_info) == TypeId.ErrorUnion);
|
||||
assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
|
||||
assert(error_union_info.ErrorUnion.payload == usize);
|
||||
}
|
||||
|
||||
test "type info: enum info" {
|
||||
testEnum();
|
||||
comptime testEnum();
|
||||
}
|
||||
|
||||
fn testEnum() void {
|
||||
const Os = enum {
|
||||
Windows,
|
||||
Macos,
|
||||
Linux,
|
||||
FreeBSD,
|
||||
};
|
||||
|
||||
const os_info = @typeInfo(Os);
|
||||
assert(TypeId(os_info) == TypeId.Enum);
|
||||
assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
|
||||
assert(os_info.Enum.fields.len == 4);
|
||||
assert(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
|
||||
assert(os_info.Enum.fields[3].value == 3);
|
||||
assert(os_info.Enum.tag_type == u2);
|
||||
assert(os_info.Enum.defs.len == 0);
|
||||
}
|
||||
|
||||
test "type info: union info" {
|
||||
testUnion();
|
||||
comptime testUnion();
|
||||
}
|
||||
|
||||
fn testUnion() void {
|
||||
const typeinfo_info = @typeInfo(TypeInfo);
|
||||
assert(TypeId(typeinfo_info) == TypeId.Union);
|
||||
assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
|
||||
assert(typeinfo_info.Union.tag_type.? == TypeId);
|
||||
assert(typeinfo_info.Union.fields.len == 24);
|
||||
assert(typeinfo_info.Union.fields[4].enum_field != null);
|
||||
assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
|
||||
assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
|
||||
assert(typeinfo_info.Union.defs.len == 20);
|
||||
|
||||
const TestNoTagUnion = union {
|
||||
Foo: void,
|
||||
Bar: u32,
|
||||
};
|
||||
|
||||
const notag_union_info = @typeInfo(TestNoTagUnion);
|
||||
assert(TypeId(notag_union_info) == TypeId.Union);
|
||||
assert(notag_union_info.Union.tag_type == null);
|
||||
assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
|
||||
assert(notag_union_info.Union.fields.len == 2);
|
||||
assert(notag_union_info.Union.fields[0].enum_field == null);
|
||||
assert(notag_union_info.Union.fields[1].field_type == u32);
|
||||
|
||||
const TestExternUnion = extern union {
|
||||
foo: *c_void,
|
||||
};
|
||||
|
||||
const extern_union_info = @typeInfo(TestExternUnion);
|
||||
assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
|
||||
assert(extern_union_info.Union.tag_type == null);
|
||||
assert(extern_union_info.Union.fields[0].enum_field == null);
|
||||
assert(extern_union_info.Union.fields[0].field_type == *c_void);
|
||||
}
|
||||
|
||||
test "type info: struct info" {
|
||||
testStruct();
|
||||
comptime testStruct();
|
||||
}
|
||||
|
||||
fn testStruct() void {
|
||||
const struct_info = @typeInfo(TestStruct);
|
||||
assert(TypeId(struct_info) == TypeId.Struct);
|
||||
assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
|
||||
assert(struct_info.Struct.fields.len == 3);
|
||||
assert(struct_info.Struct.fields[1].offset == null);
|
||||
assert(struct_info.Struct.fields[2].field_type == *TestStruct);
|
||||
assert(struct_info.Struct.defs.len == 2);
|
||||
assert(struct_info.Struct.defs[0].is_pub);
|
||||
assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
|
||||
assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
|
||||
assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
|
||||
assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
|
||||
}
|
||||
|
||||
const TestStruct = packed struct {
|
||||
const Self = @This();
|
||||
|
||||
fieldA: usize,
|
||||
fieldB: void,
|
||||
fieldC: *Self,
|
||||
|
||||
pub fn foo(self: *const Self) void {}
|
||||
};
|
||||
|
||||
test "type info: function type info" {
|
||||
testFunction();
|
||||
comptime testFunction();
|
||||
}
|
||||
|
||||
fn testFunction() void {
|
||||
const fn_info = @typeInfo(@typeOf(foo));
|
||||
assert(TypeId(fn_info) == TypeId.Fn);
|
||||
assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
|
||||
assert(fn_info.Fn.is_generic);
|
||||
assert(fn_info.Fn.args.len == 2);
|
||||
assert(fn_info.Fn.is_var_args);
|
||||
assert(fn_info.Fn.return_type == null);
|
||||
assert(fn_info.Fn.async_allocator_type == null);
|
||||
|
||||
const test_instance: TestStruct = undefined;
|
||||
const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
|
||||
assert(TypeId(bound_fn_info) == TypeId.BoundFn);
|
||||
assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
|
||||
}
|
||||
|
||||
fn foo(comptime a: usize, b: bool, args: ...) usize {
|
||||
return 0;
|
||||
}
|
||||
|
||||
test "typeInfo with comptime parameter in struct fn def" {
|
||||
const S = struct {
|
||||
pub fn func(comptime x: f32) void {}
|
||||
};
|
||||
comptime var info = @typeInfo(S);
|
||||
}
|
||||
@@ -3220,7 +3220,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ return 2;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:15: error: unable to infer expression type",
|
||||
".tmp_source.zig:2:15: error: values of type 'comptime_int' must be comptime known",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
@@ -3566,7 +3566,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\
|
||||
\\export fn entry() usize { return @sizeOf(@typeOf(a)); }
|
||||
,
|
||||
".tmp_source.zig:2:11: error: expected type, found 'i32'",
|
||||
".tmp_source.zig:2:11: error: expected type 'type', found 'i32'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
|
||||
80
test/stage1/behavior.zig
Normal file
80
test/stage1/behavior.zig
Normal file
@@ -0,0 +1,80 @@
|
||||
comptime {
|
||||
_ = @import("behavior/align.zig");
|
||||
_ = @import("behavior/alignof.zig");
|
||||
_ = @import("behavior/array.zig");
|
||||
_ = @import("behavior/asm.zig");
|
||||
_ = @import("behavior/atomics.zig");
|
||||
_ = @import("behavior/bit_shifting.zig");
|
||||
_ = @import("behavior/bitcast.zig");
|
||||
_ = @import("behavior/bitreverse.zig");
|
||||
_ = @import("behavior/bool.zig");
|
||||
_ = @import("behavior/bswap.zig");
|
||||
_ = @import("behavior/bugs/1076.zig");
|
||||
_ = @import("behavior/bugs/1111.zig");
|
||||
_ = @import("behavior/bugs/1277.zig");
|
||||
_ = @import("behavior/bugs/1322.zig");
|
||||
_ = @import("behavior/bugs/1381.zig");
|
||||
_ = @import("behavior/bugs/1421.zig");
|
||||
_ = @import("behavior/bugs/1442.zig");
|
||||
_ = @import("behavior/bugs/1486.zig");
|
||||
_ = @import("behavior/bugs/394.zig");
|
||||
_ = @import("behavior/bugs/655.zig");
|
||||
_ = @import("behavior/bugs/656.zig");
|
||||
_ = @import("behavior/bugs/726.zig");
|
||||
_ = @import("behavior/bugs/828.zig");
|
||||
_ = @import("behavior/bugs/920.zig");
|
||||
_ = @import("behavior/byval_arg_var.zig");
|
||||
_ = @import("behavior/cancel.zig");
|
||||
_ = @import("behavior/cast.zig");
|
||||
_ = @import("behavior/const_slice_child.zig");
|
||||
_ = @import("behavior/coroutine_await_struct.zig");
|
||||
_ = @import("behavior/coroutines.zig");
|
||||
_ = @import("behavior/defer.zig");
|
||||
_ = @import("behavior/enum.zig");
|
||||
_ = @import("behavior/enum_with_members.zig");
|
||||
_ = @import("behavior/error.zig");
|
||||
_ = @import("behavior/eval.zig");
|
||||
_ = @import("behavior/field_parent_ptr.zig");
|
||||
_ = @import("behavior/fn.zig");
|
||||
_ = @import("behavior/fn_in_struct_in_comptime.zig");
|
||||
_ = @import("behavior/for.zig");
|
||||
_ = @import("behavior/generics.zig");
|
||||
_ = @import("behavior/if.zig");
|
||||
_ = @import("behavior/import.zig");
|
||||
_ = @import("behavior/incomplete_struct_param_tld.zig");
|
||||
_ = @import("behavior/inttoptr.zig");
|
||||
_ = @import("behavior/ir_block_deps.zig");
|
||||
_ = @import("behavior/math.zig");
|
||||
_ = @import("behavior/merge_error_sets.zig");
|
||||
_ = @import("behavior/misc.zig");
|
||||
_ = @import("behavior/namespace_depends_on_compile_var/index.zig");
|
||||
_ = @import("behavior/new_stack_call.zig");
|
||||
_ = @import("behavior/null.zig");
|
||||
_ = @import("behavior/optional.zig");
|
||||
_ = @import("behavior/pointers.zig");
|
||||
_ = @import("behavior/popcount.zig");
|
||||
_ = @import("behavior/ptrcast.zig");
|
||||
_ = @import("behavior/pub_enum/index.zig");
|
||||
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
|
||||
_ = @import("behavior/reflection.zig");
|
||||
_ = @import("behavior/sizeof_and_typeof.zig");
|
||||
_ = @import("behavior/slice.zig");
|
||||
_ = @import("behavior/struct.zig");
|
||||
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
|
||||
_ = @import("behavior/struct_contains_slice_of_itself.zig");
|
||||
_ = @import("behavior/switch.zig");
|
||||
_ = @import("behavior/switch_prong_err_enum.zig");
|
||||
_ = @import("behavior/switch_prong_implicit_cast.zig");
|
||||
_ = @import("behavior/syntax.zig");
|
||||
_ = @import("behavior/this.zig");
|
||||
_ = @import("behavior/truncate.zig");
|
||||
_ = @import("behavior/try.zig");
|
||||
_ = @import("behavior/type_info.zig");
|
||||
_ = @import("behavior/undefined.zig");
|
||||
_ = @import("behavior/underscore.zig");
|
||||
_ = @import("behavior/union.zig");
|
||||
_ = @import("behavior/var_args.zig");
|
||||
_ = @import("behavior/void.zig");
|
||||
_ = @import("behavior/while.zig");
|
||||
_ = @import("behavior/widening.zig");
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
var foo: u8 align(4) = 100;
|
||||
|
||||
test "global variable alignment" {
|
||||
assert(@typeOf(&foo).alignment == 4);
|
||||
assert(@typeOf(&foo) == *align(4) u8);
|
||||
assertOrPanic(@typeOf(&foo).alignment == 4);
|
||||
assertOrPanic(@typeOf(&foo) == *align(4) u8);
|
||||
const slice = (*[1]u8)(&foo)[0..];
|
||||
assert(@typeOf(slice) == []align(4) u8);
|
||||
assertOrPanic(@typeOf(slice) == []align(4) u8);
|
||||
}
|
||||
|
||||
fn derp() align(@sizeOf(usize) * 2) i32 {
|
||||
@@ -17,9 +17,9 @@ fn noop1() align(1) void {}
|
||||
fn noop4() align(4) void {}
|
||||
|
||||
test "function alignment" {
|
||||
assert(derp() == 1234);
|
||||
assert(@typeOf(noop1) == fn () align(1) void);
|
||||
assert(@typeOf(noop4) == fn () align(4) void);
|
||||
assertOrPanic(derp() == 1234);
|
||||
assertOrPanic(@typeOf(noop1) == fn () align(1) void);
|
||||
assertOrPanic(@typeOf(noop4) == fn () align(4) void);
|
||||
noop1();
|
||||
noop4();
|
||||
}
|
||||
@@ -30,7 +30,7 @@ var baz: packed struct {
|
||||
} = undefined;
|
||||
|
||||
test "packed struct alignment" {
|
||||
assert(@typeOf(&baz.b) == *align(1) u32);
|
||||
assertOrPanic(@typeOf(&baz.b) == *align(1) u32);
|
||||
}
|
||||
|
||||
const blah: packed struct {
|
||||
@@ -40,17 +40,17 @@ const blah: packed struct {
|
||||
} = undefined;
|
||||
|
||||
test "bit field alignment" {
|
||||
assert(@typeOf(&blah.b) == *align(1:3:1) const u3);
|
||||
assertOrPanic(@typeOf(&blah.b) == *align(1:3:1) const u3);
|
||||
}
|
||||
|
||||
test "default alignment allows unspecified in type syntax" {
|
||||
assert(*u32 == *align(@alignOf(u32)) u32);
|
||||
assertOrPanic(*u32 == *align(@alignOf(u32)) u32);
|
||||
}
|
||||
|
||||
test "implicitly decreasing pointer alignment" {
|
||||
const a: u32 align(4) = 3;
|
||||
const b: u32 align(8) = 4;
|
||||
assert(addUnaligned(&a, &b) == 7);
|
||||
assertOrPanic(addUnaligned(&a, &b) == 7);
|
||||
}
|
||||
|
||||
fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
|
||||
@@ -60,7 +60,7 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
|
||||
test "implicitly decreasing slice alignment" {
|
||||
const a: u32 align(4) = 3;
|
||||
const b: u32 align(8) = 4;
|
||||
assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
|
||||
assertOrPanic(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
|
||||
}
|
||||
fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
|
||||
return a[0] + b[0];
|
||||
@@ -77,7 +77,7 @@ fn testBytesAlign(b: u8) void {
|
||||
b,
|
||||
};
|
||||
const ptr = @ptrCast(*u32, &bytes[0]);
|
||||
assert(ptr.* == 0x33333333);
|
||||
assertOrPanic(ptr.* == 0x33333333);
|
||||
}
|
||||
|
||||
test "specifying alignment allows slice cast" {
|
||||
@@ -91,13 +91,13 @@ fn testBytesAlignSlice(b: u8) void {
|
||||
b,
|
||||
};
|
||||
const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
|
||||
assert(slice[0] == 0x33333333);
|
||||
assertOrPanic(slice[0] == 0x33333333);
|
||||
}
|
||||
|
||||
test "@alignCast pointers" {
|
||||
var x: u32 align(4) = 1;
|
||||
expectsOnly1(&x);
|
||||
assert(x == 2);
|
||||
assertOrPanic(x == 2);
|
||||
}
|
||||
fn expectsOnly1(x: *align(1) u32) void {
|
||||
expects4(@alignCast(4, x));
|
||||
@@ -113,7 +113,7 @@ test "@alignCast slices" {
|
||||
};
|
||||
const slice = array[0..];
|
||||
sliceExpectsOnly1(slice);
|
||||
assert(slice[0] == 2);
|
||||
assertOrPanic(slice[0] == 2);
|
||||
}
|
||||
fn sliceExpectsOnly1(slice: []align(1) u32) void {
|
||||
sliceExpects4(@alignCast(4, slice));
|
||||
@@ -128,7 +128,7 @@ test "implicitly decreasing fn alignment" {
|
||||
}
|
||||
|
||||
fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void {
|
||||
assert(ptr() == answer);
|
||||
assertOrPanic(ptr() == answer);
|
||||
}
|
||||
|
||||
fn alignedSmall() align(8) i32 {
|
||||
@@ -139,7 +139,7 @@ fn alignedBig() align(16) i32 {
|
||||
}
|
||||
|
||||
test "@alignCast functions" {
|
||||
assert(fnExpectsOnly1(simple4) == 0x19);
|
||||
assertOrPanic(fnExpectsOnly1(simple4) == 0x19);
|
||||
}
|
||||
fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
|
||||
return fnExpects4(@alignCast(4, ptr));
|
||||
@@ -152,9 +152,9 @@ fn simple4() align(4) i32 {
|
||||
}
|
||||
|
||||
test "generic function with align param" {
|
||||
assert(whyWouldYouEverDoThis(1) == 0x1);
|
||||
assert(whyWouldYouEverDoThis(4) == 0x1);
|
||||
assert(whyWouldYouEverDoThis(8) == 0x1);
|
||||
assertOrPanic(whyWouldYouEverDoThis(1) == 0x1);
|
||||
assertOrPanic(whyWouldYouEverDoThis(4) == 0x1);
|
||||
assertOrPanic(whyWouldYouEverDoThis(8) == 0x1);
|
||||
}
|
||||
|
||||
fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
|
||||
@@ -164,28 +164,28 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
|
||||
test "@ptrCast preserves alignment of bigger source" {
|
||||
var x: u32 align(16) = 1234;
|
||||
const ptr = @ptrCast(*u8, &x);
|
||||
assert(@typeOf(ptr) == *align(16) u8);
|
||||
assertOrPanic(@typeOf(ptr) == *align(16) u8);
|
||||
}
|
||||
|
||||
test "runtime known array index has best alignment possible" {
|
||||
// take full advantage of over-alignment
|
||||
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);
|
||||
assertOrPanic(@typeOf(&array[0]) == *align(4) u8);
|
||||
assertOrPanic(@typeOf(&array[1]) == *u8);
|
||||
assertOrPanic(@typeOf(&array[2]) == *align(2) u8);
|
||||
assertOrPanic(@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 };
|
||||
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);
|
||||
assertOrPanic(@typeOf(&bigger[0]) == *align(2) u64);
|
||||
assertOrPanic(@typeOf(&bigger[1]) == *align(2) u64);
|
||||
assertOrPanic(@typeOf(&bigger[2]) == *align(2) u64);
|
||||
assertOrPanic(@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 };
|
||||
comptime assert(@typeOf(smaller[0..]) == []align(2) u32);
|
||||
comptime assert(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
|
||||
comptime assertOrPanic(@typeOf(smaller[0..]) == []align(2) u32);
|
||||
comptime assertOrPanic(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
|
||||
testIndex(smaller[0..].ptr, 0, *align(2) u32);
|
||||
testIndex(smaller[0..].ptr, 1, *align(2) u32);
|
||||
testIndex(smaller[0..].ptr, 2, *align(2) u32);
|
||||
@@ -198,14 +198,14 @@ test "runtime known array index has best alignment possible" {
|
||||
testIndex2(array[0..].ptr, 3, *u8);
|
||||
}
|
||||
fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
|
||||
comptime assert(@typeOf(&smaller[index]) == T);
|
||||
comptime assertOrPanic(@typeOf(&smaller[index]) == T);
|
||||
}
|
||||
fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void {
|
||||
comptime assert(@typeOf(&ptr[index]) == T);
|
||||
comptime assertOrPanic(@typeOf(&ptr[index]) == T);
|
||||
}
|
||||
|
||||
test "alignstack" {
|
||||
assert(fnWithAlignedStack() == 1234);
|
||||
assertOrPanic(fnWithAlignedStack() == 1234);
|
||||
}
|
||||
|
||||
fn fnWithAlignedStack() i32 {
|
||||
@@ -214,7 +214,7 @@ fn fnWithAlignedStack() i32 {
|
||||
}
|
||||
|
||||
test "alignment of structs" {
|
||||
assert(@alignOf(struct {
|
||||
assertOrPanic(@alignOf(struct {
|
||||
a: i32,
|
||||
b: *i32,
|
||||
}) == @alignOf(usize));
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const builtin = @import("builtin");
|
||||
const maxInt = std.math.maxInt;
|
||||
|
||||
@@ -10,8 +10,9 @@ const Foo = struct {
|
||||
};
|
||||
|
||||
test "@alignOf(T) before referencing T" {
|
||||
comptime assert(@alignOf(Foo) != maxInt(usize));
|
||||
comptime assertOrPanic(@alignOf(Foo) != maxInt(usize));
|
||||
if (builtin.arch == builtin.Arch.x86_64) {
|
||||
comptime assert(@alignOf(Foo) == 4);
|
||||
comptime assertOrPanic(@alignOf(Foo) == 4);
|
||||
}
|
||||
}
|
||||
|
||||
270
test/stage1/behavior/array.zig
Normal file
270
test/stage1/behavior/array.zig
Normal file
@@ -0,0 +1,270 @@
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
test "arrays" {
|
||||
var array: [5]u32 = undefined;
|
||||
|
||||
var i: u32 = 0;
|
||||
while (i < 5) {
|
||||
array[i] = i + 1;
|
||||
i = array[i];
|
||||
}
|
||||
|
||||
i = 0;
|
||||
var accumulator = u32(0);
|
||||
while (i < 5) {
|
||||
accumulator += array[i];
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
assertOrPanic(accumulator == 15);
|
||||
assertOrPanic(getArrayLen(array) == 5);
|
||||
}
|
||||
fn getArrayLen(a: []const u32) usize {
|
||||
return a.len;
|
||||
}
|
||||
|
||||
test "void arrays" {
|
||||
var array: [4]void = undefined;
|
||||
array[0] = void{};
|
||||
array[1] = array[2];
|
||||
assertOrPanic(@sizeOf(@typeOf(array)) == 0);
|
||||
assertOrPanic(array.len == 4);
|
||||
}
|
||||
|
||||
test "array literal" {
|
||||
const hex_mult = []u16{
|
||||
4096,
|
||||
256,
|
||||
16,
|
||||
1,
|
||||
};
|
||||
|
||||
assertOrPanic(hex_mult.len == 4);
|
||||
assertOrPanic(hex_mult[1] == 256);
|
||||
}
|
||||
|
||||
test "array dot len const expr" {
|
||||
assertOrPanic(comptime x: {
|
||||
break :x some_array.len == 4;
|
||||
});
|
||||
}
|
||||
|
||||
const ArrayDotLenConstExpr = struct {
|
||||
y: [some_array.len]u8,
|
||||
};
|
||||
const some_array = []u8{
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
};
|
||||
|
||||
test "nested arrays" {
|
||||
const array_of_strings = [][]const u8{
|
||||
"hello",
|
||||
"this",
|
||||
"is",
|
||||
"my",
|
||||
"thing",
|
||||
};
|
||||
for (array_of_strings) |s, i| {
|
||||
if (i == 0) assertOrPanic(mem.eql(u8, s, "hello"));
|
||||
if (i == 1) assertOrPanic(mem.eql(u8, s, "this"));
|
||||
if (i == 2) assertOrPanic(mem.eql(u8, s, "is"));
|
||||
if (i == 3) assertOrPanic(mem.eql(u8, s, "my"));
|
||||
if (i == 4) assertOrPanic(mem.eql(u8, s, "thing"));
|
||||
}
|
||||
}
|
||||
|
||||
var s_array: [8]Sub = undefined;
|
||||
const Sub = struct {
|
||||
b: u8,
|
||||
};
|
||||
const Str = struct {
|
||||
a: []Sub,
|
||||
};
|
||||
test "set global var array via slice embedded in struct" {
|
||||
var s = Str{ .a = s_array[0..] };
|
||||
|
||||
s.a[0].b = 1;
|
||||
s.a[1].b = 2;
|
||||
s.a[2].b = 3;
|
||||
|
||||
assertOrPanic(s_array[0].b == 1);
|
||||
assertOrPanic(s_array[1].b == 2);
|
||||
assertOrPanic(s_array[2].b == 3);
|
||||
}
|
||||
|
||||
test "array literal with specified size" {
|
||||
var array = [2]u8{
|
||||
1,
|
||||
2,
|
||||
};
|
||||
assertOrPanic(array[0] == 1);
|
||||
assertOrPanic(array[1] == 2);
|
||||
}
|
||||
|
||||
test "array child property" {
|
||||
var x: [5]i32 = undefined;
|
||||
assertOrPanic(@typeOf(x).Child == i32);
|
||||
}
|
||||
|
||||
test "array len property" {
|
||||
var x: [5]i32 = undefined;
|
||||
assertOrPanic(@typeOf(x).len == 5);
|
||||
}
|
||||
|
||||
test "array len field" {
|
||||
var arr = [4]u8{ 0, 0, 0, 0 };
|
||||
var ptr = &arr;
|
||||
assertOrPanic(arr.len == 4);
|
||||
comptime assertOrPanic(arr.len == 4);
|
||||
assertOrPanic(ptr.len == 4);
|
||||
comptime assertOrPanic(ptr.len == 4);
|
||||
}
|
||||
|
||||
test "single-item pointer to array indexing and slicing" {
|
||||
testSingleItemPtrArrayIndexSlice();
|
||||
comptime testSingleItemPtrArrayIndexSlice();
|
||||
}
|
||||
|
||||
fn testSingleItemPtrArrayIndexSlice() void {
|
||||
var array = "aaaa";
|
||||
doSomeMangling(&array);
|
||||
assertOrPanic(mem.eql(u8, "azya", array));
|
||||
}
|
||||
|
||||
fn doSomeMangling(array: *[4]u8) void {
|
||||
array[1] = 'z';
|
||||
array[2..3][0] = 'y';
|
||||
}
|
||||
|
||||
test "implicit cast single-item pointer" {
|
||||
testImplicitCastSingleItemPtr();
|
||||
comptime testImplicitCastSingleItemPtr();
|
||||
}
|
||||
|
||||
fn testImplicitCastSingleItemPtr() void {
|
||||
var byte: u8 = 100;
|
||||
const slice = (*[1]u8)(&byte)[0..];
|
||||
slice[0] += 1;
|
||||
assertOrPanic(byte == 101);
|
||||
}
|
||||
|
||||
fn testArrayByValAtComptime(b: [2]u8) u8 {
|
||||
return b[0];
|
||||
}
|
||||
|
||||
test "comptime evalutating function that takes array by value" {
|
||||
const arr = []u8{ 0, 1 };
|
||||
_ = comptime testArrayByValAtComptime(arr);
|
||||
_ = comptime testArrayByValAtComptime(arr);
|
||||
}
|
||||
|
||||
test "implicit comptime in array type size" {
|
||||
var arr: [plusOne(10)]bool = undefined;
|
||||
assertOrPanic(arr.len == 11);
|
||||
}
|
||||
|
||||
fn plusOne(x: u32) u32 {
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
test "array literal as argument to function" {
|
||||
const S = struct {
|
||||
fn entry(two: i32) void {
|
||||
foo([]i32{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
});
|
||||
foo([]i32{
|
||||
1,
|
||||
two,
|
||||
3,
|
||||
});
|
||||
foo2(true, []i32{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
});
|
||||
foo2(true, []i32{
|
||||
1,
|
||||
two,
|
||||
3,
|
||||
});
|
||||
}
|
||||
fn foo(x: []const i32) void {
|
||||
assertOrPanic(x[0] == 1);
|
||||
assertOrPanic(x[1] == 2);
|
||||
assertOrPanic(x[2] == 3);
|
||||
}
|
||||
fn foo2(trash: bool, x: []const i32) void {
|
||||
assertOrPanic(trash);
|
||||
assertOrPanic(x[0] == 1);
|
||||
assertOrPanic(x[1] == 2);
|
||||
assertOrPanic(x[2] == 3);
|
||||
}
|
||||
};
|
||||
S.entry(2);
|
||||
comptime S.entry(2);
|
||||
}
|
||||
|
||||
test "double nested array to const slice cast in array literal" {
|
||||
const S = struct {
|
||||
fn entry(two: i32) void {
|
||||
const cases = [][]const []const i32{
|
||||
[][]const i32{[]i32{1}},
|
||||
[][]const i32{[]i32{ 2, 3 }},
|
||||
[][]const i32{
|
||||
[]i32{4},
|
||||
[]i32{ 5, 6, 7 },
|
||||
},
|
||||
};
|
||||
check(cases);
|
||||
|
||||
const cases2 = [][]const i32{
|
||||
[]i32{1},
|
||||
[]i32{ two, 3 },
|
||||
};
|
||||
assertOrPanic(cases2.len == 2);
|
||||
assertOrPanic(cases2[0].len == 1);
|
||||
assertOrPanic(cases2[0][0] == 1);
|
||||
assertOrPanic(cases2[1].len == 2);
|
||||
assertOrPanic(cases2[1][0] == 2);
|
||||
assertOrPanic(cases2[1][1] == 3);
|
||||
|
||||
const cases3 = [][]const []const i32{
|
||||
[][]const i32{[]i32{1}},
|
||||
[][]const i32{[]i32{ two, 3 }},
|
||||
[][]const i32{
|
||||
[]i32{4},
|
||||
[]i32{ 5, 6, 7 },
|
||||
},
|
||||
};
|
||||
check(cases3);
|
||||
}
|
||||
|
||||
fn check(cases: []const []const []const i32) void {
|
||||
assertOrPanic(cases.len == 3);
|
||||
assertOrPanic(cases[0].len == 1);
|
||||
assertOrPanic(cases[0][0].len == 1);
|
||||
assertOrPanic(cases[0][0][0] == 1);
|
||||
assertOrPanic(cases[1].len == 1);
|
||||
assertOrPanic(cases[1][0].len == 2);
|
||||
assertOrPanic(cases[1][0][0] == 2);
|
||||
assertOrPanic(cases[1][0][1] == 3);
|
||||
assertOrPanic(cases[2].len == 2);
|
||||
assertOrPanic(cases[2][0].len == 1);
|
||||
assertOrPanic(cases[2][0][0] == 4);
|
||||
assertOrPanic(cases[2][1].len == 3);
|
||||
assertOrPanic(cases[2][1][0] == 5);
|
||||
assertOrPanic(cases[2][1][1] == 6);
|
||||
assertOrPanic(cases[2][1][2] == 7);
|
||||
}
|
||||
};
|
||||
S.entry(2);
|
||||
comptime S.entry(2);
|
||||
}
|
||||
92
test/stage1/behavior/asm.zig
Normal file
92
test/stage1/behavior/asm.zig
Normal file
@@ -0,0 +1,92 @@
|
||||
const config = @import("builtin");
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
comptime {
|
||||
if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
|
||||
asm volatile (
|
||||
\\.globl aoeu;
|
||||
\\.type aoeu, @function;
|
||||
\\.set aoeu, derp;
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
test "module level assembly" {
|
||||
if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
|
||||
assertOrPanic(aoeu() == 1234);
|
||||
}
|
||||
}
|
||||
|
||||
test "output constraint modifiers" {
|
||||
// This is only testing compilation.
|
||||
var a: u32 = 3;
|
||||
asm volatile (""
|
||||
: [_] "=m,r" (a)
|
||||
:
|
||||
: ""
|
||||
);
|
||||
asm volatile (""
|
||||
: [_] "=r,m" (a)
|
||||
:
|
||||
: ""
|
||||
);
|
||||
}
|
||||
|
||||
test "alternative constraints" {
|
||||
// Make sure we allow commas as a separator for alternative constraints.
|
||||
var a: u32 = 3;
|
||||
asm volatile (""
|
||||
: [_] "=r,m" (a)
|
||||
: [_] "r,m" (a)
|
||||
: ""
|
||||
);
|
||||
}
|
||||
|
||||
test "sized integer/float in asm input" {
|
||||
asm volatile (""
|
||||
:
|
||||
: [_] "m" (usize(3))
|
||||
: ""
|
||||
);
|
||||
asm volatile (""
|
||||
:
|
||||
: [_] "m" (i15(-3))
|
||||
: ""
|
||||
);
|
||||
asm volatile (""
|
||||
:
|
||||
: [_] "m" (u3(3))
|
||||
: ""
|
||||
);
|
||||
asm volatile (""
|
||||
:
|
||||
: [_] "m" (i3(3))
|
||||
: ""
|
||||
);
|
||||
asm volatile (""
|
||||
:
|
||||
: [_] "m" (u121(3))
|
||||
: ""
|
||||
);
|
||||
asm volatile (""
|
||||
:
|
||||
: [_] "m" (i121(3))
|
||||
: ""
|
||||
);
|
||||
asm volatile (""
|
||||
:
|
||||
: [_] "m" (f32(3.17))
|
||||
: ""
|
||||
);
|
||||
asm volatile (""
|
||||
:
|
||||
: [_] "m" (f64(3.17))
|
||||
: ""
|
||||
);
|
||||
}
|
||||
|
||||
extern fn aoeu() i32;
|
||||
|
||||
export fn derp() i32 {
|
||||
return 1234;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const builtin = @import("builtin");
|
||||
const AtomicRmwOp = builtin.AtomicRmwOp;
|
||||
const AtomicOrder = builtin.AtomicOrder;
|
||||
@@ -7,18 +7,18 @@ const AtomicOrder = builtin.AtomicOrder;
|
||||
test "cmpxchg" {
|
||||
var x: i32 = 1234;
|
||||
if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
|
||||
assert(x1 == 1234);
|
||||
assertOrPanic(x1 == 1234);
|
||||
} else {
|
||||
@panic("cmpxchg should have failed");
|
||||
}
|
||||
|
||||
while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
|
||||
assert(x1 == 1234);
|
||||
assertOrPanic(x1 == 1234);
|
||||
}
|
||||
assert(x == 5678);
|
||||
assertOrPanic(x == 5678);
|
||||
|
||||
assert(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
|
||||
assert(x == 42);
|
||||
assertOrPanic(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
|
||||
assertOrPanic(x == 42);
|
||||
}
|
||||
|
||||
test "fence" {
|
||||
@@ -30,24 +30,24 @@ test "fence" {
|
||||
test "atomicrmw and atomicload" {
|
||||
var data: u8 = 200;
|
||||
testAtomicRmw(&data);
|
||||
assert(data == 42);
|
||||
assertOrPanic(data == 42);
|
||||
testAtomicLoad(&data);
|
||||
}
|
||||
|
||||
fn testAtomicRmw(ptr: *u8) void {
|
||||
const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
|
||||
assert(prev_value == 200);
|
||||
assertOrPanic(prev_value == 200);
|
||||
comptime {
|
||||
var x: i32 = 1234;
|
||||
const y: i32 = 12345;
|
||||
assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
|
||||
assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
|
||||
assertOrPanic(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
|
||||
assertOrPanic(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
|
||||
}
|
||||
}
|
||||
|
||||
fn testAtomicLoad(ptr: *u8) void {
|
||||
const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
|
||||
assert(x == 42);
|
||||
assertOrPanic(x == 42);
|
||||
}
|
||||
|
||||
test "cmpxchg with ptr" {
|
||||
@@ -56,16 +56,16 @@ test "cmpxchg with ptr" {
|
||||
var data3: i32 = 9101;
|
||||
var x: *i32 = &data1;
|
||||
if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
|
||||
assert(x1 == &data1);
|
||||
assertOrPanic(x1 == &data1);
|
||||
} else {
|
||||
@panic("cmpxchg should have failed");
|
||||
}
|
||||
|
||||
while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
|
||||
assert(x1 == &data1);
|
||||
assertOrPanic(x1 == &data1);
|
||||
}
|
||||
assert(x == &data3);
|
||||
assertOrPanic(x == &data3);
|
||||
|
||||
assert(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
|
||||
assert(x == &data2);
|
||||
assertOrPanic(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
|
||||
assertOrPanic(x == &data2);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
|
||||
assert(Key == @IntType(false, Key.bit_count));
|
||||
assert(Key.bit_count >= mask_bit_count);
|
||||
assertOrPanic(Key == @IntType(false, Key.bit_count));
|
||||
assertOrPanic(Key.bit_count >= mask_bit_count);
|
||||
const ShardKey = @IntType(false, mask_bit_count);
|
||||
const shift_amount = Key.bit_count - ShardKey.bit_count;
|
||||
return struct {
|
||||
@@ -77,12 +77,12 @@ fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, c
|
||||
var node_buffer: [node_count]Table.Node = undefined;
|
||||
for (node_buffer) |*node, i| {
|
||||
const key = @intCast(Key, i);
|
||||
assert(table.get(key) == null);
|
||||
assertOrPanic(table.get(key) == null);
|
||||
node.init(key, {});
|
||||
table.put(node);
|
||||
}
|
||||
|
||||
for (node_buffer) |*node, i| {
|
||||
assert(table.get(@intCast(Key, i)) == node);
|
||||
assertOrPanic(table.get(@intCast(Key, i)) == node);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const maxInt = std.math.maxInt;
|
||||
|
||||
test "@bitCast i32 -> u32" {
|
||||
@@ -8,8 +8,8 @@ test "@bitCast i32 -> u32" {
|
||||
}
|
||||
|
||||
fn testBitCast_i32_u32() void {
|
||||
assert(conv(-1) == maxInt(u32));
|
||||
assert(conv2(maxInt(u32)) == -1);
|
||||
assertOrPanic(conv(-1) == maxInt(u32));
|
||||
assertOrPanic(conv2(maxInt(u32)) == -1);
|
||||
}
|
||||
|
||||
fn conv(x: i32) u32 {
|
||||
@@ -27,11 +27,10 @@ test "@bitCast extern enum to its integer type" {
|
||||
fn testBitCastExternEnum() void {
|
||||
var SOCK_DGRAM = @This().B;
|
||||
var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
|
||||
assert(sock_dgram == 1);
|
||||
assertOrPanic(sock_dgram == 1);
|
||||
}
|
||||
};
|
||||
|
||||
SOCK.testBitCastExternEnum();
|
||||
comptime SOCK.testBitCastExternEnum();
|
||||
}
|
||||
|
||||
81
test/stage1/behavior/bitreverse.zig
Normal file
81
test/stage1/behavior/bitreverse.zig
Normal file
@@ -0,0 +1,81 @@
|
||||
const std = @import("std");
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const minInt = std.math.minInt;
|
||||
|
||||
test "@bitreverse" {
|
||||
comptime testBitReverse();
|
||||
testBitReverse();
|
||||
}
|
||||
|
||||
fn testBitReverse() void {
|
||||
// using comptime_ints, unsigned
|
||||
assertOrPanic(@bitreverse(u0, 0) == 0);
|
||||
assertOrPanic(@bitreverse(u5, 0x12) == 0x9);
|
||||
assertOrPanic(@bitreverse(u8, 0x12) == 0x48);
|
||||
assertOrPanic(@bitreverse(u16, 0x1234) == 0x2c48);
|
||||
assertOrPanic(@bitreverse(u24, 0x123456) == 0x6a2c48);
|
||||
assertOrPanic(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
|
||||
assertOrPanic(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
|
||||
assertOrPanic(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
|
||||
assertOrPanic(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
|
||||
assertOrPanic(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
|
||||
assertOrPanic(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
|
||||
|
||||
// using runtime uints, unsigned
|
||||
var num0: u0 = 0;
|
||||
assertOrPanic(@bitreverse(u0, num0) == 0);
|
||||
var num5: u5 = 0x12;
|
||||
assertOrPanic(@bitreverse(u5, num5) == 0x9);
|
||||
var num8: u8 = 0x12;
|
||||
assertOrPanic(@bitreverse(u8, num8) == 0x48);
|
||||
var num16: u16 = 0x1234;
|
||||
assertOrPanic(@bitreverse(u16, num16) == 0x2c48);
|
||||
var num24: u24 = 0x123456;
|
||||
assertOrPanic(@bitreverse(u24, num24) == 0x6a2c48);
|
||||
var num32: u32 = 0x12345678;
|
||||
assertOrPanic(@bitreverse(u32, num32) == 0x1e6a2c48);
|
||||
var num40: u40 = 0x123456789a;
|
||||
assertOrPanic(@bitreverse(u40, num40) == 0x591e6a2c48);
|
||||
var num48: u48 = 0x123456789abc;
|
||||
assertOrPanic(@bitreverse(u48, num48) == 0x3d591e6a2c48);
|
||||
var num56: u56 = 0x123456789abcde;
|
||||
assertOrPanic(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
|
||||
var num64: u64 = 0x123456789abcdef1;
|
||||
assertOrPanic(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
|
||||
var num128: u128 = 0x123456789abcdef11121314151617181;
|
||||
assertOrPanic(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
|
||||
|
||||
// using comptime_ints, signed, positive
|
||||
assertOrPanic(@bitreverse(i0, 0) == 0);
|
||||
assertOrPanic(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49)));
|
||||
assertOrPanic(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48)));
|
||||
assertOrPanic(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48)));
|
||||
assertOrPanic(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48)));
|
||||
assertOrPanic(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48)));
|
||||
assertOrPanic(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48)));
|
||||
assertOrPanic(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48)));
|
||||
assertOrPanic(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48)));
|
||||
assertOrPanic(@bitreverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48)));
|
||||
|
||||
// using comptime_ints, signed, negative. Compare to runtime ints returned from llvm.
|
||||
var neg5: i5 = minInt(i5) + 1;
|
||||
assertOrPanic(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
|
||||
var neg8: i8 = -18;
|
||||
assertOrPanic(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
|
||||
var neg16: i16 = -32694;
|
||||
assertOrPanic(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
|
||||
var neg24: i24 = -6773785;
|
||||
assertOrPanic(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
|
||||
var neg32: i32 = -16773785;
|
||||
assertOrPanic(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
|
||||
var neg40: i40 = minInt(i40) + 12345;
|
||||
assertOrPanic(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
|
||||
var neg48: i48 = minInt(i48) + 12345;
|
||||
assertOrPanic(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
|
||||
var neg56: i56 = minInt(i56) + 12345;
|
||||
assertOrPanic(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
|
||||
var neg64: i64 = minInt(i64) + 12345;
|
||||
assertOrPanic(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
|
||||
var neg128: i128 = minInt(i128) + 12345;
|
||||
assertOrPanic(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
|
||||
}
|
||||
@@ -1,25 +1,25 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "bool literals" {
|
||||
assert(true);
|
||||
assert(!false);
|
||||
assertOrPanic(true);
|
||||
assertOrPanic(!false);
|
||||
}
|
||||
|
||||
test "cast bool to int" {
|
||||
const t = true;
|
||||
const f = false;
|
||||
assert(@boolToInt(t) == u32(1));
|
||||
assert(@boolToInt(f) == u32(0));
|
||||
assertOrPanic(@boolToInt(t) == u32(1));
|
||||
assertOrPanic(@boolToInt(f) == u32(0));
|
||||
nonConstCastBoolToInt(t, f);
|
||||
}
|
||||
|
||||
fn nonConstCastBoolToInt(t: bool, f: bool) void {
|
||||
assert(@boolToInt(t) == u32(1));
|
||||
assert(@boolToInt(f) == u32(0));
|
||||
assertOrPanic(@boolToInt(t) == u32(1));
|
||||
assertOrPanic(@boolToInt(f) == u32(0));
|
||||
}
|
||||
|
||||
test "bool cmp" {
|
||||
assert(testBoolCmp(true, false) == false);
|
||||
assertOrPanic(testBoolCmp(true, false) == false);
|
||||
}
|
||||
fn testBoolCmp(a: bool, b: bool) bool {
|
||||
return a == b;
|
||||
@@ -30,6 +30,6 @@ const global_t = true;
|
||||
const not_global_f = !global_f;
|
||||
const not_global_t = !global_t;
|
||||
test "compile time bool not" {
|
||||
assert(not_global_f);
|
||||
assert(!not_global_t);
|
||||
assertOrPanic(not_global_f);
|
||||
assertOrPanic(!not_global_t);
|
||||
}
|
||||
32
test/stage1/behavior/bswap.zig
Normal file
32
test/stage1/behavior/bswap.zig
Normal file
@@ -0,0 +1,32 @@
|
||||
const std = @import("std");
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
test "@bswap" {
|
||||
comptime testByteSwap();
|
||||
testByteSwap();
|
||||
}
|
||||
|
||||
fn testByteSwap() void {
|
||||
assertOrPanic(@bswap(u0, 0) == 0);
|
||||
assertOrPanic(@bswap(u8, 0x12) == 0x12);
|
||||
assertOrPanic(@bswap(u16, 0x1234) == 0x3412);
|
||||
assertOrPanic(@bswap(u24, 0x123456) == 0x563412);
|
||||
assertOrPanic(@bswap(u32, 0x12345678) == 0x78563412);
|
||||
assertOrPanic(@bswap(u40, 0x123456789a) == 0x9a78563412);
|
||||
assertOrPanic(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
|
||||
assertOrPanic(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
|
||||
assertOrPanic(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
|
||||
assertOrPanic(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
|
||||
|
||||
assertOrPanic(@bswap(i0, 0) == 0);
|
||||
assertOrPanic(@bswap(i8, -50) == -50);
|
||||
assertOrPanic(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
|
||||
assertOrPanic(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
|
||||
assertOrPanic(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
|
||||
assertOrPanic(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
|
||||
assertOrPanic(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
|
||||
assertOrPanic(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
|
||||
assertOrPanic(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
|
||||
assertOrPanic(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
|
||||
@bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
test "comptime code should not modify constant data" {
|
||||
testCastPtrOfArrayToSliceAndPtr();
|
||||
@@ -11,6 +11,6 @@ fn testCastPtrOfArrayToSliceAndPtr() void {
|
||||
var array = "aoeu";
|
||||
const x: [*]u8 = &array;
|
||||
x[0] += 1;
|
||||
assert(mem.eql(u8, array[0..], "boeu"));
|
||||
assertOrPanic(mem.eql(u8, array[0..], "boeu"));
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const C = struct {};
|
||||
|
||||
test "tagged union with all void fields but a meaningful tag" {
|
||||
var a: A = A{ .b = B{ .c = C{} } };
|
||||
std.debug.assert(@TagType(B)(a.b) == @TagType(B).c);
|
||||
std.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).c);
|
||||
a = A{ .b = B.None };
|
||||
std.debug.assert(@TagType(B)(a.b) == @TagType(B).None);
|
||||
std.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).None);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
const S = struct {
|
||||
fn method() builtin.TypeInfo {
|
||||
@@ -10,5 +10,5 @@ const S = struct {
|
||||
|
||||
test "functions with return type required to be comptime are generic" {
|
||||
const ti = S.method();
|
||||
assert(builtin.TypeId(ti) == builtin.TypeId.Struct);
|
||||
assertOrPanic(builtin.TypeId(ti) == builtin.TypeId.Struct);
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
const ptr = &global;
|
||||
var global: u64 = 123;
|
||||
|
||||
test "constant pointer to global variable causes runtime load" {
|
||||
global = 1234;
|
||||
assert(&global == ptr);
|
||||
assert(ptr.* == 1234);
|
||||
assertOrPanic(&global == ptr);
|
||||
assertOrPanic(ptr.* == 1234);
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ const S = struct {
|
||||
y: E,
|
||||
};
|
||||
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "bug 394 fixed" {
|
||||
const x = S{
|
||||
.x = 3,
|
||||
.y = E{ .B = 1 },
|
||||
};
|
||||
assert(x.x == 3);
|
||||
assertOrPanic(x.x == 3);
|
||||
}
|
||||
@@ -3,10 +3,10 @@ const other_file = @import("655_other_file.zig");
|
||||
|
||||
test "function with *const parameter with type dereferenced by namespace" {
|
||||
const x: other_file.Integer = 1234;
|
||||
comptime std.debug.assert(@typeOf(&x) == *const other_file.Integer);
|
||||
comptime std.debug.assertOrPanic(@typeOf(&x) == *const other_file.Integer);
|
||||
foo(&x);
|
||||
}
|
||||
|
||||
fn foo(x: *const other_file.Integer) void {
|
||||
std.debug.assert(x.* == 1234);
|
||||
std.debug.assertOrPanic(x.* == 1234);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
const PrefixOp = union(enum) {
|
||||
Return,
|
||||
@@ -22,7 +22,7 @@ fn foo(a: bool, b: bool) void {
|
||||
PrefixOp.AddrOf => |addr_of_info| {
|
||||
if (b) {}
|
||||
if (addr_of_info.align_expr) |align_expr| {
|
||||
assert(align_expr == 1234);
|
||||
assertOrPanic(align_expr == 1234);
|
||||
}
|
||||
},
|
||||
PrefixOp.Return => {},
|
||||
@@ -1,9 +1,9 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "@ptrCast from const to nullable" {
|
||||
const c: u8 = 4;
|
||||
var x: ?*const u8 = @ptrCast(?*const u8, &c);
|
||||
assert(x.?.* == 4);
|
||||
assertOrPanic(x.?.* == 4);
|
||||
}
|
||||
|
||||
test "@ptrCast from var in empty struct to nullable" {
|
||||
@@ -11,6 +11,6 @@ test "@ptrCast from var in empty struct to nullable" {
|
||||
var c: u8 = 4;
|
||||
};
|
||||
var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
|
||||
assert(x.?.* == 4);
|
||||
assertOrPanic(x.?.* == 4);
|
||||
}
|
||||
|
||||
@@ -60,6 +60,6 @@ test "bug 920 fixed" {
|
||||
};
|
||||
|
||||
for (NormalDist1.f) |_, i| {
|
||||
std.debug.assert(NormalDist1.f[i] == NormalDist.f[i]);
|
||||
std.debug.assertOrPanic(NormalDist1.f[i] == NormalDist.f[i]);
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@ const std = @import("std");
|
||||
|
||||
var result: []const u8 = "wrong";
|
||||
|
||||
test "aoeu" {
|
||||
test "pass string literal byvalue to a generic var param" {
|
||||
start();
|
||||
blowUpStack(10);
|
||||
|
||||
std.debug.assert(std.mem.eql(u8, result, "string literal"));
|
||||
std.debug.assertOrPanic(std.mem.eql(u8, result, "string literal"));
|
||||
}
|
||||
|
||||
fn start() void {
|
||||
@@ -10,9 +10,9 @@ test "cancel forwards" {
|
||||
|
||||
const p = async<&da.allocator> f1() catch unreachable;
|
||||
cancel p;
|
||||
std.debug.assert(defer_f1);
|
||||
std.debug.assert(defer_f2);
|
||||
std.debug.assert(defer_f3);
|
||||
std.debug.assertOrPanic(defer_f1);
|
||||
std.debug.assertOrPanic(defer_f2);
|
||||
std.debug.assertOrPanic(defer_f3);
|
||||
}
|
||||
|
||||
async fn f1() void {
|
||||
@@ -47,10 +47,10 @@ test "cancel backwards" {
|
||||
|
||||
const p = async<&da.allocator> b1() catch unreachable;
|
||||
cancel p;
|
||||
std.debug.assert(defer_b1);
|
||||
std.debug.assert(defer_b2);
|
||||
std.debug.assert(defer_b3);
|
||||
std.debug.assert(defer_b4);
|
||||
std.debug.assertOrPanic(defer_b1);
|
||||
std.debug.assertOrPanic(defer_b2);
|
||||
std.debug.assertOrPanic(defer_b3);
|
||||
std.debug.assertOrPanic(defer_b4);
|
||||
}
|
||||
|
||||
async fn b1() void {
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const mem = std.mem;
|
||||
const maxInt = std.math.maxInt;
|
||||
|
||||
@@ -7,12 +7,12 @@ test "int to ptr cast" {
|
||||
const x = usize(13);
|
||||
const y = @intToPtr(*u8, x);
|
||||
const z = @ptrToInt(y);
|
||||
assert(z == 13);
|
||||
assertOrPanic(z == 13);
|
||||
}
|
||||
|
||||
test "integer literal to pointer cast" {
|
||||
const vga_mem = @intToPtr(*u16, 0xB8000);
|
||||
assert(@ptrToInt(vga_mem) == 0xB8000);
|
||||
assertOrPanic(@ptrToInt(vga_mem) == 0xB8000);
|
||||
}
|
||||
|
||||
test "pointer reinterpret const float to int" {
|
||||
@@ -20,7 +20,7 @@ test "pointer reinterpret const float to int" {
|
||||
const float_ptr = &float;
|
||||
const int_ptr = @ptrCast(*const i32, float_ptr);
|
||||
const int_val = int_ptr.*;
|
||||
assert(int_val == 858993411);
|
||||
assertOrPanic(int_val == 858993411);
|
||||
}
|
||||
|
||||
test "implicitly cast indirect pointer to maybe-indirect pointer" {
|
||||
@@ -44,10 +44,10 @@ test "implicitly cast indirect pointer to maybe-indirect pointer" {
|
||||
const p = &s;
|
||||
const q = &p;
|
||||
const r = &q;
|
||||
assert(42 == S.constConst(q));
|
||||
assert(42 == S.maybeConstConst(q));
|
||||
assert(42 == S.constConstConst(r));
|
||||
assert(42 == S.maybeConstConstConst(r));
|
||||
assertOrPanic(42 == S.constConst(q));
|
||||
assertOrPanic(42 == S.maybeConstConst(q));
|
||||
assertOrPanic(42 == S.constConstConst(r));
|
||||
assertOrPanic(42 == S.maybeConstConstConst(r));
|
||||
}
|
||||
|
||||
test "explicit cast from integer to error type" {
|
||||
@@ -57,14 +57,14 @@ test "explicit cast from integer to error type" {
|
||||
fn testCastIntToErr(err: anyerror) void {
|
||||
const x = @errorToInt(err);
|
||||
const y = @intToError(x);
|
||||
assert(error.ItBroke == y);
|
||||
assertOrPanic(error.ItBroke == y);
|
||||
}
|
||||
|
||||
test "peer resolve arrays of different size to const slice" {
|
||||
assert(mem.eql(u8, boolToStr(true), "true"));
|
||||
assert(mem.eql(u8, boolToStr(false), "false"));
|
||||
comptime assert(mem.eql(u8, boolToStr(true), "true"));
|
||||
comptime assert(mem.eql(u8, boolToStr(false), "false"));
|
||||
assertOrPanic(mem.eql(u8, boolToStr(true), "true"));
|
||||
assertOrPanic(mem.eql(u8, boolToStr(false), "false"));
|
||||
comptime assertOrPanic(mem.eql(u8, boolToStr(true), "true"));
|
||||
comptime assertOrPanic(mem.eql(u8, boolToStr(false), "false"));
|
||||
}
|
||||
fn boolToStr(b: bool) []const u8 {
|
||||
return if (b) "true" else "false";
|
||||
@@ -77,28 +77,29 @@ test "peer resolve array and const slice" {
|
||||
fn testPeerResolveArrayConstSlice(b: bool) void {
|
||||
const value1 = if (b) "aoeu" else ([]const u8)("zz");
|
||||
const value2 = if (b) ([]const u8)("zz") else "aoeu";
|
||||
assert(mem.eql(u8, value1, "aoeu"));
|
||||
assert(mem.eql(u8, value2, "zz"));
|
||||
assertOrPanic(mem.eql(u8, value1, "aoeu"));
|
||||
assertOrPanic(mem.eql(u8, value2, "zz"));
|
||||
}
|
||||
|
||||
test "implicitly cast from T to anyerror!?T" {
|
||||
castToOptionalTypeError(1);
|
||||
comptime castToOptionalTypeError(1);
|
||||
}
|
||||
|
||||
const A = struct {
|
||||
a: i32,
|
||||
};
|
||||
fn castToOptionalTypeError(z: i32) void {
|
||||
const x = i32(1);
|
||||
const y: anyerror!?i32 = x;
|
||||
assert((try y).? == 1);
|
||||
assertOrPanic((try y).? == 1);
|
||||
|
||||
const f = z;
|
||||
const g: anyerror!?i32 = f;
|
||||
|
||||
const a = A{ .a = z };
|
||||
const b: anyerror!?A = a;
|
||||
assert((b catch unreachable).?.a == 1);
|
||||
assertOrPanic((b catch unreachable).?.a == 1);
|
||||
}
|
||||
|
||||
test "implicitly cast from int to anyerror!?T" {
|
||||
@@ -113,7 +114,7 @@ fn implicitIntLitToOptional() void {
|
||||
test "return null from fn() anyerror!?&T" {
|
||||
const a = returnNullFromOptionalTypeErrorRef();
|
||||
const b = returnNullLitFromOptionalTypeErrorRef();
|
||||
assert((try a) == null and (try b) == null);
|
||||
assertOrPanic((try a) == null and (try b) == null);
|
||||
}
|
||||
fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
|
||||
const a: ?*A = null;
|
||||
@@ -124,11 +125,11 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
|
||||
}
|
||||
|
||||
test "peer type resolution: ?T and T" {
|
||||
assert(peerTypeTAndOptionalT(true, false).? == 0);
|
||||
assert(peerTypeTAndOptionalT(false, false).? == 3);
|
||||
assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0);
|
||||
assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3);
|
||||
comptime {
|
||||
assert(peerTypeTAndOptionalT(true, false).? == 0);
|
||||
assert(peerTypeTAndOptionalT(false, false).? == 3);
|
||||
assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0);
|
||||
assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3);
|
||||
}
|
||||
}
|
||||
fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
|
||||
@@ -140,11 +141,11 @@ fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
|
||||
}
|
||||
|
||||
test "peer type resolution: [0]u8 and []const u8" {
|
||||
assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
|
||||
assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
|
||||
assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
|
||||
assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
|
||||
comptime {
|
||||
assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
|
||||
assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
|
||||
assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
|
||||
assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
|
||||
}
|
||||
}
|
||||
fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
|
||||
@@ -156,8 +157,8 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
|
||||
}
|
||||
|
||||
test "implicitly cast from [N]T to ?[]const T" {
|
||||
assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
||||
comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
||||
assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
||||
comptime assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi"));
|
||||
}
|
||||
|
||||
fn castToOptionalSlice() ?[]const u8 {
|
||||
@@ -170,7 +171,7 @@ test "implicitly cast from [0]T to anyerror![]T" {
|
||||
}
|
||||
|
||||
fn testCastZeroArrayToErrSliceMut() void {
|
||||
assert((gimmeErrOrSlice() catch unreachable).len == 0);
|
||||
assertOrPanic((gimmeErrOrSlice() catch unreachable).len == 0);
|
||||
}
|
||||
|
||||
fn gimmeErrOrSlice() anyerror![]u8 {
|
||||
@@ -181,14 +182,14 @@ test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
|
||||
{
|
||||
var data = "hi";
|
||||
const slice = data[0..];
|
||||
assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
|
||||
assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
|
||||
assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
|
||||
assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
|
||||
}
|
||||
comptime {
|
||||
var data = "hi";
|
||||
const slice = data[0..];
|
||||
assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
|
||||
assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
|
||||
assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
|
||||
assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
|
||||
}
|
||||
}
|
||||
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
|
||||
@@ -206,7 +207,7 @@ test "resolve undefined with integer" {
|
||||
fn testResolveUndefWithInt(b: bool, x: i32) void {
|
||||
const value = if (b) x else undefined;
|
||||
if (b) {
|
||||
assert(value == x);
|
||||
assertOrPanic(value == x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,17 +219,17 @@ test "implicit cast from &const [N]T to []const T" {
|
||||
fn testCastConstArrayRefToConstSlice() void {
|
||||
const blah = "aoeu";
|
||||
const const_array_ref = &blah;
|
||||
assert(@typeOf(const_array_ref) == *const [4]u8);
|
||||
assertOrPanic(@typeOf(const_array_ref) == *const [4]u8);
|
||||
const slice: []const u8 = const_array_ref;
|
||||
assert(mem.eql(u8, slice, "aoeu"));
|
||||
assertOrPanic(mem.eql(u8, slice, "aoeu"));
|
||||
}
|
||||
|
||||
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"));
|
||||
//comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
|
||||
assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
|
||||
comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
|
||||
//assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
|
||||
//comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
|
||||
assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
|
||||
comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
|
||||
}
|
||||
|
||||
//fn testPeerErrorAndArray(x: u8) error![]const u8 {
|
||||
@@ -252,9 +253,9 @@ test "@floatToInt" {
|
||||
|
||||
fn testFloatToInts() void {
|
||||
const x = i32(1e4);
|
||||
assert(x == 10000);
|
||||
assertOrPanic(x == 10000);
|
||||
const y = @floatToInt(i32, f32(1e4));
|
||||
assert(y == 10000);
|
||||
assertOrPanic(y == 10000);
|
||||
expectFloatToInt(f16, 255.1, u8, 255);
|
||||
expectFloatToInt(f16, 127.2, i8, 127);
|
||||
expectFloatToInt(f16, -128.2, i8, -128);
|
||||
@@ -265,7 +266,7 @@ fn testFloatToInts() void {
|
||||
}
|
||||
|
||||
fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void {
|
||||
assert(@floatToInt(I, f) == i);
|
||||
assertOrPanic(@floatToInt(I, f) == i);
|
||||
}
|
||||
|
||||
test "cast u128 to f128 and back" {
|
||||
@@ -274,7 +275,7 @@ test "cast u128 to f128 and back" {
|
||||
}
|
||||
|
||||
fn testCast128() void {
|
||||
assert(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
|
||||
assertOrPanic(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
|
||||
}
|
||||
|
||||
fn cast128Int(x: f128) u128 {
|
||||
@@ -294,9 +295,9 @@ test "const slice widen cast" {
|
||||
};
|
||||
|
||||
const u32_value = @bytesToSlice(u32, bytes[0..])[0];
|
||||
assert(u32_value == 0x12121212);
|
||||
assertOrPanic(u32_value == 0x12121212);
|
||||
|
||||
assert(@bitCast(u32, bytes) == 0x12121212);
|
||||
assertOrPanic(@bitCast(u32, bytes) == 0x12121212);
|
||||
}
|
||||
|
||||
test "single-item pointer of array to slice and to unknown length pointer" {
|
||||
@@ -308,76 +309,76 @@ fn testCastPtrOfArrayToSliceAndPtr() void {
|
||||
var array = "aoeu";
|
||||
const x: [*]u8 = &array;
|
||||
x[0] += 1;
|
||||
assert(mem.eql(u8, array[0..], "boeu"));
|
||||
assertOrPanic(mem.eql(u8, array[0..], "boeu"));
|
||||
const y: []u8 = &array;
|
||||
y[0] += 1;
|
||||
assert(mem.eql(u8, array[0..], "coeu"));
|
||||
assertOrPanic(mem.eql(u8, array[0..], "coeu"));
|
||||
}
|
||||
|
||||
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
|
||||
const window_name = [1][*]const u8{c"window name"};
|
||||
const x: [*]const ?[*]const u8 = &window_name;
|
||||
assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
|
||||
assertOrPanic(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
|
||||
}
|
||||
|
||||
test "@intCast comptime_int" {
|
||||
const result = @intCast(i32, 1234);
|
||||
assert(@typeOf(result) == i32);
|
||||
assert(result == 1234);
|
||||
assertOrPanic(@typeOf(result) == i32);
|
||||
assertOrPanic(result == 1234);
|
||||
}
|
||||
|
||||
test "@floatCast comptime_int and comptime_float" {
|
||||
{
|
||||
const result = @floatCast(f16, 1234);
|
||||
assert(@typeOf(result) == f16);
|
||||
assert(result == 1234.0);
|
||||
assertOrPanic(@typeOf(result) == f16);
|
||||
assertOrPanic(result == 1234.0);
|
||||
}
|
||||
{
|
||||
const result = @floatCast(f16, 1234.0);
|
||||
assert(@typeOf(result) == f16);
|
||||
assert(result == 1234.0);
|
||||
assertOrPanic(@typeOf(result) == f16);
|
||||
assertOrPanic(result == 1234.0);
|
||||
}
|
||||
{
|
||||
const result = @floatCast(f32, 1234);
|
||||
assert(@typeOf(result) == f32);
|
||||
assert(result == 1234.0);
|
||||
assertOrPanic(@typeOf(result) == f32);
|
||||
assertOrPanic(result == 1234.0);
|
||||
}
|
||||
{
|
||||
const result = @floatCast(f32, 1234.0);
|
||||
assert(@typeOf(result) == f32);
|
||||
assert(result == 1234.0);
|
||||
assertOrPanic(@typeOf(result) == f32);
|
||||
assertOrPanic(result == 1234.0);
|
||||
}
|
||||
}
|
||||
|
||||
test "comptime_int @intToFloat" {
|
||||
{
|
||||
const result = @intToFloat(f16, 1234);
|
||||
assert(@typeOf(result) == f16);
|
||||
assert(result == 1234.0);
|
||||
assertOrPanic(@typeOf(result) == f16);
|
||||
assertOrPanic(result == 1234.0);
|
||||
}
|
||||
{
|
||||
const result = @intToFloat(f32, 1234);
|
||||
assert(@typeOf(result) == f32);
|
||||
assert(result == 1234.0);
|
||||
assertOrPanic(@typeOf(result) == f32);
|
||||
assertOrPanic(result == 1234.0);
|
||||
}
|
||||
}
|
||||
|
||||
test "@bytesToSlice keeps pointer alignment" {
|
||||
var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 };
|
||||
const numbers = @bytesToSlice(u32, bytes[0..]);
|
||||
comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
|
||||
comptime assertOrPanic(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
|
||||
}
|
||||
|
||||
test "@intCast i32 to u7" {
|
||||
var x: u128 = maxInt(u128);
|
||||
var y: i32 = 120;
|
||||
var z = x >> @intCast(u7, y);
|
||||
assert(z == 0xff);
|
||||
assertOrPanic(z == 0xff);
|
||||
}
|
||||
|
||||
test "implicit cast undefined to optional" {
|
||||
assert(MakeType(void).getNull() == null);
|
||||
assert(MakeType(void).getNonNull() != null);
|
||||
assertOrPanic(MakeType(void).getNull() == null);
|
||||
assertOrPanic(MakeType(void).getNonNull() != null);
|
||||
}
|
||||
|
||||
fn MakeType(comptime T: type) type {
|
||||
@@ -397,16 +398,16 @@ test "implicit cast from *[N]T to ?[*]T" {
|
||||
var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
|
||||
|
||||
x = &y;
|
||||
assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
|
||||
assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4]));
|
||||
x.?[0] = 8;
|
||||
y[3] = 6;
|
||||
assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
|
||||
assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4]));
|
||||
}
|
||||
|
||||
test "implicit cast from *T to ?*c_void" {
|
||||
var a: u8 = 1;
|
||||
incrementVoidPtrValue(&a);
|
||||
std.debug.assert(a == 2);
|
||||
std.debug.assertOrPanic(a == 2);
|
||||
}
|
||||
|
||||
fn incrementVoidPtrValue(value: ?*c_void) void {
|
||||
@@ -416,7 +417,7 @@ fn incrementVoidPtrValue(value: ?*c_void) void {
|
||||
test "implicit cast from [*]T to ?*c_void" {
|
||||
var a = []u8{ 3, 2, 1 };
|
||||
incrementVoidPtrArray(a[0..].ptr, 3);
|
||||
assert(std.mem.eql(u8, a, []u8{ 4, 3, 2 }));
|
||||
assertOrPanic(std.mem.eql(u8, a, []u8{ 4, 3, 2 }));
|
||||
}
|
||||
|
||||
fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
|
||||
@@ -440,27 +441,27 @@ pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
|
||||
pub const PFN_void = extern fn (*c_void) void;
|
||||
|
||||
fn foobar(func: PFN_void) void {
|
||||
std.debug.assert(@ptrToInt(func) == maxInt(usize));
|
||||
std.debug.assertOrPanic(@ptrToInt(func) == maxInt(usize));
|
||||
}
|
||||
|
||||
test "implicit ptr to *c_void" {
|
||||
var a: u32 = 1;
|
||||
var ptr: *c_void = &a;
|
||||
var b: *u32 = @ptrCast(*u32, ptr);
|
||||
assert(b.* == 1);
|
||||
assertOrPanic(b.* == 1);
|
||||
var ptr2: ?*c_void = &a;
|
||||
var c: *u32 = @ptrCast(*u32, ptr2.?);
|
||||
assert(c.* == 1);
|
||||
assertOrPanic(c.* == 1);
|
||||
}
|
||||
|
||||
test "@intCast to comptime_int" {
|
||||
assert(@intCast(comptime_int, 0) == 0);
|
||||
assertOrPanic(@intCast(comptime_int, 0) == 0);
|
||||
}
|
||||
|
||||
test "implicit cast comptime numbers to any type when the value fits" {
|
||||
const a: u64 = 255;
|
||||
var b: u8 = a;
|
||||
assert(b == 255);
|
||||
assertOrPanic(b == 255);
|
||||
}
|
||||
|
||||
test "@intToEnum passed a comptime_int to an enum with one item" {
|
||||
@@ -468,5 +469,5 @@ test "@intToEnum passed a comptime_int to an enum with one item" {
|
||||
A,
|
||||
};
|
||||
const x = @intToEnum(E, 0);
|
||||
assert(x == E.A);
|
||||
assertOrPanic(x == E.A);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
const debug = @import("std").debug;
|
||||
const assert = debug.assert;
|
||||
const assertOrPanic = debug.assertOrPanic;
|
||||
|
||||
var argv: [*]const [*]const u8 = undefined;
|
||||
|
||||
@@ -15,10 +15,10 @@ test "const slice child" {
|
||||
}
|
||||
|
||||
fn foo(args: [][]const u8) void {
|
||||
assert(args.len == 3);
|
||||
assert(streql(args[0], "one"));
|
||||
assert(streql(args[1], "two"));
|
||||
assert(streql(args[2], "three"));
|
||||
assertOrPanic(args.len == 3);
|
||||
assertOrPanic(streql(args[0], "one"));
|
||||
assertOrPanic(streql(args[1], "two"));
|
||||
assertOrPanic(streql(args[2], "three"));
|
||||
}
|
||||
|
||||
fn bar(argc: usize) void {
|
||||
@@ -1,6 +1,6 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
const Foo = struct {
|
||||
x: i32,
|
||||
@@ -18,8 +18,8 @@ test "coroutine await struct" {
|
||||
await_seq('f');
|
||||
resume await_a_promise;
|
||||
await_seq('i');
|
||||
assert(await_final_result.x == 1234);
|
||||
assert(std.mem.eql(u8, await_points, "abcdefghi"));
|
||||
assertOrPanic(await_final_result.x == 1234);
|
||||
assertOrPanic(std.mem.eql(u8, await_points, "abcdefghi"));
|
||||
}
|
||||
async fn await_amain() void {
|
||||
await_seq('b');
|
||||
@@ -1,6 +1,6 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
var x: i32 = 1;
|
||||
|
||||
@@ -9,9 +9,9 @@ test "create a coroutine and cancel it" {
|
||||
defer da.deinit();
|
||||
|
||||
const p = try async<&da.allocator> simpleAsyncFn();
|
||||
comptime assert(@typeOf(p) == promise->void);
|
||||
comptime assertOrPanic(@typeOf(p) == promise->void);
|
||||
cancel p;
|
||||
assert(x == 2);
|
||||
assertOrPanic(x == 2);
|
||||
}
|
||||
async fn simpleAsyncFn() void {
|
||||
x += 1;
|
||||
@@ -31,7 +31,7 @@ test "coroutine suspend, resume, cancel" {
|
||||
cancel p;
|
||||
seq('g');
|
||||
|
||||
assert(std.mem.eql(u8, points, "abcdefg"));
|
||||
assertOrPanic(std.mem.eql(u8, points, "abcdefg"));
|
||||
}
|
||||
async fn testAsyncSeq() void {
|
||||
defer seq('e');
|
||||
@@ -53,9 +53,9 @@ test "coroutine suspend with block" {
|
||||
defer da.deinit();
|
||||
|
||||
const p = try async<&da.allocator> testSuspendBlock();
|
||||
std.debug.assert(!result);
|
||||
std.debug.assertOrPanic(!result);
|
||||
resume a_promise;
|
||||
std.debug.assert(result);
|
||||
std.debug.assertOrPanic(result);
|
||||
cancel p;
|
||||
}
|
||||
|
||||
@@ -63,13 +63,13 @@ var a_promise: promise = undefined;
|
||||
var result = false;
|
||||
async fn testSuspendBlock() void {
|
||||
suspend {
|
||||
comptime assert(@typeOf(@handle()) == promise->void);
|
||||
comptime assertOrPanic(@typeOf(@handle()) == promise->void);
|
||||
a_promise = @handle();
|
||||
}
|
||||
|
||||
//Test to make sure that @handle() works as advertised (issue #1296)
|
||||
//var our_handle: promise = @handle();
|
||||
assert( a_promise == @handle() );
|
||||
assertOrPanic(a_promise == @handle());
|
||||
|
||||
result = true;
|
||||
}
|
||||
@@ -86,8 +86,8 @@ test "coroutine await" {
|
||||
await_seq('f');
|
||||
resume await_a_promise;
|
||||
await_seq('i');
|
||||
assert(await_final_result == 1234);
|
||||
assert(std.mem.eql(u8, await_points, "abcdefghi"));
|
||||
assertOrPanic(await_final_result == 1234);
|
||||
assertOrPanic(std.mem.eql(u8, await_points, "abcdefghi"));
|
||||
}
|
||||
async fn await_amain() void {
|
||||
await_seq('b');
|
||||
@@ -123,8 +123,8 @@ test "coroutine await early return" {
|
||||
early_seq('a');
|
||||
const p = async<&da.allocator> early_amain() catch @panic("out of memory");
|
||||
early_seq('f');
|
||||
assert(early_final_result == 1234);
|
||||
assert(std.mem.eql(u8, early_points, "abcdef"));
|
||||
assertOrPanic(early_final_result == 1234);
|
||||
assertOrPanic(std.mem.eql(u8, early_points, "abcdef"));
|
||||
}
|
||||
async fn early_amain() void {
|
||||
early_seq('b');
|
||||
@@ -170,7 +170,7 @@ test "async function with dot syntax" {
|
||||
defer da.deinit();
|
||||
const p = try async<&da.allocator> S.foo();
|
||||
cancel p;
|
||||
assert(S.y == 2);
|
||||
assertOrPanic(S.y == 2);
|
||||
}
|
||||
|
||||
test "async fn pointer in a struct field" {
|
||||
@@ -182,9 +182,9 @@ test "async fn pointer in a struct field" {
|
||||
var da = std.heap.DirectAllocator.init();
|
||||
defer da.deinit();
|
||||
const p = (async<&da.allocator> foo.bar(&data)) catch unreachable;
|
||||
assert(data == 2);
|
||||
assertOrPanic(data == 2);
|
||||
cancel p;
|
||||
assert(data == 4);
|
||||
assertOrPanic(data == 4);
|
||||
}
|
||||
async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {
|
||||
defer y.* += 2;
|
||||
@@ -199,6 +199,7 @@ test "async fn with inferred error set" {
|
||||
resume p;
|
||||
cancel p;
|
||||
}
|
||||
|
||||
async fn failing() !void {
|
||||
suspend;
|
||||
return error.Fail;
|
||||
@@ -220,8 +221,7 @@ test "error return trace across suspend points - async return" {
|
||||
cancel p2;
|
||||
}
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/760
|
||||
fn nonFailing() promise->(anyerror!void) {
|
||||
fn nonFailing() (promise->anyerror!void) {
|
||||
return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
|
||||
}
|
||||
async fn suspendThenFail() anyerror!void {
|
||||
@@ -230,9 +230,9 @@ async fn suspendThenFail() anyerror!void {
|
||||
}
|
||||
async fn printTrace(p: promise->(anyerror!void)) void {
|
||||
(await p) catch |e| {
|
||||
std.debug.assert(e == error.Fail);
|
||||
std.debug.assertOrPanic(e == error.Fail);
|
||||
if (@errorReturnTrace()) |trace| {
|
||||
assert(trace.index == 1);
|
||||
assertOrPanic(trace.index == 1);
|
||||
} else switch (builtin.mode) {
|
||||
builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),
|
||||
builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},
|
||||
@@ -246,7 +246,7 @@ test "break from suspend" {
|
||||
var my_result: i32 = 1;
|
||||
const p = try async<a> testBreakFromSuspend(&my_result);
|
||||
cancel p;
|
||||
std.debug.assert(my_result == 2);
|
||||
std.debug.assertOrPanic(my_result == 2);
|
||||
}
|
||||
async fn testBreakFromSuspend(my_result: *i32) void {
|
||||
suspend {
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
var result: [3]u8 = undefined;
|
||||
var index: usize = undefined;
|
||||
@@ -21,18 +21,18 @@ fn runSomeErrorDefers(x: bool) !bool {
|
||||
}
|
||||
|
||||
test "mixing normal and error defers" {
|
||||
assert(runSomeErrorDefers(true) catch unreachable);
|
||||
assert(result[0] == 'c');
|
||||
assert(result[1] == 'a');
|
||||
assertOrPanic(runSomeErrorDefers(true) catch unreachable);
|
||||
assertOrPanic(result[0] == 'c');
|
||||
assertOrPanic(result[1] == 'a');
|
||||
|
||||
const ok = runSomeErrorDefers(false) catch |err| x: {
|
||||
assert(err == error.FalseNotAllowed);
|
||||
assertOrPanic(err == error.FalseNotAllowed);
|
||||
break :x true;
|
||||
};
|
||||
assert(ok);
|
||||
assert(result[0] == 'c');
|
||||
assert(result[1] == 'b');
|
||||
assert(result[2] == 'a');
|
||||
assertOrPanic(ok);
|
||||
assertOrPanic(result[0] == 'c');
|
||||
assertOrPanic(result[1] == 'b');
|
||||
assertOrPanic(result[2] == 'a');
|
||||
}
|
||||
|
||||
test "break and continue inside loop inside defer expression" {
|
||||
@@ -47,7 +47,7 @@ fn testBreakContInDefer(x: usize) void {
|
||||
if (i < 5) continue;
|
||||
if (i == 5) break;
|
||||
}
|
||||
assert(i == 5);
|
||||
assertOrPanic(i == 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,11 +59,11 @@ test "defer and labeled break" {
|
||||
break :blk;
|
||||
}
|
||||
|
||||
assert(i == 1);
|
||||
assertOrPanic(i == 1);
|
||||
}
|
||||
|
||||
test "errdefer does not apply to fn inside fn" {
|
||||
if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad);
|
||||
if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assertOrPanic(e == error.Bad);
|
||||
}
|
||||
|
||||
fn testNestedFnErrDefer() anyerror!void {
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
test "enum type" {
|
||||
@@ -11,16 +11,16 @@ test "enum type" {
|
||||
};
|
||||
const bar = Bar.B;
|
||||
|
||||
assert(bar == Bar.B);
|
||||
assert(@memberCount(Foo) == 3);
|
||||
assert(@memberCount(Bar) == 4);
|
||||
assert(@sizeOf(Foo) == @sizeOf(FooNoVoid));
|
||||
assert(@sizeOf(Bar) == 1);
|
||||
assertOrPanic(bar == Bar.B);
|
||||
assertOrPanic(@memberCount(Foo) == 3);
|
||||
assertOrPanic(@memberCount(Bar) == 4);
|
||||
assertOrPanic(@sizeOf(Foo) == @sizeOf(FooNoVoid));
|
||||
assertOrPanic(@sizeOf(Bar) == 1);
|
||||
}
|
||||
|
||||
test "enum as return value" {
|
||||
switch (returnAnInt(13)) {
|
||||
Foo.One => |value| assert(value == 13),
|
||||
Foo.One => |value| assertOrPanic(value == 13),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@@ -92,14 +92,14 @@ test "enum to int" {
|
||||
}
|
||||
|
||||
fn shouldEqual(n: Number, expected: u3) void {
|
||||
assert(@enumToInt(n) == expected);
|
||||
assertOrPanic(@enumToInt(n) == expected);
|
||||
}
|
||||
|
||||
test "int to enum" {
|
||||
testIntToEnumEval(3);
|
||||
}
|
||||
fn testIntToEnumEval(x: i32) void {
|
||||
assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
|
||||
assertOrPanic(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
|
||||
}
|
||||
const IntToEnumNumber = enum {
|
||||
Zero,
|
||||
@@ -110,8 +110,8 @@ const IntToEnumNumber = enum {
|
||||
};
|
||||
|
||||
test "@tagName" {
|
||||
assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
|
||||
comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
|
||||
assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
|
||||
comptime assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
|
||||
}
|
||||
|
||||
fn testEnumTagNameBare(n: BareNumber) []const u8 {
|
||||
@@ -126,8 +126,8 @@ const BareNumber = enum {
|
||||
|
||||
test "enum alignment" {
|
||||
comptime {
|
||||
assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
|
||||
assert(@alignOf(AlignTestEnum) >= @alignOf(u64));
|
||||
assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
|
||||
assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf(u64));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,10 +663,10 @@ const ValueCount257 = enum {
|
||||
|
||||
test "enum sizes" {
|
||||
comptime {
|
||||
assert(@sizeOf(ValueCount1) == 0);
|
||||
assert(@sizeOf(ValueCount2) == 1);
|
||||
assert(@sizeOf(ValueCount256) == 1);
|
||||
assert(@sizeOf(ValueCount257) == 2);
|
||||
assertOrPanic(@sizeOf(ValueCount1) == 0);
|
||||
assertOrPanic(@sizeOf(ValueCount2) == 1);
|
||||
assertOrPanic(@sizeOf(ValueCount256) == 1);
|
||||
assertOrPanic(@sizeOf(ValueCount257) == 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -685,12 +685,12 @@ test "set enum tag type" {
|
||||
{
|
||||
var x = Small.One;
|
||||
x = Small.Two;
|
||||
comptime assert(@TagType(Small) == u2);
|
||||
comptime assertOrPanic(@TagType(Small) == u2);
|
||||
}
|
||||
{
|
||||
var x = Small2.One;
|
||||
x = Small2.Two;
|
||||
comptime assert(@TagType(Small2) == u2);
|
||||
comptime assertOrPanic(@TagType(Small2) == u2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,17 +737,17 @@ const bit_field_1 = BitFieldOfEnums{
|
||||
|
||||
test "bit field access with enum fields" {
|
||||
var data = bit_field_1;
|
||||
assert(getA(&data) == A.Two);
|
||||
assert(getB(&data) == B.Three3);
|
||||
assert(getC(&data) == C.Four4);
|
||||
comptime assert(@sizeOf(BitFieldOfEnums) == 1);
|
||||
assertOrPanic(getA(&data) == A.Two);
|
||||
assertOrPanic(getB(&data) == B.Three3);
|
||||
assertOrPanic(getC(&data) == C.Four4);
|
||||
comptime assertOrPanic(@sizeOf(BitFieldOfEnums) == 1);
|
||||
|
||||
data.b = B.Four3;
|
||||
assert(data.b == B.Four3);
|
||||
assertOrPanic(data.b == B.Four3);
|
||||
|
||||
data.a = A.Three;
|
||||
assert(data.a == A.Three);
|
||||
assert(data.b == B.Four3);
|
||||
assertOrPanic(data.a == A.Three);
|
||||
assertOrPanic(data.b == B.Four3);
|
||||
}
|
||||
|
||||
fn getA(data: *const BitFieldOfEnums) A {
|
||||
@@ -768,7 +768,7 @@ test "casting enum to its tag type" {
|
||||
}
|
||||
|
||||
fn testCastEnumToTagType(value: Small2) void {
|
||||
assert(@enumToInt(value) == 1);
|
||||
assertOrPanic(@enumToInt(value) == 1);
|
||||
}
|
||||
|
||||
const MultipleChoice = enum(u32) {
|
||||
@@ -784,8 +784,8 @@ test "enum with specified tag values" {
|
||||
}
|
||||
|
||||
fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
|
||||
assert(@enumToInt(x) == 60);
|
||||
assert(1234 == switch (x) {
|
||||
assertOrPanic(@enumToInt(x) == 60);
|
||||
assertOrPanic(1234 == switch (x) {
|
||||
MultipleChoice.A => 1,
|
||||
MultipleChoice.B => 2,
|
||||
MultipleChoice.C => u32(1234),
|
||||
@@ -811,8 +811,8 @@ test "enum with specified and unspecified tag values" {
|
||||
}
|
||||
|
||||
fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
|
||||
assert(@enumToInt(x) == 1000);
|
||||
assert(1234 == switch (x) {
|
||||
assertOrPanic(@enumToInt(x) == 1000);
|
||||
assertOrPanic(1234 == switch (x) {
|
||||
MultipleChoice2.A => 1,
|
||||
MultipleChoice2.B => 2,
|
||||
MultipleChoice2.C => 3,
|
||||
@@ -826,8 +826,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
|
||||
}
|
||||
|
||||
test "cast integer literal to enum" {
|
||||
assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
|
||||
assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
|
||||
assertOrPanic(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
|
||||
assertOrPanic(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
|
||||
}
|
||||
|
||||
const EnumWithOneMember = enum {
|
||||
@@ -865,14 +865,14 @@ const EnumWithTagValues = enum(u4) {
|
||||
D = 1 << 3,
|
||||
};
|
||||
test "enum with tag values don't require parens" {
|
||||
assert(@enumToInt(EnumWithTagValues.C) == 0b0100);
|
||||
assertOrPanic(@enumToInt(EnumWithTagValues.C) == 0b0100);
|
||||
}
|
||||
|
||||
test "enum with 1 field but explicit tag type should still have the tag type" {
|
||||
const Enum = enum(u8) {
|
||||
B = 2,
|
||||
};
|
||||
comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8));
|
||||
comptime @import("std").debug.assertOrPanic(@sizeOf(Enum) == @sizeOf(u8));
|
||||
}
|
||||
|
||||
test "empty extern enum with members" {
|
||||
@@ -881,14 +881,14 @@ test "empty extern enum with members" {
|
||||
B,
|
||||
C,
|
||||
};
|
||||
assert(@sizeOf(E) == @sizeOf(c_int));
|
||||
assertOrPanic(@sizeOf(E) == @sizeOf(c_int));
|
||||
}
|
||||
|
||||
test "aoeu" {
|
||||
test "tag name with assigned enum values" {
|
||||
const LocalFoo = enum {
|
||||
A = 1,
|
||||
B = 0,
|
||||
};
|
||||
var b = LocalFoo.B;
|
||||
assert(mem.eql(u8, @tagName(b), "B"));
|
||||
assertOrPanic(mem.eql(u8, @tagName(b), "B"));
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
const mem = @import("std").mem;
|
||||
const fmt = @import("std").fmt;
|
||||
|
||||
@@ -19,9 +19,9 @@ test "enum with members" {
|
||||
const b = ET{ .UINT = 42 };
|
||||
var buf: [20]u8 = undefined;
|
||||
|
||||
assert((a.print(buf[0..]) catch unreachable) == 3);
|
||||
assert(mem.eql(u8, buf[0..3], "-42"));
|
||||
assertOrPanic((a.print(buf[0..]) catch unreachable) == 3);
|
||||
assertOrPanic(mem.eql(u8, buf[0..3], "-42"));
|
||||
|
||||
assert((b.print(buf[0..]) catch unreachable) == 2);
|
||||
assert(mem.eql(u8, buf[0..2], "42"));
|
||||
assertOrPanic((b.print(buf[0..]) catch unreachable) == 2);
|
||||
assertOrPanic(mem.eql(u8, buf[0..2], "42"));
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const assertError = std.debug.assertError;
|
||||
const mem = std.mem;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
@@ -18,7 +19,7 @@ pub fn baz() anyerror!i32 {
|
||||
}
|
||||
|
||||
test "error wrapping" {
|
||||
assert((baz() catch unreachable) == 15);
|
||||
assertOrPanic((baz() catch unreachable) == 15);
|
||||
}
|
||||
|
||||
fn gimmeItBroke() []const u8 {
|
||||
@@ -26,14 +27,14 @@ fn gimmeItBroke() []const u8 {
|
||||
}
|
||||
|
||||
test "@errorName" {
|
||||
assert(mem.eql(u8, @errorName(error.AnError), "AnError"));
|
||||
assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
|
||||
assertOrPanic(mem.eql(u8, @errorName(error.AnError), "AnError"));
|
||||
assertOrPanic(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
|
||||
}
|
||||
|
||||
test "error values" {
|
||||
const a = @errorToInt(error.err1);
|
||||
const b = @errorToInt(error.err2);
|
||||
assert(a != b);
|
||||
assertOrPanic(a != b);
|
||||
}
|
||||
|
||||
test "redefinition of error values allowed" {
|
||||
@@ -46,8 +47,8 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
|
||||
test "error binary operator" {
|
||||
const a = errBinaryOperatorG(true) catch 3;
|
||||
const b = errBinaryOperatorG(false) catch 3;
|
||||
assert(a == 3);
|
||||
assert(b == 10);
|
||||
assertOrPanic(a == 3);
|
||||
assertOrPanic(b == 10);
|
||||
}
|
||||
fn errBinaryOperatorG(x: bool) anyerror!isize {
|
||||
return if (x) error.ItBroke else isize(10);
|
||||
@@ -55,7 +56,7 @@ fn errBinaryOperatorG(x: bool) anyerror!isize {
|
||||
|
||||
test "unwrap simple value from error" {
|
||||
const i = unwrapSimpleValueFromErrorDo() catch unreachable;
|
||||
assert(i == 13);
|
||||
assertOrPanic(i == 13);
|
||||
}
|
||||
fn unwrapSimpleValueFromErrorDo() anyerror!isize {
|
||||
return 13;
|
||||
@@ -81,13 +82,13 @@ test "error union type " {
|
||||
|
||||
fn testErrorUnionType() void {
|
||||
const x: anyerror!i32 = 1234;
|
||||
if (x) |value| assert(value == 1234) else |_| unreachable;
|
||||
assert(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
|
||||
assert(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
|
||||
assert(@typeOf(x).ErrorSet == anyerror);
|
||||
if (x) |value| assertOrPanic(value == 1234) else |_| unreachable;
|
||||
assertOrPanic(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
|
||||
assertOrPanic(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
|
||||
assertOrPanic(@typeOf(x).ErrorSet == anyerror);
|
||||
}
|
||||
|
||||
test "error set type " {
|
||||
test "error set type" {
|
||||
testErrorSetType();
|
||||
comptime testErrorSetType();
|
||||
}
|
||||
@@ -98,12 +99,12 @@ const MyErrSet = error{
|
||||
};
|
||||
|
||||
fn testErrorSetType() void {
|
||||
assert(@memberCount(MyErrSet) == 2);
|
||||
assertOrPanic(@memberCount(MyErrSet) == 2);
|
||||
|
||||
const a: MyErrSet!i32 = 5678;
|
||||
const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
|
||||
|
||||
if (a) |value| assert(value == 5678) else |err| switch (err) {
|
||||
if (a) |value| assertOrPanic(value == 5678) else |err| switch (err) {
|
||||
error.OutOfMemory => unreachable,
|
||||
error.FileNotFound => unreachable,
|
||||
}
|
||||
@@ -126,7 +127,7 @@ const Set2 = error{
|
||||
fn testExplicitErrorSetCast(set1: Set1) void {
|
||||
var x = @errSetCast(Set2, set1);
|
||||
var y = @errSetCast(Set1, x);
|
||||
assert(y == error.A);
|
||||
assertOrPanic(y == error.A);
|
||||
}
|
||||
|
||||
test "comptime test error for empty error set" {
|
||||
@@ -137,12 +138,12 @@ test "comptime test error for empty error set" {
|
||||
const EmptyErrorSet = error{};
|
||||
|
||||
fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
|
||||
if (x) |v| assert(v == 1234) else |err| @compileError("bad");
|
||||
if (x) |v| assertOrPanic(v == 1234) else |err| @compileError("bad");
|
||||
}
|
||||
|
||||
test "syntax: optional operator in front of error union operator" {
|
||||
comptime {
|
||||
assert(?(anyerror!i32) == ?(anyerror!i32));
|
||||
assertOrPanic(?(anyerror!i32) == ?(anyerror!i32));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +162,6 @@ fn testErrToIntWithOnePossibleValue(
|
||||
|
||||
test "error union peer type resolution" {
|
||||
testErrorUnionPeerTypeResolution(1);
|
||||
comptime testErrorUnionPeerTypeResolution(1);
|
||||
}
|
||||
|
||||
fn testErrorUnionPeerTypeResolution(x: i32) void {
|
||||
@@ -170,6 +170,11 @@ fn testErrorUnionPeerTypeResolution(x: i32) void {
|
||||
2 => baz_1(),
|
||||
else => quux_1(),
|
||||
};
|
||||
if (y) |_| {
|
||||
@panic("expected error");
|
||||
} else |e| {
|
||||
assertOrPanic(e == error.A);
|
||||
}
|
||||
}
|
||||
|
||||
fn bar_1() anyerror {
|
||||
@@ -243,3 +248,85 @@ fn intLiteral(str: []const u8) !?i64 {
|
||||
|
||||
return error.T;
|
||||
}
|
||||
|
||||
test "nested error union function call in optional unwrap" {
|
||||
const S = struct {
|
||||
const Foo = struct {
|
||||
a: i32,
|
||||
};
|
||||
|
||||
fn errorable() !i32 {
|
||||
var x: Foo = (try getFoo()) orelse return error.Other;
|
||||
return x.a;
|
||||
}
|
||||
|
||||
fn errorable2() !i32 {
|
||||
var x: Foo = (try getFoo2()) orelse return error.Other;
|
||||
return x.a;
|
||||
}
|
||||
|
||||
fn errorable3() !i32 {
|
||||
var x: Foo = (try getFoo3()) orelse return error.Other;
|
||||
return x.a;
|
||||
}
|
||||
|
||||
fn getFoo() anyerror!?Foo {
|
||||
return Foo{ .a = 1234 };
|
||||
}
|
||||
|
||||
fn getFoo2() anyerror!?Foo {
|
||||
return error.Failure;
|
||||
}
|
||||
|
||||
fn getFoo3() anyerror!?Foo {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
assertOrPanic((try S.errorable()) == 1234);
|
||||
assertError(S.errorable2(), error.Failure);
|
||||
assertError(S.errorable3(), error.Other);
|
||||
comptime {
|
||||
assertOrPanic((try S.errorable()) == 1234);
|
||||
assertError(S.errorable2(), error.Failure);
|
||||
assertError(S.errorable3(), error.Other);
|
||||
}
|
||||
}
|
||||
|
||||
test "widen cast integer payload of error union function call" {
|
||||
const S = struct {
|
||||
fn errorable() !u64 {
|
||||
var x = u64(try number());
|
||||
return x;
|
||||
}
|
||||
|
||||
fn number() anyerror!u32 {
|
||||
return 1234;
|
||||
}
|
||||
};
|
||||
assertOrPanic((try S.errorable()) == 1234);
|
||||
}
|
||||
|
||||
test "return function call to error set from error union function" {
|
||||
const S = struct {
|
||||
fn errorable() anyerror!i32 {
|
||||
return fail();
|
||||
}
|
||||
|
||||
fn fail() anyerror {
|
||||
return error.Failure;
|
||||
}
|
||||
};
|
||||
assertError(S.errorable(), error.Failure);
|
||||
comptime assertError(S.errorable(), error.Failure);
|
||||
}
|
||||
|
||||
test "optional error set is the same size as error set" {
|
||||
comptime assertOrPanic(@sizeOf(?anyerror) == @sizeOf(anyerror));
|
||||
const S = struct {
|
||||
fn returnsOptErrSet() ?anyerror {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
assertOrPanic(S.returnsOptErrSet() == null);
|
||||
comptime assertOrPanic(S.returnsOptErrSet() == null);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const builtin = @import("builtin");
|
||||
|
||||
test "compile time recursion" {
|
||||
assert(some_data.len == 21);
|
||||
assertOrPanic(some_data.len == 21);
|
||||
}
|
||||
var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
|
||||
fn fibonacci(x: i32) i32 {
|
||||
@@ -16,7 +16,7 @@ fn unwrapAndAddOne(blah: ?i32) i32 {
|
||||
}
|
||||
const should_be_1235 = unwrapAndAddOne(1234);
|
||||
test "static add one" {
|
||||
assert(should_be_1235 == 1235);
|
||||
assertOrPanic(should_be_1235 == 1235);
|
||||
}
|
||||
|
||||
test "inlined loop" {
|
||||
@@ -24,7 +24,7 @@ test "inlined loop" {
|
||||
comptime var sum = 0;
|
||||
inline while (i <= 5) : (i += 1)
|
||||
sum += i;
|
||||
assert(sum == 15);
|
||||
assertOrPanic(sum == 15);
|
||||
}
|
||||
|
||||
fn gimme1or2(comptime a: bool) i32 {
|
||||
@@ -34,12 +34,12 @@ fn gimme1or2(comptime a: bool) i32 {
|
||||
return z;
|
||||
}
|
||||
test "inline variable gets result of const if" {
|
||||
assert(gimme1or2(true) == 1);
|
||||
assert(gimme1or2(false) == 2);
|
||||
assertOrPanic(gimme1or2(true) == 1);
|
||||
assertOrPanic(gimme1or2(false) == 2);
|
||||
}
|
||||
|
||||
test "static function evaluation" {
|
||||
assert(statically_added_number == 3);
|
||||
assertOrPanic(statically_added_number == 3);
|
||||
}
|
||||
const statically_added_number = staticAdd(1, 2);
|
||||
fn staticAdd(a: i32, b: i32) i32 {
|
||||
@@ -47,7 +47,8 @@ fn staticAdd(a: i32, b: i32) i32 {
|
||||
}
|
||||
|
||||
test "const expr eval on single expr blocks" {
|
||||
assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
|
||||
assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
|
||||
comptime assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
|
||||
}
|
||||
|
||||
fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
|
||||
@@ -63,10 +64,10 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
|
||||
}
|
||||
|
||||
test "statically initialized list" {
|
||||
assert(static_point_list[0].x == 1);
|
||||
assert(static_point_list[0].y == 2);
|
||||
assert(static_point_list[1].x == 3);
|
||||
assert(static_point_list[1].y == 4);
|
||||
assertOrPanic(static_point_list[0].x == 1);
|
||||
assertOrPanic(static_point_list[0].y == 2);
|
||||
assertOrPanic(static_point_list[1].x == 3);
|
||||
assertOrPanic(static_point_list[1].y == 4);
|
||||
}
|
||||
const Point = struct {
|
||||
x: i32,
|
||||
@@ -84,8 +85,8 @@ 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);
|
||||
assertOrPanic(static_vec3.data[2] == 1.0);
|
||||
assertOrPanic(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
|
||||
}
|
||||
const static_vec3 = vec3(0.0, 0.0, 1.0);
|
||||
pub const Vec3 = struct {
|
||||
@@ -101,12 +102,12 @@ pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
|
||||
|
||||
test "constant expressions" {
|
||||
var array: [array_size]u8 = undefined;
|
||||
assert(@sizeOf(@typeOf(array)) == 20);
|
||||
assertOrPanic(@sizeOf(@typeOf(array)) == 20);
|
||||
}
|
||||
const array_size: u8 = 20;
|
||||
|
||||
test "constant struct with negation" {
|
||||
assert(vertices[0].x == -0.6);
|
||||
assertOrPanic(vertices[0].x == -0.6);
|
||||
}
|
||||
const Vertex = struct {
|
||||
x: f32,
|
||||
@@ -141,7 +142,7 @@ const vertices = []Vertex{
|
||||
|
||||
test "statically initialized struct" {
|
||||
st_init_str_foo.x += 1;
|
||||
assert(st_init_str_foo.x == 14);
|
||||
assertOrPanic(st_init_str_foo.x == 14);
|
||||
}
|
||||
const StInitStrFoo = struct {
|
||||
x: i32,
|
||||
@@ -154,7 +155,7 @@ var st_init_str_foo = StInitStrFoo{
|
||||
|
||||
test "statically initalized array literal" {
|
||||
const y: [4]u8 = st_init_arr_lit_x;
|
||||
assert(y[3] == 4);
|
||||
assertOrPanic(y[3] == 4);
|
||||
}
|
||||
const st_init_arr_lit_x = []u8{
|
||||
1,
|
||||
@@ -166,15 +167,15 @@ const st_init_arr_lit_x = []u8{
|
||||
test "const slice" {
|
||||
comptime {
|
||||
const a = "1234567890";
|
||||
assert(a.len == 10);
|
||||
assertOrPanic(a.len == 10);
|
||||
const b = a[1..2];
|
||||
assert(b.len == 1);
|
||||
assert(b[0] == '2');
|
||||
assertOrPanic(b.len == 1);
|
||||
assertOrPanic(b[0] == '2');
|
||||
}
|
||||
}
|
||||
|
||||
test "try to trick eval with runtime if" {
|
||||
assert(testTryToTrickEvalWithRuntimeIf(true) == 10);
|
||||
assertOrPanic(testTryToTrickEvalWithRuntimeIf(true) == 10);
|
||||
}
|
||||
|
||||
fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
|
||||
@@ -200,16 +201,16 @@ fn letsTryToCompareBools(a: bool, b: bool) bool {
|
||||
return max(bool, a, b);
|
||||
}
|
||||
test "inlined block and runtime block phi" {
|
||||
assert(letsTryToCompareBools(true, true));
|
||||
assert(letsTryToCompareBools(true, false));
|
||||
assert(letsTryToCompareBools(false, true));
|
||||
assert(!letsTryToCompareBools(false, false));
|
||||
assertOrPanic(letsTryToCompareBools(true, true));
|
||||
assertOrPanic(letsTryToCompareBools(true, false));
|
||||
assertOrPanic(letsTryToCompareBools(false, true));
|
||||
assertOrPanic(!letsTryToCompareBools(false, false));
|
||||
|
||||
comptime {
|
||||
assert(letsTryToCompareBools(true, true));
|
||||
assert(letsTryToCompareBools(true, false));
|
||||
assert(letsTryToCompareBools(false, true));
|
||||
assert(!letsTryToCompareBools(false, false));
|
||||
assertOrPanic(letsTryToCompareBools(true, true));
|
||||
assertOrPanic(letsTryToCompareBools(true, false));
|
||||
assertOrPanic(letsTryToCompareBools(false, true));
|
||||
assertOrPanic(!letsTryToCompareBools(false, false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,14 +255,14 @@ fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
|
||||
}
|
||||
|
||||
test "comptime iterate over fn ptr list" {
|
||||
assert(performFn('t', 1) == 6);
|
||||
assert(performFn('o', 0) == 1);
|
||||
assert(performFn('w', 99) == 99);
|
||||
assertOrPanic(performFn('t', 1) == 6);
|
||||
assertOrPanic(performFn('o', 0) == 1);
|
||||
assertOrPanic(performFn('w', 99) == 99);
|
||||
}
|
||||
|
||||
test "eval @setRuntimeSafety at compile-time" {
|
||||
const result = comptime fnWithSetRuntimeSafety();
|
||||
assert(result == 1234);
|
||||
assertOrPanic(result == 1234);
|
||||
}
|
||||
|
||||
fn fnWithSetRuntimeSafety() i32 {
|
||||
@@ -271,7 +272,7 @@ fn fnWithSetRuntimeSafety() i32 {
|
||||
|
||||
test "eval @setFloatMode at compile-time" {
|
||||
const result = comptime fnWithFloatMode();
|
||||
assert(result == 1234.0);
|
||||
assertOrPanic(result == 1234.0);
|
||||
}
|
||||
|
||||
fn fnWithFloatMode() f32 {
|
||||
@@ -292,15 +293,15 @@ var simple_struct = SimpleStruct{ .field = 1234 };
|
||||
const bound_fn = simple_struct.method;
|
||||
|
||||
test "call method on bound fn referring to var instance" {
|
||||
assert(bound_fn() == 1237);
|
||||
assertOrPanic(bound_fn() == 1237);
|
||||
}
|
||||
|
||||
test "ptr to local array argument at comptime" {
|
||||
comptime {
|
||||
var bytes: [10]u8 = undefined;
|
||||
modifySomeBytes(bytes[0..]);
|
||||
assert(bytes[0] == 'a');
|
||||
assert(bytes[9] == 'b');
|
||||
assertOrPanic(bytes[0] == 'a');
|
||||
assertOrPanic(bytes[9] == 'b');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,9 +329,9 @@ fn testCompTimeUIntComparisons(x: u32) void {
|
||||
}
|
||||
|
||||
test "const ptr to variable data changes at runtime" {
|
||||
assert(foo_ref.name[0] == 'a');
|
||||
assertOrPanic(foo_ref.name[0] == 'a');
|
||||
foo_ref.name = "b";
|
||||
assert(foo_ref.name[0] == 'b');
|
||||
assertOrPanic(foo_ref.name[0] == 'b');
|
||||
}
|
||||
|
||||
const Foo = struct {
|
||||
@@ -341,8 +342,8 @@ 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);
|
||||
assertOrPanic(global_array[5] == 5 * 5);
|
||||
assertOrPanic(global_array[9] == 9 * 9);
|
||||
}
|
||||
|
||||
const global_array = x: {
|
||||
@@ -357,7 +358,7 @@ test "compile-time downcast when the bits fit" {
|
||||
comptime {
|
||||
const spartan_count: u16 = 255;
|
||||
const byte = @intCast(u8, spartan_count);
|
||||
assert(byte == 255);
|
||||
assertOrPanic(byte == 255);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,44 +366,45 @@ const hi1 = "hi";
|
||||
const hi2 = hi1;
|
||||
test "const global shares pointer with other same one" {
|
||||
assertEqualPtrs(&hi1[0], &hi2[0]);
|
||||
comptime assert(&hi1[0] == &hi2[0]);
|
||||
comptime assertOrPanic(&hi1[0] == &hi2[0]);
|
||||
}
|
||||
fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void {
|
||||
assert(ptr1 == ptr2);
|
||||
assertOrPanic(ptr1 == ptr2);
|
||||
}
|
||||
|
||||
test "@setEvalBranchQuota" {
|
||||
comptime {
|
||||
// 1001 for the loop and then 1 more for the assert fn call
|
||||
// 1001 for the loop and then 1 more for the assertOrPanic fn call
|
||||
@setEvalBranchQuota(1002);
|
||||
var i = 0;
|
||||
var sum = 0;
|
||||
while (i < 1001) : (i += 1) {
|
||||
sum += i;
|
||||
}
|
||||
assert(sum == 500500);
|
||||
assertOrPanic(sum == 500500);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO test "float literal at compile time not lossy" {
|
||||
// TODO assert(16777216.0 + 1.0 == 16777217.0);
|
||||
// TODO assert(9007199254740992.0 + 1.0 == 9007199254740993.0);
|
||||
// TODO assertOrPanic(16777216.0 + 1.0 == 16777217.0);
|
||||
// TODO assertOrPanic(9007199254740992.0 + 1.0 == 9007199254740993.0);
|
||||
// TODO }
|
||||
|
||||
test "f32 at compile time is lossy" {
|
||||
assert(f32(1 << 24) + 1 == 1 << 24);
|
||||
assertOrPanic(f32(1 << 24) + 1 == 1 << 24);
|
||||
}
|
||||
|
||||
test "f64 at compile time is lossy" {
|
||||
assert(f64(1 << 53) + 1 == 1 << 53);
|
||||
assertOrPanic(f64(1 << 53) + 1 == 1 << 53);
|
||||
}
|
||||
|
||||
test "f128 at compile time is lossy" {
|
||||
assert(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
|
||||
assertOrPanic(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
|
||||
}
|
||||
|
||||
// TODO need a better implementation of bigfloat_init_bigint
|
||||
// assert(f128(1 << 113) == 10384593717069655257060992658440192);
|
||||
comptime {
|
||||
assertOrPanic(f128(1 << 113) == 10384593717069655257060992658440192);
|
||||
}
|
||||
|
||||
pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
|
||||
return struct {
|
||||
@@ -413,15 +415,15 @@ pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
|
||||
test "string literal used as comptime slice is memoized" {
|
||||
const a = "link";
|
||||
const b = "link";
|
||||
comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
|
||||
comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
|
||||
comptime assertOrPanic(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
|
||||
comptime assertOrPanic(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
|
||||
}
|
||||
|
||||
test "comptime slice of undefined pointer of length 0" {
|
||||
const slice1 = ([*]i32)(undefined)[0..0];
|
||||
assert(slice1.len == 0);
|
||||
assertOrPanic(slice1.len == 0);
|
||||
const slice2 = ([*]i32)(undefined)[100..100];
|
||||
assert(slice2.len == 0);
|
||||
assertOrPanic(slice2.len == 0);
|
||||
}
|
||||
|
||||
fn copyWithPartialInline(s: []u32, b: []u8) void {
|
||||
@@ -443,16 +445,16 @@ test "binary math operator in partially inlined function" {
|
||||
r.* = @intCast(u8, i + 1);
|
||||
|
||||
copyWithPartialInline(s[0..], b[0..]);
|
||||
assert(s[0] == 0x1020304);
|
||||
assert(s[1] == 0x5060708);
|
||||
assert(s[2] == 0x90a0b0c);
|
||||
assert(s[3] == 0xd0e0f10);
|
||||
assertOrPanic(s[0] == 0x1020304);
|
||||
assertOrPanic(s[1] == 0x5060708);
|
||||
assertOrPanic(s[2] == 0x90a0b0c);
|
||||
assertOrPanic(s[3] == 0xd0e0f10);
|
||||
}
|
||||
|
||||
test "comptime function with the same args is memoized" {
|
||||
comptime {
|
||||
assert(MakeType(i32) == MakeType(i32));
|
||||
assert(MakeType(i32) != MakeType(f64));
|
||||
assertOrPanic(MakeType(i32) == MakeType(i32));
|
||||
assertOrPanic(MakeType(i32) != MakeType(f64));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,7 +470,7 @@ test "comptime function with mutable pointer is not memoized" {
|
||||
const ptr = &x;
|
||||
increment(ptr);
|
||||
increment(ptr);
|
||||
assert(x == 3);
|
||||
assertOrPanic(x == 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,14 +496,14 @@ fn doesAlotT(comptime T: type, value: usize) T {
|
||||
}
|
||||
|
||||
test "@setEvalBranchQuota at same scope as generic function call" {
|
||||
assert(doesAlotT(u32, 2) == 2);
|
||||
assertOrPanic(doesAlotT(u32, 2) == 2);
|
||||
}
|
||||
|
||||
test "comptime slice of slice preserves comptime var" {
|
||||
comptime {
|
||||
var buff: [10]u8 = undefined;
|
||||
buff[0..][0..][0] = 1;
|
||||
assert(buff[0..][0..][0] == 1);
|
||||
assertOrPanic(buff[0..][0..][0] == 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -510,7 +512,7 @@ test "comptime slice of pointer preserves comptime var" {
|
||||
var buff: [10]u8 = undefined;
|
||||
var a = buff[0..].ptr;
|
||||
a[0..1][0] = 1;
|
||||
assert(buff[0..][0..][0] == 1);
|
||||
assertOrPanic(buff[0..][0..][0] == 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,9 +526,9 @@ const SingleFieldStruct = struct {
|
||||
test "const ptr to comptime mutable data is not memoized" {
|
||||
comptime {
|
||||
var foo = SingleFieldStruct{ .x = 1 };
|
||||
assert(foo.read_x() == 1);
|
||||
assertOrPanic(foo.read_x() == 1);
|
||||
foo.x = 2;
|
||||
assert(foo.read_x() == 2);
|
||||
assertOrPanic(foo.read_x() == 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,7 +537,7 @@ test "array concat of slices gives slice" {
|
||||
var a: []const u8 = "aoeu";
|
||||
var b: []const u8 = "asdf";
|
||||
const c = a ++ b;
|
||||
assert(std.mem.eql(u8, c, "aoeuasdf"));
|
||||
assertOrPanic(std.mem.eql(u8, c, "aoeuasdf"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,14 +554,14 @@ test "comptime shlWithOverflow" {
|
||||
break :amt amt;
|
||||
};
|
||||
|
||||
assert(ct_shifted == rt_shifted);
|
||||
assertOrPanic(ct_shifted == rt_shifted);
|
||||
}
|
||||
|
||||
test "runtime 128 bit integer division" {
|
||||
var a: u128 = 152313999999999991610955792383;
|
||||
var b: u128 = 10000000000000000000;
|
||||
var c = a / b;
|
||||
assert(c == 15231399999);
|
||||
assertOrPanic(c == 15231399999);
|
||||
}
|
||||
|
||||
pub const Info = struct {
|
||||
@@ -572,20 +574,20 @@ test "comptime modification of const struct field" {
|
||||
comptime {
|
||||
var res = diamond_info;
|
||||
res.version = 1;
|
||||
assert(diamond_info.version == 0);
|
||||
assert(res.version == 1);
|
||||
assertOrPanic(diamond_info.version == 0);
|
||||
assertOrPanic(res.version == 1);
|
||||
}
|
||||
}
|
||||
|
||||
test "pointer to type" {
|
||||
comptime {
|
||||
var T: type = i32;
|
||||
assert(T == i32);
|
||||
assertOrPanic(T == i32);
|
||||
var ptr = &T;
|
||||
assert(@typeOf(ptr) == *type);
|
||||
assertOrPanic(@typeOf(ptr) == *type);
|
||||
ptr.* = f32;
|
||||
assert(T == f32);
|
||||
assert(*T == *f32);
|
||||
assertOrPanic(T == f32);
|
||||
assertOrPanic(*T == *f32);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -594,17 +596,17 @@ test "slice of type" {
|
||||
var types_array = []type{ i32, f64, type };
|
||||
for (types_array) |T, i| {
|
||||
switch (i) {
|
||||
0 => assert(T == i32),
|
||||
1 => assert(T == f64),
|
||||
2 => assert(T == type),
|
||||
0 => assertOrPanic(T == i32),
|
||||
1 => assertOrPanic(T == f64),
|
||||
2 => assertOrPanic(T == type),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
for (types_array[0..]) |T, i| {
|
||||
switch (i) {
|
||||
0 => assert(T == i32),
|
||||
1 => assert(T == f64),
|
||||
2 => assert(T == type),
|
||||
0 => assertOrPanic(T == i32),
|
||||
1 => assertOrPanic(T == f64),
|
||||
2 => assertOrPanic(T == type),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@@ -621,7 +623,7 @@ fn wrap(comptime T: type) Wrapper {
|
||||
|
||||
test "function which returns struct with type field causes implicit comptime" {
|
||||
const ty = wrap(i32).T;
|
||||
assert(ty == i32);
|
||||
assertOrPanic(ty == i32);
|
||||
}
|
||||
|
||||
test "call method with comptime pass-by-non-copying-value self parameter" {
|
||||
@@ -635,12 +637,12 @@ test "call method with comptime pass-by-non-copying-value self parameter" {
|
||||
|
||||
const s = S{ .a = 2 };
|
||||
var b = s.b();
|
||||
assert(b == 2);
|
||||
assertOrPanic(b == 2);
|
||||
}
|
||||
|
||||
test "@tagName of @typeId" {
|
||||
const str = @tagName(@typeId(u8));
|
||||
assert(std.mem.eql(u8, str, "Int"));
|
||||
assertOrPanic(std.mem.eql(u8, str, "Int"));
|
||||
}
|
||||
|
||||
test "setting backward branch quota just before a generic fn call" {
|
||||
@@ -661,8 +663,8 @@ fn testVarInsideInlineLoop(args: ...) void {
|
||||
comptime var i = 0;
|
||||
inline while (i < args.len) : (i += 1) {
|
||||
const x = args[i];
|
||||
if (i == 0) assert(x);
|
||||
if (i == 1) assert(x == 42);
|
||||
if (i == 0) assertOrPanic(x);
|
||||
if (i == 1) assertOrPanic(x == 42);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -672,7 +674,7 @@ test "inline for with same type but different values" {
|
||||
var a: T = undefined;
|
||||
res += a.len;
|
||||
}
|
||||
assert(res == 5);
|
||||
assertOrPanic(res == 5);
|
||||
}
|
||||
|
||||
test "refer to the type of a generic function" {
|
||||
@@ -686,19 +688,19 @@ fn doNothingWithType(comptime T: type) void {}
|
||||
test "zero extend from u0 to u1" {
|
||||
var zero_u0: u0 = 0;
|
||||
var zero_u1: u1 = zero_u0;
|
||||
assert(zero_u1 == 0);
|
||||
assertOrPanic(zero_u1 == 0);
|
||||
}
|
||||
|
||||
test "bit shift a u1" {
|
||||
var x: u1 = 1;
|
||||
var y = x << 0;
|
||||
assert(y == 1);
|
||||
assertOrPanic(y == 1);
|
||||
}
|
||||
|
||||
test "@intCast to a u0" {
|
||||
var x: u8 = 0;
|
||||
var y: u0 = @intCast(u0, x);
|
||||
assert(y == 0);
|
||||
assertOrPanic(y == 0);
|
||||
}
|
||||
|
||||
test "@bytesToslice on a packed struct" {
|
||||
@@ -708,7 +710,7 @@ test "@bytesToslice on a packed struct" {
|
||||
|
||||
var b = [1]u8{9};
|
||||
var f = @bytesToSlice(F, b);
|
||||
assert(f[0].a == 9);
|
||||
assertOrPanic(f[0].a == 9);
|
||||
}
|
||||
|
||||
test "comptime pointer cast array and then slice" {
|
||||
@@ -720,8 +722,8 @@ test "comptime pointer cast array and then slice" {
|
||||
const ptrB: [*]const u8 = &array;
|
||||
const sliceB: []const u8 = ptrB[0..2];
|
||||
|
||||
assert(sliceA[1] == 2);
|
||||
assert(sliceB[1] == 2);
|
||||
assertOrPanic(sliceA[1] == 2);
|
||||
assertOrPanic(sliceB[1] == 2);
|
||||
}
|
||||
|
||||
test "slice bounds in comptime concatenation" {
|
||||
@@ -730,47 +732,47 @@ test "slice bounds in comptime concatenation" {
|
||||
break :blk b[0..1];
|
||||
};
|
||||
const str = "" ++ bs;
|
||||
assert(str.len == 1);
|
||||
assert(std.mem.eql(u8, str, "1"));
|
||||
assertOrPanic(str.len == 1);
|
||||
assertOrPanic(std.mem.eql(u8, str, "1"));
|
||||
|
||||
const str2 = bs ++ "";
|
||||
assert(str2.len == 1);
|
||||
assert(std.mem.eql(u8, str2, "1"));
|
||||
assertOrPanic(str2.len == 1);
|
||||
assertOrPanic(std.mem.eql(u8, str2, "1"));
|
||||
}
|
||||
|
||||
test "comptime bitwise operators" {
|
||||
comptime {
|
||||
assert(3 & 1 == 1);
|
||||
assert(3 & -1 == 3);
|
||||
assert(-3 & -1 == -3);
|
||||
assert(3 | -1 == -1);
|
||||
assert(-3 | -1 == -1);
|
||||
assert(3 ^ -1 == -4);
|
||||
assert(-3 ^ -1 == 2);
|
||||
assert(~i8(-1) == 0);
|
||||
assert(~i128(-1) == 0);
|
||||
assert(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
|
||||
assert(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
|
||||
assert(~u128(0) == 0xffffffffffffffffffffffffffffffff);
|
||||
assertOrPanic(3 & 1 == 1);
|
||||
assertOrPanic(3 & -1 == 3);
|
||||
assertOrPanic(-3 & -1 == -3);
|
||||
assertOrPanic(3 | -1 == -1);
|
||||
assertOrPanic(-3 | -1 == -1);
|
||||
assertOrPanic(3 ^ -1 == -4);
|
||||
assertOrPanic(-3 ^ -1 == 2);
|
||||
assertOrPanic(~i8(-1) == 0);
|
||||
assertOrPanic(~i128(-1) == 0);
|
||||
assertOrPanic(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
|
||||
assertOrPanic(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
|
||||
assertOrPanic(~u128(0) == 0xffffffffffffffffffffffffffffffff);
|
||||
}
|
||||
}
|
||||
|
||||
test "*align(1) u16 is the same as *align(1:0:2) u16" {
|
||||
comptime {
|
||||
assert(*align(1:0:2) u16 == *align(1) u16);
|
||||
assertOrPanic(*align(1:0:2) u16 == *align(1) u16);
|
||||
// TODO add parsing support for this syntax
|
||||
//assert(*align(:0:2) u16 == *u16);
|
||||
//assertOrPanic(*align(:0:2) u16 == *u16);
|
||||
}
|
||||
}
|
||||
|
||||
test "array concatenation forces comptime" {
|
||||
var a = oneItem(3) ++ oneItem(4);
|
||||
assert(std.mem.eql(i32, a, []i32{3, 4}));
|
||||
assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 4 }));
|
||||
}
|
||||
|
||||
test "array multiplication forces comptime" {
|
||||
var a = oneItem(3) ** scalar(2);
|
||||
assert(std.mem.eql(i32, a, []i32{3, 3}));
|
||||
assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 3 }));
|
||||
}
|
||||
|
||||
fn oneItem(x: i32) [1]i32 {
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "@fieldParentPtr non-first field" {
|
||||
testParentFieldPtr(&foo.c);
|
||||
@@ -25,17 +25,17 @@ const foo = Foo{
|
||||
};
|
||||
|
||||
fn testParentFieldPtr(c: *const i32) void {
|
||||
assert(c == &foo.c);
|
||||
assertOrPanic(c == &foo.c);
|
||||
|
||||
const base = @fieldParentPtr(Foo, "c", c);
|
||||
assert(base == &foo);
|
||||
assert(&base.c == c);
|
||||
assertOrPanic(base == &foo);
|
||||
assertOrPanic(&base.c == c);
|
||||
}
|
||||
|
||||
fn testParentFieldPtrFirst(a: *const bool) void {
|
||||
assert(a == &foo.a);
|
||||
assertOrPanic(a == &foo.a);
|
||||
|
||||
const base = @fieldParentPtr(Foo, "a", a);
|
||||
assert(base == &foo);
|
||||
assert(&base.a == a);
|
||||
assertOrPanic(base == &foo);
|
||||
assertOrPanic(&base.a == a);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "params" {
|
||||
assert(testParamsAdd(22, 11) == 33);
|
||||
assertOrPanic(testParamsAdd(22, 11) == 33);
|
||||
}
|
||||
fn testParamsAdd(a: i32, b: i32) i32 {
|
||||
return a + b;
|
||||
@@ -21,32 +21,32 @@ test "void parameters" {
|
||||
fn voidFun(a: i32, b: void, c: i32, d: void) void {
|
||||
const v = b;
|
||||
const vv: void = if (a == 1) v else {};
|
||||
assert(a + c == 3);
|
||||
assertOrPanic(a + c == 3);
|
||||
return vv;
|
||||
}
|
||||
|
||||
test "mutable local variables" {
|
||||
var zero: i32 = 0;
|
||||
assert(zero == 0);
|
||||
assertOrPanic(zero == 0);
|
||||
|
||||
var i = i32(0);
|
||||
while (i != 3) {
|
||||
i += 1;
|
||||
}
|
||||
assert(i == 3);
|
||||
assertOrPanic(i == 3);
|
||||
}
|
||||
|
||||
test "separate block scopes" {
|
||||
{
|
||||
const no_conflict: i32 = 5;
|
||||
assert(no_conflict == 5);
|
||||
assertOrPanic(no_conflict == 5);
|
||||
}
|
||||
|
||||
const c = x: {
|
||||
const no_conflict = i32(10);
|
||||
break :x no_conflict;
|
||||
};
|
||||
assert(c == 10);
|
||||
assertOrPanic(c == 10);
|
||||
}
|
||||
|
||||
test "call function with empty string" {
|
||||
@@ -59,7 +59,7 @@ fn @"weird function name"() i32 {
|
||||
return 1234;
|
||||
}
|
||||
test "weird function name" {
|
||||
assert(@"weird function name"() == 1234);
|
||||
assertOrPanic(@"weird function name"() == 1234);
|
||||
}
|
||||
|
||||
test "implicit cast function unreachable return" {
|
||||
@@ -80,7 +80,7 @@ test "function pointers" {
|
||||
fn4,
|
||||
};
|
||||
for (fns) |f, i| {
|
||||
assert(f() == @intCast(u32, i) + 5);
|
||||
assertOrPanic(f() == @intCast(u32, i) + 5);
|
||||
}
|
||||
}
|
||||
fn fn1() u32 {
|
||||
@@ -97,7 +97,7 @@ fn fn4() u32 {
|
||||
}
|
||||
|
||||
test "inline function call" {
|
||||
assert(@inlineCall(add, 3, 9) == 12);
|
||||
assertOrPanic(@inlineCall(add, 3, 9) == 12);
|
||||
}
|
||||
|
||||
fn add(a: i32, b: i32) i32 {
|
||||
@@ -110,7 +110,7 @@ test "number literal as an argument" {
|
||||
}
|
||||
|
||||
fn numberLiteralArg(a: var) void {
|
||||
assert(a == 3);
|
||||
assertOrPanic(a == 3);
|
||||
}
|
||||
|
||||
test "assign inline fn to const variable" {
|
||||
@@ -121,7 +121,7 @@ test "assign inline fn to const variable" {
|
||||
inline fn inlineFn() void {}
|
||||
|
||||
test "pass by non-copying value" {
|
||||
assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
|
||||
assertOrPanic(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
|
||||
}
|
||||
|
||||
const Point = struct {
|
||||
@@ -134,17 +134,17 @@ fn addPointCoords(pt: Point) i32 {
|
||||
}
|
||||
|
||||
test "pass by non-copying value through var arg" {
|
||||
assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
|
||||
assertOrPanic(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
|
||||
}
|
||||
|
||||
fn addPointCoordsVar(pt: var) i32 {
|
||||
comptime assert(@typeOf(pt) == Point);
|
||||
comptime assertOrPanic(@typeOf(pt) == Point);
|
||||
return pt.x + pt.y;
|
||||
}
|
||||
|
||||
test "pass by non-copying value as method" {
|
||||
var pt = Point2{ .x = 1, .y = 2 };
|
||||
assert(pt.addPointCoords() == 3);
|
||||
assertOrPanic(pt.addPointCoords() == 3);
|
||||
}
|
||||
|
||||
const Point2 = struct {
|
||||
@@ -158,7 +158,7 @@ const Point2 = struct {
|
||||
|
||||
test "pass by non-copying value as method, which is generic" {
|
||||
var pt = Point3{ .x = 1, .y = 2 };
|
||||
assert(pt.addPointCoords(i32) == 3);
|
||||
assertOrPanic(pt.addPointCoords(i32) == 3);
|
||||
}
|
||||
|
||||
const Point3 = struct {
|
||||
@@ -173,7 +173,7 @@ const Point3 = struct {
|
||||
test "pass by non-copying value as method, at comptime" {
|
||||
comptime {
|
||||
var pt = Point2{ .x = 1, .y = 2 };
|
||||
assert(pt.addPointCoords() == 3);
|
||||
assertOrPanic(pt.addPointCoords() == 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ fn outer(y: u32) fn (u32) u32 {
|
||||
|
||||
test "return inner function which references comptime variable of outer function" {
|
||||
var func = outer(10);
|
||||
assert(func(3) == 7);
|
||||
assertOrPanic(func(3) == 7);
|
||||
}
|
||||
|
||||
test "extern struct with stdcallcc fn pointer" {
|
||||
@@ -203,5 +203,6 @@ test "extern struct with stdcallcc fn pointer" {
|
||||
|
||||
var s: S = undefined;
|
||||
s.ptr = S.foo;
|
||||
assert(s.ptr() == 1234);
|
||||
assertOrPanic(s.ptr() == 1234);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
fn get_foo() fn (*u8) usize {
|
||||
comptime {
|
||||
@@ -13,5 +13,5 @@ fn get_foo() fn (*u8) usize {
|
||||
|
||||
test "define a function in an anonymous struct in comptime" {
|
||||
const foo = get_foo();
|
||||
assert(foo(@intToPtr(*u8, 12345)) == 12345);
|
||||
assertOrPanic(foo(@intToPtr(*u8, 12345)) == 12345);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const mem = std.mem;
|
||||
|
||||
test "continue in for loop" {
|
||||
@@ -26,7 +26,7 @@ test "for loop with pointer elem var" {
|
||||
var target: [source.len]u8 = undefined;
|
||||
mem.copy(u8, target[0..], source);
|
||||
mangleString(target[0..]);
|
||||
assert(mem.eql(u8, target, "bcdefgh"));
|
||||
assertOrPanic(mem.eql(u8, target, "bcdefgh"));
|
||||
}
|
||||
fn mangleString(s: []u8) void {
|
||||
for (s) |*c| {
|
||||
@@ -68,7 +68,7 @@ test "basic for loop" {
|
||||
buf_index += 1;
|
||||
}
|
||||
|
||||
assert(mem.eql(u8, buffer[0..buf_index], expected_result));
|
||||
assertOrPanic(mem.eql(u8, buffer[0..buf_index], expected_result));
|
||||
}
|
||||
|
||||
test "break from outer for loop" {
|
||||
@@ -85,7 +85,7 @@ fn testBreakOuter() void {
|
||||
break :outer;
|
||||
}
|
||||
}
|
||||
assert(count == 1);
|
||||
assertOrPanic(count == 1);
|
||||
}
|
||||
|
||||
test "continue outer for loop" {
|
||||
@@ -102,5 +102,5 @@ fn testContinueOuter() void {
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
assert(counter == array.len);
|
||||
assertOrPanic(counter == array.len);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "simple generic fn" {
|
||||
assert(max(i32, 3, -1) == 3);
|
||||
assert(max(f32, 0.123, 0.456) == 0.456);
|
||||
assert(add(2, 3) == 5);
|
||||
assertOrPanic(max(i32, 3, -1) == 3);
|
||||
assertOrPanic(max(f32, 0.123, 0.456) == 0.456);
|
||||
assertOrPanic(add(2, 3) == 5);
|
||||
}
|
||||
|
||||
fn max(comptime T: type, a: T, b: T) T {
|
||||
@@ -16,7 +16,7 @@ fn add(comptime a: i32, b: i32) i32 {
|
||||
|
||||
const the_max = max(u32, 1234, 5678);
|
||||
test "compile time generic eval" {
|
||||
assert(the_max == 5678);
|
||||
assertOrPanic(the_max == 5678);
|
||||
}
|
||||
|
||||
fn gimmeTheBigOne(a: u32, b: u32) u32 {
|
||||
@@ -32,19 +32,19 @@ fn sameButWithFloats(a: f64, b: f64) f64 {
|
||||
}
|
||||
|
||||
test "fn with comptime args" {
|
||||
assert(gimmeTheBigOne(1234, 5678) == 5678);
|
||||
assert(shouldCallSameInstance(34, 12) == 34);
|
||||
assert(sameButWithFloats(0.43, 0.49) == 0.49);
|
||||
assertOrPanic(gimmeTheBigOne(1234, 5678) == 5678);
|
||||
assertOrPanic(shouldCallSameInstance(34, 12) == 34);
|
||||
assertOrPanic(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);
|
||||
assertOrPanic(max_i32(12, 34) == 34);
|
||||
assertOrPanic(max_f64(1.2, 3.4) == 3.4);
|
||||
}
|
||||
|
||||
comptime {
|
||||
assert(max_i32(12, 34) == 34);
|
||||
assert(max_f64(1.2, 3.4) == 3.4);
|
||||
assertOrPanic(max_i32(12, 34) == 34);
|
||||
assertOrPanic(max_f64(1.2, 3.4) == 3.4);
|
||||
}
|
||||
|
||||
fn max_var(a: var, b: var) @typeOf(a + b) {
|
||||
@@ -76,8 +76,8 @@ test "function with return type type" {
|
||||
var list2: List(i32) = undefined;
|
||||
list.length = 10;
|
||||
list2.length = 10;
|
||||
assert(list.prealloc_items.len == 8);
|
||||
assert(list2.prealloc_items.len == 8);
|
||||
assertOrPanic(list.prealloc_items.len == 8);
|
||||
assertOrPanic(list2.prealloc_items.len == 8);
|
||||
}
|
||||
|
||||
test "generic struct" {
|
||||
@@ -89,9 +89,9 @@ test "generic struct" {
|
||||
.value = true,
|
||||
.next = null,
|
||||
};
|
||||
assert(a1.value == 13);
|
||||
assert(a1.value == a1.getVal());
|
||||
assert(b1.getVal());
|
||||
assertOrPanic(a1.value == 13);
|
||||
assertOrPanic(a1.value == a1.getVal());
|
||||
assertOrPanic(b1.getVal());
|
||||
}
|
||||
fn GenNode(comptime T: type) type {
|
||||
return struct {
|
||||
@@ -104,7 +104,7 @@ fn GenNode(comptime T: type) type {
|
||||
}
|
||||
|
||||
test "const decls in struct" {
|
||||
assert(GenericDataThing(3).count_plus_one == 4);
|
||||
assertOrPanic(GenericDataThing(3).count_plus_one == 4);
|
||||
}
|
||||
fn GenericDataThing(comptime count: isize) type {
|
||||
return struct {
|
||||
@@ -113,15 +113,15 @@ fn GenericDataThing(comptime count: isize) type {
|
||||
}
|
||||
|
||||
test "use generic param in generic param" {
|
||||
assert(aGenericFn(i32, 3, 4) == 7);
|
||||
assertOrPanic(aGenericFn(i32, 3, 4) == 7);
|
||||
}
|
||||
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{
|
||||
assertOrPanic(getFirstByte(u8, []u8{13}) == 13);
|
||||
assertOrPanic(getFirstByte(u16, []u16{
|
||||
0,
|
||||
13,
|
||||
}) == 0);
|
||||
@@ -146,6 +146,6 @@ fn foo2(arg: var) bool {
|
||||
}
|
||||
|
||||
test "array of generic fns" {
|
||||
assert(foos[0](true));
|
||||
assert(!foos[1](true));
|
||||
assertOrPanic(foos[0](true));
|
||||
assertOrPanic(!foos[1](true));
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "if statements" {
|
||||
shouldBeEqual(1, 1);
|
||||
@@ -24,7 +24,7 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void {
|
||||
}
|
||||
|
||||
test "else if expression" {
|
||||
assert(elseIfExpressionF(1) == 1);
|
||||
assertOrPanic(elseIfExpressionF(1) == 1);
|
||||
}
|
||||
fn elseIfExpressionF(c: u8) u8 {
|
||||
if (c == 0) {
|
||||
10
test/stage1/behavior/import.zig
Normal file
10
test/stage1/behavior/import.zig
Normal file
@@ -0,0 +1,10 @@
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
const a_namespace = @import("import/a_namespace.zig");
|
||||
|
||||
test "call fn via namespace lookup" {
|
||||
assertOrPanic(a_namespace.foo() == 1234);
|
||||
}
|
||||
|
||||
test "importing the same thing gives the same import" {
|
||||
assertOrPanic(@import("std") == @import("std"));
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
const A = struct {
|
||||
b: B,
|
||||
@@ -26,5 +26,5 @@ test "incomplete struct param top level declaration" {
|
||||
.c = C{ .x = 13 },
|
||||
},
|
||||
};
|
||||
assert(foo(a) == 13);
|
||||
assertOrPanic(foo(a) == 13);
|
||||
}
|
||||
@@ -24,4 +24,3 @@ fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
fn foo(id: u64) !i32 {
|
||||
return switch (id) {
|
||||
@@ -16,6 +16,6 @@ fn getErrInt() anyerror!i32 {
|
||||
}
|
||||
|
||||
test "ir block deps" {
|
||||
assert((foo(1) catch unreachable) == 0);
|
||||
assert((foo(2) catch unreachable) == 0);
|
||||
assertOrPanic((foo(1) catch unreachable) == 0);
|
||||
assertOrPanic((foo(2) catch unreachable) == 0);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const maxInt = std.math.maxInt;
|
||||
const minInt = std.math.minInt;
|
||||
|
||||
@@ -8,57 +8,57 @@ test "division" {
|
||||
comptime testDivision();
|
||||
}
|
||||
fn testDivision() void {
|
||||
assert(div(u32, 13, 3) == 4);
|
||||
assert(div(f16, 1.0, 2.0) == 0.5);
|
||||
assert(div(f32, 1.0, 2.0) == 0.5);
|
||||
assertOrPanic(div(u32, 13, 3) == 4);
|
||||
assertOrPanic(div(f16, 1.0, 2.0) == 0.5);
|
||||
assertOrPanic(div(f32, 1.0, 2.0) == 0.5);
|
||||
|
||||
assert(divExact(u32, 55, 11) == 5);
|
||||
assert(divExact(i32, -55, 11) == -5);
|
||||
assert(divExact(f16, 55.0, 11.0) == 5.0);
|
||||
assert(divExact(f16, -55.0, 11.0) == -5.0);
|
||||
assert(divExact(f32, 55.0, 11.0) == 5.0);
|
||||
assert(divExact(f32, -55.0, 11.0) == -5.0);
|
||||
assertOrPanic(divExact(u32, 55, 11) == 5);
|
||||
assertOrPanic(divExact(i32, -55, 11) == -5);
|
||||
assertOrPanic(divExact(f16, 55.0, 11.0) == 5.0);
|
||||
assertOrPanic(divExact(f16, -55.0, 11.0) == -5.0);
|
||||
assertOrPanic(divExact(f32, 55.0, 11.0) == 5.0);
|
||||
assertOrPanic(divExact(f32, -55.0, 11.0) == -5.0);
|
||||
|
||||
assert(divFloor(i32, 5, 3) == 1);
|
||||
assert(divFloor(i32, -5, 3) == -2);
|
||||
assert(divFloor(f16, 5.0, 3.0) == 1.0);
|
||||
assert(divFloor(f16, -5.0, 3.0) == -2.0);
|
||||
assert(divFloor(f32, 5.0, 3.0) == 1.0);
|
||||
assert(divFloor(f32, -5.0, 3.0) == -2.0);
|
||||
assert(divFloor(i32, -0x80000000, -2) == 0x40000000);
|
||||
assert(divFloor(i32, 0, -0x80000000) == 0);
|
||||
assert(divFloor(i32, -0x40000001, 0x40000000) == -2);
|
||||
assert(divFloor(i32, -0x80000000, 1) == -0x80000000);
|
||||
assertOrPanic(divFloor(i32, 5, 3) == 1);
|
||||
assertOrPanic(divFloor(i32, -5, 3) == -2);
|
||||
assertOrPanic(divFloor(f16, 5.0, 3.0) == 1.0);
|
||||
assertOrPanic(divFloor(f16, -5.0, 3.0) == -2.0);
|
||||
assertOrPanic(divFloor(f32, 5.0, 3.0) == 1.0);
|
||||
assertOrPanic(divFloor(f32, -5.0, 3.0) == -2.0);
|
||||
assertOrPanic(divFloor(i32, -0x80000000, -2) == 0x40000000);
|
||||
assertOrPanic(divFloor(i32, 0, -0x80000000) == 0);
|
||||
assertOrPanic(divFloor(i32, -0x40000001, 0x40000000) == -2);
|
||||
assertOrPanic(divFloor(i32, -0x80000000, 1) == -0x80000000);
|
||||
|
||||
assert(divTrunc(i32, 5, 3) == 1);
|
||||
assert(divTrunc(i32, -5, 3) == -1);
|
||||
assert(divTrunc(f16, 5.0, 3.0) == 1.0);
|
||||
assert(divTrunc(f16, -5.0, 3.0) == -1.0);
|
||||
assert(divTrunc(f32, 5.0, 3.0) == 1.0);
|
||||
assert(divTrunc(f32, -5.0, 3.0) == -1.0);
|
||||
assert(divTrunc(f64, 5.0, 3.0) == 1.0);
|
||||
assert(divTrunc(f64, -5.0, 3.0) == -1.0);
|
||||
assertOrPanic(divTrunc(i32, 5, 3) == 1);
|
||||
assertOrPanic(divTrunc(i32, -5, 3) == -1);
|
||||
assertOrPanic(divTrunc(f16, 5.0, 3.0) == 1.0);
|
||||
assertOrPanic(divTrunc(f16, -5.0, 3.0) == -1.0);
|
||||
assertOrPanic(divTrunc(f32, 5.0, 3.0) == 1.0);
|
||||
assertOrPanic(divTrunc(f32, -5.0, 3.0) == -1.0);
|
||||
assertOrPanic(divTrunc(f64, 5.0, 3.0) == 1.0);
|
||||
assertOrPanic(divTrunc(f64, -5.0, 3.0) == -1.0);
|
||||
|
||||
comptime {
|
||||
assert(
|
||||
assertOrPanic(
|
||||
1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
|
||||
);
|
||||
assert(
|
||||
assertOrPanic(
|
||||
@rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
|
||||
);
|
||||
assert(
|
||||
assertOrPanic(
|
||||
1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
|
||||
);
|
||||
assert(
|
||||
assertOrPanic(
|
||||
@divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
|
||||
);
|
||||
assert(
|
||||
assertOrPanic(
|
||||
@divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
|
||||
);
|
||||
assert(
|
||||
assertOrPanic(
|
||||
@divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
|
||||
);
|
||||
assert(
|
||||
assertOrPanic(
|
||||
4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
|
||||
);
|
||||
}
|
||||
@@ -78,9 +78,9 @@ fn divTrunc(comptime T: type, a: T, b: T) T {
|
||||
|
||||
test "@addWithOverflow" {
|
||||
var result: u8 = undefined;
|
||||
assert(@addWithOverflow(u8, 250, 100, &result));
|
||||
assert(!@addWithOverflow(u8, 100, 150, &result));
|
||||
assert(result == 250);
|
||||
assertOrPanic(@addWithOverflow(u8, 250, 100, &result));
|
||||
assertOrPanic(!@addWithOverflow(u8, 100, 150, &result));
|
||||
assertOrPanic(result == 250);
|
||||
}
|
||||
|
||||
// TODO test mulWithOverflow
|
||||
@@ -88,9 +88,9 @@ test "@addWithOverflow" {
|
||||
|
||||
test "@shlWithOverflow" {
|
||||
var result: u16 = undefined;
|
||||
assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
|
||||
assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
|
||||
assert(result == 0b1011111111111100);
|
||||
assertOrPanic(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
|
||||
assertOrPanic(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
|
||||
assertOrPanic(result == 0b1011111111111100);
|
||||
}
|
||||
|
||||
test "@clz" {
|
||||
@@ -99,11 +99,11 @@ test "@clz" {
|
||||
}
|
||||
|
||||
fn testClz() void {
|
||||
assert(clz(u8(0b00001010)) == 4);
|
||||
assert(clz(u8(0b10001010)) == 0);
|
||||
assert(clz(u8(0b00000000)) == 8);
|
||||
assert(clz(u128(0xffffffffffffffff)) == 64);
|
||||
assert(clz(u128(0x10000000000000000)) == 63);
|
||||
assertOrPanic(clz(u8(0b00001010)) == 4);
|
||||
assertOrPanic(clz(u8(0b10001010)) == 0);
|
||||
assertOrPanic(clz(u8(0b00000000)) == 8);
|
||||
assertOrPanic(clz(u128(0xffffffffffffffff)) == 64);
|
||||
assertOrPanic(clz(u128(0x10000000000000000)) == 63);
|
||||
}
|
||||
|
||||
fn clz(x: var) usize {
|
||||
@@ -116,9 +116,9 @@ test "@ctz" {
|
||||
}
|
||||
|
||||
fn testCtz() void {
|
||||
assert(ctz(u8(0b10100000)) == 5);
|
||||
assert(ctz(u8(0b10001010)) == 1);
|
||||
assert(ctz(u8(0b00000000)) == 8);
|
||||
assertOrPanic(ctz(u8(0b10100000)) == 5);
|
||||
assertOrPanic(ctz(u8(0b10001010)) == 1);
|
||||
assertOrPanic(ctz(u8(0b00000000)) == 8);
|
||||
}
|
||||
|
||||
fn ctz(x: var) usize {
|
||||
@@ -128,27 +128,27 @@ fn ctz(x: var) usize {
|
||||
test "assignment operators" {
|
||||
var i: u32 = 0;
|
||||
i += 5;
|
||||
assert(i == 5);
|
||||
assertOrPanic(i == 5);
|
||||
i -= 2;
|
||||
assert(i == 3);
|
||||
assertOrPanic(i == 3);
|
||||
i *= 20;
|
||||
assert(i == 60);
|
||||
assertOrPanic(i == 60);
|
||||
i /= 3;
|
||||
assert(i == 20);
|
||||
assertOrPanic(i == 20);
|
||||
i %= 11;
|
||||
assert(i == 9);
|
||||
assertOrPanic(i == 9);
|
||||
i <<= 1;
|
||||
assert(i == 18);
|
||||
assertOrPanic(i == 18);
|
||||
i >>= 2;
|
||||
assert(i == 4);
|
||||
assertOrPanic(i == 4);
|
||||
i = 6;
|
||||
i &= 5;
|
||||
assert(i == 4);
|
||||
assertOrPanic(i == 4);
|
||||
i ^= 6;
|
||||
assert(i == 2);
|
||||
assertOrPanic(i == 2);
|
||||
i = 6;
|
||||
i |= 3;
|
||||
assert(i == 7);
|
||||
assertOrPanic(i == 7);
|
||||
}
|
||||
|
||||
test "three expr in a row" {
|
||||
@@ -170,14 +170,14 @@ fn testThreeExprInARow(f: bool, t: bool) void {
|
||||
assertFalse(i32(7) != --(i32(7)));
|
||||
}
|
||||
fn assertFalse(b: bool) void {
|
||||
assert(!b);
|
||||
assertOrPanic(!b);
|
||||
}
|
||||
|
||||
test "const number literal" {
|
||||
const one = 1;
|
||||
const eleven = ten + one;
|
||||
|
||||
assert(eleven == 11);
|
||||
assertOrPanic(eleven == 11);
|
||||
}
|
||||
const ten = 10;
|
||||
|
||||
@@ -187,9 +187,9 @@ test "unsigned wrapping" {
|
||||
}
|
||||
fn testUnsignedWrappingEval(x: u32) void {
|
||||
const zero = x +% 1;
|
||||
assert(zero == 0);
|
||||
assertOrPanic(zero == 0);
|
||||
const orig = zero -% 1;
|
||||
assert(orig == maxInt(u32));
|
||||
assertOrPanic(orig == maxInt(u32));
|
||||
}
|
||||
|
||||
test "signed wrapping" {
|
||||
@@ -198,9 +198,9 @@ test "signed wrapping" {
|
||||
}
|
||||
fn testSignedWrappingEval(x: i32) void {
|
||||
const min_val = x +% 1;
|
||||
assert(min_val == minInt(i32));
|
||||
assertOrPanic(min_val == minInt(i32));
|
||||
const max_val = min_val -% 1;
|
||||
assert(max_val == maxInt(i32));
|
||||
assertOrPanic(max_val == maxInt(i32));
|
||||
}
|
||||
|
||||
test "negation wrapping" {
|
||||
@@ -208,9 +208,9 @@ test "negation wrapping" {
|
||||
comptime testNegationWrappingEval(minInt(i16));
|
||||
}
|
||||
fn testNegationWrappingEval(x: i16) void {
|
||||
assert(x == -32768);
|
||||
assertOrPanic(x == -32768);
|
||||
const neg = -%x;
|
||||
assert(neg == -32768);
|
||||
assertOrPanic(neg == -32768);
|
||||
}
|
||||
|
||||
test "unsigned 64-bit division" {
|
||||
@@ -219,8 +219,8 @@ test "unsigned 64-bit division" {
|
||||
}
|
||||
fn test_u64_div() void {
|
||||
const result = divWithResult(1152921504606846976, 34359738365);
|
||||
assert(result.quotient == 33554432);
|
||||
assert(result.remainder == 100663296);
|
||||
assertOrPanic(result.quotient == 33554432);
|
||||
assertOrPanic(result.remainder == 100663296);
|
||||
}
|
||||
fn divWithResult(a: u64, b: u64) DivResult {
|
||||
return DivResult{
|
||||
@@ -234,36 +234,36 @@ const DivResult = struct {
|
||||
};
|
||||
|
||||
test "binary not" {
|
||||
assert(comptime x: {
|
||||
assertOrPanic(comptime x: {
|
||||
break :x ~u16(0b1010101010101010) == 0b0101010101010101;
|
||||
});
|
||||
assert(comptime x: {
|
||||
assertOrPanic(comptime x: {
|
||||
break :x ~u64(2147483647) == 18446744071562067968;
|
||||
});
|
||||
testBinaryNot(0b1010101010101010);
|
||||
}
|
||||
|
||||
fn testBinaryNot(x: u16) void {
|
||||
assert(~x == 0b0101010101010101);
|
||||
assertOrPanic(~x == 0b0101010101010101);
|
||||
}
|
||||
|
||||
test "small int addition" {
|
||||
var x: @IntType(false, 2) = 0;
|
||||
assert(x == 0);
|
||||
assertOrPanic(x == 0);
|
||||
|
||||
x += 1;
|
||||
assert(x == 1);
|
||||
assertOrPanic(x == 1);
|
||||
|
||||
x += 1;
|
||||
assert(x == 2);
|
||||
assertOrPanic(x == 2);
|
||||
|
||||
x += 1;
|
||||
assert(x == 3);
|
||||
assertOrPanic(x == 3);
|
||||
|
||||
var result: @typeOf(x) = 3;
|
||||
assert(@addWithOverflow(@typeOf(x), x, 1, &result));
|
||||
assertOrPanic(@addWithOverflow(@typeOf(x), x, 1, &result));
|
||||
|
||||
assert(result == 0);
|
||||
assertOrPanic(result == 0);
|
||||
}
|
||||
|
||||
test "float equality" {
|
||||
@@ -276,20 +276,20 @@ test "float equality" {
|
||||
|
||||
fn testFloatEqualityImpl(x: f64, y: f64) void {
|
||||
const y2 = x + 1.0;
|
||||
assert(y == y2);
|
||||
assertOrPanic(y == y2);
|
||||
}
|
||||
|
||||
test "allow signed integer division/remainder when values are comptime known and positive or exact" {
|
||||
assert(5 / 3 == 1);
|
||||
assert(-5 / -3 == 1);
|
||||
assert(-6 / 3 == -2);
|
||||
assertOrPanic(5 / 3 == 1);
|
||||
assertOrPanic(-5 / -3 == 1);
|
||||
assertOrPanic(-6 / 3 == -2);
|
||||
|
||||
assert(5 % 3 == 2);
|
||||
assert(-6 % 3 == 0);
|
||||
assertOrPanic(5 % 3 == 2);
|
||||
assertOrPanic(-6 % 3 == 0);
|
||||
}
|
||||
|
||||
test "hex float literal parsing" {
|
||||
comptime assert(0x1.0 == 1.0);
|
||||
comptime assertOrPanic(0x1.0 == 1.0);
|
||||
}
|
||||
|
||||
test "quad hex float literal parsing in range" {
|
||||
@@ -304,7 +304,7 @@ test "quad hex float literal parsing accurate" {
|
||||
|
||||
// implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
|
||||
const expected: u128 = 0x3fff1111222233334444555566667777;
|
||||
assert(@bitCast(u128, a) == expected);
|
||||
assertOrPanic(@bitCast(u128, a) == expected);
|
||||
}
|
||||
|
||||
test "hex float literal within range" {
|
||||
@@ -319,7 +319,7 @@ test "truncating shift left" {
|
||||
}
|
||||
fn testShlTrunc(x: u16) void {
|
||||
const shifted = x << 1;
|
||||
assert(shifted == 65534);
|
||||
assertOrPanic(shifted == 65534);
|
||||
}
|
||||
|
||||
test "truncating shift right" {
|
||||
@@ -328,7 +328,7 @@ test "truncating shift right" {
|
||||
}
|
||||
fn testShrTrunc(x: u16) void {
|
||||
const shifted = x >> 1;
|
||||
assert(shifted == 32767);
|
||||
assertOrPanic(shifted == 32767);
|
||||
}
|
||||
|
||||
test "exact shift left" {
|
||||
@@ -337,7 +337,7 @@ test "exact shift left" {
|
||||
}
|
||||
fn testShlExact(x: u8) void {
|
||||
const shifted = @shlExact(x, 2);
|
||||
assert(shifted == 0b11010100);
|
||||
assertOrPanic(shifted == 0b11010100);
|
||||
}
|
||||
|
||||
test "exact shift right" {
|
||||
@@ -346,22 +346,22 @@ test "exact shift right" {
|
||||
}
|
||||
fn testShrExact(x: u8) void {
|
||||
const shifted = @shrExact(x, 2);
|
||||
assert(shifted == 0b00101101);
|
||||
assertOrPanic(shifted == 0b00101101);
|
||||
}
|
||||
|
||||
test "comptime_int addition" {
|
||||
comptime {
|
||||
assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
|
||||
assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
|
||||
assertOrPanic(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
|
||||
assertOrPanic(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
|
||||
}
|
||||
}
|
||||
|
||||
test "comptime_int multiplication" {
|
||||
comptime {
|
||||
assert(
|
||||
assertOrPanic(
|
||||
45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
|
||||
);
|
||||
assert(
|
||||
assertOrPanic(
|
||||
594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
|
||||
);
|
||||
}
|
||||
@@ -369,7 +369,7 @@ test "comptime_int multiplication" {
|
||||
|
||||
test "comptime_int shifting" {
|
||||
comptime {
|
||||
assert((u128(1) << 127) == 0x80000000000000000000000000000000);
|
||||
assertOrPanic((u128(1) << 127) == 0x80000000000000000000000000000000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,16 +377,16 @@ test "comptime_int multi-limb shift and mask" {
|
||||
comptime {
|
||||
var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
|
||||
|
||||
assert(u32(a & 0xffffffff) == 0xaaaaaaab);
|
||||
assertOrPanic(u32(a & 0xffffffff) == 0xaaaaaaab);
|
||||
a >>= 32;
|
||||
assert(u32(a & 0xffffffff) == 0xeeeeeeef);
|
||||
assertOrPanic(u32(a & 0xffffffff) == 0xeeeeeeef);
|
||||
a >>= 32;
|
||||
assert(u32(a & 0xffffffff) == 0xa0000001);
|
||||
assertOrPanic(u32(a & 0xffffffff) == 0xa0000001);
|
||||
a >>= 32;
|
||||
assert(u32(a & 0xffffffff) == 0xefffffff);
|
||||
assertOrPanic(u32(a & 0xffffffff) == 0xefffffff);
|
||||
a >>= 32;
|
||||
|
||||
assert(a == 0);
|
||||
assertOrPanic(a == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ test "comptime_int multi-limb partial shift right" {
|
||||
comptime {
|
||||
var a = 0x1ffffffffeeeeeeee;
|
||||
a >>= 16;
|
||||
assert(a == 0x1ffffffffeeee);
|
||||
assertOrPanic(a == 0x1ffffffffeeee);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,23 +404,23 @@ test "xor" {
|
||||
}
|
||||
|
||||
fn test_xor() void {
|
||||
assert(0xFF ^ 0x00 == 0xFF);
|
||||
assert(0xF0 ^ 0x0F == 0xFF);
|
||||
assert(0xFF ^ 0xF0 == 0x0F);
|
||||
assert(0xFF ^ 0x0F == 0xF0);
|
||||
assert(0xFF ^ 0xFF == 0x00);
|
||||
assertOrPanic(0xFF ^ 0x00 == 0xFF);
|
||||
assertOrPanic(0xF0 ^ 0x0F == 0xFF);
|
||||
assertOrPanic(0xFF ^ 0xF0 == 0x0F);
|
||||
assertOrPanic(0xFF ^ 0x0F == 0xF0);
|
||||
assertOrPanic(0xFF ^ 0xFF == 0x00);
|
||||
}
|
||||
|
||||
test "comptime_int xor" {
|
||||
comptime {
|
||||
assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||
assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||
assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
|
||||
assert(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
|
||||
assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
|
||||
assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||
assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
|
||||
assert(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
|
||||
assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||
assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||
assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
|
||||
assertOrPanic(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
|
||||
assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
|
||||
assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||
assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
|
||||
assertOrPanic(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,23 +434,23 @@ fn make_f128(x: f128) f128 {
|
||||
}
|
||||
|
||||
fn test_f128() void {
|
||||
assert(@sizeOf(f128) == 16);
|
||||
assert(make_f128(1.0) == 1.0);
|
||||
assert(make_f128(1.0) != 1.1);
|
||||
assert(make_f128(1.0) > 0.9);
|
||||
assert(make_f128(1.0) >= 0.9);
|
||||
assert(make_f128(1.0) >= 1.0);
|
||||
assertOrPanic(@sizeOf(f128) == 16);
|
||||
assertOrPanic(make_f128(1.0) == 1.0);
|
||||
assertOrPanic(make_f128(1.0) != 1.1);
|
||||
assertOrPanic(make_f128(1.0) > 0.9);
|
||||
assertOrPanic(make_f128(1.0) >= 0.9);
|
||||
assertOrPanic(make_f128(1.0) >= 1.0);
|
||||
should_not_be_zero(1.0);
|
||||
}
|
||||
|
||||
fn should_not_be_zero(x: f128) void {
|
||||
assert(x != 0.0);
|
||||
assertOrPanic(x != 0.0);
|
||||
}
|
||||
|
||||
test "comptime float rem int" {
|
||||
comptime {
|
||||
var x = f32(1) % 2;
|
||||
assert(x == 1.0);
|
||||
assertOrPanic(x == 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,8 +465,8 @@ test "remainder division" {
|
||||
}
|
||||
|
||||
fn remdiv(comptime T: type) void {
|
||||
assert(T(1) == T(1) % T(2));
|
||||
assert(T(1) == T(7) % T(3));
|
||||
assertOrPanic(T(1) == T(1) % T(2));
|
||||
assertOrPanic(T(1) == T(7) % T(3));
|
||||
}
|
||||
|
||||
test "@sqrt" {
|
||||
@@ -480,19 +480,19 @@ test "@sqrt" {
|
||||
const x = 14.0;
|
||||
const y = x * x;
|
||||
const z = @sqrt(@typeOf(y), y);
|
||||
comptime assert(z == x);
|
||||
comptime assertOrPanic(z == x);
|
||||
}
|
||||
|
||||
fn testSqrt(comptime T: type, x: T) void {
|
||||
assert(@sqrt(T, x * x) == x);
|
||||
assertOrPanic(@sqrt(T, x * x) == x);
|
||||
}
|
||||
|
||||
test "comptime_int param and return" {
|
||||
const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
|
||||
assert(a == 137114567242441932203689521744947848950);
|
||||
assertOrPanic(a == 137114567242441932203689521744947848950);
|
||||
|
||||
const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
|
||||
assert(b == 985095453608931032642182098849559179469148836107390954364380);
|
||||
assertOrPanic(b == 985095453608931032642182098849559179469148836107390954364380);
|
||||
}
|
||||
|
||||
fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const mem = std.mem;
|
||||
const cstr = std.cstr;
|
||||
const builtin = @import("builtin");
|
||||
@@ -26,38 +26,38 @@ test "call disabled extern fn" {
|
||||
}
|
||||
|
||||
test "@IntType builtin" {
|
||||
assert(@IntType(true, 8) == i8);
|
||||
assert(@IntType(true, 16) == i16);
|
||||
assert(@IntType(true, 32) == i32);
|
||||
assert(@IntType(true, 64) == i64);
|
||||
assertOrPanic(@IntType(true, 8) == i8);
|
||||
assertOrPanic(@IntType(true, 16) == i16);
|
||||
assertOrPanic(@IntType(true, 32) == i32);
|
||||
assertOrPanic(@IntType(true, 64) == i64);
|
||||
|
||||
assert(@IntType(false, 8) == u8);
|
||||
assert(@IntType(false, 16) == u16);
|
||||
assert(@IntType(false, 32) == u32);
|
||||
assert(@IntType(false, 64) == u64);
|
||||
assertOrPanic(@IntType(false, 8) == u8);
|
||||
assertOrPanic(@IntType(false, 16) == u16);
|
||||
assertOrPanic(@IntType(false, 32) == u32);
|
||||
assertOrPanic(@IntType(false, 64) == u64);
|
||||
|
||||
assert(i8.bit_count == 8);
|
||||
assert(i16.bit_count == 16);
|
||||
assert(i32.bit_count == 32);
|
||||
assert(i64.bit_count == 64);
|
||||
assertOrPanic(i8.bit_count == 8);
|
||||
assertOrPanic(i16.bit_count == 16);
|
||||
assertOrPanic(i32.bit_count == 32);
|
||||
assertOrPanic(i64.bit_count == 64);
|
||||
|
||||
assert(i8.is_signed);
|
||||
assert(i16.is_signed);
|
||||
assert(i32.is_signed);
|
||||
assert(i64.is_signed);
|
||||
assert(isize.is_signed);
|
||||
assertOrPanic(i8.is_signed);
|
||||
assertOrPanic(i16.is_signed);
|
||||
assertOrPanic(i32.is_signed);
|
||||
assertOrPanic(i64.is_signed);
|
||||
assertOrPanic(isize.is_signed);
|
||||
|
||||
assert(!u8.is_signed);
|
||||
assert(!u16.is_signed);
|
||||
assert(!u32.is_signed);
|
||||
assert(!u64.is_signed);
|
||||
assert(!usize.is_signed);
|
||||
assertOrPanic(!u8.is_signed);
|
||||
assertOrPanic(!u16.is_signed);
|
||||
assertOrPanic(!u32.is_signed);
|
||||
assertOrPanic(!u64.is_signed);
|
||||
assertOrPanic(!usize.is_signed);
|
||||
}
|
||||
|
||||
test "floating point primitive bit counts" {
|
||||
assert(f16.bit_count == 16);
|
||||
assert(f32.bit_count == 32);
|
||||
assert(f64.bit_count == 64);
|
||||
assertOrPanic(f16.bit_count == 16);
|
||||
assertOrPanic(f32.bit_count == 32);
|
||||
assertOrPanic(f64.bit_count == 64);
|
||||
}
|
||||
|
||||
test "short circuit" {
|
||||
@@ -72,7 +72,7 @@ fn testShortCircuit(f: bool, t: bool) void {
|
||||
var hit_4 = f;
|
||||
|
||||
if (t or x: {
|
||||
assert(f);
|
||||
assertOrPanic(f);
|
||||
break :x f;
|
||||
}) {
|
||||
hit_1 = t;
|
||||
@@ -81,31 +81,31 @@ fn testShortCircuit(f: bool, t: bool) void {
|
||||
hit_2 = t;
|
||||
break :x f;
|
||||
}) {
|
||||
assert(f);
|
||||
assertOrPanic(f);
|
||||
}
|
||||
|
||||
if (t and x: {
|
||||
hit_3 = t;
|
||||
break :x f;
|
||||
}) {
|
||||
assert(f);
|
||||
assertOrPanic(f);
|
||||
}
|
||||
if (f and x: {
|
||||
assert(f);
|
||||
assertOrPanic(f);
|
||||
break :x f;
|
||||
}) {
|
||||
assert(f);
|
||||
assertOrPanic(f);
|
||||
} else {
|
||||
hit_4 = t;
|
||||
}
|
||||
assert(hit_1);
|
||||
assert(hit_2);
|
||||
assert(hit_3);
|
||||
assert(hit_4);
|
||||
assertOrPanic(hit_1);
|
||||
assertOrPanic(hit_2);
|
||||
assertOrPanic(hit_3);
|
||||
assertOrPanic(hit_4);
|
||||
}
|
||||
|
||||
test "truncate" {
|
||||
assert(testTruncate(0x10fd) == 0xfd);
|
||||
assertOrPanic(testTruncate(0x10fd) == 0xfd);
|
||||
}
|
||||
fn testTruncate(x: u32) u8 {
|
||||
return @truncate(u8, x);
|
||||
@@ -116,16 +116,16 @@ fn first4KeysOfHomeRow() []const u8 {
|
||||
}
|
||||
|
||||
test "return string from function" {
|
||||
assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
|
||||
assertOrPanic(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
|
||||
}
|
||||
|
||||
const g1: i32 = 1233 + 1;
|
||||
var g2: i32 = 0;
|
||||
|
||||
test "global variables" {
|
||||
assert(g2 == 0);
|
||||
assertOrPanic(g2 == 0);
|
||||
g2 = g1;
|
||||
assert(g2 == 1234);
|
||||
assertOrPanic(g2 == 1234);
|
||||
}
|
||||
|
||||
test "memcpy and memset intrinsics" {
|
||||
@@ -142,7 +142,7 @@ test "builtin static eval" {
|
||||
const x: i32 = comptime x: {
|
||||
break :x 1 + 2 + 3;
|
||||
};
|
||||
assert(x == comptime 6);
|
||||
assertOrPanic(x == comptime 6);
|
||||
}
|
||||
|
||||
test "slicing" {
|
||||
@@ -163,7 +163,7 @@ test "slicing" {
|
||||
|
||||
test "constant equal function pointers" {
|
||||
const alias = emptyFn;
|
||||
assert(comptime x: {
|
||||
assertOrPanic(comptime x: {
|
||||
break :x emptyFn == alias;
|
||||
});
|
||||
}
|
||||
@@ -171,25 +171,25 @@ test "constant equal function pointers" {
|
||||
fn emptyFn() void {}
|
||||
|
||||
test "hex escape" {
|
||||
assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
|
||||
assertOrPanic(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
|
||||
}
|
||||
|
||||
test "string concatenation" {
|
||||
assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
|
||||
assertOrPanic(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
|
||||
}
|
||||
|
||||
test "array mult operator" {
|
||||
assert(mem.eql(u8, "ab" ** 5, "ababababab"));
|
||||
assertOrPanic(mem.eql(u8, "ab" ** 5, "ababababab"));
|
||||
}
|
||||
|
||||
test "string escapes" {
|
||||
assert(mem.eql(u8, "\"", "\x22"));
|
||||
assert(mem.eql(u8, "\'", "\x27"));
|
||||
assert(mem.eql(u8, "\n", "\x0a"));
|
||||
assert(mem.eql(u8, "\r", "\x0d"));
|
||||
assert(mem.eql(u8, "\t", "\x09"));
|
||||
assert(mem.eql(u8, "\\", "\x5c"));
|
||||
assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
|
||||
assertOrPanic(mem.eql(u8, "\"", "\x22"));
|
||||
assertOrPanic(mem.eql(u8, "\'", "\x27"));
|
||||
assertOrPanic(mem.eql(u8, "\n", "\x0a"));
|
||||
assertOrPanic(mem.eql(u8, "\r", "\x0d"));
|
||||
assertOrPanic(mem.eql(u8, "\t", "\x09"));
|
||||
assertOrPanic(mem.eql(u8, "\\", "\x5c"));
|
||||
assertOrPanic(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
|
||||
}
|
||||
|
||||
test "multiline string" {
|
||||
@@ -199,7 +199,7 @@ test "multiline string" {
|
||||
\\three
|
||||
;
|
||||
const s2 = "one\ntwo)\nthree";
|
||||
assert(mem.eql(u8, s1, s2));
|
||||
assertOrPanic(mem.eql(u8, s1, s2));
|
||||
}
|
||||
|
||||
test "multiline C string" {
|
||||
@@ -209,11 +209,11 @@ test "multiline C string" {
|
||||
c\\three
|
||||
;
|
||||
const s2 = c"one\ntwo)\nthree";
|
||||
assert(cstr.cmp(s1, s2) == 0);
|
||||
assertOrPanic(cstr.cmp(s1, s2) == 0);
|
||||
}
|
||||
|
||||
test "type equality" {
|
||||
assert(*const u8 != *u8);
|
||||
assertOrPanic(*const u8 != *u8);
|
||||
}
|
||||
|
||||
const global_a: i32 = 1234;
|
||||
@@ -221,7 +221,7 @@ 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);
|
||||
assertOrPanic(d.* == 1234);
|
||||
}
|
||||
|
||||
test "explicit cast maybe pointers" {
|
||||
@@ -247,8 +247,8 @@ 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));
|
||||
assertOrPanic(castSmallUnsignedToLargerSigned1(200) == i16(200));
|
||||
assertOrPanic(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
|
||||
}
|
||||
fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
|
||||
return x;
|
||||
@@ -258,7 +258,7 @@ fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
|
||||
}
|
||||
|
||||
test "implicit cast after unreachable" {
|
||||
assert(outer() == 1234);
|
||||
assertOrPanic(outer() == 1234);
|
||||
}
|
||||
fn inner() i32 {
|
||||
return 1234;
|
||||
@@ -273,13 +273,13 @@ test "pointer dereferencing" {
|
||||
|
||||
y.* += 1;
|
||||
|
||||
assert(x == 4);
|
||||
assert(y.* == 4);
|
||||
assertOrPanic(x == 4);
|
||||
assertOrPanic(y.* == 4);
|
||||
}
|
||||
|
||||
test "call result of if else expression" {
|
||||
assert(mem.eql(u8, f2(true), "a"));
|
||||
assert(mem.eql(u8, f2(false), "b"));
|
||||
assertOrPanic(mem.eql(u8, f2(true), "a"));
|
||||
assertOrPanic(mem.eql(u8, f2(false), "b"));
|
||||
}
|
||||
fn f2(x: bool) []const u8 {
|
||||
return (if (x) fA else fB)();
|
||||
@@ -321,8 +321,8 @@ const test3_bar = Test3Foo{ .Two = 13 };
|
||||
fn test3_1(f: Test3Foo) void {
|
||||
switch (f) {
|
||||
Test3Foo.Three => |pt| {
|
||||
assert(pt.x == 3);
|
||||
assert(pt.y == 4);
|
||||
assertOrPanic(pt.x == 3);
|
||||
assertOrPanic(pt.y == 4);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
@@ -330,14 +330,14 @@ fn test3_1(f: Test3Foo) void {
|
||||
fn test3_2(f: Test3Foo) void {
|
||||
switch (f) {
|
||||
Test3Foo.Two => |x| {
|
||||
assert(x == 13);
|
||||
assertOrPanic(x == 13);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
test "character literals" {
|
||||
assert('\'' == single_quote);
|
||||
assertOrPanic('\'' == single_quote);
|
||||
}
|
||||
const single_quote = '\'';
|
||||
|
||||
@@ -346,13 +346,13 @@ test "take address of parameter" {
|
||||
}
|
||||
fn testTakeAddressOfParameter(f: f32) void {
|
||||
const f_ptr = &f;
|
||||
assert(f_ptr.* == 12.34);
|
||||
assertOrPanic(f_ptr.* == 12.34);
|
||||
}
|
||||
|
||||
test "pointer comparison" {
|
||||
const a = ([]const u8)("a");
|
||||
const b = &a;
|
||||
assert(ptrEql(b, b));
|
||||
assertOrPanic(ptrEql(b, b));
|
||||
}
|
||||
fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
|
||||
return a == b;
|
||||
@@ -367,36 +367,31 @@ test "C string concatenation" {
|
||||
{
|
||||
var i: u32 = 0;
|
||||
while (i < len_with_null) : (i += 1) {
|
||||
assert(a[i] == b[i]);
|
||||
assertOrPanic(a[i] == b[i]);
|
||||
}
|
||||
}
|
||||
assert(a[len] == 0);
|
||||
assert(b[len] == 0);
|
||||
assertOrPanic(a[len] == 0);
|
||||
assertOrPanic(b[len] == 0);
|
||||
}
|
||||
|
||||
test "cast slice to u8 slice" {
|
||||
assert(@sizeOf(i32) == 4);
|
||||
var big_thing_array = []i32{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
};
|
||||
assertOrPanic(@sizeOf(i32) == 4);
|
||||
var big_thing_array = []i32{ 1, 2, 3, 4 };
|
||||
const big_thing_slice: []i32 = big_thing_array[0..];
|
||||
const bytes = @sliceToBytes(big_thing_slice);
|
||||
assert(bytes.len == 4 * 4);
|
||||
assertOrPanic(bytes.len == 4 * 4);
|
||||
bytes[4] = 0;
|
||||
bytes[5] = 0;
|
||||
bytes[6] = 0;
|
||||
bytes[7] = 0;
|
||||
assert(big_thing_slice[1] == 0);
|
||||
assertOrPanic(big_thing_slice[1] == 0);
|
||||
const big_thing_again = @bytesToSlice(i32, bytes);
|
||||
assert(big_thing_again[2] == 3);
|
||||
assertOrPanic(big_thing_again[2] == 3);
|
||||
big_thing_again[2] = -1;
|
||||
assert(bytes[8] == maxInt(u8));
|
||||
assert(bytes[9] == maxInt(u8));
|
||||
assert(bytes[10] == maxInt(u8));
|
||||
assert(bytes[11] == maxInt(u8));
|
||||
assertOrPanic(bytes[8] == maxInt(u8));
|
||||
assertOrPanic(bytes[9] == maxInt(u8));
|
||||
assertOrPanic(bytes[10] == maxInt(u8));
|
||||
assertOrPanic(bytes[11] == maxInt(u8));
|
||||
}
|
||||
|
||||
test "pointer to void return type" {
|
||||
@@ -413,7 +408,7 @@ fn testPointerToVoidReturnType2() *const void {
|
||||
|
||||
test "non const ptr to aliased type" {
|
||||
const int = i32;
|
||||
assert(?*int == ?*i32);
|
||||
assertOrPanic(?*int == ?*i32);
|
||||
}
|
||||
|
||||
test "array 2D const double ptr" {
|
||||
@@ -426,8 +421,8 @@ test "array 2D const double ptr" {
|
||||
|
||||
fn testArray2DConstDoublePtr(ptr: *const f32) void {
|
||||
const ptr2 = @ptrCast([*]const f32, ptr);
|
||||
assert(ptr2[0] == 1.0);
|
||||
assert(ptr2[1] == 2.0);
|
||||
assertOrPanic(ptr2[0] == 1.0);
|
||||
assertOrPanic(ptr2[1] == 2.0);
|
||||
}
|
||||
|
||||
const Tid = builtin.TypeId;
|
||||
@@ -449,32 +444,32 @@ const AUnion = union {
|
||||
|
||||
test "@typeId" {
|
||||
comptime {
|
||||
assert(@typeId(type) == Tid.Type);
|
||||
assert(@typeId(void) == Tid.Void);
|
||||
assert(@typeId(bool) == Tid.Bool);
|
||||
assert(@typeId(noreturn) == Tid.NoReturn);
|
||||
assert(@typeId(i8) == Tid.Int);
|
||||
assert(@typeId(u8) == Tid.Int);
|
||||
assert(@typeId(i64) == Tid.Int);
|
||||
assert(@typeId(u64) == Tid.Int);
|
||||
assert(@typeId(f32) == Tid.Float);
|
||||
assert(@typeId(f64) == Tid.Float);
|
||||
assert(@typeId(*f32) == Tid.Pointer);
|
||||
assert(@typeId([2]u8) == Tid.Array);
|
||||
assert(@typeId(AStruct) == Tid.Struct);
|
||||
assert(@typeId(@typeOf(1)) == Tid.ComptimeInt);
|
||||
assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
|
||||
assert(@typeId(@typeOf(undefined)) == Tid.Undefined);
|
||||
assert(@typeId(@typeOf(null)) == Tid.Null);
|
||||
assert(@typeId(?i32) == Tid.Optional);
|
||||
assert(@typeId(anyerror!i32) == Tid.ErrorUnion);
|
||||
assert(@typeId(anyerror) == Tid.ErrorSet);
|
||||
assert(@typeId(AnEnum) == Tid.Enum);
|
||||
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(@typeOf(builtin)) == Tid.Namespace);
|
||||
assertOrPanic(@typeId(type) == Tid.Type);
|
||||
assertOrPanic(@typeId(void) == Tid.Void);
|
||||
assertOrPanic(@typeId(bool) == Tid.Bool);
|
||||
assertOrPanic(@typeId(noreturn) == Tid.NoReturn);
|
||||
assertOrPanic(@typeId(i8) == Tid.Int);
|
||||
assertOrPanic(@typeId(u8) == Tid.Int);
|
||||
assertOrPanic(@typeId(i64) == Tid.Int);
|
||||
assertOrPanic(@typeId(u64) == Tid.Int);
|
||||
assertOrPanic(@typeId(f32) == Tid.Float);
|
||||
assertOrPanic(@typeId(f64) == Tid.Float);
|
||||
assertOrPanic(@typeId(*f32) == Tid.Pointer);
|
||||
assertOrPanic(@typeId([2]u8) == Tid.Array);
|
||||
assertOrPanic(@typeId(AStruct) == Tid.Struct);
|
||||
assertOrPanic(@typeId(@typeOf(1)) == Tid.ComptimeInt);
|
||||
assertOrPanic(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
|
||||
assertOrPanic(@typeId(@typeOf(undefined)) == Tid.Undefined);
|
||||
assertOrPanic(@typeId(@typeOf(null)) == Tid.Null);
|
||||
assertOrPanic(@typeId(?i32) == Tid.Optional);
|
||||
assertOrPanic(@typeId(anyerror!i32) == Tid.ErrorUnion);
|
||||
assertOrPanic(@typeId(anyerror) == Tid.ErrorSet);
|
||||
assertOrPanic(@typeId(AnEnum) == Tid.Enum);
|
||||
assertOrPanic(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
|
||||
assertOrPanic(@typeId(AUnionEnum) == Tid.Union);
|
||||
assertOrPanic(@typeId(AUnion) == Tid.Union);
|
||||
assertOrPanic(@typeId(fn () void) == Tid.Fn);
|
||||
assertOrPanic(@typeId(@typeOf(builtin)) == Tid.Namespace);
|
||||
// TODO bound fn
|
||||
// TODO arg tuple
|
||||
// TODO opaque
|
||||
@@ -490,13 +485,13 @@ test "@typeName" {
|
||||
Unused,
|
||||
};
|
||||
comptime {
|
||||
assert(mem.eql(u8, @typeName(i64), "i64"));
|
||||
assert(mem.eql(u8, @typeName(*usize), "*usize"));
|
||||
assertOrPanic(mem.eql(u8, @typeName(i64), "i64"));
|
||||
assertOrPanic(mem.eql(u8, @typeName(*usize), "*usize"));
|
||||
// https://github.com/ziglang/zig/issues/675
|
||||
assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
|
||||
assert(mem.eql(u8, @typeName(Struct), "Struct"));
|
||||
assert(mem.eql(u8, @typeName(Union), "Union"));
|
||||
assert(mem.eql(u8, @typeName(Enum), "Enum"));
|
||||
assertOrPanic(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
|
||||
assertOrPanic(mem.eql(u8, @typeName(Struct), "Struct"));
|
||||
assertOrPanic(mem.eql(u8, @typeName(Union), "Union"));
|
||||
assertOrPanic(mem.eql(u8, @typeName(Enum), "Enum"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,28 +499,16 @@ fn TypeFromFn(comptime T: type) type {
|
||||
return struct {};
|
||||
}
|
||||
|
||||
test "volatile load and store" {
|
||||
var number: i32 = 1234;
|
||||
const ptr = (*volatile i32)(&number);
|
||||
ptr.* += 1;
|
||||
assert(ptr.* == 1235);
|
||||
test "double implicit cast in same expression" {
|
||||
var x = i32(u16(nine()));
|
||||
assertOrPanic(x == 9);
|
||||
}
|
||||
|
||||
test "slice string literal has type []const u8" {
|
||||
comptime {
|
||||
assert(@typeOf("aoeu"[0..]) == []const u8);
|
||||
const array = []i32{
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
};
|
||||
assert(@typeOf(array[0..]) == []const i32);
|
||||
}
|
||||
fn nine() u8 {
|
||||
return 9;
|
||||
}
|
||||
|
||||
test "global variable initialized to global variable array element" {
|
||||
assert(global_ptr == &gdt[0]);
|
||||
assertOrPanic(global_ptr == &gdt[0]);
|
||||
}
|
||||
const GDTEntry = struct {
|
||||
field: i32,
|
||||
@@ -543,16 +526,12 @@ export fn writeToVRam() void {
|
||||
vram[0] = 'X';
|
||||
}
|
||||
|
||||
test "pointer child field" {
|
||||
assert((*u32).Child == u32);
|
||||
}
|
||||
|
||||
const OpaqueA = @OpaqueType();
|
||||
const OpaqueB = @OpaqueType();
|
||||
test "@OpaqueType" {
|
||||
assert(*OpaqueA != *OpaqueB);
|
||||
assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
|
||||
assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
|
||||
assertOrPanic(*OpaqueA != *OpaqueB);
|
||||
assertOrPanic(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
|
||||
assertOrPanic(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
|
||||
}
|
||||
|
||||
test "variable is allowed to be a pointer to an opaque type" {
|
||||
@@ -581,25 +560,6 @@ test "implicit comptime while" {
|
||||
}
|
||||
}
|
||||
|
||||
test "struct inside function" {
|
||||
testStructInFn();
|
||||
comptime testStructInFn();
|
||||
}
|
||||
|
||||
fn testStructInFn() void {
|
||||
const BlockKind = u32;
|
||||
|
||||
const Block = struct {
|
||||
kind: BlockKind,
|
||||
};
|
||||
|
||||
var block = Block{ .kind = 1234 };
|
||||
|
||||
block.kind += 1;
|
||||
|
||||
assert(block.kind == 1235);
|
||||
}
|
||||
|
||||
fn fnThatClosesOverLocalConst() type {
|
||||
const c = 1;
|
||||
return struct {
|
||||
@@ -611,7 +571,7 @@ fn fnThatClosesOverLocalConst() type {
|
||||
|
||||
test "function closes over local const" {
|
||||
const x = fnThatClosesOverLocalConst().g();
|
||||
assert(x == 1);
|
||||
assertOrPanic(x == 1);
|
||||
}
|
||||
|
||||
test "cold function" {
|
||||
@@ -648,21 +608,21 @@ export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: Pack
|
||||
test "slicing zero length array" {
|
||||
const s1 = ""[0..];
|
||||
const s2 = ([]u32{})[0..];
|
||||
assert(s1.len == 0);
|
||||
assert(s2.len == 0);
|
||||
assert(mem.eql(u8, s1, ""));
|
||||
assert(mem.eql(u32, s2, []u32{}));
|
||||
assertOrPanic(s1.len == 0);
|
||||
assertOrPanic(s2.len == 0);
|
||||
assertOrPanic(mem.eql(u8, s1, ""));
|
||||
assertOrPanic(mem.eql(u32, s2, []u32{}));
|
||||
}
|
||||
|
||||
const addr1 = @ptrCast(*const u8, emptyFn);
|
||||
test "comptime cast fn to ptr" {
|
||||
const addr2 = @ptrCast(*const u8, emptyFn);
|
||||
comptime assert(addr1 == addr2);
|
||||
comptime assertOrPanic(addr1 == addr2);
|
||||
}
|
||||
|
||||
test "equality compare fn ptrs" {
|
||||
var a = emptyFn;
|
||||
assert(a == a);
|
||||
assertOrPanic(a == a);
|
||||
}
|
||||
|
||||
test "self reference through fn ptr field" {
|
||||
@@ -677,5 +637,51 @@ test "self reference through fn ptr field" {
|
||||
};
|
||||
var a: S.A = undefined;
|
||||
a.f = S.foo;
|
||||
assert(a.f(a) == 12);
|
||||
assertOrPanic(a.f(a) == 12);
|
||||
}
|
||||
|
||||
test "volatile load and store" {
|
||||
var number: i32 = 1234;
|
||||
const ptr = (*volatile i32)(&number);
|
||||
ptr.* += 1;
|
||||
assertOrPanic(ptr.* == 1235);
|
||||
}
|
||||
|
||||
test "slice string literal has type []const u8" {
|
||||
comptime {
|
||||
assertOrPanic(@typeOf("aoeu"[0..]) == []const u8);
|
||||
const array = []i32{ 1, 2, 3, 4 };
|
||||
assertOrPanic(@typeOf(array[0..]) == []const i32);
|
||||
}
|
||||
}
|
||||
|
||||
test "pointer child field" {
|
||||
assertOrPanic((*u32).Child == u32);
|
||||
}
|
||||
|
||||
test "struct inside function" {
|
||||
testStructInFn();
|
||||
comptime testStructInFn();
|
||||
}
|
||||
|
||||
fn testStructInFn() void {
|
||||
const BlockKind = u32;
|
||||
|
||||
const Block = struct {
|
||||
kind: BlockKind,
|
||||
};
|
||||
|
||||
var block = Block{ .kind = 1234 };
|
||||
|
||||
block.kind += 1;
|
||||
|
||||
assertOrPanic(block.kind == 1235);
|
||||
}
|
||||
|
||||
test "fn call returning scalar optional in equality expression" {
|
||||
assertOrPanic(getNull() == null);
|
||||
}
|
||||
|
||||
fn getNull() ?*i32 {
|
||||
return null;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
const builtin = @import("builtin");
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "namespace depends on compile var" {
|
||||
if (some_namespace.a_bool) {
|
||||
assert(some_namespace.a_bool);
|
||||
assertOrPanic(some_namespace.a_bool);
|
||||
} else {
|
||||
assert(!some_namespace.a_bool);
|
||||
assertOrPanic(!some_namespace.a_bool);
|
||||
}
|
||||
}
|
||||
const some_namespace = switch (builtin.os) {
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
var new_stack_bytes: [1024]u8 = undefined;
|
||||
|
||||
@@ -10,17 +10,17 @@ test "calling a function with a new stack" {
|
||||
const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
|
||||
_ = targetFunction(arg);
|
||||
|
||||
assert(arg == 1234);
|
||||
assert(a < b);
|
||||
assertOrPanic(arg == 1234);
|
||||
assertOrPanic(a < b);
|
||||
}
|
||||
|
||||
fn targetFunction(x: i32) usize {
|
||||
assert(x == 1234);
|
||||
assertOrPanic(x == 1234);
|
||||
|
||||
var local_variable: i32 = 42;
|
||||
const ptr = &local_variable;
|
||||
ptr.* += 1;
|
||||
|
||||
assert(local_variable == 43);
|
||||
assertOrPanic(local_variable == 43);
|
||||
return @ptrToInt(ptr);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "optional type" {
|
||||
const x: ?bool = true;
|
||||
@@ -17,13 +17,13 @@ test "optional type" {
|
||||
|
||||
const z = next_x orelse 1234;
|
||||
|
||||
assert(z == 1234);
|
||||
assertOrPanic(z == 1234);
|
||||
|
||||
const final_x: ?i32 = 13;
|
||||
|
||||
const num = final_x orelse unreachable;
|
||||
|
||||
assert(num == 13);
|
||||
assertOrPanic(num == 13);
|
||||
}
|
||||
|
||||
test "test maybe object and get a pointer to the inner value" {
|
||||
@@ -33,7 +33,7 @@ test "test maybe object and get a pointer to the inner value" {
|
||||
b.* = false;
|
||||
}
|
||||
|
||||
assert(maybe_bool.? == false);
|
||||
assertOrPanic(maybe_bool.? == false);
|
||||
}
|
||||
|
||||
test "rhs maybe unwrap return" {
|
||||
@@ -47,9 +47,9 @@ test "maybe return" {
|
||||
}
|
||||
|
||||
fn maybeReturnImpl() void {
|
||||
assert(foo(1235).?);
|
||||
assertOrPanic(foo(1235).?);
|
||||
if (foo(null) != null) unreachable;
|
||||
assert(!foo(1234).?);
|
||||
assertOrPanic(!foo(1234).?);
|
||||
}
|
||||
|
||||
fn foo(x: ?i32) ?bool {
|
||||
@@ -58,7 +58,7 @@ fn foo(x: ?i32) ?bool {
|
||||
}
|
||||
|
||||
test "if var maybe pointer" {
|
||||
assert(shouldBeAPlus1(Particle{
|
||||
assertOrPanic(shouldBeAPlus1(Particle{
|
||||
.a = 14,
|
||||
.b = 1,
|
||||
.c = 1,
|
||||
@@ -84,10 +84,10 @@ const Particle = struct {
|
||||
|
||||
test "null literal outside function" {
|
||||
const is_null = here_is_a_null_literal.context == null;
|
||||
assert(is_null);
|
||||
assertOrPanic(is_null);
|
||||
|
||||
const is_non_null = here_is_a_null_literal.context != null;
|
||||
assert(!is_non_null);
|
||||
assertOrPanic(!is_non_null);
|
||||
}
|
||||
const SillyStruct = struct {
|
||||
context: ?i32,
|
||||
@@ -98,8 +98,8 @@ test "test null runtime" {
|
||||
testTestNullRuntime(null);
|
||||
}
|
||||
fn testTestNullRuntime(x: ?i32) void {
|
||||
assert(x == null);
|
||||
assert(!(x != null));
|
||||
assertOrPanic(x == null);
|
||||
assertOrPanic(!(x != null));
|
||||
}
|
||||
|
||||
test "optional void" {
|
||||
@@ -108,8 +108,8 @@ test "optional void" {
|
||||
}
|
||||
|
||||
fn optionalVoidImpl() void {
|
||||
assert(bar(null) == null);
|
||||
assert(bar({}) != null);
|
||||
assertOrPanic(bar(null) == null);
|
||||
assertOrPanic(bar({}) != null);
|
||||
}
|
||||
|
||||
fn bar(x: ?void) ?void {
|
||||
@@ -133,7 +133,7 @@ test "unwrap optional which is field of global var" {
|
||||
}
|
||||
struct_with_optional.field = 1234;
|
||||
if (struct_with_optional.field) |payload| {
|
||||
assert(payload == 1234);
|
||||
assertOrPanic(payload == 1234);
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
@@ -141,13 +141,13 @@ test "unwrap optional which is field of global var" {
|
||||
|
||||
test "null with default unwrap" {
|
||||
const x: i32 = null orelse 1;
|
||||
assert(x == 1);
|
||||
assertOrPanic(x == 1);
|
||||
}
|
||||
|
||||
test "optional types" {
|
||||
comptime {
|
||||
const opt_type_struct = StructWithOptionalType{ .t = u8 };
|
||||
assert(opt_type_struct.t != null and opt_type_struct.t.? == u8);
|
||||
assertOrPanic(opt_type_struct.t != null and opt_type_struct.t.? == u8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,5 +158,5 @@ const StructWithOptionalType = struct {
|
||||
test "optional pointer to 0 bit type null value at runtime" {
|
||||
const EmptyStruct = struct {};
|
||||
var x: ?*EmptyStruct = null;
|
||||
assert(x == null);
|
||||
assertOrPanic(x == null);
|
||||
}
|
||||
81
test/stage1/behavior/optional.zig
Normal file
81
test/stage1/behavior/optional.zig
Normal file
@@ -0,0 +1,81 @@
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
pub const EmptyStruct = struct {};
|
||||
|
||||
test "optional pointer to size zero struct" {
|
||||
var e = EmptyStruct{};
|
||||
var o: ?*EmptyStruct = &e;
|
||||
assertOrPanic(o != null);
|
||||
}
|
||||
|
||||
test "equality compare nullable pointers" {
|
||||
testNullPtrsEql();
|
||||
comptime testNullPtrsEql();
|
||||
}
|
||||
|
||||
fn testNullPtrsEql() void {
|
||||
var number: i32 = 1234;
|
||||
|
||||
var x: ?*i32 = null;
|
||||
var y: ?*i32 = null;
|
||||
assertOrPanic(x == y);
|
||||
y = &number;
|
||||
assertOrPanic(x != y);
|
||||
assertOrPanic(x != &number);
|
||||
assertOrPanic(&number != x);
|
||||
x = &number;
|
||||
assertOrPanic(x == y);
|
||||
assertOrPanic(x == &number);
|
||||
assertOrPanic(&number == x);
|
||||
}
|
||||
|
||||
test "address of unwrap optional" {
|
||||
const S = struct {
|
||||
const Foo = struct {
|
||||
a: i32,
|
||||
};
|
||||
|
||||
var global: ?Foo = null;
|
||||
|
||||
pub fn getFoo() anyerror!*Foo {
|
||||
return &global.?;
|
||||
}
|
||||
};
|
||||
S.global = S.Foo{ .a = 1234 };
|
||||
const foo = S.getFoo() catch unreachable;
|
||||
assertOrPanic(foo.a == 1234);
|
||||
}
|
||||
|
||||
test "passing an optional integer as a parameter" {
|
||||
const S = struct {
|
||||
fn entry() bool {
|
||||
var x: i32 = 1234;
|
||||
return foo(x);
|
||||
}
|
||||
|
||||
fn foo(x: ?i32) bool {
|
||||
return x.? == 1234;
|
||||
}
|
||||
};
|
||||
assertOrPanic(S.entry());
|
||||
comptime assertOrPanic(S.entry());
|
||||
}
|
||||
|
||||
test "unwrap function call with optional pointer return value" {
|
||||
const S = struct {
|
||||
fn entry() void {
|
||||
assertOrPanic(foo().?.* == 1234);
|
||||
assertOrPanic(bar() == null);
|
||||
}
|
||||
const global: i32 = 1234;
|
||||
fn foo() ?*const i32 {
|
||||
return &global;
|
||||
}
|
||||
fn bar() ?*i32 {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
S.entry();
|
||||
// TODO https://github.com/ziglang/zig/issues/1901
|
||||
//comptime S.entry();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
test "dereference pointer" {
|
||||
comptime testDerefPtr();
|
||||
@@ -10,33 +10,33 @@ fn testDerefPtr() void {
|
||||
var x: i32 = 1234;
|
||||
var y = &x;
|
||||
y.* += 1;
|
||||
assert(x == 1235);
|
||||
assertOrPanic(x == 1235);
|
||||
}
|
||||
|
||||
test "pointer arithmetic" {
|
||||
var ptr = c"abcd";
|
||||
|
||||
assert(ptr[0] == 'a');
|
||||
assertOrPanic(ptr[0] == 'a');
|
||||
ptr += 1;
|
||||
assert(ptr[0] == 'b');
|
||||
assertOrPanic(ptr[0] == 'b');
|
||||
ptr += 1;
|
||||
assert(ptr[0] == 'c');
|
||||
assertOrPanic(ptr[0] == 'c');
|
||||
ptr += 1;
|
||||
assert(ptr[0] == 'd');
|
||||
assertOrPanic(ptr[0] == 'd');
|
||||
ptr += 1;
|
||||
assert(ptr[0] == 0);
|
||||
assertOrPanic(ptr[0] == 0);
|
||||
ptr -= 1;
|
||||
assert(ptr[0] == 'd');
|
||||
assertOrPanic(ptr[0] == 'd');
|
||||
ptr -= 1;
|
||||
assert(ptr[0] == 'c');
|
||||
assertOrPanic(ptr[0] == 'c');
|
||||
ptr -= 1;
|
||||
assert(ptr[0] == 'b');
|
||||
assertOrPanic(ptr[0] == 'b');
|
||||
ptr -= 1;
|
||||
assert(ptr[0] == 'a');
|
||||
assertOrPanic(ptr[0] == 'a');
|
||||
}
|
||||
|
||||
test "double pointer parsing" {
|
||||
comptime assert(PtrOf(PtrOf(i32)) == **i32);
|
||||
comptime assertOrPanic(PtrOf(PtrOf(i32)) == **i32);
|
||||
}
|
||||
|
||||
fn PtrOf(comptime T: type) type {
|
||||
25
test/stage1/behavior/popcount.zig
Normal file
25
test/stage1/behavior/popcount.zig
Normal file
@@ -0,0 +1,25 @@
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "@popCount" {
|
||||
comptime testPopCount();
|
||||
testPopCount();
|
||||
}
|
||||
|
||||
fn testPopCount() void {
|
||||
{
|
||||
var x: u32 = 0xaa;
|
||||
assertOrPanic(@popCount(x) == 4);
|
||||
}
|
||||
{
|
||||
var x: u32 = 0xaaaaaaaa;
|
||||
assertOrPanic(@popCount(x) == 16);
|
||||
}
|
||||
{
|
||||
var x: i16 = -1;
|
||||
assertOrPanic(@popCount(x) == 16);
|
||||
}
|
||||
comptime {
|
||||
assertOrPanic(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
const other = @import("other.zig");
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "pub enum" {
|
||||
pubEnumTest(other.APubEnum.Two);
|
||||
}
|
||||
fn pubEnumTest(foo: other.APubEnum) void {
|
||||
assert(foo == other.APubEnum.Two);
|
||||
assertOrPanic(foo == other.APubEnum.Two);
|
||||
}
|
||||
|
||||
test "cast with imported symbol" {
|
||||
assert(other.size_t(42) == 42);
|
||||
assertOrPanic(other.size_t(42) == 42);
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
var ok: bool = false;
|
||||
test "reference a variable in an if after an if in the 2nd switch prong" {
|
||||
foo(true, Num.Two, false, "aoeu");
|
||||
assert(!ok);
|
||||
assertOrPanic(!ok);
|
||||
foo(false, Num.One, false, "aoeu");
|
||||
assert(!ok);
|
||||
assertOrPanic(!ok);
|
||||
foo(true, Num.One, false, "aoeu");
|
||||
assert(ok);
|
||||
assertOrPanic(ok);
|
||||
}
|
||||
|
||||
const Num = enum {
|
||||
@@ -32,6 +32,6 @@ fn foo(c: bool, k: Num, c2: bool, b: []const u8) void {
|
||||
}
|
||||
|
||||
fn a(x: []const u8) void {
|
||||
assert(mem.eql(u8, x, "aoeu"));
|
||||
assertOrPanic(mem.eql(u8, x, "aoeu"));
|
||||
ok = true;
|
||||
}
|
||||
96
test/stage1/behavior/reflection.zig
Normal file
96
test/stage1/behavior/reflection.zig
Normal file
@@ -0,0 +1,96 @@
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
const mem = @import("std").mem;
|
||||
const reflection = @This();
|
||||
|
||||
test "reflection: array, pointer, optional, error union type child" {
|
||||
comptime {
|
||||
assertOrPanic(([10]u8).Child == u8);
|
||||
assertOrPanic((*u8).Child == u8);
|
||||
assertOrPanic((anyerror!u8).Payload == u8);
|
||||
assertOrPanic((?u8).Child == u8);
|
||||
}
|
||||
}
|
||||
|
||||
test "reflection: function return type, var args, and param types" {
|
||||
comptime {
|
||||
assertOrPanic(@typeOf(dummy).ReturnType == i32);
|
||||
assertOrPanic(!@typeOf(dummy).is_var_args);
|
||||
assertOrPanic(@typeOf(dummy_varargs).is_var_args);
|
||||
assertOrPanic(@typeOf(dummy).arg_count == 3);
|
||||
assertOrPanic(@ArgType(@typeOf(dummy), 0) == bool);
|
||||
assertOrPanic(@ArgType(@typeOf(dummy), 1) == i32);
|
||||
assertOrPanic(@ArgType(@typeOf(dummy), 2) == f32);
|
||||
}
|
||||
}
|
||||
|
||||
fn dummy(a: bool, b: i32, c: f32) i32 {
|
||||
return 1234;
|
||||
}
|
||||
fn dummy_varargs(args: ...) void {}
|
||||
|
||||
test "reflection: struct member types and names" {
|
||||
comptime {
|
||||
assertOrPanic(@memberCount(Foo) == 3);
|
||||
|
||||
assertOrPanic(@memberType(Foo, 0) == i32);
|
||||
assertOrPanic(@memberType(Foo, 1) == bool);
|
||||
assertOrPanic(@memberType(Foo, 2) == void);
|
||||
|
||||
assertOrPanic(mem.eql(u8, @memberName(Foo, 0), "one"));
|
||||
assertOrPanic(mem.eql(u8, @memberName(Foo, 1), "two"));
|
||||
assertOrPanic(mem.eql(u8, @memberName(Foo, 2), "three"));
|
||||
}
|
||||
}
|
||||
|
||||
test "reflection: enum member types and names" {
|
||||
comptime {
|
||||
assertOrPanic(@memberCount(Bar) == 4);
|
||||
|
||||
assertOrPanic(@memberType(Bar, 0) == void);
|
||||
assertOrPanic(@memberType(Bar, 1) == i32);
|
||||
assertOrPanic(@memberType(Bar, 2) == bool);
|
||||
assertOrPanic(@memberType(Bar, 3) == f64);
|
||||
|
||||
assertOrPanic(mem.eql(u8, @memberName(Bar, 0), "One"));
|
||||
assertOrPanic(mem.eql(u8, @memberName(Bar, 1), "Two"));
|
||||
assertOrPanic(mem.eql(u8, @memberName(Bar, 2), "Three"));
|
||||
assertOrPanic(mem.eql(u8, @memberName(Bar, 3), "Four"));
|
||||
}
|
||||
}
|
||||
|
||||
test "reflection: @field" {
|
||||
var f = Foo{
|
||||
.one = 42,
|
||||
.two = true,
|
||||
.three = void{},
|
||||
};
|
||||
|
||||
assertOrPanic(f.one == f.one);
|
||||
assertOrPanic(@field(f, "o" ++ "ne") == f.one);
|
||||
assertOrPanic(@field(f, "t" ++ "wo") == f.two);
|
||||
assertOrPanic(@field(f, "th" ++ "ree") == f.three);
|
||||
assertOrPanic(@field(Foo, "const" ++ "ant") == Foo.constant);
|
||||
assertOrPanic(@field(Bar, "O" ++ "ne") == Bar.One);
|
||||
assertOrPanic(@field(Bar, "T" ++ "wo") == Bar.Two);
|
||||
assertOrPanic(@field(Bar, "Th" ++ "ree") == Bar.Three);
|
||||
assertOrPanic(@field(Bar, "F" ++ "our") == Bar.Four);
|
||||
assertOrPanic(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
|
||||
@field(f, "o" ++ "ne") = 4;
|
||||
assertOrPanic(f.one == 4);
|
||||
}
|
||||
|
||||
const Foo = struct {
|
||||
const constant = 52;
|
||||
|
||||
one: i32,
|
||||
two: bool,
|
||||
three: void,
|
||||
};
|
||||
|
||||
const Bar = union(enum) {
|
||||
One: void,
|
||||
Two: i32,
|
||||
Three: bool,
|
||||
Four: f64,
|
||||
};
|
||||
|
||||
69
test/stage1/behavior/sizeof_and_typeof.zig
Normal file
69
test/stage1/behavior/sizeof_and_typeof.zig
Normal file
@@ -0,0 +1,69 @@
|
||||
const builtin = @import("builtin");
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "@sizeOf and @typeOf" {
|
||||
const y: @typeOf(x) = 120;
|
||||
assertOrPanic(@sizeOf(@typeOf(y)) == 2);
|
||||
}
|
||||
const x: u16 = 13;
|
||||
const z: @typeOf(x) = 19;
|
||||
|
||||
const A = struct {
|
||||
a: u8,
|
||||
b: u32,
|
||||
c: u8,
|
||||
d: u3,
|
||||
e: u5,
|
||||
f: u16,
|
||||
g: u16,
|
||||
};
|
||||
|
||||
const P = packed struct {
|
||||
a: u8,
|
||||
b: u32,
|
||||
c: u8,
|
||||
d: u3,
|
||||
e: u5,
|
||||
f: u16,
|
||||
g: u16,
|
||||
};
|
||||
|
||||
test "@byteOffsetOf" {
|
||||
// Packed structs have fixed memory layout
|
||||
assertOrPanic(@byteOffsetOf(P, "a") == 0);
|
||||
assertOrPanic(@byteOffsetOf(P, "b") == 1);
|
||||
assertOrPanic(@byteOffsetOf(P, "c") == 5);
|
||||
assertOrPanic(@byteOffsetOf(P, "d") == 6);
|
||||
assertOrPanic(@byteOffsetOf(P, "e") == 6);
|
||||
assertOrPanic(@byteOffsetOf(P, "f") == 7);
|
||||
assertOrPanic(@byteOffsetOf(P, "g") == 9);
|
||||
|
||||
// Normal struct fields can be moved/padded
|
||||
var a: A = undefined;
|
||||
assertOrPanic(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
|
||||
assertOrPanic(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
|
||||
assertOrPanic(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
|
||||
assertOrPanic(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
|
||||
assertOrPanic(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
|
||||
assertOrPanic(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
|
||||
assertOrPanic(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
|
||||
}
|
||||
|
||||
test "@bitOffsetOf" {
|
||||
// Packed structs have fixed memory layout
|
||||
assertOrPanic(@bitOffsetOf(P, "a") == 0);
|
||||
assertOrPanic(@bitOffsetOf(P, "b") == 8);
|
||||
assertOrPanic(@bitOffsetOf(P, "c") == 40);
|
||||
assertOrPanic(@bitOffsetOf(P, "d") == 48);
|
||||
assertOrPanic(@bitOffsetOf(P, "e") == 51);
|
||||
assertOrPanic(@bitOffsetOf(P, "f") == 56);
|
||||
assertOrPanic(@bitOffsetOf(P, "g") == 72);
|
||||
|
||||
assertOrPanic(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
|
||||
assertOrPanic(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
|
||||
assertOrPanic(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
|
||||
assertOrPanic(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
|
||||
assertOrPanic(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
|
||||
assertOrPanic(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
|
||||
assertOrPanic(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
const mem = @import("std").mem;
|
||||
|
||||
const x = @intToPtr([*]i32, 0x1000)[0..0x500];
|
||||
const y = x[0x100..];
|
||||
test "compile time slice of pointer to hard coded address" {
|
||||
assert(@ptrToInt(x.ptr) == 0x1000);
|
||||
assert(x.len == 0x500);
|
||||
assertOrPanic(@ptrToInt(x.ptr) == 0x1000);
|
||||
assertOrPanic(x.len == 0x500);
|
||||
|
||||
assert(@ptrToInt(y.ptr) == 0x1100);
|
||||
assert(y.len == 0x400);
|
||||
assertOrPanic(@ptrToInt(y.ptr) == 0x1100);
|
||||
assertOrPanic(y.len == 0x400);
|
||||
}
|
||||
|
||||
test "slice child property" {
|
||||
var array: [5]i32 = undefined;
|
||||
var slice = array[0..];
|
||||
assert(@typeOf(slice).Child == i32);
|
||||
assertOrPanic(@typeOf(slice).Child == i32);
|
||||
}
|
||||
|
||||
test "runtime safety lets us slice from len..len" {
|
||||
@@ -23,7 +23,7 @@ test "runtime safety lets us slice from len..len" {
|
||||
2,
|
||||
3,
|
||||
};
|
||||
assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
|
||||
assertOrPanic(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
|
||||
}
|
||||
|
||||
fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
|
||||
@@ -36,5 +36,5 @@ test "implicitly cast array of size 0 to slice" {
|
||||
}
|
||||
|
||||
fn assertLenIsZero(msg: []const u8) void {
|
||||
assert(msg.len == 0);
|
||||
assertOrPanic(msg.len == 0);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
const builtin = @import("builtin");
|
||||
const maxInt = std.math.maxInt;
|
||||
|
||||
@@ -12,7 +12,7 @@ const empty_global_instance = StructWithNoFields{};
|
||||
|
||||
test "call struct static method" {
|
||||
const result = StructWithNoFields.add(3, 4);
|
||||
assert(result == 7);
|
||||
assertOrPanic(result == 7);
|
||||
}
|
||||
|
||||
test "return empty struct instance" {
|
||||
@@ -24,8 +24,8 @@ fn returnEmptyStructInstance() StructWithNoFields {
|
||||
|
||||
const should_be_11 = StructWithNoFields.add(5, 6);
|
||||
|
||||
test "invake static method in global scope" {
|
||||
assert(should_be_11 == 11);
|
||||
test "invoke static method in global scope" {
|
||||
assertOrPanic(should_be_11 == 11);
|
||||
}
|
||||
|
||||
test "void struct fields" {
|
||||
@@ -34,8 +34,8 @@ test "void struct fields" {
|
||||
.b = 1,
|
||||
.c = void{},
|
||||
};
|
||||
assert(foo.b == 1);
|
||||
assert(@sizeOf(VoidStructFieldsFoo) == 4);
|
||||
assertOrPanic(foo.b == 1);
|
||||
assertOrPanic(@sizeOf(VoidStructFieldsFoo) == 4);
|
||||
}
|
||||
const VoidStructFieldsFoo = struct {
|
||||
a: void,
|
||||
@@ -50,7 +50,7 @@ test "structs" {
|
||||
foo.b = foo.a == 1;
|
||||
testFoo(foo);
|
||||
testMutation(&foo);
|
||||
assert(foo.c == 100);
|
||||
assertOrPanic(foo.c == 100);
|
||||
}
|
||||
const StructFoo = struct {
|
||||
a: i32,
|
||||
@@ -58,7 +58,7 @@ const StructFoo = struct {
|
||||
c: f32,
|
||||
};
|
||||
fn testFoo(foo: StructFoo) void {
|
||||
assert(foo.b);
|
||||
assertOrPanic(foo.b);
|
||||
}
|
||||
fn testMutation(foo: *StructFoo) void {
|
||||
foo.c = 100;
|
||||
@@ -83,7 +83,7 @@ test "struct point to self" {
|
||||
|
||||
root.next = &node;
|
||||
|
||||
assert(node.next.next.next.val.x == 1);
|
||||
assertOrPanic(node.next.next.next.val.x == 1);
|
||||
}
|
||||
|
||||
test "struct byval assign" {
|
||||
@@ -92,18 +92,18 @@ test "struct byval assign" {
|
||||
|
||||
foo1.a = 1234;
|
||||
foo2.a = 0;
|
||||
assert(foo2.a == 0);
|
||||
assertOrPanic(foo2.a == 0);
|
||||
foo2 = foo1;
|
||||
assert(foo2.a == 1234);
|
||||
assertOrPanic(foo2.a == 1234);
|
||||
}
|
||||
|
||||
fn structInitializer() void {
|
||||
const val = Val{ .x = 42 };
|
||||
assert(val.x == 42);
|
||||
assertOrPanic(val.x == 42);
|
||||
}
|
||||
|
||||
test "fn call of struct field" {
|
||||
assert(callStructField(Foo{ .ptr = aFunc }) == 13);
|
||||
assertOrPanic(callStructField(Foo{ .ptr = aFunc }) == 13);
|
||||
}
|
||||
|
||||
const Foo = struct {
|
||||
@@ -122,7 +122,7 @@ test "store member function in variable" {
|
||||
const instance = MemberFnTestFoo{ .x = 1234 };
|
||||
const memberFn = MemberFnTestFoo.member;
|
||||
const result = memberFn(instance);
|
||||
assert(result == 1234);
|
||||
assertOrPanic(result == 1234);
|
||||
}
|
||||
const MemberFnTestFoo = struct {
|
||||
x: i32,
|
||||
@@ -134,12 +134,12 @@ const MemberFnTestFoo = struct {
|
||||
test "call member function directly" {
|
||||
const instance = MemberFnTestFoo{ .x = 1234 };
|
||||
const result = MemberFnTestFoo.member(instance);
|
||||
assert(result == 1234);
|
||||
assertOrPanic(result == 1234);
|
||||
}
|
||||
|
||||
test "member functions" {
|
||||
const r = MemberFnRand{ .seed = 1234 };
|
||||
assert(r.getSeed() == 1234);
|
||||
assertOrPanic(r.getSeed() == 1234);
|
||||
}
|
||||
const MemberFnRand = struct {
|
||||
seed: u32,
|
||||
@@ -150,7 +150,7 @@ const MemberFnRand = struct {
|
||||
|
||||
test "return struct byval from function" {
|
||||
const bar = makeBar(1234, 5678);
|
||||
assert(bar.y == 5678);
|
||||
assertOrPanic(bar.y == 5678);
|
||||
}
|
||||
const Bar = struct {
|
||||
x: i32,
|
||||
@@ -165,7 +165,7 @@ fn makeBar(x: i32, y: i32) Bar {
|
||||
|
||||
test "empty struct method call" {
|
||||
const es = EmptyStruct{};
|
||||
assert(es.method() == 1234);
|
||||
assertOrPanic(es.method() == 1234);
|
||||
}
|
||||
const EmptyStruct = struct {
|
||||
fn method(es: *const EmptyStruct) i32 {
|
||||
@@ -182,7 +182,7 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 {
|
||||
}
|
||||
|
||||
test "pass slice of empty struct to fn" {
|
||||
assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1);
|
||||
assertOrPanic(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1);
|
||||
}
|
||||
fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
|
||||
return slice.len;
|
||||
@@ -200,7 +200,7 @@ test "packed struct" {
|
||||
};
|
||||
foo.y += 1;
|
||||
const four = foo.x + foo.y;
|
||||
assert(four == 4);
|
||||
assertOrPanic(four == 4);
|
||||
}
|
||||
|
||||
const BitField1 = packed struct {
|
||||
@@ -217,17 +217,17 @@ const bit_field_1 = BitField1{
|
||||
|
||||
test "bit field access" {
|
||||
var data = bit_field_1;
|
||||
assert(getA(&data) == 1);
|
||||
assert(getB(&data) == 2);
|
||||
assert(getC(&data) == 3);
|
||||
comptime assert(@sizeOf(BitField1) == 1);
|
||||
assertOrPanic(getA(&data) == 1);
|
||||
assertOrPanic(getB(&data) == 2);
|
||||
assertOrPanic(getC(&data) == 3);
|
||||
comptime assertOrPanic(@sizeOf(BitField1) == 1);
|
||||
|
||||
data.b += 1;
|
||||
assert(data.b == 3);
|
||||
assertOrPanic(data.b == 3);
|
||||
|
||||
data.a += 1;
|
||||
assert(data.a == 2);
|
||||
assert(data.b == 3);
|
||||
assertOrPanic(data.a == 2);
|
||||
assertOrPanic(data.b == 3);
|
||||
}
|
||||
|
||||
fn getA(data: *const BitField1) u3 {
|
||||
@@ -254,8 +254,8 @@ const Foo96Bits = packed struct {
|
||||
|
||||
test "packed struct 24bits" {
|
||||
comptime {
|
||||
assert(@sizeOf(Foo24Bits) == 3);
|
||||
assert(@sizeOf(Foo96Bits) == 12);
|
||||
assertOrPanic(@sizeOf(Foo24Bits) == 3);
|
||||
assertOrPanic(@sizeOf(Foo96Bits) == 12);
|
||||
}
|
||||
|
||||
var value = Foo96Bits{
|
||||
@@ -265,28 +265,28 @@ test "packed struct 24bits" {
|
||||
.d = 0,
|
||||
};
|
||||
value.a += 1;
|
||||
assert(value.a == 1);
|
||||
assert(value.b == 0);
|
||||
assert(value.c == 0);
|
||||
assert(value.d == 0);
|
||||
assertOrPanic(value.a == 1);
|
||||
assertOrPanic(value.b == 0);
|
||||
assertOrPanic(value.c == 0);
|
||||
assertOrPanic(value.d == 0);
|
||||
|
||||
value.b += 1;
|
||||
assert(value.a == 1);
|
||||
assert(value.b == 1);
|
||||
assert(value.c == 0);
|
||||
assert(value.d == 0);
|
||||
assertOrPanic(value.a == 1);
|
||||
assertOrPanic(value.b == 1);
|
||||
assertOrPanic(value.c == 0);
|
||||
assertOrPanic(value.d == 0);
|
||||
|
||||
value.c += 1;
|
||||
assert(value.a == 1);
|
||||
assert(value.b == 1);
|
||||
assert(value.c == 1);
|
||||
assert(value.d == 0);
|
||||
assertOrPanic(value.a == 1);
|
||||
assertOrPanic(value.b == 1);
|
||||
assertOrPanic(value.c == 1);
|
||||
assertOrPanic(value.d == 0);
|
||||
|
||||
value.d += 1;
|
||||
assert(value.a == 1);
|
||||
assert(value.b == 1);
|
||||
assert(value.c == 1);
|
||||
assert(value.d == 1);
|
||||
assertOrPanic(value.a == 1);
|
||||
assertOrPanic(value.b == 1);
|
||||
assertOrPanic(value.c == 1);
|
||||
assertOrPanic(value.d == 1);
|
||||
}
|
||||
|
||||
const FooArray24Bits = packed struct {
|
||||
@@ -297,43 +297,43 @@ const FooArray24Bits = packed struct {
|
||||
|
||||
test "packed array 24bits" {
|
||||
comptime {
|
||||
assert(@sizeOf([9]Foo24Bits) == 9 * 3);
|
||||
assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
|
||||
assertOrPanic(@sizeOf([9]Foo24Bits) == 9 * 3);
|
||||
assertOrPanic(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
|
||||
}
|
||||
|
||||
var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
|
||||
bytes[bytes.len - 1] = 0xaa;
|
||||
const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
|
||||
assert(ptr.a == 0);
|
||||
assert(ptr.b[0].field == 0);
|
||||
assert(ptr.b[1].field == 0);
|
||||
assert(ptr.c == 0);
|
||||
assertOrPanic(ptr.a == 0);
|
||||
assertOrPanic(ptr.b[0].field == 0);
|
||||
assertOrPanic(ptr.b[1].field == 0);
|
||||
assertOrPanic(ptr.c == 0);
|
||||
|
||||
ptr.a = maxInt(u16);
|
||||
assert(ptr.a == maxInt(u16));
|
||||
assert(ptr.b[0].field == 0);
|
||||
assert(ptr.b[1].field == 0);
|
||||
assert(ptr.c == 0);
|
||||
assertOrPanic(ptr.a == maxInt(u16));
|
||||
assertOrPanic(ptr.b[0].field == 0);
|
||||
assertOrPanic(ptr.b[1].field == 0);
|
||||
assertOrPanic(ptr.c == 0);
|
||||
|
||||
ptr.b[0].field = maxInt(u24);
|
||||
assert(ptr.a == maxInt(u16));
|
||||
assert(ptr.b[0].field == maxInt(u24));
|
||||
assert(ptr.b[1].field == 0);
|
||||
assert(ptr.c == 0);
|
||||
assertOrPanic(ptr.a == maxInt(u16));
|
||||
assertOrPanic(ptr.b[0].field == maxInt(u24));
|
||||
assertOrPanic(ptr.b[1].field == 0);
|
||||
assertOrPanic(ptr.c == 0);
|
||||
|
||||
ptr.b[1].field = maxInt(u24);
|
||||
assert(ptr.a == maxInt(u16));
|
||||
assert(ptr.b[0].field == maxInt(u24));
|
||||
assert(ptr.b[1].field == maxInt(u24));
|
||||
assert(ptr.c == 0);
|
||||
assertOrPanic(ptr.a == maxInt(u16));
|
||||
assertOrPanic(ptr.b[0].field == maxInt(u24));
|
||||
assertOrPanic(ptr.b[1].field == maxInt(u24));
|
||||
assertOrPanic(ptr.c == 0);
|
||||
|
||||
ptr.c = maxInt(u16);
|
||||
assert(ptr.a == maxInt(u16));
|
||||
assert(ptr.b[0].field == maxInt(u24));
|
||||
assert(ptr.b[1].field == maxInt(u24));
|
||||
assert(ptr.c == maxInt(u16));
|
||||
assertOrPanic(ptr.a == maxInt(u16));
|
||||
assertOrPanic(ptr.b[0].field == maxInt(u24));
|
||||
assertOrPanic(ptr.b[1].field == maxInt(u24));
|
||||
assertOrPanic(ptr.c == maxInt(u16));
|
||||
|
||||
assert(bytes[bytes.len - 1] == 0xaa);
|
||||
assertOrPanic(bytes[bytes.len - 1] == 0xaa);
|
||||
}
|
||||
|
||||
const FooStructAligned = packed struct {
|
||||
@@ -347,17 +347,17 @@ const FooArrayOfAligned = packed struct {
|
||||
|
||||
test "aligned array of packed struct" {
|
||||
comptime {
|
||||
assert(@sizeOf(FooStructAligned) == 2);
|
||||
assert(@sizeOf(FooArrayOfAligned) == 2 * 2);
|
||||
assertOrPanic(@sizeOf(FooStructAligned) == 2);
|
||||
assertOrPanic(@sizeOf(FooArrayOfAligned) == 2 * 2);
|
||||
}
|
||||
|
||||
var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
|
||||
const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
|
||||
|
||||
assert(ptr.a[0].a == 0xbb);
|
||||
assert(ptr.a[0].b == 0xbb);
|
||||
assert(ptr.a[1].a == 0xbb);
|
||||
assert(ptr.a[1].b == 0xbb);
|
||||
assertOrPanic(ptr.a[0].a == 0xbb);
|
||||
assertOrPanic(ptr.a[0].b == 0xbb);
|
||||
assertOrPanic(ptr.a[1].a == 0xbb);
|
||||
assertOrPanic(ptr.a[1].b == 0xbb);
|
||||
}
|
||||
|
||||
test "runtime struct initialization of bitfield" {
|
||||
@@ -370,10 +370,10 @@ test "runtime struct initialization of bitfield" {
|
||||
.y = @intCast(u4, x2),
|
||||
};
|
||||
|
||||
assert(s1.x == x1);
|
||||
assert(s1.y == x1);
|
||||
assert(s2.x == @intCast(u4, x2));
|
||||
assert(s2.y == @intCast(u4, x2));
|
||||
assertOrPanic(s1.x == x1);
|
||||
assertOrPanic(s1.y == x1);
|
||||
assertOrPanic(s2.x == @intCast(u4, x2));
|
||||
assertOrPanic(s2.y == @intCast(u4, x2));
|
||||
}
|
||||
|
||||
var x1 = u4(1);
|
||||
@@ -400,18 +400,18 @@ test "native bit field understands endianness" {
|
||||
@memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
|
||||
var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
|
||||
|
||||
assert(bitfields.f1 == 0x1111);
|
||||
assert(bitfields.f2 == 0x2222);
|
||||
assert(bitfields.f3 == 0x33);
|
||||
assert(bitfields.f4 == 0x44);
|
||||
assert(bitfields.f5 == 0x5);
|
||||
assert(bitfields.f6 == 0x6);
|
||||
assert(bitfields.f7 == 0x77);
|
||||
assertOrPanic(bitfields.f1 == 0x1111);
|
||||
assertOrPanic(bitfields.f2 == 0x2222);
|
||||
assertOrPanic(bitfields.f3 == 0x33);
|
||||
assertOrPanic(bitfields.f4 == 0x44);
|
||||
assertOrPanic(bitfields.f5 == 0x5);
|
||||
assertOrPanic(bitfields.f6 == 0x6);
|
||||
assertOrPanic(bitfields.f7 == 0x77);
|
||||
}
|
||||
|
||||
test "align 1 field before self referential align 8 field as slice return type" {
|
||||
const result = alloc(Expr);
|
||||
assert(result.len == 0);
|
||||
assertOrPanic(result.len == 0);
|
||||
}
|
||||
|
||||
const Expr = union(enum) {
|
||||
@@ -434,10 +434,10 @@ test "call method with mutable reference to struct with no fields" {
|
||||
};
|
||||
|
||||
var s = S{};
|
||||
assert(S.doC(&s));
|
||||
assert(s.doC());
|
||||
assert(S.do(&s));
|
||||
assert(s.do());
|
||||
assertOrPanic(S.doC(&s));
|
||||
assertOrPanic(s.doC());
|
||||
assertOrPanic(S.do(&s));
|
||||
assertOrPanic(s.do());
|
||||
}
|
||||
|
||||
test "implicit cast packed struct field to const ptr" {
|
||||
@@ -453,7 +453,7 @@ test "implicit cast packed struct field to const ptr" {
|
||||
var lup: LevelUpMove = undefined;
|
||||
lup.level = 12;
|
||||
const res = LevelUpMove.toInt(lup.level);
|
||||
assert(res == 12);
|
||||
assertOrPanic(res == 12);
|
||||
}
|
||||
|
||||
test "pointer to packed struct member in a stack variable" {
|
||||
@@ -464,7 +464,7 @@ test "pointer to packed struct member in a stack variable" {
|
||||
|
||||
var s = S{ .a = 2, .b = 0 };
|
||||
var b_ptr = &s.b;
|
||||
assert(s.b == 0);
|
||||
assertOrPanic(s.b == 0);
|
||||
b_ptr.* = 2;
|
||||
assert(s.b == 2);
|
||||
assertOrPanic(s.b == 2);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
test "struct contains null pointer which contains original struct" {
|
||||
var x: ?*NodeLineComment = null;
|
||||
assert(x == null);
|
||||
assertOrPanic(x == null);
|
||||
}
|
||||
|
||||
pub const Node = struct {
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
const Node = struct {
|
||||
payload: i32,
|
||||
@@ -39,12 +39,12 @@ test "struct contains slice of itself" {
|
||||
.payload = 1234,
|
||||
.children = nodes[0..],
|
||||
};
|
||||
assert(root.payload == 1234);
|
||||
assert(root.children[0].payload == 1);
|
||||
assert(root.children[1].payload == 2);
|
||||
assert(root.children[2].payload == 3);
|
||||
assert(root.children[2].children[0].payload == 31);
|
||||
assert(root.children[2].children[1].payload == 32);
|
||||
assertOrPanic(root.payload == 1234);
|
||||
assertOrPanic(root.children[0].payload == 1);
|
||||
assertOrPanic(root.children[1].payload == 2);
|
||||
assertOrPanic(root.children[2].payload == 3);
|
||||
assertOrPanic(root.children[2].children[0].payload == 31);
|
||||
assertOrPanic(root.children[2].children[1].payload == 32);
|
||||
}
|
||||
|
||||
test "struct contains aligned slice of itself" {
|
||||
@@ -76,10 +76,10 @@ test "struct contains aligned slice of itself" {
|
||||
.payload = 1234,
|
||||
.children = nodes[0..],
|
||||
};
|
||||
assert(root.payload == 1234);
|
||||
assert(root.children[0].payload == 1);
|
||||
assert(root.children[1].payload == 2);
|
||||
assert(root.children[2].payload == 3);
|
||||
assert(root.children[2].children[0].payload == 31);
|
||||
assert(root.children[2].children[1].payload == 32);
|
||||
assertOrPanic(root.payload == 1234);
|
||||
assertOrPanic(root.children[0].payload == 1);
|
||||
assertOrPanic(root.children[1].payload == 2);
|
||||
assertOrPanic(root.children[2].payload == 3);
|
||||
assertOrPanic(root.children[2].children[0].payload == 31);
|
||||
assertOrPanic(root.children[2].children[1].payload == 32);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "switch with numbers" {
|
||||
testSwitchWithNumbers(13);
|
||||
@@ -10,14 +10,14 @@ fn testSwitchWithNumbers(x: u32) void {
|
||||
13 => true,
|
||||
else => false,
|
||||
};
|
||||
assert(result);
|
||||
assertOrPanic(result);
|
||||
}
|
||||
|
||||
test "switch with all ranges" {
|
||||
assert(testSwitchWithAllRanges(50, 3) == 1);
|
||||
assert(testSwitchWithAllRanges(101, 0) == 2);
|
||||
assert(testSwitchWithAllRanges(300, 5) == 3);
|
||||
assert(testSwitchWithAllRanges(301, 6) == 6);
|
||||
assertOrPanic(testSwitchWithAllRanges(50, 3) == 1);
|
||||
assertOrPanic(testSwitchWithAllRanges(101, 0) == 2);
|
||||
assertOrPanic(testSwitchWithAllRanges(300, 5) == 3);
|
||||
assertOrPanic(testSwitchWithAllRanges(301, 6) == 6);
|
||||
}
|
||||
|
||||
fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
|
||||
@@ -40,7 +40,7 @@ test "implicit comptime switch" {
|
||||
};
|
||||
|
||||
comptime {
|
||||
assert(result + 1 == 14);
|
||||
assertOrPanic(result + 1 == 14);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ fn nonConstSwitch(foo: SwitchStatmentFoo) void {
|
||||
SwitchStatmentFoo.C => 3,
|
||||
SwitchStatmentFoo.D => 4,
|
||||
};
|
||||
assert(val == 3);
|
||||
assertOrPanic(val == 3);
|
||||
}
|
||||
const SwitchStatmentFoo = enum {
|
||||
A,
|
||||
@@ -93,10 +93,10 @@ const SwitchProngWithVarEnum = union(enum) {
|
||||
fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void {
|
||||
switch (a) {
|
||||
SwitchProngWithVarEnum.One => |x| {
|
||||
assert(x == 13);
|
||||
assertOrPanic(x == 13);
|
||||
},
|
||||
SwitchProngWithVarEnum.Two => |x| {
|
||||
assert(x == 13.0);
|
||||
assertOrPanic(x == 13.0);
|
||||
},
|
||||
SwitchProngWithVarEnum.Meh => |x| {
|
||||
const v: void = x;
|
||||
@@ -116,7 +116,7 @@ fn testSwitchEnumPtrCapture() void {
|
||||
else => unreachable,
|
||||
}
|
||||
switch (value) {
|
||||
SwitchProngWithVarEnum.One => |x| assert(x == 1235),
|
||||
SwitchProngWithVarEnum.One => |x| assertOrPanic(x == 1235),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@@ -127,7 +127,7 @@ test "switch with multiple expressions" {
|
||||
4, 5, 6 => 2,
|
||||
else => i32(3),
|
||||
};
|
||||
assert(x == 2);
|
||||
assertOrPanic(x == 2);
|
||||
}
|
||||
fn returnsFive() i32 {
|
||||
return 5;
|
||||
@@ -149,12 +149,12 @@ fn returnsFalse() bool {
|
||||
}
|
||||
}
|
||||
test "switch on const enum with var" {
|
||||
assert(!returnsFalse());
|
||||
assertOrPanic(!returnsFalse());
|
||||
}
|
||||
|
||||
test "switch on type" {
|
||||
assert(trueIfBoolFalseOtherwise(bool));
|
||||
assert(!trueIfBoolFalseOtherwise(i32));
|
||||
assertOrPanic(trueIfBoolFalseOtherwise(bool));
|
||||
assertOrPanic(!trueIfBoolFalseOtherwise(i32));
|
||||
}
|
||||
|
||||
fn trueIfBoolFalseOtherwise(comptime T: type) bool {
|
||||
@@ -170,16 +170,16 @@ test "switch handles all cases of number" {
|
||||
}
|
||||
|
||||
fn testSwitchHandleAllCases() void {
|
||||
assert(testSwitchHandleAllCasesExhaustive(0) == 3);
|
||||
assert(testSwitchHandleAllCasesExhaustive(1) == 2);
|
||||
assert(testSwitchHandleAllCasesExhaustive(2) == 1);
|
||||
assert(testSwitchHandleAllCasesExhaustive(3) == 0);
|
||||
assertOrPanic(testSwitchHandleAllCasesExhaustive(0) == 3);
|
||||
assertOrPanic(testSwitchHandleAllCasesExhaustive(1) == 2);
|
||||
assertOrPanic(testSwitchHandleAllCasesExhaustive(2) == 1);
|
||||
assertOrPanic(testSwitchHandleAllCasesExhaustive(3) == 0);
|
||||
|
||||
assert(testSwitchHandleAllCasesRange(100) == 0);
|
||||
assert(testSwitchHandleAllCasesRange(200) == 1);
|
||||
assert(testSwitchHandleAllCasesRange(201) == 2);
|
||||
assert(testSwitchHandleAllCasesRange(202) == 4);
|
||||
assert(testSwitchHandleAllCasesRange(230) == 3);
|
||||
assertOrPanic(testSwitchHandleAllCasesRange(100) == 0);
|
||||
assertOrPanic(testSwitchHandleAllCasesRange(200) == 1);
|
||||
assertOrPanic(testSwitchHandleAllCasesRange(201) == 2);
|
||||
assertOrPanic(testSwitchHandleAllCasesRange(202) == 4);
|
||||
assertOrPanic(testSwitchHandleAllCasesRange(230) == 3);
|
||||
}
|
||||
|
||||
fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
|
||||
@@ -207,8 +207,8 @@ test "switch all prongs unreachable" {
|
||||
}
|
||||
|
||||
fn testAllProngsUnreachable() void {
|
||||
assert(switchWithUnreachable(1) == 2);
|
||||
assert(switchWithUnreachable(2) == 10);
|
||||
assertOrPanic(switchWithUnreachable(1) == 2);
|
||||
assertOrPanic(switchWithUnreachable(2) == 10);
|
||||
}
|
||||
|
||||
fn switchWithUnreachable(x: i32) i32 {
|
||||
@@ -230,7 +230,7 @@ test "capture value of switch with all unreachable prongs" {
|
||||
const x = return_a_number() catch |err| switch (err) {
|
||||
else => unreachable,
|
||||
};
|
||||
assert(x == 1);
|
||||
assertOrPanic(x == 1);
|
||||
}
|
||||
|
||||
test "switching on booleans" {
|
||||
@@ -239,14 +239,14 @@ test "switching on booleans" {
|
||||
}
|
||||
|
||||
fn testSwitchOnBools() void {
|
||||
assert(testSwitchOnBoolsTrueAndFalse(true) == false);
|
||||
assert(testSwitchOnBoolsTrueAndFalse(false) == true);
|
||||
assertOrPanic(testSwitchOnBoolsTrueAndFalse(true) == false);
|
||||
assertOrPanic(testSwitchOnBoolsTrueAndFalse(false) == true);
|
||||
|
||||
assert(testSwitchOnBoolsTrueWithElse(true) == false);
|
||||
assert(testSwitchOnBoolsTrueWithElse(false) == true);
|
||||
assertOrPanic(testSwitchOnBoolsTrueWithElse(true) == false);
|
||||
assertOrPanic(testSwitchOnBoolsTrueWithElse(false) == true);
|
||||
|
||||
assert(testSwitchOnBoolsFalseWithElse(true) == false);
|
||||
assert(testSwitchOnBoolsFalseWithElse(false) == true);
|
||||
assertOrPanic(testSwitchOnBoolsFalseWithElse(true) == false);
|
||||
assertOrPanic(testSwitchOnBoolsFalseWithElse(false) == true);
|
||||
}
|
||||
|
||||
fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
var read_count: u64 = 0;
|
||||
|
||||
@@ -22,9 +22,9 @@ fn doThing(form_id: u64) anyerror!FormValue {
|
||||
test "switch prong returns error enum" {
|
||||
switch (doThing(17) catch unreachable) {
|
||||
FormValue.Address => |payload| {
|
||||
assert(payload == 1);
|
||||
assertOrPanic(payload == 1);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
assert(read_count == 1);
|
||||
assertOrPanic(read_count == 1);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
const FormValue = union(enum) {
|
||||
One: void,
|
||||
@@ -18,5 +18,5 @@ test "switch prong implicit cast" {
|
||||
FormValue.One => false,
|
||||
FormValue.Two => |x| x,
|
||||
};
|
||||
assert(result);
|
||||
assertOrPanic(result);
|
||||
}
|
||||
@@ -57,3 +57,4 @@ fn asm_lists() void {
|
||||
:::"a","b",);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
const module = @This();
|
||||
|
||||
@@ -20,7 +20,7 @@ fn add(x: i32, y: i32) i32 {
|
||||
}
|
||||
|
||||
test "this refer to module call private fn" {
|
||||
assert(module.add(1, 2) == 3);
|
||||
assertOrPanic(module.add(1, 2) == 3);
|
||||
}
|
||||
|
||||
test "this refer to container" {
|
||||
@@ -29,6 +29,7 @@ test "this refer to container" {
|
||||
.y = 34,
|
||||
};
|
||||
pt.addOne();
|
||||
assert(pt.x == 13);
|
||||
assert(pt.y == 35);
|
||||
assertOrPanic(pt.x == 13);
|
||||
assertOrPanic(pt.y == 35);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
test "truncate u0 to larger integer allowed and has comptime known result" {
|
||||
var x: u0 = 0;
|
||||
const y = @truncate(u8, x);
|
||||
comptime assert(y == 0);
|
||||
comptime assertOrPanic(y == 0);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
const assertOrPanic = @import("std").debug.assertOrPanic;
|
||||
|
||||
test "try on error union" {
|
||||
tryOnErrorUnionImpl();
|
||||
@@ -11,7 +11,7 @@ fn tryOnErrorUnionImpl() void {
|
||||
error.CrappedOut => i32(2),
|
||||
else => unreachable,
|
||||
};
|
||||
assert(x == 11);
|
||||
assertOrPanic(x == 11);
|
||||
}
|
||||
|
||||
fn returnsTen() anyerror!i32 {
|
||||
@@ -20,10 +20,10 @@ fn returnsTen() anyerror!i32 {
|
||||
|
||||
test "try without vars" {
|
||||
const result1 = if (failIfTrue(true)) 1 else |_| i32(2);
|
||||
assert(result1 == 2);
|
||||
assertOrPanic(result1 == 2);
|
||||
|
||||
const result2 = if (failIfTrue(false)) 1 else |_| i32(2);
|
||||
assert(result2 == 1);
|
||||
assertOrPanic(result2 == 1);
|
||||
}
|
||||
|
||||
fn failIfTrue(ok: bool) anyerror!void {
|
||||
@@ -38,6 +38,6 @@ test "try then not executed with assignment" {
|
||||
if (failIfTrue(true)) {
|
||||
unreachable;
|
||||
} else |err| {
|
||||
assert(err == error.ItBroke);
|
||||
assertOrPanic(err == error.ItBroke);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user