| author | |
| committer | |
| log | 581edd643fb18a66c472f77e2f8cd3f4cea524a2 |
| tree | a03f6a3ade952729456b94584f21d4beb51a4802 |
| parent | 9c328b42916d463465b134457c7f13b5c65da406 |
| signature |
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.181 files changed, 10595 insertions(+), 9692 deletions(-)
build.zig+2-3| ... | ... | @@ -104,7 +104,7 @@ pub fn build(b: *Builder) !void { |
| 104 | 104 | } |
| 105 | 105 | const modes = chosen_modes[0..chosen_mode_index]; |
| 106 | 106 | |
| 107 | test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes)); | |
| 107 | test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes)); | |
| 108 | 108 | |
| 109 | 109 | test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes)); |
| 110 | 110 | |
| ... | ... | @@ -299,8 +299,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { |
| 299 | 299 | } else if (exe.target.isFreeBSD()) { |
| 300 | 300 | try addCxxKnownPath(b, ctx, exe, "libc++.a", null); |
| 301 | 301 | exe.linkSystemLibrary("pthread"); |
| 302 | } | |
| 303 | else if (exe.target.isDarwin()) { | |
| 302 | } else if (exe.target.isDarwin()) { | |
| 304 | 303 | if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) { |
| 305 | 304 | // Compiler is GCC. |
| 306 | 305 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null); |
doc/langref.html.in+7-6| ... | ... | @@ -4327,7 +4327,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 { |
| 4327 | 4327 | <p> |
| 4328 | 4328 | For example, if we were to introduce another function to the above snippet: |
| 4329 | 4329 | </p> |
| 4330 | {#code_begin|test_err|unable to evaluate constant expression#} | |
| 4330 | {#code_begin|test_err|values of type 'type' must be comptime known#} | |
| 4331 | 4331 | fn max(comptime T: type, a: T, b: T) T { |
| 4332 | 4332 | return if (a > b) a else b; |
| 4333 | 4333 | } |
| ... | ... | @@ -5905,13 +5905,13 @@ fn add(a: i32, b: i32) i32 { return a + b; } |
| 5905 | 5905 | This function is a low level intrinsic with no safety mechanisms. Most code |
| 5906 | 5906 | should not use this function, instead using something like this: |
| 5907 | 5907 | </p> |
| 5908 | <pre>{#syntax#}for (source[0...byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre> | |
| 5908 | <pre>{#syntax#}for (source[0..byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre> | |
| 5909 | 5909 | <p> |
| 5910 | 5910 | The optimizer is intelligent enough to turn the above snippet into a memcpy. |
| 5911 | 5911 | </p> |
| 5912 | 5912 | <p>There is also a standard library function for this:</p> |
| 5913 | 5913 | <pre>{#syntax#}const mem = @import("std").mem; |
| 5914 | mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> | |
| 5914 | mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#}</pre> | |
| 5915 | 5915 | {#header_close#} |
| 5916 | 5916 | |
| 5917 | 5917 | {#header_open|@memset#} |
| ... | ... | @@ -5923,7 +5923,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre> |
| 5923 | 5923 | This function is a low level intrinsic with no safety mechanisms. Most |
| 5924 | 5924 | code should not use this function, instead using something like this: |
| 5925 | 5925 | </p> |
| 5926 | <pre>{#syntax#}for (dest[0...byte_count]) |*b| b.* = c;{#endsyntax#}</pre> | |
| 5926 | <pre>{#syntax#}for (dest[0..byte_count]) |*b| b.* = c;{#endsyntax#}</pre> | |
| 5927 | 5927 | <p> |
| 5928 | 5928 | The optimizer is intelligent enough to turn the above snippet into a memset. |
| 5929 | 5929 | </p> |
| ... | ... | @@ -6592,9 +6592,10 @@ pub const TypeInfo = union(TypeId) { |
| 6592 | 6592 | {#header_close#} |
| 6593 | 6593 | |
| 6594 | 6594 | {#header_open|@typeName#} |
| 6595 | <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre> | |
| 6595 | <pre>{#syntax#}@typeName(T: type) [N]u8{#endsyntax#}</pre> | |
| 6596 | 6596 | <p> |
| 6597 | This function returns the string representation of a type. | |
| 6597 | This function returns the string representation of a type, as | |
| 6598 | an array. It is equivalent to a string literal of the type name. | |
| 6598 | 6599 | </p> |
| 6599 | 6600 | |
| 6600 | 6601 | {#header_close#} |
src/all_types.hpp+115-50| ... | ... | @@ -56,9 +56,6 @@ struct IrExecutable { |
| 56 | 56 | size_t next_debug_id; |
| 57 | 57 | size_t *backward_branch_count; |
| 58 | 58 | size_t backward_branch_quota; |
| 59 | bool invalid; | |
| 60 | bool is_inline; | |
| 61 | bool is_generic_instantiation; | |
| 62 | 59 | ZigFn *fn_entry; |
| 63 | 60 | Buf *c_import_buf; |
| 64 | 61 | AstNode *source_node; |
| ... | ... | @@ -78,6 +75,10 @@ struct IrExecutable { |
| 78 | 75 | IrBasicBlock *coro_suspend_block; |
| 79 | 76 | IrBasicBlock *coro_final_cleanup_block; |
| 80 | 77 | ZigVar *coro_allocator_var; |
| 78 | ||
| 79 | bool invalid; | |
| 80 | bool is_inline; | |
| 81 | bool is_generic_instantiation; | |
| 81 | 82 | }; |
| 82 | 83 | |
| 83 | 84 | enum OutType { |
| ... | ... | @@ -90,6 +91,9 @@ enum OutType { |
| 90 | 91 | enum ConstParentId { |
| 91 | 92 | ConstParentIdNone, |
| 92 | 93 | ConstParentIdStruct, |
| 94 | ConstParentIdErrUnionCode, | |
| 95 | ConstParentIdErrUnionPayload, | |
| 96 | ConstParentIdOptionalPayload, | |
| 93 | 97 | ConstParentIdArray, |
| 94 | 98 | ConstParentIdUnion, |
| 95 | 99 | ConstParentIdScalar, |
| ... | ... | @@ -107,6 +111,15 @@ struct ConstParent { |
| 107 | 111 | ConstExprValue *struct_val; |
| 108 | 112 | size_t field_index; |
| 109 | 113 | } p_struct; |
| 114 | struct { | |
| 115 | ConstExprValue *err_union_val; | |
| 116 | } p_err_union_code; | |
| 117 | struct { | |
| 118 | ConstExprValue *err_union_val; | |
| 119 | } p_err_union_payload; | |
| 120 | struct { | |
| 121 | ConstExprValue *optional_val; | |
| 122 | } p_optional_payload; | |
| 110 | 123 | struct { |
| 111 | 124 | ConstExprValue *union_val; |
| 112 | 125 | } p_union; |
| ... | ... | @@ -118,13 +131,11 @@ struct ConstParent { |
| 118 | 131 | |
| 119 | 132 | struct ConstStructValue { |
| 120 | 133 | ConstExprValue *fields; |
| 121 | ConstParent parent; | |
| 122 | 134 | }; |
| 123 | 135 | |
| 124 | 136 | struct ConstUnionValue { |
| 125 | 137 | BigInt tag; |
| 126 | 138 | ConstExprValue *payload; |
| 127 | ConstParent parent; | |
| 128 | 139 | }; |
| 129 | 140 | |
| 130 | 141 | enum ConstArraySpecial { |
| ... | ... | @@ -138,7 +149,6 @@ struct ConstArrayValue { |
| 138 | 149 | union { |
| 139 | 150 | struct { |
| 140 | 151 | ConstExprValue *elements; |
| 141 | ConstParent parent; | |
| 142 | 152 | } s_none; |
| 143 | 153 | Buf *s_buf; |
| 144 | 154 | } data; |
| ... | ... | @@ -153,19 +163,29 @@ enum ConstPtrSpecial { |
| 153 | 163 | ConstPtrSpecialBaseArray, |
| 154 | 164 | // The pointer points to a field in an underlying struct. |
| 155 | 165 | ConstPtrSpecialBaseStruct, |
| 166 | // The pointer points to the error set field of an error union | |
| 167 | ConstPtrSpecialBaseErrorUnionCode, | |
| 168 | // The pointer points to the payload field of an error union | |
| 169 | ConstPtrSpecialBaseErrorUnionPayload, | |
| 170 | // The pointer points to the payload field of an optional | |
| 171 | ConstPtrSpecialBaseOptionalPayload, | |
| 156 | 172 | // This means that we did a compile-time pointer reinterpret and we cannot |
| 157 | 173 | // understand the value of pointee at compile time. However, we will still |
| 158 | 174 | // emit a binary with a compile time known address. |
| 159 | 175 | // In this case index is the numeric address value. |
| 160 | // We also use this for null pointer. We need the data layout for ConstCastOnly == true | |
| 161 | // types to be the same, so all optionals of pointer types use x_ptr | |
| 162 | // instead of x_optional | |
| 163 | 176 | ConstPtrSpecialHardCodedAddr, |
| 164 | 177 | // This means that the pointer represents memory of assigning to _. |
| 165 | 178 | // That is, storing discards the data, and loading is invalid. |
| 166 | 179 | ConstPtrSpecialDiscard, |
| 167 | 180 | // This is actually a function. |
| 168 | 181 | ConstPtrSpecialFunction, |
| 182 | // This means the pointer is null. This is only allowed when the type is ?*T. | |
| 183 | // We use this instead of ConstPtrSpecialHardCodedAddr because often we check | |
| 184 | // for that value to avoid doing comptime work. | |
| 185 | // We need the data layout for ConstCastOnly == true | |
| 186 | // types to be the same, so all optionals of pointer types use x_ptr | |
| 187 | // instead of x_optional. | |
| 188 | ConstPtrSpecialNull, | |
| 169 | 189 | }; |
| 170 | 190 | |
| 171 | 191 | enum ConstPtrMut { |
| ... | ... | @@ -199,6 +219,15 @@ struct ConstPtrValue { |
| 199 | 219 | ConstExprValue *struct_val; |
| 200 | 220 | size_t field_index; |
| 201 | 221 | } base_struct; |
| 222 | struct { | |
| 223 | ConstExprValue *err_union_val; | |
| 224 | } base_err_union_code; | |
| 225 | struct { | |
| 226 | ConstExprValue *err_union_val; | |
| 227 | } base_err_union_payload; | |
| 228 | struct { | |
| 229 | ConstExprValue *optional_val; | |
| 230 | } base_optional_payload; | |
| 202 | 231 | struct { |
| 203 | 232 | uint64_t addr; |
| 204 | 233 | } hard_coded_addr; |
| ... | ... | @@ -209,7 +238,7 @@ struct ConstPtrValue { |
| 209 | 238 | }; |
| 210 | 239 | |
| 211 | 240 | struct ConstErrValue { |
| 212 | ErrorTableEntry *err; | |
| 241 | ConstExprValue *error_set; | |
| 213 | 242 | ConstExprValue *payload; |
| 214 | 243 | }; |
| 215 | 244 | |
| ... | ... | @@ -265,6 +294,7 @@ struct ConstGlobalRefs { |
| 265 | 294 | struct ConstExprValue { |
| 266 | 295 | ZigType *type; |
| 267 | 296 | ConstValSpecial special; |
| 297 | ConstParent parent; | |
| 268 | 298 | ConstGlobalRefs *global_refs; |
| 269 | 299 | |
| 270 | 300 | union { |
| ... | ... | @@ -433,7 +463,7 @@ enum NodeType { |
| 433 | 463 | NodeTypeArrayType, |
| 434 | 464 | NodeTypeErrorType, |
| 435 | 465 | NodeTypeIfErrorExpr, |
| 436 | NodeTypeTestExpr, | |
| 466 | NodeTypeIfOptional, | |
| 437 | 467 | NodeTypeErrorSetDecl, |
| 438 | 468 | NodeTypeCancel, |
| 439 | 469 | NodeTypeResume, |
| ... | ... | @@ -677,7 +707,7 @@ struct AstNodeUse { |
| 677 | 707 | AstNode *expr; |
| 678 | 708 | |
| 679 | 709 | TldResolution resolution; |
| 680 | IrInstruction *value; | |
| 710 | ConstExprValue *value; | |
| 681 | 711 | }; |
| 682 | 712 | |
| 683 | 713 | struct AstNodeIfBoolExpr { |
| ... | ... | @@ -1610,7 +1640,7 @@ struct CodeGen { |
| 1610 | 1640 | HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table; |
| 1611 | 1641 | HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table; |
| 1612 | 1642 | HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table; |
| 1613 | HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; | |
| 1643 | HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; | |
| 1614 | 1644 | HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table; |
| 1615 | 1645 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names; |
| 1616 | 1646 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes; |
| ... | ... | @@ -1802,10 +1832,9 @@ enum VarLinkage { |
| 1802 | 1832 | |
| 1803 | 1833 | struct ZigVar { |
| 1804 | 1834 | Buf name; |
| 1805 | ConstExprValue *value; | |
| 1835 | ConstExprValue *const_value; | |
| 1836 | ZigType *var_type; | |
| 1806 | 1837 | LLVMValueRef value_ref; |
| 1807 | bool src_is_const; | |
| 1808 | bool gen_is_const; | |
| 1809 | 1838 | IrInstruction *is_comptime; |
| 1810 | 1839 | // which node is the declaration of the variable |
| 1811 | 1840 | AstNode *decl_node; |
| ... | ... | @@ -1815,17 +1844,21 @@ struct ZigVar { |
| 1815 | 1844 | Scope *parent_scope; |
| 1816 | 1845 | Scope *child_scope; |
| 1817 | 1846 | LLVMValueRef param_value_ref; |
| 1818 | bool shadowable; | |
| 1819 | 1847 | size_t mem_slot_index; |
| 1820 | 1848 | IrExecutable *owner_exec; |
| 1821 | 1849 | size_t ref_count; |
| 1822 | VarLinkage linkage; | |
| 1823 | uint32_t align_bytes; | |
| 1824 | 1850 | |
| 1825 | 1851 | // In an inline loop, multiple variables may be created, |
| 1826 | 1852 | // In this case, a reference to a variable should follow |
| 1827 | 1853 | // this pointer to the redefined variable. |
| 1828 | 1854 | ZigVar *next_var; |
| 1855 | ||
| 1856 | uint32_t align_bytes; | |
| 1857 | VarLinkage linkage; | |
| 1858 | ||
| 1859 | bool shadowable; | |
| 1860 | bool src_is_const; | |
| 1861 | bool gen_is_const; | |
| 1829 | 1862 | }; |
| 1830 | 1863 | |
| 1831 | 1864 | struct ErrorTableEntry { |
| ... | ... | @@ -1891,10 +1924,11 @@ struct ScopeBlock { |
| 1891 | 1924 | ZigList<IrInstruction *> *incoming_values; |
| 1892 | 1925 | ZigList<IrBasicBlock *> *incoming_blocks; |
| 1893 | 1926 | |
| 1894 | bool safety_off; | |
| 1895 | 1927 | AstNode *safety_set_node; |
| 1896 | bool fast_math_on; | |
| 1897 | 1928 | AstNode *fast_math_set_node; |
| 1929 | ||
| 1930 | bool safety_off; | |
| 1931 | bool fast_math_on; | |
| 1898 | 1932 | }; |
| 1899 | 1933 | |
| 1900 | 1934 | // This scope is created from every defer expression. |
| ... | ... | @@ -2030,8 +2064,19 @@ struct IrBasicBlock { |
| 2030 | 2064 | IrInstruction *must_be_comptime_source_instr; |
| 2031 | 2065 | }; |
| 2032 | 2066 | |
| 2067 | // These instructions are in transition to having "pass 1" instructions | |
| 2068 | // and "pass 2" instructions. The pass 1 instructions are suffixed with Src | |
| 2069 | // and pass 2 are suffixed with Gen. | |
| 2070 | // Once all instructions are separated in this way, they'll have different | |
| 2071 | // base types for better type safety. | |
| 2072 | // Src instructions are generated by ir_gen_* functions in ir.cpp from AST. | |
| 2073 | // ir_analyze_* functions consume Src instructions and produce Gen instructions. | |
| 2074 | // ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR. | |
| 2075 | // Src instructions do not have type information; Gen instructions do. | |
| 2033 | 2076 | enum IrInstructionId { |
| 2034 | 2077 | IrInstructionIdInvalid, |
| 2078 | IrInstructionIdDeclVarSrc, | |
| 2079 | IrInstructionIdDeclVarGen, | |
| 2035 | 2080 | IrInstructionIdBr, |
| 2036 | 2081 | IrInstructionIdCondBr, |
| 2037 | 2082 | IrInstructionIdSwitchBr, |
| ... | ... | @@ -2040,7 +2085,6 @@ enum IrInstructionId { |
| 2040 | 2085 | IrInstructionIdPhi, |
| 2041 | 2086 | IrInstructionIdUnOp, |
| 2042 | 2087 | IrInstructionIdBinOp, |
| 2043 | IrInstructionIdDeclVar, | |
| 2044 | 2088 | IrInstructionIdLoadPtr, |
| 2045 | 2089 | IrInstructionIdStorePtr, |
| 2046 | 2090 | IrInstructionIdFieldPtr, |
| ... | ... | @@ -2069,7 +2113,7 @@ enum IrInstructionId { |
| 2069 | 2113 | IrInstructionIdAsm, |
| 2070 | 2114 | IrInstructionIdSizeOf, |
| 2071 | 2115 | IrInstructionIdTestNonNull, |
| 2072 | IrInstructionIdUnwrapOptional, | |
| 2116 | IrInstructionIdOptionalUnwrapPtr, | |
| 2073 | 2117 | IrInstructionIdOptionalWrap, |
| 2074 | 2118 | IrInstructionIdUnionTag, |
| 2075 | 2119 | IrInstructionIdClz, |
| ... | ... | @@ -2085,7 +2129,8 @@ enum IrInstructionId { |
| 2085 | 2129 | IrInstructionIdCompileLog, |
| 2086 | 2130 | IrInstructionIdErrName, |
| 2087 | 2131 | IrInstructionIdEmbedFile, |
| 2088 | IrInstructionIdCmpxchg, | |
| 2132 | IrInstructionIdCmpxchgSrc, | |
| 2133 | IrInstructionIdCmpxchgGen, | |
| 2089 | 2134 | IrInstructionIdFence, |
| 2090 | 2135 | IrInstructionIdTruncate, |
| 2091 | 2136 | IrInstructionIdIntCast, |
| ... | ... | @@ -2114,7 +2159,8 @@ enum IrInstructionId { |
| 2114 | 2159 | IrInstructionIdErrWrapPayload, |
| 2115 | 2160 | IrInstructionIdFnProto, |
| 2116 | 2161 | IrInstructionIdTestComptime, |
| 2117 | IrInstructionIdPtrCast, | |
| 2162 | IrInstructionIdPtrCastSrc, | |
| 2163 | IrInstructionIdPtrCastGen, | |
| 2118 | 2164 | IrInstructionIdBitCast, |
| 2119 | 2165 | IrInstructionIdWidenOrShorten, |
| 2120 | 2166 | IrInstructionIdIntToPtr, |
| ... | ... | @@ -2194,6 +2240,22 @@ struct IrInstruction { |
| 2194 | 2240 | bool is_gen; |
| 2195 | 2241 | }; |
| 2196 | 2242 | |
| 2243 | struct IrInstructionDeclVarSrc { | |
| 2244 | IrInstruction base; | |
| 2245 | ||
| 2246 | ZigVar *var; | |
| 2247 | IrInstruction *var_type; | |
| 2248 | IrInstruction *align_value; | |
| 2249 | IrInstruction *init_value; | |
| 2250 | }; | |
| 2251 | ||
| 2252 | struct IrInstructionDeclVarGen { | |
| 2253 | IrInstruction base; | |
| 2254 | ||
| 2255 | ZigVar *var; | |
| 2256 | IrInstruction *init_value; | |
| 2257 | }; | |
| 2258 | ||
| 2197 | 2259 | struct IrInstructionCondBr { |
| 2198 | 2260 | IrInstruction base; |
| 2199 | 2261 | |
| ... | ... | @@ -2302,20 +2364,11 @@ struct IrInstructionBinOp { |
| 2302 | 2364 | IrInstruction base; |
| 2303 | 2365 | |
| 2304 | 2366 | IrInstruction *op1; |
| 2305 | IrBinOp op_id; | |
| 2306 | 2367 | IrInstruction *op2; |
| 2368 | IrBinOp op_id; | |
| 2307 | 2369 | bool safety_check_on; |
| 2308 | 2370 | }; |
| 2309 | 2371 | |
| 2310 | struct IrInstructionDeclVar { | |
| 2311 | IrInstruction base; | |
| 2312 | ||
| 2313 | ZigVar *var; | |
| 2314 | IrInstruction *var_type; | |
| 2315 | IrInstruction *align_value; | |
| 2316 | IrInstruction *init_value; | |
| 2317 | }; | |
| 2318 | ||
| 2319 | 2372 | struct IrInstructionLoadPtr { |
| 2320 | 2373 | IrInstruction base; |
| 2321 | 2374 | |
| ... | ... | @@ -2335,7 +2388,6 @@ struct IrInstructionFieldPtr { |
| 2335 | 2388 | IrInstruction *container_ptr; |
| 2336 | 2389 | Buf *field_name_buffer; |
| 2337 | 2390 | IrInstruction *field_name_expr; |
| 2338 | bool is_const; | |
| 2339 | 2391 | }; |
| 2340 | 2392 | |
| 2341 | 2393 | struct IrInstructionStructFieldPtr { |
| ... | ... | @@ -2378,13 +2430,13 @@ struct IrInstructionCall { |
| 2378 | 2430 | ZigFn *fn_entry; |
| 2379 | 2431 | size_t arg_count; |
| 2380 | 2432 | IrInstruction **args; |
| 2381 | bool is_comptime; | |
| 2382 | 2433 | LLVMValueRef tmp_ptr; |
| 2383 | FnInline fn_inline; | |
| 2384 | bool is_async; | |
| 2385 | 2434 | |
| 2386 | 2435 | IrInstruction *async_allocator; |
| 2387 | 2436 | IrInstruction *new_stack; |
| 2437 | FnInline fn_inline; | |
| 2438 | bool is_async; | |
| 2439 | bool is_comptime; | |
| 2388 | 2440 | }; |
| 2389 | 2441 | |
| 2390 | 2442 | struct IrInstructionConst { |
| ... | ... | @@ -2527,9 +2579,9 @@ struct IrInstructionSliceType { |
| 2527 | 2579 | IrInstruction base; |
| 2528 | 2580 | |
| 2529 | 2581 | IrInstruction *align_value; |
| 2582 | IrInstruction *child_type; | |
| 2530 | 2583 | bool is_const; |
| 2531 | 2584 | bool is_volatile; |
| 2532 | IrInstruction *child_type; | |
| 2533 | 2585 | }; |
| 2534 | 2586 | |
| 2535 | 2587 | struct IrInstructionAsm { |
| ... | ... | @@ -2557,10 +2609,12 @@ struct IrInstructionTestNonNull { |
| 2557 | 2609 | IrInstruction *value; |
| 2558 | 2610 | }; |
| 2559 | 2611 | |
| 2560 | struct IrInstructionUnwrapOptional { | |
| 2612 | // Takes a pointer to an optional value, returns a pointer | |
| 2613 | // to the payload. | |
| 2614 | struct IrInstructionOptionalUnwrapPtr { | |
| 2561 | 2615 | IrInstruction base; |
| 2562 | 2616 | |
| 2563 | IrInstruction *value; | |
| 2617 | IrInstruction *base_ptr; | |
| 2564 | 2618 | bool safety_check_on; |
| 2565 | 2619 | }; |
| 2566 | 2620 | |
| ... | ... | @@ -2651,7 +2705,7 @@ struct IrInstructionEmbedFile { |
| 2651 | 2705 | IrInstruction *name; |
| 2652 | 2706 | }; |
| 2653 | 2707 | |
| 2654 | struct IrInstructionCmpxchg { | |
| 2708 | struct IrInstructionCmpxchgSrc { | |
| 2655 | 2709 | IrInstruction base; |
| 2656 | 2710 | |
| 2657 | 2711 | IrInstruction *type_value; |
| ... | ... | @@ -2661,14 +2715,19 @@ struct IrInstructionCmpxchg { |
| 2661 | 2715 | IrInstruction *success_order_value; |
| 2662 | 2716 | IrInstruction *failure_order_value; |
| 2663 | 2717 | |
| 2664 | // if this instruction gets to runtime then we know these values: | |
| 2665 | ZigType *type; | |
| 2666 | AtomicOrder success_order; | |
| 2667 | AtomicOrder failure_order; | |
| 2668 | ||
| 2669 | 2718 | bool is_weak; |
| 2719 | }; | |
| 2670 | 2720 | |
| 2721 | struct IrInstructionCmpxchgGen { | |
| 2722 | IrInstruction base; | |
| 2723 | ||
| 2724 | IrInstruction *ptr; | |
| 2725 | IrInstruction *cmp_value; | |
| 2726 | IrInstruction *new_value; | |
| 2671 | 2727 | LLVMValueRef tmp_ptr; |
| 2728 | AtomicOrder success_order; | |
| 2729 | AtomicOrder failure_order; | |
| 2730 | bool is_weak; | |
| 2672 | 2731 | }; |
| 2673 | 2732 | |
| 2674 | 2733 | struct IrInstructionFence { |
| ... | ... | @@ -2851,7 +2910,7 @@ struct IrInstructionTestErr { |
| 2851 | 2910 | struct IrInstructionUnwrapErrCode { |
| 2852 | 2911 | IrInstruction base; |
| 2853 | 2912 | |
| 2854 | IrInstruction *value; | |
| 2913 | IrInstruction *err_union; | |
| 2855 | 2914 | }; |
| 2856 | 2915 | |
| 2857 | 2916 | struct IrInstructionUnwrapErrPayload { |
| ... | ... | @@ -2899,13 +2958,19 @@ struct IrInstructionTestComptime { |
| 2899 | 2958 | IrInstruction *value; |
| 2900 | 2959 | }; |
| 2901 | 2960 | |
| 2902 | struct IrInstructionPtrCast { | |
| 2961 | struct IrInstructionPtrCastSrc { | |
| 2903 | 2962 | IrInstruction base; |
| 2904 | 2963 | |
| 2905 | 2964 | IrInstruction *dest_type; |
| 2906 | 2965 | IrInstruction *ptr; |
| 2907 | 2966 | }; |
| 2908 | 2967 | |
| 2968 | struct IrInstructionPtrCastGen { | |
| 2969 | IrInstruction base; | |
| 2970 | ||
| 2971 | IrInstruction *ptr; | |
| 2972 | }; | |
| 2973 | ||
| 2909 | 2974 | struct IrInstructionBitCast { |
| 2910 | 2975 | IrInstruction base; |
| 2911 | 2976 |
src/analyze.cpp+213-84| ... | ... | @@ -570,7 +570,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { |
| 570 | 570 | if (child_type->zero_bits) { |
| 571 | 571 | entry->type_ref = LLVMInt1Type(); |
| 572 | 572 | entry->di_type = g->builtin_types.entry_bool->di_type; |
| 573 | } else if (type_is_codegen_pointer(child_type)) { | |
| 573 | } else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) { | |
| 574 | 574 | assert(child_type->di_type); |
| 575 | 575 | // this is an optimization but also is necessary for calling C |
| 576 | 576 | // functions where all pointers are maybe pointers |
| ... | ... | @@ -1278,7 +1278,9 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind |
| 1278 | 1278 | return entry; |
| 1279 | 1279 | } |
| 1280 | 1280 | |
| 1281 | static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) { | |
| 1281 | static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, | |
| 1282 | Buf *type_name) | |
| 1283 | { | |
| 1282 | 1284 | size_t backward_branch_count = 0; |
| 1283 | 1285 | return ir_eval_const_value(g, scope, node, type_entry, |
| 1284 | 1286 | &backward_branch_count, default_backward_branch_quota, |
| ... | ... | @@ -1286,12 +1288,12 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod |
| 1286 | 1288 | } |
| 1287 | 1289 | |
| 1288 | 1290 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { |
| 1289 | IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); | |
| 1290 | if (result->value.type->id == ZigTypeIdInvalid) | |
| 1291 | ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); | |
| 1292 | if (type_is_invalid(result->type)) | |
| 1291 | 1293 | return g->builtin_types.entry_invalid; |
| 1292 | 1294 | |
| 1293 | assert(result->value.special != ConstValSpecialRuntime); | |
| 1294 | return result->value.data.x_type; | |
| 1295 | assert(result->special != ConstValSpecialRuntime); | |
| 1296 | return result->data.x_type; | |
| 1295 | 1297 | } |
| 1296 | 1298 | |
| 1297 | 1299 | 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 |
| 1342 | 1344 | } |
| 1343 | 1345 | |
| 1344 | 1346 | static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) { |
| 1345 | IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); | |
| 1346 | if (type_is_invalid(align_result->value.type)) | |
| 1347 | ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr); | |
| 1348 | if (type_is_invalid(align_result->type)) | |
| 1347 | 1349 | return false; |
| 1348 | 1350 | |
| 1349 | uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint); | |
| 1351 | uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint); | |
| 1350 | 1352 | if (align_bytes == 0) { |
| 1351 | 1353 | add_node_error(g, node, buf_sprintf("alignment must be >= 1")); |
| 1352 | 1354 | return false; |
| ... | ... | @@ -1364,12 +1366,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** |
| 1364 | 1366 | ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, |
| 1365 | 1367 | PtrLenUnknown, 0, 0, 0); |
| 1366 | 1368 | ZigType *str_type = get_slice_type(g, ptr_type); |
| 1367 | IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr); | |
| 1368 | if (type_is_invalid(instr->value.type)) | |
| 1369 | ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr); | |
| 1370 | if (type_is_invalid(result_val->type)) | |
| 1369 | 1371 | return false; |
| 1370 | 1372 | |
| 1371 | ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index]; | |
| 1372 | ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index]; | |
| 1373 | ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index]; | |
| 1374 | ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index]; | |
| 1373 | 1375 | |
| 1374 | 1376 | assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); |
| 1375 | 1377 | 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) { |
| 2504 | 2506 | // In this first pass we resolve explicit tag values. |
| 2505 | 2507 | // In a second pass we will fill in the unspecified ones. |
| 2506 | 2508 | if (tag_value != nullptr) { |
| 2507 | IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | |
| 2508 | if (result_inst->value.type->id == ZigTypeIdInvalid) { | |
| 2509 | ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | |
| 2510 | if (type_is_invalid(result->type)) { | |
| 2509 | 2511 | enum_type->data.enumeration.is_invalid = true; |
| 2510 | 2512 | continue; |
| 2511 | 2513 | } |
| 2512 | assert(result_inst->value.special != ConstValSpecialRuntime); | |
| 2513 | assert(result_inst->value.type->id == ZigTypeIdInt || | |
| 2514 | result_inst->value.type->id == ZigTypeIdComptimeInt); | |
| 2515 | auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); | |
| 2514 | assert(result->special != ConstValSpecialRuntime); | |
| 2515 | assert(result->type->id == ZigTypeIdInt || | |
| 2516 | result->type->id == ZigTypeIdComptimeInt); | |
| 2517 | auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); | |
| 2516 | 2518 | if (entry == nullptr) { |
| 2517 | bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint); | |
| 2519 | bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint); | |
| 2518 | 2520 | } else { |
| 2519 | 2521 | Buf *val_buf = buf_alloc(); |
| 2520 | bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); | |
| 2522 | bigint_append_buf(val_buf, &result->data.x_bigint, 10); | |
| 2521 | 2523 | |
| 2522 | 2524 | ErrorMsg *msg = add_node_error(g, tag_value, |
| 2523 | 2525 | 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) { |
| 2944 | 2946 | // In a second pass we will fill in the unspecified ones. |
| 2945 | 2947 | if (tag_value != nullptr) { |
| 2946 | 2948 | ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type; |
| 2947 | IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | |
| 2948 | if (result_inst->value.type->id == ZigTypeIdInvalid) { | |
| 2949 | ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); | |
| 2950 | if (type_is_invalid(result->type)) { | |
| 2949 | 2951 | union_type->data.unionation.is_invalid = true; |
| 2950 | 2952 | continue; |
| 2951 | 2953 | } |
| 2952 | assert(result_inst->value.special != ConstValSpecialRuntime); | |
| 2953 | assert(result_inst->value.type->id == ZigTypeIdInt); | |
| 2954 | auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value); | |
| 2954 | assert(result->special != ConstValSpecialRuntime); | |
| 2955 | assert(result->type->id == ZigTypeIdInt); | |
| 2956 | auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value); | |
| 2955 | 2957 | if (entry == nullptr) { |
| 2956 | bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint); | |
| 2958 | bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint); | |
| 2957 | 2959 | } else { |
| 2958 | 2960 | Buf *val_buf = buf_alloc(); |
| 2959 | bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10); | |
| 2961 | bigint_append_buf(val_buf, &result->data.x_bigint, 10); | |
| 2960 | 2962 | |
| 2961 | 2963 | ErrorMsg *msg = add_node_error(g, tag_value, |
| 2962 | 2964 | 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) { |
| 3419 | 3421 | resolve_top_level_decl(g, tld, false, tld->source_node); |
| 3420 | 3422 | assert(tld->id == TldIdVar); |
| 3421 | 3423 | TldVar *tld_var = (TldVar *)tld; |
| 3422 | tld_var->var->value = value; | |
| 3424 | tld_var->var->const_value = value; | |
| 3425 | tld_var->var->var_type = value->type; | |
| 3423 | 3426 | tld_var->var->align_bytes = get_abi_alignment(g, value->type); |
| 3424 | 3427 | } |
| 3425 | 3428 | |
| ... | ... | @@ -3513,7 +3516,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 3513 | 3516 | case NodeTypeArrayType: |
| 3514 | 3517 | case NodeTypeErrorType: |
| 3515 | 3518 | case NodeTypeIfErrorExpr: |
| 3516 | case NodeTypeTestExpr: | |
| 3519 | case NodeTypeIfOptional: | |
| 3517 | 3520 | case NodeTypeErrorSetDecl: |
| 3518 | 3521 | case NodeTypeCancel: |
| 3519 | 3522 | case NodeTypeResume: |
| ... | ... | @@ -3582,13 +3585,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry |
| 3582 | 3585 | // Set name to nullptr to make the variable anonymous (not visible to programmer). |
| 3583 | 3586 | // TODO merge with definition of add_local_var in ir.cpp |
| 3584 | 3587 | ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, |
| 3585 | bool is_const, ConstExprValue *value, Tld *src_tld) | |
| 3588 | bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type) | |
| 3586 | 3589 | { |
| 3587 | 3590 | Error err; |
| 3588 | assert(value); | |
| 3591 | assert(const_value != nullptr); | |
| 3592 | assert(var_type != nullptr); | |
| 3589 | 3593 | |
| 3590 | 3594 | ZigVar *variable_entry = allocate<ZigVar>(1); |
| 3591 | variable_entry->value = value; | |
| 3595 | variable_entry->const_value = const_value; | |
| 3596 | variable_entry->var_type = var_type; | |
| 3592 | 3597 | variable_entry->parent_scope = parent_scope; |
| 3593 | 3598 | variable_entry->shadowable = false; |
| 3594 | 3599 | variable_entry->mem_slot_index = SIZE_MAX; |
| ... | ... | @@ -3597,23 +3602,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf |
| 3597 | 3602 | assert(name); |
| 3598 | 3603 | buf_init_from_buf(&variable_entry->name, name); |
| 3599 | 3604 | |
| 3600 | if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) { | |
| 3601 | variable_entry->value->type = g->builtin_types.entry_invalid; | |
| 3605 | if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) { | |
| 3606 | variable_entry->var_type = g->builtin_types.entry_invalid; | |
| 3602 | 3607 | } else { |
| 3603 | variable_entry->align_bytes = get_abi_alignment(g, value->type); | |
| 3608 | variable_entry->align_bytes = get_abi_alignment(g, var_type); | |
| 3604 | 3609 | |
| 3605 | 3610 | ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr); |
| 3606 | 3611 | if (existing_var && !existing_var->shadowable) { |
| 3607 | 3612 | ErrorMsg *msg = add_node_error(g, source_node, |
| 3608 | 3613 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); |
| 3609 | 3614 | add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); |
| 3610 | variable_entry->value->type = g->builtin_types.entry_invalid; | |
| 3615 | variable_entry->var_type = g->builtin_types.entry_invalid; | |
| 3611 | 3616 | } else { |
| 3612 | 3617 | ZigType *type; |
| 3613 | 3618 | if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) { |
| 3614 | 3619 | add_node_error(g, source_node, |
| 3615 | 3620 | buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); |
| 3616 | variable_entry->value->type = g->builtin_types.entry_invalid; | |
| 3621 | variable_entry->var_type = g->builtin_types.entry_invalid; | |
| 3617 | 3622 | } else { |
| 3618 | 3623 | Scope *search_scope = nullptr; |
| 3619 | 3624 | if (src_tld == nullptr) { |
| ... | ... | @@ -3627,7 +3632,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf |
| 3627 | 3632 | ErrorMsg *msg = add_node_error(g, source_node, |
| 3628 | 3633 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 3629 | 3634 | add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here")); |
| 3630 | variable_entry->value->type = g->builtin_types.entry_invalid; | |
| 3635 | variable_entry->var_type = g->builtin_types.entry_invalid; | |
| 3631 | 3636 | } |
| 3632 | 3637 | } |
| 3633 | 3638 | } |
| ... | ... | @@ -3677,7 +3682,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3677 | 3682 | linkage = VarLinkageInternal; |
| 3678 | 3683 | } |
| 3679 | 3684 | |
| 3680 | IrInstruction *init_value = nullptr; | |
| 3685 | ConstExprValue *init_value = nullptr; | |
| 3681 | 3686 | |
| 3682 | 3687 | // TODO more validation for types that can't be used for export/extern variables |
| 3683 | 3688 | ZigType *implicit_type = nullptr; |
| ... | ... | @@ -3686,7 +3691,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3686 | 3691 | } else if (var_decl->expr) { |
| 3687 | 3692 | init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol); |
| 3688 | 3693 | assert(init_value); |
| 3689 | implicit_type = init_value->value.type; | |
| 3694 | implicit_type = init_value->type; | |
| 3690 | 3695 | |
| 3691 | 3696 | if (implicit_type->id == ZigTypeIdUnreachable) { |
| 3692 | 3697 | 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) { |
| 3704 | 3709 | add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant")); |
| 3705 | 3710 | implicit_type = g->builtin_types.entry_invalid; |
| 3706 | 3711 | } |
| 3707 | assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime); | |
| 3712 | assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime); | |
| 3708 | 3713 | } else if (linkage != VarLinkageExternal) { |
| 3709 | 3714 | add_node_error(g, source_node, buf_sprintf("variables must be initialized")); |
| 3710 | 3715 | implicit_type = g->builtin_types.entry_invalid; |
| ... | ... | @@ -3713,19 +3718,19 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3713 | 3718 | ZigType *type = explicit_type ? explicit_type : implicit_type; |
| 3714 | 3719 | assert(type != nullptr); // should have been caught by the parser |
| 3715 | 3720 | |
| 3716 | ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type); | |
| 3721 | ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type); | |
| 3717 | 3722 | |
| 3718 | 3723 | tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol, |
| 3719 | is_const, init_val, &tld_var->base); | |
| 3724 | is_const, init_val, &tld_var->base, type); | |
| 3720 | 3725 | tld_var->var->linkage = linkage; |
| 3721 | 3726 | |
| 3722 | 3727 | if (implicit_type != nullptr && type_is_invalid(implicit_type)) { |
| 3723 | tld_var->var->value->type = g->builtin_types.entry_invalid; | |
| 3728 | tld_var->var->var_type = g->builtin_types.entry_invalid; | |
| 3724 | 3729 | } |
| 3725 | 3730 | |
| 3726 | 3731 | if (var_decl->align_expr != nullptr) { |
| 3727 | 3732 | if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) { |
| 3728 | tld_var->var->value->type = g->builtin_types.entry_invalid; | |
| 3733 | tld_var->var->var_type = g->builtin_types.entry_invalid; | |
| 3729 | 3734 | } |
| 3730 | 3735 | } |
| 3731 | 3736 | |
| ... | ... | @@ -4090,7 +4095,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { |
| 4090 | 4095 | } |
| 4091 | 4096 | |
| 4092 | 4097 | ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope, |
| 4093 | param_name, true, create_const_runtime(param_type), nullptr); | |
| 4098 | param_name, true, create_const_runtime(param_type), nullptr, param_type); | |
| 4094 | 4099 | var->src_arg_index = i; |
| 4095 | 4100 | fn_table_entry->child_scope = var->child_scope; |
| 4096 | 4101 | var->shadowable = var->shadowable || is_var_args; |
| ... | ... | @@ -4228,18 +4233,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * |
| 4228 | 4233 | preview_use_decl(g, src_use_node); |
| 4229 | 4234 | } |
| 4230 | 4235 | |
| 4231 | IrInstruction *use_target_value = src_use_node->data.use.value; | |
| 4232 | if (use_target_value->value.type->id == ZigTypeIdInvalid) { | |
| 4236 | ConstExprValue *use_target_value = src_use_node->data.use.value; | |
| 4237 | if (type_is_invalid(use_target_value->type)) { | |
| 4233 | 4238 | dst_use_node->owner->any_imports_failed = true; |
| 4234 | 4239 | return; |
| 4235 | 4240 | } |
| 4236 | 4241 | |
| 4237 | 4242 | dst_use_node->data.use.resolution = TldResolutionOk; |
| 4238 | 4243 | |
| 4239 | ConstExprValue *const_val = &use_target_value->value; | |
| 4240 | assert(const_val->special != ConstValSpecialRuntime); | |
| 4244 | assert(use_target_value->special != ConstValSpecialRuntime); | |
| 4241 | 4245 | |
| 4242 | ImportTableEntry *target_import = const_val->data.x_import; | |
| 4246 | ImportTableEntry *target_import = use_target_value->data.x_import; | |
| 4243 | 4247 | assert(target_import); |
| 4244 | 4248 | |
| 4245 | 4249 | if (target_import->any_imports_failed) { |
| ... | ... | @@ -4302,10 +4306,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) { |
| 4302 | 4306 | } |
| 4303 | 4307 | |
| 4304 | 4308 | node->data.use.resolution = TldResolutionResolving; |
| 4305 | IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base, | |
| 4309 | ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base, | |
| 4306 | 4310 | node->data.use.expr, g->builtin_types.entry_namespace, nullptr); |
| 4307 | 4311 | |
| 4308 | if (result->value.type->id == ZigTypeIdInvalid) | |
| 4312 | if (type_is_invalid(result->type)) | |
| 4309 | 4313 | node->owner->any_imports_failed = true; |
| 4310 | 4314 | |
| 4311 | 4315 | node->data.use.value = result; |
| ... | ... | @@ -4486,7 +4490,8 @@ bool handle_is_ptr(ZigType *type_entry) { |
| 4486 | 4490 | return type_has_bits(type_entry->data.error_union.payload_type); |
| 4487 | 4491 | case ZigTypeIdOptional: |
| 4488 | 4492 | return type_has_bits(type_entry->data.maybe.child_type) && |
| 4489 | !type_is_codegen_pointer(type_entry->data.maybe.child_type); | |
| 4493 | !type_is_codegen_pointer(type_entry->data.maybe.child_type) && | |
| 4494 | type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet; | |
| 4490 | 4495 | case ZigTypeIdUnion: |
| 4491 | 4496 | assert(type_entry->data.unionation.zero_bits_known); |
| 4492 | 4497 | if (type_entry->data.unionation.gen_field_count == 0) |
| ... | ... | @@ -4732,6 +4737,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) { |
| 4732 | 4737 | return true; |
| 4733 | 4738 | } |
| 4734 | 4739 | |
| 4740 | static uint32_t hash_const_val_error_set(ConstExprValue *const_val) { | |
| 4741 | assert(const_val->data.x_err_set != nullptr); | |
| 4742 | return const_val->data.x_err_set->value ^ 2630160122; | |
| 4743 | } | |
| 4744 | ||
| 4735 | 4745 | static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { |
| 4736 | 4746 | uint32_t hash_val = 0; |
| 4737 | 4747 | switch (const_val->data.x_ptr.mut) { |
| ... | ... | @@ -4763,6 +4773,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) { |
| 4763 | 4773 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val); |
| 4764 | 4774 | hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index); |
| 4765 | 4775 | return hash_val; |
| 4776 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 4777 | hash_val += (uint32_t)2994743799; | |
| 4778 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val); | |
| 4779 | return hash_val; | |
| 4780 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 4781 | hash_val += (uint32_t)3456080131; | |
| 4782 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val); | |
| 4783 | return hash_val; | |
| 4784 | case ConstPtrSpecialBaseOptionalPayload: | |
| 4785 | hash_val += (uint32_t)3163140517; | |
| 4786 | hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val); | |
| 4787 | return hash_val; | |
| 4766 | 4788 | case ConstPtrSpecialHardCodedAddr: |
| 4767 | 4789 | hash_val += (uint32_t)4048518294; |
| 4768 | 4790 | 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) { |
| 4774 | 4796 | hash_val += (uint32_t)2590901619; |
| 4775 | 4797 | hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry); |
| 4776 | 4798 | return hash_val; |
| 4799 | case ConstPtrSpecialNull: | |
| 4800 | hash_val += (uint32_t)1486246455; | |
| 4801 | return hash_val; | |
| 4777 | 4802 | } |
| 4778 | 4803 | zig_unreachable(); |
| 4779 | 4804 | } |
| ... | ... | @@ -4872,7 +4897,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4872 | 4897 | return 2709806591; |
| 4873 | 4898 | case ZigTypeIdOptional: |
| 4874 | 4899 | if (get_codegen_ptr_type(const_val->type) != nullptr) { |
| 4875 | return hash_const_val(const_val) * 1992916303; | |
| 4900 | return hash_const_val_ptr(const_val) * 1992916303; | |
| 4901 | } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) { | |
| 4902 | return hash_const_val_error_set(const_val) * 3147031929; | |
| 4876 | 4903 | } else { |
| 4877 | 4904 | if (const_val->data.x_optional) { |
| 4878 | 4905 | return hash_const_val(const_val->data.x_optional) * 1992916303; |
| ... | ... | @@ -4884,8 +4911,7 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 4884 | 4911 | // TODO better hashing algorithm |
| 4885 | 4912 | return 3415065496; |
| 4886 | 4913 | case ZigTypeIdErrorSet: |
| 4887 | assert(const_val->data.x_err_set != nullptr); | |
| 4888 | return const_val->data.x_err_set->value ^ 2630160122; | |
| 4914 | return hash_const_val_error_set(const_val); | |
| 4889 | 4915 | case ZigTypeIdNamespace: |
| 4890 | 4916 | return hash_ptr(const_val->data.x_import); |
| 4891 | 4917 | case ZigTypeIdBoundFn: |
| ... | ... | @@ -4987,7 +5013,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { |
| 4987 | 5013 | return can_mutate_comptime_var_state(value->data.x_optional); |
| 4988 | 5014 | |
| 4989 | 5015 | case ZigTypeIdErrorUnion: |
| 4990 | if (value->data.x_err_union.err != nullptr) | |
| 5016 | if (value->data.x_err_union.error_set->data.x_err_set != nullptr) | |
| 4991 | 5017 | return false; |
| 4992 | 5018 | assert(value->data.x_err_union.payload != nullptr); |
| 4993 | 5019 | 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) { |
| 5048 | 5074 | while (scope) { |
| 5049 | 5075 | if (scope->id == ScopeIdVarDecl) { |
| 5050 | 5076 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; |
| 5051 | if (type_is_invalid(var_scope->var->value->type)) | |
| 5077 | if (type_is_invalid(var_scope->var->var_type)) | |
| 5052 | 5078 | return false; |
| 5053 | if (can_mutate_comptime_var_state(var_scope->var->value)) | |
| 5079 | if (can_mutate_comptime_var_state(var_scope->var->const_value)) | |
| 5054 | 5080 | return false; |
| 5055 | 5081 | } else if (scope->id == ScopeIdFnDef) { |
| 5056 | 5082 | return true; |
| ... | ... | @@ -5068,7 +5094,7 @@ uint32_t fn_eval_hash(Scope* scope) { |
| 5068 | 5094 | while (scope) { |
| 5069 | 5095 | if (scope->id == ScopeIdVarDecl) { |
| 5070 | 5096 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; |
| 5071 | result += hash_const_val(var_scope->var->value); | |
| 5097 | result += hash_const_val(var_scope->var->const_value); | |
| 5072 | 5098 | } else if (scope->id == ScopeIdFnDef) { |
| 5073 | 5099 | ScopeFnDef *fn_scope = (ScopeFnDef *)scope; |
| 5074 | 5100 | result += hash_ptr(fn_scope->fn_entry); |
| ... | ... | @@ -5092,10 +5118,16 @@ bool fn_eval_eql(Scope *a, Scope *b) { |
| 5092 | 5118 | if (a->id == ScopeIdVarDecl) { |
| 5093 | 5119 | ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a; |
| 5094 | 5120 | ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b; |
| 5095 | if (a_var_scope->var->value->type != b_var_scope->var->value->type) | |
| 5096 | return false; | |
| 5097 | if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value)) | |
| 5121 | if (a_var_scope->var->var_type != b_var_scope->var->var_type) | |
| 5098 | 5122 | return false; |
| 5123 | if (a_var_scope->var->var_type == a_var_scope->var->const_value->type && | |
| 5124 | b_var_scope->var->var_type == b_var_scope->var->const_value->type) | |
| 5125 | { | |
| 5126 | if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value)) | |
| 5127 | return false; | |
| 5128 | } else { | |
| 5129 | zig_panic("TODO comptime ptr reinterpret for fn_eval_eql"); | |
| 5130 | } | |
| 5099 | 5131 | } else if (a->id == ScopeIdFnDef) { |
| 5100 | 5132 | ScopeFnDef *a_fn_scope = (ScopeFnDef *)a; |
| 5101 | 5133 | ScopeFnDef *b_fn_scope = (ScopeFnDef *)b; |
| ... | ... | @@ -5113,6 +5145,7 @@ bool fn_eval_eql(Scope *a, Scope *b) { |
| 5113 | 5145 | return false; |
| 5114 | 5146 | } |
| 5115 | 5147 | |
| 5148 | // Whether the type has bits at runtime. | |
| 5116 | 5149 | bool type_has_bits(ZigType *type_entry) { |
| 5117 | 5150 | assert(type_entry); |
| 5118 | 5151 | assert(!type_is_invalid(type_entry)); |
| ... | ... | @@ -5120,6 +5153,65 @@ bool type_has_bits(ZigType *type_entry) { |
| 5120 | 5153 | return !type_entry->zero_bits; |
| 5121 | 5154 | } |
| 5122 | 5155 | |
| 5156 | // Whether you can infer the value based solely on the type. | |
| 5157 | OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { | |
| 5158 | assert(type_entry != nullptr); | |
| 5159 | Error err; | |
| 5160 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) | |
| 5161 | return OnePossibleValueInvalid; | |
| 5162 | switch (type_entry->id) { | |
| 5163 | case ZigTypeIdInvalid: | |
| 5164 | zig_unreachable(); | |
| 5165 | case ZigTypeIdOpaque: | |
| 5166 | case ZigTypeIdComptimeFloat: | |
| 5167 | case ZigTypeIdComptimeInt: | |
| 5168 | case ZigTypeIdMetaType: | |
| 5169 | case ZigTypeIdNamespace: | |
| 5170 | case ZigTypeIdBoundFn: | |
| 5171 | case ZigTypeIdArgTuple: | |
| 5172 | case ZigTypeIdOptional: | |
| 5173 | case ZigTypeIdFn: | |
| 5174 | case ZigTypeIdBool: | |
| 5175 | case ZigTypeIdFloat: | |
| 5176 | case ZigTypeIdPromise: | |
| 5177 | case ZigTypeIdErrorUnion: | |
| 5178 | return OnePossibleValueNo; | |
| 5179 | case ZigTypeIdUndefined: | |
| 5180 | case ZigTypeIdNull: | |
| 5181 | case ZigTypeIdVoid: | |
| 5182 | case ZigTypeIdUnreachable: | |
| 5183 | return OnePossibleValueYes; | |
| 5184 | case ZigTypeIdArray: | |
| 5185 | if (type_entry->data.array.len == 0) | |
| 5186 | return OnePossibleValueYes; | |
| 5187 | return type_has_one_possible_value(g, type_entry->data.array.child_type); | |
| 5188 | case ZigTypeIdStruct: | |
| 5189 | for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { | |
| 5190 | TypeStructField *field = &type_entry->data.structure.fields[i]; | |
| 5191 | switch (type_has_one_possible_value(g, field->type_entry)) { | |
| 5192 | case OnePossibleValueInvalid: | |
| 5193 | return OnePossibleValueInvalid; | |
| 5194 | case OnePossibleValueNo: | |
| 5195 | return OnePossibleValueNo; | |
| 5196 | case OnePossibleValueYes: | |
| 5197 | continue; | |
| 5198 | } | |
| 5199 | } | |
| 5200 | return OnePossibleValueYes; | |
| 5201 | case ZigTypeIdErrorSet: | |
| 5202 | case ZigTypeIdEnum: | |
| 5203 | case ZigTypeIdInt: | |
| 5204 | return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes; | |
| 5205 | case ZigTypeIdPointer: | |
| 5206 | return type_has_one_possible_value(g, type_entry->data.pointer.child_type); | |
| 5207 | case ZigTypeIdUnion: | |
| 5208 | if (type_entry->data.unionation.src_field_count > 1) | |
| 5209 | return OnePossibleValueNo; | |
| 5210 | return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry); | |
| 5211 | } | |
| 5212 | zig_unreachable(); | |
| 5213 | } | |
| 5214 | ||
| 5123 | 5215 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) { |
| 5124 | 5216 | Error err; |
| 5125 | 5217 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) |
| ... | ... | @@ -5574,6 +5666,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { |
| 5574 | 5666 | if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index) |
| 5575 | 5667 | return false; |
| 5576 | 5668 | return true; |
| 5669 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 5670 | if (a->data.x_ptr.data.base_err_union_code.err_union_val != | |
| 5671 | b->data.x_ptr.data.base_err_union_code.err_union_val && | |
| 5672 | a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs != | |
| 5673 | b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs) | |
| 5674 | { | |
| 5675 | return false; | |
| 5676 | } | |
| 5677 | return true; | |
| 5678 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 5679 | if (a->data.x_ptr.data.base_err_union_payload.err_union_val != | |
| 5680 | b->data.x_ptr.data.base_err_union_payload.err_union_val && | |
| 5681 | a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs != | |
| 5682 | b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs) | |
| 5683 | { | |
| 5684 | return false; | |
| 5685 | } | |
| 5686 | return true; | |
| 5687 | case ConstPtrSpecialBaseOptionalPayload: | |
| 5688 | if (a->data.x_ptr.data.base_optional_payload.optional_val != | |
| 5689 | b->data.x_ptr.data.base_optional_payload.optional_val && | |
| 5690 | a->data.x_ptr.data.base_optional_payload.optional_val->global_refs != | |
| 5691 | b->data.x_ptr.data.base_optional_payload.optional_val->global_refs) | |
| 5692 | { | |
| 5693 | return false; | |
| 5694 | } | |
| 5695 | return true; | |
| 5577 | 5696 | case ConstPtrSpecialHardCodedAddr: |
| 5578 | 5697 | if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr) |
| 5579 | 5698 | return false; |
| ... | ... | @@ -5582,6 +5701,8 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { |
| 5582 | 5701 | return true; |
| 5583 | 5702 | case ConstPtrSpecialFunction: |
| 5584 | 5703 | return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry; |
| 5704 | case ConstPtrSpecialNull: | |
| 5705 | return true; | |
| 5585 | 5706 | } |
| 5586 | 5707 | zig_unreachable(); |
| 5587 | 5708 | } |
| ... | ... | @@ -5750,7 +5871,7 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v |
| 5750 | 5871 | } |
| 5751 | 5872 | } |
| 5752 | 5873 | |
| 5753 | void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { | |
| 5874 | static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { | |
| 5754 | 5875 | assert(type_entry->id == ZigTypeIdPointer); |
| 5755 | 5876 | |
| 5756 | 5877 | 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 |
| 5763 | 5884 | zig_unreachable(); |
| 5764 | 5885 | case ConstPtrSpecialRef: |
| 5765 | 5886 | case ConstPtrSpecialBaseStruct: |
| 5887 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 5888 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 5889 | case ConstPtrSpecialBaseOptionalPayload: | |
| 5766 | 5890 | buf_appendf(buf, "*"); |
| 5767 | 5891 | // TODO we need a source node for const_ptr_pointee because it can generate compile errors |
| 5768 | 5892 | 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 |
| 5790 | 5914 | buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name)); |
| 5791 | 5915 | return; |
| 5792 | 5916 | } |
| 5917 | case ConstPtrSpecialNull: | |
| 5918 | buf_append_str(buf, "null"); | |
| 5919 | return; | |
| 5793 | 5920 | } |
| 5794 | 5921 | zig_unreachable(); |
| 5795 | 5922 | } |
| 5796 | 5923 | |
| 5924 | static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) { | |
| 5925 | if (const_val->data.x_err_set == nullptr) { | |
| 5926 | buf_append_str(buf, "null"); | |
| 5927 | } else { | |
| 5928 | buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name)); | |
| 5929 | } | |
| 5930 | } | |
| 5931 | ||
| 5797 | 5932 | void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5798 | 5933 | switch (const_val->special) { |
| 5799 | 5934 | case ConstValSpecialRuntime: |
| ... | ... | @@ -5921,6 +6056,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5921 | 6056 | { |
| 5922 | 6057 | if (get_codegen_ptr_type(const_val->type) != nullptr) |
| 5923 | 6058 | return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type); |
| 6059 | if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet) | |
| 6060 | return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type); | |
| 5924 | 6061 | if (const_val->data.x_optional) { |
| 5925 | 6062 | render_const_value(g, buf, const_val->data.x_optional); |
| 5926 | 6063 | } else { |
| ... | ... | @@ -5958,11 +6095,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5958 | 6095 | case ZigTypeIdErrorUnion: |
| 5959 | 6096 | { |
| 5960 | 6097 | buf_appendf(buf, "%s(", buf_ptr(&type_entry->name)); |
| 5961 | if (const_val->data.x_err_union.err == nullptr) { | |
| 6098 | ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; | |
| 6099 | if (err_set == nullptr) { | |
| 5962 | 6100 | render_const_value(g, buf, const_val->data.x_err_union.payload); |
| 5963 | 6101 | } else { |
| 5964 | 6102 | buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name), |
| 5965 | buf_ptr(&const_val->data.x_err_union.err->name)); | |
| 6103 | buf_ptr(&err_set->name)); | |
| 5966 | 6104 | } |
| 5967 | 6105 | buf_appendf(buf, ")"); |
| 5968 | 6106 | return; |
| ... | ... | @@ -5977,10 +6115,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { |
| 5977 | 6115 | return; |
| 5978 | 6116 | } |
| 5979 | 6117 | case ZigTypeIdErrorSet: |
| 5980 | { | |
| 5981 | buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name)); | |
| 5982 | return; | |
| 5983 | } | |
| 6118 | return render_const_val_err_set(g, buf, const_val, type_entry); | |
| 5984 | 6119 | case ZigTypeIdArgTuple: |
| 5985 | 6120 | { |
| 5986 | 6121 | buf_appendf(buf, "(args value)"); |
| ... | ... | @@ -6172,6 +6307,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) { |
| 6172 | 6307 | // Canonicalize the array value as ConstArraySpecialNone |
| 6173 | 6308 | void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6174 | 6309 | assert(const_val->type->id == ZigTypeIdArray); |
| 6310 | if (const_val->special == ConstValSpecialUndef) { | |
| 6311 | const_val->special = ConstValSpecialStatic; | |
| 6312 | const_val->data.x_array.special = ConstArraySpecialUndef; | |
| 6313 | } | |
| 6175 | 6314 | switch (const_val->data.x_array.special) { |
| 6176 | 6315 | case ConstArraySpecialNone: |
| 6177 | 6316 | return; |
| ... | ... | @@ -6215,17 +6354,7 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) { |
| 6215 | 6354 | } |
| 6216 | 6355 | |
| 6217 | 6356 | ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) { |
| 6218 | assert(value->type); | |
| 6219 | ZigType *type_entry = value->type; | |
| 6220 | if (type_entry->id == ZigTypeIdArray) { | |
| 6221 | expand_undef_array(g, value); | |
| 6222 | return &value->data.x_array.data.s_none.parent; | |
| 6223 | } else if (type_entry->id == ZigTypeIdStruct) { | |
| 6224 | return &value->data.x_struct.parent; | |
| 6225 | } else if (type_entry->id == ZigTypeIdUnion) { | |
| 6226 | return &value->data.x_union.parent; | |
| 6227 | } | |
| 6228 | return nullptr; | |
| 6357 | return &value->parent; | |
| 6229 | 6358 | } |
| 6230 | 6359 | |
| 6231 | 6360 | static const ZigTypeId all_type_ids[] = { |
| ... | ... | @@ -6453,7 +6582,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { |
| 6453 | 6582 | resolve_top_level_decl(codegen, tld, false, nullptr); |
| 6454 | 6583 | assert(tld->id == TldIdVar); |
| 6455 | 6584 | TldVar *tld_var = (TldVar *)tld; |
| 6456 | ConstExprValue *var_value = tld_var->var->value; | |
| 6585 | ConstExprValue *var_value = tld_var->var->const_value; | |
| 6457 | 6586 | assert(var_value != nullptr); |
| 6458 | 6587 | return var_value; |
| 6459 | 6588 | } |
src/analyze.hpp+8-1| ... | ... | @@ -81,7 +81,7 @@ ZigFn *scope_fn_entry(Scope *scope); |
| 81 | 81 | ImportTableEntry *get_scope_import(Scope *scope); |
| 82 | 82 | void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope); |
| 83 | 83 | ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, |
| 84 | bool is_const, ConstExprValue *init_value, Tld *src_tld); | |
| 84 | bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type); | |
| 85 | 85 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node); |
| 86 | 86 | ZigFn *create_fn(CodeGen *g, AstNode *proto_node); |
| 87 | 87 | ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value); |
| ... | ... | @@ -222,6 +222,13 @@ enum ReqCompTime { |
| 222 | 222 | }; |
| 223 | 223 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry); |
| 224 | 224 | |
| 225 | enum OnePossibleValue { | |
| 226 | OnePossibleValueInvalid, | |
| 227 | OnePossibleValueNo, | |
| 228 | OnePossibleValueYes, | |
| 229 | }; | |
| 230 | OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry); | |
| 231 | ||
| 225 | 232 | Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, |
| 226 | 233 | ConstExprValue *const_val, ZigType *wanted_type); |
| 227 | 234 |
src/ast_render.cpp+4-4| ... | ... | @@ -233,8 +233,8 @@ static const char *node_type_str(NodeType node_type) { |
| 233 | 233 | return "ErrorType"; |
| 234 | 234 | case NodeTypeIfErrorExpr: |
| 235 | 235 | return "IfErrorExpr"; |
| 236 | case NodeTypeTestExpr: | |
| 237 | return "TestExpr"; | |
| 236 | case NodeTypeIfOptional: | |
| 237 | return "IfOptional"; | |
| 238 | 238 | case NodeTypeErrorSetDecl: |
| 239 | 239 | return "ErrorSetDecl"; |
| 240 | 240 | case NodeTypeCancel: |
| ... | ... | @@ -387,7 +387,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) { |
| 387 | 387 | if (node->data.if_err_expr.else_node) |
| 388 | 388 | return statement_terminates_without_semicolon(node->data.if_err_expr.else_node); |
| 389 | 389 | return node->data.if_err_expr.then_node->type == NodeTypeBlock; |
| 390 | case NodeTypeTestExpr: | |
| 390 | case NodeTypeIfOptional: | |
| 391 | 391 | if (node->data.test_expr.else_node) |
| 392 | 392 | return statement_terminates_without_semicolon(node->data.test_expr.else_node); |
| 393 | 393 | return node->data.test_expr.then_node->type == NodeTypeBlock; |
| ... | ... | @@ -974,7 +974,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 974 | 974 | } |
| 975 | 975 | break; |
| 976 | 976 | } |
| 977 | case NodeTypeTestExpr: | |
| 977 | case NodeTypeIfOptional: | |
| 978 | 978 | { |
| 979 | 979 | fprintf(ar->f, "if ("); |
| 980 | 980 | render_node_grouped(ar, node->data.test_expr.target_node); |
src/codegen.cpp+285-100| ... | ... | @@ -313,6 +313,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char * |
| 313 | 313 | static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name); |
| 314 | 314 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name); |
| 315 | 315 | static void generate_error_name_table(CodeGen *g); |
| 316 | static bool value_is_all_undef(ConstExprValue *const_val); | |
| 317 | static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr); | |
| 316 | 318 | |
| 317 | 319 | static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) { |
| 318 | 320 | unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name)); |
| ... | ... | @@ -461,6 +463,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag |
| 461 | 463 | } |
| 462 | 464 | } |
| 463 | 465 | |
| 466 | static bool cc_want_sret_attr(CallingConvention cc) { | |
| 467 | switch (cc) { | |
| 468 | case CallingConventionNaked: | |
| 469 | zig_unreachable(); | |
| 470 | case CallingConventionC: | |
| 471 | case CallingConventionCold: | |
| 472 | case CallingConventionStdcall: | |
| 473 | return true; | |
| 474 | case CallingConventionAsync: | |
| 475 | case CallingConventionUnspecified: | |
| 476 | return false; | |
| 477 | } | |
| 478 | zig_unreachable(); | |
| 479 | } | |
| 480 | ||
| 464 | 481 | static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 465 | 482 | if (fn_table_entry->llvm_value) |
| 466 | 483 | return fn_table_entry->llvm_value; |
| ... | ... | @@ -598,9 +615,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 598 | 615 | } else if (type_is_codegen_pointer(return_type)) { |
| 599 | 616 | addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); |
| 600 | 617 | } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) { |
| 601 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); | |
| 602 | 618 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull"); |
| 603 | if (cc == CallingConventionC) { | |
| 619 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); | |
| 620 | if (cc_want_sret_attr(cc)) { | |
| 604 | 621 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias"); |
| 605 | 622 | } |
| 606 | 623 | init_gen_i = 1; |
| ... | ... | @@ -2200,10 +2217,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { |
| 2200 | 2217 | assert(variable); |
| 2201 | 2218 | assert(variable->value_ref); |
| 2202 | 2219 | |
| 2203 | if (!handle_is_ptr(variable->value->type)) { | |
| 2220 | if (!handle_is_ptr(variable->var_type)) { | |
| 2204 | 2221 | clear_debug_source_node(g); |
| 2205 | gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref, | |
| 2206 | variable->align_bytes, false); | |
| 2222 | gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), | |
| 2223 | variable->value_ref, variable->align_bytes, false); | |
| 2207 | 2224 | } |
| 2208 | 2225 | |
| 2209 | 2226 | if (variable->decl_node) { |
| ... | ... | @@ -2961,7 +2978,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, |
| 2961 | 2978 | } |
| 2962 | 2979 | |
| 2963 | 2980 | static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, |
| 2964 | IrInstructionPtrCast *instruction) | |
| 2981 | IrInstructionPtrCastGen *instruction) | |
| 2965 | 2982 | { |
| 2966 | 2983 | ZigType *wanted_type = instruction->base.value.type; |
| 2967 | 2984 | if (!type_has_bits(wanted_type)) { |
| ... | ... | @@ -3149,11 +3166,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI |
| 3149 | 3166 | } |
| 3150 | 3167 | |
| 3151 | 3168 | static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 3152 | IrInstructionDeclVar *decl_var_instruction) | |
| 3169 | IrInstructionDeclVarGen *decl_var_instruction) | |
| 3153 | 3170 | { |
| 3154 | 3171 | ZigVar *var = decl_var_instruction->var; |
| 3155 | 3172 | |
| 3156 | if (!type_has_bits(var->value->type)) | |
| 3173 | if (!type_has_bits(var->var_type)) | |
| 3157 | 3174 | return nullptr; |
| 3158 | 3175 | |
| 3159 | 3176 | if (var->ref_count == 0 && g->build_mode != BuildModeDebug) |
| ... | ... | @@ -3161,34 +3178,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, |
| 3161 | 3178 | |
| 3162 | 3179 | IrInstruction *init_value = decl_var_instruction->init_value; |
| 3163 | 3180 | |
| 3164 | bool have_init_expr = false; | |
| 3165 | ||
| 3166 | ConstExprValue *const_val = &init_value->value; | |
| 3167 | if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic) | |
| 3168 | have_init_expr = true; | |
| 3181 | bool have_init_expr = !value_is_all_undef(&init_value->value); | |
| 3169 | 3182 | |
| 3170 | 3183 | if (have_init_expr) { |
| 3171 | assert(var->value->type == init_value->value.type); | |
| 3172 | ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false, | |
| 3184 | ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false, | |
| 3173 | 3185 | PtrLenSingle, var->align_bytes, 0, 0); |
| 3174 | 3186 | LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value); |
| 3175 | 3187 | gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val); |
| 3176 | } else { | |
| 3177 | bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base); | |
| 3178 | if (want_safe) { | |
| 3179 | ZigType *usize = g->builtin_types.entry_usize; | |
| 3180 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref); | |
| 3181 | assert(size_bytes > 0); | |
| 3182 | ||
| 3183 | assert(var->align_bytes > 0); | |
| 3184 | ||
| 3185 | // memset uninitialized memory to 0xa | |
| 3186 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | |
| 3187 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); | |
| 3188 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, ""); | |
| 3189 | LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); | |
| 3190 | ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false); | |
| 3191 | } | |
| 3188 | } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) { | |
| 3189 | uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes; | |
| 3190 | gen_undef_init(g, align_bytes, var->var_type, var->value_ref); | |
| 3192 | 3191 | } |
| 3193 | 3192 | |
| 3194 | 3193 | gen_var_debug_decl(g, var); |
| ... | ... | @@ -3225,21 +3224,75 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3225 | 3224 | return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, ""); |
| 3226 | 3225 | } |
| 3227 | 3226 | |
| 3228 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { | |
| 3229 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); | |
| 3230 | LLVMValueRef value = ir_llvm_value(g, instruction->value); | |
| 3227 | static bool value_is_all_undef(ConstExprValue *const_val) { | |
| 3228 | switch (const_val->special) { | |
| 3229 | case ConstValSpecialRuntime: | |
| 3230 | return false; | |
| 3231 | case ConstValSpecialUndef: | |
| 3232 | return true; | |
| 3233 | case ConstValSpecialStatic: | |
| 3234 | if (const_val->type->id == ZigTypeIdStruct) { | |
| 3235 | for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) { | |
| 3236 | if (!value_is_all_undef(&const_val->data.x_struct.fields[i])) | |
| 3237 | return false; | |
| 3238 | } | |
| 3239 | return true; | |
| 3240 | } else if (const_val->type->id == ZigTypeIdArray) { | |
| 3241 | switch (const_val->data.x_array.special) { | |
| 3242 | case ConstArraySpecialUndef: | |
| 3243 | return true; | |
| 3244 | case ConstArraySpecialBuf: | |
| 3245 | return false; | |
| 3246 | case ConstArraySpecialNone: | |
| 3247 | for (size_t i = 0; i < const_val->type->data.array.len; i += 1) { | |
| 3248 | if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i])) | |
| 3249 | return false; | |
| 3250 | } | |
| 3251 | return true; | |
| 3252 | } | |
| 3253 | zig_unreachable(); | |
| 3254 | } else { | |
| 3255 | return false; | |
| 3256 | } | |
| 3257 | } | |
| 3258 | zig_unreachable(); | |
| 3259 | } | |
| 3231 | 3260 | |
| 3232 | assert(instruction->ptr->value.type->id == ZigTypeIdPointer); | |
| 3233 | ZigType *ptr_type = instruction->ptr->value.type; | |
| 3261 | static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) { | |
| 3262 | assert(type_has_bits(value_type)); | |
| 3263 | uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref); | |
| 3264 | assert(size_bytes > 0); | |
| 3265 | assert(ptr_align_bytes > 0); | |
| 3266 | // memset uninitialized memory to 0xaa | |
| 3267 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | |
| 3268 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); | |
| 3269 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, ""); | |
| 3270 | ZigType *usize = g->builtin_types.entry_usize; | |
| 3271 | LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); | |
| 3272 | ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false); | |
| 3273 | } | |
| 3234 | 3274 | |
| 3235 | gen_assign_raw(g, ptr, ptr_type, value); | |
| 3275 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { | |
| 3276 | ZigType *ptr_type = instruction->ptr->value.type; | |
| 3277 | assert(ptr_type->id == ZigTypeIdPointer); | |
| 3278 | if (!type_has_bits(ptr_type)) | |
| 3279 | return nullptr; | |
| 3236 | 3280 | |
| 3281 | bool have_init_expr = !value_is_all_undef(&instruction->value->value); | |
| 3282 | if (have_init_expr) { | |
| 3283 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); | |
| 3284 | LLVMValueRef value = ir_llvm_value(g, instruction->value); | |
| 3285 | gen_assign_raw(g, ptr, ptr_type, value); | |
| 3286 | } else if (ir_want_runtime_safety(g, &instruction->base)) { | |
| 3287 | gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type, | |
| 3288 | ir_llvm_value(g, instruction->ptr)); | |
| 3289 | } | |
| 3237 | 3290 | return nullptr; |
| 3238 | 3291 | } |
| 3239 | 3292 | |
| 3240 | 3293 | static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) { |
| 3241 | 3294 | ZigVar *var = instruction->var; |
| 3242 | if (type_has_bits(var->value->type)) { | |
| 3295 | if (type_has_bits(var->var_type)) { | |
| 3243 | 3296 | assert(var->value_ref); |
| 3244 | 3297 | return var->value_ref; |
| 3245 | 3298 | } else { |
| ... | ... | @@ -3553,7 +3606,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab |
| 3553 | 3606 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 3554 | 3607 | } |
| 3555 | 3608 | |
| 3556 | LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, ""); | |
| 3609 | LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, | |
| 3610 | union_type->data.unionation.gen_union_index, ""); | |
| 3557 | 3611 | LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); |
| 3558 | 3612 | return bitcasted_union_field_ptr; |
| 3559 | 3613 | } |
| ... | ... | @@ -3715,8 +3769,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR |
| 3715 | 3769 | if (child_type->zero_bits) { |
| 3716 | 3770 | return maybe_handle; |
| 3717 | 3771 | } else { |
| 3718 | bool maybe_is_ptr = type_is_codegen_pointer(child_type); | |
| 3719 | if (maybe_is_ptr) { | |
| 3772 | bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet; | |
| 3773 | if (is_scalar) { | |
| 3720 | 3774 | return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), ""); |
| 3721 | 3775 | } else { |
| 3722 | 3776 | 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 |
| 3731 | 3785 | return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value)); |
| 3732 | 3786 | } |
| 3733 | 3787 | |
| 3734 | static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, | |
| 3735 | IrInstructionUnwrapOptional *instruction) | |
| 3788 | static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable, | |
| 3789 | IrInstructionOptionalUnwrapPtr *instruction) | |
| 3736 | 3790 | { |
| 3737 | ZigType *ptr_type = instruction->value->value.type; | |
| 3791 | ZigType *ptr_type = instruction->base_ptr->value.type; | |
| 3738 | 3792 | assert(ptr_type->id == ZigTypeIdPointer); |
| 3739 | 3793 | ZigType *maybe_type = ptr_type->data.pointer.child_type; |
| 3740 | 3794 | assert(maybe_type->id == ZigTypeIdOptional); |
| 3741 | 3795 | ZigType *child_type = maybe_type->data.maybe.child_type; |
| 3742 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); | |
| 3743 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); | |
| 3796 | LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr); | |
| 3744 | 3797 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) { |
| 3798 | LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type); | |
| 3745 | 3799 | LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle); |
| 3746 | 3800 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk"); |
| 3747 | 3801 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail"); |
| ... | ... | @@ -3755,8 +3809,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, |
| 3755 | 3809 | if (child_type->zero_bits) { |
| 3756 | 3810 | return nullptr; |
| 3757 | 3811 | } else { |
| 3758 | bool maybe_is_ptr = type_is_codegen_pointer(child_type); | |
| 3759 | if (maybe_is_ptr) { | |
| 3812 | bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet; | |
| 3813 | if (is_scalar) { | |
| 3760 | 3814 | return maybe_ptr; |
| 3761 | 3815 | } else { |
| 3762 | 3816 | 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) |
| 4174 | 4228 | zig_unreachable(); |
| 4175 | 4229 | } |
| 4176 | 4230 | |
| 4177 | static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) { | |
| 4231 | static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) { | |
| 4178 | 4232 | LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr); |
| 4179 | 4233 | LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value); |
| 4180 | 4234 | LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value); |
| ... | ... | @@ -4189,18 +4243,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn |
| 4189 | 4243 | assert(maybe_type->id == ZigTypeIdOptional); |
| 4190 | 4244 | ZigType *child_type = maybe_type->data.maybe.child_type; |
| 4191 | 4245 | |
| 4192 | if (type_is_codegen_pointer(child_type)) { | |
| 4246 | if (!handle_is_ptr(maybe_type)) { | |
| 4193 | 4247 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); |
| 4194 | 4248 | LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); |
| 4195 | 4249 | return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, ""); |
| 4196 | 4250 | } |
| 4197 | 4251 | |
| 4198 | 4252 | assert(instruction->tmp_ptr != nullptr); |
| 4199 | assert(type_has_bits(instruction->type)); | |
| 4253 | assert(type_has_bits(child_type)); | |
| 4200 | 4254 | |
| 4201 | 4255 | LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); |
| 4202 | 4256 | LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, ""); |
| 4203 | gen_assign_raw(g, val_ptr, get_pointer_to_type(g, instruction->type, false), payload_val); | |
| 4257 | gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val); | |
| 4204 | 4258 | |
| 4205 | 4259 | LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); |
| 4206 | 4260 | LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, ""); |
| ... | ... | @@ -4351,6 +4405,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst |
| 4351 | 4405 | assert(array_type->data.structure.is_slice); |
| 4352 | 4406 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); |
| 4353 | 4407 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); |
| 4408 | assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind); | |
| 4354 | 4409 | |
| 4355 | 4410 | size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index; |
| 4356 | 4411 | assert(ptr_index != SIZE_MAX); |
| ... | ... | @@ -4540,12 +4595,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI |
| 4540 | 4595 | return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, ""); |
| 4541 | 4596 | } |
| 4542 | 4597 | |
| 4543 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) { | |
| 4544 | ZigType *ptr_type = instruction->value->value.type; | |
| 4598 | static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, | |
| 4599 | IrInstructionUnwrapErrCode *instruction) | |
| 4600 | { | |
| 4601 | ZigType *ptr_type = instruction->err_union->value.type; | |
| 4545 | 4602 | assert(ptr_type->id == ZigTypeIdPointer); |
| 4546 | 4603 | ZigType *err_union_type = ptr_type->data.pointer.child_type; |
| 4547 | 4604 | ZigType *payload_type = err_union_type->data.error_union.payload_type; |
| 4548 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value); | |
| 4605 | LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union); | |
| 4549 | 4606 | LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); |
| 4550 | 4607 | |
| 4551 | 4608 | if (type_has_bits(payload_type)) { |
| ... | ... | @@ -4556,7 +4613,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab |
| 4556 | 4613 | } |
| 4557 | 4614 | } |
| 4558 | 4615 | |
| 4559 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) { | |
| 4616 | static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, | |
| 4617 | IrInstructionUnwrapErrPayload *instruction) | |
| 4618 | { | |
| 4619 | bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && | |
| 4620 | g->errors_by_index.length > 1; | |
| 4621 | if (!want_safety && !type_has_bits(instruction->base.value.type)) | |
| 4622 | return nullptr; | |
| 4560 | 4623 | ZigType *ptr_type = instruction->value->value.type; |
| 4561 | 4624 | assert(ptr_type->id == ZigTypeIdPointer); |
| 4562 | 4625 | 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 |
| 4568 | 4631 | return err_union_handle; |
| 4569 | 4632 | } |
| 4570 | 4633 | |
| 4571 | if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) { | |
| 4634 | if (want_safety) { | |
| 4572 | 4635 | LLVMValueRef err_val; |
| 4573 | 4636 | if (type_has_bits(payload_type)) { |
| 4574 | 4637 | 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 |
| 4607 | 4670 | } |
| 4608 | 4671 | |
| 4609 | 4672 | LLVMValueRef payload_val = ir_llvm_value(g, instruction->value); |
| 4610 | if (type_is_codegen_pointer(child_type)) { | |
| 4673 | if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) { | |
| 4611 | 4674 | return payload_val; |
| 4612 | 4675 | } |
| 4613 | 4676 | |
| ... | ... | @@ -5184,12 +5247,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5184 | 5247 | case IrInstructionIdToBytes: |
| 5185 | 5248 | case IrInstructionIdEnumToInt: |
| 5186 | 5249 | case IrInstructionIdCheckRuntimeScope: |
| 5250 | case IrInstructionIdDeclVarSrc: | |
| 5251 | case IrInstructionIdPtrCastSrc: | |
| 5252 | case IrInstructionIdCmpxchgSrc: | |
| 5187 | 5253 | zig_unreachable(); |
| 5188 | 5254 | |
| 5255 | case IrInstructionIdDeclVarGen: | |
| 5256 | return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction); | |
| 5189 | 5257 | case IrInstructionIdReturn: |
| 5190 | 5258 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| 5191 | case IrInstructionIdDeclVar: | |
| 5192 | return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction); | |
| 5193 | 5259 | case IrInstructionIdBinOp: |
| 5194 | 5260 | return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction); |
| 5195 | 5261 | case IrInstructionIdCast: |
| ... | ... | @@ -5220,8 +5286,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5220 | 5286 | return ir_render_asm(g, executable, (IrInstructionAsm *)instruction); |
| 5221 | 5287 | case IrInstructionIdTestNonNull: |
| 5222 | 5288 | return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction); |
| 5223 | case IrInstructionIdUnwrapOptional: | |
| 5224 | return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction); | |
| 5289 | case IrInstructionIdOptionalUnwrapPtr: | |
| 5290 | return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction); | |
| 5225 | 5291 | case IrInstructionIdClz: |
| 5226 | 5292 | return ir_render_clz(g, executable, (IrInstructionClz *)instruction); |
| 5227 | 5293 | case IrInstructionIdCtz: |
| ... | ... | @@ -5236,8 +5302,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5236 | 5302 | return ir_render_ref(g, executable, (IrInstructionRef *)instruction); |
| 5237 | 5303 | case IrInstructionIdErrName: |
| 5238 | 5304 | return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction); |
| 5239 | case IrInstructionIdCmpxchg: | |
| 5240 | return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction); | |
| 5305 | case IrInstructionIdCmpxchgGen: | |
| 5306 | return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction); | |
| 5241 | 5307 | case IrInstructionIdFence: |
| 5242 | 5308 | return ir_render_fence(g, executable, (IrInstructionFence *)instruction); |
| 5243 | 5309 | case IrInstructionIdTruncate: |
| ... | ... | @@ -5278,8 +5344,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5278 | 5344 | return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction); |
| 5279 | 5345 | case IrInstructionIdUnionInit: |
| 5280 | 5346 | return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction); |
| 5281 | case IrInstructionIdPtrCast: | |
| 5282 | return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction); | |
| 5347 | case IrInstructionIdPtrCastGen: | |
| 5348 | return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction); | |
| 5283 | 5349 | case IrInstructionIdBitCast: |
| 5284 | 5350 | return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction); |
| 5285 | 5351 | case IrInstructionIdWidenOrShorten: |
| ... | ... | @@ -5377,6 +5443,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { |
| 5377 | 5443 | static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index); |
| 5378 | 5444 | static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index); |
| 5379 | 5445 | static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val); |
| 5446 | static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val); | |
| 5447 | static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val); | |
| 5448 | static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val); | |
| 5380 | 5449 | |
| 5381 | 5450 | static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) { |
| 5382 | 5451 | switch (parent->id) { |
| ... | ... | @@ -5387,6 +5456,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent |
| 5387 | 5456 | case ConstParentIdStruct: |
| 5388 | 5457 | return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val, |
| 5389 | 5458 | parent->data.p_struct.field_index); |
| 5459 | case ConstParentIdErrUnionCode: | |
| 5460 | return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val); | |
| 5461 | case ConstParentIdErrUnionPayload: | |
| 5462 | return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val); | |
| 5463 | case ConstParentIdOptionalPayload: | |
| 5464 | return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val); | |
| 5390 | 5465 | case ConstParentIdArray: |
| 5391 | 5466 | return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val, |
| 5392 | 5467 | parent->data.p_array.elem_index); |
| ... | ... | @@ -5402,7 +5477,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent |
| 5402 | 5477 | |
| 5403 | 5478 | static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) { |
| 5404 | 5479 | expand_undef_array(g, array_const_val); |
| 5405 | ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent; | |
| 5480 | ConstParent *parent = &array_const_val->parent; | |
| 5406 | 5481 | LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent); |
| 5407 | 5482 | |
| 5408 | 5483 | LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr))); |
| ... | ... | @@ -5427,7 +5502,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar |
| 5427 | 5502 | } |
| 5428 | 5503 | |
| 5429 | 5504 | static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) { |
| 5430 | ConstParent *parent = &struct_const_val->data.x_struct.parent; | |
| 5505 | ConstParent *parent = &struct_const_val->parent; | |
| 5431 | 5506 | LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent); |
| 5432 | 5507 | |
| 5433 | 5508 | ZigType *u32 = g->builtin_types.entry_u32; |
| ... | ... | @@ -5438,8 +5513,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s |
| 5438 | 5513 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); |
| 5439 | 5514 | } |
| 5440 | 5515 | |
| 5516 | static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val) { | |
| 5517 | ConstParent *parent = &err_union_const_val->parent; | |
| 5518 | LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent); | |
| 5519 | ||
| 5520 | ZigType *u32 = g->builtin_types.entry_u32; | |
| 5521 | LLVMValueRef indices[] = { | |
| 5522 | LLVMConstNull(u32->type_ref), | |
| 5523 | LLVMConstInt(u32->type_ref, err_union_err_index, false), | |
| 5524 | }; | |
| 5525 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | |
| 5526 | } | |
| 5527 | ||
| 5528 | static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val) { | |
| 5529 | ConstParent *parent = &err_union_const_val->parent; | |
| 5530 | LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent); | |
| 5531 | ||
| 5532 | ZigType *u32 = g->builtin_types.entry_u32; | |
| 5533 | LLVMValueRef indices[] = { | |
| 5534 | LLVMConstNull(u32->type_ref), | |
| 5535 | LLVMConstInt(u32->type_ref, err_union_payload_index, false), | |
| 5536 | }; | |
| 5537 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | |
| 5538 | } | |
| 5539 | ||
| 5540 | static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val) { | |
| 5541 | ConstParent *parent = &optional_const_val->parent; | |
| 5542 | LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent); | |
| 5543 | ||
| 5544 | ZigType *u32 = g->builtin_types.entry_u32; | |
| 5545 | LLVMValueRef indices[] = { | |
| 5546 | LLVMConstNull(u32->type_ref), | |
| 5547 | LLVMConstInt(u32->type_ref, maybe_child_index, false), | |
| 5548 | }; | |
| 5549 | return LLVMConstInBoundsGEP(base_ptr, indices, 2); | |
| 5550 | } | |
| 5551 | ||
| 5441 | 5552 | static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) { |
| 5442 | ConstParent *parent = &union_const_val->data.x_union.parent; | |
| 5553 | ConstParent *parent = &union_const_val->parent; | |
| 5443 | 5554 | LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent); |
| 5444 | 5555 | |
| 5445 | 5556 | ZigType *u32 = g->builtin_types.entry_u32; |
| ... | ... | @@ -5609,6 +5720,63 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con |
| 5609 | 5720 | render_const_val_global(g, const_val, ""); |
| 5610 | 5721 | return ptr_val; |
| 5611 | 5722 | } |
| 5723 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 5724 | { | |
| 5725 | render_const_val_global(g, const_val, name); | |
| 5726 | ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val; | |
| 5727 | assert(err_union_const_val->type->id == ZigTypeIdErrorUnion); | |
| 5728 | if (err_union_const_val->type->zero_bits) { | |
| 5729 | // make this a null pointer | |
| 5730 | ZigType *usize = g->builtin_types.entry_usize; | |
| 5731 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | |
| 5732 | const_val->type->type_ref); | |
| 5733 | render_const_val_global(g, const_val, ""); | |
| 5734 | return const_val->global_refs->llvm_value; | |
| 5735 | } | |
| 5736 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val); | |
| 5737 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | |
| 5738 | const_val->global_refs->llvm_value = ptr_val; | |
| 5739 | render_const_val_global(g, const_val, ""); | |
| 5740 | return ptr_val; | |
| 5741 | } | |
| 5742 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 5743 | { | |
| 5744 | render_const_val_global(g, const_val, name); | |
| 5745 | ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val; | |
| 5746 | assert(err_union_const_val->type->id == ZigTypeIdErrorUnion); | |
| 5747 | if (err_union_const_val->type->zero_bits) { | |
| 5748 | // make this a null pointer | |
| 5749 | ZigType *usize = g->builtin_types.entry_usize; | |
| 5750 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | |
| 5751 | const_val->type->type_ref); | |
| 5752 | render_const_val_global(g, const_val, ""); | |
| 5753 | return const_val->global_refs->llvm_value; | |
| 5754 | } | |
| 5755 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val); | |
| 5756 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | |
| 5757 | const_val->global_refs->llvm_value = ptr_val; | |
| 5758 | render_const_val_global(g, const_val, ""); | |
| 5759 | return ptr_val; | |
| 5760 | } | |
| 5761 | case ConstPtrSpecialBaseOptionalPayload: | |
| 5762 | { | |
| 5763 | render_const_val_global(g, const_val, name); | |
| 5764 | ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val; | |
| 5765 | assert(optional_const_val->type->id == ZigTypeIdOptional); | |
| 5766 | if (optional_const_val->type->zero_bits) { | |
| 5767 | // make this a null pointer | |
| 5768 | ZigType *usize = g->builtin_types.entry_usize; | |
| 5769 | const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), | |
| 5770 | const_val->type->type_ref); | |
| 5771 | render_const_val_global(g, const_val, ""); | |
| 5772 | return const_val->global_refs->llvm_value; | |
| 5773 | } | |
| 5774 | LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val); | |
| 5775 | LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); | |
| 5776 | const_val->global_refs->llvm_value = ptr_val; | |
| 5777 | render_const_val_global(g, const_val, ""); | |
| 5778 | return ptr_val; | |
| 5779 | } | |
| 5612 | 5780 | case ConstPtrSpecialHardCodedAddr: |
| 5613 | 5781 | { |
| 5614 | 5782 | render_const_val_global(g, const_val, name); |
| ... | ... | @@ -5621,10 +5789,17 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con |
| 5621 | 5789 | } |
| 5622 | 5790 | case ConstPtrSpecialFunction: |
| 5623 | 5791 | return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref); |
| 5792 | case ConstPtrSpecialNull: | |
| 5793 | return LLVMConstNull(const_val->type->type_ref); | |
| 5624 | 5794 | } |
| 5625 | 5795 | zig_unreachable(); |
| 5626 | 5796 | } |
| 5627 | 5797 | |
| 5798 | static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) { | |
| 5799 | uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value; | |
| 5800 | return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false); | |
| 5801 | } | |
| 5802 | ||
| 5628 | 5803 | static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) { |
| 5629 | 5804 | Error err; |
| 5630 | 5805 | |
| ... | ... | @@ -5644,9 +5819,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5644 | 5819 | case ZigTypeIdInt: |
| 5645 | 5820 | return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); |
| 5646 | 5821 | case ZigTypeIdErrorSet: |
| 5647 | assert(const_val->data.x_err_set != nullptr); | |
| 5648 | return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, | |
| 5649 | const_val->data.x_err_set->value, false); | |
| 5822 | return gen_const_val_err_set(g, const_val, name); | |
| 5650 | 5823 | case ZigTypeIdFloat: |
| 5651 | 5824 | switch (type_entry->data.floating.bit_count) { |
| 5652 | 5825 | case 16: |
| ... | ... | @@ -5680,6 +5853,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5680 | 5853 | return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false); |
| 5681 | 5854 | } else if (type_is_codegen_pointer(child_type)) { |
| 5682 | 5855 | return gen_const_val_ptr(g, const_val, name); |
| 5856 | } else if (child_type->id == ZigTypeIdErrorSet) { | |
| 5857 | return gen_const_val_err_set(g, const_val, name); | |
| 5683 | 5858 | } else { |
| 5684 | 5859 | LLVMValueRef child_val; |
| 5685 | 5860 | LLVMValueRef maybe_val; |
| ... | ... | @@ -5914,7 +6089,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5914 | 6089 | ZigType *err_set_type = type_entry->data.error_union.err_set_type; |
| 5915 | 6090 | if (!type_has_bits(payload_type)) { |
| 5916 | 6091 | assert(type_has_bits(err_set_type)); |
| 5917 | uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0; | |
| 6092 | ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; | |
| 6093 | uint64_t value = (err_set == nullptr) ? 0 : err_set->value; | |
| 5918 | 6094 | return LLVMConstInt(g->err_tag_type->type_ref, value, false); |
| 5919 | 6095 | } else if (!type_has_bits(err_set_type)) { |
| 5920 | 6096 | assert(type_has_bits(payload_type)); |
| ... | ... | @@ -5923,8 +6099,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c |
| 5923 | 6099 | LLVMValueRef err_tag_value; |
| 5924 | 6100 | LLVMValueRef err_payload_value; |
| 5925 | 6101 | bool make_unnamed_struct; |
| 5926 | if (const_val->data.x_err_union.err) { | |
| 5927 | err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false); | |
| 6102 | ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; | |
| 6103 | if (err_set != nullptr) { | |
| 6104 | err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false); | |
| 5928 | 6105 | err_payload_value = LLVMConstNull(payload_type->type_ref); |
| 5929 | 6106 | make_unnamed_struct = false; |
| 5930 | 6107 | } else { |
| ... | ... | @@ -6130,10 +6307,13 @@ static void do_code_gen(CodeGen *g) { |
| 6130 | 6307 | TldVar *tld_var = g->global_vars.at(i); |
| 6131 | 6308 | ZigVar *var = tld_var->var; |
| 6132 | 6309 | |
| 6133 | if (var->value->type->id == ZigTypeIdComptimeFloat) { | |
| 6310 | if (var->var_type->id == ZigTypeIdComptimeFloat) { | |
| 6134 | 6311 | // Generate debug info for it but that's it. |
| 6135 | ConstExprValue *const_val = var->value; | |
| 6312 | ConstExprValue *const_val = var->const_value; | |
| 6136 | 6313 | assert(const_val->special != ConstValSpecialRuntime); |
| 6314 | if (const_val->type != var->var_type) { | |
| 6315 | zig_panic("TODO debug info for var with ptr casted value"); | |
| 6316 | } | |
| 6137 | 6317 | ZigType *var_type = g->builtin_types.entry_f128; |
| 6138 | 6318 | ConstExprValue coerced_value; |
| 6139 | 6319 | coerced_value.special = ConstValSpecialStatic; |
| ... | ... | @@ -6144,10 +6324,13 @@ static void do_code_gen(CodeGen *g) { |
| 6144 | 6324 | continue; |
| 6145 | 6325 | } |
| 6146 | 6326 | |
| 6147 | if (var->value->type->id == ZigTypeIdComptimeInt) { | |
| 6327 | if (var->var_type->id == ZigTypeIdComptimeInt) { | |
| 6148 | 6328 | // Generate debug info for it but that's it. |
| 6149 | ConstExprValue *const_val = var->value; | |
| 6329 | ConstExprValue *const_val = var->const_value; | |
| 6150 | 6330 | assert(const_val->special != ConstValSpecialRuntime); |
| 6331 | if (const_val->type != var->var_type) { | |
| 6332 | zig_panic("TODO debug info for var with ptr casted value"); | |
| 6333 | } | |
| 6151 | 6334 | size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint); |
| 6152 | 6335 | if (bits_needed < 8) { |
| 6153 | 6336 | bits_needed = 8; |
| ... | ... | @@ -6158,7 +6341,7 @@ static void do_code_gen(CodeGen *g) { |
| 6158 | 6341 | continue; |
| 6159 | 6342 | } |
| 6160 | 6343 | |
| 6161 | if (!type_has_bits(var->value->type)) | |
| 6344 | if (!type_has_bits(var->var_type)) | |
| 6162 | 6345 | continue; |
| 6163 | 6346 | |
| 6164 | 6347 | assert(var->decl_node); |
| ... | ... | @@ -6167,9 +6350,9 @@ static void do_code_gen(CodeGen *g) { |
| 6167 | 6350 | if (var->linkage == VarLinkageExternal) { |
| 6168 | 6351 | LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name)); |
| 6169 | 6352 | if (existing_llvm_var) { |
| 6170 | global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->value->type->type_ref, 0)); | |
| 6353 | global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0)); | |
| 6171 | 6354 | } else { |
| 6172 | global_value = LLVMAddGlobal(g->module, var->value->type->type_ref, buf_ptr(&var->name)); | |
| 6355 | global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name)); | |
| 6173 | 6356 | // TODO debug info for the extern variable |
| 6174 | 6357 | |
| 6175 | 6358 | LLVMSetLinkage(global_value, LLVMExternalLinkage); |
| ... | ... | @@ -6180,9 +6363,9 @@ static void do_code_gen(CodeGen *g) { |
| 6180 | 6363 | } else { |
| 6181 | 6364 | bool exported = (var->linkage == VarLinkageExport); |
| 6182 | 6365 | const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported)); |
| 6183 | render_const_val(g, var->value, mangled_name); | |
| 6184 | render_const_val_global(g, var->value, mangled_name); | |
| 6185 | global_value = var->value->global_refs->llvm_global; | |
| 6366 | render_const_val(g, var->const_value, mangled_name); | |
| 6367 | render_const_val_global(g, var->const_value, mangled_name); | |
| 6368 | global_value = var->const_value->global_refs->llvm_global; | |
| 6186 | 6369 | |
| 6187 | 6370 | if (exported) { |
| 6188 | 6371 | LLVMSetLinkage(global_value, LLVMExternalLinkage); |
| ... | ... | @@ -6194,8 +6377,10 @@ static void do_code_gen(CodeGen *g) { |
| 6194 | 6377 | LLVMSetAlignment(global_value, var->align_bytes); |
| 6195 | 6378 | |
| 6196 | 6379 | // TODO debug info for function pointers |
| 6197 | if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) { | |
| 6198 | gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type); | |
| 6380 | // Here we use const_value->type because that's the type of the llvm global, | |
| 6381 | // which we const ptr cast upon use to whatever it needs to be. | |
| 6382 | if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) { | |
| 6383 | gen_global_var(g, var, var->const_value->global_refs->llvm_value, var->const_value->type); | |
| 6199 | 6384 | } |
| 6200 | 6385 | |
| 6201 | 6386 | LLVMSetGlobalConstant(global_value, var->gen_is_const); |
| ... | ... | @@ -6281,8 +6466,8 @@ static void do_code_gen(CodeGen *g) { |
| 6281 | 6466 | } else if (instruction->id == IrInstructionIdErrWrapCode) { |
| 6282 | 6467 | IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction; |
| 6283 | 6468 | slot = &err_wrap_code_instruction->tmp_ptr; |
| 6284 | } else if (instruction->id == IrInstructionIdCmpxchg) { | |
| 6285 | IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction; | |
| 6469 | } else if (instruction->id == IrInstructionIdCmpxchgGen) { | |
| 6470 | IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction; | |
| 6286 | 6471 | slot = &cmpxchg_instruction->tmp_ptr; |
| 6287 | 6472 | } else { |
| 6288 | 6473 | zig_unreachable(); |
| ... | ... | @@ -6304,12 +6489,12 @@ static void do_code_gen(CodeGen *g) { |
| 6304 | 6489 | for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) { |
| 6305 | 6490 | ZigVar *var = fn_table_entry->variable_list.at(var_i); |
| 6306 | 6491 | |
| 6307 | if (!type_has_bits(var->value->type)) { | |
| 6492 | if (!type_has_bits(var->var_type)) { | |
| 6308 | 6493 | continue; |
| 6309 | 6494 | } |
| 6310 | 6495 | if (ir_get_var_is_comptime(var)) |
| 6311 | 6496 | continue; |
| 6312 | switch (type_requires_comptime(g, var->value->type)) { | |
| 6497 | switch (type_requires_comptime(g, var->var_type)) { | |
| 6313 | 6498 | case ReqCompTimeInvalid: |
| 6314 | 6499 | zig_unreachable(); |
| 6315 | 6500 | case ReqCompTimeYes: |
| ... | ... | @@ -6319,11 +6504,11 @@ static void do_code_gen(CodeGen *g) { |
| 6319 | 6504 | } |
| 6320 | 6505 | |
| 6321 | 6506 | if (var->src_arg_index == SIZE_MAX) { |
| 6322 | var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); | |
| 6507 | var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes); | |
| 6323 | 6508 | |
| 6324 | 6509 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 6325 | 6510 | buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1), |
| 6326 | var->value->type->di_type, !g->strip_debug_symbols, 0); | |
| 6511 | var->var_type->di_type, !g->strip_debug_symbols, 0); | |
| 6327 | 6512 | |
| 6328 | 6513 | } else if (is_c_abi) { |
| 6329 | 6514 | fn_walk_var.data.vars.var = var; |
| ... | ... | @@ -6333,16 +6518,16 @@ static void do_code_gen(CodeGen *g) { |
| 6333 | 6518 | ZigType *gen_type; |
| 6334 | 6519 | FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; |
| 6335 | 6520 | |
| 6336 | if (handle_is_ptr(var->value->type)) { | |
| 6521 | if (handle_is_ptr(var->var_type)) { | |
| 6337 | 6522 | if (gen_info->is_byval) { |
| 6338 | gen_type = var->value->type; | |
| 6523 | gen_type = var->var_type; | |
| 6339 | 6524 | } else { |
| 6340 | 6525 | gen_type = gen_info->type; |
| 6341 | 6526 | } |
| 6342 | 6527 | var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index); |
| 6343 | 6528 | } else { |
| 6344 | gen_type = var->value->type; | |
| 6345 | var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes); | |
| 6529 | gen_type = var->var_type; | |
| 6530 | var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes); | |
| 6346 | 6531 | } |
| 6347 | 6532 | if (var->decl_node) { |
| 6348 | 6533 | 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) { |
| 7458 | 7643 | ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i]; |
| 7459 | 7644 | this_val->special = ConstValSpecialStatic; |
| 7460 | 7645 | this_val->type = struct_type; |
| 7461 | this_val->data.x_struct.parent.id = ConstParentIdArray; | |
| 7462 | this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array; | |
| 7463 | this_val->data.x_struct.parent.data.p_array.elem_index = i; | |
| 7646 | this_val->parent.id = ConstParentIdArray; | |
| 7647 | this_val->parent.data.p_array.array_val = test_fn_array; | |
| 7648 | this_val->parent.data.p_array.elem_index = i; | |
| 7464 | 7649 | this_val->data.x_struct.fields = create_const_vals(2); |
| 7465 | 7650 | |
| 7466 | 7651 | ConstExprValue *name_field = &this_val->data.x_struct.fields[0]; |
src/ir.cpp+827-644| ... | ... | @@ -167,6 +167,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 167 | 167 | ZigType *dest_type, IrInstruction *dest_type_src); |
| 168 | 168 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); |
| 169 | 169 | static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs); |
| 170 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); | |
| 170 | 171 | |
| 171 | 172 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 172 | 173 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | ... | @@ -178,15 +179,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c |
| 178 | 179 | case ConstPtrSpecialRef: |
| 179 | 180 | result = const_val->data.x_ptr.data.ref.pointee; |
| 180 | 181 | break; |
| 181 | case ConstPtrSpecialBaseArray: | |
| 182 | expand_undef_array(g, const_val->data.x_ptr.data.base_array.array_val); | |
| 183 | result = &const_val->data.x_ptr.data.base_array.array_val->data.x_array.data.s_none.elements[ | |
| 184 | const_val->data.x_ptr.data.base_array.elem_index]; | |
| 182 | case ConstPtrSpecialBaseArray: { | |
| 183 | ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val; | |
| 184 | expand_undef_array(g, array_val); | |
| 185 | result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index]; | |
| 185 | 186 | break; |
| 187 | } | |
| 186 | 188 | case ConstPtrSpecialBaseStruct: |
| 187 | 189 | result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[ |
| 188 | 190 | const_val->data.x_ptr.data.base_struct.field_index]; |
| 189 | 191 | break; |
| 192 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 193 | result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set; | |
| 194 | break; | |
| 195 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 196 | result = const_val->data.x_ptr.data.base_err_union_payload.err_union_val->data.x_err_union.payload; | |
| 197 | break; | |
| 198 | case ConstPtrSpecialBaseOptionalPayload: | |
| 199 | result = const_val->data.x_ptr.data.base_optional_payload.optional_val->data.x_optional; | |
| 200 | break; | |
| 201 | case ConstPtrSpecialNull: | |
| 202 | result = const_val; | |
| 203 | break; | |
| 190 | 204 | case ConstPtrSpecialHardCodedAddr: |
| 191 | 205 | zig_unreachable(); |
| 192 | 206 | case ConstPtrSpecialDiscard: |
| ... | ... | @@ -198,6 +212,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c |
| 198 | 212 | return result; |
| 199 | 213 | } |
| 200 | 214 | |
| 215 | static bool is_opt_err_set(ZigType *ty) { | |
| 216 | return ty->id == ZigTypeIdErrorSet || | |
| 217 | (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet); | |
| 218 | } | |
| 219 | ||
| 201 | 220 | static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { |
| 202 | 221 | if (a == b) |
| 203 | 222 | return true; |
| ... | ... | @@ -208,15 +227,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { |
| 208 | 227 | if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr) |
| 209 | 228 | return true; |
| 210 | 229 | |
| 211 | return false; | |
| 212 | } | |
| 230 | if (is_opt_err_set(a) && is_opt_err_set(b)) | |
| 231 | return true; | |
| 213 | 232 | |
| 214 | ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) { | |
| 215 | ConstExprValue *result = const_ptr_pointee_unchecked(g, const_val); | |
| 216 | if (const_val->type->id == ZigTypeIdPointer) { | |
| 217 | assert(types_have_same_zig_comptime_repr(const_val->type->data.pointer.child_type, result->type)); | |
| 218 | } | |
| 219 | return result; | |
| 233 | return false; | |
| 220 | 234 | } |
| 221 | 235 | |
| 222 | 236 | static bool ir_should_inline(IrExecutable *exec, Scope *scope) { |
| ... | ... | @@ -305,6 +319,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) { |
| 305 | 319 | return new_bb; |
| 306 | 320 | } |
| 307 | 321 | |
| 322 | static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarSrc *) { | |
| 323 | return IrInstructionIdDeclVarSrc; | |
| 324 | } | |
| 325 | ||
| 326 | static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarGen *) { | |
| 327 | return IrInstructionIdDeclVarGen; | |
| 328 | } | |
| 329 | ||
| 308 | 330 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) { |
| 309 | 331 | return IrInstructionIdCondBr; |
| 310 | 332 | } |
| ... | ... | @@ -337,10 +359,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) { |
| 337 | 359 | return IrInstructionIdBinOp; |
| 338 | 360 | } |
| 339 | 361 | |
| 340 | static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) { | |
| 341 | return IrInstructionIdDeclVar; | |
| 342 | } | |
| 343 | ||
| 344 | 362 | static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) { |
| 345 | 363 | return IrInstructionIdExport; |
| 346 | 364 | } |
| ... | ... | @@ -449,8 +467,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) { |
| 449 | 467 | return IrInstructionIdTestNonNull; |
| 450 | 468 | } |
| 451 | 469 | |
| 452 | static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) { | |
| 453 | return IrInstructionIdUnwrapOptional; | |
| 470 | static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) { | |
| 471 | return IrInstructionIdOptionalUnwrapPtr; | |
| 454 | 472 | } |
| 455 | 473 | |
| 456 | 474 | static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) { |
| ... | ... | @@ -517,8 +535,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) { |
| 517 | 535 | return IrInstructionIdEmbedFile; |
| 518 | 536 | } |
| 519 | 537 | |
| 520 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchg *) { | |
| 521 | return IrInstructionIdCmpxchg; | |
| 538 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) { | |
| 539 | return IrInstructionIdCmpxchgSrc; | |
| 540 | } | |
| 541 | ||
| 542 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) { | |
| 543 | return IrInstructionIdCmpxchgGen; | |
| 522 | 544 | } |
| 523 | 545 | |
| 524 | 546 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) { |
| ... | ... | @@ -649,8 +671,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *) |
| 649 | 671 | return IrInstructionIdTestComptime; |
| 650 | 672 | } |
| 651 | 673 | |
| 652 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) { | |
| 653 | return IrInstructionIdPtrCast; | |
| 674 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) { | |
| 675 | return IrInstructionIdPtrCastSrc; | |
| 676 | } | |
| 677 | ||
| 678 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) { | |
| 679 | return IrInstructionIdPtrCastGen; | |
| 654 | 680 | } |
| 655 | 681 | |
| 656 | 682 | static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) { |
| ... | ... | @@ -915,7 +941,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so |
| 915 | 941 | ir_ref_instruction(condition, irb->current_basic_block); |
| 916 | 942 | ir_ref_bb(then_block); |
| 917 | 943 | ir_ref_bb(else_block); |
| 918 | if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block); | |
| 944 | if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block); | |
| 919 | 945 | |
| 920 | 946 | return &cond_br_instruction->base; |
| 921 | 947 | } |
| ... | ... | @@ -931,16 +957,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou |
| 931 | 957 | return &return_instruction->base; |
| 932 | 958 | } |
| 933 | 959 | |
| 934 | static IrInstruction *ir_create_const(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 935 | ZigType *type_entry) | |
| 936 | { | |
| 937 | assert(type_entry); | |
| 938 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb, scope, source_node); | |
| 939 | const_instruction->base.value.type = type_entry; | |
| 940 | const_instruction->base.value.special = ConstValSpecialStatic; | |
| 941 | return &const_instruction->base; | |
| 942 | } | |
| 943 | ||
| 944 | 960 | static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 945 | 961 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node); |
| 946 | 962 | const_instruction->base.value.type = irb->codegen->builtin_types.entry_void; |
| ... | ... | @@ -1188,14 +1204,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc |
| 1188 | 1204 | call_instruction->async_allocator = async_allocator; |
| 1189 | 1205 | call_instruction->new_stack = new_stack; |
| 1190 | 1206 | |
| 1191 | if (fn_ref) | |
| 1192 | ir_ref_instruction(fn_ref, irb->current_basic_block); | |
| 1207 | if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block); | |
| 1193 | 1208 | for (size_t i = 0; i < arg_count; i += 1) |
| 1194 | 1209 | ir_ref_instruction(args[i], irb->current_basic_block); |
| 1195 | if (async_allocator) | |
| 1196 | ir_ref_instruction(async_allocator, irb->current_basic_block); | |
| 1197 | if (new_stack != nullptr) | |
| 1198 | ir_ref_instruction(new_stack, irb->current_basic_block); | |
| 1210 | if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block); | |
| 1211 | if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block); | |
| 1199 | 1212 | |
| 1200 | 1213 | return &call_instruction->base; |
| 1201 | 1214 | } |
| ... | ... | @@ -1280,7 +1293,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, |
| 1280 | 1293 | container_init_list_instruction->item_count = item_count; |
| 1281 | 1294 | container_init_list_instruction->items = items; |
| 1282 | 1295 | |
| 1283 | ir_ref_instruction(container_type, irb->current_basic_block); | |
| 1296 | if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block); | |
| 1284 | 1297 | for (size_t i = 0; i < item_count; i += 1) { |
| 1285 | 1298 | ir_ref_instruction(items[i], irb->current_basic_block); |
| 1286 | 1299 | } |
| ... | ... | @@ -1355,10 +1368,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode * |
| 1355 | 1368 | return &instruction->base; |
| 1356 | 1369 | } |
| 1357 | 1370 | |
| 1358 | static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1371 | static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1359 | 1372 | ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value) |
| 1360 | 1373 | { |
| 1361 | IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, scope, source_node); | |
| 1374 | IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarSrc>(irb, scope, source_node); | |
| 1362 | 1375 | decl_var_instruction->base.value.special = ConstValSpecialStatic; |
| 1363 | 1376 | decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void; |
| 1364 | 1377 | decl_var_instruction->var = var; |
| ... | ... | @@ -1366,13 +1379,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s |
| 1366 | 1379 | decl_var_instruction->align_value = align_value; |
| 1367 | 1380 | decl_var_instruction->init_value = init_value; |
| 1368 | 1381 | |
| 1369 | if (var_type) ir_ref_instruction(var_type, irb->current_basic_block); | |
| 1370 | if (align_value) ir_ref_instruction(align_value, irb->current_basic_block); | |
| 1382 | if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block); | |
| 1383 | if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block); | |
| 1371 | 1384 | ir_ref_instruction(init_value, irb->current_basic_block); |
| 1372 | 1385 | |
| 1373 | 1386 | return &decl_var_instruction->base; |
| 1374 | 1387 | } |
| 1375 | 1388 | |
| 1389 | static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction, | |
| 1390 | ZigVar *var, IrInstruction *init_value) | |
| 1391 | { | |
| 1392 | IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarGen>(&ira->new_irb, | |
| 1393 | source_instruction->scope, source_instruction->source_node); | |
| 1394 | decl_var_instruction->base.value.special = ConstValSpecialStatic; | |
| 1395 | decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void; | |
| 1396 | decl_var_instruction->var = var; | |
| 1397 | decl_var_instruction->init_value = init_value; | |
| 1398 | ||
| 1399 | ir_ref_instruction(init_value, ira->new_irb.current_basic_block); | |
| 1400 | ||
| 1401 | return &decl_var_instruction->base; | |
| 1402 | } | |
| 1403 | ||
| 1376 | 1404 | static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1377 | 1405 | IrInstruction *name, IrInstruction *target, IrInstruction *linkage) |
| 1378 | 1406 | { |
| ... | ... | @@ -1542,14 +1570,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod |
| 1542 | 1570 | return &instruction->base; |
| 1543 | 1571 | } |
| 1544 | 1572 | |
| 1545 | static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value, | |
| 1546 | bool safety_check_on) | |
| 1573 | static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1574 | IrInstruction *base_ptr, bool safety_check_on) | |
| 1547 | 1575 | { |
| 1548 | IrInstructionUnwrapOptional *instruction = ir_build_instruction<IrInstructionUnwrapOptional>(irb, scope, source_node); | |
| 1549 | instruction->value = value; | |
| 1576 | IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node); | |
| 1577 | instruction->base_ptr = base_ptr; | |
| 1550 | 1578 | instruction->safety_check_on = safety_check_on; |
| 1551 | 1579 | |
| 1552 | ir_ref_instruction(value, irb->current_basic_block); | |
| 1580 | ir_ref_instruction(base_ptr, irb->current_basic_block); | |
| 1553 | 1581 | |
| 1554 | 1582 | return &instruction->base; |
| 1555 | 1583 | } |
| ... | ... | @@ -1765,13 +1793,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode |
| 1765 | 1793 | return &instruction->base; |
| 1766 | 1794 | } |
| 1767 | 1795 | |
| 1768 | static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value, | |
| 1769 | IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, | |
| 1796 | static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1797 | IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, | |
| 1770 | 1798 | IrInstruction *success_order_value, IrInstruction *failure_order_value, |
| 1771 | bool is_weak, | |
| 1772 | ZigType *type, AtomicOrder success_order, AtomicOrder failure_order) | |
| 1799 | bool is_weak) | |
| 1773 | 1800 | { |
| 1774 | IrInstructionCmpxchg *instruction = ir_build_instruction<IrInstructionCmpxchg>(irb, scope, source_node); | |
| 1801 | IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node); | |
| 1775 | 1802 | instruction->type_value = type_value; |
| 1776 | 1803 | instruction->ptr = ptr; |
| 1777 | 1804 | instruction->cmp_value = cmp_value; |
| ... | ... | @@ -1779,16 +1806,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so |
| 1779 | 1806 | instruction->success_order_value = success_order_value; |
| 1780 | 1807 | instruction->failure_order_value = failure_order_value; |
| 1781 | 1808 | instruction->is_weak = is_weak; |
| 1782 | instruction->type = type; | |
| 1783 | instruction->success_order = success_order; | |
| 1784 | instruction->failure_order = failure_order; | |
| 1785 | 1809 | |
| 1786 | if (type_value != nullptr) ir_ref_instruction(type_value, irb->current_basic_block); | |
| 1810 | ir_ref_instruction(type_value, irb->current_basic_block); | |
| 1787 | 1811 | ir_ref_instruction(ptr, irb->current_basic_block); |
| 1788 | 1812 | ir_ref_instruction(cmp_value, irb->current_basic_block); |
| 1789 | 1813 | ir_ref_instruction(new_value, irb->current_basic_block); |
| 1790 | if (type_value != nullptr) ir_ref_instruction(success_order_value, irb->current_basic_block); | |
| 1791 | if (type_value != nullptr) ir_ref_instruction(failure_order_value, irb->current_basic_block); | |
| 1814 | ir_ref_instruction(success_order_value, irb->current_basic_block); | |
| 1815 | ir_ref_instruction(failure_order_value, irb->current_basic_block); | |
| 1816 | ||
| 1817 | return &instruction->base; | |
| 1818 | } | |
| 1819 | ||
| 1820 | static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction, | |
| 1821 | IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value, | |
| 1822 | AtomicOrder success_order, AtomicOrder failure_order, bool is_weak) | |
| 1823 | { | |
| 1824 | IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb, | |
| 1825 | source_instruction->scope, source_instruction->source_node); | |
| 1826 | instruction->ptr = ptr; | |
| 1827 | instruction->cmp_value = cmp_value; | |
| 1828 | instruction->new_value = new_value; | |
| 1829 | instruction->success_order = success_order; | |
| 1830 | instruction->failure_order = failure_order; | |
| 1831 | instruction->is_weak = is_weak; | |
| 1832 | ||
| 1833 | ir_ref_instruction(ptr, ira->new_irb.current_basic_block); | |
| 1834 | ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block); | |
| 1835 | ir_ref_instruction(new_value, ira->new_irb.current_basic_block); | |
| 1792 | 1836 | |
| 1793 | 1837 | return &instruction->base; |
| 1794 | 1838 | } |
| ... | ... | @@ -2060,12 +2104,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s |
| 2060 | 2104 | } |
| 2061 | 2105 | |
| 2062 | 2106 | static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2063 | IrInstruction *value) | |
| 2107 | IrInstruction *err_union) | |
| 2064 | 2108 | { |
| 2065 | 2109 | IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node); |
| 2066 | instruction->value = value; | |
| 2110 | instruction->err_union = err_union; | |
| 2067 | 2111 | |
| 2068 | ir_ref_instruction(value, irb->current_basic_block); | |
| 2112 | ir_ref_instruction(err_union, irb->current_basic_block); | |
| 2069 | 2113 | |
| 2070 | 2114 | return &instruction->base; |
| 2071 | 2115 | } |
| ... | ... | @@ -2115,20 +2159,33 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo |
| 2115 | 2159 | return &instruction->base; |
| 2116 | 2160 | } |
| 2117 | 2161 | |
| 2118 | static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 2162 | static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 2119 | 2163 | IrInstruction *dest_type, IrInstruction *ptr) |
| 2120 | 2164 | { |
| 2121 | IrInstructionPtrCast *instruction = ir_build_instruction<IrInstructionPtrCast>( | |
| 2165 | IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>( | |
| 2122 | 2166 | irb, scope, source_node); |
| 2123 | 2167 | instruction->dest_type = dest_type; |
| 2124 | 2168 | instruction->ptr = ptr; |
| 2125 | 2169 | |
| 2126 | if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block); | |
| 2170 | ir_ref_instruction(dest_type, irb->current_basic_block); | |
| 2127 | 2171 | ir_ref_instruction(ptr, irb->current_basic_block); |
| 2128 | 2172 | |
| 2129 | 2173 | return &instruction->base; |
| 2130 | 2174 | } |
| 2131 | 2175 | |
| 2176 | static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction, | |
| 2177 | ZigType *ptr_type, IrInstruction *ptr) | |
| 2178 | { | |
| 2179 | IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>( | |
| 2180 | &ira->new_irb, source_instruction->scope, source_instruction->source_node); | |
| 2181 | instruction->base.value.type = ptr_type; | |
| 2182 | instruction->ptr = ptr; | |
| 2183 | ||
| 2184 | ir_ref_instruction(ptr, ira->new_irb.current_basic_block); | |
| 2185 | ||
| 2186 | return &instruction->base; | |
| 2187 | } | |
| 2188 | ||
| 2132 | 2189 | static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2133 | 2190 | IrInstruction *dest_type, IrInstruction *value) |
| 2134 | 2191 | { |
| ... | ... | @@ -2807,10 +2864,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o |
| 2807 | 2864 | Scope *defer_expr_scope = defer_node->data.defer.expr_scope; |
| 2808 | 2865 | IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); |
| 2809 | 2866 | if (defer_expr_value != irb->codegen->invalid_instruction) { |
| 2810 | if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == ZigTypeIdUnreachable) { | |
| 2867 | if (defer_expr_value->value.type != nullptr && | |
| 2868 | defer_expr_value->value.type->id == ZigTypeIdUnreachable) | |
| 2869 | { | |
| 2811 | 2870 | is_noreturn = true; |
| 2812 | 2871 | } else { |
| 2813 | ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value)); | |
| 2872 | ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, | |
| 2873 | defer_expr_value)); | |
| 2814 | 2874 | } |
| 2815 | 2875 | } |
| 2816 | 2876 | } |
| ... | ... | @@ -3065,7 +3125,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s |
| 3065 | 3125 | variable_entry->mem_slot_index = SIZE_MAX; |
| 3066 | 3126 | variable_entry->is_comptime = is_comptime; |
| 3067 | 3127 | variable_entry->src_arg_index = SIZE_MAX; |
| 3068 | variable_entry->value = create_const_vals(1); | |
| 3128 | variable_entry->const_value = create_const_vals(1); | |
| 3069 | 3129 | |
| 3070 | 3130 | if (is_comptime != nullptr) { |
| 3071 | 3131 | is_comptime->ref_count += 1; |
| ... | ... | @@ -3080,20 +3140,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s |
| 3080 | 3140 | ErrorMsg *msg = add_node_error(codegen, node, |
| 3081 | 3141 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); |
| 3082 | 3142 | add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); |
| 3083 | variable_entry->value->type = codegen->builtin_types.entry_invalid; | |
| 3143 | variable_entry->var_type = codegen->builtin_types.entry_invalid; | |
| 3084 | 3144 | } else { |
| 3085 | 3145 | ZigType *type; |
| 3086 | 3146 | if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) { |
| 3087 | 3147 | add_node_error(codegen, node, |
| 3088 | 3148 | buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name))); |
| 3089 | variable_entry->value->type = codegen->builtin_types.entry_invalid; | |
| 3149 | variable_entry->var_type = codegen->builtin_types.entry_invalid; | |
| 3090 | 3150 | } else { |
| 3091 | 3151 | Tld *tld = find_decl(codegen, parent_scope, name); |
| 3092 | 3152 | if (tld != nullptr) { |
| 3093 | 3153 | ErrorMsg *msg = add_node_error(codegen, node, |
| 3094 | 3154 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 3095 | 3155 | add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here")); |
| 3096 | variable_entry->value->type = codegen->builtin_types.entry_invalid; | |
| 3156 | variable_entry->var_type = codegen->builtin_types.entry_invalid; | |
| 3097 | 3157 | } |
| 3098 | 3158 | } |
| 3099 | 3159 | } |
| ... | ... | @@ -3156,7 +3216,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3156 | 3216 | scope_block->incoming_blocks = &incoming_blocks; |
| 3157 | 3217 | scope_block->incoming_values = &incoming_values; |
| 3158 | 3218 | scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd"); |
| 3159 | scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope)); | |
| 3219 | scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, | |
| 3220 | ir_should_inline(irb->exec, parent_scope)); | |
| 3160 | 3221 | } |
| 3161 | 3222 | |
| 3162 | 3223 | bool is_continuation_unreachable = false; |
| ... | ... | @@ -3174,9 +3235,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode |
| 3174 | 3235 | // defer starts a new scope |
| 3175 | 3236 | child_scope = statement_node->data.defer.child_scope; |
| 3176 | 3237 | assert(child_scope); |
| 3177 | } else if (statement_value->id == IrInstructionIdDeclVar) { | |
| 3238 | } else if (statement_value->id == IrInstructionIdDeclVarSrc) { | |
| 3178 | 3239 | // variable declarations start a new scope |
| 3179 | IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value; | |
| 3240 | IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value; | |
| 3180 | 3241 | child_scope = decl_var_instruction->var->child_scope; |
| 3181 | 3242 | } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) { |
| 3182 | 3243 | // this statement's value must be void |
| ... | ... | @@ -3331,7 +3392,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod |
| 3331 | 3392 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); |
| 3332 | 3393 | } |
| 3333 | 3394 | |
| 3334 | static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | |
| 3395 | static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | |
| 3335 | 3396 | assert(node->type == NodeTypeBinOpExpr); |
| 3336 | 3397 | |
| 3337 | 3398 | AstNode *op1_node = node->data.bin_op_expr.op1; |
| ... | ... | @@ -3365,7 +3426,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As |
| 3365 | 3426 | ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime)); |
| 3366 | 3427 | |
| 3367 | 3428 | ir_set_cursor_at_end_and_append_block(irb, ok_block); |
| 3368 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false); | |
| 3429 | IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false); | |
| 3369 | 3430 | IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); |
| 3370 | 3431 | IrBasicBlock *after_ok_block = irb->current_basic_block; |
| 3371 | 3432 | ir_build_br(irb, parent_scope, node, end_block, is_comptime); |
| ... | ... | @@ -3483,7 +3544,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) |
| 3483 | 3544 | case BinOpTypeMergeErrorSets: |
| 3484 | 3545 | return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets); |
| 3485 | 3546 | case BinOpTypeUnwrapOptional: |
| 3486 | return ir_gen_maybe_ok_or(irb, scope, node); | |
| 3547 | return ir_gen_orelse(irb, scope, node); | |
| 3487 | 3548 | case BinOpTypeErrorUnion: |
| 3488 | 3549 | return ir_gen_error_union(irb, scope, node); |
| 3489 | 3550 | } |
| ... | ... | @@ -3542,6 +3603,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 3542 | 3603 | buf_ptr(variable_name))); |
| 3543 | 3604 | return irb->codegen->invalid_instruction; |
| 3544 | 3605 | } |
| 3606 | assert(err == ErrorPrimitiveTypeNotFound); | |
| 3545 | 3607 | } else { |
| 3546 | 3608 | IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type); |
| 3547 | 3609 | if (lval == LValPtr) { |
| ... | ... | @@ -3904,9 +3966,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 3904 | 3966 | if (arg5_value == irb->codegen->invalid_instruction) |
| 3905 | 3967 | return arg5_value; |
| 3906 | 3968 | |
| 3907 | IrInstruction *cmpxchg = ir_build_cmpxchg(irb, scope, node, arg0_value, arg1_value, | |
| 3908 | arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak), | |
| 3909 | nullptr, AtomicOrderUnordered, AtomicOrderUnordered); | |
| 3969 | IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value, | |
| 3970 | arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak)); | |
| 3910 | 3971 | return ir_lval_wrap(irb, scope, cmpxchg, lval); |
| 3911 | 3972 | } |
| 3912 | 3973 | case BuiltinFnIdFence: |
| ... | ... | @@ -4346,7 +4407,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4346 | 4407 | if (arg1_value == irb->codegen->invalid_instruction) |
| 4347 | 4408 | return arg1_value; |
| 4348 | 4409 | |
| 4349 | IrInstruction *ptr_cast = ir_build_ptr_cast(irb, scope, node, arg0_value, arg1_value); | |
| 4410 | IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value); | |
| 4350 | 4411 | return ir_lval_wrap(irb, scope, ptr_cast, lval); |
| 4351 | 4412 | } |
| 4352 | 4413 | case BuiltinFnIdBitCast: |
| ... | ... | @@ -4784,7 +4845,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node |
| 4784 | 4845 | } |
| 4785 | 4846 | } |
| 4786 | 4847 | |
| 4787 | IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, nullptr); | |
| 4848 | IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, | |
| 4849 | is_async, async_allocator, nullptr); | |
| 4788 | 4850 | return ir_lval_wrap(irb, scope, fn_call, lval); |
| 4789 | 4851 | } |
| 4790 | 4852 | |
| ... | ... | @@ -4793,7 +4855,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4793 | 4855 | |
| 4794 | 4856 | IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope); |
| 4795 | 4857 | if (condition == irb->codegen->invalid_instruction) |
| 4796 | return condition; | |
| 4858 | return irb->codegen->invalid_instruction; | |
| 4797 | 4859 | |
| 4798 | 4860 | IrInstruction *is_comptime; |
| 4799 | 4861 | if (ir_should_inline(irb->exec, scope)) { |
| ... | ... | @@ -4816,7 +4878,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4816 | 4878 | Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime); |
| 4817 | 4879 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope); |
| 4818 | 4880 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 4819 | return then_expr_result; | |
| 4881 | return irb->codegen->invalid_instruction; | |
| 4820 | 4882 | IrBasicBlock *after_then_block = irb->current_basic_block; |
| 4821 | 4883 | if (!instr_is_unreachable(then_expr_result)) |
| 4822 | 4884 | ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime)); |
| ... | ... | @@ -4826,7 +4888,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode |
| 4826 | 4888 | if (else_node) { |
| 4827 | 4889 | else_expr_result = ir_gen_node(irb, else_node, subexpr_scope); |
| 4828 | 4890 | if (else_expr_result == irb->codegen->invalid_instruction) |
| 4829 | return else_expr_result; | |
| 4891 | return irb->codegen->invalid_instruction; | |
| 4830 | 4892 | } else { |
| 4831 | 4893 | else_expr_result = ir_build_const_void(irb, scope, node); |
| 4832 | 4894 | } |
| ... | ... | @@ -4927,7 +4989,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode |
| 4927 | 4989 | ptr_len, align_value, bit_offset_start, host_int_bytes); |
| 4928 | 4990 | } |
| 4929 | 4991 | |
| 4930 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node, | |
| 4992 | static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node, | |
| 4931 | 4993 | LVal lval) |
| 4932 | 4994 | { |
| 4933 | 4995 | IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr); |
| ... | ... | @@ -5053,11 +5115,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5053 | 5115 | ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime); |
| 5054 | 5116 | ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol, |
| 5055 | 5117 | is_const, is_const, is_shadowable, is_comptime); |
| 5056 | // we detect IrInstructionIdDeclVar in gen_block to make sure the next node | |
| 5118 | // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node | |
| 5057 | 5119 | // is inside var->child_scope |
| 5058 | 5120 | |
| 5059 | 5121 | if (!is_extern && !variable_declaration->expr) { |
| 5060 | var->value->type = irb->codegen->builtin_types.entry_invalid; | |
| 5122 | var->var_type = irb->codegen->builtin_types.entry_invalid; | |
| 5061 | 5123 | add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized")); |
| 5062 | 5124 | return irb->codegen->invalid_instruction; |
| 5063 | 5125 | } |
| ... | ... | @@ -5084,7 +5146,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5084 | 5146 | if (init_value == irb->codegen->invalid_instruction) |
| 5085 | 5147 | return init_value; |
| 5086 | 5148 | |
| 5087 | return ir_build_var_decl(irb, scope, node, var, type_instruction, align_value, init_value); | |
| 5149 | return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value); | |
| 5088 | 5150 | } |
| 5089 | 5151 | |
| 5090 | 5152 | static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) { |
| ... | ... | @@ -5140,7 +5202,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5140 | 5202 | err_val_ptr, false); |
| 5141 | 5203 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? |
| 5142 | 5204 | var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value); |
| 5143 | ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value); | |
| 5205 | ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value); | |
| 5144 | 5206 | } |
| 5145 | 5207 | |
| 5146 | 5208 | ZigList<IrInstruction *> incoming_values = {0}; |
| ... | ... | @@ -5180,7 +5242,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5180 | 5242 | true, false, false, is_comptime); |
| 5181 | 5243 | Scope *err_scope = err_var->child_scope; |
| 5182 | 5244 | IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr); |
| 5183 | ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value); | |
| 5245 | ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value); | |
| 5184 | 5246 | |
| 5185 | 5247 | IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope); |
| 5186 | 5248 | if (else_result == irb->codegen->invalid_instruction) |
| ... | ... | @@ -5220,10 +5282,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 5220 | 5282 | } |
| 5221 | 5283 | |
| 5222 | 5284 | ir_set_cursor_at_end_and_append_block(irb, body_block); |
| 5223 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false); | |
| 5285 | IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false); | |
| 5224 | 5286 | IrInstruction *var_value = node->data.while_expr.var_is_ptr ? |
| 5225 | 5287 | var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value); |
| 5226 | ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value); | |
| 5288 | ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value); | |
| 5227 | 5289 | |
| 5228 | 5290 | ZigList<IrInstruction *> incoming_values = {0}; |
| 5229 | 5291 | ZigList<IrBasicBlock *> incoming_blocks = {0}; |
| ... | ... | @@ -5380,7 +5442,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5380 | 5442 | Scope *child_scope = elem_var->child_scope; |
| 5381 | 5443 | |
| 5382 | 5444 | IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node); |
| 5383 | ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value); | |
| 5445 | ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value); | |
| 5384 | 5446 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var); |
| 5385 | 5447 | |
| 5386 | 5448 | AstNode *index_var_source_node; |
| ... | ... | @@ -5398,7 +5460,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 5398 | 5460 | IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize); |
| 5399 | 5461 | IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); |
| 5400 | 5462 | IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1); |
| 5401 | ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero); | |
| 5463 | ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero); | |
| 5402 | 5464 | IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var); |
| 5403 | 5465 | |
| 5404 | 5466 | |
| ... | ... | @@ -5622,8 +5684,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5622 | 5684 | return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile); |
| 5623 | 5685 | } |
| 5624 | 5686 | |
| 5625 | static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) { | |
| 5626 | assert(node->type == NodeTypeTestExpr); | |
| 5687 | static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) { | |
| 5688 | assert(node->type == NodeTypeIfOptional); | |
| 5627 | 5689 | |
| 5628 | 5690 | Buf *var_symbol = node->data.test_expr.var_symbol; |
| 5629 | 5691 | AstNode *expr_node = node->data.test_expr.target_node; |
| ... | ... | @@ -5661,9 +5723,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no |
| 5661 | 5723 | ZigVar *var = ir_create_var(irb, node, subexpr_scope, |
| 5662 | 5724 | var_symbol, is_const, is_const, is_shadowable, is_comptime); |
| 5663 | 5725 | |
| 5664 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, subexpr_scope, node, maybe_val_ptr, false); | |
| 5726 | IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false); | |
| 5665 | 5727 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value); |
| 5666 | ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); | |
| 5728 | ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value); | |
| 5667 | 5729 | var_scope = var->child_scope; |
| 5668 | 5730 | } else { |
| 5669 | 5731 | var_scope = subexpr_scope; |
| ... | ... | @@ -5738,7 +5800,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 5738 | 5800 | |
| 5739 | 5801 | IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false); |
| 5740 | 5802 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value); |
| 5741 | ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); | |
| 5803 | ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value); | |
| 5742 | 5804 | var_scope = var->child_scope; |
| 5743 | 5805 | } else { |
| 5744 | 5806 | var_scope = subexpr_scope; |
| ... | ... | @@ -5763,7 +5825,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 5763 | 5825 | err_symbol, is_const, is_const, is_shadowable, is_comptime); |
| 5764 | 5826 | |
| 5765 | 5827 | IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr); |
| 5766 | ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value); | |
| 5828 | ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value); | |
| 5767 | 5829 | err_var_scope = var->child_scope; |
| 5768 | 5830 | } else { |
| 5769 | 5831 | err_var_scope = subexpr_scope; |
| ... | ... | @@ -5818,7 +5880,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit |
| 5818 | 5880 | var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); |
| 5819 | 5881 | } |
| 5820 | 5882 | IrInstruction *var_type = nullptr; // infer the type |
| 5821 | ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, nullptr, var_value); | |
| 5883 | ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value); | |
| 5822 | 5884 | } else { |
| 5823 | 5885 | child_scope = scope; |
| 5824 | 5886 | } |
| ... | ... | @@ -6228,7 +6290,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) |
| 6228 | 6290 | return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true); |
| 6229 | 6291 | } |
| 6230 | 6292 | |
| 6231 | static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | |
| 6293 | static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | |
| 6232 | 6294 | assert(node->type == NodeTypeUnwrapErrorExpr); |
| 6233 | 6295 | |
| 6234 | 6296 | AstNode *op1_node = node->data.unwrap_err_expr.op1; |
| ... | ... | @@ -6242,7 +6304,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 6242 | 6304 | add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name))); |
| 6243 | 6305 | return irb->codegen->invalid_instruction; |
| 6244 | 6306 | } |
| 6245 | return ir_gen_err_assert_ok(irb, parent_scope, node, op1_node, LValNone); | |
| 6307 | return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, LValNone); | |
| 6246 | 6308 | } |
| 6247 | 6309 | |
| 6248 | 6310 | |
| ... | ... | @@ -6276,7 +6338,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN |
| 6276 | 6338 | is_const, is_const, is_shadowable, is_comptime); |
| 6277 | 6339 | err_scope = var->child_scope; |
| 6278 | 6340 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr); |
| 6279 | ir_build_var_decl(irb, err_scope, var_node, var, nullptr, nullptr, err_val); | |
| 6341 | ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val); | |
| 6280 | 6342 | } else { |
| 6281 | 6343 | err_scope = parent_scope; |
| 6282 | 6344 | } |
| ... | ... | @@ -6312,7 +6374,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o |
| 6312 | 6374 | ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope; |
| 6313 | 6375 | if (need_comma) |
| 6314 | 6376 | buf_append_char(name, ','); |
| 6315 | render_const_value(codegen, name, var_scope->var->value); | |
| 6377 | // TODO: const ptr reinterpret here to make the var type agree with the value? | |
| 6378 | render_const_value(codegen, name, var_scope->var->const_value); | |
| 6316 | 6379 | return true; |
| 6317 | 6380 | } |
| 6318 | 6381 | |
| ... | ... | @@ -6562,7 +6625,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode |
| 6562 | 6625 | IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010 |
| 6563 | 6626 | |
| 6564 | 6627 | // TODO relies on Zig not re-ordering fields |
| 6565 | IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst); | |
| 6628 | IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst); | |
| 6566 | 6629 | IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst); |
| 6567 | 6630 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); |
| 6568 | 6631 | IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| ... | ... | @@ -6640,7 +6703,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode |
| 6640 | 6703 | get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void)); |
| 6641 | 6704 | |
| 6642 | 6705 | // TODO relies on Zig not re-ordering fields |
| 6643 | IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst); | |
| 6706 | IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst); | |
| 6644 | 6707 | IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst); |
| 6645 | 6708 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); |
| 6646 | 6709 | IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, |
| ... | ... | @@ -6756,7 +6819,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n |
| 6756 | 6819 | IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst); |
| 6757 | 6820 | IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type); |
| 6758 | 6821 | ir_build_await_bookkeeping(irb, scope, node, promise_result_type); |
| 6759 | ir_build_var_decl(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value); | |
| 6822 | ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value); | |
| 6760 | 6823 | IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var); |
| 6761 | 6824 | ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr); |
| 6762 | 6825 | IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle); |
| ... | ... | @@ -7050,7 +7113,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 7050 | 7113 | if (maybe_ptr == irb->codegen->invalid_instruction) |
| 7051 | 7114 | return irb->codegen->invalid_instruction; |
| 7052 | 7115 | |
| 7053 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true); | |
| 7116 | IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true); | |
| 7054 | 7117 | if (lval == LValPtr) |
| 7055 | 7118 | return unwrapped_ptr; |
| 7056 | 7119 | |
| ... | ... | @@ -7074,8 +7137,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 7074 | 7137 | return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval); |
| 7075 | 7138 | case NodeTypeIfErrorExpr: |
| 7076 | 7139 | return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval); |
| 7077 | case NodeTypeTestExpr: | |
| 7078 | return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval); | |
| 7140 | case NodeTypeIfOptional: | |
| 7141 | return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval); | |
| 7079 | 7142 | case NodeTypeSwitchExpr: |
| 7080 | 7143 | return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval); |
| 7081 | 7144 | case NodeTypeCompTime: |
| ... | ... | @@ -7093,7 +7156,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 7093 | 7156 | case NodeTypeSliceExpr: |
| 7094 | 7157 | return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval); |
| 7095 | 7158 | case NodeTypeUnwrapErrorExpr: |
| 7096 | return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval); | |
| 7159 | return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval); | |
| 7097 | 7160 | case NodeTypeContainerDecl: |
| 7098 | 7161 | return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); |
| 7099 | 7162 | case NodeTypeFnProto: |
| ... | ... | @@ -7152,6 +7215,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7152 | 7215 | ir_ref_bb(irb->current_basic_block); |
| 7153 | 7216 | |
| 7154 | 7217 | ZigFn *fn_entry = exec_fn_entry(irb->exec); |
| 7218 | ||
| 7155 | 7219 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| 7156 | 7220 | IrInstruction *coro_id; |
| 7157 | 7221 | IrInstruction *u8_ptr_type; |
| ... | ... | @@ -7172,27 +7236,27 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7172 | 7236 | ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type); |
| 7173 | 7237 | IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type); |
| 7174 | 7238 | // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa |
| 7175 | ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef); | |
| 7239 | ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef); | |
| 7176 | 7240 | coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var); |
| 7177 | 7241 | |
| 7178 | 7242 | ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false); |
| 7179 | 7243 | IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node); |
| 7180 | 7244 | IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node, |
| 7181 | 7245 | get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise)); |
| 7182 | ir_build_var_decl(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value); | |
| 7246 | ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value); | |
| 7183 | 7247 | irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var); |
| 7184 | 7248 | |
| 7185 | 7249 | u8_ptr_type = ir_build_const_type(irb, coro_scope, node, |
| 7186 | 7250 | get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false)); |
| 7187 | IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr); | |
| 7251 | IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr); | |
| 7188 | 7252 | coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr); |
| 7189 | 7253 | coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false); |
| 7190 | 7254 | IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node); |
| 7191 | ir_build_var_decl(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size); | |
| 7255 | ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size); | |
| 7192 | 7256 | IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node, |
| 7193 | 7257 | ImplicitAllocatorIdArg); |
| 7194 | 7258 | irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false); |
| 7195 | ir_build_var_decl(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr); | |
| 7259 | ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr); | |
| 7196 | 7260 | Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); |
| 7197 | 7261 | IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name); |
| 7198 | 7262 | IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr); |
| ... | ... | @@ -7208,7 +7272,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7208 | 7272 | ir_build_return(irb, coro_scope, node, undef); |
| 7209 | 7273 | |
| 7210 | 7274 | ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block); |
| 7211 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr); | |
| 7275 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr); | |
| 7212 | 7276 | irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr); |
| 7213 | 7277 | |
| 7214 | 7278 | Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME); |
| ... | ... | @@ -7286,8 +7350,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7286 | 7350 | get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, |
| 7287 | 7351 | false, false, PtrLenUnknown, 0, 0, 0)); |
| 7288 | 7352 | IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr); |
| 7289 | IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr); | |
| 7290 | IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, | |
| 7353 | IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr); | |
| 7354 | IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, | |
| 7291 | 7355 | irb->exec->coro_result_field_ptr); |
| 7292 | 7356 | IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node, |
| 7293 | 7357 | fn_entry->type_entry->data.fn.fn_type_id.return_type); |
| ... | ... | @@ -7303,7 +7367,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7303 | 7367 | // Before we destroy the coroutine frame, we need to load the target promise into |
| 7304 | 7368 | // a register or local variable which does not get spilled into the frame, |
| 7305 | 7369 | // otherwise llvm tries to access memory inside the destroyed frame. |
| 7306 | IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node, | |
| 7370 | IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, | |
| 7307 | 7371 | irb->exec->await_handle_var_ptr, false); |
| 7308 | 7372 | IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr); |
| 7309 | 7373 | ir_build_br(irb, scope, node, check_free_block, const_bool_false); |
| ... | ... | @@ -7338,7 +7402,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 7338 | 7402 | IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node, |
| 7339 | 7403 | get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8, |
| 7340 | 7404 | false, false, PtrLenUnknown, 0, 0, 0)); |
| 7341 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe); | |
| 7405 | IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe); | |
| 7342 | 7406 | IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false); |
| 7343 | 7407 | IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var); |
| 7344 | 7408 | IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr); |
| ... | ... | @@ -7435,7 +7499,7 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal |
| 7435 | 7499 | return val; |
| 7436 | 7500 | } |
| 7437 | 7501 | |
| 7438 | static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) { | |
| 7502 | static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) { | |
| 7439 | 7503 | IrBasicBlock *bb = exec->basic_block_list.at(0); |
| 7440 | 7504 | for (size_t i = 0; i < bb->instruction_list.length; i += 1) { |
| 7441 | 7505 | IrInstruction *instruction = bb->instruction_list.at(i); |
| ... | ... | @@ -7445,16 +7509,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) |
| 7445 | 7509 | if (value->value.special == ConstValSpecialRuntime) { |
| 7446 | 7510 | exec_add_error_node(codegen, exec, value->source_node, |
| 7447 | 7511 | buf_sprintf("unable to evaluate constant expression")); |
| 7448 | return codegen->invalid_instruction; | |
| 7512 | return &codegen->invalid_instruction->value; | |
| 7449 | 7513 | } |
| 7450 | return value; | |
| 7514 | return &value->value; | |
| 7451 | 7515 | } else if (ir_has_side_effects(instruction)) { |
| 7452 | 7516 | exec_add_error_node(codegen, exec, instruction->source_node, |
| 7453 | 7517 | buf_sprintf("unable to evaluate constant expression")); |
| 7454 | return codegen->invalid_instruction; | |
| 7518 | return &codegen->invalid_instruction->value; | |
| 7455 | 7519 | } |
| 7456 | 7520 | } |
| 7457 | return codegen->invalid_instruction; | |
| 7521 | return &codegen->invalid_instruction->value; | |
| 7458 | 7522 | } |
| 7459 | 7523 | |
| 7460 | 7524 | static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) { |
| ... | ... | @@ -8768,13 +8832,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 8768 | 8832 | size_t errors_count = 0; |
| 8769 | 8833 | ZigType *err_set_type = nullptr; |
| 8770 | 8834 | if (prev_inst->value.type->id == ZigTypeIdErrorSet) { |
| 8835 | if (!resolve_inferred_error_set(ira->codegen, prev_inst->value.type, prev_inst->source_node)) { | |
| 8836 | return ira->codegen->builtin_types.entry_invalid; | |
| 8837 | } | |
| 8771 | 8838 | if (type_is_global_error_set(prev_inst->value.type)) { |
| 8772 | 8839 | err_set_type = ira->codegen->builtin_types.entry_global_error_set; |
| 8773 | 8840 | } else { |
| 8774 | 8841 | err_set_type = prev_inst->value.type; |
| 8775 | if (!resolve_inferred_error_set(ira->codegen, err_set_type, prev_inst->source_node)) { | |
| 8776 | return ira->codegen->builtin_types.entry_invalid; | |
| 8777 | } | |
| 8778 | 8842 | update_errors_helper(ira->codegen, &errors, &errors_count); |
| 8779 | 8843 | |
| 8780 | 8844 | for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) { |
| ... | ... | @@ -8933,6 +8997,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 8933 | 8997 | if (prev_type->id == ZigTypeIdArray) { |
| 8934 | 8998 | convert_to_const_slice = true; |
| 8935 | 8999 | } |
| 9000 | if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) { | |
| 9001 | return ira->codegen->builtin_types.entry_invalid; | |
| 9002 | } | |
| 8936 | 9003 | if (type_is_global_error_set(cur_type)) { |
| 8937 | 9004 | err_set_type = ira->codegen->builtin_types.entry_global_error_set; |
| 8938 | 9005 | continue; |
| ... | ... | @@ -8940,9 +9007,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT |
| 8940 | 9007 | if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) { |
| 8941 | 9008 | continue; |
| 8942 | 9009 | } |
| 8943 | if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) { | |
| 8944 | return ira->codegen->builtin_types.entry_invalid; | |
| 8945 | } | |
| 8946 | 9010 | |
| 8947 | 9011 | update_errors_helper(ira->codegen, &errors, &errors_count); |
| 8948 | 9012 | |
| ... | ... | @@ -9432,14 +9496,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_ |
| 9432 | 9496 | } |
| 9433 | 9497 | return true; |
| 9434 | 9498 | } |
| 9499 | ||
| 9500 | static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) { | |
| 9501 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | |
| 9502 | old_instruction->scope, old_instruction->source_node); | |
| 9503 | IrInstruction *new_instruction = &const_instruction->base; | |
| 9504 | new_instruction->value.type = ty; | |
| 9505 | new_instruction->value.special = ConstValSpecialStatic; | |
| 9506 | return new_instruction; | |
| 9507 | } | |
| 9508 | ||
| 9435 | 9509 | static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, |
| 9436 | 9510 | ZigType *wanted_type, CastOp cast_op, bool need_alloca) |
| 9437 | 9511 | { |
| 9438 | 9512 | if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) && |
| 9439 | 9513 | cast_op != CastOpResizeSlice) |
| 9440 | 9514 | { |
| 9441 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 9442 | source_instr->source_node, wanted_type); | |
| 9515 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 9443 | 9516 | if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type, |
| 9444 | 9517 | &result->value, wanted_type)) |
| 9445 | 9518 | { |
| ... | ... | @@ -9476,9 +9549,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira, |
| 9476 | 9549 | if (pointee == nullptr) |
| 9477 | 9550 | return ira->codegen->invalid_instruction; |
| 9478 | 9551 | if (pointee->special != ConstValSpecialRuntime) { |
| 9479 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 9480 | source_instr->source_node, wanted_type); | |
| 9481 | result->value.type = wanted_type; | |
| 9552 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 9482 | 9553 | result->value.data.x_ptr.special = ConstPtrSpecialBaseArray; |
| 9483 | 9554 | result->value.data.x_ptr.mut = value->value.data.x_ptr.mut; |
| 9484 | 9555 | result->value.data.x_ptr.data.base_array.array_val = pointee; |
| ... | ... | @@ -9517,8 +9588,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc |
| 9517 | 9588 | assert(is_slice(wanted_type)); |
| 9518 | 9589 | bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const; |
| 9519 | 9590 | |
| 9520 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 9521 | source_instr->source_node, wanted_type); | |
| 9591 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 9522 | 9592 | init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const); |
| 9523 | 9593 | result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = |
| 9524 | 9594 | value->value.data.x_ptr.mut; |
| ... | ... | @@ -9653,15 +9723,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction) |
| 9653 | 9723 | return instruction; |
| 9654 | 9724 | } |
| 9655 | 9725 | |
| 9656 | static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) { | |
| 9657 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | |
| 9658 | old_instruction->scope, old_instruction->source_node); | |
| 9659 | IrInstruction *new_instruction = &const_instruction->base; | |
| 9660 | new_instruction->value.type = ty; | |
| 9661 | new_instruction->value.special = ConstValSpecialStatic; | |
| 9662 | return new_instruction; | |
| 9663 | } | |
| 9664 | ||
| 9665 | 9726 | static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) { |
| 9666 | 9727 | IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type); |
| 9667 | 9728 | result->value.data.x_type = ty; |
| ... | ... | @@ -9719,13 +9780,13 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un |
| 9719 | 9780 | zig_unreachable(); |
| 9720 | 9781 | } |
| 9721 | 9782 | |
| 9722 | IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | |
| 9783 | ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | |
| 9723 | 9784 | ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, |
| 9724 | 9785 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, |
| 9725 | 9786 | IrExecutable *parent_exec) |
| 9726 | 9787 | { |
| 9727 | 9788 | if (expected_type != nullptr && type_is_invalid(expected_type)) |
| 9728 | return codegen->invalid_instruction; | |
| 9789 | return &codegen->invalid_instruction->value; | |
| 9729 | 9790 | |
| 9730 | 9791 | IrExecutable *ir_executable = allocate<IrExecutable>(1); |
| 9731 | 9792 | ir_executable->source_node = source_node; |
| ... | ... | @@ -9738,13 +9799,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node |
| 9738 | 9799 | ir_gen(codegen, node, scope, ir_executable); |
| 9739 | 9800 | |
| 9740 | 9801 | if (ir_executable->invalid) |
| 9741 | return codegen->invalid_instruction; | |
| 9802 | return &codegen->invalid_instruction->value; | |
| 9742 | 9803 | |
| 9743 | 9804 | if (codegen->verbose_ir) { |
| 9744 | 9805 | fprintf(stderr, "\nSource: "); |
| 9745 | 9806 | ast_render(codegen, stderr, node, 4); |
| 9746 | 9807 | fprintf(stderr, "\n{ // (IR)\n"); |
| 9747 | ir_print(codegen, stderr, ir_executable, 4); | |
| 9808 | ir_print(codegen, stderr, ir_executable, 2); | |
| 9748 | 9809 | fprintf(stderr, "}\n"); |
| 9749 | 9810 | } |
| 9750 | 9811 | IrExecutable *analyzed_executable = allocate<IrExecutable>(1); |
| ... | ... | @@ -9760,11 +9821,11 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node |
| 9760 | 9821 | analyzed_executable->begin_scope = scope; |
| 9761 | 9822 | ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node); |
| 9762 | 9823 | if (type_is_invalid(result_type)) |
| 9763 | return codegen->invalid_instruction; | |
| 9824 | return &codegen->invalid_instruction->value; | |
| 9764 | 9825 | |
| 9765 | 9826 | if (codegen->verbose_ir) { |
| 9766 | 9827 | fprintf(stderr, "{ // (analyzed)\n"); |
| 9767 | ir_print(codegen, stderr, analyzed_executable, 4); | |
| 9828 | ir_print(codegen, stderr, analyzed_executable, 2); | |
| 9768 | 9829 | fprintf(stderr, "}\n"); |
| 9769 | 9830 | } |
| 9770 | 9831 | |
| ... | ... | @@ -9838,7 +9899,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| 9838 | 9899 | return const_val->data.x_ptr.data.fn.fn_entry; |
| 9839 | 9900 | } |
| 9840 | 9901 | |
| 9841 | static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) { | |
| 9902 | static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, | |
| 9903 | ZigType *wanted_type) | |
| 9904 | { | |
| 9842 | 9905 | assert(wanted_type->id == ZigTypeIdOptional); |
| 9843 | 9906 | |
| 9844 | 9907 | if (instr_is_comptime(value)) { |
| ... | ... | @@ -9854,7 +9917,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc |
| 9854 | 9917 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 9855 | 9918 | source_instr->scope, source_instr->source_node); |
| 9856 | 9919 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 9857 | if (get_codegen_ptr_type(wanted_type) != nullptr) { | |
| 9920 | if (types_have_same_zig_comptime_repr(wanted_type, payload_type)) { | |
| 9858 | 9921 | copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst); |
| 9859 | 9922 | } else { |
| 9860 | 9923 | const_instruction->base.value.data.x_optional = val; |
| ... | ... | @@ -9885,11 +9948,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction |
| 9885 | 9948 | if (!val) |
| 9886 | 9949 | return ira->codegen->invalid_instruction; |
| 9887 | 9950 | |
| 9951 | ConstExprValue *err_set_val = create_const_vals(1); | |
| 9952 | err_set_val->type = wanted_type->data.error_union.err_set_type; | |
| 9953 | err_set_val->special = ConstValSpecialStatic; | |
| 9954 | err_set_val->data.x_err_set = nullptr; | |
| 9955 | ||
| 9888 | 9956 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 9889 | 9957 | source_instr->scope, source_instr->source_node); |
| 9890 | 9958 | const_instruction->base.value.type = wanted_type; |
| 9891 | 9959 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 9892 | const_instruction->base.value.data.x_err_union.err = nullptr; | |
| 9960 | const_instruction->base.value.data.x_err_union.error_set = err_set_val; | |
| 9893 | 9961 | const_instruction->base.value.data.x_err_union.payload = val; |
| 9894 | 9962 | return &const_instruction->base; |
| 9895 | 9963 | } |
| ... | ... | @@ -9954,11 +10022,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so |
| 9954 | 10022 | if (!val) |
| 9955 | 10023 | return ira->codegen->invalid_instruction; |
| 9956 | 10024 | |
| 10025 | ConstExprValue *err_set_val = create_const_vals(1); | |
| 10026 | err_set_val->special = ConstValSpecialStatic; | |
| 10027 | err_set_val->type = wanted_type->data.error_union.err_set_type; | |
| 10028 | err_set_val->data.x_err_set = val->data.x_err_set; | |
| 10029 | ||
| 9957 | 10030 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 9958 | 10031 | source_instr->scope, source_instr->source_node); |
| 9959 | 10032 | const_instruction->base.value.type = wanted_type; |
| 9960 | 10033 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 9961 | const_instruction->base.value.data.x_err_union.err = val->data.x_err_set; | |
| 10034 | const_instruction->base.value.data.x_err_union.error_set = err_set_val; | |
| 9962 | 10035 | const_instruction->base.value.data.x_err_union.payload = nullptr; |
| 9963 | 10036 | return &const_instruction->base; |
| 9964 | 10037 | } |
| ... | ... | @@ -9980,8 +10053,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so |
| 9980 | 10053 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 9981 | 10054 | const_instruction->base.value.special = ConstValSpecialStatic; |
| 9982 | 10055 | if (get_codegen_ptr_type(wanted_type) != nullptr) { |
| 9983 | const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | |
| 9984 | const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0; | |
| 10056 | const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull; | |
| 10057 | } else if (is_opt_err_set(wanted_type)) { | |
| 10058 | const_instruction->base.value.data.x_err_set = nullptr; | |
| 9985 | 10059 | } else { |
| 9986 | 10060 | const_instruction->base.value.data.x_optional = nullptr; |
| 9987 | 10061 | } |
| ... | ... | @@ -10014,7 +10088,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi |
| 10014 | 10088 | source_instruction->source_node, value, is_const, is_volatile); |
| 10015 | 10089 | new_instruction->value.type = ptr_type; |
| 10016 | 10090 | new_instruction->value.data.rh_ptr = RuntimeHintPtrStack; |
| 10017 | if (type_has_bits(ptr_type)) { | |
| 10091 | if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) { | |
| 10018 | 10092 | ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); |
| 10019 | 10093 | assert(fn_entry); |
| 10020 | 10094 | fn_entry->alloca_list.append(new_instruction); |
| ... | ... | @@ -10040,20 +10114,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 10040 | 10114 | ZigType *array_type = array->value.type; |
| 10041 | 10115 | assert(array_type->id == ZigTypeIdArray); |
| 10042 | 10116 | |
| 10043 | if (instr_is_comptime(array)) { | |
| 10044 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10045 | source_instr->source_node, wanted_type); | |
| 10117 | if (instr_is_comptime(array) || array_type->data.array.len == 0) { | |
| 10118 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10046 | 10119 | init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true); |
| 10047 | 10120 | result->value.type = wanted_type; |
| 10048 | 10121 | return result; |
| 10049 | 10122 | } |
| 10050 | 10123 | |
| 10051 | IrInstruction *start = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10052 | source_instr->source_node, ira->codegen->builtin_types.entry_usize); | |
| 10124 | IrInstruction *start = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize); | |
| 10053 | 10125 | init_const_usize(ira->codegen, &start->value, 0); |
| 10054 | 10126 | |
| 10055 | IrInstruction *end = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10056 | source_instr->source_node, ira->codegen->builtin_types.entry_usize); | |
| 10127 | IrInstruction *end = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize); | |
| 10057 | 10128 | init_const_usize(ira->codegen, &end->value, array_type->data.array.len); |
| 10058 | 10129 | |
| 10059 | 10130 | if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false); |
| ... | ... | @@ -10092,8 +10163,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour |
| 10092 | 10163 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 10093 | 10164 | if (!val) |
| 10094 | 10165 | return ira->codegen->invalid_instruction; |
| 10095 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10096 | source_instr->source_node, wanted_type); | |
| 10166 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10097 | 10167 | init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag); |
| 10098 | 10168 | return result; |
| 10099 | 10169 | } |
| ... | ... | @@ -10103,8 +10173,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour |
| 10103 | 10173 | actual_type->data.enumeration.src_field_count == 1) |
| 10104 | 10174 | { |
| 10105 | 10175 | assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int); |
| 10106 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10107 | source_instr->source_node, wanted_type); | |
| 10176 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10108 | 10177 | init_const_bigint(&result->value, wanted_type, |
| 10109 | 10178 | &actual_type->data.enumeration.fields[0].value); |
| 10110 | 10179 | return result; |
| ... | ... | @@ -10127,8 +10196,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou |
| 10127 | 10196 | ConstExprValue *val = ir_resolve_const(ira, target, UndefBad); |
| 10128 | 10197 | if (!val) |
| 10129 | 10198 | return ira->codegen->invalid_instruction; |
| 10130 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10131 | source_instr->source_node, wanted_type); | |
| 10199 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10132 | 10200 | result->value.special = ConstValSpecialStatic; |
| 10133 | 10201 | result->value.type = wanted_type; |
| 10134 | 10202 | bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag); |
| ... | ... | @@ -10139,8 +10207,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou |
| 10139 | 10207 | if (wanted_type->data.enumeration.layout == ContainerLayoutAuto && |
| 10140 | 10208 | wanted_type->data.enumeration.src_field_count == 1) |
| 10141 | 10209 | { |
| 10142 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10143 | source_instr->source_node, wanted_type); | |
| 10210 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10144 | 10211 | result->value.special = ConstValSpecialStatic; |
| 10145 | 10212 | result->value.type = wanted_type; |
| 10146 | 10213 | TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field; |
| ... | ... | @@ -10157,8 +10224,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou |
| 10157 | 10224 | static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr, |
| 10158 | 10225 | IrInstruction *target, ZigType *wanted_type) |
| 10159 | 10226 | { |
| 10160 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10161 | source_instr->source_node, wanted_type); | |
| 10227 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10162 | 10228 | init_const_undefined(ira->codegen, &result->value); |
| 10163 | 10229 | return result; |
| 10164 | 10230 | } |
| ... | ... | @@ -10190,8 +10256,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so |
| 10190 | 10256 | buf_sprintf("field '%s' declared here", buf_ptr(union_field->name))); |
| 10191 | 10257 | return ira->codegen->invalid_instruction; |
| 10192 | 10258 | } |
| 10193 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10194 | source_instr->source_node, wanted_type); | |
| 10259 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10195 | 10260 | result->value.special = ConstValSpecialStatic; |
| 10196 | 10261 | result->value.type = wanted_type; |
| 10197 | 10262 | bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag); |
| ... | ... | @@ -10246,8 +10311,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction |
| 10246 | 10311 | return ira->codegen->invalid_instruction; |
| 10247 | 10312 | } |
| 10248 | 10313 | } |
| 10249 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10250 | source_instr->source_node, wanted_type); | |
| 10314 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10251 | 10315 | result->value.type = wanted_type; |
| 10252 | 10316 | if (wanted_type->id == ZigTypeIdInt) { |
| 10253 | 10317 | bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint); |
| ... | ... | @@ -10301,8 +10365,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour |
| 10301 | 10365 | return ira->codegen->invalid_instruction; |
| 10302 | 10366 | } |
| 10303 | 10367 | |
| 10304 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10305 | source_instr->source_node, wanted_type); | |
| 10368 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10306 | 10369 | bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint); |
| 10307 | 10370 | return result; |
| 10308 | 10371 | } |
| ... | ... | @@ -10320,8 +10383,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction |
| 10320 | 10383 | if (!val) |
| 10321 | 10384 | return ira->codegen->invalid_instruction; |
| 10322 | 10385 | |
| 10323 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10324 | source_instr->source_node, wanted_type); | |
| 10386 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10325 | 10387 | if (wanted_type->id == ZigTypeIdComptimeFloat) { |
| 10326 | 10388 | float_init_float(&result->value, val); |
| 10327 | 10389 | } else if (wanted_type->id == ZigTypeIdComptimeInt) { |
| ... | ... | @@ -10344,8 +10406,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc |
| 10344 | 10406 | if (!val) |
| 10345 | 10407 | return ira->codegen->invalid_instruction; |
| 10346 | 10408 | |
| 10347 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10348 | source_instr->source_node, wanted_type); | |
| 10409 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10349 | 10410 | |
| 10350 | 10411 | if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) { |
| 10351 | 10412 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -10409,12 +10470,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc |
| 10409 | 10470 | if (!val) |
| 10410 | 10471 | return ira->codegen->invalid_instruction; |
| 10411 | 10472 | |
| 10412 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10413 | source_instr->source_node, wanted_type); | |
| 10473 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10414 | 10474 | |
| 10415 | 10475 | ErrorTableEntry *err; |
| 10416 | 10476 | if (err_type->id == ZigTypeIdErrorUnion) { |
| 10417 | err = val->data.x_err_union.err; | |
| 10477 | err = val->data.x_err_union.error_set->data.x_err_set; | |
| 10418 | 10478 | } else if (err_type->id == ZigTypeIdErrorSet) { |
| 10419 | 10479 | err = val->data.x_err_set; |
| 10420 | 10480 | } else { |
| ... | ... | @@ -10449,15 +10509,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc |
| 10449 | 10509 | return ira->codegen->invalid_instruction; |
| 10450 | 10510 | } |
| 10451 | 10511 | if (err_set_type->data.error_set.err_count == 0) { |
| 10452 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10453 | source_instr->source_node, wanted_type); | |
| 10454 | result->value.type = wanted_type; | |
| 10512 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10455 | 10513 | bigint_init_unsigned(&result->value.data.x_bigint, 0); |
| 10456 | 10514 | return result; |
| 10457 | 10515 | } else if (err_set_type->data.error_set.err_count == 1) { |
| 10458 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, | |
| 10459 | source_instr->source_node, wanted_type); | |
| 10460 | result->value.type = wanted_type; | |
| 10516 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10461 | 10517 | ErrorTableEntry *err = err_set_type->data.error_set.errors[0]; |
| 10462 | 10518 | bigint_init_unsigned(&result->value.data.x_bigint, err->value); |
| 10463 | 10519 | return result; |
| ... | ... | @@ -10504,8 +10560,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou |
| 10504 | 10560 | array_val->type = array_type; |
| 10505 | 10561 | array_val->data.x_array.special = ConstArraySpecialNone; |
| 10506 | 10562 | array_val->data.x_array.data.s_none.elements = pointee; |
| 10507 | array_val->data.x_array.data.s_none.parent.id = ConstParentIdScalar; | |
| 10508 | array_val->data.x_array.data.s_none.parent.data.p_scalar.scalar_val = pointee; | |
| 10563 | array_val->parent.id = ConstParentIdScalar; | |
| 10564 | array_val->parent.data.p_scalar.scalar_val = pointee; | |
| 10509 | 10565 | |
| 10510 | 10566 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, |
| 10511 | 10567 | source_instr->scope, source_instr->source_node); |
| ... | ... | @@ -10653,12 +10709,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10653 | 10709 | if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, |
| 10654 | 10710 | false).id == ConstCastResultIdOk) |
| 10655 | 10711 | { |
| 10656 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); | |
| 10712 | return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type); | |
| 10657 | 10713 | } else if (actual_type->id == ZigTypeIdComptimeInt || |
| 10658 | 10714 | actual_type->id == ZigTypeIdComptimeFloat) |
| 10659 | 10715 | { |
| 10660 | 10716 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) { |
| 10661 | return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type); | |
| 10717 | return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type); | |
| 10662 | 10718 | } else { |
| 10663 | 10719 | return ira->codegen->invalid_instruction; |
| 10664 | 10720 | } |
| ... | ... | @@ -10682,7 +10738,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10682 | 10738 | wanted_child_type); |
| 10683 | 10739 | if (type_is_invalid(cast1->value.type)) |
| 10684 | 10740 | return ira->codegen->invalid_instruction; |
| 10685 | return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type); | |
| 10741 | return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type); | |
| 10686 | 10742 | } |
| 10687 | 10743 | } |
| 10688 | 10744 | } |
| ... | ... | @@ -10735,6 +10791,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10735 | 10791 | (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt || |
| 10736 | 10792 | wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat)) |
| 10737 | 10793 | { |
| 10794 | if (value->value.special == ConstValSpecialUndef) { | |
| 10795 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); | |
| 10796 | result->value.special = ConstValSpecialUndef; | |
| 10797 | return result; | |
| 10798 | } | |
| 10738 | 10799 | if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) { |
| 10739 | 10800 | if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) { |
| 10740 | 10801 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| ... | ... | @@ -10788,6 +10849,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10788 | 10849 | |
| 10789 | 10850 | |
| 10790 | 10851 | // cast from [N]T to []const T |
| 10852 | // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this | |
| 10791 | 10853 | if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) { |
| 10792 | 10854 | ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; |
| 10793 | 10855 | assert(ptr_type->id == ZigTypeIdPointer); |
| ... | ... | @@ -10800,6 +10862,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10800 | 10862 | } |
| 10801 | 10863 | |
| 10802 | 10864 | // cast from [N]T to ?[]const T |
| 10865 | // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this | |
| 10803 | 10866 | if (wanted_type->id == ZigTypeIdOptional && |
| 10804 | 10867 | is_slice(wanted_type->data.maybe.child_type) && |
| 10805 | 10868 | actual_type->id == ZigTypeIdArray) |
| ... | ... | @@ -10894,7 +10957,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 10894 | 10957 | } |
| 10895 | 10958 | } |
| 10896 | 10959 | |
| 10897 | // cast from error set to error union type | |
| 10960 | // cast from E to E!T | |
| 10898 | 10961 | if (wanted_type->id == ZigTypeIdErrorUnion && |
| 10899 | 10962 | actual_type->id == ZigTypeIdErrorSet) |
| 10900 | 10963 | { |
| ... | ... | @@ -11046,8 +11109,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 11046 | 11109 | ZigType *child_type = type_entry->data.pointer.child_type; |
| 11047 | 11110 | // dereferencing a *u0 is comptime known to be 0 |
| 11048 | 11111 | if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) { |
| 11049 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, | |
| 11050 | source_instruction->source_node, child_type); | |
| 11112 | IrInstruction *result = ir_const(ira, source_instruction, child_type); | |
| 11051 | 11113 | init_const_unsigned_negative(&result->value, child_type, 0, false); |
| 11052 | 11114 | return result; |
| 11053 | 11115 | } |
| ... | ... | @@ -11061,8 +11123,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 11061 | 11123 | { |
| 11062 | 11124 | ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); |
| 11063 | 11125 | if (pointee->special != ConstValSpecialRuntime) { |
| 11064 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, | |
| 11065 | source_instruction->source_node, child_type); | |
| 11126 | IrInstruction *result = ir_const(ira, source_instruction, child_type); | |
| 11066 | 11127 | |
| 11067 | 11128 | if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value, |
| 11068 | 11129 | &ptr->value))) |
| ... | ... | @@ -11074,7 +11135,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 11074 | 11135 | } |
| 11075 | 11136 | } |
| 11076 | 11137 | } |
| 11077 | // TODO if the instruction is a const ref instruction we can skip it | |
| 11138 | // if the instruction is a const ref instruction we can skip it | |
| 11139 | if (ptr->id == IrInstructionIdRef) { | |
| 11140 | IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr); | |
| 11141 | return ref_inst->value; | |
| 11142 | } | |
| 11078 | 11143 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, |
| 11079 | 11144 | source_instruction->source_node, ptr); |
| 11080 | 11145 | load_ptr_instruction->value.type = child_type; |
| ... | ... | @@ -11321,8 +11386,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio |
| 11321 | 11386 | |
| 11322 | 11387 | static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) { |
| 11323 | 11388 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); |
| 11324 | // TODO determine if we need to use copy_const_val here | |
| 11325 | result->value = instruction->base.value; | |
| 11389 | copy_const_val(&result->value, &instruction->base.value, true); | |
| 11326 | 11390 | return result; |
| 11327 | 11391 | } |
| 11328 | 11392 | |
| ... | ... | @@ -11397,6 +11461,8 @@ static bool optional_value_is_null(ConstExprValue *val) { |
| 11397 | 11461 | if (get_codegen_ptr_type(val->type) != nullptr) { |
| 11398 | 11462 | return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && |
| 11399 | 11463 | val->data.x_ptr.data.hard_coded_addr.addr == 0; |
| 11464 | } else if (is_opt_err_set(val->type)) { | |
| 11465 | return val->data.x_err_set == nullptr; | |
| 11400 | 11466 | } else { |
| 11401 | 11467 | return val->data.x_optional == nullptr; |
| 11402 | 11468 | } |
| ... | ... | @@ -11596,19 +11662,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 11596 | 11662 | if (casted_op2 == ira->codegen->invalid_instruction) |
| 11597 | 11663 | return ira->codegen->invalid_instruction; |
| 11598 | 11664 | |
| 11599 | bool requires_comptime; | |
| 11600 | switch (type_requires_comptime(ira->codegen, resolved_type)) { | |
| 11601 | case ReqCompTimeYes: | |
| 11602 | requires_comptime = true; | |
| 11665 | bool one_possible_value; | |
| 11666 | switch (type_has_one_possible_value(ira->codegen, resolved_type)) { | |
| 11667 | case OnePossibleValueInvalid: | |
| 11668 | return ira->codegen->invalid_instruction; | |
| 11669 | case OnePossibleValueYes: | |
| 11670 | one_possible_value = true; | |
| 11603 | 11671 | break; |
| 11604 | case ReqCompTimeNo: | |
| 11605 | requires_comptime = false; | |
| 11672 | case OnePossibleValueNo: | |
| 11673 | one_possible_value = false; | |
| 11606 | 11674 | break; |
| 11607 | case ReqCompTimeInvalid: | |
| 11608 | return ira->codegen->invalid_instruction; | |
| 11609 | 11675 | } |
| 11610 | 11676 | |
| 11611 | bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type); | |
| 11612 | 11677 | if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) { |
| 11613 | 11678 | ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad); |
| 11614 | 11679 | if (op1_val == nullptr) |
| ... | ... | @@ -12497,13 +12562,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio |
| 12497 | 12562 | zig_unreachable(); |
| 12498 | 12563 | } |
| 12499 | 12564 | |
| 12500 | static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) { | |
| 12565 | static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, | |
| 12566 | IrInstructionDeclVarSrc *decl_var_instruction) | |
| 12567 | { | |
| 12501 | 12568 | Error err; |
| 12502 | 12569 | ZigVar *var = decl_var_instruction->var; |
| 12503 | 12570 | |
| 12504 | 12571 | IrInstruction *init_value = decl_var_instruction->init_value->child; |
| 12505 | 12572 | if (type_is_invalid(init_value->value.type)) { |
| 12506 | var->value->type = ira->codegen->builtin_types.entry_invalid; | |
| 12573 | var->var_type = ira->codegen->builtin_types.entry_invalid; | |
| 12507 | 12574 | return ira->codegen->invalid_instruction; |
| 12508 | 12575 | } |
| 12509 | 12576 | |
| ... | ... | @@ -12514,7 +12581,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12514 | 12581 | ZigType *proposed_type = ir_resolve_type(ira, var_type); |
| 12515 | 12582 | explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type); |
| 12516 | 12583 | if (type_is_invalid(explicit_type)) { |
| 12517 | var->value->type = ira->codegen->builtin_types.entry_invalid; | |
| 12584 | var->var_type = ira->codegen->builtin_types.entry_invalid; | |
| 12518 | 12585 | return ira->codegen->invalid_instruction; |
| 12519 | 12586 | } |
| 12520 | 12587 | } |
| ... | ... | @@ -12539,7 +12606,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12539 | 12606 | case ReqCompTimeInvalid: |
| 12540 | 12607 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12541 | 12608 | break; |
| 12542 | case ReqCompTimeYes: { | |
| 12609 | case ReqCompTimeYes: | |
| 12543 | 12610 | var_class_requires_const = true; |
| 12544 | 12611 | if (!var->gen_is_const && !is_comptime_var) { |
| 12545 | 12612 | ir_add_error_node(ira, source_node, |
| ... | ... | @@ -12548,7 +12615,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12548 | 12615 | result_type = ira->codegen->builtin_types.entry_invalid; |
| 12549 | 12616 | } |
| 12550 | 12617 | break; |
| 12551 | } | |
| 12552 | 12618 | case ReqCompTimeNo: |
| 12553 | 12619 | if (casted_init_value->value.special == ConstValSpecialStatic && |
| 12554 | 12620 | casted_init_value->value.type->id == ZigTypeIdFn && |
| ... | ... | @@ -12567,7 +12633,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12567 | 12633 | break; |
| 12568 | 12634 | } |
| 12569 | 12635 | |
| 12570 | if (var->value->type != nullptr && !is_comptime_var) { | |
| 12636 | if (var->var_type != nullptr && !is_comptime_var) { | |
| 12571 | 12637 | // This is at least the second time we've seen this variable declaration during analysis. |
| 12572 | 12638 | // This means that this is actually a different variable due to, e.g. an inline while loop. |
| 12573 | 12639 | // We make a new variable so that it can hold a different type, and so the debug info can |
| ... | ... | @@ -12589,8 +12655,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12589 | 12655 | // This must be done after possibly creating a new variable above |
| 12590 | 12656 | var->ref_count = 0; |
| 12591 | 12657 | |
| 12592 | var->value->type = result_type; | |
| 12593 | assert(var->value->type); | |
| 12658 | var->var_type = result_type; | |
| 12659 | assert(var->var_type); | |
| 12594 | 12660 | |
| 12595 | 12661 | if (type_is_invalid(result_type)) { |
| 12596 | 12662 | return ir_const_void(ira, &decl_var_instruction->base); |
| ... | ... | @@ -12598,13 +12664,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12598 | 12664 | |
| 12599 | 12665 | if (decl_var_instruction->align_value == nullptr) { |
| 12600 | 12666 | if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) { |
| 12601 | var->value->type = ira->codegen->builtin_types.entry_invalid; | |
| 12667 | var->var_type = ira->codegen->builtin_types.entry_invalid; | |
| 12602 | 12668 | return ir_const_void(ira, &decl_var_instruction->base); |
| 12603 | 12669 | } |
| 12604 | 12670 | var->align_bytes = get_abi_alignment(ira->codegen, result_type); |
| 12605 | 12671 | } else { |
| 12606 | 12672 | if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) { |
| 12607 | var->value->type = ira->codegen->builtin_types.entry_invalid; | |
| 12673 | var->var_type = ira->codegen->builtin_types.entry_invalid; | |
| 12608 | 12674 | } |
| 12609 | 12675 | } |
| 12610 | 12676 | |
| ... | ... | @@ -12621,7 +12687,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12621 | 12687 | } else if (is_comptime_var) { |
| 12622 | 12688 | ir_add_error(ira, &decl_var_instruction->base, |
| 12623 | 12689 | buf_sprintf("cannot store runtime value in compile time variable")); |
| 12624 | var->value->type = ira->codegen->builtin_types.entry_invalid; | |
| 12690 | var->var_type = ira->codegen->builtin_types.entry_invalid; | |
| 12625 | 12691 | return ira->codegen->invalid_instruction; |
| 12626 | 12692 | } |
| 12627 | 12693 | |
| ... | ... | @@ -12629,11 +12695,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12629 | 12695 | if (fn_entry) |
| 12630 | 12696 | fn_entry->variable_list.append(var); |
| 12631 | 12697 | |
| 12632 | IrInstruction *result = ir_build_var_decl(&ira->new_irb, | |
| 12633 | decl_var_instruction->base.scope, decl_var_instruction->base.source_node, | |
| 12634 | var, var_type, nullptr, casted_init_value); | |
| 12635 | result->value.type = ira->codegen->builtin_types.entry_void; | |
| 12636 | return result; | |
| 12698 | return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value); | |
| 12637 | 12699 | } |
| 12638 | 12700 | |
| 12639 | 12701 | static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) { |
| ... | ... | @@ -12963,7 +13025,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node |
| 12963 | 13025 | |
| 12964 | 13026 | Buf *param_name = param_decl_node->data.param_decl.name; |
| 12965 | 13027 | ZigVar *var = add_variable(ira->codegen, param_decl_node, |
| 12966 | *exec_scope, param_name, true, arg_val, nullptr); | |
| 13028 | *exec_scope, param_name, true, arg_val, nullptr, arg_val->type); | |
| 12967 | 13029 | *exec_scope = var->child_scope; |
| 12968 | 13030 | *next_proto_i += 1; |
| 12969 | 13031 | |
| ... | ... | @@ -13021,7 +13083,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod |
| 13021 | 13083 | if (!param_name) return false; |
| 13022 | 13084 | if (!is_var_args) { |
| 13023 | 13085 | ZigVar *var = add_variable(ira->codegen, param_decl_node, |
| 13024 | *child_scope, param_name, true, arg_val, nullptr); | |
| 13086 | *child_scope, param_name, true, arg_val, nullptr, arg_val->type); | |
| 13025 | 13087 | *child_scope = var->child_scope; |
| 13026 | 13088 | var->shadowable = !comptime_arg; |
| 13027 | 13089 | |
| ... | ... | @@ -13075,9 +13137,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) { |
| 13075 | 13137 | return fn_entry->variable_list.at(next_var_i); |
| 13076 | 13138 | } |
| 13077 | 13139 | |
| 13078 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, | |
| 13079 | ZigVar *var) | |
| 13080 | { | |
| 13140 | static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) { | |
| 13081 | 13141 | while (var->next_var != nullptr) { |
| 13082 | 13142 | var = var->next_var; |
| 13083 | 13143 | } |
| ... | ... | @@ -13086,14 +13146,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 13086 | 13146 | assert(ira->codegen->errors.length != 0); |
| 13087 | 13147 | return ira->codegen->invalid_instruction; |
| 13088 | 13148 | } |
| 13089 | if (var->value->type == nullptr || type_is_invalid(var->value->type)) | |
| 13149 | if (var->var_type == nullptr || type_is_invalid(var->var_type)) | |
| 13090 | 13150 | return ira->codegen->invalid_instruction; |
| 13091 | 13151 | |
| 13092 | 13152 | bool comptime_var_mem = ir_get_var_is_comptime(var); |
| 13093 | 13153 | |
| 13094 | 13154 | ConstExprValue *mem_slot = nullptr; |
| 13095 | if (var->value->special == ConstValSpecialStatic) { | |
| 13096 | mem_slot = var->value; | |
| 13155 | if (var->const_value->special == ConstValSpecialStatic) { | |
| 13156 | mem_slot = var->const_value; | |
| 13097 | 13157 | } else { |
| 13098 | 13158 | if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) { |
| 13099 | 13159 | // find the relevant exec_context |
| ... | ... | @@ -13122,7 +13182,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 13122 | 13182 | assert(!comptime_var_mem); |
| 13123 | 13183 | ptr_mut = ConstPtrMutRuntimeVar; |
| 13124 | 13184 | } |
| 13125 | return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type, | |
| 13185 | return ir_get_const_ptr(ira, instruction, mem_slot, var->var_type, | |
| 13126 | 13186 | ptr_mut, is_const, is_volatile, var->align_bytes); |
| 13127 | 13187 | } |
| 13128 | 13188 | } |
| ... | ... | @@ -13133,7 +13193,7 @@ no_mem_slot: |
| 13133 | 13193 | |
| 13134 | 13194 | IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb, |
| 13135 | 13195 | instruction->scope, instruction->source_node, var); |
| 13136 | var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type, | |
| 13196 | var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type, | |
| 13137 | 13197 | var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0); |
| 13138 | 13198 | |
| 13139 | 13199 | bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr); |
| ... | ... | @@ -13142,6 +13202,96 @@ no_mem_slot: |
| 13142 | 13202 | return var_ptr_instruction; |
| 13143 | 13203 | } |
| 13144 | 13204 | |
| 13205 | static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr, | |
| 13206 | IrInstruction *ptr, IrInstruction *uncasted_value) | |
| 13207 | { | |
| 13208 | if (ptr->value.type->id != ZigTypeIdPointer) { | |
| 13209 | ir_add_error(ira, ptr, | |
| 13210 | buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name))); | |
| 13211 | return ira->codegen->invalid_instruction; | |
| 13212 | } | |
| 13213 | ||
| 13214 | if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) { | |
| 13215 | return ir_const_void(ira, source_instr); | |
| 13216 | } | |
| 13217 | ||
| 13218 | if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) { | |
| 13219 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); | |
| 13220 | return ira->codegen->invalid_instruction; | |
| 13221 | } | |
| 13222 | ||
| 13223 | ZigType *child_type = ptr->value.type->data.pointer.child_type; | |
| 13224 | IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type); | |
| 13225 | if (value == ira->codegen->invalid_instruction) | |
| 13226 | return ira->codegen->invalid_instruction; | |
| 13227 | ||
| 13228 | if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | |
| 13229 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) { | |
| 13230 | ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); | |
| 13231 | return ira->codegen->invalid_instruction; | |
| 13232 | } | |
| 13233 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) { | |
| 13234 | if (instr_is_comptime(value)) { | |
| 13235 | ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node); | |
| 13236 | if (dest_val == nullptr) | |
| 13237 | return ira->codegen->invalid_instruction; | |
| 13238 | if (dest_val->special != ConstValSpecialRuntime) { | |
| 13239 | // TODO this allows a value stored to have the original value modified and then | |
| 13240 | // have that affect what should be a copy. We need some kind of advanced copy-on-write | |
| 13241 | // system to make these two tests pass at the same time: | |
| 13242 | // * "string literal used as comptime slice is memoized" | |
| 13243 | // * "comptime modification of const struct field" - except modified to avoid | |
| 13244 | // ConstPtrMutComptimeVar, thus defeating the logic below. | |
| 13245 | bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar; | |
| 13246 | copy_const_val(dest_val, &value->value, same_global_refs); | |
| 13247 | if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) { | |
| 13248 | switch (type_has_one_possible_value(ira->codegen, child_type)) { | |
| 13249 | case OnePossibleValueInvalid: | |
| 13250 | return ira->codegen->invalid_instruction; | |
| 13251 | case OnePossibleValueNo: | |
| 13252 | ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr; | |
| 13253 | break; | |
| 13254 | case OnePossibleValueYes: | |
| 13255 | break; | |
| 13256 | } | |
| 13257 | } | |
| 13258 | return ir_const_void(ira, source_instr); | |
| 13259 | } | |
| 13260 | } | |
| 13261 | ir_add_error(ira, source_instr, | |
| 13262 | buf_sprintf("cannot store runtime value in compile time variable")); | |
| 13263 | ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); | |
| 13264 | dest_val->type = ira->codegen->builtin_types.entry_invalid; | |
| 13265 | ||
| 13266 | return ira->codegen->invalid_instruction; | |
| 13267 | } | |
| 13268 | } | |
| 13269 | ||
| 13270 | switch (type_requires_comptime(ira->codegen, child_type)) { | |
| 13271 | case ReqCompTimeInvalid: | |
| 13272 | return ira->codegen->invalid_instruction; | |
| 13273 | case ReqCompTimeYes: | |
| 13274 | switch (type_has_one_possible_value(ira->codegen, ptr->value.type)) { | |
| 13275 | case OnePossibleValueInvalid: | |
| 13276 | return ira->codegen->invalid_instruction; | |
| 13277 | case OnePossibleValueNo: | |
| 13278 | ir_add_error(ira, source_instr, | |
| 13279 | buf_sprintf("cannot store runtime value in type '%s'", buf_ptr(&child_type->name))); | |
| 13280 | return ira->codegen->invalid_instruction; | |
| 13281 | case OnePossibleValueYes: | |
| 13282 | return ir_const_void(ira, source_instr); | |
| 13283 | } | |
| 13284 | zig_unreachable(); | |
| 13285 | case ReqCompTimeNo: | |
| 13286 | break; | |
| 13287 | } | |
| 13288 | ||
| 13289 | IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, | |
| 13290 | ptr, value); | |
| 13291 | result->value.type = ira->codegen->builtin_types.entry_void; | |
| 13292 | return result; | |
| 13293 | } | |
| 13294 | ||
| 13145 | 13295 | static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction, |
| 13146 | 13296 | ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref, |
| 13147 | 13297 | IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline) |
| ... | ... | @@ -13286,7 +13436,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13286 | 13436 | } |
| 13287 | 13437 | |
| 13288 | 13438 | bool cacheable = fn_eval_cacheable(exec_scope, return_type); |
| 13289 | IrInstruction *result = nullptr; | |
| 13439 | ConstExprValue *result = nullptr; | |
| 13290 | 13440 | if (cacheable) { |
| 13291 | 13441 | auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); |
| 13292 | 13442 | if (entry) |
| ... | ... | @@ -13302,18 +13452,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13302 | 13452 | |
| 13303 | 13453 | if (inferred_err_set_type != nullptr) { |
| 13304 | 13454 | inferred_err_set_type->data.error_set.infer_fn = nullptr; |
| 13305 | if (result->value.type->id == ZigTypeIdErrorUnion) { | |
| 13306 | if (result->value.data.x_err_union.err != nullptr) { | |
| 13455 | if (result->type->id == ZigTypeIdErrorUnion) { | |
| 13456 | ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set; | |
| 13457 | if (err != nullptr) { | |
| 13307 | 13458 | inferred_err_set_type->data.error_set.err_count = 1; |
| 13308 | 13459 | inferred_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1); |
| 13309 | inferred_err_set_type->data.error_set.errors[0] = result->value.data.x_err_union.err; | |
| 13460 | inferred_err_set_type->data.error_set.errors[0] = err; | |
| 13310 | 13461 | } |
| 13311 | ZigType *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type; | |
| 13462 | ZigType *fn_inferred_err_set_type = result->type->data.error_union.err_set_type; | |
| 13312 | 13463 | inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count; |
| 13313 | 13464 | inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors; |
| 13314 | } else if (result->value.type->id == ZigTypeIdErrorSet) { | |
| 13315 | inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count; | |
| 13316 | inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors; | |
| 13465 | } else if (result->type->id == ZigTypeIdErrorSet) { | |
| 13466 | inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count; | |
| 13467 | inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors; | |
| 13317 | 13468 | } |
| 13318 | 13469 | } |
| 13319 | 13470 | |
| ... | ... | @@ -13321,13 +13472,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13321 | 13472 | ira->codegen->memoized_fn_eval_table.put(exec_scope, result); |
| 13322 | 13473 | } |
| 13323 | 13474 | |
| 13324 | if (type_is_invalid(result->value.type)) | |
| 13475 | if (type_is_invalid(result->type)) | |
| 13325 | 13476 | return ira->codegen->invalid_instruction; |
| 13326 | 13477 | } |
| 13327 | 13478 | |
| 13328 | IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type); | |
| 13329 | // TODO should we use copy_const_val? | |
| 13330 | new_instruction->value = result->value; | |
| 13479 | IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type); | |
| 13480 | copy_const_val(&new_instruction->value, result, true); | |
| 13331 | 13481 | new_instruction->value.type = return_type; |
| 13332 | 13482 | return ir_finish_anal(ira, new_instruction); |
| 13333 | 13483 | } |
| ... | ... | @@ -13486,18 +13636,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13486 | 13636 | ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen, |
| 13487 | 13637 | first_var_arg, inst_fn_type_id.param_count); |
| 13488 | 13638 | ZigVar *var = add_variable(ira->codegen, param_decl_node, |
| 13489 | impl_fn->child_scope, param_name, true, var_args_val, nullptr); | |
| 13639 | impl_fn->child_scope, param_name, true, var_args_val, nullptr, var_args_val->type); | |
| 13490 | 13640 | impl_fn->child_scope = var->child_scope; |
| 13491 | 13641 | } |
| 13492 | 13642 | |
| 13493 | 13643 | if (fn_proto_node->data.fn_proto.align_expr != nullptr) { |
| 13494 | IrInstruction *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, | |
| 13644 | ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, | |
| 13495 | 13645 | fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), |
| 13496 | 13646 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, |
| 13497 | 13647 | nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec); |
| 13648 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, | |
| 13649 | impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); | |
| 13650 | const_instruction->base.value = *align_result; | |
| 13498 | 13651 | |
| 13499 | 13652 | uint32_t align_bytes = 0; |
| 13500 | ir_resolve_align(ira, align_result, &align_bytes); | |
| 13653 | ir_resolve_align(ira, &const_instruction->base, &align_bytes); | |
| 13501 | 13654 | impl_fn->align_bytes = align_bytes; |
| 13502 | 13655 | inst_fn_type_id.alignment = align_bytes; |
| 13503 | 13656 | } |
| ... | ... | @@ -13575,12 +13728,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13575 | 13728 | ira->codegen->fn_defs.append(impl_fn); |
| 13576 | 13729 | } |
| 13577 | 13730 | |
| 13578 | ZigType *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; | |
| 13579 | if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) { | |
| 13731 | FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id; | |
| 13732 | if (fn_type_can_fail(impl_fn_type_id)) { | |
| 13580 | 13733 | parent_fn_entry->calls_or_awaits_errorable_fn = true; |
| 13581 | 13734 | } |
| 13582 | 13735 | |
| 13583 | size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count; | |
| 13736 | size_t impl_param_count = impl_fn_type_id->param_count; | |
| 13584 | 13737 | if (call_instruction->is_async) { |
| 13585 | 13738 | IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry, |
| 13586 | 13739 | fn_ref, casted_args, impl_param_count, async_allocator_inst); |
| ... | ... | @@ -13593,9 +13746,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call |
| 13593 | 13746 | call_instruction->base.scope, call_instruction->base.source_node, |
| 13594 | 13747 | impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline, |
| 13595 | 13748 | call_instruction->is_async, nullptr, casted_new_stack); |
| 13596 | new_call_instruction->value.type = return_type; | |
| 13749 | new_call_instruction->value.type = impl_fn_type_id->return_type; | |
| 13597 | 13750 | |
| 13598 | ir_add_alloca(ira, new_call_instruction, return_type); | |
| 13751 | ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type); | |
| 13599 | 13752 | |
| 13600 | 13753 | return ir_finish_anal(ira, new_call_instruction); |
| 13601 | 13754 | } |
| ... | ... | @@ -13790,6 +13943,13 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source |
| 13790 | 13943 | switch (ptr_val->data.x_ptr.special) { |
| 13791 | 13944 | case ConstPtrSpecialInvalid: |
| 13792 | 13945 | zig_unreachable(); |
| 13946 | case ConstPtrSpecialNull: | |
| 13947 | if (dst_size == 0) | |
| 13948 | return ErrorNone; | |
| 13949 | opt_ir_add_error_node(ira, codegen, source_node, | |
| 13950 | buf_sprintf("attempt to read %zu bytes from null pointer", | |
| 13951 | dst_size)); | |
| 13952 | return ErrorSemanticAnalyzeFail; | |
| 13793 | 13953 | case ConstPtrSpecialRef: { |
| 13794 | 13954 | opt_ir_add_error_node(ira, codegen, source_node, |
| 13795 | 13955 | buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes", |
| ... | ... | @@ -13822,6 +13982,9 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source |
| 13822 | 13982 | return ErrorNone; |
| 13823 | 13983 | } |
| 13824 | 13984 | case ConstPtrSpecialBaseStruct: |
| 13985 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 13986 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 13987 | case ConstPtrSpecialBaseOptionalPayload: | |
| 13825 | 13988 | case ConstPtrSpecialDiscard: |
| 13826 | 13989 | case ConstPtrSpecialHardCodedAddr: |
| 13827 | 13990 | case ConstPtrSpecialFunction: |
| ... | ... | @@ -14017,9 +14180,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi |
| 14017 | 14180 | if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime)) |
| 14018 | 14181 | return ir_unreach_error(ira); |
| 14019 | 14182 | |
| 14020 | if (is_comptime || instr_is_comptime(condition)) { | |
| 14183 | ZigType *bool_type = ira->codegen->builtin_types.entry_bool; | |
| 14184 | IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type); | |
| 14185 | if (type_is_invalid(casted_condition->value.type)) | |
| 14186 | return ir_unreach_error(ira); | |
| 14187 | ||
| 14188 | if (is_comptime || instr_is_comptime(casted_condition)) { | |
| 14021 | 14189 | bool cond_is_true; |
| 14022 | if (!ir_resolve_bool(ira, condition, &cond_is_true)) | |
| 14190 | if (!ir_resolve_bool(ira, casted_condition, &cond_is_true)) | |
| 14023 | 14191 | return ir_unreach_error(ira); |
| 14024 | 14192 | |
| 14025 | 14193 | IrBasicBlock *old_dest_block = cond_is_true ? |
| ... | ... | @@ -14038,11 +14206,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi |
| 14038 | 14206 | return ir_finish_anal(ira, result); |
| 14039 | 14207 | } |
| 14040 | 14208 | |
| 14041 | ZigType *bool_type = ira->codegen->builtin_types.entry_bool; | |
| 14042 | IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type); | |
| 14043 | if (casted_condition == ira->codegen->invalid_instruction) | |
| 14044 | return ir_unreach_error(ira); | |
| 14045 | ||
| 14046 | 14209 | assert(cond_br_instruction->then_block != cond_br_instruction->else_block); |
| 14047 | 14210 | IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base); |
| 14048 | 14211 | if (new_then_block == nullptr) |
| ... | ... | @@ -14081,8 +14244,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 14081 | 14244 | |
| 14082 | 14245 | if (value->value.special != ConstValSpecialRuntime) { |
| 14083 | 14246 | IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr); |
| 14084 | // TODO use copy_const_val? | |
| 14085 | result->value = value->value; | |
| 14247 | copy_const_val(&result->value, &value->value, true); | |
| 14086 | 14248 | return result; |
| 14087 | 14249 | } else { |
| 14088 | 14250 | return value; |
| ... | ... | @@ -14131,14 +14293,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh |
| 14131 | 14293 | if (type_is_invalid(resolved_type)) |
| 14132 | 14294 | return ira->codegen->invalid_instruction; |
| 14133 | 14295 | |
| 14134 | if (resolved_type->id == ZigTypeIdComptimeFloat || | |
| 14135 | resolved_type->id == ZigTypeIdComptimeInt || | |
| 14136 | resolved_type->id == ZigTypeIdNull || | |
| 14137 | resolved_type->id == ZigTypeIdUndefined) | |
| 14138 | { | |
| 14296 | switch (type_has_one_possible_value(ira->codegen, resolved_type)) { | |
| 14297 | case OnePossibleValueInvalid: | |
| 14298 | return ira->codegen->invalid_instruction; | |
| 14299 | case OnePossibleValueYes: | |
| 14300 | return ir_const(ira, &phi_instruction->base, resolved_type); | |
| 14301 | case OnePossibleValueNo: | |
| 14302 | break; | |
| 14303 | } | |
| 14304 | ||
| 14305 | switch (type_requires_comptime(ira->codegen, resolved_type)) { | |
| 14306 | case ReqCompTimeInvalid: | |
| 14307 | return ira->codegen->invalid_instruction; | |
| 14308 | case ReqCompTimeYes: | |
| 14139 | 14309 | ir_add_error_node(ira, phi_instruction->base.source_node, |
| 14140 | buf_sprintf("unable to infer expression type")); | |
| 14310 | buf_sprintf("values of type '%s' must be comptime known", buf_ptr(&resolved_type->name))); | |
| 14141 | 14311 | return ira->codegen->invalid_instruction; |
| 14312 | case ReqCompTimeNo: | |
| 14313 | break; | |
| 14142 | 14314 | } |
| 14143 | 14315 | |
| 14144 | 14316 | bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer); |
| ... | ... | @@ -14428,10 +14600,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 14428 | 14600 | } |
| 14429 | 14601 | case ConstPtrSpecialBaseStruct: |
| 14430 | 14602 | zig_panic("TODO elem ptr on a const inner struct"); |
| 14603 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 14604 | zig_panic("TODO elem ptr on a const inner error union code"); | |
| 14605 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 14606 | zig_panic("TODO elem ptr on a const inner error union payload"); | |
| 14607 | case ConstPtrSpecialBaseOptionalPayload: | |
| 14608 | zig_panic("TODO elem ptr on a const inner optional payload"); | |
| 14431 | 14609 | case ConstPtrSpecialHardCodedAddr: |
| 14432 | 14610 | zig_unreachable(); |
| 14433 | 14611 | case ConstPtrSpecialFunction: |
| 14434 | 14612 | zig_panic("TODO element ptr of a function casted to a ptr"); |
| 14613 | case ConstPtrSpecialNull: | |
| 14614 | zig_panic("TODO elem ptr on a null pointer"); | |
| 14435 | 14615 | } |
| 14436 | 14616 | if (new_index >= mem_size) { |
| 14437 | 14617 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| ... | ... | @@ -14481,10 +14661,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct |
| 14481 | 14661 | } |
| 14482 | 14662 | case ConstPtrSpecialBaseStruct: |
| 14483 | 14663 | zig_panic("TODO elem ptr on a slice backed by const inner struct"); |
| 14664 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 14665 | zig_panic("TODO elem ptr on a slice backed by const inner error union code"); | |
| 14666 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 14667 | zig_panic("TODO elem ptr on a slice backed by const inner error union payload"); | |
| 14668 | case ConstPtrSpecialBaseOptionalPayload: | |
| 14669 | zig_panic("TODO elem ptr on a slice backed by const optional payload"); | |
| 14484 | 14670 | case ConstPtrSpecialHardCodedAddr: |
| 14485 | 14671 | zig_unreachable(); |
| 14486 | 14672 | case ConstPtrSpecialFunction: |
| 14487 | 14673 | zig_panic("TODO elem ptr on a slice that was ptrcast from a function"); |
| 14674 | case ConstPtrSpecialNull: | |
| 14675 | zig_panic("TODO elem ptr on a slice has a null pointer"); | |
| 14488 | 14676 | } |
| 14489 | 14677 | return result; |
| 14490 | 14678 | } else if (array_type->id == ZigTypeIdArray) { |
| ... | ... | @@ -15171,74 +15359,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc |
| 15171 | 15359 | } |
| 15172 | 15360 | } |
| 15173 | 15361 | |
| 15174 | static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) { | |
| 15175 | IrInstruction *ptr = load_ptr_instruction->ptr->child; | |
| 15176 | if (type_is_invalid(ptr->value.type)) | |
| 15177 | return ira->codegen->invalid_instruction; | |
| 15178 | return ir_get_deref(ira, &load_ptr_instruction->base, ptr); | |
| 15179 | } | |
| 15180 | ||
| 15181 | static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) { | |
| 15182 | IrInstruction *ptr = store_ptr_instruction->ptr->child; | |
| 15362 | static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) { | |
| 15363 | IrInstruction *ptr = instruction->ptr->child; | |
| 15183 | 15364 | if (type_is_invalid(ptr->value.type)) |
| 15184 | 15365 | return ira->codegen->invalid_instruction; |
| 15185 | 15366 | |
| 15186 | IrInstruction *value = store_ptr_instruction->value->child; | |
| 15367 | IrInstruction *value = instruction->value->child; | |
| 15187 | 15368 | if (type_is_invalid(value->value.type)) |
| 15188 | 15369 | return ira->codegen->invalid_instruction; |
| 15189 | 15370 | |
| 15190 | if (ptr->value.type->id != ZigTypeIdPointer) { | |
| 15191 | ir_add_error(ira, ptr, | |
| 15192 | buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name))); | |
| 15193 | return ira->codegen->invalid_instruction; | |
| 15194 | } | |
| 15195 | ||
| 15196 | if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) { | |
| 15197 | return ir_const_void(ira, &store_ptr_instruction->base); | |
| 15198 | } | |
| 15199 | ||
| 15200 | if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) { | |
| 15201 | ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant")); | |
| 15202 | return ira->codegen->invalid_instruction; | |
| 15203 | } | |
| 15371 | return ir_analyze_store_ptr(ira, &instruction->base, ptr, value); | |
| 15372 | } | |
| 15204 | 15373 | |
| 15205 | ZigType *child_type = ptr->value.type->data.pointer.child_type; | |
| 15206 | IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type); | |
| 15207 | if (casted_value == ira->codegen->invalid_instruction) | |
| 15374 | static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) { | |
| 15375 | IrInstruction *ptr = instruction->ptr->child; | |
| 15376 | if (type_is_invalid(ptr->value.type)) | |
| 15208 | 15377 | return ira->codegen->invalid_instruction; |
| 15209 | ||
| 15210 | if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | |
| 15211 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) { | |
| 15212 | ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant")); | |
| 15213 | return ira->codegen->invalid_instruction; | |
| 15214 | } | |
| 15215 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) { | |
| 15216 | if (instr_is_comptime(casted_value)) { | |
| 15217 | ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, store_ptr_instruction->base.source_node); | |
| 15218 | if (dest_val == nullptr) | |
| 15219 | return ira->codegen->invalid_instruction; | |
| 15220 | if (dest_val->special != ConstValSpecialRuntime) { | |
| 15221 | *dest_val = casted_value->value; | |
| 15222 | if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) { | |
| 15223 | ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base; | |
| 15224 | } | |
| 15225 | return ir_const_void(ira, &store_ptr_instruction->base); | |
| 15226 | } | |
| 15227 | } | |
| 15228 | ir_add_error(ira, &store_ptr_instruction->base, | |
| 15229 | buf_sprintf("cannot store runtime value in compile time variable")); | |
| 15230 | ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); | |
| 15231 | dest_val->type = ira->codegen->builtin_types.entry_invalid; | |
| 15232 | ||
| 15233 | return ira->codegen->invalid_instruction; | |
| 15234 | } | |
| 15235 | } | |
| 15236 | ||
| 15237 | IrInstruction *result = ir_build_store_ptr(&ira->new_irb, | |
| 15238 | store_ptr_instruction->base.scope, store_ptr_instruction->base.source_node, | |
| 15239 | ptr, casted_value); | |
| 15240 | result->value.type = ira->codegen->builtin_types.entry_void; | |
| 15241 | return result; | |
| 15378 | return ir_get_deref(ira, &instruction->base, ptr); | |
| 15242 | 15379 | } |
| 15243 | 15380 | |
| 15244 | 15381 | static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) { |
| ... | ... | @@ -15709,11 +15846,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, |
| 15709 | 15846 | zig_unreachable(); |
| 15710 | 15847 | } |
| 15711 | 15848 | |
| 15712 | static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) { | |
| 15713 | IrInstruction *value = instruction->value->child; | |
| 15714 | if (type_is_invalid(value->value.type)) | |
| 15715 | return ira->codegen->invalid_instruction; | |
| 15716 | ||
| 15849 | static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) { | |
| 15717 | 15850 | ZigType *type_entry = value->value.type; |
| 15718 | 15851 | |
| 15719 | 15852 | if (type_entry->id == ZigTypeIdOptional) { |
| ... | ... | @@ -15722,60 +15855,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns |
| 15722 | 15855 | if (!maybe_val) |
| 15723 | 15856 | return ira->codegen->invalid_instruction; |
| 15724 | 15857 | |
| 15725 | return ir_const_bool(ira, &instruction->base, !optional_value_is_null(maybe_val)); | |
| 15858 | return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val)); | |
| 15726 | 15859 | } |
| 15727 | 15860 | |
| 15728 | 15861 | IrInstruction *result = ir_build_test_nonnull(&ira->new_irb, |
| 15729 | instruction->base.scope, instruction->base.source_node, value); | |
| 15862 | source_inst->scope, source_inst->source_node, value); | |
| 15730 | 15863 | result->value.type = ira->codegen->builtin_types.entry_bool; |
| 15731 | 15864 | return result; |
| 15732 | 15865 | } else if (type_entry->id == ZigTypeIdNull) { |
| 15733 | return ir_const_bool(ira, &instruction->base, false); | |
| 15866 | return ir_const_bool(ira, source_inst, false); | |
| 15734 | 15867 | } else { |
| 15735 | return ir_const_bool(ira, &instruction->base, true); | |
| 15868 | return ir_const_bool(ira, source_inst, true); | |
| 15736 | 15869 | } |
| 15737 | 15870 | } |
| 15738 | 15871 | |
| 15739 | static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, | |
| 15740 | IrInstructionUnwrapOptional *unwrap_maybe_instruction) | |
| 15741 | { | |
| 15742 | IrInstruction *value = unwrap_maybe_instruction->value->child; | |
| 15872 | static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) { | |
| 15873 | IrInstruction *value = instruction->value->child; | |
| 15743 | 15874 | if (type_is_invalid(value->value.type)) |
| 15744 | 15875 | return ira->codegen->invalid_instruction; |
| 15745 | 15876 | |
| 15746 | ZigType *ptr_type = value->value.type; | |
| 15877 | return ir_analyze_test_non_null(ira, &instruction->base, value); | |
| 15878 | } | |
| 15879 | ||
| 15880 | static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, | |
| 15881 | IrInstruction *base_ptr, bool safety_check_on) | |
| 15882 | { | |
| 15883 | ZigType *ptr_type = base_ptr->value.type; | |
| 15747 | 15884 | assert(ptr_type->id == ZigTypeIdPointer); |
| 15748 | 15885 | |
| 15749 | 15886 | ZigType *type_entry = ptr_type->data.pointer.child_type; |
| 15750 | if (type_is_invalid(type_entry)) { | |
| 15887 | if (type_is_invalid(type_entry)) | |
| 15751 | 15888 | return ira->codegen->invalid_instruction; |
| 15752 | } else if (type_entry->id != ZigTypeIdOptional) { | |
| 15753 | ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node, | |
| 15889 | ||
| 15890 | if (type_entry->id != ZigTypeIdOptional) { | |
| 15891 | ir_add_error_node(ira, base_ptr->source_node, | |
| 15754 | 15892 | buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name))); |
| 15755 | 15893 | return ira->codegen->invalid_instruction; |
| 15756 | 15894 | } |
| 15895 | ||
| 15757 | 15896 | ZigType *child_type = type_entry->data.maybe.child_type; |
| 15758 | 15897 | ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type, |
| 15759 | 15898 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0); |
| 15760 | 15899 | |
| 15761 | if (instr_is_comptime(value)) { | |
| 15762 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | |
| 15900 | if (instr_is_comptime(base_ptr)) { | |
| 15901 | ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad); | |
| 15763 | 15902 | if (!val) |
| 15764 | 15903 | return ira->codegen->invalid_instruction; |
| 15765 | ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, unwrap_maybe_instruction->base.source_node); | |
| 15904 | ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node); | |
| 15766 | 15905 | if (maybe_val == nullptr) |
| 15767 | 15906 | return ira->codegen->invalid_instruction; |
| 15768 | 15907 | |
| 15769 | 15908 | if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) { |
| 15770 | 15909 | if (optional_value_is_null(maybe_val)) { |
| 15771 | ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null")); | |
| 15910 | ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null")); | |
| 15772 | 15911 | return ira->codegen->invalid_instruction; |
| 15773 | 15912 | } |
| 15774 | IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type); | |
| 15913 | IrInstruction *result = ir_const(ira, source_instr, result_type); | |
| 15775 | 15914 | ConstExprValue *out_val = &result->value; |
| 15776 | 15915 | out_val->data.x_ptr.special = ConstPtrSpecialRef; |
| 15777 | 15916 | out_val->data.x_ptr.mut = val->data.x_ptr.mut; |
| 15778 | if (type_is_codegen_pointer(child_type)) { | |
| 15917 | if (types_have_same_zig_comptime_repr(type_entry, child_type)) { | |
| 15779 | 15918 | out_val->data.x_ptr.data.ref.pointee = maybe_val; |
| 15780 | 15919 | } else { |
| 15781 | 15920 | out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional; |
| ... | ... | @@ -15784,13 +15923,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira, |
| 15784 | 15923 | } |
| 15785 | 15924 | } |
| 15786 | 15925 | |
| 15787 | IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb, | |
| 15788 | unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node, | |
| 15789 | value, unwrap_maybe_instruction->safety_check_on); | |
| 15926 | IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope, | |
| 15927 | source_instr->source_node, base_ptr, safety_check_on); | |
| 15790 | 15928 | result->value.type = result_type; |
| 15791 | 15929 | return result; |
| 15792 | 15930 | } |
| 15793 | 15931 | |
| 15932 | static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira, | |
| 15933 | IrInstructionOptionalUnwrapPtr *instruction) | |
| 15934 | { | |
| 15935 | IrInstruction *base_ptr = instruction->base_ptr->child; | |
| 15936 | if (type_is_invalid(base_ptr->value.type)) | |
| 15937 | return ira->codegen->invalid_instruction; | |
| 15938 | ||
| 15939 | return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on); | |
| 15940 | } | |
| 15941 | ||
| 15794 | 15942 | static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) { |
| 15795 | 15943 | IrInstruction *value = ctz_instruction->value->child; |
| 15796 | 15944 | if (type_is_invalid(value->value.type)) { |
| ... | ... | @@ -16091,9 +16239,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 16091 | 16239 | return result; |
| 16092 | 16240 | } |
| 16093 | 16241 | |
| 16094 | IrInstruction *result = ir_build_load_ptr(&ira->new_irb, | |
| 16095 | switch_target_instruction->base.scope, switch_target_instruction->base.source_node, | |
| 16096 | target_value_ptr); | |
| 16242 | IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr); | |
| 16097 | 16243 | result->value.type = target_type; |
| 16098 | 16244 | return result; |
| 16099 | 16245 | } |
| ... | ... | @@ -16123,8 +16269,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 16123 | 16269 | return result; |
| 16124 | 16270 | } |
| 16125 | 16271 | |
| 16126 | IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, | |
| 16127 | switch_target_instruction->base.source_node, target_value_ptr); | |
| 16272 | IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr); | |
| 16128 | 16273 | union_value->value.type = target_type; |
| 16129 | 16274 | |
| 16130 | 16275 | IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope, |
| ... | ... | @@ -16148,8 +16293,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira, |
| 16148 | 16293 | return result; |
| 16149 | 16294 | } |
| 16150 | 16295 | |
| 16151 | IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope, | |
| 16152 | switch_target_instruction->base.source_node, target_value_ptr); | |
| 16296 | IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr); | |
| 16153 | 16297 | enum_value->value.type = target_type; |
| 16154 | 16298 | return enum_value; |
| 16155 | 16299 | } |
| ... | ... | @@ -16306,7 +16450,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI |
| 16306 | 16450 | Error err; |
| 16307 | 16451 | assert(container_type->id == ZigTypeIdUnion); |
| 16308 | 16452 | |
| 16309 | if ((err = ensure_complete_type(ira->codegen, container_type))) | |
| 16453 | if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) | |
| 16310 | 16454 | return ira->codegen->invalid_instruction; |
| 16311 | 16455 | |
| 16312 | 16456 | if (instr_field_count != 1) { |
| ... | ... | @@ -16350,12 +16494,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI |
| 16350 | 16494 | ConstExprValue *out_val = &result->value; |
| 16351 | 16495 | out_val->data.x_union.payload = field_val; |
| 16352 | 16496 | out_val->data.x_union.tag = type_field->enum_field->value; |
| 16353 | ||
| 16354 | ConstParent *parent = get_const_val_parent(ira->codegen, field_val); | |
| 16355 | if (parent != nullptr) { | |
| 16356 | parent->id = ConstParentIdUnion; | |
| 16357 | parent->data.p_union.union_val = out_val; | |
| 16358 | } | |
| 16497 | out_val->parent.id = ConstParentIdUnion; | |
| 16498 | out_val->parent.data.p_union.union_val = out_val; | |
| 16359 | 16499 | |
| 16360 | 16500 | return result; |
| 16361 | 16501 | } |
| ... | ... | @@ -16382,7 +16522,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 16382 | 16522 | return ira->codegen->invalid_instruction; |
| 16383 | 16523 | } |
| 16384 | 16524 | |
| 16385 | if ((err = ensure_complete_type(ira->codegen, container_type))) | |
| 16525 | if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) | |
| 16386 | 16526 | return ira->codegen->invalid_instruction; |
| 16387 | 16527 | |
| 16388 | 16528 | size_t actual_field_count = container_type->data.structure.src_field_count; |
| ... | ... | @@ -16461,9 +16601,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 16461 | 16601 | if (const_val.special == ConstValSpecialStatic) { |
| 16462 | 16602 | IrInstruction *result = ir_const(ira, instruction, nullptr); |
| 16463 | 16603 | ConstExprValue *out_val = &result->value; |
| 16464 | // TODO copy_const_val? | |
| 16465 | *out_val = const_val; | |
| 16466 | result->value.type = container_type; | |
| 16604 | copy_const_val(out_val, &const_val, true); | |
| 16605 | out_val->type = container_type; | |
| 16467 | 16606 | |
| 16468 | 16607 | for (size_t i = 0; i < instr_field_count; i += 1) { |
| 16469 | 16608 | ConstExprValue *field_val = &out_val->data.x_struct.fields[i]; |
| ... | ... | @@ -16495,127 +16634,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc |
| 16495 | 16634 | static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, |
| 16496 | 16635 | IrInstructionContainerInitList *instruction) |
| 16497 | 16636 | { |
| 16498 | IrInstruction *container_type_value = instruction->container_type->child; | |
| 16499 | if (type_is_invalid(container_type_value->value.type)) | |
| 16637 | ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child); | |
| 16638 | if (type_is_invalid(container_type)) | |
| 16500 | 16639 | return ira->codegen->invalid_instruction; |
| 16501 | 16640 | |
| 16502 | 16641 | size_t elem_count = instruction->item_count; |
| 16503 | if (container_type_value->value.type->id == ZigTypeIdMetaType) { | |
| 16504 | ZigType *container_type = ir_resolve_type(ira, container_type_value); | |
| 16505 | if (type_is_invalid(container_type)) | |
| 16506 | return ira->codegen->invalid_instruction; | |
| 16507 | 16642 | |
| 16508 | if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) { | |
| 16509 | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, | |
| 16510 | 0, nullptr); | |
| 16511 | } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) { | |
| 16512 | // array is same as slice init but we make a compile error if the length is wrong | |
| 16513 | ZigType *child_type; | |
| 16514 | if (container_type->id == ZigTypeIdArray) { | |
| 16515 | child_type = container_type->data.array.child_type; | |
| 16516 | if (container_type->data.array.len != elem_count) { | |
| 16517 | ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); | |
| 16643 | if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) { | |
| 16644 | return ir_analyze_container_init_fields(ira, &instruction->base, container_type, | |
| 16645 | 0, nullptr); | |
| 16646 | } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) { | |
| 16647 | // array is same as slice init but we make a compile error if the length is wrong | |
| 16648 | ZigType *child_type; | |
| 16649 | if (container_type->id == ZigTypeIdArray) { | |
| 16650 | child_type = container_type->data.array.child_type; | |
| 16651 | if (container_type->data.array.len != elem_count) { | |
| 16652 | ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); | |
| 16518 | 16653 | |
| 16519 | ir_add_error(ira, &instruction->base, | |
| 16520 | buf_sprintf("expected %s literal, found %s literal", | |
| 16521 | buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); | |
| 16522 | return ira->codegen->invalid_instruction; | |
| 16523 | } | |
| 16524 | } else { | |
| 16525 | ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry; | |
| 16526 | assert(pointer_type->id == ZigTypeIdPointer); | |
| 16527 | child_type = pointer_type->data.pointer.child_type; | |
| 16654 | ir_add_error(ira, &instruction->base, | |
| 16655 | buf_sprintf("expected %s literal, found %s literal", | |
| 16656 | buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); | |
| 16657 | return ira->codegen->invalid_instruction; | |
| 16528 | 16658 | } |
| 16659 | } else { | |
| 16660 | ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry; | |
| 16661 | assert(pointer_type->id == ZigTypeIdPointer); | |
| 16662 | child_type = pointer_type->data.pointer.child_type; | |
| 16663 | } | |
| 16529 | 16664 | |
| 16530 | ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); | |
| 16665 | ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); | |
| 16531 | 16666 | |
| 16532 | ConstExprValue const_val = {}; | |
| 16533 | const_val.special = ConstValSpecialStatic; | |
| 16534 | const_val.type = fixed_size_array_type; | |
| 16535 | const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count); | |
| 16667 | ConstExprValue const_val = {}; | |
| 16668 | const_val.special = ConstValSpecialStatic; | |
| 16669 | const_val.type = fixed_size_array_type; | |
| 16670 | const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count); | |
| 16536 | 16671 | |
| 16537 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope); | |
| 16672 | bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope); | |
| 16538 | 16673 | |
| 16539 | IrInstruction **new_items = allocate<IrInstruction *>(elem_count); | |
| 16674 | IrInstruction **new_items = allocate<IrInstruction *>(elem_count); | |
| 16540 | 16675 | |
| 16541 | IrInstruction *first_non_const_instruction = nullptr; | |
| 16676 | IrInstruction *first_non_const_instruction = nullptr; | |
| 16542 | 16677 | |
| 16543 | for (size_t i = 0; i < elem_count; i += 1) { | |
| 16544 | IrInstruction *arg_value = instruction->items[i]->child; | |
| 16545 | if (type_is_invalid(arg_value->value.type)) | |
| 16546 | return ira->codegen->invalid_instruction; | |
| 16678 | for (size_t i = 0; i < elem_count; i += 1) { | |
| 16679 | IrInstruction *arg_value = instruction->items[i]->child; | |
| 16680 | if (type_is_invalid(arg_value->value.type)) | |
| 16681 | return ira->codegen->invalid_instruction; | |
| 16547 | 16682 | |
| 16548 | IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type); | |
| 16549 | if (casted_arg == ira->codegen->invalid_instruction) | |
| 16550 | return ira->codegen->invalid_instruction; | |
| 16683 | IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type); | |
| 16684 | if (casted_arg == ira->codegen->invalid_instruction) | |
| 16685 | return ira->codegen->invalid_instruction; | |
| 16551 | 16686 | |
| 16552 | new_items[i] = casted_arg; | |
| 16687 | new_items[i] = casted_arg; | |
| 16553 | 16688 | |
| 16554 | if (const_val.special == ConstValSpecialStatic) { | |
| 16555 | if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) { | |
| 16556 | ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad); | |
| 16557 | if (!elem_val) | |
| 16558 | return ira->codegen->invalid_instruction; | |
| 16689 | if (const_val.special == ConstValSpecialStatic) { | |
| 16690 | if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) { | |
| 16691 | ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad); | |
| 16692 | if (!elem_val) | |
| 16693 | return ira->codegen->invalid_instruction; | |
| 16559 | 16694 | |
| 16560 | copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true); | |
| 16561 | } else { | |
| 16562 | first_non_const_instruction = casted_arg; | |
| 16563 | const_val.special = ConstValSpecialRuntime; | |
| 16564 | } | |
| 16695 | copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true); | |
| 16696 | } else { | |
| 16697 | first_non_const_instruction = casted_arg; | |
| 16698 | const_val.special = ConstValSpecialRuntime; | |
| 16565 | 16699 | } |
| 16566 | 16700 | } |
| 16701 | } | |
| 16567 | 16702 | |
| 16568 | if (const_val.special == ConstValSpecialStatic) { | |
| 16569 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); | |
| 16570 | ConstExprValue *out_val = &result->value; | |
| 16571 | // TODO copy_const_val? | |
| 16572 | *out_val = const_val; | |
| 16573 | result->value.type = fixed_size_array_type; | |
| 16574 | for (size_t i = 0; i < elem_count; i += 1) { | |
| 16575 | ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i]; | |
| 16576 | ConstParent *parent = get_const_val_parent(ira->codegen, elem_val); | |
| 16577 | if (parent != nullptr) { | |
| 16578 | parent->id = ConstParentIdArray; | |
| 16579 | parent->data.p_array.array_val = out_val; | |
| 16580 | parent->data.p_array.elem_index = i; | |
| 16581 | } | |
| 16703 | if (const_val.special == ConstValSpecialStatic) { | |
| 16704 | IrInstruction *result = ir_const(ira, &instruction->base, nullptr); | |
| 16705 | ConstExprValue *out_val = &result->value; | |
| 16706 | copy_const_val(out_val, &const_val, true); | |
| 16707 | result->value.type = fixed_size_array_type; | |
| 16708 | for (size_t i = 0; i < elem_count; i += 1) { | |
| 16709 | ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i]; | |
| 16710 | ConstParent *parent = get_const_val_parent(ira->codegen, elem_val); | |
| 16711 | if (parent != nullptr) { | |
| 16712 | parent->id = ConstParentIdArray; | |
| 16713 | parent->data.p_array.array_val = out_val; | |
| 16714 | parent->data.p_array.elem_index = i; | |
| 16582 | 16715 | } |
| 16583 | return result; | |
| 16584 | 16716 | } |
| 16717 | return result; | |
| 16718 | } | |
| 16585 | 16719 | |
| 16586 | if (is_comptime) { | |
| 16587 | ir_add_error_node(ira, first_non_const_instruction->source_node, | |
| 16588 | buf_sprintf("unable to evaluate constant expression")); | |
| 16589 | return ira->codegen->invalid_instruction; | |
| 16590 | } | |
| 16720 | if (is_comptime) { | |
| 16721 | ir_add_error_node(ira, first_non_const_instruction->source_node, | |
| 16722 | buf_sprintf("unable to evaluate constant expression")); | |
| 16723 | return ira->codegen->invalid_instruction; | |
| 16724 | } | |
| 16591 | 16725 | |
| 16592 | IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb, | |
| 16593 | instruction->base.scope, instruction->base.source_node, | |
| 16594 | container_type_value, elem_count, new_items); | |
| 16595 | new_instruction->value.type = fixed_size_array_type; | |
| 16596 | ir_add_alloca(ira, new_instruction, fixed_size_array_type); | |
| 16597 | return new_instruction; | |
| 16598 | } else if (container_type->id == ZigTypeIdVoid) { | |
| 16599 | if (elem_count != 0) { | |
| 16600 | ir_add_error_node(ira, instruction->base.source_node, | |
| 16601 | buf_sprintf("void expression expects no arguments")); | |
| 16602 | return ira->codegen->invalid_instruction; | |
| 16603 | } | |
| 16604 | return ir_const_void(ira, &instruction->base); | |
| 16605 | } else { | |
| 16726 | IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb, | |
| 16727 | instruction->base.scope, instruction->base.source_node, | |
| 16728 | nullptr, elem_count, new_items); | |
| 16729 | new_instruction->value.type = fixed_size_array_type; | |
| 16730 | ir_add_alloca(ira, new_instruction, fixed_size_array_type); | |
| 16731 | return new_instruction; | |
| 16732 | } else if (container_type->id == ZigTypeIdVoid) { | |
| 16733 | if (elem_count != 0) { | |
| 16606 | 16734 | ir_add_error_node(ira, instruction->base.source_node, |
| 16607 | buf_sprintf("type '%s' does not support array initialization", | |
| 16608 | buf_ptr(&container_type->name))); | |
| 16735 | buf_sprintf("void expression expects no arguments")); | |
| 16609 | 16736 | return ira->codegen->invalid_instruction; |
| 16610 | 16737 | } |
| 16738 | return ir_const_void(ira, &instruction->base); | |
| 16611 | 16739 | } else { |
| 16612 | ir_add_error(ira, container_type_value, | |
| 16613 | buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name))); | |
| 16740 | ir_add_error_node(ira, instruction->base.source_node, | |
| 16741 | buf_sprintf("type '%s' does not support array initialization", | |
| 16742 | buf_ptr(&container_type->name))); | |
| 16614 | 16743 | return ira->codegen->invalid_instruction; |
| 16615 | 16744 | } |
| 16616 | 16745 | } |
| 16617 | 16746 | |
| 16618 | static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) { | |
| 16747 | static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, | |
| 16748 | IrInstructionContainerInitFields *instruction) | |
| 16749 | { | |
| 16619 | 16750 | IrInstruction *container_type_value = instruction->container_type->child; |
| 16620 | 16751 | ZigType *container_type = ir_resolve_type(ira, container_type_value); |
| 16621 | 16752 | if (type_is_invalid(container_type)) |
| ... | ... | @@ -16675,7 +16806,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct |
| 16675 | 16806 | if (type_is_invalid(value->value.type)) |
| 16676 | 16807 | return ira->codegen->invalid_instruction; |
| 16677 | 16808 | |
| 16678 | IrInstruction *casted_value = ir_implicit_cast(ira, value, value->value.type); | |
| 16809 | IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set); | |
| 16679 | 16810 | if (type_is_invalid(casted_value->value.type)) |
| 16680 | 16811 | return ira->codegen->invalid_instruction; |
| 16681 | 16812 | |
| ... | ... | @@ -16936,10 +17067,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig |
| 16936 | 17067 | |
| 16937 | 17068 | ZigVar *var = tld->var; |
| 16938 | 17069 | |
| 16939 | if ((err = ensure_complete_type(ira->codegen, var->value->type))) | |
| 17070 | if ((err = ensure_complete_type(ira->codegen, var->const_value->type))) | |
| 16940 | 17071 | return ira->codegen->builtin_types.entry_invalid; |
| 16941 | assert(var->value->type->id == ZigTypeIdMetaType); | |
| 16942 | return var->value->data.x_type; | |
| 17072 | ||
| 17073 | assert(var->const_value->type->id == ZigTypeIdMetaType); | |
| 17074 | return var->const_value->data.x_type; | |
| 16943 | 17075 | } |
| 16944 | 17076 | |
| 16945 | 17077 | static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) { |
| ... | ... | @@ -16994,7 +17126,6 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 16994 | 17126 | definition_array->special = ConstValSpecialStatic; |
| 16995 | 17127 | definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count); |
| 16996 | 17128 | definition_array->data.x_array.special = ConstArraySpecialNone; |
| 16997 | definition_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | |
| 16998 | 17129 | definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count); |
| 16999 | 17130 | init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false); |
| 17000 | 17131 | |
| ... | ... | @@ -17025,33 +17156,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 17025 | 17156 | inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub; |
| 17026 | 17157 | inner_fields[2].special = ConstValSpecialStatic; |
| 17027 | 17158 | inner_fields[2].type = type_info_definition_data_type; |
| 17028 | inner_fields[2].data.x_union.parent.id = ConstParentIdStruct; | |
| 17029 | inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val; | |
| 17030 | inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1; | |
| 17159 | inner_fields[2].parent.id = ConstParentIdStruct; | |
| 17160 | inner_fields[2].parent.data.p_struct.struct_val = definition_val; | |
| 17161 | inner_fields[2].parent.data.p_struct.field_index = 1; | |
| 17031 | 17162 | |
| 17032 | 17163 | switch (curr_entry->value->id) { |
| 17033 | 17164 | case TldIdVar: |
| 17034 | 17165 | { |
| 17035 | 17166 | ZigVar *var = ((TldVar *)curr_entry->value)->var; |
| 17036 | if ((err = ensure_complete_type(ira->codegen, var->value->type))) | |
| 17167 | if ((err = ensure_complete_type(ira->codegen, var->const_value->type))) | |
| 17037 | 17168 | return ErrorSemanticAnalyzeFail; |
| 17038 | 17169 | |
| 17039 | if (var->value->type->id == ZigTypeIdMetaType) | |
| 17040 | { | |
| 17170 | if (var->const_value->type->id == ZigTypeIdMetaType) { | |
| 17041 | 17171 | // We have a variable of type 'type', so it's actually a type definition. |
| 17042 | 17172 | // 0: Data.Type: type |
| 17043 | 17173 | bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); |
| 17044 | inner_fields[2].data.x_union.payload = var->value; | |
| 17045 | } | |
| 17046 | else | |
| 17047 | { | |
| 17174 | inner_fields[2].data.x_union.payload = var->const_value; | |
| 17175 | } else { | |
| 17048 | 17176 | // We have a variable of another type, so we store the type of the variable. |
| 17049 | 17177 | // 1: Data.Var: type |
| 17050 | 17178 | bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1); |
| 17051 | 17179 | |
| 17052 | 17180 | ConstExprValue *payload = create_const_vals(1); |
| 17053 | 17181 | payload->type = ira->codegen->builtin_types.entry_type; |
| 17054 | payload->data.x_type = var->value->type; | |
| 17182 | payload->data.x_type = var->const_value->type; | |
| 17055 | 17183 | |
| 17056 | 17184 | inner_fields[2].data.x_union.payload = payload; |
| 17057 | 17185 | } |
| ... | ... | @@ -17071,8 +17199,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 17071 | 17199 | ConstExprValue *fn_def_val = create_const_vals(1); |
| 17072 | 17200 | fn_def_val->special = ConstValSpecialStatic; |
| 17073 | 17201 | fn_def_val->type = type_info_fn_def_type; |
| 17074 | fn_def_val->data.x_struct.parent.id = ConstParentIdUnion; | |
| 17075 | fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2]; | |
| 17202 | fn_def_val->parent.id = ConstParentIdUnion; | |
| 17203 | fn_def_val->parent.data.p_union.union_val = &inner_fields[2]; | |
| 17076 | 17204 | |
| 17077 | 17205 | ConstExprValue *fn_def_fields = create_const_vals(9); |
| 17078 | 17206 | fn_def_val->data.x_struct.fields = fn_def_fields; |
| ... | ... | @@ -17136,20 +17264,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco |
| 17136 | 17264 | fn_arg_name_array->type = get_array_type(ira->codegen, |
| 17137 | 17265 | get_slice_type(ira->codegen, u8_ptr), fn_arg_count); |
| 17138 | 17266 | fn_arg_name_array->data.x_array.special = ConstArraySpecialNone; |
| 17139 | fn_arg_name_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | |
| 17140 | 17267 | fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); |
| 17141 | 17268 | |
| 17142 | 17269 | init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false); |
| 17143 | 17270 | |
| 17144 | for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) | |
| 17145 | { | |
| 17271 | for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) { | |
| 17146 | 17272 | ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index); |
| 17147 | 17273 | ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index]; |
| 17148 | 17274 | ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name); |
| 17149 | 17275 | init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true); |
| 17150 | fn_arg_name_val->data.x_struct.parent.id = ConstParentIdArray; | |
| 17151 | fn_arg_name_val->data.x_struct.parent.data.p_array.array_val = fn_arg_name_array; | |
| 17152 | fn_arg_name_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index; | |
| 17276 | fn_arg_name_val->parent.id = ConstParentIdArray; | |
| 17277 | fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array; | |
| 17278 | fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index; | |
| 17153 | 17279 | } |
| 17154 | 17280 | |
| 17155 | 17281 | inner_fields[2].data.x_union.payload = fn_def_val; |
| ... | ... | @@ -17442,7 +17568,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17442 | 17568 | enum_field_array->special = ConstValSpecialStatic; |
| 17443 | 17569 | enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count); |
| 17444 | 17570 | enum_field_array->data.x_array.special = ConstArraySpecialNone; |
| 17445 | enum_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | |
| 17446 | 17571 | enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count); |
| 17447 | 17572 | |
| 17448 | 17573 | init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false); |
| ... | ... | @@ -17452,9 +17577,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17452 | 17577 | TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index]; |
| 17453 | 17578 | ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index]; |
| 17454 | 17579 | make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type); |
| 17455 | enum_field_val->data.x_struct.parent.id = ConstParentIdArray; | |
| 17456 | enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array; | |
| 17457 | enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index; | |
| 17580 | enum_field_val->parent.id = ConstParentIdArray; | |
| 17581 | enum_field_val->parent.data.p_array.array_val = enum_field_array; | |
| 17582 | enum_field_val->parent.data.p_array.elem_index = enum_field_index; | |
| 17458 | 17583 | } |
| 17459 | 17584 | // defs: []TypeInfo.Definition |
| 17460 | 17585 | ensure_field_index(result->type, "defs", 3); |
| ... | ... | @@ -17481,7 +17606,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17481 | 17606 | error_array->special = ConstValSpecialStatic; |
| 17482 | 17607 | error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count); |
| 17483 | 17608 | error_array->data.x_array.special = ConstArraySpecialNone; |
| 17484 | error_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | |
| 17485 | 17609 | error_array->data.x_array.data.s_none.elements = create_const_vals(error_count); |
| 17486 | 17610 | |
| 17487 | 17611 | init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false); |
| ... | ... | @@ -17505,9 +17629,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17505 | 17629 | bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value); |
| 17506 | 17630 | |
| 17507 | 17631 | error_val->data.x_struct.fields = inner_fields; |
| 17508 | error_val->data.x_struct.parent.id = ConstParentIdArray; | |
| 17509 | error_val->data.x_struct.parent.data.p_array.array_val = error_array; | |
| 17510 | error_val->data.x_struct.parent.data.p_array.elem_index = error_index; | |
| 17632 | error_val->parent.id = ConstParentIdArray; | |
| 17633 | error_val->parent.data.p_array.array_val = error_array; | |
| 17634 | error_val->parent.data.p_array.elem_index = error_index; | |
| 17511 | 17635 | } |
| 17512 | 17636 | |
| 17513 | 17637 | break; |
| ... | ... | @@ -17576,7 +17700,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17576 | 17700 | union_field_array->special = ConstValSpecialStatic; |
| 17577 | 17701 | union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count); |
| 17578 | 17702 | union_field_array->data.x_array.special = ConstArraySpecialNone; |
| 17579 | union_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | |
| 17580 | 17703 | union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count); |
| 17581 | 17704 | |
| 17582 | 17705 | init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false); |
| ... | ... | @@ -17609,9 +17732,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17609 | 17732 | init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true); |
| 17610 | 17733 | |
| 17611 | 17734 | union_field_val->data.x_struct.fields = inner_fields; |
| 17612 | union_field_val->data.x_struct.parent.id = ConstParentIdArray; | |
| 17613 | union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array; | |
| 17614 | union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index; | |
| 17735 | union_field_val->parent.id = ConstParentIdArray; | |
| 17736 | union_field_val->parent.data.p_array.array_val = union_field_array; | |
| 17737 | union_field_val->parent.data.p_array.elem_index = union_field_index; | |
| 17615 | 17738 | } |
| 17616 | 17739 | // defs: []TypeInfo.Definition |
| 17617 | 17740 | ensure_field_index(result->type, "defs", 3); |
| ... | ... | @@ -17651,7 +17774,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17651 | 17774 | struct_field_array->special = ConstValSpecialStatic; |
| 17652 | 17775 | struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count); |
| 17653 | 17776 | struct_field_array->data.x_array.special = ConstArraySpecialNone; |
| 17654 | struct_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | |
| 17655 | 17777 | struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count); |
| 17656 | 17778 | |
| 17657 | 17779 | init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false); |
| ... | ... | @@ -17685,9 +17807,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17685 | 17807 | init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true); |
| 17686 | 17808 | |
| 17687 | 17809 | struct_field_val->data.x_struct.fields = inner_fields; |
| 17688 | struct_field_val->data.x_struct.parent.id = ConstParentIdArray; | |
| 17689 | struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array; | |
| 17690 | struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index; | |
| 17810 | struct_field_val->parent.id = ConstParentIdArray; | |
| 17811 | struct_field_val->parent.data.p_array.array_val = struct_field_array; | |
| 17812 | struct_field_val->parent.data.p_array.elem_index = struct_field_index; | |
| 17691 | 17813 | } |
| 17692 | 17814 | // defs: []TypeInfo.Definition |
| 17693 | 17815 | ensure_field_index(result->type, "defs", 2); |
| ... | ... | @@ -17757,7 +17879,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17757 | 17879 | fn_arg_array->special = ConstValSpecialStatic; |
| 17758 | 17880 | fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count); |
| 17759 | 17881 | fn_arg_array->data.x_array.special = ConstArraySpecialNone; |
| 17760 | fn_arg_array->data.x_array.data.s_none.parent.id = ConstParentIdNone; | |
| 17761 | 17882 | fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); |
| 17762 | 17883 | |
| 17763 | 17884 | init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false); |
| ... | ... | @@ -17794,9 +17915,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE |
| 17794 | 17915 | } |
| 17795 | 17916 | |
| 17796 | 17917 | fn_arg_val->data.x_struct.fields = inner_fields; |
| 17797 | fn_arg_val->data.x_struct.parent.id = ConstParentIdArray; | |
| 17798 | fn_arg_val->data.x_struct.parent.data.p_array.array_val = fn_arg_array; | |
| 17799 | fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index; | |
| 17918 | fn_arg_val->parent.id = ConstParentIdArray; | |
| 17919 | fn_arg_val->parent.data.p_array.array_val = fn_arg_array; | |
| 17920 | fn_arg_val->parent.data.p_array.elem_index = fn_arg_index; | |
| 17800 | 17921 | } |
| 17801 | 17922 | |
| 17802 | 17923 | break; |
| ... | ... | @@ -17840,8 +17961,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, |
| 17840 | 17961 | |
| 17841 | 17962 | if (payload != nullptr) { |
| 17842 | 17963 | assert(payload->type->id == ZigTypeIdStruct); |
| 17843 | payload->data.x_struct.parent.id = ConstParentIdUnion; | |
| 17844 | payload->data.x_struct.parent.data.p_union.union_val = out_val; | |
| 17964 | payload->parent.id = ConstParentIdUnion; | |
| 17965 | payload->parent.data.p_union.union_val = out_val; | |
| 17845 | 17966 | } |
| 17846 | 17967 | |
| 17847 | 17968 | return result; |
| ... | ... | @@ -17913,10 +18034,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct |
| 17913 | 18034 | |
| 17914 | 18035 | // Execute the C import block like an inline function |
| 17915 | 18036 | ZigType *void_type = ira->codegen->builtin_types.entry_void; |
| 17916 | IrInstruction *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, | |
| 18037 | ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, | |
| 17917 | 18038 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, |
| 17918 | 18039 | &cimport_scope->buf, block_node, nullptr, nullptr); |
| 17919 | if (type_is_invalid(cimport_result->value.type)) | |
| 18040 | if (type_is_invalid(cimport_result->type)) | |
| 17920 | 18041 | return ira->codegen->invalid_instruction; |
| 17921 | 18042 | |
| 17922 | 18043 | find_libc_include_path(ira->codegen); |
| ... | ... | @@ -18066,7 +18187,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru |
| 18066 | 18187 | return result; |
| 18067 | 18188 | } |
| 18068 | 18189 | |
| 18069 | static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) { | |
| 18190 | static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) { | |
| 18070 | 18191 | ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child); |
| 18071 | 18192 | if (type_is_invalid(operand_type)) |
| 18072 | 18193 | return ira->codegen->invalid_instruction; |
| ... | ... | @@ -18138,9 +18259,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi |
| 18138 | 18259 | zig_panic("TODO compile-time execution of cmpxchg"); |
| 18139 | 18260 | } |
| 18140 | 18261 | |
| 18141 | IrInstruction *result = ir_build_cmpxchg(&ira->new_irb, instruction->base.scope, instruction->base.source_node, | |
| 18142 | nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak, | |
| 18143 | operand_type, success_order, failure_order); | |
| 18262 | IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base, | |
| 18263 | casted_ptr, casted_cmp_value, casted_new_value, | |
| 18264 | success_order, failure_order, instruction->is_weak); | |
| 18144 | 18265 | result->value.type = get_optional_type(ira->codegen, operand_type); |
| 18145 | 18266 | ir_add_alloca(ira, result, result->value.type); |
| 18146 | 18267 | return result; |
| ... | ... | @@ -18312,18 +18433,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst |
| 18312 | 18433 | return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type); |
| 18313 | 18434 | } |
| 18314 | 18435 | |
| 18315 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { | |
| 18316 | Error err; | |
| 18317 | ||
| 18318 | if (ty->id == ZigTypeIdPointer) { | |
| 18319 | if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown))) | |
| 18320 | return err; | |
| 18321 | } | |
| 18322 | ||
| 18323 | *result_align = get_ptr_align(ira->codegen, ty); | |
| 18324 | return ErrorNone; | |
| 18325 | } | |
| 18326 | ||
| 18327 | 18436 | static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) { |
| 18328 | 18437 | Error err; |
| 18329 | 18438 | |
| ... | ... | @@ -18442,6 +18551,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct |
| 18442 | 18551 | return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true); |
| 18443 | 18552 | } |
| 18444 | 18553 | |
| 18554 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { | |
| 18555 | Error err; | |
| 18556 | ||
| 18557 | ZigType *ptr_type = get_src_ptr_type(ty); | |
| 18558 | assert(ptr_type != nullptr); | |
| 18559 | if (ptr_type->id == ZigTypeIdPointer) { | |
| 18560 | if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) | |
| 18561 | return err; | |
| 18562 | } | |
| 18563 | ||
| 18564 | *result_align = get_ptr_align(ira->codegen, ty); | |
| 18565 | return ErrorNone; | |
| 18566 | } | |
| 18567 | ||
| 18445 | 18568 | static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) { |
| 18446 | 18569 | ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); |
| 18447 | 18570 | if (type_is_invalid(dest_type)) |
| ... | ... | @@ -18646,10 +18769,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio |
| 18646 | 18769 | } |
| 18647 | 18770 | case ConstPtrSpecialBaseStruct: |
| 18648 | 18771 | zig_panic("TODO memset on const inner struct"); |
| 18772 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 18773 | zig_panic("TODO memset on const inner error union code"); | |
| 18774 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 18775 | zig_panic("TODO memset on const inner error union payload"); | |
| 18776 | case ConstPtrSpecialBaseOptionalPayload: | |
| 18777 | zig_panic("TODO memset on const inner optional payload"); | |
| 18649 | 18778 | case ConstPtrSpecialHardCodedAddr: |
| 18650 | 18779 | zig_unreachable(); |
| 18651 | 18780 | case ConstPtrSpecialFunction: |
| 18652 | 18781 | zig_panic("TODO memset on ptr cast from function"); |
| 18782 | case ConstPtrSpecialNull: | |
| 18783 | zig_panic("TODO memset on null ptr"); | |
| 18653 | 18784 | } |
| 18654 | 18785 | |
| 18655 | 18786 | size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint); |
| ... | ... | @@ -18761,10 +18892,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio |
| 18761 | 18892 | } |
| 18762 | 18893 | case ConstPtrSpecialBaseStruct: |
| 18763 | 18894 | zig_panic("TODO memcpy on const inner struct"); |
| 18895 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 18896 | zig_panic("TODO memcpy on const inner error union code"); | |
| 18897 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 18898 | zig_panic("TODO memcpy on const inner error union payload"); | |
| 18899 | case ConstPtrSpecialBaseOptionalPayload: | |
| 18900 | zig_panic("TODO memcpy on const inner optional payload"); | |
| 18764 | 18901 | case ConstPtrSpecialHardCodedAddr: |
| 18765 | 18902 | zig_unreachable(); |
| 18766 | 18903 | case ConstPtrSpecialFunction: |
| 18767 | 18904 | zig_panic("TODO memcpy on ptr cast from function"); |
| 18905 | case ConstPtrSpecialNull: | |
| 18906 | zig_panic("TODO memcpy on null ptr"); | |
| 18768 | 18907 | } |
| 18769 | 18908 | |
| 18770 | 18909 | if (dest_start + count > dest_end) { |
| ... | ... | @@ -18797,10 +18936,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio |
| 18797 | 18936 | } |
| 18798 | 18937 | case ConstPtrSpecialBaseStruct: |
| 18799 | 18938 | zig_panic("TODO memcpy on const inner struct"); |
| 18939 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 18940 | zig_panic("TODO memcpy on const inner error union code"); | |
| 18941 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 18942 | zig_panic("TODO memcpy on const inner error union payload"); | |
| 18943 | case ConstPtrSpecialBaseOptionalPayload: | |
| 18944 | zig_panic("TODO memcpy on const inner optional payload"); | |
| 18800 | 18945 | case ConstPtrSpecialHardCodedAddr: |
| 18801 | 18946 | zig_unreachable(); |
| 18802 | 18947 | case ConstPtrSpecialFunction: |
| 18803 | 18948 | zig_panic("TODO memcpy on ptr cast from function"); |
| 18949 | case ConstPtrSpecialNull: | |
| 18950 | zig_panic("TODO memcpy on null ptr"); | |
| 18804 | 18951 | } |
| 18805 | 18952 | |
| 18806 | 18953 | if (src_start + count > src_end) { |
| ... | ... | @@ -18828,9 +18975,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18828 | 18975 | if (type_is_invalid(ptr_ptr->value.type)) |
| 18829 | 18976 | return ira->codegen->invalid_instruction; |
| 18830 | 18977 | |
| 18831 | ZigType *ptr_type = ptr_ptr->value.type; | |
| 18832 | assert(ptr_type->id == ZigTypeIdPointer); | |
| 18833 | ZigType *array_type = ptr_type->data.pointer.child_type; | |
| 18978 | ZigType *ptr_ptr_type = ptr_ptr->value.type; | |
| 18979 | assert(ptr_ptr_type->id == ZigTypeIdPointer); | |
| 18980 | ZigType *array_type = ptr_ptr_type->data.pointer.child_type; | |
| 18834 | 18981 | |
| 18835 | 18982 | IrInstruction *start = instruction->start->child; |
| 18836 | 18983 | if (type_is_invalid(start->value.type)) |
| ... | ... | @@ -18859,10 +19006,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18859 | 19006 | bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic && |
| 18860 | 19007 | ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst; |
| 18861 | 19008 | ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type, |
| 18862 | ptr_type->data.pointer.is_const || is_comptime_const, | |
| 18863 | ptr_type->data.pointer.is_volatile, | |
| 19009 | ptr_ptr_type->data.pointer.is_const || is_comptime_const, | |
| 19010 | ptr_ptr_type->data.pointer.is_volatile, | |
| 18864 | 19011 | PtrLenUnknown, |
| 18865 | ptr_type->data.pointer.explicit_alignment, 0, 0); | |
| 19012 | ptr_ptr_type->data.pointer.explicit_alignment, 0, 0); | |
| 18866 | 19013 | return_type = get_slice_type(ira->codegen, slice_ptr_type); |
| 18867 | 19014 | } else if (array_type->id == ZigTypeIdPointer) { |
| 18868 | 19015 | if (array_type->data.pointer.ptr_len == PtrLenSingle) { |
| ... | ... | @@ -18960,6 +19107,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18960 | 19107 | break; |
| 18961 | 19108 | case ConstPtrSpecialBaseStruct: |
| 18962 | 19109 | zig_panic("TODO slice const inner struct"); |
| 19110 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 19111 | zig_panic("TODO slice const inner error union code"); | |
| 19112 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 19113 | zig_panic("TODO slice const inner error union payload"); | |
| 19114 | case ConstPtrSpecialBaseOptionalPayload: | |
| 19115 | zig_panic("TODO slice const inner optional payload"); | |
| 18963 | 19116 | case ConstPtrSpecialHardCodedAddr: |
| 18964 | 19117 | array_val = nullptr; |
| 18965 | 19118 | abs_offset = 0; |
| ... | ... | @@ -18967,6 +19120,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18967 | 19120 | break; |
| 18968 | 19121 | case ConstPtrSpecialFunction: |
| 18969 | 19122 | zig_panic("TODO slice of ptr cast from function"); |
| 19123 | case ConstPtrSpecialNull: | |
| 19124 | zig_panic("TODO slice of null ptr"); | |
| 18970 | 19125 | } |
| 18971 | 19126 | } else if (is_slice(array_type)) { |
| 18972 | 19127 | ConstExprValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node); |
| ... | ... | @@ -18997,6 +19152,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 18997 | 19152 | break; |
| 18998 | 19153 | case ConstPtrSpecialBaseStruct: |
| 18999 | 19154 | zig_panic("TODO slice const inner struct"); |
| 19155 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 19156 | zig_panic("TODO slice const inner error union code"); | |
| 19157 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 19158 | zig_panic("TODO slice const inner error union payload"); | |
| 19159 | case ConstPtrSpecialBaseOptionalPayload: | |
| 19160 | zig_panic("TODO slice const inner optional payload"); | |
| 19000 | 19161 | case ConstPtrSpecialHardCodedAddr: |
| 19001 | 19162 | array_val = nullptr; |
| 19002 | 19163 | abs_offset = 0; |
| ... | ... | @@ -19004,6 +19165,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 19004 | 19165 | break; |
| 19005 | 19166 | case ConstPtrSpecialFunction: |
| 19006 | 19167 | zig_panic("TODO slice of slice cast from function"); |
| 19168 | case ConstPtrSpecialNull: | |
| 19169 | zig_panic("TODO slice of null"); | |
| 19007 | 19170 | } |
| 19008 | 19171 | } else { |
| 19009 | 19172 | zig_unreachable(); |
| ... | ... | @@ -19069,6 +19232,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 19069 | 19232 | zig_unreachable(); |
| 19070 | 19233 | case ConstPtrSpecialBaseStruct: |
| 19071 | 19234 | zig_panic("TODO"); |
| 19235 | case ConstPtrSpecialBaseErrorUnionCode: | |
| 19236 | zig_panic("TODO"); | |
| 19237 | case ConstPtrSpecialBaseErrorUnionPayload: | |
| 19238 | zig_panic("TODO"); | |
| 19239 | case ConstPtrSpecialBaseOptionalPayload: | |
| 19240 | zig_panic("TODO"); | |
| 19072 | 19241 | case ConstPtrSpecialHardCodedAddr: |
| 19073 | 19242 | init_const_ptr_hard_coded_addr(ira->codegen, ptr_val, |
| 19074 | 19243 | parent_ptr->type->data.pointer.child_type, |
| ... | ... | @@ -19077,6 +19246,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction |
| 19077 | 19246 | break; |
| 19078 | 19247 | case ConstPtrSpecialFunction: |
| 19079 | 19248 | zig_panic("TODO"); |
| 19249 | case ConstPtrSpecialNull: | |
| 19250 | zig_panic("TODO"); | |
| 19080 | 19251 | } |
| 19081 | 19252 | |
| 19082 | 19253 | ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index]; |
| ... | ... | @@ -19432,7 +19603,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct |
| 19432 | 19603 | return ira->codegen->invalid_instruction; |
| 19433 | 19604 | |
| 19434 | 19605 | if (err_union_val->special != ConstValSpecialRuntime) { |
| 19435 | return ir_const_bool(ira, &instruction->base, (err_union_val->data.x_err_union.err != nullptr)); | |
| 19606 | ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set; | |
| 19607 | return ir_const_bool(ira, &instruction->base, (err != nullptr)); | |
| 19436 | 19608 | } |
| 19437 | 19609 | } |
| 19438 | 19610 | |
| ... | ... | @@ -19458,48 +19630,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct |
| 19458 | 19630 | } |
| 19459 | 19631 | } |
| 19460 | 19632 | |
| 19461 | static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, | |
| 19462 | IrInstructionUnwrapErrCode *instruction) | |
| 19463 | { | |
| 19464 | IrInstruction *value = instruction->value->child; | |
| 19465 | if (type_is_invalid(value->value.type)) | |
| 19633 | static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) { | |
| 19634 | IrInstruction *base_ptr = instruction->err_union->child; | |
| 19635 | if (type_is_invalid(base_ptr->value.type)) | |
| 19466 | 19636 | return ira->codegen->invalid_instruction; |
| 19467 | ZigType *ptr_type = value->value.type; | |
| 19637 | ZigType *ptr_type = base_ptr->value.type; | |
| 19468 | 19638 | |
| 19469 | 19639 | // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing. |
| 19470 | 19640 | assert(ptr_type->id == ZigTypeIdPointer); |
| 19471 | 19641 | |
| 19472 | 19642 | ZigType *type_entry = ptr_type->data.pointer.child_type; |
| 19473 | if (type_is_invalid(type_entry)) { | |
| 19643 | if (type_is_invalid(type_entry)) | |
| 19474 | 19644 | return ira->codegen->invalid_instruction; |
| 19475 | } else if (type_entry->id == ZigTypeIdErrorUnion) { | |
| 19476 | if (instr_is_comptime(value)) { | |
| 19477 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); | |
| 19478 | if (!ptr_val) | |
| 19479 | return ira->codegen->invalid_instruction; | |
| 19480 | ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node); | |
| 19481 | if (err_union_val == nullptr) | |
| 19482 | return ira->codegen->invalid_instruction; | |
| 19483 | if (err_union_val->special != ConstValSpecialRuntime) { | |
| 19484 | ErrorTableEntry *err = err_union_val->data.x_err_union.err; | |
| 19485 | assert(err); | |
| 19486 | ||
| 19487 | IrInstruction *result = ir_const(ira, &instruction->base, | |
| 19488 | type_entry->data.error_union.err_set_type); | |
| 19489 | result->value.data.x_err_set = err; | |
| 19490 | return result; | |
| 19491 | } | |
| 19492 | } | |
| 19493 | 19645 | |
| 19494 | IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb, | |
| 19495 | instruction->base.scope, instruction->base.source_node, value); | |
| 19496 | result->value.type = type_entry->data.error_union.err_set_type; | |
| 19497 | return result; | |
| 19498 | } else { | |
| 19499 | ir_add_error(ira, value, | |
| 19646 | if (type_entry->id != ZigTypeIdErrorUnion) { | |
| 19647 | ir_add_error(ira, base_ptr, | |
| 19500 | 19648 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); |
| 19501 | 19649 | return ira->codegen->invalid_instruction; |
| 19502 | 19650 | } |
| 19651 | ||
| 19652 | if (instr_is_comptime(base_ptr)) { | |
| 19653 | ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad); | |
| 19654 | if (!ptr_val) | |
| 19655 | return ira->codegen->invalid_instruction; | |
| 19656 | ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node); | |
| 19657 | if (err_union_val == nullptr) | |
| 19658 | return ira->codegen->invalid_instruction; | |
| 19659 | if (err_union_val->special != ConstValSpecialRuntime) { | |
| 19660 | ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set; | |
| 19661 | assert(err); | |
| 19662 | ||
| 19663 | IrInstruction *result = ir_const(ira, &instruction->base, | |
| 19664 | type_entry->data.error_union.err_set_type); | |
| 19665 | result->value.data.x_err_set = err; | |
| 19666 | return result; | |
| 19667 | } | |
| 19668 | } | |
| 19669 | ||
| 19670 | IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb, | |
| 19671 | instruction->base.scope, instruction->base.source_node, base_ptr); | |
| 19672 | result->value.type = type_entry->data.error_union.err_set_type; | |
| 19673 | return result; | |
| 19503 | 19674 | } |
| 19504 | 19675 | |
| 19505 | 19676 | static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| ... | ... | @@ -19515,48 +19686,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| 19515 | 19686 | assert(ptr_type->id == ZigTypeIdPointer); |
| 19516 | 19687 | |
| 19517 | 19688 | ZigType *type_entry = ptr_type->data.pointer.child_type; |
| 19518 | if (type_is_invalid(type_entry)) { | |
| 19689 | if (type_is_invalid(type_entry)) | |
| 19519 | 19690 | return ira->codegen->invalid_instruction; |
| 19520 | } else if (type_entry->id == ZigTypeIdErrorUnion) { | |
| 19521 | ZigType *payload_type = type_entry->data.error_union.payload_type; | |
| 19522 | if (type_is_invalid(payload_type)) { | |
| 19523 | return ira->codegen->invalid_instruction; | |
| 19524 | } | |
| 19525 | ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type, | |
| 19526 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | |
| 19527 | PtrLenSingle, 0, 0, 0); | |
| 19528 | if (instr_is_comptime(value)) { | |
| 19529 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); | |
| 19530 | if (!ptr_val) | |
| 19531 | return ira->codegen->invalid_instruction; | |
| 19532 | ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node); | |
| 19533 | if (err_union_val == nullptr) | |
| 19534 | return ira->codegen->invalid_instruction; | |
| 19535 | if (err_union_val->special != ConstValSpecialRuntime) { | |
| 19536 | ErrorTableEntry *err = err_union_val->data.x_err_union.err; | |
| 19537 | if (err != nullptr) { | |
| 19538 | ir_add_error(ira, &instruction->base, | |
| 19539 | buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name))); | |
| 19540 | return ira->codegen->invalid_instruction; | |
| 19541 | } | |
| 19542 | 19691 | |
| 19543 | IrInstruction *result = ir_const(ira, &instruction->base, result_type); | |
| 19544 | result->value.data.x_ptr.special = ConstPtrSpecialRef; | |
| 19545 | result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload; | |
| 19546 | return result; | |
| 19547 | } | |
| 19548 | } | |
| 19549 | ||
| 19550 | IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb, | |
| 19551 | instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on); | |
| 19552 | result->value.type = result_type; | |
| 19553 | return result; | |
| 19554 | } else { | |
| 19692 | if (type_entry->id != ZigTypeIdErrorUnion) { | |
| 19555 | 19693 | ir_add_error(ira, value, |
| 19556 | 19694 | buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name))); |
| 19557 | 19695 | return ira->codegen->invalid_instruction; |
| 19558 | 19696 | } |
| 19559 | 19697 | |
| 19698 | ZigType *payload_type = type_entry->data.error_union.payload_type; | |
| 19699 | if (type_is_invalid(payload_type)) | |
| 19700 | return ira->codegen->invalid_instruction; | |
| 19701 | ||
| 19702 | ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type, | |
| 19703 | ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, | |
| 19704 | PtrLenSingle, 0, 0, 0); | |
| 19705 | if (instr_is_comptime(value)) { | |
| 19706 | ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad); | |
| 19707 | if (!ptr_val) | |
| 19708 | return ira->codegen->invalid_instruction; | |
| 19709 | ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node); | |
| 19710 | if (err_union_val == nullptr) | |
| 19711 | return ira->codegen->invalid_instruction; | |
| 19712 | if (err_union_val->special != ConstValSpecialRuntime) { | |
| 19713 | ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set; | |
| 19714 | if (err != nullptr) { | |
| 19715 | ir_add_error(ira, &instruction->base, | |
| 19716 | buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name))); | |
| 19717 | return ira->codegen->invalid_instruction; | |
| 19718 | } | |
| 19719 | ||
| 19720 | IrInstruction *result = ir_const(ira, &instruction->base, result_type); | |
| 19721 | result->value.data.x_ptr.special = ConstPtrSpecialRef; | |
| 19722 | result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload; | |
| 19723 | return result; | |
| 19724 | } | |
| 19725 | } | |
| 19726 | ||
| 19727 | IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb, | |
| 19728 | instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on); | |
| 19729 | result->value.type = result_type; | |
| 19730 | return result; | |
| 19560 | 19731 | } |
| 19561 | 19732 | |
| 19562 | 19733 | static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { |
| ... | ... | @@ -19973,7 +20144,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 |
| 19973 | 20144 | return ira->codegen->invalid_instruction; |
| 19974 | 20145 | } |
| 19975 | 20146 | |
| 19976 | IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type); | |
| 20147 | IrInstruction *result = ir_const(ira, target, result_type); | |
| 19977 | 20148 | copy_const_val(&result->value, val, false); |
| 19978 | 20149 | result->value.type = result_type; |
| 19979 | 20150 | return result; |
| ... | ... | @@ -20021,8 +20192,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 20021 | 20192 | if (!val) |
| 20022 | 20193 | return ira->codegen->invalid_instruction; |
| 20023 | 20194 | |
| 20024 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node, | |
| 20025 | dest_type); | |
| 20195 | IrInstruction *result = ir_const(ira, source_instr, dest_type); | |
| 20026 | 20196 | copy_const_val(&result->value, val, false); |
| 20027 | 20197 | result->value.type = dest_type; |
| 20028 | 20198 | return result; |
| ... | ... | @@ -20045,9 +20215,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 20045 | 20215 | return ira->codegen->invalid_instruction; |
| 20046 | 20216 | } |
| 20047 | 20217 | |
| 20048 | IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope, | |
| 20049 | source_instr->source_node, nullptr, ptr); | |
| 20050 | casted_ptr->value.type = dest_type; | |
| 20218 | IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr); | |
| 20051 | 20219 | |
| 20052 | 20220 | if (type_has_bits(dest_type) && !type_has_bits(src_type)) { |
| 20053 | 20221 | ErrorMsg *msg = ir_add_error(ira, source_instr, |
| ... | ... | @@ -20073,7 +20241,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ |
| 20073 | 20241 | return result; |
| 20074 | 20242 | } |
| 20075 | 20243 | |
| 20076 | static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) { | |
| 20244 | static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) { | |
| 20077 | 20245 | IrInstruction *dest_type_value = instruction->dest_type->child; |
| 20078 | 20246 | ZigType *dest_type = ir_resolve_type(ira, dest_type_value); |
| 20079 | 20247 | if (type_is_invalid(dest_type)) |
| ... | ... | @@ -20211,15 +20379,29 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 20211 | 20379 | if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem))) |
| 20212 | 20380 | return err; |
| 20213 | 20381 | } |
| 20214 | break; | |
| 20382 | return ErrorNone; | |
| 20215 | 20383 | case ConstArraySpecialUndef: |
| 20216 | 20384 | zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type"); |
| 20217 | 20385 | case ConstArraySpecialBuf: |
| 20218 | 20386 | zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type"); |
| 20219 | 20387 | } |
| 20220 | ||
| 20221 | return ErrorNone; | |
| 20388 | zig_unreachable(); | |
| 20222 | 20389 | } |
| 20390 | case ZigTypeIdEnum: | |
| 20391 | switch (val->type->data.enumeration.layout) { | |
| 20392 | case ContainerLayoutAuto: | |
| 20393 | zig_panic("TODO buf_read_value_bytes enum auto"); | |
| 20394 | case ContainerLayoutPacked: | |
| 20395 | zig_panic("TODO buf_read_value_bytes enum packed"); | |
| 20396 | case ContainerLayoutExtern: { | |
| 20397 | ZigType *tag_int_type = val->type->data.enumeration.tag_int_type; | |
| 20398 | assert(tag_int_type->id == ZigTypeIdInt); | |
| 20399 | bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count, | |
| 20400 | codegen->is_big_endian, tag_int_type->data.integral.is_signed); | |
| 20401 | return ErrorNone; | |
| 20402 | } | |
| 20403 | } | |
| 20404 | zig_unreachable(); | |
| 20223 | 20405 | case ZigTypeIdStruct: |
| 20224 | 20406 | switch (val->type->data.structure.layout) { |
| 20225 | 20407 | case ContainerLayoutAuto: { |
| ... | ... | @@ -20258,8 +20440,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou |
| 20258 | 20440 | zig_panic("TODO buf_read_value_bytes error union"); |
| 20259 | 20441 | case ZigTypeIdErrorSet: |
| 20260 | 20442 | zig_panic("TODO buf_read_value_bytes pure error type"); |
| 20261 | case ZigTypeIdEnum: | |
| 20262 | zig_panic("TODO buf_read_value_bytes enum type"); | |
| 20263 | 20443 | case ZigTypeIdFn: |
| 20264 | 20444 | zig_panic("TODO buf_read_value_bytes fn type"); |
| 20265 | 20445 | case ZigTypeIdUnion: |
| ... | ... | @@ -20426,8 +20606,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, |
| 20426 | 20606 | case TldIdContainer: |
| 20427 | 20607 | case TldIdCompTime: |
| 20428 | 20608 | zig_unreachable(); |
| 20429 | case TldIdVar: | |
| 20430 | { | |
| 20609 | case TldIdVar: { | |
| 20431 | 20610 | TldVar *tld_var = (TldVar *)tld; |
| 20432 | 20611 | ZigVar *var = tld_var->var; |
| 20433 | 20612 | |
| ... | ... | @@ -20445,8 +20624,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, |
| 20445 | 20624 | return ir_get_deref(ira, &instruction->base, var_ptr); |
| 20446 | 20625 | } |
| 20447 | 20626 | } |
| 20448 | case TldIdFn: | |
| 20449 | { | |
| 20627 | case TldIdFn: { | |
| 20450 | 20628 | TldFn *tld_fn = (TldFn *)tld; |
| 20451 | 20629 | ZigFn *fn_entry = tld_fn->fn_entry; |
| 20452 | 20630 | assert(fn_entry->type_entry); |
| ... | ... | @@ -20492,8 +20670,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru |
| 20492 | 20670 | if (!val) |
| 20493 | 20671 | return ira->codegen->invalid_instruction; |
| 20494 | 20672 | if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { |
| 20495 | IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope, | |
| 20496 | instruction->base.source_node, usize); | |
| 20673 | IrInstruction *result = ir_const(ira, &instruction->base, usize); | |
| 20497 | 20674 | bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr); |
| 20498 | 20675 | result->value.type = usize; |
| 20499 | 20676 | return result; |
| ... | ... | @@ -21331,6 +21508,9 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21331 | 21508 | case IrInstructionIdErrWrapCode: |
| 21332 | 21509 | case IrInstructionIdErrWrapPayload: |
| 21333 | 21510 | case IrInstructionIdCast: |
| 21511 | case IrInstructionIdDeclVarGen: | |
| 21512 | case IrInstructionIdPtrCastGen: | |
| 21513 | case IrInstructionIdCmpxchgGen: | |
| 21334 | 21514 | zig_unreachable(); |
| 21335 | 21515 | |
| 21336 | 21516 | case IrInstructionIdReturn: |
| ... | ... | @@ -21341,8 +21521,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21341 | 21521 | return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction); |
| 21342 | 21522 | case IrInstructionIdBinOp: |
| 21343 | 21523 | return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction); |
| 21344 | case IrInstructionIdDeclVar: | |
| 21345 | return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction); | |
| 21524 | case IrInstructionIdDeclVarSrc: | |
| 21525 | return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction); | |
| 21346 | 21526 | case IrInstructionIdLoadPtr: |
| 21347 | 21527 | return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); |
| 21348 | 21528 | case IrInstructionIdStorePtr: |
| ... | ... | @@ -21387,8 +21567,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21387 | 21567 | return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction); |
| 21388 | 21568 | case IrInstructionIdTestNonNull: |
| 21389 | 21569 | return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction); |
| 21390 | case IrInstructionIdUnwrapOptional: | |
| 21391 | return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction); | |
| 21570 | case IrInstructionIdOptionalUnwrapPtr: | |
| 21571 | return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction); | |
| 21392 | 21572 | case IrInstructionIdClz: |
| 21393 | 21573 | return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction); |
| 21394 | 21574 | case IrInstructionIdCtz: |
| ... | ... | @@ -21429,8 +21609,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21429 | 21609 | return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction); |
| 21430 | 21610 | case IrInstructionIdEmbedFile: |
| 21431 | 21611 | return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction); |
| 21432 | case IrInstructionIdCmpxchg: | |
| 21433 | return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchg *)instruction); | |
| 21612 | case IrInstructionIdCmpxchgSrc: | |
| 21613 | return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction); | |
| 21434 | 21614 | case IrInstructionIdFence: |
| 21435 | 21615 | return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction); |
| 21436 | 21616 | case IrInstructionIdTruncate: |
| ... | ... | @@ -21497,8 +21677,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio |
| 21497 | 21677 | return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction); |
| 21498 | 21678 | case IrInstructionIdPanic: |
| 21499 | 21679 | return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction); |
| 21500 | case IrInstructionIdPtrCast: | |
| 21501 | return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction); | |
| 21680 | case IrInstructionIdPtrCastSrc: | |
| 21681 | return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction); | |
| 21502 | 21682 | case IrInstructionIdBitCast: |
| 21503 | 21683 | return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction); |
| 21504 | 21684 | case IrInstructionIdIntToPtr: |
| ... | ... | @@ -21682,7 +21862,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21682 | 21862 | case IrInstructionIdBr: |
| 21683 | 21863 | case IrInstructionIdCondBr: |
| 21684 | 21864 | case IrInstructionIdSwitchBr: |
| 21685 | case IrInstructionIdDeclVar: | |
| 21865 | case IrInstructionIdDeclVarSrc: | |
| 21866 | case IrInstructionIdDeclVarGen: | |
| 21686 | 21867 | case IrInstructionIdStorePtr: |
| 21687 | 21868 | case IrInstructionIdCall: |
| 21688 | 21869 | case IrInstructionIdReturn: |
| ... | ... | @@ -21697,7 +21878,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21697 | 21878 | case IrInstructionIdCInclude: |
| 21698 | 21879 | case IrInstructionIdCDefine: |
| 21699 | 21880 | case IrInstructionIdCUndef: |
| 21700 | case IrInstructionIdCmpxchg: | |
| 21701 | 21881 | case IrInstructionIdFence: |
| 21702 | 21882 | case IrInstructionIdMemset: |
| 21703 | 21883 | case IrInstructionIdMemcpy: |
| ... | ... | @@ -21725,6 +21905,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21725 | 21905 | case IrInstructionIdMergeErrRetTraces: |
| 21726 | 21906 | case IrInstructionIdMarkErrRetTracePtr: |
| 21727 | 21907 | case IrInstructionIdAtomicRmw: |
| 21908 | case IrInstructionIdCmpxchgGen: | |
| 21909 | case IrInstructionIdCmpxchgSrc: | |
| 21728 | 21910 | return true; |
| 21729 | 21911 | |
| 21730 | 21912 | case IrInstructionIdPhi: |
| ... | ... | @@ -21750,7 +21932,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21750 | 21932 | case IrInstructionIdSliceType: |
| 21751 | 21933 | case IrInstructionIdSizeOf: |
| 21752 | 21934 | case IrInstructionIdTestNonNull: |
| 21753 | case IrInstructionIdUnwrapOptional: | |
| 21935 | case IrInstructionIdOptionalUnwrapPtr: | |
| 21754 | 21936 | case IrInstructionIdClz: |
| 21755 | 21937 | case IrInstructionIdCtz: |
| 21756 | 21938 | case IrInstructionIdPopCount: |
| ... | ... | @@ -21777,7 +21959,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 21777 | 21959 | case IrInstructionIdErrWrapPayload: |
| 21778 | 21960 | case IrInstructionIdFnProto: |
| 21779 | 21961 | case IrInstructionIdTestComptime: |
| 21780 | case IrInstructionIdPtrCast: | |
| 21962 | case IrInstructionIdPtrCastSrc: | |
| 21963 | case IrInstructionIdPtrCastGen: | |
| 21781 | 21964 | case IrInstructionIdBitCast: |
| 21782 | 21965 | case IrInstructionIdWidenOrShorten: |
| 21783 | 21966 | case IrInstructionIdPtrToInt: |
src/ir.hpp+1-1| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable); |
| 14 | 14 | bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); |
| 15 | 15 | |
| 16 | IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | |
| 16 | ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, | |
| 17 | 17 | ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, |
| 18 | 18 | ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, |
| 19 | 19 | IrExecutable *parent_exec); |
src/ir_print.cpp+61-22| ... | ... | @@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction |
| 172 | 172 | } |
| 173 | 173 | } |
| 174 | 174 | |
| 175 | static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) { | |
| 175 | static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) { | |
| 176 | 176 | const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; |
| 177 | 177 | const char *name = buf_ptr(&decl_var_instruction->var->name); |
| 178 | 178 | if (decl_var_instruction->var_type) { |
| ... | ... | @@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) { |
| 332 | 332 | } |
| 333 | 333 | |
| 334 | 334 | static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) { |
| 335 | fprintf(irp->f, "*"); | |
| 336 | 335 | ir_print_other_instruction(irp, instruction->ptr); |
| 336 | fprintf(irp->f, ".*"); | |
| 337 | 337 | } |
| 338 | 338 | |
| 339 | 339 | static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) { |
| ... | ... | @@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) { |
| 479 | 479 | fprintf(irp->f, ")"); |
| 480 | 480 | } |
| 481 | 481 | |
| 482 | static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) { | |
| 483 | fprintf(irp->f, "*"); | |
| 482 | static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) { | |
| 484 | 483 | ir_print_other_instruction(irp, instruction->value); |
| 485 | 484 | fprintf(irp->f, " != null"); |
| 486 | 485 | } |
| 487 | 486 | |
| 488 | static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) { | |
| 489 | fprintf(irp->f, "&??*"); | |
| 490 | ir_print_other_instruction(irp, instruction->value); | |
| 487 | static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) { | |
| 488 | fprintf(irp->f, "&"); | |
| 489 | ir_print_other_instruction(irp, instruction->base_ptr); | |
| 490 | fprintf(irp->f, ".*.?"); | |
| 491 | 491 | if (!instruction->safety_check_on) { |
| 492 | 492 | fprintf(irp->f, " // no safety"); |
| 493 | 493 | } |
| ... | ... | @@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio |
| 613 | 613 | fprintf(irp->f, ")"); |
| 614 | 614 | } |
| 615 | 615 | |
| 616 | static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) { | |
| 616 | static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) { | |
| 617 | 617 | fprintf(irp->f, "@cmpxchg("); |
| 618 | 618 | ir_print_other_instruction(irp, instruction->ptr); |
| 619 | 619 | fprintf(irp->f, ", "); |
| ... | ... | @@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) { |
| 627 | 627 | fprintf(irp->f, ")"); |
| 628 | 628 | } |
| 629 | 629 | |
| 630 | static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) { | |
| 631 | fprintf(irp->f, "@cmpxchg("); | |
| 632 | ir_print_other_instruction(irp, instruction->ptr); | |
| 633 | fprintf(irp->f, ", "); | |
| 634 | ir_print_other_instruction(irp, instruction->cmp_value); | |
| 635 | fprintf(irp->f, ", "); | |
| 636 | ir_print_other_instruction(irp, instruction->new_value); | |
| 637 | fprintf(irp->f, ", TODO print atomic orders)"); | |
| 638 | } | |
| 639 | ||
| 630 | 640 | static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) { |
| 631 | 641 | fprintf(irp->f, "@fence("); |
| 632 | 642 | ir_print_other_instruction(irp, instruction->order_value); |
| ... | ... | @@ -820,13 +830,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) { |
| 820 | 830 | } |
| 821 | 831 | |
| 822 | 832 | static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) { |
| 823 | fprintf(irp->f, "@unwrapErrorCode("); | |
| 824 | ir_print_other_instruction(irp, instruction->value); | |
| 833 | fprintf(irp->f, "UnwrapErrorCode("); | |
| 834 | ir_print_other_instruction(irp, instruction->err_union); | |
| 825 | 835 | fprintf(irp->f, ")"); |
| 826 | 836 | } |
| 827 | 837 | |
| 828 | 838 | static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) { |
| 829 | fprintf(irp->f, "@unwrapErrorPayload("); | |
| 839 | fprintf(irp->f, "ErrorUnionFieldPayload("); | |
| 830 | 840 | ir_print_other_instruction(irp, instruction->value); |
| 831 | 841 | fprintf(irp->f, ")"); |
| 832 | 842 | if (!instruction->safety_check_on) { |
| ... | ... | @@ -879,7 +889,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst |
| 879 | 889 | fprintf(irp->f, ")"); |
| 880 | 890 | } |
| 881 | 891 | |
| 882 | static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { | |
| 892 | static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) { | |
| 883 | 893 | fprintf(irp->f, "@ptrCast("); |
| 884 | 894 | if (instruction->dest_type) { |
| 885 | 895 | ir_print_other_instruction(irp, instruction->dest_type); |
| ... | ... | @@ -889,6 +899,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) { |
| 889 | 899 | fprintf(irp->f, ")"); |
| 890 | 900 | } |
| 891 | 901 | |
| 902 | static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) { | |
| 903 | fprintf(irp->f, "@ptrCast("); | |
| 904 | ir_print_other_instruction(irp, instruction->ptr); | |
| 905 | fprintf(irp->f, ")"); | |
| 906 | } | |
| 907 | ||
| 892 | 908 | static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { |
| 893 | 909 | fprintf(irp->f, "@bitCast("); |
| 894 | 910 | if (instruction->dest_type) { |
| ... | ... | @@ -900,7 +916,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) { |
| 900 | 916 | } |
| 901 | 917 | |
| 902 | 918 | static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) { |
| 903 | fprintf(irp->f, "@widenOrShorten("); | |
| 919 | fprintf(irp->f, "WidenOrShorten("); | |
| 904 | 920 | ir_print_other_instruction(irp, instruction->target); |
| 905 | 921 | fprintf(irp->f, ")"); |
| 906 | 922 | } |
| ... | ... | @@ -1323,6 +1339,20 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) { |
| 1323 | 1339 | fprintf(irp->f, ")"); |
| 1324 | 1340 | } |
| 1325 | 1341 | |
| 1342 | static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) { | |
| 1343 | ZigVar *var = decl_var_instruction->var; | |
| 1344 | const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var"; | |
| 1345 | const char *name = buf_ptr(&decl_var_instruction->var->name); | |
| 1346 | fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name), | |
| 1347 | var->align_bytes); | |
| 1348 | ||
| 1349 | ir_print_other_instruction(irp, decl_var_instruction->init_value); | |
| 1350 | if (decl_var_instruction->var->is_comptime != nullptr) { | |
| 1351 | fprintf(irp->f, " // comptime = "); | |
| 1352 | ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime); | |
| 1353 | } | |
| 1354 | } | |
| 1355 | ||
| 1326 | 1356 | static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) { |
| 1327 | 1357 | fprintf(irp->f, "@bswap("); |
| 1328 | 1358 | if (instruction->type != nullptr) { |
| ... | ... | @@ -1361,8 +1391,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1361 | 1391 | case IrInstructionIdBinOp: |
| 1362 | 1392 | ir_print_bin_op(irp, (IrInstructionBinOp *)instruction); |
| 1363 | 1393 | break; |
| 1364 | case IrInstructionIdDeclVar: | |
| 1365 | ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction); | |
| 1394 | case IrInstructionIdDeclVarSrc: | |
| 1395 | ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction); | |
| 1366 | 1396 | break; |
| 1367 | 1397 | case IrInstructionIdCast: |
| 1368 | 1398 | ir_print_cast(irp, (IrInstructionCast *)instruction); |
| ... | ... | @@ -1452,10 +1482,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1452 | 1482 | ir_print_size_of(irp, (IrInstructionSizeOf *)instruction); |
| 1453 | 1483 | break; |
| 1454 | 1484 | case IrInstructionIdTestNonNull: |
| 1455 | ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction); | |
| 1485 | ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction); | |
| 1456 | 1486 | break; |
| 1457 | case IrInstructionIdUnwrapOptional: | |
| 1458 | ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction); | |
| 1487 | case IrInstructionIdOptionalUnwrapPtr: | |
| 1488 | ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction); | |
| 1459 | 1489 | break; |
| 1460 | 1490 | case IrInstructionIdCtz: |
| 1461 | 1491 | ir_print_ctz(irp, (IrInstructionCtz *)instruction); |
| ... | ... | @@ -1508,8 +1538,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1508 | 1538 | case IrInstructionIdEmbedFile: |
| 1509 | 1539 | ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction); |
| 1510 | 1540 | break; |
| 1511 | case IrInstructionIdCmpxchg: | |
| 1512 | ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction); | |
| 1541 | case IrInstructionIdCmpxchgSrc: | |
| 1542 | ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction); | |
| 1543 | break; | |
| 1544 | case IrInstructionIdCmpxchgGen: | |
| 1545 | ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction); | |
| 1513 | 1546 | break; |
| 1514 | 1547 | case IrInstructionIdFence: |
| 1515 | 1548 | ir_print_fence(irp, (IrInstructionFence *)instruction); |
| ... | ... | @@ -1607,8 +1640,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1607 | 1640 | case IrInstructionIdTestComptime: |
| 1608 | 1641 | ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction); |
| 1609 | 1642 | break; |
| 1610 | case IrInstructionIdPtrCast: | |
| 1611 | ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction); | |
| 1643 | case IrInstructionIdPtrCastSrc: | |
| 1644 | ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction); | |
| 1645 | break; | |
| 1646 | case IrInstructionIdPtrCastGen: | |
| 1647 | ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction); | |
| 1612 | 1648 | break; |
| 1613 | 1649 | case IrInstructionIdBitCast: |
| 1614 | 1650 | ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction); |
| ... | ... | @@ -1775,6 +1811,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1775 | 1811 | case IrInstructionIdCheckRuntimeScope: |
| 1776 | 1812 | ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction); |
| 1777 | 1813 | break; |
| 1814 | case IrInstructionIdDeclVarGen: | |
| 1815 | ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction); | |
| 1816 | break; | |
| 1778 | 1817 | } |
| 1779 | 1818 | fprintf(irp->f, "\n"); |
| 1780 | 1819 | } |
src/parser.cpp+4-4| ... | ... | @@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse |
| 381 | 381 | else_body = ast_expect(pc, body_parser); |
| 382 | 382 | } |
| 383 | 383 | |
| 384 | assert(res->type == NodeTypeTestExpr); | |
| 384 | assert(res->type == NodeTypeIfOptional); | |
| 385 | 385 | if (err_payload != nullptr) { |
| 386 | 386 | AstNodeTestExpr old = res->data.test_expr; |
| 387 | 387 | res->type = NodeTypeIfErrorExpr; |
| ... | ... | @@ -990,7 +990,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { |
| 990 | 990 | if (requires_semi && else_body == nullptr) |
| 991 | 991 | expect_token(pc, TokenIdSemicolon); |
| 992 | 992 | |
| 993 | assert(res->type == NodeTypeTestExpr); | |
| 993 | assert(res->type == NodeTypeIfOptional); | |
| 994 | 994 | if (err_payload != nullptr) { |
| 995 | 995 | AstNodeTestExpr old = res->data.test_expr; |
| 996 | 996 | res->type = NodeTypeIfErrorExpr; |
| ... | ... | @@ -2204,7 +2204,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) { |
| 2204 | 2204 | Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc); |
| 2205 | 2205 | |
| 2206 | 2206 | PtrPayload payload; |
| 2207 | AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first); | |
| 2207 | AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first); | |
| 2208 | 2208 | res->data.test_expr.target_node = condition; |
| 2209 | 2209 | if (opt_payload.unwrap(&payload)) { |
| 2210 | 2210 | 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 |
| 2999 | 2999 | visit_field(&node->data.if_err_expr.then_node, visit, context); |
| 3000 | 3000 | visit_field(&node->data.if_err_expr.else_node, visit, context); |
| 3001 | 3001 | break; |
| 3002 | case NodeTypeTestExpr: | |
| 3002 | case NodeTypeIfOptional: | |
| 3003 | 3003 | visit_field(&node->data.test_expr.target_node, visit, context); |
| 3004 | 3004 | visit_field(&node->data.test_expr.then_node, visit, context); |
| 3005 | 3005 | visit_field(&node->data.test_expr.else_node, visit, context); |
std/event/fs.zig+23-26| ... | ... | @@ -1307,32 +1307,29 @@ pub fn Watch(comptime V: type) type { |
| 1307 | 1307 | |
| 1308 | 1308 | const test_tmp_dir = "std_event_fs_test"; |
| 1309 | 1309 | |
| 1310 | test "write a file, watch it, write it again" { | |
| 1311 | if (builtin.os == builtin.Os.windows) { | |
| 1312 | // TODO this test is disabled on windows until the coroutine rewrite is finished. | |
| 1313 | // https://github.com/ziglang/zig/issues/1363 | |
| 1314 | return error.SkipZigTest; | |
| 1315 | } | |
| 1316 | var da = std.heap.DirectAllocator.init(); | |
| 1317 | defer da.deinit(); | |
| 1318 | ||
| 1319 | const allocator = &da.allocator; | |
| 1320 | ||
| 1321 | // TODO move this into event loop too | |
| 1322 | try os.makePath(allocator, test_tmp_dir); | |
| 1323 | defer os.deleteTree(allocator, test_tmp_dir) catch {}; | |
| 1324 | ||
| 1325 | var loop: Loop = undefined; | |
| 1326 | try loop.initMultiThreaded(allocator); | |
| 1327 | defer loop.deinit(); | |
| 1328 | ||
| 1329 | var result: anyerror!void = error.ResultNeverWritten; | |
| 1330 | const handle = try async<allocator> testFsWatchCantFail(&loop, &result); | |
| 1331 | defer cancel handle; | |
| 1332 | ||
| 1333 | loop.run(); | |
| 1334 | return result; | |
| 1335 | } | |
| 1310 | // TODO this test is disabled until the coroutine rewrite is finished. | |
| 1311 | //test "write a file, watch it, write it again" { | |
| 1312 | // return error.SkipZigTest; | |
| 1313 | // var da = std.heap.DirectAllocator.init(); | |
| 1314 | // defer da.deinit(); | |
| 1315 | // | |
| 1316 | // const allocator = &da.allocator; | |
| 1317 | // | |
| 1318 | // // TODO move this into event loop too | |
| 1319 | // try os.makePath(allocator, test_tmp_dir); | |
| 1320 | // defer os.deleteTree(allocator, test_tmp_dir) catch {}; | |
| 1321 | // | |
| 1322 | // var loop: Loop = undefined; | |
| 1323 | // try loop.initMultiThreaded(allocator); | |
| 1324 | // defer loop.deinit(); | |
| 1325 | // | |
| 1326 | // var result: anyerror!void = error.ResultNeverWritten; | |
| 1327 | // const handle = try async<allocator> testFsWatchCantFail(&loop, &result); | |
| 1328 | // defer cancel handle; | |
| 1329 | // | |
| 1330 | // loop.run(); | |
| 1331 | // return result; | |
| 1332 | //} | |
| 1336 | 1333 | |
| 1337 | 1334 | async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void { |
| 1338 | 1335 | result.* = await (async testFsWatch(loop) catch unreachable); |
test/behavior.zig deleted-82| ... | ... | @@ -1,82 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | comptime { | |
| 4 | _ = @import("cases/align.zig"); | |
| 5 | _ = @import("cases/alignof.zig"); | |
| 6 | _ = @import("cases/array.zig"); | |
| 7 | _ = @import("cases/asm.zig"); | |
| 8 | _ = @import("cases/atomics.zig"); | |
| 9 | _ = @import("cases/bitcast.zig"); | |
| 10 | _ = @import("cases/bool.zig"); | |
| 11 | _ = @import("cases/bswap.zig"); | |
| 12 | _ = @import("cases/bitreverse.zig"); | |
| 13 | _ = @import("cases/bugs/1076.zig"); | |
| 14 | _ = @import("cases/bugs/1111.zig"); | |
| 15 | _ = @import("cases/bugs/1277.zig"); | |
| 16 | _ = @import("cases/bugs/1322.zig"); | |
| 17 | _ = @import("cases/bugs/1381.zig"); | |
| 18 | _ = @import("cases/bugs/1421.zig"); | |
| 19 | _ = @import("cases/bugs/1442.zig"); | |
| 20 | _ = @import("cases/bugs/1486.zig"); | |
| 21 | _ = @import("cases/bugs/394.zig"); | |
| 22 | _ = @import("cases/bugs/655.zig"); | |
| 23 | _ = @import("cases/bugs/656.zig"); | |
| 24 | _ = @import("cases/bugs/726.zig"); | |
| 25 | _ = @import("cases/bugs/828.zig"); | |
| 26 | _ = @import("cases/bugs/920.zig"); | |
| 27 | _ = @import("cases/byval_arg_var.zig"); | |
| 28 | _ = @import("cases/cancel.zig"); | |
| 29 | _ = @import("cases/cast.zig"); | |
| 30 | _ = @import("cases/const_slice_child.zig"); | |
| 31 | _ = @import("cases/coroutine_await_struct.zig"); | |
| 32 | _ = @import("cases/coroutines.zig"); | |
| 33 | _ = @import("cases/defer.zig"); | |
| 34 | _ = @import("cases/enum.zig"); | |
| 35 | _ = @import("cases/enum_with_members.zig"); | |
| 36 | _ = @import("cases/error.zig"); | |
| 37 | _ = @import("cases/eval.zig"); | |
| 38 | _ = @import("cases/field_parent_ptr.zig"); | |
| 39 | _ = @import("cases/fn.zig"); | |
| 40 | _ = @import("cases/fn_in_struct_in_comptime.zig"); | |
| 41 | _ = @import("cases/for.zig"); | |
| 42 | _ = @import("cases/generics.zig"); | |
| 43 | _ = @import("cases/if.zig"); | |
| 44 | _ = @import("cases/import.zig"); | |
| 45 | _ = @import("cases/incomplete_struct_param_tld.zig"); | |
| 46 | _ = @import("cases/inttoptr.zig"); | |
| 47 | _ = @import("cases/ir_block_deps.zig"); | |
| 48 | _ = @import("cases/math.zig"); | |
| 49 | _ = @import("cases/merge_error_sets.zig"); | |
| 50 | _ = @import("cases/misc.zig"); | |
| 51 | _ = @import("cases/namespace_depends_on_compile_var/index.zig"); | |
| 52 | _ = @import("cases/new_stack_call.zig"); | |
| 53 | _ = @import("cases/null.zig"); | |
| 54 | _ = @import("cases/optional.zig"); | |
| 55 | _ = @import("cases/pointers.zig"); | |
| 56 | _ = @import("cases/popcount.zig"); | |
| 57 | _ = @import("cases/ptrcast.zig"); | |
| 58 | _ = @import("cases/pub_enum/index.zig"); | |
| 59 | _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); | |
| 60 | _ = @import("cases/reflection.zig"); | |
| 61 | _ = @import("cases/sizeof_and_typeof.zig"); | |
| 62 | _ = @import("cases/slice.zig"); | |
| 63 | _ = @import("cases/struct.zig"); | |
| 64 | _ = @import("cases/struct_contains_null_ptr_itself.zig"); | |
| 65 | _ = @import("cases/struct_contains_slice_of_itself.zig"); | |
| 66 | _ = @import("cases/switch.zig"); | |
| 67 | _ = @import("cases/switch_prong_err_enum.zig"); | |
| 68 | _ = @import("cases/switch_prong_implicit_cast.zig"); | |
| 69 | _ = @import("cases/syntax.zig"); | |
| 70 | _ = @import("cases/this.zig"); | |
| 71 | _ = @import("cases/truncate.zig"); | |
| 72 | _ = @import("cases/try.zig"); | |
| 73 | _ = @import("cases/type_info.zig"); | |
| 74 | _ = @import("cases/undefined.zig"); | |
| 75 | _ = @import("cases/underscore.zig"); | |
| 76 | _ = @import("cases/union.zig"); | |
| 77 | _ = @import("cases/var_args.zig"); | |
| 78 | _ = @import("cases/void.zig"); | |
| 79 | _ = @import("cases/while.zig"); | |
| 80 | _ = @import("cases/widening.zig"); | |
| 81 | _ = @import("cases/bit_shifting.zig"); | |
| 82 | } |
test/cases/align.zig deleted-230| ... | ... | @@ -1,230 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | const builtin = @import("builtin"); | |
| 3 | ||
| 4 | var foo: u8 align(4) = 100; | |
| 5 | ||
| 6 | test "global variable alignment" { | |
| 7 | assert(@typeOf(&foo).alignment == 4); | |
| 8 | assert(@typeOf(&foo) == *align(4) u8); | |
| 9 | const slice = (*[1]u8)(&foo)[0..]; | |
| 10 | assert(@typeOf(slice) == []align(4) u8); | |
| 11 | } | |
| 12 | ||
| 13 | fn derp() align(@sizeOf(usize) * 2) i32 { | |
| 14 | return 1234; | |
| 15 | } | |
| 16 | fn noop1() align(1) void {} | |
| 17 | fn noop4() align(4) void {} | |
| 18 | ||
| 19 | test "function alignment" { | |
| 20 | assert(derp() == 1234); | |
| 21 | assert(@typeOf(noop1) == fn () align(1) void); | |
| 22 | assert(@typeOf(noop4) == fn () align(4) void); | |
| 23 | noop1(); | |
| 24 | noop4(); | |
| 25 | } | |
| 26 | ||
| 27 | var baz: packed struct { | |
| 28 | a: u32, | |
| 29 | b: u32, | |
| 30 | } = undefined; | |
| 31 | ||
| 32 | test "packed struct alignment" { | |
| 33 | assert(@typeOf(&baz.b) == *align(1) u32); | |
| 34 | } | |
| 35 | ||
| 36 | const blah: packed struct { | |
| 37 | a: u3, | |
| 38 | b: u3, | |
| 39 | c: u2, | |
| 40 | } = undefined; | |
| 41 | ||
| 42 | test "bit field alignment" { | |
| 43 | assert(@typeOf(&blah.b) == *align(1:3:1) const u3); | |
| 44 | } | |
| 45 | ||
| 46 | test "default alignment allows unspecified in type syntax" { | |
| 47 | assert(*u32 == *align(@alignOf(u32)) u32); | |
| 48 | } | |
| 49 | ||
| 50 | test "implicitly decreasing pointer alignment" { | |
| 51 | const a: u32 align(4) = 3; | |
| 52 | const b: u32 align(8) = 4; | |
| 53 | assert(addUnaligned(&a, &b) == 7); | |
| 54 | } | |
| 55 | ||
| 56 | fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { | |
| 57 | return a.* + b.*; | |
| 58 | } | |
| 59 | ||
| 60 | test "implicitly decreasing slice alignment" { | |
| 61 | const a: u32 align(4) = 3; | |
| 62 | const b: u32 align(8) = 4; | |
| 63 | assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7); | |
| 64 | } | |
| 65 | fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { | |
| 66 | return a[0] + b[0]; | |
| 67 | } | |
| 68 | ||
| 69 | test "specifying alignment allows pointer cast" { | |
| 70 | testBytesAlign(0x33); | |
| 71 | } | |
| 72 | fn testBytesAlign(b: u8) void { | |
| 73 | var bytes align(4) = []u8{ | |
| 74 | b, | |
| 75 | b, | |
| 76 | b, | |
| 77 | b, | |
| 78 | }; | |
| 79 | const ptr = @ptrCast(*u32, &bytes[0]); | |
| 80 | assert(ptr.* == 0x33333333); | |
| 81 | } | |
| 82 | ||
| 83 | test "specifying alignment allows slice cast" { | |
| 84 | testBytesAlignSlice(0x33); | |
| 85 | } | |
| 86 | fn testBytesAlignSlice(b: u8) void { | |
| 87 | var bytes align(4) = []u8{ | |
| 88 | b, | |
| 89 | b, | |
| 90 | b, | |
| 91 | b, | |
| 92 | }; | |
| 93 | const slice: []u32 = @bytesToSlice(u32, bytes[0..]); | |
| 94 | assert(slice[0] == 0x33333333); | |
| 95 | } | |
| 96 | ||
| 97 | test "@alignCast pointers" { | |
| 98 | var x: u32 align(4) = 1; | |
| 99 | expectsOnly1(&x); | |
| 100 | assert(x == 2); | |
| 101 | } | |
| 102 | fn expectsOnly1(x: *align(1) u32) void { | |
| 103 | expects4(@alignCast(4, x)); | |
| 104 | } | |
| 105 | fn expects4(x: *align(4) u32) void { | |
| 106 | x.* += 1; | |
| 107 | } | |
| 108 | ||
| 109 | test "@alignCast slices" { | |
| 110 | var array align(4) = []u32{ | |
| 111 | 1, | |
| 112 | 1, | |
| 113 | }; | |
| 114 | const slice = array[0..]; | |
| 115 | sliceExpectsOnly1(slice); | |
| 116 | assert(slice[0] == 2); | |
| 117 | } | |
| 118 | fn sliceExpectsOnly1(slice: []align(1) u32) void { | |
| 119 | sliceExpects4(@alignCast(4, slice)); | |
| 120 | } | |
| 121 | fn sliceExpects4(slice: []align(4) u32) void { | |
| 122 | slice[0] += 1; | |
| 123 | } | |
| 124 | ||
| 125 | test "implicitly decreasing fn alignment" { | |
| 126 | testImplicitlyDecreaseFnAlign(alignedSmall, 1234); | |
| 127 | testImplicitlyDecreaseFnAlign(alignedBig, 5678); | |
| 128 | } | |
| 129 | ||
| 130 | fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void { | |
| 131 | assert(ptr() == answer); | |
| 132 | } | |
| 133 | ||
| 134 | fn alignedSmall() align(8) i32 { | |
| 135 | return 1234; | |
| 136 | } | |
| 137 | fn alignedBig() align(16) i32 { | |
| 138 | return 5678; | |
| 139 | } | |
| 140 | ||
| 141 | test "@alignCast functions" { | |
| 142 | assert(fnExpectsOnly1(simple4) == 0x19); | |
| 143 | } | |
| 144 | fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 { | |
| 145 | return fnExpects4(@alignCast(4, ptr)); | |
| 146 | } | |
| 147 | fn fnExpects4(ptr: fn () align(4) i32) i32 { | |
| 148 | return ptr(); | |
| 149 | } | |
| 150 | fn simple4() align(4) i32 { | |
| 151 | return 0x19; | |
| 152 | } | |
| 153 | ||
| 154 | test "generic function with align param" { | |
| 155 | assert(whyWouldYouEverDoThis(1) == 0x1); | |
| 156 | assert(whyWouldYouEverDoThis(4) == 0x1); | |
| 157 | assert(whyWouldYouEverDoThis(8) == 0x1); | |
| 158 | } | |
| 159 | ||
| 160 | fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { | |
| 161 | return 0x1; | |
| 162 | } | |
| 163 | ||
| 164 | test "@ptrCast preserves alignment of bigger source" { | |
| 165 | var x: u32 align(16) = 1234; | |
| 166 | const ptr = @ptrCast(*u8, &x); | |
| 167 | assert(@typeOf(ptr) == *align(16) u8); | |
| 168 | } | |
| 169 | ||
| 170 | test "runtime known array index has best alignment possible" { | |
| 171 | // take full advantage of over-alignment | |
| 172 | var array align(4) = []u8{ 1, 2, 3, 4 }; | |
| 173 | assert(@typeOf(&array[0]) == *align(4) u8); | |
| 174 | assert(@typeOf(&array[1]) == *u8); | |
| 175 | assert(@typeOf(&array[2]) == *align(2) u8); | |
| 176 | assert(@typeOf(&array[3]) == *u8); | |
| 177 | ||
| 178 | // because align is too small but we still figure out to use 2 | |
| 179 | var bigger align(2) = []u64{ 1, 2, 3, 4 }; | |
| 180 | assert(@typeOf(&bigger[0]) == *align(2) u64); | |
| 181 | assert(@typeOf(&bigger[1]) == *align(2) u64); | |
| 182 | assert(@typeOf(&bigger[2]) == *align(2) u64); | |
| 183 | assert(@typeOf(&bigger[3]) == *align(2) u64); | |
| 184 | ||
| 185 | // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2 | |
| 186 | var smaller align(2) = []u32{ 1, 2, 3, 4 }; | |
| 187 | comptime assert(@typeOf(smaller[0..]) == []align(2) u32); | |
| 188 | comptime assert(@typeOf(smaller[0..].ptr) == [*]align(2) u32); | |
| 189 | testIndex(smaller[0..].ptr, 0, *align(2) u32); | |
| 190 | testIndex(smaller[0..].ptr, 1, *align(2) u32); | |
| 191 | testIndex(smaller[0..].ptr, 2, *align(2) u32); | |
| 192 | testIndex(smaller[0..].ptr, 3, *align(2) u32); | |
| 193 | ||
| 194 | // has to use ABI alignment because index known at runtime only | |
| 195 | testIndex2(array[0..].ptr, 0, *u8); | |
| 196 | testIndex2(array[0..].ptr, 1, *u8); | |
| 197 | testIndex2(array[0..].ptr, 2, *u8); | |
| 198 | testIndex2(array[0..].ptr, 3, *u8); | |
| 199 | } | |
| 200 | fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void { | |
| 201 | comptime assert(@typeOf(&smaller[index]) == T); | |
| 202 | } | |
| 203 | fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void { | |
| 204 | comptime assert(@typeOf(&ptr[index]) == T); | |
| 205 | } | |
| 206 | ||
| 207 | test "alignstack" { | |
| 208 | assert(fnWithAlignedStack() == 1234); | |
| 209 | } | |
| 210 | ||
| 211 | fn fnWithAlignedStack() i32 { | |
| 212 | @setAlignStack(256); | |
| 213 | return 1234; | |
| 214 | } | |
| 215 | ||
| 216 | test "alignment of structs" { | |
| 217 | assert(@alignOf(struct { | |
| 218 | a: i32, | |
| 219 | b: *i32, | |
| 220 | }) == @alignOf(usize)); | |
| 221 | } | |
| 222 | ||
| 223 | test "alignment of extern() void" { | |
| 224 | var runtime_nothing = nothing; | |
| 225 | const casted1 = @ptrCast(*const u8, runtime_nothing); | |
| 226 | const casted2 = @ptrCast(extern fn () void, casted1); | |
| 227 | casted2(); | |
| 228 | } | |
| 229 | ||
| 230 | extern fn nothing() void {} |
test/cases/alignof.zig deleted-17| ... | ... | @@ -1,17 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | const maxInt = std.math.maxInt; | |
| 5 | ||
| 6 | const Foo = struct { | |
| 7 | x: u32, | |
| 8 | y: u32, | |
| 9 | z: u32, | |
| 10 | }; | |
| 11 | ||
| 12 | test "@alignOf(T) before referencing T" { | |
| 13 | comptime assert(@alignOf(Foo) != maxInt(usize)); | |
| 14 | if (builtin.arch == builtin.Arch.x86_64) { | |
| 15 | comptime assert(@alignOf(Foo) == 4); | |
| 16 | } | |
| 17 | } |
test/cases/array.zig deleted-173| ... | ... | @@ -1,173 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | const mem = @import("std").mem; | |
| 3 | ||
| 4 | test "arrays" { | |
| 5 | var array: [5]u32 = undefined; | |
| 6 | ||
| 7 | var i: u32 = 0; | |
| 8 | while (i < 5) { | |
| 9 | array[i] = i + 1; | |
| 10 | i = array[i]; | |
| 11 | } | |
| 12 | ||
| 13 | i = 0; | |
| 14 | var accumulator = u32(0); | |
| 15 | while (i < 5) { | |
| 16 | accumulator += array[i]; | |
| 17 | ||
| 18 | i += 1; | |
| 19 | } | |
| 20 | ||
| 21 | assert(accumulator == 15); | |
| 22 | assert(getArrayLen(array) == 5); | |
| 23 | } | |
| 24 | fn getArrayLen(a: []const u32) usize { | |
| 25 | return a.len; | |
| 26 | } | |
| 27 | ||
| 28 | test "void arrays" { | |
| 29 | var array: [4]void = undefined; | |
| 30 | array[0] = void{}; | |
| 31 | array[1] = array[2]; | |
| 32 | assert(@sizeOf(@typeOf(array)) == 0); | |
| 33 | assert(array.len == 4); | |
| 34 | } | |
| 35 | ||
| 36 | test "array literal" { | |
| 37 | const hex_mult = []u16{ | |
| 38 | 4096, | |
| 39 | 256, | |
| 40 | 16, | |
| 41 | 1, | |
| 42 | }; | |
| 43 | ||
| 44 | assert(hex_mult.len == 4); | |
| 45 | assert(hex_mult[1] == 256); | |
| 46 | } | |
| 47 | ||
| 48 | test "array dot len const expr" { | |
| 49 | assert(comptime x: { | |
| 50 | break :x some_array.len == 4; | |
| 51 | }); | |
| 52 | } | |
| 53 | ||
| 54 | const ArrayDotLenConstExpr = struct { | |
| 55 | y: [some_array.len]u8, | |
| 56 | }; | |
| 57 | const some_array = []u8{ | |
| 58 | 0, | |
| 59 | 1, | |
| 60 | 2, | |
| 61 | 3, | |
| 62 | }; | |
| 63 | ||
| 64 | test "nested arrays" { | |
| 65 | const array_of_strings = [][]const u8{ | |
| 66 | "hello", | |
| 67 | "this", | |
| 68 | "is", | |
| 69 | "my", | |
| 70 | "thing", | |
| 71 | }; | |
| 72 | for (array_of_strings) |s, i| { | |
| 73 | if (i == 0) assert(mem.eql(u8, s, "hello")); | |
| 74 | if (i == 1) assert(mem.eql(u8, s, "this")); | |
| 75 | if (i == 2) assert(mem.eql(u8, s, "is")); | |
| 76 | if (i == 3) assert(mem.eql(u8, s, "my")); | |
| 77 | if (i == 4) assert(mem.eql(u8, s, "thing")); | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 81 | var s_array: [8]Sub = undefined; | |
| 82 | const Sub = struct { | |
| 83 | b: u8, | |
| 84 | }; | |
| 85 | const Str = struct { | |
| 86 | a: []Sub, | |
| 87 | }; | |
| 88 | test "set global var array via slice embedded in struct" { | |
| 89 | var s = Str{ .a = s_array[0..] }; | |
| 90 | ||
| 91 | s.a[0].b = 1; | |
| 92 | s.a[1].b = 2; | |
| 93 | s.a[2].b = 3; | |
| 94 | ||
| 95 | assert(s_array[0].b == 1); | |
| 96 | assert(s_array[1].b == 2); | |
| 97 | assert(s_array[2].b == 3); | |
| 98 | } | |
| 99 | ||
| 100 | test "array literal with specified size" { | |
| 101 | var array = [2]u8{ | |
| 102 | 1, | |
| 103 | 2, | |
| 104 | }; | |
| 105 | assert(array[0] == 1); | |
| 106 | assert(array[1] == 2); | |
| 107 | } | |
| 108 | ||
| 109 | test "array child property" { | |
| 110 | var x: [5]i32 = undefined; | |
| 111 | assert(@typeOf(x).Child == i32); | |
| 112 | } | |
| 113 | ||
| 114 | test "array len property" { | |
| 115 | var x: [5]i32 = undefined; | |
| 116 | assert(@typeOf(x).len == 5); | |
| 117 | } | |
| 118 | ||
| 119 | test "array len field" { | |
| 120 | var arr = [4]u8{ 0, 0, 0, 0 }; | |
| 121 | var ptr = &arr; | |
| 122 | assert(arr.len == 4); | |
| 123 | comptime assert(arr.len == 4); | |
| 124 | assert(ptr.len == 4); | |
| 125 | comptime assert(ptr.len == 4); | |
| 126 | } | |
| 127 | ||
| 128 | test "single-item pointer to array indexing and slicing" { | |
| 129 | testSingleItemPtrArrayIndexSlice(); | |
| 130 | comptime testSingleItemPtrArrayIndexSlice(); | |
| 131 | } | |
| 132 | ||
| 133 | fn testSingleItemPtrArrayIndexSlice() void { | |
| 134 | var array = "aaaa"; | |
| 135 | doSomeMangling(&array); | |
| 136 | assert(mem.eql(u8, "azya", array)); | |
| 137 | } | |
| 138 | ||
| 139 | fn doSomeMangling(array: *[4]u8) void { | |
| 140 | array[1] = 'z'; | |
| 141 | array[2..3][0] = 'y'; | |
| 142 | } | |
| 143 | ||
| 144 | test "implicit cast single-item pointer" { | |
| 145 | testImplicitCastSingleItemPtr(); | |
| 146 | comptime testImplicitCastSingleItemPtr(); | |
| 147 | } | |
| 148 | ||
| 149 | fn testImplicitCastSingleItemPtr() void { | |
| 150 | var byte: u8 = 100; | |
| 151 | const slice = (*[1]u8)(&byte)[0..]; | |
| 152 | slice[0] += 1; | |
| 153 | assert(byte == 101); | |
| 154 | } | |
| 155 | ||
| 156 | fn testArrayByValAtComptime(b: [2]u8) u8 { | |
| 157 | return b[0]; | |
| 158 | } | |
| 159 | ||
| 160 | test "comptime evalutating function that takes array by value" { | |
| 161 | const arr = []u8{ 0, 1 }; | |
| 162 | _ = comptime testArrayByValAtComptime(arr); | |
| 163 | _ = comptime testArrayByValAtComptime(arr); | |
| 164 | } | |
| 165 | ||
| 166 | test "implicit comptime in array type size" { | |
| 167 | var arr: [plusOne(10)]bool = undefined; | |
| 168 | assert(arr.len == 11); | |
| 169 | } | |
| 170 | ||
| 171 | fn plusOne(x: u32) u32 { | |
| 172 | return x + 1; | |
| 173 | } |
test/cases/asm.zig deleted-48| ... | ... | @@ -1,48 +0,0 @@ |
| 1 | const config = @import("builtin"); | |
| 2 | const assert = @import("std").debug.assert; | |
| 3 | ||
| 4 | comptime { | |
| 5 | if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { | |
| 6 | asm volatile ( | |
| 7 | \\.globl aoeu; | |
| 8 | \\.type aoeu, @function; | |
| 9 | \\.set aoeu, derp; | |
| 10 | ); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | test "module level assembly" { | |
| 15 | if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { | |
| 16 | assert(aoeu() == 1234); | |
| 17 | } | |
| 18 | } | |
| 19 | ||
| 20 | test "output constraint modifiers" { | |
| 21 | // This is only testing compilation. | |
| 22 | var a: u32 = 3; | |
| 23 | asm volatile ("" : [_]"=m,r"(a) : : ""); | |
| 24 | asm volatile ("" : [_]"=r,m"(a) : : ""); | |
| 25 | } | |
| 26 | ||
| 27 | test "alternative constraints" { | |
| 28 | // Make sure we allow commas as a separator for alternative constraints. | |
| 29 | var a: u32 = 3; | |
| 30 | asm volatile ("" : [_]"=r,m"(a) : [_]"r,m"(a) : ""); | |
| 31 | } | |
| 32 | ||
| 33 | test "sized integer/float in asm input" { | |
| 34 | asm volatile ("" : : [_]"m"(usize(3)) : ""); | |
| 35 | asm volatile ("" : : [_]"m"(i15(-3)) : ""); | |
| 36 | asm volatile ("" : : [_]"m"(u3(3)) : ""); | |
| 37 | asm volatile ("" : : [_]"m"(i3(3)) : ""); | |
| 38 | asm volatile ("" : : [_]"m"(u121(3)) : ""); | |
| 39 | asm volatile ("" : : [_]"m"(i121(3)) : ""); | |
| 40 | asm volatile ("" : : [_]"m"(f32(3.17)) : ""); | |
| 41 | asm volatile ("" : : [_]"m"(f64(3.17)) : ""); | |
| 42 | } | |
| 43 | ||
| 44 | extern fn aoeu() i32; | |
| 45 | ||
| 46 | export fn derp() i32 { | |
| 47 | return 1234; | |
| 48 | } |
test/cases/atomics.zig deleted-71| ... | ... | @@ -1,71 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | |
| 5 | const AtomicOrder = builtin.AtomicOrder; | |
| 6 | ||
| 7 | test "cmpxchg" { | |
| 8 | var x: i32 = 1234; | |
| 9 | if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | |
| 10 | assert(x1 == 1234); | |
| 11 | } else { | |
| 12 | @panic("cmpxchg should have failed"); | |
| 13 | } | |
| 14 | ||
| 15 | while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | |
| 16 | assert(x1 == 1234); | |
| 17 | } | |
| 18 | assert(x == 5678); | |
| 19 | ||
| 20 | assert(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); | |
| 21 | assert(x == 42); | |
| 22 | } | |
| 23 | ||
| 24 | test "fence" { | |
| 25 | var x: i32 = 1234; | |
| 26 | @fence(AtomicOrder.SeqCst); | |
| 27 | x = 5678; | |
| 28 | } | |
| 29 | ||
| 30 | test "atomicrmw and atomicload" { | |
| 31 | var data: u8 = 200; | |
| 32 | testAtomicRmw(&data); | |
| 33 | assert(data == 42); | |
| 34 | testAtomicLoad(&data); | |
| 35 | } | |
| 36 | ||
| 37 | fn testAtomicRmw(ptr: *u8) void { | |
| 38 | const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst); | |
| 39 | assert(prev_value == 200); | |
| 40 | comptime { | |
| 41 | var x: i32 = 1234; | |
| 42 | const y: i32 = 12345; | |
| 43 | assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234); | |
| 44 | assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345); | |
| 45 | } | |
| 46 | } | |
| 47 | ||
| 48 | fn testAtomicLoad(ptr: *u8) void { | |
| 49 | const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst); | |
| 50 | assert(x == 42); | |
| 51 | } | |
| 52 | ||
| 53 | test "cmpxchg with ptr" { | |
| 54 | var data1: i32 = 1234; | |
| 55 | var data2: i32 = 5678; | |
| 56 | var data3: i32 = 9101; | |
| 57 | var x: *i32 = &data1; | |
| 58 | if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | |
| 59 | assert(x1 == &data1); | |
| 60 | } else { | |
| 61 | @panic("cmpxchg should have failed"); | |
| 62 | } | |
| 63 | ||
| 64 | while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | |
| 65 | assert(x1 == &data1); | |
| 66 | } | |
| 67 | assert(x == &data3); | |
| 68 | ||
| 69 | assert(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); | |
| 70 | assert(x == &data2); | |
| 71 | } |
test/cases/bit_shifting.zig deleted-88| ... | ... | @@ -1,88 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | ||
| 4 | fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type { | |
| 5 | assert(Key == @IntType(false, Key.bit_count)); | |
| 6 | assert(Key.bit_count >= mask_bit_count); | |
| 7 | const ShardKey = @IntType(false, mask_bit_count); | |
| 8 | const shift_amount = Key.bit_count - ShardKey.bit_count; | |
| 9 | return struct { | |
| 10 | const Self = @This(); | |
| 11 | shards: [1 << ShardKey.bit_count]?*Node, | |
| 12 | ||
| 13 | pub fn create() Self { | |
| 14 | return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) }; | |
| 15 | } | |
| 16 | ||
| 17 | fn getShardKey(key: Key) ShardKey { | |
| 18 | // https://github.com/ziglang/zig/issues/1544 | |
| 19 | // this special case is needed because you can't u32 >> 32. | |
| 20 | if (ShardKey == u0) return 0; | |
| 21 | ||
| 22 | // this can be u1 >> u0 | |
| 23 | const shard_key = key >> shift_amount; | |
| 24 | ||
| 25 | // TODO: https://github.com/ziglang/zig/issues/1544 | |
| 26 | // This cast could be implicit if we teach the compiler that | |
| 27 | // u32 >> 30 -> u2 | |
| 28 | return @intCast(ShardKey, shard_key); | |
| 29 | } | |
| 30 | ||
| 31 | pub fn put(self: *Self, node: *Node) void { | |
| 32 | const shard_key = Self.getShardKey(node.key); | |
| 33 | node.next = self.shards[shard_key]; | |
| 34 | self.shards[shard_key] = node; | |
| 35 | } | |
| 36 | ||
| 37 | pub fn get(self: *Self, key: Key) ?*Node { | |
| 38 | const shard_key = Self.getShardKey(key); | |
| 39 | var maybe_node = self.shards[shard_key]; | |
| 40 | while (maybe_node) |node| : (maybe_node = node.next) { | |
| 41 | if (node.key == key) return node; | |
| 42 | } | |
| 43 | return null; | |
| 44 | } | |
| 45 | ||
| 46 | pub const Node = struct { | |
| 47 | key: Key, | |
| 48 | value: V, | |
| 49 | next: ?*Node, | |
| 50 | ||
| 51 | pub fn init(self: *Node, key: Key, value: V) void { | |
| 52 | self.key = key; | |
| 53 | self.value = value; | |
| 54 | self.next = null; | |
| 55 | } | |
| 56 | }; | |
| 57 | }; | |
| 58 | } | |
| 59 | ||
| 60 | test "sharded table" { | |
| 61 | // realistic 16-way sharding | |
| 62 | testShardedTable(u32, 4, 8); | |
| 63 | ||
| 64 | testShardedTable(u5, 0, 32); // ShardKey == u0 | |
| 65 | testShardedTable(u5, 2, 32); | |
| 66 | testShardedTable(u5, 5, 32); | |
| 67 | ||
| 68 | testShardedTable(u1, 0, 2); | |
| 69 | testShardedTable(u1, 1, 2); // this does u1 >> u0 | |
| 70 | ||
| 71 | testShardedTable(u0, 0, 1); | |
| 72 | } | |
| 73 | fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void { | |
| 74 | const Table = ShardedTable(Key, mask_bit_count, void); | |
| 75 | ||
| 76 | var table = Table.create(); | |
| 77 | var node_buffer: [node_count]Table.Node = undefined; | |
| 78 | for (node_buffer) |*node, i| { | |
| 79 | const key = @intCast(Key, i); | |
| 80 | assert(table.get(key) == null); | |
| 81 | node.init(key, {}); | |
| 82 | table.put(node); | |
| 83 | } | |
| 84 | ||
| 85 | for (node_buffer) |*node, i| { | |
| 86 | assert(table.get(@intCast(Key, i)) == node); | |
| 87 | } | |
| 88 | } |
test/cases/bitcast.zig deleted-37| ... | ... | @@ -1,37 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const maxInt = std.math.maxInt; | |
| 4 | ||
| 5 | test "@bitCast i32 -> u32" { | |
| 6 | testBitCast_i32_u32(); | |
| 7 | comptime testBitCast_i32_u32(); | |
| 8 | } | |
| 9 | ||
| 10 | fn testBitCast_i32_u32() void { | |
| 11 | assert(conv(-1) == maxInt(u32)); | |
| 12 | assert(conv2(maxInt(u32)) == -1); | |
| 13 | } | |
| 14 | ||
| 15 | fn conv(x: i32) u32 { | |
| 16 | return @bitCast(u32, x); | |
| 17 | } | |
| 18 | fn conv2(x: u32) i32 { | |
| 19 | return @bitCast(i32, x); | |
| 20 | } | |
| 21 | ||
| 22 | test "@bitCast extern enum to its integer type" { | |
| 23 | const SOCK = extern enum { | |
| 24 | A, | |
| 25 | B, | |
| 26 | ||
| 27 | fn testBitCastExternEnum() void { | |
| 28 | var SOCK_DGRAM = @This().B; | |
| 29 | var sock_dgram = @bitCast(c_int, SOCK_DGRAM); | |
| 30 | assert(sock_dgram == 1); | |
| 31 | } | |
| 32 | }; | |
| 33 | ||
| 34 | SOCK.testBitCastExternEnum(); | |
| 35 | comptime SOCK.testBitCastExternEnum(); | |
| 36 | } | |
| 37 |
test/cases/bitreverse.zig deleted-81| ... | ... | @@ -1,81 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const minInt = std.math.minInt; | |
| 4 | ||
| 5 | test "@bitreverse" { | |
| 6 | comptime testBitReverse(); | |
| 7 | testBitReverse(); | |
| 8 | } | |
| 9 | ||
| 10 | fn testBitReverse() void { | |
| 11 | // using comptime_ints, unsigned | |
| 12 | assert(@bitreverse(u0, 0) == 0); | |
| 13 | assert(@bitreverse(u5, 0x12) == 0x9); | |
| 14 | assert(@bitreverse(u8, 0x12) == 0x48); | |
| 15 | assert(@bitreverse(u16, 0x1234) == 0x2c48); | |
| 16 | assert(@bitreverse(u24, 0x123456) == 0x6a2c48); | |
| 17 | assert(@bitreverse(u32, 0x12345678) == 0x1e6a2c48); | |
| 18 | assert(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48); | |
| 19 | assert(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48); | |
| 20 | assert(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48); | |
| 21 | assert(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48); | |
| 22 | assert(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48); | |
| 23 | ||
| 24 | // using runtime uints, unsigned | |
| 25 | var num0: u0 = 0; | |
| 26 | assert(@bitreverse(u0, num0) == 0); | |
| 27 | var num5: u5 = 0x12; | |
| 28 | assert(@bitreverse(u5, num5) == 0x9); | |
| 29 | var num8: u8 = 0x12; | |
| 30 | assert(@bitreverse(u8, num8) == 0x48); | |
| 31 | var num16: u16 = 0x1234; | |
| 32 | assert(@bitreverse(u16, num16) == 0x2c48); | |
| 33 | var num24: u24 = 0x123456; | |
| 34 | assert(@bitreverse(u24, num24) == 0x6a2c48); | |
| 35 | var num32: u32 = 0x12345678; | |
| 36 | assert(@bitreverse(u32, num32) == 0x1e6a2c48); | |
| 37 | var num40: u40 = 0x123456789a; | |
| 38 | assert(@bitreverse(u40, num40) == 0x591e6a2c48); | |
| 39 | var num48: u48 = 0x123456789abc; | |
| 40 | assert(@bitreverse(u48, num48) == 0x3d591e6a2c48); | |
| 41 | var num56: u56 = 0x123456789abcde; | |
| 42 | assert(@bitreverse(u56, num56) == 0x7b3d591e6a2c48); | |
| 43 | var num64: u64 = 0x123456789abcdef1; | |
| 44 | assert(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48); | |
| 45 | var num128: u128 = 0x123456789abcdef11121314151617181; | |
| 46 | assert(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48); | |
| 47 | ||
| 48 | // using comptime_ints, signed, positive | |
| 49 | assert(@bitreverse(i0, 0) == 0); | |
| 50 | assert(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8( 0x49))); | |
| 51 | assert(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16( 0x2c48))); | |
| 52 | assert(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24( 0x6a2c48))); | |
| 53 | assert(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32( 0x1e6a2c48))); | |
| 54 | assert(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40( 0x591e6a2c48))); | |
| 55 | assert(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48( 0x3d591e6a2c48))); | |
| 56 | assert(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56( 0x7b3d591e6a2c48))); | |
| 57 | assert(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64,u64(0x8f7b3d591e6a2c48))); | |
| 58 | assert(@bitreverse(i128, @bitCast(i128,u128(0x123456789abcdef11121314151617181))) == @bitCast(i128,u128(0x818e868a828c84888f7b3d591e6a2c48))); | |
| 59 | ||
| 60 | // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm. | |
| 61 | var neg5: i5 = minInt(i5) + 1; | |
| 62 | assert(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5)); | |
| 63 | var neg8: i8 = -18; | |
| 64 | assert(@bitreverse(i8, -18) == @bitreverse(i8, neg8)); | |
| 65 | var neg16: i16 = -32694; | |
| 66 | assert(@bitreverse(i16, -32694) == @bitreverse(i16, neg16)); | |
| 67 | var neg24: i24 = -6773785; | |
| 68 | assert(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24)); | |
| 69 | var neg32: i32 = -16773785; | |
| 70 | assert(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32)); | |
| 71 | var neg40: i40 = minInt(i40) + 12345; | |
| 72 | assert(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40)); | |
| 73 | var neg48: i48 = minInt(i48) + 12345; | |
| 74 | assert(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48)); | |
| 75 | var neg56: i56 = minInt(i56) + 12345; | |
| 76 | assert(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56)); | |
| 77 | var neg64: i64 = minInt(i64) + 12345; | |
| 78 | assert(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64)); | |
| 79 | var neg128: i128 = minInt(i128) + 12345; | |
| 80 | assert(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128)); | |
| 81 | } |
test/cases/bool.zig deleted-35| ... | ... | @@ -1,35 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "bool literals" { | |
| 4 | assert(true); | |
| 5 | assert(!false); | |
| 6 | } | |
| 7 | ||
| 8 | test "cast bool to int" { | |
| 9 | const t = true; | |
| 10 | const f = false; | |
| 11 | assert(@boolToInt(t) == u32(1)); | |
| 12 | assert(@boolToInt(f) == u32(0)); | |
| 13 | nonConstCastBoolToInt(t, f); | |
| 14 | } | |
| 15 | ||
| 16 | fn nonConstCastBoolToInt(t: bool, f: bool) void { | |
| 17 | assert(@boolToInt(t) == u32(1)); | |
| 18 | assert(@boolToInt(f) == u32(0)); | |
| 19 | } | |
| 20 | ||
| 21 | test "bool cmp" { | |
| 22 | assert(testBoolCmp(true, false) == false); | |
| 23 | } | |
| 24 | fn testBoolCmp(a: bool, b: bool) bool { | |
| 25 | return a == b; | |
| 26 | } | |
| 27 | ||
| 28 | const global_f = false; | |
| 29 | const global_t = true; | |
| 30 | const not_global_f = !global_f; | |
| 31 | const not_global_t = !global_t; | |
| 32 | test "compile time bool not" { | |
| 33 | assert(not_global_f); | |
| 34 | assert(!not_global_t); | |
| 35 | } |
test/cases/bswap.zig deleted-32| ... | ... | @@ -1,32 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | ||
| 4 | test "@bswap" { | |
| 5 | comptime testByteSwap(); | |
| 6 | testByteSwap(); | |
| 7 | } | |
| 8 | ||
| 9 | fn testByteSwap() void { | |
| 10 | assert(@bswap(u0, 0) == 0); | |
| 11 | assert(@bswap(u8, 0x12) == 0x12); | |
| 12 | assert(@bswap(u16, 0x1234) == 0x3412); | |
| 13 | assert(@bswap(u24, 0x123456) == 0x563412); | |
| 14 | assert(@bswap(u32, 0x12345678) == 0x78563412); | |
| 15 | assert(@bswap(u40, 0x123456789a) == 0x9a78563412); | |
| 16 | assert(@bswap(u48, 0x123456789abc) == 0xbc9a78563412); | |
| 17 | assert(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412); | |
| 18 | assert(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412); | |
| 19 | assert(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412); | |
| 20 | ||
| 21 | assert(@bswap(i0, 0) == 0); | |
| 22 | assert(@bswap(i8, -50) == -50); | |
| 23 | assert(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412))); | |
| 24 | assert(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412))); | |
| 25 | assert(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412))); | |
| 26 | assert(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412))); | |
| 27 | assert(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412))); | |
| 28 | assert(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412))); | |
| 29 | assert(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412))); | |
| 30 | assert(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == | |
| 31 | @bitCast(i128, u128(0x8171615141312111f1debc9a78563412))); | |
| 32 | } |
test/cases/bugs/1076.zig deleted-16| ... | ... | @@ -1,16 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const mem = std.mem; | |
| 3 | const assert = std.debug.assert; | |
| 4 | ||
| 5 | test "comptime code should not modify constant data" { | |
| 6 | testCastPtrOfArrayToSliceAndPtr(); | |
| 7 | comptime testCastPtrOfArrayToSliceAndPtr(); | |
| 8 | } | |
| 9 | ||
| 10 | fn testCastPtrOfArrayToSliceAndPtr() void { | |
| 11 | var array = "aoeu"; | |
| 12 | const x: [*]u8 = &array; | |
| 13 | x[0] += 1; | |
| 14 | assert(mem.eql(u8, array[0..], "boeu")); | |
| 15 | } | |
| 16 |
test/cases/bugs/1111.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | const Foo = extern enum { | |
| 2 | Bar = -1, | |
| 3 | }; | |
| 4 | ||
| 5 | test "issue 1111 fixed" { | |
| 6 | const v = Foo.Bar; | |
| 7 | ||
| 8 | switch (v) { | |
| 9 | Foo.Bar => return, | |
| 10 | else => return, | |
| 11 | } | |
| 12 | } |
test/cases/bugs/1277.zig deleted-15| ... | ... | @@ -1,15 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | const S = struct { | |
| 4 | f: ?fn () i32, | |
| 5 | }; | |
| 6 | ||
| 7 | const s = S{ .f = f }; | |
| 8 | ||
| 9 | fn f() i32 { | |
| 10 | return 1234; | |
| 11 | } | |
| 12 | ||
| 13 | test "don't emit an LLVM global for a const function when it's in an optional in a struct" { | |
| 14 | std.debug.assertOrPanic(s.f.?() == 1234); | |
| 15 | } |
test/cases/bugs/1322.zig deleted-19| ... | ... | @@ -1,19 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | const B = union(enum) { | |
| 4 | c: C, | |
| 5 | None, | |
| 6 | }; | |
| 7 | ||
| 8 | const A = struct { | |
| 9 | b: B, | |
| 10 | }; | |
| 11 | ||
| 12 | const C = struct {}; | |
| 13 | ||
| 14 | test "tagged union with all void fields but a meaningful tag" { | |
| 15 | var a: A = A{ .b = B{ .c = C{} } }; | |
| 16 | std.debug.assert(@TagType(B)(a.b) == @TagType(B).c); | |
| 17 | a = A{ .b = B.None }; | |
| 18 | std.debug.assert(@TagType(B)(a.b) == @TagType(B).None); | |
| 19 | } |
test/cases/bugs/1381.zig deleted-21| ... | ... | @@ -1,21 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | const B = union(enum) { | |
| 4 | D: u8, | |
| 5 | E: u16, | |
| 6 | }; | |
| 7 | ||
| 8 | const A = union(enum) { | |
| 9 | B: B, | |
| 10 | C: u8, | |
| 11 | }; | |
| 12 | ||
| 13 | test "union that needs padding bytes inside an array" { | |
| 14 | var as = []A{ | |
| 15 | A{ .B = B{ .D = 1 } }, | |
| 16 | A{ .B = B{ .D = 1 } }, | |
| 17 | }; | |
| 18 | ||
| 19 | const a = as[0].B; | |
| 20 | std.debug.assertOrPanic(a.D == 1); | |
| 21 | } |
test/cases/bugs/1421.zig deleted-14| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const assert = std.debug.assert; | |
| 4 | ||
| 5 | const S = struct { | |
| 6 | fn method() builtin.TypeInfo { | |
| 7 | return @typeInfo(S); | |
| 8 | } | |
| 9 | }; | |
| 10 | ||
| 11 | test "functions with return type required to be comptime are generic" { | |
| 12 | const ti = S.method(); | |
| 13 | assert(builtin.TypeId(ti) == builtin.TypeId.Struct); | |
| 14 | } |
test/cases/bugs/1442.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | const Union = union(enum) { | |
| 4 | Text: []const u8, | |
| 5 | Color: u32, | |
| 6 | }; | |
| 7 | ||
| 8 | test "const error union field alignment" { | |
| 9 | var union_or_err: anyerror!Union = Union{ .Color = 1234 }; | |
| 10 | std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234); | |
| 11 | } |
test/cases/bugs/1486.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | const ptr = &global; | |
| 4 | var global: u64 = 123; | |
| 5 | ||
| 6 | test "constant pointer to global variable causes runtime load" { | |
| 7 | global = 1234; | |
| 8 | assert(&global == ptr); | |
| 9 | assert(ptr.* == 1234); | |
| 10 | } | |
| 11 |
test/cases/bugs/394.zig deleted-18| ... | ... | @@ -1,18 +0,0 @@ |
| 1 | const E = union(enum) { | |
| 2 | A: [9]u8, | |
| 3 | B: u64, | |
| 4 | }; | |
| 5 | const S = struct { | |
| 6 | x: u8, | |
| 7 | y: E, | |
| 8 | }; | |
| 9 | ||
| 10 | const assert = @import("std").debug.assert; | |
| 11 | ||
| 12 | test "bug 394 fixed" { | |
| 13 | const x = S{ | |
| 14 | .x = 3, | |
| 15 | .y = E{ .B = 1 }, | |
| 16 | }; | |
| 17 | assert(x.x == 3); | |
| 18 | } |
test/cases/bugs/655.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const other_file = @import("655_other_file.zig"); | |
| 3 | ||
| 4 | test "function with *const parameter with type dereferenced by namespace" { | |
| 5 | const x: other_file.Integer = 1234; | |
| 6 | comptime std.debug.assert(@typeOf(&x) == *const other_file.Integer); | |
| 7 | foo(&x); | |
| 8 | } | |
| 9 | ||
| 10 | fn foo(x: *const other_file.Integer) void { | |
| 11 | std.debug.assert(x.* == 1234); | |
| 12 | } |
test/cases/bugs/655_other_file.zig deleted-1| ... | ... | @@ -1 +0,0 @@ |
| 1 | pub const Integer = u32; |
test/cases/bugs/656.zig deleted-31| ... | ... | @@ -1,31 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | const PrefixOp = union(enum) { | |
| 4 | Return, | |
| 5 | AddrOf: Value, | |
| 6 | }; | |
| 7 | ||
| 8 | const Value = struct { | |
| 9 | align_expr: ?u32, | |
| 10 | }; | |
| 11 | ||
| 12 | test "optional if after an if in a switch prong of a switch with 2 prongs in an else" { | |
| 13 | foo(false, true); | |
| 14 | } | |
| 15 | ||
| 16 | fn foo(a: bool, b: bool) void { | |
| 17 | var prefix_op = PrefixOp{ | |
| 18 | .AddrOf = Value{ .align_expr = 1234 }, | |
| 19 | }; | |
| 20 | if (a) {} else { | |
| 21 | switch (prefix_op) { | |
| 22 | PrefixOp.AddrOf => |addr_of_info| { | |
| 23 | if (b) {} | |
| 24 | if (addr_of_info.align_expr) |align_expr| { | |
| 25 | assert(align_expr == 1234); | |
| 26 | } | |
| 27 | }, | |
| 28 | PrefixOp.Return => {}, | |
| 29 | } | |
| 30 | } | |
| 31 | } |
test/cases/bugs/726.zig deleted-16| ... | ... | @@ -1,16 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "@ptrCast from const to nullable" { | |
| 4 | const c: u8 = 4; | |
| 5 | var x: ?*const u8 = @ptrCast(?*const u8, &c); | |
| 6 | assert(x.?.* == 4); | |
| 7 | } | |
| 8 | ||
| 9 | test "@ptrCast from var in empty struct to nullable" { | |
| 10 | const container = struct { | |
| 11 | var c: u8 = 4; | |
| 12 | }; | |
| 13 | var x: ?*const u8 = @ptrCast(?*const u8, &container.c); | |
| 14 | assert(x.?.* == 4); | |
| 15 | } | |
| 16 |
test/cases/bugs/828.zig deleted-33| ... | ... | @@ -1,33 +0,0 @@ |
| 1 | const CountBy = struct { | |
| 2 | a: usize, | |
| 3 | ||
| 4 | const One = CountBy{ .a = 1 }; | |
| 5 | ||
| 6 | pub fn counter(self: *const CountBy) Counter { | |
| 7 | return Counter{ .i = 0 }; | |
| 8 | } | |
| 9 | }; | |
| 10 | ||
| 11 | const Counter = struct { | |
| 12 | i: usize, | |
| 13 | ||
| 14 | pub fn count(self: *Counter) bool { | |
| 15 | self.i += 1; | |
| 16 | return self.i <= 10; | |
| 17 | } | |
| 18 | }; | |
| 19 | ||
| 20 | fn constCount(comptime cb: *const CountBy, comptime unused: u32) void { | |
| 21 | comptime { | |
| 22 | var cnt = cb.counter(); | |
| 23 | if (cnt.i != 0) @compileError("Counter instance reused!"); | |
| 24 | while (cnt.count()) {} | |
| 25 | } | |
| 26 | } | |
| 27 | ||
| 28 | test "comptime struct return should not return the same instance" { | |
| 29 | //the first parameter must be passed by reference to trigger the bug | |
| 30 | //a second parameter is required to trigger the bug | |
| 31 | const ValA = constCount(&CountBy.One, 12); | |
| 32 | const ValB = constCount(&CountBy.One, 15); | |
| 33 | } |
test/cases/bugs/920.zig deleted-65| ... | ... | @@ -1,65 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const math = std.math; | |
| 3 | const Random = std.rand.Random; | |
| 4 | ||
| 5 | const ZigTable = struct { | |
| 6 | r: f64, | |
| 7 | x: [257]f64, | |
| 8 | f: [257]f64, | |
| 9 | ||
| 10 | pdf: fn (f64) f64, | |
| 11 | is_symmetric: bool, | |
| 12 | zero_case: fn (*Random, f64) f64, | |
| 13 | }; | |
| 14 | ||
| 15 | fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable { | |
| 16 | var tables: ZigTable = undefined; | |
| 17 | ||
| 18 | tables.is_symmetric = is_symmetric; | |
| 19 | tables.r = r; | |
| 20 | tables.pdf = f; | |
| 21 | tables.zero_case = zero_case; | |
| 22 | ||
| 23 | tables.x[0] = v / f(r); | |
| 24 | tables.x[1] = r; | |
| 25 | ||
| 26 | for (tables.x[2..256]) |*entry, i| { | |
| 27 | const last = tables.x[2 + i - 1]; | |
| 28 | entry.* = f_inv(v / last + f(last)); | |
| 29 | } | |
| 30 | tables.x[256] = 0; | |
| 31 | ||
| 32 | for (tables.f[0..]) |*entry, i| { | |
| 33 | entry.* = f(tables.x[i]); | |
| 34 | } | |
| 35 | ||
| 36 | return tables; | |
| 37 | } | |
| 38 | ||
| 39 | const norm_r = 3.6541528853610088; | |
| 40 | const norm_v = 0.00492867323399; | |
| 41 | ||
| 42 | fn norm_f(x: f64) f64 { | |
| 43 | return math.exp(-x * x / 2.0); | |
| 44 | } | |
| 45 | fn norm_f_inv(y: f64) f64 { | |
| 46 | return math.sqrt(-2.0 * math.ln(y)); | |
| 47 | } | |
| 48 | fn norm_zero_case(random: *Random, u: f64) f64 { | |
| 49 | return 0.0; | |
| 50 | } | |
| 51 | ||
| 52 | const NormalDist = blk: { | |
| 53 | @setEvalBranchQuota(30000); | |
| 54 | break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case); | |
| 55 | }; | |
| 56 | ||
| 57 | test "bug 920 fixed" { | |
| 58 | const NormalDist1 = blk: { | |
| 59 | break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case); | |
| 60 | }; | |
| 61 | ||
| 62 | for (NormalDist1.f) |_, i| { | |
| 63 | std.debug.assert(NormalDist1.f[i] == NormalDist.f[i]); | |
| 64 | } | |
| 65 | } |
test/cases/byval_arg_var.zig deleted-27| ... | ... | @@ -1,27 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | var result: []const u8 = "wrong"; | |
| 4 | ||
| 5 | test "aoeu" { | |
| 6 | start(); | |
| 7 | blowUpStack(10); | |
| 8 | ||
| 9 | std.debug.assert(std.mem.eql(u8, result, "string literal")); | |
| 10 | } | |
| 11 | ||
| 12 | fn start() void { | |
| 13 | foo("string literal"); | |
| 14 | } | |
| 15 | ||
| 16 | fn foo(x: var) void { | |
| 17 | bar(x); | |
| 18 | } | |
| 19 | ||
| 20 | fn bar(x: var) void { | |
| 21 | result = x; | |
| 22 | } | |
| 23 | ||
| 24 | fn blowUpStack(x: u32) void { | |
| 25 | if (x == 0) return; | |
| 26 | blowUpStack(x - 1); | |
| 27 | } |
test/cases/cancel.zig deleted-92| ... | ... | @@ -1,92 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | var defer_f1: bool = false; | |
| 4 | var defer_f2: bool = false; | |
| 5 | var defer_f3: bool = false; | |
| 6 | ||
| 7 | test "cancel forwards" { | |
| 8 | var da = std.heap.DirectAllocator.init(); | |
| 9 | defer da.deinit(); | |
| 10 | ||
| 11 | const p = async<&da.allocator> f1() catch unreachable; | |
| 12 | cancel p; | |
| 13 | std.debug.assert(defer_f1); | |
| 14 | std.debug.assert(defer_f2); | |
| 15 | std.debug.assert(defer_f3); | |
| 16 | } | |
| 17 | ||
| 18 | async fn f1() void { | |
| 19 | defer { | |
| 20 | defer_f1 = true; | |
| 21 | } | |
| 22 | await (async f2() catch unreachable); | |
| 23 | } | |
| 24 | ||
| 25 | async fn f2() void { | |
| 26 | defer { | |
| 27 | defer_f2 = true; | |
| 28 | } | |
| 29 | await (async f3() catch unreachable); | |
| 30 | } | |
| 31 | ||
| 32 | async fn f3() void { | |
| 33 | defer { | |
| 34 | defer_f3 = true; | |
| 35 | } | |
| 36 | suspend; | |
| 37 | } | |
| 38 | ||
| 39 | var defer_b1: bool = false; | |
| 40 | var defer_b2: bool = false; | |
| 41 | var defer_b3: bool = false; | |
| 42 | var defer_b4: bool = false; | |
| 43 | ||
| 44 | test "cancel backwards" { | |
| 45 | var da = std.heap.DirectAllocator.init(); | |
| 46 | defer da.deinit(); | |
| 47 | ||
| 48 | const p = async<&da.allocator> b1() catch unreachable; | |
| 49 | cancel p; | |
| 50 | std.debug.assert(defer_b1); | |
| 51 | std.debug.assert(defer_b2); | |
| 52 | std.debug.assert(defer_b3); | |
| 53 | std.debug.assert(defer_b4); | |
| 54 | } | |
| 55 | ||
| 56 | async fn b1() void { | |
| 57 | defer { | |
| 58 | defer_b1 = true; | |
| 59 | } | |
| 60 | await (async b2() catch unreachable); | |
| 61 | } | |
| 62 | ||
| 63 | var b4_handle: promise = undefined; | |
| 64 | ||
| 65 | async fn b2() void { | |
| 66 | const b3_handle = async b3() catch unreachable; | |
| 67 | resume b4_handle; | |
| 68 | cancel b4_handle; | |
| 69 | defer { | |
| 70 | defer_b2 = true; | |
| 71 | } | |
| 72 | const value = await b3_handle; | |
| 73 | @panic("unreachable"); | |
| 74 | } | |
| 75 | ||
| 76 | async fn b3() i32 { | |
| 77 | defer { | |
| 78 | defer_b3 = true; | |
| 79 | } | |
| 80 | await (async b4() catch unreachable); | |
| 81 | return 1234; | |
| 82 | } | |
| 83 | ||
| 84 | async fn b4() void { | |
| 85 | defer { | |
| 86 | defer_b4 = true; | |
| 87 | } | |
| 88 | suspend { | |
| 89 | b4_handle = @handle(); | |
| 90 | } | |
| 91 | suspend; | |
| 92 | } |
test/cases/cast.zig deleted-472| ... | ... | @@ -1,472 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const mem = std.mem; | |
| 4 | const maxInt = std.math.maxInt; | |
| 5 | ||
| 6 | test "int to ptr cast" { | |
| 7 | const x = usize(13); | |
| 8 | const y = @intToPtr(*u8, x); | |
| 9 | const z = @ptrToInt(y); | |
| 10 | assert(z == 13); | |
| 11 | } | |
| 12 | ||
| 13 | test "integer literal to pointer cast" { | |
| 14 | const vga_mem = @intToPtr(*u16, 0xB8000); | |
| 15 | assert(@ptrToInt(vga_mem) == 0xB8000); | |
| 16 | } | |
| 17 | ||
| 18 | test "pointer reinterpret const float to int" { | |
| 19 | const float: f64 = 5.99999999999994648725e-01; | |
| 20 | const float_ptr = &float; | |
| 21 | const int_ptr = @ptrCast(*const i32, float_ptr); | |
| 22 | const int_val = int_ptr.*; | |
| 23 | assert(int_val == 858993411); | |
| 24 | } | |
| 25 | ||
| 26 | test "implicitly cast indirect pointer to maybe-indirect pointer" { | |
| 27 | const S = struct { | |
| 28 | const Self = @This(); | |
| 29 | x: u8, | |
| 30 | fn constConst(p: *const *const Self) u8 { | |
| 31 | return p.*.x; | |
| 32 | } | |
| 33 | fn maybeConstConst(p: ?*const *const Self) u8 { | |
| 34 | return p.?.*.x; | |
| 35 | } | |
| 36 | fn constConstConst(p: *const *const *const Self) u8 { | |
| 37 | return p.*.*.x; | |
| 38 | } | |
| 39 | fn maybeConstConstConst(p: ?*const *const *const Self) u8 { | |
| 40 | return p.?.*.*.x; | |
| 41 | } | |
| 42 | }; | |
| 43 | const s = S{ .x = 42 }; | |
| 44 | const p = &s; | |
| 45 | const q = &p; | |
| 46 | const r = &q; | |
| 47 | assert(42 == S.constConst(q)); | |
| 48 | assert(42 == S.maybeConstConst(q)); | |
| 49 | assert(42 == S.constConstConst(r)); | |
| 50 | assert(42 == S.maybeConstConstConst(r)); | |
| 51 | } | |
| 52 | ||
| 53 | test "explicit cast from integer to error type" { | |
| 54 | testCastIntToErr(error.ItBroke); | |
| 55 | comptime testCastIntToErr(error.ItBroke); | |
| 56 | } | |
| 57 | fn testCastIntToErr(err: anyerror) void { | |
| 58 | const x = @errorToInt(err); | |
| 59 | const y = @intToError(x); | |
| 60 | assert(error.ItBroke == y); | |
| 61 | } | |
| 62 | ||
| 63 | test "peer resolve arrays of different size to const slice" { | |
| 64 | assert(mem.eql(u8, boolToStr(true), "true")); | |
| 65 | assert(mem.eql(u8, boolToStr(false), "false")); | |
| 66 | comptime assert(mem.eql(u8, boolToStr(true), "true")); | |
| 67 | comptime assert(mem.eql(u8, boolToStr(false), "false")); | |
| 68 | } | |
| 69 | fn boolToStr(b: bool) []const u8 { | |
| 70 | return if (b) "true" else "false"; | |
| 71 | } | |
| 72 | ||
| 73 | test "peer resolve array and const slice" { | |
| 74 | testPeerResolveArrayConstSlice(true); | |
| 75 | comptime testPeerResolveArrayConstSlice(true); | |
| 76 | } | |
| 77 | fn testPeerResolveArrayConstSlice(b: bool) void { | |
| 78 | const value1 = if (b) "aoeu" else ([]const u8)("zz"); | |
| 79 | const value2 = if (b) ([]const u8)("zz") else "aoeu"; | |
| 80 | assert(mem.eql(u8, value1, "aoeu")); | |
| 81 | assert(mem.eql(u8, value2, "zz")); | |
| 82 | } | |
| 83 | ||
| 84 | test "implicitly cast from T to anyerror!?T" { | |
| 85 | castToOptionalTypeError(1); | |
| 86 | comptime castToOptionalTypeError(1); | |
| 87 | } | |
| 88 | const A = struct { | |
| 89 | a: i32, | |
| 90 | }; | |
| 91 | fn castToOptionalTypeError(z: i32) void { | |
| 92 | const x = i32(1); | |
| 93 | const y: anyerror!?i32 = x; | |
| 94 | assert((try y).? == 1); | |
| 95 | ||
| 96 | const f = z; | |
| 97 | const g: anyerror!?i32 = f; | |
| 98 | ||
| 99 | const a = A{ .a = z }; | |
| 100 | const b: anyerror!?A = a; | |
| 101 | assert((b catch unreachable).?.a == 1); | |
| 102 | } | |
| 103 | ||
| 104 | test "implicitly cast from int to anyerror!?T" { | |
| 105 | implicitIntLitToOptional(); | |
| 106 | comptime implicitIntLitToOptional(); | |
| 107 | } | |
| 108 | fn implicitIntLitToOptional() void { | |
| 109 | const f: ?i32 = 1; | |
| 110 | const g: anyerror!?i32 = 1; | |
| 111 | } | |
| 112 | ||
| 113 | test "return null from fn() anyerror!?&T" { | |
| 114 | const a = returnNullFromOptionalTypeErrorRef(); | |
| 115 | const b = returnNullLitFromOptionalTypeErrorRef(); | |
| 116 | assert((try a) == null and (try b) == null); | |
| 117 | } | |
| 118 | fn returnNullFromOptionalTypeErrorRef() anyerror!?*A { | |
| 119 | const a: ?*A = null; | |
| 120 | return a; | |
| 121 | } | |
| 122 | fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { | |
| 123 | return null; | |
| 124 | } | |
| 125 | ||
| 126 | test "peer type resolution: ?T and T" { | |
| 127 | assert(peerTypeTAndOptionalT(true, false).? == 0); | |
| 128 | assert(peerTypeTAndOptionalT(false, false).? == 3); | |
| 129 | comptime { | |
| 130 | assert(peerTypeTAndOptionalT(true, false).? == 0); | |
| 131 | assert(peerTypeTAndOptionalT(false, false).? == 3); | |
| 132 | } | |
| 133 | } | |
| 134 | fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { | |
| 135 | if (c) { | |
| 136 | return if (b) null else usize(0); | |
| 137 | } | |
| 138 | ||
| 139 | return usize(3); | |
| 140 | } | |
| 141 | ||
| 142 | test "peer type resolution: [0]u8 and []const u8" { | |
| 143 | assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | |
| 144 | assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | |
| 145 | comptime { | |
| 146 | assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | |
| 147 | assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | |
| 148 | } | |
| 149 | } | |
| 150 | fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { | |
| 151 | if (a) { | |
| 152 | return []const u8{}; | |
| 153 | } | |
| 154 | ||
| 155 | return slice[0..1]; | |
| 156 | } | |
| 157 | ||
| 158 | test "implicitly cast from [N]T to ?[]const T" { | |
| 159 | assert(mem.eql(u8, castToOptionalSlice().?, "hi")); | |
| 160 | comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi")); | |
| 161 | } | |
| 162 | ||
| 163 | fn castToOptionalSlice() ?[]const u8 { | |
| 164 | return "hi"; | |
| 165 | } | |
| 166 | ||
| 167 | test "implicitly cast from [0]T to anyerror![]T" { | |
| 168 | testCastZeroArrayToErrSliceMut(); | |
| 169 | comptime testCastZeroArrayToErrSliceMut(); | |
| 170 | } | |
| 171 | ||
| 172 | fn testCastZeroArrayToErrSliceMut() void { | |
| 173 | assert((gimmeErrOrSlice() catch unreachable).len == 0); | |
| 174 | } | |
| 175 | ||
| 176 | fn gimmeErrOrSlice() anyerror![]u8 { | |
| 177 | return []u8{}; | |
| 178 | } | |
| 179 | ||
| 180 | test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" { | |
| 181 | { | |
| 182 | var data = "hi"; | |
| 183 | const slice = data[0..]; | |
| 184 | assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); | |
| 185 | assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); | |
| 186 | } | |
| 187 | comptime { | |
| 188 | var data = "hi"; | |
| 189 | const slice = data[0..]; | |
| 190 | assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); | |
| 191 | assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); | |
| 192 | } | |
| 193 | } | |
| 194 | fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { | |
| 195 | if (a) { | |
| 196 | return []u8{}; | |
| 197 | } | |
| 198 | ||
| 199 | return slice[0..1]; | |
| 200 | } | |
| 201 | ||
| 202 | test "resolve undefined with integer" { | |
| 203 | testResolveUndefWithInt(true, 1234); | |
| 204 | comptime testResolveUndefWithInt(true, 1234); | |
| 205 | } | |
| 206 | fn testResolveUndefWithInt(b: bool, x: i32) void { | |
| 207 | const value = if (b) x else undefined; | |
| 208 | if (b) { | |
| 209 | assert(value == x); | |
| 210 | } | |
| 211 | } | |
| 212 | ||
| 213 | test "implicit cast from &const [N]T to []const T" { | |
| 214 | testCastConstArrayRefToConstSlice(); | |
| 215 | comptime testCastConstArrayRefToConstSlice(); | |
| 216 | } | |
| 217 | ||
| 218 | fn testCastConstArrayRefToConstSlice() void { | |
| 219 | const blah = "aoeu"; | |
| 220 | const const_array_ref = &blah; | |
| 221 | assert(@typeOf(const_array_ref) == *const [4]u8); | |
| 222 | const slice: []const u8 = const_array_ref; | |
| 223 | assert(mem.eql(u8, slice, "aoeu")); | |
| 224 | } | |
| 225 | ||
| 226 | test "peer type resolution: error and [N]T" { | |
| 227 | // TODO: implicit error!T to error!U where T can implicitly cast to U | |
| 228 | //assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); | |
| 229 | //comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); | |
| 230 | assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); | |
| 231 | comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); | |
| 232 | } | |
| 233 | ||
| 234 | //fn testPeerErrorAndArray(x: u8) error![]const u8 { | |
| 235 | // return switch (x) { | |
| 236 | // 0x00 => "OK", | |
| 237 | // else => error.BadValue, | |
| 238 | // }; | |
| 239 | //} | |
| 240 | fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 { | |
| 241 | return switch (x) { | |
| 242 | 0x00 => "OK", | |
| 243 | 0x01 => "OKK", | |
| 244 | else => error.BadValue, | |
| 245 | }; | |
| 246 | } | |
| 247 | ||
| 248 | test "@floatToInt" { | |
| 249 | testFloatToInts(); | |
| 250 | comptime testFloatToInts(); | |
| 251 | } | |
| 252 | ||
| 253 | fn testFloatToInts() void { | |
| 254 | const x = i32(1e4); | |
| 255 | assert(x == 10000); | |
| 256 | const y = @floatToInt(i32, f32(1e4)); | |
| 257 | assert(y == 10000); | |
| 258 | expectFloatToInt(f16, 255.1, u8, 255); | |
| 259 | expectFloatToInt(f16, 127.2, i8, 127); | |
| 260 | expectFloatToInt(f16, -128.2, i8, -128); | |
| 261 | expectFloatToInt(f32, 255.1, u8, 255); | |
| 262 | expectFloatToInt(f32, 127.2, i8, 127); | |
| 263 | expectFloatToInt(f32, -128.2, i8, -128); | |
| 264 | expectFloatToInt(comptime_int, 1234, i16, 1234); | |
| 265 | } | |
| 266 | ||
| 267 | fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void { | |
| 268 | assert(@floatToInt(I, f) == i); | |
| 269 | } | |
| 270 | ||
| 271 | test "cast u128 to f128 and back" { | |
| 272 | comptime testCast128(); | |
| 273 | testCast128(); | |
| 274 | } | |
| 275 | ||
| 276 | fn testCast128() void { | |
| 277 | assert(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); | |
| 278 | } | |
| 279 | ||
| 280 | fn cast128Int(x: f128) u128 { | |
| 281 | return @bitCast(u128, x); | |
| 282 | } | |
| 283 | ||
| 284 | fn cast128Float(x: u128) f128 { | |
| 285 | return @bitCast(f128, x); | |
| 286 | } | |
| 287 | ||
| 288 | test "const slice widen cast" { | |
| 289 | const bytes align(4) = []u8{ | |
| 290 | 0x12, | |
| 291 | 0x12, | |
| 292 | 0x12, | |
| 293 | 0x12, | |
| 294 | }; | |
| 295 | ||
| 296 | const u32_value = @bytesToSlice(u32, bytes[0..])[0]; | |
| 297 | assert(u32_value == 0x12121212); | |
| 298 | ||
| 299 | assert(@bitCast(u32, bytes) == 0x12121212); | |
| 300 | } | |
| 301 | ||
| 302 | test "single-item pointer of array to slice and to unknown length pointer" { | |
| 303 | testCastPtrOfArrayToSliceAndPtr(); | |
| 304 | comptime testCastPtrOfArrayToSliceAndPtr(); | |
| 305 | } | |
| 306 | ||
| 307 | fn testCastPtrOfArrayToSliceAndPtr() void { | |
| 308 | var array = "aoeu"; | |
| 309 | const x: [*]u8 = &array; | |
| 310 | x[0] += 1; | |
| 311 | assert(mem.eql(u8, array[0..], "boeu")); | |
| 312 | const y: []u8 = &array; | |
| 313 | y[0] += 1; | |
| 314 | assert(mem.eql(u8, array[0..], "coeu")); | |
| 315 | } | |
| 316 | ||
| 317 | test "cast *[1][*]const u8 to [*]const ?[*]const u8" { | |
| 318 | const window_name = [1][*]const u8{c"window name"}; | |
| 319 | const x: [*]const ?[*]const u8 = &window_name; | |
| 320 | assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name")); | |
| 321 | } | |
| 322 | ||
| 323 | test "@intCast comptime_int" { | |
| 324 | const result = @intCast(i32, 1234); | |
| 325 | assert(@typeOf(result) == i32); | |
| 326 | assert(result == 1234); | |
| 327 | } | |
| 328 | ||
| 329 | test "@floatCast comptime_int and comptime_float" { | |
| 330 | { | |
| 331 | const result = @floatCast(f16, 1234); | |
| 332 | assert(@typeOf(result) == f16); | |
| 333 | assert(result == 1234.0); | |
| 334 | } | |
| 335 | { | |
| 336 | const result = @floatCast(f16, 1234.0); | |
| 337 | assert(@typeOf(result) == f16); | |
| 338 | assert(result == 1234.0); | |
| 339 | } | |
| 340 | { | |
| 341 | const result = @floatCast(f32, 1234); | |
| 342 | assert(@typeOf(result) == f32); | |
| 343 | assert(result == 1234.0); | |
| 344 | } | |
| 345 | { | |
| 346 | const result = @floatCast(f32, 1234.0); | |
| 347 | assert(@typeOf(result) == f32); | |
| 348 | assert(result == 1234.0); | |
| 349 | } | |
| 350 | } | |
| 351 | ||
| 352 | test "comptime_int @intToFloat" { | |
| 353 | { | |
| 354 | const result = @intToFloat(f16, 1234); | |
| 355 | assert(@typeOf(result) == f16); | |
| 356 | assert(result == 1234.0); | |
| 357 | } | |
| 358 | { | |
| 359 | const result = @intToFloat(f32, 1234); | |
| 360 | assert(@typeOf(result) == f32); | |
| 361 | assert(result == 1234.0); | |
| 362 | } | |
| 363 | } | |
| 364 | ||
| 365 | test "@bytesToSlice keeps pointer alignment" { | |
| 366 | var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 }; | |
| 367 | const numbers = @bytesToSlice(u32, bytes[0..]); | |
| 368 | comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32); | |
| 369 | } | |
| 370 | ||
| 371 | test "@intCast i32 to u7" { | |
| 372 | var x: u128 = maxInt(u128); | |
| 373 | var y: i32 = 120; | |
| 374 | var z = x >> @intCast(u7, y); | |
| 375 | assert(z == 0xff); | |
| 376 | } | |
| 377 | ||
| 378 | test "implicit cast undefined to optional" { | |
| 379 | assert(MakeType(void).getNull() == null); | |
| 380 | assert(MakeType(void).getNonNull() != null); | |
| 381 | } | |
| 382 | ||
| 383 | fn MakeType(comptime T: type) type { | |
| 384 | return struct { | |
| 385 | fn getNull() ?T { | |
| 386 | return null; | |
| 387 | } | |
| 388 | ||
| 389 | fn getNonNull() ?T { | |
| 390 | return T(undefined); | |
| 391 | } | |
| 392 | }; | |
| 393 | } | |
| 394 | ||
| 395 | test "implicit cast from *[N]T to ?[*]T" { | |
| 396 | var x: ?[*]u16 = null; | |
| 397 | var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; | |
| 398 | ||
| 399 | x = &y; | |
| 400 | assert(std.mem.eql(u16, x.?[0..4], y[0..4])); | |
| 401 | x.?[0] = 8; | |
| 402 | y[3] = 6; | |
| 403 | assert(std.mem.eql(u16, x.?[0..4], y[0..4])); | |
| 404 | } | |
| 405 | ||
| 406 | test "implicit cast from *T to ?*c_void" { | |
| 407 | var a: u8 = 1; | |
| 408 | incrementVoidPtrValue(&a); | |
| 409 | std.debug.assert(a == 2); | |
| 410 | } | |
| 411 | ||
| 412 | fn incrementVoidPtrValue(value: ?*c_void) void { | |
| 413 | @ptrCast(*u8, value.?).* += 1; | |
| 414 | } | |
| 415 | ||
| 416 | test "implicit cast from [*]T to ?*c_void" { | |
| 417 | var a = []u8{ 3, 2, 1 }; | |
| 418 | incrementVoidPtrArray(a[0..].ptr, 3); | |
| 419 | assert(std.mem.eql(u8, a, []u8{ 4, 3, 2 })); | |
| 420 | } | |
| 421 | ||
| 422 | fn incrementVoidPtrArray(array: ?*c_void, len: usize) void { | |
| 423 | var n: usize = 0; | |
| 424 | while (n < len) : (n += 1) { | |
| 425 | @ptrCast([*]u8, array.?)[n] += 1; | |
| 426 | } | |
| 427 | } | |
| 428 | ||
| 429 | test "*usize to *void" { | |
| 430 | var i = usize(0); | |
| 431 | var v = @ptrCast(*void, &i); | |
| 432 | v.* = {}; | |
| 433 | } | |
| 434 | ||
| 435 | test "compile time int to ptr of function" { | |
| 436 | foobar(FUNCTION_CONSTANT); | |
| 437 | } | |
| 438 | ||
| 439 | pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize)); | |
| 440 | pub const PFN_void = extern fn (*c_void) void; | |
| 441 | ||
| 442 | fn foobar(func: PFN_void) void { | |
| 443 | std.debug.assert(@ptrToInt(func) == maxInt(usize)); | |
| 444 | } | |
| 445 | ||
| 446 | test "implicit ptr to *c_void" { | |
| 447 | var a: u32 = 1; | |
| 448 | var ptr: *c_void = &a; | |
| 449 | var b: *u32 = @ptrCast(*u32, ptr); | |
| 450 | assert(b.* == 1); | |
| 451 | var ptr2: ?*c_void = &a; | |
| 452 | var c: *u32 = @ptrCast(*u32, ptr2.?); | |
| 453 | assert(c.* == 1); | |
| 454 | } | |
| 455 | ||
| 456 | test "@intCast to comptime_int" { | |
| 457 | assert(@intCast(comptime_int, 0) == 0); | |
| 458 | } | |
| 459 | ||
| 460 | test "implicit cast comptime numbers to any type when the value fits" { | |
| 461 | const a: u64 = 255; | |
| 462 | var b: u8 = a; | |
| 463 | assert(b == 255); | |
| 464 | } | |
| 465 | ||
| 466 | test "@intToEnum passed a comptime_int to an enum with one item" { | |
| 467 | const E = enum { | |
| 468 | A, | |
| 469 | }; | |
| 470 | const x = @intToEnum(E, 0); | |
| 471 | assert(x == E.A); | |
| 472 | } |
test/cases/const_slice_child.zig deleted-45| ... | ... | @@ -1,45 +0,0 @@ |
| 1 | const debug = @import("std").debug; | |
| 2 | const assert = debug.assert; | |
| 3 | ||
| 4 | var argv: [*]const [*]const u8 = undefined; | |
| 5 | ||
| 6 | test "const slice child" { | |
| 7 | const strs = ([][*]const u8){ | |
| 8 | c"one", | |
| 9 | c"two", | |
| 10 | c"three", | |
| 11 | }; | |
| 12 | // TODO this should implicitly cast | |
| 13 | argv = @ptrCast([*]const [*]const u8, &strs); | |
| 14 | bar(strs.len); | |
| 15 | } | |
| 16 | ||
| 17 | fn foo(args: [][]const u8) void { | |
| 18 | assert(args.len == 3); | |
| 19 | assert(streql(args[0], "one")); | |
| 20 | assert(streql(args[1], "two")); | |
| 21 | assert(streql(args[2], "three")); | |
| 22 | } | |
| 23 | ||
| 24 | fn bar(argc: usize) void { | |
| 25 | const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable; | |
| 26 | for (args) |_, i| { | |
| 27 | const ptr = argv[i]; | |
| 28 | args[i] = ptr[0..strlen(ptr)]; | |
| 29 | } | |
| 30 | foo(args); | |
| 31 | } | |
| 32 | ||
| 33 | fn strlen(ptr: [*]const u8) usize { | |
| 34 | var count: usize = 0; | |
| 35 | while (ptr[count] != 0) : (count += 1) {} | |
| 36 | return count; | |
| 37 | } | |
| 38 | ||
| 39 | fn streql(a: []const u8, b: []const u8) bool { | |
| 40 | if (a.len != b.len) return false; | |
| 41 | for (a) |item, index| { | |
| 42 | if (b[index] != item) return false; | |
| 43 | } | |
| 44 | return true; | |
| 45 | } |
test/cases/coroutine_await_struct.zig deleted-47| ... | ... | @@ -1,47 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const assert = std.debug.assert; | |
| 4 | ||
| 5 | const Foo = struct { | |
| 6 | x: i32, | |
| 7 | }; | |
| 8 | ||
| 9 | var await_a_promise: promise = undefined; | |
| 10 | var await_final_result = Foo{ .x = 0 }; | |
| 11 | ||
| 12 | test "coroutine await struct" { | |
| 13 | var da = std.heap.DirectAllocator.init(); | |
| 14 | defer da.deinit(); | |
| 15 | ||
| 16 | await_seq('a'); | |
| 17 | const p = async<&da.allocator> await_amain() catch unreachable; | |
| 18 | await_seq('f'); | |
| 19 | resume await_a_promise; | |
| 20 | await_seq('i'); | |
| 21 | assert(await_final_result.x == 1234); | |
| 22 | assert(std.mem.eql(u8, await_points, "abcdefghi")); | |
| 23 | } | |
| 24 | async fn await_amain() void { | |
| 25 | await_seq('b'); | |
| 26 | const p = async await_another() catch unreachable; | |
| 27 | await_seq('e'); | |
| 28 | await_final_result = await p; | |
| 29 | await_seq('h'); | |
| 30 | } | |
| 31 | async fn await_another() Foo { | |
| 32 | await_seq('c'); | |
| 33 | suspend { | |
| 34 | await_seq('d'); | |
| 35 | await_a_promise = @handle(); | |
| 36 | } | |
| 37 | await_seq('g'); | |
| 38 | return Foo{ .x = 1234 }; | |
| 39 | } | |
| 40 | ||
| 41 | var await_points = []u8{0} ** "abcdefghi".len; | |
| 42 | var await_seq_index: usize = 0; | |
| 43 | ||
| 44 | fn await_seq(c: u8) void { | |
| 45 | await_points[await_seq_index] = c; | |
| 46 | await_seq_index += 1; | |
| 47 | } |
test/cases/coroutines.zig deleted-258| ... | ... | @@ -1,258 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const assert = std.debug.assert; | |
| 4 | ||
| 5 | var x: i32 = 1; | |
| 6 | ||
| 7 | test "create a coroutine and cancel it" { | |
| 8 | var da = std.heap.DirectAllocator.init(); | |
| 9 | defer da.deinit(); | |
| 10 | ||
| 11 | const p = try async<&da.allocator> simpleAsyncFn(); | |
| 12 | comptime assert(@typeOf(p) == promise->void); | |
| 13 | cancel p; | |
| 14 | assert(x == 2); | |
| 15 | } | |
| 16 | async fn simpleAsyncFn() void { | |
| 17 | x += 1; | |
| 18 | suspend; | |
| 19 | x += 1; | |
| 20 | } | |
| 21 | ||
| 22 | test "coroutine suspend, resume, cancel" { | |
| 23 | var da = std.heap.DirectAllocator.init(); | |
| 24 | defer da.deinit(); | |
| 25 | ||
| 26 | seq('a'); | |
| 27 | const p = try async<&da.allocator> testAsyncSeq(); | |
| 28 | seq('c'); | |
| 29 | resume p; | |
| 30 | seq('f'); | |
| 31 | cancel p; | |
| 32 | seq('g'); | |
| 33 | ||
| 34 | assert(std.mem.eql(u8, points, "abcdefg")); | |
| 35 | } | |
| 36 | async fn testAsyncSeq() void { | |
| 37 | defer seq('e'); | |
| 38 | ||
| 39 | seq('b'); | |
| 40 | suspend; | |
| 41 | seq('d'); | |
| 42 | } | |
| 43 | var points = []u8{0} ** "abcdefg".len; | |
| 44 | var index: usize = 0; | |
| 45 | ||
| 46 | fn seq(c: u8) void { | |
| 47 | points[index] = c; | |
| 48 | index += 1; | |
| 49 | } | |
| 50 | ||
| 51 | test "coroutine suspend with block" { | |
| 52 | var da = std.heap.DirectAllocator.init(); | |
| 53 | defer da.deinit(); | |
| 54 | ||
| 55 | const p = try async<&da.allocator> testSuspendBlock(); | |
| 56 | std.debug.assert(!result); | |
| 57 | resume a_promise; | |
| 58 | std.debug.assert(result); | |
| 59 | cancel p; | |
| 60 | } | |
| 61 | ||
| 62 | var a_promise: promise = undefined; | |
| 63 | var result = false; | |
| 64 | async fn testSuspendBlock() void { | |
| 65 | suspend { | |
| 66 | comptime assert(@typeOf(@handle()) == promise->void); | |
| 67 | a_promise = @handle(); | |
| 68 | } | |
| 69 | ||
| 70 | //Test to make sure that @handle() works as advertised (issue #1296) | |
| 71 | //var our_handle: promise = @handle(); | |
| 72 | assert( a_promise == @handle() ); | |
| 73 | ||
| 74 | result = true; | |
| 75 | } | |
| 76 | ||
| 77 | var await_a_promise: promise = undefined; | |
| 78 | var await_final_result: i32 = 0; | |
| 79 | ||
| 80 | test "coroutine await" { | |
| 81 | var da = std.heap.DirectAllocator.init(); | |
| 82 | defer da.deinit(); | |
| 83 | ||
| 84 | await_seq('a'); | |
| 85 | const p = async<&da.allocator> await_amain() catch unreachable; | |
| 86 | await_seq('f'); | |
| 87 | resume await_a_promise; | |
| 88 | await_seq('i'); | |
| 89 | assert(await_final_result == 1234); | |
| 90 | assert(std.mem.eql(u8, await_points, "abcdefghi")); | |
| 91 | } | |
| 92 | async fn await_amain() void { | |
| 93 | await_seq('b'); | |
| 94 | const p = async await_another() catch unreachable; | |
| 95 | await_seq('e'); | |
| 96 | await_final_result = await p; | |
| 97 | await_seq('h'); | |
| 98 | } | |
| 99 | async fn await_another() i32 { | |
| 100 | await_seq('c'); | |
| 101 | suspend { | |
| 102 | await_seq('d'); | |
| 103 | await_a_promise = @handle(); | |
| 104 | } | |
| 105 | await_seq('g'); | |
| 106 | return 1234; | |
| 107 | } | |
| 108 | ||
| 109 | var await_points = []u8{0} ** "abcdefghi".len; | |
| 110 | var await_seq_index: usize = 0; | |
| 111 | ||
| 112 | fn await_seq(c: u8) void { | |
| 113 | await_points[await_seq_index] = c; | |
| 114 | await_seq_index += 1; | |
| 115 | } | |
| 116 | ||
| 117 | var early_final_result: i32 = 0; | |
| 118 | ||
| 119 | test "coroutine await early return" { | |
| 120 | var da = std.heap.DirectAllocator.init(); | |
| 121 | defer da.deinit(); | |
| 122 | ||
| 123 | early_seq('a'); | |
| 124 | const p = async<&da.allocator> early_amain() catch @panic("out of memory"); | |
| 125 | early_seq('f'); | |
| 126 | assert(early_final_result == 1234); | |
| 127 | assert(std.mem.eql(u8, early_points, "abcdef")); | |
| 128 | } | |
| 129 | async fn early_amain() void { | |
| 130 | early_seq('b'); | |
| 131 | const p = async early_another() catch @panic("out of memory"); | |
| 132 | early_seq('d'); | |
| 133 | early_final_result = await p; | |
| 134 | early_seq('e'); | |
| 135 | } | |
| 136 | async fn early_another() i32 { | |
| 137 | early_seq('c'); | |
| 138 | return 1234; | |
| 139 | } | |
| 140 | ||
| 141 | var early_points = []u8{0} ** "abcdef".len; | |
| 142 | var early_seq_index: usize = 0; | |
| 143 | ||
| 144 | fn early_seq(c: u8) void { | |
| 145 | early_points[early_seq_index] = c; | |
| 146 | early_seq_index += 1; | |
| 147 | } | |
| 148 | ||
| 149 | test "coro allocation failure" { | |
| 150 | var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0); | |
| 151 | if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) { | |
| 152 | @panic("expected allocation failure"); | |
| 153 | } else |err| switch (err) { | |
| 154 | error.OutOfMemory => {}, | |
| 155 | } | |
| 156 | } | |
| 157 | async fn asyncFuncThatNeverGetsRun() void { | |
| 158 | @panic("coro frame allocation should fail"); | |
| 159 | } | |
| 160 | ||
| 161 | test "async function with dot syntax" { | |
| 162 | const S = struct { | |
| 163 | var y: i32 = 1; | |
| 164 | async fn foo() void { | |
| 165 | y += 1; | |
| 166 | suspend; | |
| 167 | } | |
| 168 | }; | |
| 169 | var da = std.heap.DirectAllocator.init(); | |
| 170 | defer da.deinit(); | |
| 171 | const p = try async<&da.allocator> S.foo(); | |
| 172 | cancel p; | |
| 173 | assert(S.y == 2); | |
| 174 | } | |
| 175 | ||
| 176 | test "async fn pointer in a struct field" { | |
| 177 | var data: i32 = 1; | |
| 178 | const Foo = struct { | |
| 179 | bar: async<*std.mem.Allocator> fn (*i32) void, | |
| 180 | }; | |
| 181 | var foo = Foo{ .bar = simpleAsyncFn2 }; | |
| 182 | var da = std.heap.DirectAllocator.init(); | |
| 183 | defer da.deinit(); | |
| 184 | const p = (async<&da.allocator> foo.bar(&data)) catch unreachable; | |
| 185 | assert(data == 2); | |
| 186 | cancel p; | |
| 187 | assert(data == 4); | |
| 188 | } | |
| 189 | async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void { | |
| 190 | defer y.* += 2; | |
| 191 | y.* += 1; | |
| 192 | suspend; | |
| 193 | } | |
| 194 | ||
| 195 | test "async fn with inferred error set" { | |
| 196 | var da = std.heap.DirectAllocator.init(); | |
| 197 | defer da.deinit(); | |
| 198 | const p = (async<&da.allocator> failing()) catch unreachable; | |
| 199 | resume p; | |
| 200 | cancel p; | |
| 201 | } | |
| 202 | async fn failing() !void { | |
| 203 | suspend; | |
| 204 | return error.Fail; | |
| 205 | } | |
| 206 | ||
| 207 | test "error return trace across suspend points - early return" { | |
| 208 | const p = nonFailing(); | |
| 209 | resume p; | |
| 210 | var da = std.heap.DirectAllocator.init(); | |
| 211 | defer da.deinit(); | |
| 212 | const p2 = try async<&da.allocator> printTrace(p); | |
| 213 | cancel p2; | |
| 214 | } | |
| 215 | ||
| 216 | test "error return trace across suspend points - async return" { | |
| 217 | const p = nonFailing(); | |
| 218 | const p2 = try async<std.debug.global_allocator> printTrace(p); | |
| 219 | resume p; | |
| 220 | cancel p2; | |
| 221 | } | |
| 222 | ||
| 223 | // TODO https://github.com/ziglang/zig/issues/760 | |
| 224 | fn nonFailing() promise->(anyerror!void) { | |
| 225 | return async<std.debug.global_allocator> suspendThenFail() catch unreachable; | |
| 226 | } | |
| 227 | async fn suspendThenFail() anyerror!void { | |
| 228 | suspend; | |
| 229 | return error.Fail; | |
| 230 | } | |
| 231 | async fn printTrace(p: promise->(anyerror!void)) void { | |
| 232 | (await p) catch |e| { | |
| 233 | std.debug.assert(e == error.Fail); | |
| 234 | if (@errorReturnTrace()) |trace| { | |
| 235 | assert(trace.index == 1); | |
| 236 | } else switch (builtin.mode) { | |
| 237 | builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"), | |
| 238 | builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {}, | |
| 239 | } | |
| 240 | }; | |
| 241 | } | |
| 242 | ||
| 243 | test "break from suspend" { | |
| 244 | var buf: [500]u8 = undefined; | |
| 245 | var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator; | |
| 246 | var my_result: i32 = 1; | |
| 247 | const p = try async<a> testBreakFromSuspend(&my_result); | |
| 248 | cancel p; | |
| 249 | std.debug.assert(my_result == 2); | |
| 250 | } | |
| 251 | async fn testBreakFromSuspend(my_result: *i32) void { | |
| 252 | suspend { | |
| 253 | resume @handle(); | |
| 254 | } | |
| 255 | my_result.* += 1; | |
| 256 | suspend; | |
| 257 | my_result.* += 1; | |
| 258 | } |
test/cases/defer.zig deleted-78| ... | ... | @@ -1,78 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | var result: [3]u8 = undefined; | |
| 4 | var index: usize = undefined; | |
| 5 | ||
| 6 | fn runSomeErrorDefers(x: bool) !bool { | |
| 7 | index = 0; | |
| 8 | defer { | |
| 9 | result[index] = 'a'; | |
| 10 | index += 1; | |
| 11 | } | |
| 12 | errdefer { | |
| 13 | result[index] = 'b'; | |
| 14 | index += 1; | |
| 15 | } | |
| 16 | defer { | |
| 17 | result[index] = 'c'; | |
| 18 | index += 1; | |
| 19 | } | |
| 20 | return if (x) x else error.FalseNotAllowed; | |
| 21 | } | |
| 22 | ||
| 23 | test "mixing normal and error defers" { | |
| 24 | assert(runSomeErrorDefers(true) catch unreachable); | |
| 25 | assert(result[0] == 'c'); | |
| 26 | assert(result[1] == 'a'); | |
| 27 | ||
| 28 | const ok = runSomeErrorDefers(false) catch |err| x: { | |
| 29 | assert(err == error.FalseNotAllowed); | |
| 30 | break :x true; | |
| 31 | }; | |
| 32 | assert(ok); | |
| 33 | assert(result[0] == 'c'); | |
| 34 | assert(result[1] == 'b'); | |
| 35 | assert(result[2] == 'a'); | |
| 36 | } | |
| 37 | ||
| 38 | test "break and continue inside loop inside defer expression" { | |
| 39 | testBreakContInDefer(10); | |
| 40 | comptime testBreakContInDefer(10); | |
| 41 | } | |
| 42 | ||
| 43 | fn testBreakContInDefer(x: usize) void { | |
| 44 | defer { | |
| 45 | var i: usize = 0; | |
| 46 | while (i < x) : (i += 1) { | |
| 47 | if (i < 5) continue; | |
| 48 | if (i == 5) break; | |
| 49 | } | |
| 50 | assert(i == 5); | |
| 51 | } | |
| 52 | } | |
| 53 | ||
| 54 | test "defer and labeled break" { | |
| 55 | var i = usize(0); | |
| 56 | ||
| 57 | blk: { | |
| 58 | defer i += 1; | |
| 59 | break :blk; | |
| 60 | } | |
| 61 | ||
| 62 | assert(i == 1); | |
| 63 | } | |
| 64 | ||
| 65 | test "errdefer does not apply to fn inside fn" { | |
| 66 | if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad); | |
| 67 | } | |
| 68 | ||
| 69 | fn testNestedFnErrDefer() anyerror!void { | |
| 70 | var a: i32 = 0; | |
| 71 | errdefer a += 1; | |
| 72 | const S = struct { | |
| 73 | fn baz() anyerror { | |
| 74 | return error.Bad; | |
| 75 | } | |
| 76 | }; | |
| 77 | return S.baz(); | |
| 78 | } |
test/cases/enum.zig deleted-894| ... | ... | @@ -1,894 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | const mem = @import("std").mem; | |
| 3 | ||
| 4 | test "enum type" { | |
| 5 | const foo1 = Foo{ .One = 13 }; | |
| 6 | const foo2 = Foo{ | |
| 7 | .Two = Point{ | |
| 8 | .x = 1234, | |
| 9 | .y = 5678, | |
| 10 | }, | |
| 11 | }; | |
| 12 | const bar = Bar.B; | |
| 13 | ||
| 14 | assert(bar == Bar.B); | |
| 15 | assert(@memberCount(Foo) == 3); | |
| 16 | assert(@memberCount(Bar) == 4); | |
| 17 | assert(@sizeOf(Foo) == @sizeOf(FooNoVoid)); | |
| 18 | assert(@sizeOf(Bar) == 1); | |
| 19 | } | |
| 20 | ||
| 21 | test "enum as return value" { | |
| 22 | switch (returnAnInt(13)) { | |
| 23 | Foo.One => |value| assert(value == 13), | |
| 24 | else => unreachable, | |
| 25 | } | |
| 26 | } | |
| 27 | ||
| 28 | const Point = struct { | |
| 29 | x: u64, | |
| 30 | y: u64, | |
| 31 | }; | |
| 32 | const Foo = union(enum) { | |
| 33 | One: i32, | |
| 34 | Two: Point, | |
| 35 | Three: void, | |
| 36 | }; | |
| 37 | const FooNoVoid = union(enum) { | |
| 38 | One: i32, | |
| 39 | Two: Point, | |
| 40 | }; | |
| 41 | const Bar = enum { | |
| 42 | A, | |
| 43 | B, | |
| 44 | C, | |
| 45 | D, | |
| 46 | }; | |
| 47 | ||
| 48 | fn returnAnInt(x: i32) Foo { | |
| 49 | return Foo{ .One = x }; | |
| 50 | } | |
| 51 | ||
| 52 | test "constant enum with payload" { | |
| 53 | var empty = AnEnumWithPayload{ .Empty = {} }; | |
| 54 | var full = AnEnumWithPayload{ .Full = 13 }; | |
| 55 | shouldBeEmpty(empty); | |
| 56 | shouldBeNotEmpty(full); | |
| 57 | } | |
| 58 | ||
| 59 | fn shouldBeEmpty(x: AnEnumWithPayload) void { | |
| 60 | switch (x) { | |
| 61 | AnEnumWithPayload.Empty => {}, | |
| 62 | else => unreachable, | |
| 63 | } | |
| 64 | } | |
| 65 | ||
| 66 | fn shouldBeNotEmpty(x: AnEnumWithPayload) void { | |
| 67 | switch (x) { | |
| 68 | AnEnumWithPayload.Empty => unreachable, | |
| 69 | else => {}, | |
| 70 | } | |
| 71 | } | |
| 72 | ||
| 73 | const AnEnumWithPayload = union(enum) { | |
| 74 | Empty: void, | |
| 75 | Full: i32, | |
| 76 | }; | |
| 77 | ||
| 78 | const Number = enum { | |
| 79 | Zero, | |
| 80 | One, | |
| 81 | Two, | |
| 82 | Three, | |
| 83 | Four, | |
| 84 | }; | |
| 85 | ||
| 86 | test "enum to int" { | |
| 87 | shouldEqual(Number.Zero, 0); | |
| 88 | shouldEqual(Number.One, 1); | |
| 89 | shouldEqual(Number.Two, 2); | |
| 90 | shouldEqual(Number.Three, 3); | |
| 91 | shouldEqual(Number.Four, 4); | |
| 92 | } | |
| 93 | ||
| 94 | fn shouldEqual(n: Number, expected: u3) void { | |
| 95 | assert(@enumToInt(n) == expected); | |
| 96 | } | |
| 97 | ||
| 98 | test "int to enum" { | |
| 99 | testIntToEnumEval(3); | |
| 100 | } | |
| 101 | fn testIntToEnumEval(x: i32) void { | |
| 102 | assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three); | |
| 103 | } | |
| 104 | const IntToEnumNumber = enum { | |
| 105 | Zero, | |
| 106 | One, | |
| 107 | Two, | |
| 108 | Three, | |
| 109 | Four, | |
| 110 | }; | |
| 111 | ||
| 112 | test "@tagName" { | |
| 113 | assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | |
| 114 | comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | |
| 115 | } | |
| 116 | ||
| 117 | fn testEnumTagNameBare(n: BareNumber) []const u8 { | |
| 118 | return @tagName(n); | |
| 119 | } | |
| 120 | ||
| 121 | const BareNumber = enum { | |
| 122 | One, | |
| 123 | Two, | |
| 124 | Three, | |
| 125 | }; | |
| 126 | ||
| 127 | test "enum alignment" { | |
| 128 | comptime { | |
| 129 | assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); | |
| 130 | assert(@alignOf(AlignTestEnum) >= @alignOf(u64)); | |
| 131 | } | |
| 132 | } | |
| 133 | ||
| 134 | const AlignTestEnum = union(enum) { | |
| 135 | A: [9]u8, | |
| 136 | B: u64, | |
| 137 | }; | |
| 138 | ||
| 139 | const ValueCount1 = enum { | |
| 140 | I0, | |
| 141 | }; | |
| 142 | const ValueCount2 = enum { | |
| 143 | I0, | |
| 144 | I1, | |
| 145 | }; | |
| 146 | const ValueCount256 = enum { | |
| 147 | I0, | |
| 148 | I1, | |
| 149 | I2, | |
| 150 | I3, | |
| 151 | I4, | |
| 152 | I5, | |
| 153 | I6, | |
| 154 | I7, | |
| 155 | I8, | |
| 156 | I9, | |
| 157 | I10, | |
| 158 | I11, | |
| 159 | I12, | |
| 160 | I13, | |
| 161 | I14, | |
| 162 | I15, | |
| 163 | I16, | |
| 164 | I17, | |
| 165 | I18, | |
| 166 | I19, | |
| 167 | I20, | |
| 168 | I21, | |
| 169 | I22, | |
| 170 | I23, | |
| 171 | I24, | |
| 172 | I25, | |
| 173 | I26, | |
| 174 | I27, | |
| 175 | I28, | |
| 176 | I29, | |
| 177 | I30, | |
| 178 | I31, | |
| 179 | I32, | |
| 180 | I33, | |
| 181 | I34, | |
| 182 | I35, | |
| 183 | I36, | |
| 184 | I37, | |
| 185 | I38, | |
| 186 | I39, | |
| 187 | I40, | |
| 188 | I41, | |
| 189 | I42, | |
| 190 | I43, | |
| 191 | I44, | |
| 192 | I45, | |
| 193 | I46, | |
| 194 | I47, | |
| 195 | I48, | |
| 196 | I49, | |
| 197 | I50, | |
| 198 | I51, | |
| 199 | I52, | |
| 200 | I53, | |
| 201 | I54, | |
| 202 | I55, | |
| 203 | I56, | |
| 204 | I57, | |
| 205 | I58, | |
| 206 | I59, | |
| 207 | I60, | |
| 208 | I61, | |
| 209 | I62, | |
| 210 | I63, | |
| 211 | I64, | |
| 212 | I65, | |
| 213 | I66, | |
| 214 | I67, | |
| 215 | I68, | |
| 216 | I69, | |
| 217 | I70, | |
| 218 | I71, | |
| 219 | I72, | |
| 220 | I73, | |
| 221 | I74, | |
| 222 | I75, | |
| 223 | I76, | |
| 224 | I77, | |
| 225 | I78, | |
| 226 | I79, | |
| 227 | I80, | |
| 228 | I81, | |
| 229 | I82, | |
| 230 | I83, | |
| 231 | I84, | |
| 232 | I85, | |
| 233 | I86, | |
| 234 | I87, | |
| 235 | I88, | |
| 236 | I89, | |
| 237 | I90, | |
| 238 | I91, | |
| 239 | I92, | |
| 240 | I93, | |
| 241 | I94, | |
| 242 | I95, | |
| 243 | I96, | |
| 244 | I97, | |
| 245 | I98, | |
| 246 | I99, | |
| 247 | I100, | |
| 248 | I101, | |
| 249 | I102, | |
| 250 | I103, | |
| 251 | I104, | |
| 252 | I105, | |
| 253 | I106, | |
| 254 | I107, | |
| 255 | I108, | |
| 256 | I109, | |
| 257 | I110, | |
| 258 | I111, | |
| 259 | I112, | |
| 260 | I113, | |
| 261 | I114, | |
| 262 | I115, | |
| 263 | I116, | |
| 264 | I117, | |
| 265 | I118, | |
| 266 | I119, | |
| 267 | I120, | |
| 268 | I121, | |
| 269 | I122, | |
| 270 | I123, | |
| 271 | I124, | |
| 272 | I125, | |
| 273 | I126, | |
| 274 | I127, | |
| 275 | I128, | |
| 276 | I129, | |
| 277 | I130, | |
| 278 | I131, | |
| 279 | I132, | |
| 280 | I133, | |
| 281 | I134, | |
| 282 | I135, | |
| 283 | I136, | |
| 284 | I137, | |
| 285 | I138, | |
| 286 | I139, | |
| 287 | I140, | |
| 288 | I141, | |
| 289 | I142, | |
| 290 | I143, | |
| 291 | I144, | |
| 292 | I145, | |
| 293 | I146, | |
| 294 | I147, | |
| 295 | I148, | |
| 296 | I149, | |
| 297 | I150, | |
| 298 | I151, | |
| 299 | I152, | |
| 300 | I153, | |
| 301 | I154, | |
| 302 | I155, | |
| 303 | I156, | |
| 304 | I157, | |
| 305 | I158, | |
| 306 | I159, | |
| 307 | I160, | |
| 308 | I161, | |
| 309 | I162, | |
| 310 | I163, | |
| 311 | I164, | |
| 312 | I165, | |
| 313 | I166, | |
| 314 | I167, | |
| 315 | I168, | |
| 316 | I169, | |
| 317 | I170, | |
| 318 | I171, | |
| 319 | I172, | |
| 320 | I173, | |
| 321 | I174, | |
| 322 | I175, | |
| 323 | I176, | |
| 324 | I177, | |
| 325 | I178, | |
| 326 | I179, | |
| 327 | I180, | |
| 328 | I181, | |
| 329 | I182, | |
| 330 | I183, | |
| 331 | I184, | |
| 332 | I185, | |
| 333 | I186, | |
| 334 | I187, | |
| 335 | I188, | |
| 336 | I189, | |
| 337 | I190, | |
| 338 | I191, | |
| 339 | I192, | |
| 340 | I193, | |
| 341 | I194, | |
| 342 | I195, | |
| 343 | I196, | |
| 344 | I197, | |
| 345 | I198, | |
| 346 | I199, | |
| 347 | I200, | |
| 348 | I201, | |
| 349 | I202, | |
| 350 | I203, | |
| 351 | I204, | |
| 352 | I205, | |
| 353 | I206, | |
| 354 | I207, | |
| 355 | I208, | |
| 356 | I209, | |
| 357 | I210, | |
| 358 | I211, | |
| 359 | I212, | |
| 360 | I213, | |
| 361 | I214, | |
| 362 | I215, | |
| 363 | I216, | |
| 364 | I217, | |
| 365 | I218, | |
| 366 | I219, | |
| 367 | I220, | |
| 368 | I221, | |
| 369 | I222, | |
| 370 | I223, | |
| 371 | I224, | |
| 372 | I225, | |
| 373 | I226, | |
| 374 | I227, | |
| 375 | I228, | |
| 376 | I229, | |
| 377 | I230, | |
| 378 | I231, | |
| 379 | I232, | |
| 380 | I233, | |
| 381 | I234, | |
| 382 | I235, | |
| 383 | I236, | |
| 384 | I237, | |
| 385 | I238, | |
| 386 | I239, | |
| 387 | I240, | |
| 388 | I241, | |
| 389 | I242, | |
| 390 | I243, | |
| 391 | I244, | |
| 392 | I245, | |
| 393 | I246, | |
| 394 | I247, | |
| 395 | I248, | |
| 396 | I249, | |
| 397 | I250, | |
| 398 | I251, | |
| 399 | I252, | |
| 400 | I253, | |
| 401 | I254, | |
| 402 | I255, | |
| 403 | }; | |
| 404 | const ValueCount257 = enum { | |
| 405 | I0, | |
| 406 | I1, | |
| 407 | I2, | |
| 408 | I3, | |
| 409 | I4, | |
| 410 | I5, | |
| 411 | I6, | |
| 412 | I7, | |
| 413 | I8, | |
| 414 | I9, | |
| 415 | I10, | |
| 416 | I11, | |
| 417 | I12, | |
| 418 | I13, | |
| 419 | I14, | |
| 420 | I15, | |
| 421 | I16, | |
| 422 | I17, | |
| 423 | I18, | |
| 424 | I19, | |
| 425 | I20, | |
| 426 | I21, | |
| 427 | I22, | |
| 428 | I23, | |
| 429 | I24, | |
| 430 | I25, | |
| 431 | I26, | |
| 432 | I27, | |
| 433 | I28, | |
| 434 | I29, | |
| 435 | I30, | |
| 436 | I31, | |
| 437 | I32, | |
| 438 | I33, | |
| 439 | I34, | |
| 440 | I35, | |
| 441 | I36, | |
| 442 | I37, | |
| 443 | I38, | |
| 444 | I39, | |
| 445 | I40, | |
| 446 | I41, | |
| 447 | I42, | |
| 448 | I43, | |
| 449 | I44, | |
| 450 | I45, | |
| 451 | I46, | |
| 452 | I47, | |
| 453 | I48, | |
| 454 | I49, | |
| 455 | I50, | |
| 456 | I51, | |
| 457 | I52, | |
| 458 | I53, | |
| 459 | I54, | |
| 460 | I55, | |
| 461 | I56, | |
| 462 | I57, | |
| 463 | I58, | |
| 464 | I59, | |
| 465 | I60, | |
| 466 | I61, | |
| 467 | I62, | |
| 468 | I63, | |
| 469 | I64, | |
| 470 | I65, | |
| 471 | I66, | |
| 472 | I67, | |
| 473 | I68, | |
| 474 | I69, | |
| 475 | I70, | |
| 476 | I71, | |
| 477 | I72, | |
| 478 | I73, | |
| 479 | I74, | |
| 480 | I75, | |
| 481 | I76, | |
| 482 | I77, | |
| 483 | I78, | |
| 484 | I79, | |
| 485 | I80, | |
| 486 | I81, | |
| 487 | I82, | |
| 488 | I83, | |
| 489 | I84, | |
| 490 | I85, | |
| 491 | I86, | |
| 492 | I87, | |
| 493 | I88, | |
| 494 | I89, | |
| 495 | I90, | |
| 496 | I91, | |
| 497 | I92, | |
| 498 | I93, | |
| 499 | I94, | |
| 500 | I95, | |
| 501 | I96, | |
| 502 | I97, | |
| 503 | I98, | |
| 504 | I99, | |
| 505 | I100, | |
| 506 | I101, | |
| 507 | I102, | |
| 508 | I103, | |
| 509 | I104, | |
| 510 | I105, | |
| 511 | I106, | |
| 512 | I107, | |
| 513 | I108, | |
| 514 | I109, | |
| 515 | I110, | |
| 516 | I111, | |
| 517 | I112, | |
| 518 | I113, | |
| 519 | I114, | |
| 520 | I115, | |
| 521 | I116, | |
| 522 | I117, | |
| 523 | I118, | |
| 524 | I119, | |
| 525 | I120, | |
| 526 | I121, | |
| 527 | I122, | |
| 528 | I123, | |
| 529 | I124, | |
| 530 | I125, | |
| 531 | I126, | |
| 532 | I127, | |
| 533 | I128, | |
| 534 | I129, | |
| 535 | I130, | |
| 536 | I131, | |
| 537 | I132, | |
| 538 | I133, | |
| 539 | I134, | |
| 540 | I135, | |
| 541 | I136, | |
| 542 | I137, | |
| 543 | I138, | |
| 544 | I139, | |
| 545 | I140, | |
| 546 | I141, | |
| 547 | I142, | |
| 548 | I143, | |
| 549 | I144, | |
| 550 | I145, | |
| 551 | I146, | |
| 552 | I147, | |
| 553 | I148, | |
| 554 | I149, | |
| 555 | I150, | |
| 556 | I151, | |
| 557 | I152, | |
| 558 | I153, | |
| 559 | I154, | |
| 560 | I155, | |
| 561 | I156, | |
| 562 | I157, | |
| 563 | I158, | |
| 564 | I159, | |
| 565 | I160, | |
| 566 | I161, | |
| 567 | I162, | |
| 568 | I163, | |
| 569 | I164, | |
| 570 | I165, | |
| 571 | I166, | |
| 572 | I167, | |
| 573 | I168, | |
| 574 | I169, | |
| 575 | I170, | |
| 576 | I171, | |
| 577 | I172, | |
| 578 | I173, | |
| 579 | I174, | |
| 580 | I175, | |
| 581 | I176, | |
| 582 | I177, | |
| 583 | I178, | |
| 584 | I179, | |
| 585 | I180, | |
| 586 | I181, | |
| 587 | I182, | |
| 588 | I183, | |
| 589 | I184, | |
| 590 | I185, | |
| 591 | I186, | |
| 592 | I187, | |
| 593 | I188, | |
| 594 | I189, | |
| 595 | I190, | |
| 596 | I191, | |
| 597 | I192, | |
| 598 | I193, | |
| 599 | I194, | |
| 600 | I195, | |
| 601 | I196, | |
| 602 | I197, | |
| 603 | I198, | |
| 604 | I199, | |
| 605 | I200, | |
| 606 | I201, | |
| 607 | I202, | |
| 608 | I203, | |
| 609 | I204, | |
| 610 | I205, | |
| 611 | I206, | |
| 612 | I207, | |
| 613 | I208, | |
| 614 | I209, | |
| 615 | I210, | |
| 616 | I211, | |
| 617 | I212, | |
| 618 | I213, | |
| 619 | I214, | |
| 620 | I215, | |
| 621 | I216, | |
| 622 | I217, | |
| 623 | I218, | |
| 624 | I219, | |
| 625 | I220, | |
| 626 | I221, | |
| 627 | I222, | |
| 628 | I223, | |
| 629 | I224, | |
| 630 | I225, | |
| 631 | I226, | |
| 632 | I227, | |
| 633 | I228, | |
| 634 | I229, | |
| 635 | I230, | |
| 636 | I231, | |
| 637 | I232, | |
| 638 | I233, | |
| 639 | I234, | |
| 640 | I235, | |
| 641 | I236, | |
| 642 | I237, | |
| 643 | I238, | |
| 644 | I239, | |
| 645 | I240, | |
| 646 | I241, | |
| 647 | I242, | |
| 648 | I243, | |
| 649 | I244, | |
| 650 | I245, | |
| 651 | I246, | |
| 652 | I247, | |
| 653 | I248, | |
| 654 | I249, | |
| 655 | I250, | |
| 656 | I251, | |
| 657 | I252, | |
| 658 | I253, | |
| 659 | I254, | |
| 660 | I255, | |
| 661 | I256, | |
| 662 | }; | |
| 663 | ||
| 664 | test "enum sizes" { | |
| 665 | comptime { | |
| 666 | assert(@sizeOf(ValueCount1) == 0); | |
| 667 | assert(@sizeOf(ValueCount2) == 1); | |
| 668 | assert(@sizeOf(ValueCount256) == 1); | |
| 669 | assert(@sizeOf(ValueCount257) == 2); | |
| 670 | } | |
| 671 | } | |
| 672 | ||
| 673 | const Small2 = enum(u2) { | |
| 674 | One, | |
| 675 | Two, | |
| 676 | }; | |
| 677 | const Small = enum(u2) { | |
| 678 | One, | |
| 679 | Two, | |
| 680 | Three, | |
| 681 | Four, | |
| 682 | }; | |
| 683 | ||
| 684 | test "set enum tag type" { | |
| 685 | { | |
| 686 | var x = Small.One; | |
| 687 | x = Small.Two; | |
| 688 | comptime assert(@TagType(Small) == u2); | |
| 689 | } | |
| 690 | { | |
| 691 | var x = Small2.One; | |
| 692 | x = Small2.Two; | |
| 693 | comptime assert(@TagType(Small2) == u2); | |
| 694 | } | |
| 695 | } | |
| 696 | ||
| 697 | const A = enum(u3) { | |
| 698 | One, | |
| 699 | Two, | |
| 700 | Three, | |
| 701 | Four, | |
| 702 | One2, | |
| 703 | Two2, | |
| 704 | Three2, | |
| 705 | Four2, | |
| 706 | }; | |
| 707 | ||
| 708 | const B = enum(u3) { | |
| 709 | One3, | |
| 710 | Two3, | |
| 711 | Three3, | |
| 712 | Four3, | |
| 713 | One23, | |
| 714 | Two23, | |
| 715 | Three23, | |
| 716 | Four23, | |
| 717 | }; | |
| 718 | ||
| 719 | const C = enum(u2) { | |
| 720 | One4, | |
| 721 | Two4, | |
| 722 | Three4, | |
| 723 | Four4, | |
| 724 | }; | |
| 725 | ||
| 726 | const BitFieldOfEnums = packed struct { | |
| 727 | a: A, | |
| 728 | b: B, | |
| 729 | c: C, | |
| 730 | }; | |
| 731 | ||
| 732 | const bit_field_1 = BitFieldOfEnums{ | |
| 733 | .a = A.Two, | |
| 734 | .b = B.Three3, | |
| 735 | .c = C.Four4, | |
| 736 | }; | |
| 737 | ||
| 738 | test "bit field access with enum fields" { | |
| 739 | var data = bit_field_1; | |
| 740 | assert(getA(&data) == A.Two); | |
| 741 | assert(getB(&data) == B.Three3); | |
| 742 | assert(getC(&data) == C.Four4); | |
| 743 | comptime assert(@sizeOf(BitFieldOfEnums) == 1); | |
| 744 | ||
| 745 | data.b = B.Four3; | |
| 746 | assert(data.b == B.Four3); | |
| 747 | ||
| 748 | data.a = A.Three; | |
| 749 | assert(data.a == A.Three); | |
| 750 | assert(data.b == B.Four3); | |
| 751 | } | |
| 752 | ||
| 753 | fn getA(data: *const BitFieldOfEnums) A { | |
| 754 | return data.a; | |
| 755 | } | |
| 756 | ||
| 757 | fn getB(data: *const BitFieldOfEnums) B { | |
| 758 | return data.b; | |
| 759 | } | |
| 760 | ||
| 761 | fn getC(data: *const BitFieldOfEnums) C { | |
| 762 | return data.c; | |
| 763 | } | |
| 764 | ||
| 765 | test "casting enum to its tag type" { | |
| 766 | testCastEnumToTagType(Small2.Two); | |
| 767 | comptime testCastEnumToTagType(Small2.Two); | |
| 768 | } | |
| 769 | ||
| 770 | fn testCastEnumToTagType(value: Small2) void { | |
| 771 | assert(@enumToInt(value) == 1); | |
| 772 | } | |
| 773 | ||
| 774 | const MultipleChoice = enum(u32) { | |
| 775 | A = 20, | |
| 776 | B = 40, | |
| 777 | C = 60, | |
| 778 | D = 1000, | |
| 779 | }; | |
| 780 | ||
| 781 | test "enum with specified tag values" { | |
| 782 | testEnumWithSpecifiedTagValues(MultipleChoice.C); | |
| 783 | comptime testEnumWithSpecifiedTagValues(MultipleChoice.C); | |
| 784 | } | |
| 785 | ||
| 786 | fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void { | |
| 787 | assert(@enumToInt(x) == 60); | |
| 788 | assert(1234 == switch (x) { | |
| 789 | MultipleChoice.A => 1, | |
| 790 | MultipleChoice.B => 2, | |
| 791 | MultipleChoice.C => u32(1234), | |
| 792 | MultipleChoice.D => 4, | |
| 793 | }); | |
| 794 | } | |
| 795 | ||
| 796 | const MultipleChoice2 = enum(u32) { | |
| 797 | Unspecified1, | |
| 798 | A = 20, | |
| 799 | Unspecified2, | |
| 800 | B = 40, | |
| 801 | Unspecified3, | |
| 802 | C = 60, | |
| 803 | Unspecified4, | |
| 804 | D = 1000, | |
| 805 | Unspecified5, | |
| 806 | }; | |
| 807 | ||
| 808 | test "enum with specified and unspecified tag values" { | |
| 809 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | |
| 810 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | |
| 811 | } | |
| 812 | ||
| 813 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { | |
| 814 | assert(@enumToInt(x) == 1000); | |
| 815 | assert(1234 == switch (x) { | |
| 816 | MultipleChoice2.A => 1, | |
| 817 | MultipleChoice2.B => 2, | |
| 818 | MultipleChoice2.C => 3, | |
| 819 | MultipleChoice2.D => u32(1234), | |
| 820 | MultipleChoice2.Unspecified1 => 5, | |
| 821 | MultipleChoice2.Unspecified2 => 6, | |
| 822 | MultipleChoice2.Unspecified3 => 7, | |
| 823 | MultipleChoice2.Unspecified4 => 8, | |
| 824 | MultipleChoice2.Unspecified5 => 9, | |
| 825 | }); | |
| 826 | } | |
| 827 | ||
| 828 | test "cast integer literal to enum" { | |
| 829 | assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1); | |
| 830 | assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B); | |
| 831 | } | |
| 832 | ||
| 833 | const EnumWithOneMember = enum { | |
| 834 | Eof, | |
| 835 | }; | |
| 836 | ||
| 837 | fn doALoopThing(id: EnumWithOneMember) void { | |
| 838 | while (true) { | |
| 839 | if (id == EnumWithOneMember.Eof) { | |
| 840 | break; | |
| 841 | } | |
| 842 | @compileError("above if condition should be comptime"); | |
| 843 | } | |
| 844 | } | |
| 845 | ||
| 846 | test "comparison operator on enum with one member is comptime known" { | |
| 847 | doALoopThing(EnumWithOneMember.Eof); | |
| 848 | } | |
| 849 | ||
| 850 | const State = enum { | |
| 851 | Start, | |
| 852 | }; | |
| 853 | test "switch on enum with one member is comptime known" { | |
| 854 | var state = State.Start; | |
| 855 | switch (state) { | |
| 856 | State.Start => return, | |
| 857 | } | |
| 858 | @compileError("analysis should not reach here"); | |
| 859 | } | |
| 860 | ||
| 861 | const EnumWithTagValues = enum(u4) { | |
| 862 | A = 1 << 0, | |
| 863 | B = 1 << 1, | |
| 864 | C = 1 << 2, | |
| 865 | D = 1 << 3, | |
| 866 | }; | |
| 867 | test "enum with tag values don't require parens" { | |
| 868 | assert(@enumToInt(EnumWithTagValues.C) == 0b0100); | |
| 869 | } | |
| 870 | ||
| 871 | test "enum with 1 field but explicit tag type should still have the tag type" { | |
| 872 | const Enum = enum(u8) { | |
| 873 | B = 2, | |
| 874 | }; | |
| 875 | comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8)); | |
| 876 | } | |
| 877 | ||
| 878 | test "empty extern enum with members" { | |
| 879 | const E = extern enum { | |
| 880 | A, | |
| 881 | B, | |
| 882 | C, | |
| 883 | }; | |
| 884 | assert(@sizeOf(E) == @sizeOf(c_int)); | |
| 885 | } | |
| 886 | ||
| 887 | test "aoeu" { | |
| 888 | const LocalFoo = enum { | |
| 889 | A = 1, | |
| 890 | B = 0, | |
| 891 | }; | |
| 892 | var b = LocalFoo.B; | |
| 893 | assert(mem.eql(u8, @tagName(b), "B")); | |
| 894 | } |
test/cases/enum_with_members.zig deleted-27| ... | ... | @@ -1,27 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | const mem = @import("std").mem; | |
| 3 | const fmt = @import("std").fmt; | |
| 4 | ||
| 5 | const ET = union(enum) { | |
| 6 | SINT: i32, | |
| 7 | UINT: u32, | |
| 8 | ||
| 9 | pub fn print(a: *const ET, buf: []u8) anyerror!usize { | |
| 10 | return switch (a.*) { | |
| 11 | ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), | |
| 12 | ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), | |
| 13 | }; | |
| 14 | } | |
| 15 | }; | |
| 16 | ||
| 17 | test "enum with members" { | |
| 18 | const a = ET{ .SINT = -42 }; | |
| 19 | const b = ET{ .UINT = 42 }; | |
| 20 | var buf: [20]u8 = undefined; | |
| 21 | ||
| 22 | assert((a.print(buf[0..]) catch unreachable) == 3); | |
| 23 | assert(mem.eql(u8, buf[0..3], "-42")); | |
| 24 | ||
| 25 | assert((b.print(buf[0..]) catch unreachable) == 2); | |
| 26 | assert(mem.eql(u8, buf[0..2], "42")); | |
| 27 | } |
test/cases/error.zig deleted-245| ... | ... | @@ -1,245 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const mem = std.mem; | |
| 4 | const builtin = @import("builtin"); | |
| 5 | ||
| 6 | pub fn foo() anyerror!i32 { | |
| 7 | const x = try bar(); | |
| 8 | return x + 1; | |
| 9 | } | |
| 10 | ||
| 11 | pub fn bar() anyerror!i32 { | |
| 12 | return 13; | |
| 13 | } | |
| 14 | ||
| 15 | pub fn baz() anyerror!i32 { | |
| 16 | const y = foo() catch 1234; | |
| 17 | return y + 1; | |
| 18 | } | |
| 19 | ||
| 20 | test "error wrapping" { | |
| 21 | assert((baz() catch unreachable) == 15); | |
| 22 | } | |
| 23 | ||
| 24 | fn gimmeItBroke() []const u8 { | |
| 25 | return @errorName(error.ItBroke); | |
| 26 | } | |
| 27 | ||
| 28 | test "@errorName" { | |
| 29 | assert(mem.eql(u8, @errorName(error.AnError), "AnError")); | |
| 30 | assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); | |
| 31 | } | |
| 32 | ||
| 33 | test "error values" { | |
| 34 | const a = @errorToInt(error.err1); | |
| 35 | const b = @errorToInt(error.err2); | |
| 36 | assert(a != b); | |
| 37 | } | |
| 38 | ||
| 39 | test "redefinition of error values allowed" { | |
| 40 | shouldBeNotEqual(error.AnError, error.SecondError); | |
| 41 | } | |
| 42 | fn shouldBeNotEqual(a: anyerror, b: anyerror) void { | |
| 43 | if (a == b) unreachable; | |
| 44 | } | |
| 45 | ||
| 46 | test "error binary operator" { | |
| 47 | const a = errBinaryOperatorG(true) catch 3; | |
| 48 | const b = errBinaryOperatorG(false) catch 3; | |
| 49 | assert(a == 3); | |
| 50 | assert(b == 10); | |
| 51 | } | |
| 52 | fn errBinaryOperatorG(x: bool) anyerror!isize { | |
| 53 | return if (x) error.ItBroke else isize(10); | |
| 54 | } | |
| 55 | ||
| 56 | test "unwrap simple value from error" { | |
| 57 | const i = unwrapSimpleValueFromErrorDo() catch unreachable; | |
| 58 | assert(i == 13); | |
| 59 | } | |
| 60 | fn unwrapSimpleValueFromErrorDo() anyerror!isize { | |
| 61 | return 13; | |
| 62 | } | |
| 63 | ||
| 64 | test "error return in assignment" { | |
| 65 | doErrReturnInAssignment() catch unreachable; | |
| 66 | } | |
| 67 | ||
| 68 | fn doErrReturnInAssignment() anyerror!void { | |
| 69 | var x: i32 = undefined; | |
| 70 | x = try makeANonErr(); | |
| 71 | } | |
| 72 | ||
| 73 | fn makeANonErr() anyerror!i32 { | |
| 74 | return 1; | |
| 75 | } | |
| 76 | ||
| 77 | test "error union type " { | |
| 78 | testErrorUnionType(); | |
| 79 | comptime testErrorUnionType(); | |
| 80 | } | |
| 81 | ||
| 82 | fn testErrorUnionType() void { | |
| 83 | const x: anyerror!i32 = 1234; | |
| 84 | if (x) |value| assert(value == 1234) else |_| unreachable; | |
| 85 | assert(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion); | |
| 86 | assert(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet); | |
| 87 | assert(@typeOf(x).ErrorSet == anyerror); | |
| 88 | } | |
| 89 | ||
| 90 | test "error set type " { | |
| 91 | testErrorSetType(); | |
| 92 | comptime testErrorSetType(); | |
| 93 | } | |
| 94 | ||
| 95 | const MyErrSet = error{ | |
| 96 | OutOfMemory, | |
| 97 | FileNotFound, | |
| 98 | }; | |
| 99 | ||
| 100 | fn testErrorSetType() void { | |
| 101 | assert(@memberCount(MyErrSet) == 2); | |
| 102 | ||
| 103 | const a: MyErrSet!i32 = 5678; | |
| 104 | const b: MyErrSet!i32 = MyErrSet.OutOfMemory; | |
| 105 | ||
| 106 | if (a) |value| assert(value == 5678) else |err| switch (err) { | |
| 107 | error.OutOfMemory => unreachable, | |
| 108 | error.FileNotFound => unreachable, | |
| 109 | } | |
| 110 | } | |
| 111 | ||
| 112 | test "explicit error set cast" { | |
| 113 | testExplicitErrorSetCast(Set1.A); | |
| 114 | comptime testExplicitErrorSetCast(Set1.A); | |
| 115 | } | |
| 116 | ||
| 117 | const Set1 = error{ | |
| 118 | A, | |
| 119 | B, | |
| 120 | }; | |
| 121 | const Set2 = error{ | |
| 122 | A, | |
| 123 | C, | |
| 124 | }; | |
| 125 | ||
| 126 | fn testExplicitErrorSetCast(set1: Set1) void { | |
| 127 | var x = @errSetCast(Set2, set1); | |
| 128 | var y = @errSetCast(Set1, x); | |
| 129 | assert(y == error.A); | |
| 130 | } | |
| 131 | ||
| 132 | test "comptime test error for empty error set" { | |
| 133 | testComptimeTestErrorEmptySet(1234); | |
| 134 | comptime testComptimeTestErrorEmptySet(1234); | |
| 135 | } | |
| 136 | ||
| 137 | const EmptyErrorSet = error{}; | |
| 138 | ||
| 139 | fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void { | |
| 140 | if (x) |v| assert(v == 1234) else |err| @compileError("bad"); | |
| 141 | } | |
| 142 | ||
| 143 | test "syntax: optional operator in front of error union operator" { | |
| 144 | comptime { | |
| 145 | assert(?(anyerror!i32) == ?(anyerror!i32)); | |
| 146 | } | |
| 147 | } | |
| 148 | ||
| 149 | test "comptime err to int of error set with only 1 possible value" { | |
| 150 | testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A)); | |
| 151 | comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A)); | |
| 152 | } | |
| 153 | fn testErrToIntWithOnePossibleValue( | |
| 154 | x: error{A}, | |
| 155 | comptime value: u32, | |
| 156 | ) void { | |
| 157 | if (@errorToInt(x) != value) { | |
| 158 | @compileError("bad"); | |
| 159 | } | |
| 160 | } | |
| 161 | ||
| 162 | test "error union peer type resolution" { | |
| 163 | testErrorUnionPeerTypeResolution(1); | |
| 164 | comptime testErrorUnionPeerTypeResolution(1); | |
| 165 | } | |
| 166 | ||
| 167 | fn testErrorUnionPeerTypeResolution(x: i32) void { | |
| 168 | const y = switch (x) { | |
| 169 | 1 => bar_1(), | |
| 170 | 2 => baz_1(), | |
| 171 | else => quux_1(), | |
| 172 | }; | |
| 173 | } | |
| 174 | ||
| 175 | fn bar_1() anyerror { | |
| 176 | return error.A; | |
| 177 | } | |
| 178 | ||
| 179 | fn baz_1() !i32 { | |
| 180 | return error.B; | |
| 181 | } | |
| 182 | ||
| 183 | fn quux_1() !i32 { | |
| 184 | return error.C; | |
| 185 | } | |
| 186 | ||
| 187 | test "error: fn returning empty error set can be passed as fn returning any error" { | |
| 188 | entry(); | |
| 189 | comptime entry(); | |
| 190 | } | |
| 191 | ||
| 192 | fn entry() void { | |
| 193 | foo2(bar2); | |
| 194 | } | |
| 195 | ||
| 196 | fn foo2(f: fn () anyerror!void) void { | |
| 197 | const x = f(); | |
| 198 | } | |
| 199 | ||
| 200 | fn bar2() (error{}!void) {} | |
| 201 | ||
| 202 | test "error: Zero sized error set returned with value payload crash" { | |
| 203 | _ = foo3(0); | |
| 204 | _ = comptime foo3(0); | |
| 205 | } | |
| 206 | ||
| 207 | const Error = error{}; | |
| 208 | fn foo3(b: usize) Error!usize { | |
| 209 | return b; | |
| 210 | } | |
| 211 | ||
| 212 | test "error: Infer error set from literals" { | |
| 213 | _ = nullLiteral("n") catch |err| handleErrors(err); | |
| 214 | _ = floatLiteral("n") catch |err| handleErrors(err); | |
| 215 | _ = intLiteral("n") catch |err| handleErrors(err); | |
| 216 | _ = comptime nullLiteral("n") catch |err| handleErrors(err); | |
| 217 | _ = comptime floatLiteral("n") catch |err| handleErrors(err); | |
| 218 | _ = comptime intLiteral("n") catch |err| handleErrors(err); | |
| 219 | } | |
| 220 | ||
| 221 | fn handleErrors(err: var) noreturn { | |
| 222 | switch (err) { | |
| 223 | error.T => {}, | |
| 224 | } | |
| 225 | ||
| 226 | unreachable; | |
| 227 | } | |
| 228 | ||
| 229 | fn nullLiteral(str: []const u8) !?i64 { | |
| 230 | if (str[0] == 'n') return null; | |
| 231 | ||
| 232 | return error.T; | |
| 233 | } | |
| 234 | ||
| 235 | fn floatLiteral(str: []const u8) !?f64 { | |
| 236 | if (str[0] == 'n') return 1.0; | |
| 237 | ||
| 238 | return error.T; | |
| 239 | } | |
| 240 | ||
| 241 | fn intLiteral(str: []const u8) !?i64 { | |
| 242 | if (str[0] == 'n') return 1; | |
| 243 | ||
| 244 | return error.T; | |
| 245 | } |
test/cases/eval.zig deleted-782| ... | ... | @@ -1,782 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | ||
| 5 | test "compile time recursion" { | |
| 6 | assert(some_data.len == 21); | |
| 7 | } | |
| 8 | var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined; | |
| 9 | fn fibonacci(x: i32) i32 { | |
| 10 | if (x <= 1) return 1; | |
| 11 | return fibonacci(x - 1) + fibonacci(x - 2); | |
| 12 | } | |
| 13 | ||
| 14 | fn unwrapAndAddOne(blah: ?i32) i32 { | |
| 15 | return blah.? + 1; | |
| 16 | } | |
| 17 | const should_be_1235 = unwrapAndAddOne(1234); | |
| 18 | test "static add one" { | |
| 19 | assert(should_be_1235 == 1235); | |
| 20 | } | |
| 21 | ||
| 22 | test "inlined loop" { | |
| 23 | comptime var i = 0; | |
| 24 | comptime var sum = 0; | |
| 25 | inline while (i <= 5) : (i += 1) | |
| 26 | sum += i; | |
| 27 | assert(sum == 15); | |
| 28 | } | |
| 29 | ||
| 30 | fn gimme1or2(comptime a: bool) i32 { | |
| 31 | const x: i32 = 1; | |
| 32 | const y: i32 = 2; | |
| 33 | comptime var z: i32 = if (a) x else y; | |
| 34 | return z; | |
| 35 | } | |
| 36 | test "inline variable gets result of const if" { | |
| 37 | assert(gimme1or2(true) == 1); | |
| 38 | assert(gimme1or2(false) == 2); | |
| 39 | } | |
| 40 | ||
| 41 | test "static function evaluation" { | |
| 42 | assert(statically_added_number == 3); | |
| 43 | } | |
| 44 | const statically_added_number = staticAdd(1, 2); | |
| 45 | fn staticAdd(a: i32, b: i32) i32 { | |
| 46 | return a + b; | |
| 47 | } | |
| 48 | ||
| 49 | test "const expr eval on single expr blocks" { | |
| 50 | assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3); | |
| 51 | } | |
| 52 | ||
| 53 | fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { | |
| 54 | const literal = 3; | |
| 55 | ||
| 56 | const result = if (b) b: { | |
| 57 | break :b literal; | |
| 58 | } else b: { | |
| 59 | break :b x; | |
| 60 | }; | |
| 61 | ||
| 62 | return result; | |
| 63 | } | |
| 64 | ||
| 65 | test "statically initialized list" { | |
| 66 | assert(static_point_list[0].x == 1); | |
| 67 | assert(static_point_list[0].y == 2); | |
| 68 | assert(static_point_list[1].x == 3); | |
| 69 | assert(static_point_list[1].y == 4); | |
| 70 | } | |
| 71 | const Point = struct { | |
| 72 | x: i32, | |
| 73 | y: i32, | |
| 74 | }; | |
| 75 | const static_point_list = []Point{ | |
| 76 | makePoint(1, 2), | |
| 77 | makePoint(3, 4), | |
| 78 | }; | |
| 79 | fn makePoint(x: i32, y: i32) Point { | |
| 80 | return Point{ | |
| 81 | .x = x, | |
| 82 | .y = y, | |
| 83 | }; | |
| 84 | } | |
| 85 | ||
| 86 | test "static eval list init" { | |
| 87 | assert(static_vec3.data[2] == 1.0); | |
| 88 | assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0); | |
| 89 | } | |
| 90 | const static_vec3 = vec3(0.0, 0.0, 1.0); | |
| 91 | pub const Vec3 = struct { | |
| 92 | data: [3]f32, | |
| 93 | }; | |
| 94 | pub fn vec3(x: f32, y: f32, z: f32) Vec3 { | |
| 95 | return Vec3{ .data = []f32{ | |
| 96 | x, | |
| 97 | y, | |
| 98 | z, | |
| 99 | } }; | |
| 100 | } | |
| 101 | ||
| 102 | test "constant expressions" { | |
| 103 | var array: [array_size]u8 = undefined; | |
| 104 | assert(@sizeOf(@typeOf(array)) == 20); | |
| 105 | } | |
| 106 | const array_size: u8 = 20; | |
| 107 | ||
| 108 | test "constant struct with negation" { | |
| 109 | assert(vertices[0].x == -0.6); | |
| 110 | } | |
| 111 | const Vertex = struct { | |
| 112 | x: f32, | |
| 113 | y: f32, | |
| 114 | r: f32, | |
| 115 | g: f32, | |
| 116 | b: f32, | |
| 117 | }; | |
| 118 | const vertices = []Vertex{ | |
| 119 | Vertex{ | |
| 120 | .x = -0.6, | |
| 121 | .y = -0.4, | |
| 122 | .r = 1.0, | |
| 123 | .g = 0.0, | |
| 124 | .b = 0.0, | |
| 125 | }, | |
| 126 | Vertex{ | |
| 127 | .x = 0.6, | |
| 128 | .y = -0.4, | |
| 129 | .r = 0.0, | |
| 130 | .g = 1.0, | |
| 131 | .b = 0.0, | |
| 132 | }, | |
| 133 | Vertex{ | |
| 134 | .x = 0.0, | |
| 135 | .y = 0.6, | |
| 136 | .r = 0.0, | |
| 137 | .g = 0.0, | |
| 138 | .b = 1.0, | |
| 139 | }, | |
| 140 | }; | |
| 141 | ||
| 142 | test "statically initialized struct" { | |
| 143 | st_init_str_foo.x += 1; | |
| 144 | assert(st_init_str_foo.x == 14); | |
| 145 | } | |
| 146 | const StInitStrFoo = struct { | |
| 147 | x: i32, | |
| 148 | y: bool, | |
| 149 | }; | |
| 150 | var st_init_str_foo = StInitStrFoo{ | |
| 151 | .x = 13, | |
| 152 | .y = true, | |
| 153 | }; | |
| 154 | ||
| 155 | test "statically initalized array literal" { | |
| 156 | const y: [4]u8 = st_init_arr_lit_x; | |
| 157 | assert(y[3] == 4); | |
| 158 | } | |
| 159 | const st_init_arr_lit_x = []u8{ | |
| 160 | 1, | |
| 161 | 2, | |
| 162 | 3, | |
| 163 | 4, | |
| 164 | }; | |
| 165 | ||
| 166 | test "const slice" { | |
| 167 | comptime { | |
| 168 | const a = "1234567890"; | |
| 169 | assert(a.len == 10); | |
| 170 | const b = a[1..2]; | |
| 171 | assert(b.len == 1); | |
| 172 | assert(b[0] == '2'); | |
| 173 | } | |
| 174 | } | |
| 175 | ||
| 176 | test "try to trick eval with runtime if" { | |
| 177 | assert(testTryToTrickEvalWithRuntimeIf(true) == 10); | |
| 178 | } | |
| 179 | ||
| 180 | fn testTryToTrickEvalWithRuntimeIf(b: bool) usize { | |
| 181 | comptime var i: usize = 0; | |
| 182 | inline while (i < 10) : (i += 1) { | |
| 183 | const result = if (b) false else true; | |
| 184 | } | |
| 185 | comptime { | |
| 186 | return i; | |
| 187 | } | |
| 188 | } | |
| 189 | ||
| 190 | fn max(comptime T: type, a: T, b: T) T { | |
| 191 | if (T == bool) { | |
| 192 | return a or b; | |
| 193 | } else if (a > b) { | |
| 194 | return a; | |
| 195 | } else { | |
| 196 | return b; | |
| 197 | } | |
| 198 | } | |
| 199 | fn letsTryToCompareBools(a: bool, b: bool) bool { | |
| 200 | return max(bool, a, b); | |
| 201 | } | |
| 202 | test "inlined block and runtime block phi" { | |
| 203 | assert(letsTryToCompareBools(true, true)); | |
| 204 | assert(letsTryToCompareBools(true, false)); | |
| 205 | assert(letsTryToCompareBools(false, true)); | |
| 206 | assert(!letsTryToCompareBools(false, false)); | |
| 207 | ||
| 208 | comptime { | |
| 209 | assert(letsTryToCompareBools(true, true)); | |
| 210 | assert(letsTryToCompareBools(true, false)); | |
| 211 | assert(letsTryToCompareBools(false, true)); | |
| 212 | assert(!letsTryToCompareBools(false, false)); | |
| 213 | } | |
| 214 | } | |
| 215 | ||
| 216 | const CmdFn = struct { | |
| 217 | name: []const u8, | |
| 218 | func: fn (i32) i32, | |
| 219 | }; | |
| 220 | ||
| 221 | const cmd_fns = []CmdFn{ | |
| 222 | CmdFn{ | |
| 223 | .name = "one", | |
| 224 | .func = one, | |
| 225 | }, | |
| 226 | CmdFn{ | |
| 227 | .name = "two", | |
| 228 | .func = two, | |
| 229 | }, | |
| 230 | CmdFn{ | |
| 231 | .name = "three", | |
| 232 | .func = three, | |
| 233 | }, | |
| 234 | }; | |
| 235 | fn one(value: i32) i32 { | |
| 236 | return value + 1; | |
| 237 | } | |
| 238 | fn two(value: i32) i32 { | |
| 239 | return value + 2; | |
| 240 | } | |
| 241 | fn three(value: i32) i32 { | |
| 242 | return value + 3; | |
| 243 | } | |
| 244 | ||
| 245 | fn performFn(comptime prefix_char: u8, start_value: i32) i32 { | |
| 246 | var result: i32 = start_value; | |
| 247 | comptime var i = 0; | |
| 248 | inline while (i < cmd_fns.len) : (i += 1) { | |
| 249 | if (cmd_fns[i].name[0] == prefix_char) { | |
| 250 | result = cmd_fns[i].func(result); | |
| 251 | } | |
| 252 | } | |
| 253 | return result; | |
| 254 | } | |
| 255 | ||
| 256 | test "comptime iterate over fn ptr list" { | |
| 257 | assert(performFn('t', 1) == 6); | |
| 258 | assert(performFn('o', 0) == 1); | |
| 259 | assert(performFn('w', 99) == 99); | |
| 260 | } | |
| 261 | ||
| 262 | test "eval @setRuntimeSafety at compile-time" { | |
| 263 | const result = comptime fnWithSetRuntimeSafety(); | |
| 264 | assert(result == 1234); | |
| 265 | } | |
| 266 | ||
| 267 | fn fnWithSetRuntimeSafety() i32 { | |
| 268 | @setRuntimeSafety(true); | |
| 269 | return 1234; | |
| 270 | } | |
| 271 | ||
| 272 | test "eval @setFloatMode at compile-time" { | |
| 273 | const result = comptime fnWithFloatMode(); | |
| 274 | assert(result == 1234.0); | |
| 275 | } | |
| 276 | ||
| 277 | fn fnWithFloatMode() f32 { | |
| 278 | @setFloatMode(builtin.FloatMode.Strict); | |
| 279 | return 1234.0; | |
| 280 | } | |
| 281 | ||
| 282 | const SimpleStruct = struct { | |
| 283 | field: i32, | |
| 284 | ||
| 285 | fn method(self: *const SimpleStruct) i32 { | |
| 286 | return self.field + 3; | |
| 287 | } | |
| 288 | }; | |
| 289 | ||
| 290 | var simple_struct = SimpleStruct{ .field = 1234 }; | |
| 291 | ||
| 292 | const bound_fn = simple_struct.method; | |
| 293 | ||
| 294 | test "call method on bound fn referring to var instance" { | |
| 295 | assert(bound_fn() == 1237); | |
| 296 | } | |
| 297 | ||
| 298 | test "ptr to local array argument at comptime" { | |
| 299 | comptime { | |
| 300 | var bytes: [10]u8 = undefined; | |
| 301 | modifySomeBytes(bytes[0..]); | |
| 302 | assert(bytes[0] == 'a'); | |
| 303 | assert(bytes[9] == 'b'); | |
| 304 | } | |
| 305 | } | |
| 306 | ||
| 307 | fn modifySomeBytes(bytes: []u8) void { | |
| 308 | bytes[0] = 'a'; | |
| 309 | bytes[9] = 'b'; | |
| 310 | } | |
| 311 | ||
| 312 | test "comparisons 0 <= uint and 0 > uint should be comptime" { | |
| 313 | testCompTimeUIntComparisons(1234); | |
| 314 | } | |
| 315 | fn testCompTimeUIntComparisons(x: u32) void { | |
| 316 | if (!(0 <= x)) { | |
| 317 | @compileError("this condition should be comptime known"); | |
| 318 | } | |
| 319 | if (0 > x) { | |
| 320 | @compileError("this condition should be comptime known"); | |
| 321 | } | |
| 322 | if (!(x >= 0)) { | |
| 323 | @compileError("this condition should be comptime known"); | |
| 324 | } | |
| 325 | if (x < 0) { | |
| 326 | @compileError("this condition should be comptime known"); | |
| 327 | } | |
| 328 | } | |
| 329 | ||
| 330 | test "const ptr to variable data changes at runtime" { | |
| 331 | assert(foo_ref.name[0] == 'a'); | |
| 332 | foo_ref.name = "b"; | |
| 333 | assert(foo_ref.name[0] == 'b'); | |
| 334 | } | |
| 335 | ||
| 336 | const Foo = struct { | |
| 337 | name: []const u8, | |
| 338 | }; | |
| 339 | ||
| 340 | var foo_contents = Foo{ .name = "a" }; | |
| 341 | const foo_ref = &foo_contents; | |
| 342 | ||
| 343 | test "create global array with for loop" { | |
| 344 | assert(global_array[5] == 5 * 5); | |
| 345 | assert(global_array[9] == 9 * 9); | |
| 346 | } | |
| 347 | ||
| 348 | const global_array = x: { | |
| 349 | var result: [10]usize = undefined; | |
| 350 | for (result) |*item, index| { | |
| 351 | item.* = index * index; | |
| 352 | } | |
| 353 | break :x result; | |
| 354 | }; | |
| 355 | ||
| 356 | test "compile-time downcast when the bits fit" { | |
| 357 | comptime { | |
| 358 | const spartan_count: u16 = 255; | |
| 359 | const byte = @intCast(u8, spartan_count); | |
| 360 | assert(byte == 255); | |
| 361 | } | |
| 362 | } | |
| 363 | ||
| 364 | const hi1 = "hi"; | |
| 365 | const hi2 = hi1; | |
| 366 | test "const global shares pointer with other same one" { | |
| 367 | assertEqualPtrs(&hi1[0], &hi2[0]); | |
| 368 | comptime assert(&hi1[0] == &hi2[0]); | |
| 369 | } | |
| 370 | fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void { | |
| 371 | assert(ptr1 == ptr2); | |
| 372 | } | |
| 373 | ||
| 374 | test "@setEvalBranchQuota" { | |
| 375 | comptime { | |
| 376 | // 1001 for the loop and then 1 more for the assert fn call | |
| 377 | @setEvalBranchQuota(1002); | |
| 378 | var i = 0; | |
| 379 | var sum = 0; | |
| 380 | while (i < 1001) : (i += 1) { | |
| 381 | sum += i; | |
| 382 | } | |
| 383 | assert(sum == 500500); | |
| 384 | } | |
| 385 | } | |
| 386 | ||
| 387 | // TODO test "float literal at compile time not lossy" { | |
| 388 | // TODO assert(16777216.0 + 1.0 == 16777217.0); | |
| 389 | // TODO assert(9007199254740992.0 + 1.0 == 9007199254740993.0); | |
| 390 | // TODO } | |
| 391 | ||
| 392 | test "f32 at compile time is lossy" { | |
| 393 | assert(f32(1 << 24) + 1 == 1 << 24); | |
| 394 | } | |
| 395 | ||
| 396 | test "f64 at compile time is lossy" { | |
| 397 | assert(f64(1 << 53) + 1 == 1 << 53); | |
| 398 | } | |
| 399 | ||
| 400 | test "f128 at compile time is lossy" { | |
| 401 | assert(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); | |
| 402 | } | |
| 403 | ||
| 404 | // TODO need a better implementation of bigfloat_init_bigint | |
| 405 | // assert(f128(1 << 113) == 10384593717069655257060992658440192); | |
| 406 | ||
| 407 | pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { | |
| 408 | return struct { | |
| 409 | pub const Node = struct {}; | |
| 410 | }; | |
| 411 | } | |
| 412 | ||
| 413 | test "string literal used as comptime slice is memoized" { | |
| 414 | const a = "link"; | |
| 415 | const b = "link"; | |
| 416 | comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node); | |
| 417 | comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node); | |
| 418 | } | |
| 419 | ||
| 420 | test "comptime slice of undefined pointer of length 0" { | |
| 421 | const slice1 = ([*]i32)(undefined)[0..0]; | |
| 422 | assert(slice1.len == 0); | |
| 423 | const slice2 = ([*]i32)(undefined)[100..100]; | |
| 424 | assert(slice2.len == 0); | |
| 425 | } | |
| 426 | ||
| 427 | fn copyWithPartialInline(s: []u32, b: []u8) void { | |
| 428 | comptime var i: usize = 0; | |
| 429 | inline while (i < 4) : (i += 1) { | |
| 430 | s[i] = 0; | |
| 431 | s[i] |= u32(b[i * 4 + 0]) << 24; | |
| 432 | s[i] |= u32(b[i * 4 + 1]) << 16; | |
| 433 | s[i] |= u32(b[i * 4 + 2]) << 8; | |
| 434 | s[i] |= u32(b[i * 4 + 3]) << 0; | |
| 435 | } | |
| 436 | } | |
| 437 | ||
| 438 | test "binary math operator in partially inlined function" { | |
| 439 | var s: [4]u32 = undefined; | |
| 440 | var b: [16]u8 = undefined; | |
| 441 | ||
| 442 | for (b) |*r, i| | |
| 443 | r.* = @intCast(u8, i + 1); | |
| 444 | ||
| 445 | copyWithPartialInline(s[0..], b[0..]); | |
| 446 | assert(s[0] == 0x1020304); | |
| 447 | assert(s[1] == 0x5060708); | |
| 448 | assert(s[2] == 0x90a0b0c); | |
| 449 | assert(s[3] == 0xd0e0f10); | |
| 450 | } | |
| 451 | ||
| 452 | test "comptime function with the same args is memoized" { | |
| 453 | comptime { | |
| 454 | assert(MakeType(i32) == MakeType(i32)); | |
| 455 | assert(MakeType(i32) != MakeType(f64)); | |
| 456 | } | |
| 457 | } | |
| 458 | ||
| 459 | fn MakeType(comptime T: type) type { | |
| 460 | return struct { | |
| 461 | field: T, | |
| 462 | }; | |
| 463 | } | |
| 464 | ||
| 465 | test "comptime function with mutable pointer is not memoized" { | |
| 466 | comptime { | |
| 467 | var x: i32 = 1; | |
| 468 | const ptr = &x; | |
| 469 | increment(ptr); | |
| 470 | increment(ptr); | |
| 471 | assert(x == 3); | |
| 472 | } | |
| 473 | } | |
| 474 | ||
| 475 | fn increment(value: *i32) void { | |
| 476 | value.* += 1; | |
| 477 | } | |
| 478 | ||
| 479 | fn generateTable(comptime T: type) [1010]T { | |
| 480 | var res: [1010]T = undefined; | |
| 481 | var i: usize = 0; | |
| 482 | while (i < 1010) : (i += 1) { | |
| 483 | res[i] = @intCast(T, i); | |
| 484 | } | |
| 485 | return res; | |
| 486 | } | |
| 487 | ||
| 488 | fn doesAlotT(comptime T: type, value: usize) T { | |
| 489 | @setEvalBranchQuota(5000); | |
| 490 | const table = comptime blk: { | |
| 491 | break :blk generateTable(T); | |
| 492 | }; | |
| 493 | return table[value]; | |
| 494 | } | |
| 495 | ||
| 496 | test "@setEvalBranchQuota at same scope as generic function call" { | |
| 497 | assert(doesAlotT(u32, 2) == 2); | |
| 498 | } | |
| 499 | ||
| 500 | test "comptime slice of slice preserves comptime var" { | |
| 501 | comptime { | |
| 502 | var buff: [10]u8 = undefined; | |
| 503 | buff[0..][0..][0] = 1; | |
| 504 | assert(buff[0..][0..][0] == 1); | |
| 505 | } | |
| 506 | } | |
| 507 | ||
| 508 | test "comptime slice of pointer preserves comptime var" { | |
| 509 | comptime { | |
| 510 | var buff: [10]u8 = undefined; | |
| 511 | var a = buff[0..].ptr; | |
| 512 | a[0..1][0] = 1; | |
| 513 | assert(buff[0..][0..][0] == 1); | |
| 514 | } | |
| 515 | } | |
| 516 | ||
| 517 | const SingleFieldStruct = struct { | |
| 518 | x: i32, | |
| 519 | ||
| 520 | fn read_x(self: *const SingleFieldStruct) i32 { | |
| 521 | return self.x; | |
| 522 | } | |
| 523 | }; | |
| 524 | test "const ptr to comptime mutable data is not memoized" { | |
| 525 | comptime { | |
| 526 | var foo = SingleFieldStruct{ .x = 1 }; | |
| 527 | assert(foo.read_x() == 1); | |
| 528 | foo.x = 2; | |
| 529 | assert(foo.read_x() == 2); | |
| 530 | } | |
| 531 | } | |
| 532 | ||
| 533 | test "array concat of slices gives slice" { | |
| 534 | comptime { | |
| 535 | var a: []const u8 = "aoeu"; | |
| 536 | var b: []const u8 = "asdf"; | |
| 537 | const c = a ++ b; | |
| 538 | assert(std.mem.eql(u8, c, "aoeuasdf")); | |
| 539 | } | |
| 540 | } | |
| 541 | ||
| 542 | test "comptime shlWithOverflow" { | |
| 543 | const ct_shifted: u64 = comptime amt: { | |
| 544 | var amt = u64(0); | |
| 545 | _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); | |
| 546 | break :amt amt; | |
| 547 | }; | |
| 548 | ||
| 549 | const rt_shifted: u64 = amt: { | |
| 550 | var amt = u64(0); | |
| 551 | _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); | |
| 552 | break :amt amt; | |
| 553 | }; | |
| 554 | ||
| 555 | assert(ct_shifted == rt_shifted); | |
| 556 | } | |
| 557 | ||
| 558 | test "runtime 128 bit integer division" { | |
| 559 | var a: u128 = 152313999999999991610955792383; | |
| 560 | var b: u128 = 10000000000000000000; | |
| 561 | var c = a / b; | |
| 562 | assert(c == 15231399999); | |
| 563 | } | |
| 564 | ||
| 565 | pub const Info = struct { | |
| 566 | version: u8, | |
| 567 | }; | |
| 568 | ||
| 569 | pub const diamond_info = Info{ .version = 0 }; | |
| 570 | ||
| 571 | test "comptime modification of const struct field" { | |
| 572 | comptime { | |
| 573 | var res = diamond_info; | |
| 574 | res.version = 1; | |
| 575 | assert(diamond_info.version == 0); | |
| 576 | assert(res.version == 1); | |
| 577 | } | |
| 578 | } | |
| 579 | ||
| 580 | test "pointer to type" { | |
| 581 | comptime { | |
| 582 | var T: type = i32; | |
| 583 | assert(T == i32); | |
| 584 | var ptr = &T; | |
| 585 | assert(@typeOf(ptr) == *type); | |
| 586 | ptr.* = f32; | |
| 587 | assert(T == f32); | |
| 588 | assert(*T == *f32); | |
| 589 | } | |
| 590 | } | |
| 591 | ||
| 592 | test "slice of type" { | |
| 593 | comptime { | |
| 594 | var types_array = []type{ i32, f64, type }; | |
| 595 | for (types_array) |T, i| { | |
| 596 | switch (i) { | |
| 597 | 0 => assert(T == i32), | |
| 598 | 1 => assert(T == f64), | |
| 599 | 2 => assert(T == type), | |
| 600 | else => unreachable, | |
| 601 | } | |
| 602 | } | |
| 603 | for (types_array[0..]) |T, i| { | |
| 604 | switch (i) { | |
| 605 | 0 => assert(T == i32), | |
| 606 | 1 => assert(T == f64), | |
| 607 | 2 => assert(T == type), | |
| 608 | else => unreachable, | |
| 609 | } | |
| 610 | } | |
| 611 | } | |
| 612 | } | |
| 613 | ||
| 614 | const Wrapper = struct { | |
| 615 | T: type, | |
| 616 | }; | |
| 617 | ||
| 618 | fn wrap(comptime T: type) Wrapper { | |
| 619 | return Wrapper{ .T = T }; | |
| 620 | } | |
| 621 | ||
| 622 | test "function which returns struct with type field causes implicit comptime" { | |
| 623 | const ty = wrap(i32).T; | |
| 624 | assert(ty == i32); | |
| 625 | } | |
| 626 | ||
| 627 | test "call method with comptime pass-by-non-copying-value self parameter" { | |
| 628 | const S = struct { | |
| 629 | a: u8, | |
| 630 | ||
| 631 | fn b(comptime s: @This()) u8 { | |
| 632 | return s.a; | |
| 633 | } | |
| 634 | }; | |
| 635 | ||
| 636 | const s = S{ .a = 2 }; | |
| 637 | var b = s.b(); | |
| 638 | assert(b == 2); | |
| 639 | } | |
| 640 | ||
| 641 | test "@tagName of @typeId" { | |
| 642 | const str = @tagName(@typeId(u8)); | |
| 643 | assert(std.mem.eql(u8, str, "Int")); | |
| 644 | } | |
| 645 | ||
| 646 | test "setting backward branch quota just before a generic fn call" { | |
| 647 | @setEvalBranchQuota(1001); | |
| 648 | loopNTimes(1001); | |
| 649 | } | |
| 650 | ||
| 651 | fn loopNTimes(comptime n: usize) void { | |
| 652 | comptime var i = 0; | |
| 653 | inline while (i < n) : (i += 1) {} | |
| 654 | } | |
| 655 | ||
| 656 | test "variable inside inline loop that has different types on different iterations" { | |
| 657 | testVarInsideInlineLoop(true, u32(42)); | |
| 658 | } | |
| 659 | ||
| 660 | fn testVarInsideInlineLoop(args: ...) void { | |
| 661 | comptime var i = 0; | |
| 662 | inline while (i < args.len) : (i += 1) { | |
| 663 | const x = args[i]; | |
| 664 | if (i == 0) assert(x); | |
| 665 | if (i == 1) assert(x == 42); | |
| 666 | } | |
| 667 | } | |
| 668 | ||
| 669 | test "inline for with same type but different values" { | |
| 670 | var res: usize = 0; | |
| 671 | inline for ([]type{ [2]u8, [1]u8, [2]u8 }) |T| { | |
| 672 | var a: T = undefined; | |
| 673 | res += a.len; | |
| 674 | } | |
| 675 | assert(res == 5); | |
| 676 | } | |
| 677 | ||
| 678 | test "refer to the type of a generic function" { | |
| 679 | const Func = fn (type) void; | |
| 680 | const f: Func = doNothingWithType; | |
| 681 | f(i32); | |
| 682 | } | |
| 683 | ||
| 684 | fn doNothingWithType(comptime T: type) void {} | |
| 685 | ||
| 686 | test "zero extend from u0 to u1" { | |
| 687 | var zero_u0: u0 = 0; | |
| 688 | var zero_u1: u1 = zero_u0; | |
| 689 | assert(zero_u1 == 0); | |
| 690 | } | |
| 691 | ||
| 692 | test "bit shift a u1" { | |
| 693 | var x: u1 = 1; | |
| 694 | var y = x << 0; | |
| 695 | assert(y == 1); | |
| 696 | } | |
| 697 | ||
| 698 | test "@intCast to a u0" { | |
| 699 | var x: u8 = 0; | |
| 700 | var y: u0 = @intCast(u0, x); | |
| 701 | assert(y == 0); | |
| 702 | } | |
| 703 | ||
| 704 | test "@bytesToslice on a packed struct" { | |
| 705 | const F = packed struct { | |
| 706 | a: u8, | |
| 707 | }; | |
| 708 | ||
| 709 | var b = [1]u8{9}; | |
| 710 | var f = @bytesToSlice(F, b); | |
| 711 | assert(f[0].a == 9); | |
| 712 | } | |
| 713 | ||
| 714 | test "comptime pointer cast array and then slice" { | |
| 715 | const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; | |
| 716 | ||
| 717 | const ptrA: [*]const u8 = @ptrCast([*]const u8, &array); | |
| 718 | const sliceA: []const u8 = ptrA[0..2]; | |
| 719 | ||
| 720 | const ptrB: [*]const u8 = &array; | |
| 721 | const sliceB: []const u8 = ptrB[0..2]; | |
| 722 | ||
| 723 | assert(sliceA[1] == 2); | |
| 724 | assert(sliceB[1] == 2); | |
| 725 | } | |
| 726 | ||
| 727 | test "slice bounds in comptime concatenation" { | |
| 728 | const bs = comptime blk: { | |
| 729 | const b = c"11"; | |
| 730 | break :blk b[0..1]; | |
| 731 | }; | |
| 732 | const str = "" ++ bs; | |
| 733 | assert(str.len == 1); | |
| 734 | assert(std.mem.eql(u8, str, "1")); | |
| 735 | ||
| 736 | const str2 = bs ++ ""; | |
| 737 | assert(str2.len == 1); | |
| 738 | assert(std.mem.eql(u8, str2, "1")); | |
| 739 | } | |
| 740 | ||
| 741 | test "comptime bitwise operators" { | |
| 742 | comptime { | |
| 743 | assert(3 & 1 == 1); | |
| 744 | assert(3 & -1 == 3); | |
| 745 | assert(-3 & -1 == -3); | |
| 746 | assert(3 | -1 == -1); | |
| 747 | assert(-3 | -1 == -1); | |
| 748 | assert(3 ^ -1 == -4); | |
| 749 | assert(-3 ^ -1 == 2); | |
| 750 | assert(~i8(-1) == 0); | |
| 751 | assert(~i128(-1) == 0); | |
| 752 | assert(18446744073709551615 & 18446744073709551611 == 18446744073709551611); | |
| 753 | assert(-18446744073709551615 & -18446744073709551611 == -18446744073709551615); | |
| 754 | assert(~u128(0) == 0xffffffffffffffffffffffffffffffff); | |
| 755 | } | |
| 756 | } | |
| 757 | ||
| 758 | test "*align(1) u16 is the same as *align(1:0:2) u16" { | |
| 759 | comptime { | |
| 760 | assert(*align(1:0:2) u16 == *align(1) u16); | |
| 761 | // TODO add parsing support for this syntax | |
| 762 | //assert(*align(:0:2) u16 == *u16); | |
| 763 | } | |
| 764 | } | |
| 765 | ||
| 766 | test "array concatenation forces comptime" { | |
| 767 | var a = oneItem(3) ++ oneItem(4); | |
| 768 | assert(std.mem.eql(i32, a, []i32{3, 4})); | |
| 769 | } | |
| 770 | ||
| 771 | test "array multiplication forces comptime" { | |
| 772 | var a = oneItem(3) ** scalar(2); | |
| 773 | assert(std.mem.eql(i32, a, []i32{3, 3})); | |
| 774 | } | |
| 775 | ||
| 776 | fn oneItem(x: i32) [1]i32 { | |
| 777 | return []i32{x}; | |
| 778 | } | |
| 779 | ||
| 780 | fn scalar(x: u32) u32 { | |
| 781 | return x; | |
| 782 | } |
test/cases/field_parent_ptr.zig deleted-41| ... | ... | @@ -1,41 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "@fieldParentPtr non-first field" { | |
| 4 | testParentFieldPtr(&foo.c); | |
| 5 | comptime testParentFieldPtr(&foo.c); | |
| 6 | } | |
| 7 | ||
| 8 | test "@fieldParentPtr first field" { | |
| 9 | testParentFieldPtrFirst(&foo.a); | |
| 10 | comptime testParentFieldPtrFirst(&foo.a); | |
| 11 | } | |
| 12 | ||
| 13 | const Foo = struct { | |
| 14 | a: bool, | |
| 15 | b: f32, | |
| 16 | c: i32, | |
| 17 | d: i32, | |
| 18 | }; | |
| 19 | ||
| 20 | const foo = Foo{ | |
| 21 | .a = true, | |
| 22 | .b = 0.123, | |
| 23 | .c = 1234, | |
| 24 | .d = -10, | |
| 25 | }; | |
| 26 | ||
| 27 | fn testParentFieldPtr(c: *const i32) void { | |
| 28 | assert(c == &foo.c); | |
| 29 | ||
| 30 | const base = @fieldParentPtr(Foo, "c", c); | |
| 31 | assert(base == &foo); | |
| 32 | assert(&base.c == c); | |
| 33 | } | |
| 34 | ||
| 35 | fn testParentFieldPtrFirst(a: *const bool) void { | |
| 36 | assert(a == &foo.a); | |
| 37 | ||
| 38 | const base = @fieldParentPtr(Foo, "a", a); | |
| 39 | assert(base == &foo); | |
| 40 | assert(&base.a == a); | |
| 41 | } |
test/cases/fn.zig deleted-207| ... | ... | @@ -1,207 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "params" { | |
| 4 | assert(testParamsAdd(22, 11) == 33); | |
| 5 | } | |
| 6 | fn testParamsAdd(a: i32, b: i32) i32 { | |
| 7 | return a + b; | |
| 8 | } | |
| 9 | ||
| 10 | test "local variables" { | |
| 11 | testLocVars(2); | |
| 12 | } | |
| 13 | fn testLocVars(b: i32) void { | |
| 14 | const a: i32 = 1; | |
| 15 | if (a + b != 3) unreachable; | |
| 16 | } | |
| 17 | ||
| 18 | test "void parameters" { | |
| 19 | voidFun(1, void{}, 2, {}); | |
| 20 | } | |
| 21 | fn voidFun(a: i32, b: void, c: i32, d: void) void { | |
| 22 | const v = b; | |
| 23 | const vv: void = if (a == 1) v else {}; | |
| 24 | assert(a + c == 3); | |
| 25 | return vv; | |
| 26 | } | |
| 27 | ||
| 28 | test "mutable local variables" { | |
| 29 | var zero: i32 = 0; | |
| 30 | assert(zero == 0); | |
| 31 | ||
| 32 | var i = i32(0); | |
| 33 | while (i != 3) { | |
| 34 | i += 1; | |
| 35 | } | |
| 36 | assert(i == 3); | |
| 37 | } | |
| 38 | ||
| 39 | test "separate block scopes" { | |
| 40 | { | |
| 41 | const no_conflict: i32 = 5; | |
| 42 | assert(no_conflict == 5); | |
| 43 | } | |
| 44 | ||
| 45 | const c = x: { | |
| 46 | const no_conflict = i32(10); | |
| 47 | break :x no_conflict; | |
| 48 | }; | |
| 49 | assert(c == 10); | |
| 50 | } | |
| 51 | ||
| 52 | test "call function with empty string" { | |
| 53 | acceptsString(""); | |
| 54 | } | |
| 55 | ||
| 56 | fn acceptsString(foo: []u8) void {} | |
| 57 | ||
| 58 | fn @"weird function name"() i32 { | |
| 59 | return 1234; | |
| 60 | } | |
| 61 | test "weird function name" { | |
| 62 | assert(@"weird function name"() == 1234); | |
| 63 | } | |
| 64 | ||
| 65 | test "implicit cast function unreachable return" { | |
| 66 | wantsFnWithVoid(fnWithUnreachable); | |
| 67 | } | |
| 68 | ||
| 69 | fn wantsFnWithVoid(f: fn () void) void {} | |
| 70 | ||
| 71 | fn fnWithUnreachable() noreturn { | |
| 72 | unreachable; | |
| 73 | } | |
| 74 | ||
| 75 | test "function pointers" { | |
| 76 | const fns = []@typeOf(fn1){ | |
| 77 | fn1, | |
| 78 | fn2, | |
| 79 | fn3, | |
| 80 | fn4, | |
| 81 | }; | |
| 82 | for (fns) |f, i| { | |
| 83 | assert(f() == @intCast(u32, i) + 5); | |
| 84 | } | |
| 85 | } | |
| 86 | fn fn1() u32 { | |
| 87 | return 5; | |
| 88 | } | |
| 89 | fn fn2() u32 { | |
| 90 | return 6; | |
| 91 | } | |
| 92 | fn fn3() u32 { | |
| 93 | return 7; | |
| 94 | } | |
| 95 | fn fn4() u32 { | |
| 96 | return 8; | |
| 97 | } | |
| 98 | ||
| 99 | test "inline function call" { | |
| 100 | assert(@inlineCall(add, 3, 9) == 12); | |
| 101 | } | |
| 102 | ||
| 103 | fn add(a: i32, b: i32) i32 { | |
| 104 | return a + b; | |
| 105 | } | |
| 106 | ||
| 107 | test "number literal as an argument" { | |
| 108 | numberLiteralArg(3); | |
| 109 | comptime numberLiteralArg(3); | |
| 110 | } | |
| 111 | ||
| 112 | fn numberLiteralArg(a: var) void { | |
| 113 | assert(a == 3); | |
| 114 | } | |
| 115 | ||
| 116 | test "assign inline fn to const variable" { | |
| 117 | const a = inlineFn; | |
| 118 | a(); | |
| 119 | } | |
| 120 | ||
| 121 | inline fn inlineFn() void {} | |
| 122 | ||
| 123 | test "pass by non-copying value" { | |
| 124 | assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3); | |
| 125 | } | |
| 126 | ||
| 127 | const Point = struct { | |
| 128 | x: i32, | |
| 129 | y: i32, | |
| 130 | }; | |
| 131 | ||
| 132 | fn addPointCoords(pt: Point) i32 { | |
| 133 | return pt.x + pt.y; | |
| 134 | } | |
| 135 | ||
| 136 | test "pass by non-copying value through var arg" { | |
| 137 | assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3); | |
| 138 | } | |
| 139 | ||
| 140 | fn addPointCoordsVar(pt: var) i32 { | |
| 141 | comptime assert(@typeOf(pt) == Point); | |
| 142 | return pt.x + pt.y; | |
| 143 | } | |
| 144 | ||
| 145 | test "pass by non-copying value as method" { | |
| 146 | var pt = Point2{ .x = 1, .y = 2 }; | |
| 147 | assert(pt.addPointCoords() == 3); | |
| 148 | } | |
| 149 | ||
| 150 | const Point2 = struct { | |
| 151 | x: i32, | |
| 152 | y: i32, | |
| 153 | ||
| 154 | fn addPointCoords(self: Point2) i32 { | |
| 155 | return self.x + self.y; | |
| 156 | } | |
| 157 | }; | |
| 158 | ||
| 159 | test "pass by non-copying value as method, which is generic" { | |
| 160 | var pt = Point3{ .x = 1, .y = 2 }; | |
| 161 | assert(pt.addPointCoords(i32) == 3); | |
| 162 | } | |
| 163 | ||
| 164 | const Point3 = struct { | |
| 165 | x: i32, | |
| 166 | y: i32, | |
| 167 | ||
| 168 | fn addPointCoords(self: Point3, comptime T: type) i32 { | |
| 169 | return self.x + self.y; | |
| 170 | } | |
| 171 | }; | |
| 172 | ||
| 173 | test "pass by non-copying value as method, at comptime" { | |
| 174 | comptime { | |
| 175 | var pt = Point2{ .x = 1, .y = 2 }; | |
| 176 | assert(pt.addPointCoords() == 3); | |
| 177 | } | |
| 178 | } | |
| 179 | ||
| 180 | fn outer(y: u32) fn (u32) u32 { | |
| 181 | const Y = @typeOf(y); | |
| 182 | const st = struct { | |
| 183 | fn get(z: u32) u32 { | |
| 184 | return z + @sizeOf(Y); | |
| 185 | } | |
| 186 | }; | |
| 187 | return st.get; | |
| 188 | } | |
| 189 | ||
| 190 | test "return inner function which references comptime variable of outer function" { | |
| 191 | var func = outer(10); | |
| 192 | assert(func(3) == 7); | |
| 193 | } | |
| 194 | ||
| 195 | test "extern struct with stdcallcc fn pointer" { | |
| 196 | const S = extern struct { | |
| 197 | ptr: stdcallcc fn () i32, | |
| 198 | ||
| 199 | stdcallcc fn foo() i32 { | |
| 200 | return 1234; | |
| 201 | } | |
| 202 | }; | |
| 203 | ||
| 204 | var s: S = undefined; | |
| 205 | s.ptr = S.foo; | |
| 206 | assert(s.ptr() == 1234); | |
| 207 | } |
test/cases/fn_in_struct_in_comptime.zig deleted-17| ... | ... | @@ -1,17 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | fn get_foo() fn (*u8) usize { | |
| 4 | comptime { | |
| 5 | return struct { | |
| 6 | fn func(ptr: *u8) usize { | |
| 7 | var u = @ptrToInt(ptr); | |
| 8 | return u; | |
| 9 | } | |
| 10 | }.func; | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | test "define a function in an anonymous struct in comptime" { | |
| 15 | const foo = get_foo(); | |
| 16 | assert(foo(@intToPtr(*u8, 12345)) == 12345); | |
| 17 | } |
test/cases/for.zig deleted-106| ... | ... | @@ -1,106 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const mem = std.mem; | |
| 4 | ||
| 5 | test "continue in for loop" { | |
| 6 | const array = []i32{ | |
| 7 | 1, | |
| 8 | 2, | |
| 9 | 3, | |
| 10 | 4, | |
| 11 | 5, | |
| 12 | }; | |
| 13 | var sum: i32 = 0; | |
| 14 | for (array) |x| { | |
| 15 | sum += x; | |
| 16 | if (x < 3) { | |
| 17 | continue; | |
| 18 | } | |
| 19 | break; | |
| 20 | } | |
| 21 | if (sum != 6) unreachable; | |
| 22 | } | |
| 23 | ||
| 24 | test "for loop with pointer elem var" { | |
| 25 | const source = "abcdefg"; | |
| 26 | var target: [source.len]u8 = undefined; | |
| 27 | mem.copy(u8, target[0..], source); | |
| 28 | mangleString(target[0..]); | |
| 29 | assert(mem.eql(u8, target, "bcdefgh")); | |
| 30 | } | |
| 31 | fn mangleString(s: []u8) void { | |
| 32 | for (s) |*c| { | |
| 33 | c.* += 1; | |
| 34 | } | |
| 35 | } | |
| 36 | ||
| 37 | test "basic for loop" { | |
| 38 | const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3; | |
| 39 | ||
| 40 | var buffer: [expected_result.len]u8 = undefined; | |
| 41 | var buf_index: usize = 0; | |
| 42 | ||
| 43 | const array = []u8{ 9, 8, 7, 6 }; | |
| 44 | for (array) |item| { | |
| 45 | buffer[buf_index] = item; | |
| 46 | buf_index += 1; | |
| 47 | } | |
| 48 | for (array) |item, index| { | |
| 49 | buffer[buf_index] = @intCast(u8, index); | |
| 50 | buf_index += 1; | |
| 51 | } | |
| 52 | const array_ptr = &array; | |
| 53 | for (array_ptr) |item| { | |
| 54 | buffer[buf_index] = item; | |
| 55 | buf_index += 1; | |
| 56 | } | |
| 57 | for (array_ptr) |item, index| { | |
| 58 | buffer[buf_index] = @intCast(u8, index); | |
| 59 | buf_index += 1; | |
| 60 | } | |
| 61 | const unknown_size: []const u8 = array; | |
| 62 | for (unknown_size) |item| { | |
| 63 | buffer[buf_index] = item; | |
| 64 | buf_index += 1; | |
| 65 | } | |
| 66 | for (unknown_size) |item, index| { | |
| 67 | buffer[buf_index] = @intCast(u8, index); | |
| 68 | buf_index += 1; | |
| 69 | } | |
| 70 | ||
| 71 | assert(mem.eql(u8, buffer[0..buf_index], expected_result)); | |
| 72 | } | |
| 73 | ||
| 74 | test "break from outer for loop" { | |
| 75 | testBreakOuter(); | |
| 76 | comptime testBreakOuter(); | |
| 77 | } | |
| 78 | ||
| 79 | fn testBreakOuter() void { | |
| 80 | var array = "aoeu"; | |
| 81 | var count: usize = 0; | |
| 82 | outer: for (array) |_| { | |
| 83 | for (array) |_| { | |
| 84 | count += 1; | |
| 85 | break :outer; | |
| 86 | } | |
| 87 | } | |
| 88 | assert(count == 1); | |
| 89 | } | |
| 90 | ||
| 91 | test "continue outer for loop" { | |
| 92 | testContinueOuter(); | |
| 93 | comptime testContinueOuter(); | |
| 94 | } | |
| 95 | ||
| 96 | fn testContinueOuter() void { | |
| 97 | var array = "aoeu"; | |
| 98 | var counter: usize = 0; | |
| 99 | outer: for (array) |_| { | |
| 100 | for (array) |_| { | |
| 101 | counter += 1; | |
| 102 | continue :outer; | |
| 103 | } | |
| 104 | } | |
| 105 | assert(counter == array.len); | |
| 106 | } |
test/cases/generics.zig deleted-151| ... | ... | @@ -1,151 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "simple generic fn" { | |
| 4 | assert(max(i32, 3, -1) == 3); | |
| 5 | assert(max(f32, 0.123, 0.456) == 0.456); | |
| 6 | assert(add(2, 3) == 5); | |
| 7 | } | |
| 8 | ||
| 9 | fn max(comptime T: type, a: T, b: T) T { | |
| 10 | return if (a > b) a else b; | |
| 11 | } | |
| 12 | ||
| 13 | fn add(comptime a: i32, b: i32) i32 { | |
| 14 | return (comptime a) + b; | |
| 15 | } | |
| 16 | ||
| 17 | const the_max = max(u32, 1234, 5678); | |
| 18 | test "compile time generic eval" { | |
| 19 | assert(the_max == 5678); | |
| 20 | } | |
| 21 | ||
| 22 | fn gimmeTheBigOne(a: u32, b: u32) u32 { | |
| 23 | return max(u32, a, b); | |
| 24 | } | |
| 25 | ||
| 26 | fn shouldCallSameInstance(a: u32, b: u32) u32 { | |
| 27 | return max(u32, a, b); | |
| 28 | } | |
| 29 | ||
| 30 | fn sameButWithFloats(a: f64, b: f64) f64 { | |
| 31 | return max(f64, a, b); | |
| 32 | } | |
| 33 | ||
| 34 | test "fn with comptime args" { | |
| 35 | assert(gimmeTheBigOne(1234, 5678) == 5678); | |
| 36 | assert(shouldCallSameInstance(34, 12) == 34); | |
| 37 | assert(sameButWithFloats(0.43, 0.49) == 0.49); | |
| 38 | } | |
| 39 | ||
| 40 | test "var params" { | |
| 41 | assert(max_i32(12, 34) == 34); | |
| 42 | assert(max_f64(1.2, 3.4) == 3.4); | |
| 43 | } | |
| 44 | ||
| 45 | comptime { | |
| 46 | assert(max_i32(12, 34) == 34); | |
| 47 | assert(max_f64(1.2, 3.4) == 3.4); | |
| 48 | } | |
| 49 | ||
| 50 | fn max_var(a: var, b: var) @typeOf(a + b) { | |
| 51 | return if (a > b) a else b; | |
| 52 | } | |
| 53 | ||
| 54 | fn max_i32(a: i32, b: i32) i32 { | |
| 55 | return max_var(a, b); | |
| 56 | } | |
| 57 | ||
| 58 | fn max_f64(a: f64, b: f64) f64 { | |
| 59 | return max_var(a, b); | |
| 60 | } | |
| 61 | ||
| 62 | pub fn List(comptime T: type) type { | |
| 63 | return SmallList(T, 8); | |
| 64 | } | |
| 65 | ||
| 66 | pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type { | |
| 67 | return struct { | |
| 68 | items: []T, | |
| 69 | length: usize, | |
| 70 | prealloc_items: [STATIC_SIZE]T, | |
| 71 | }; | |
| 72 | } | |
| 73 | ||
| 74 | test "function with return type type" { | |
| 75 | var list: List(i32) = undefined; | |
| 76 | var list2: List(i32) = undefined; | |
| 77 | list.length = 10; | |
| 78 | list2.length = 10; | |
| 79 | assert(list.prealloc_items.len == 8); | |
| 80 | assert(list2.prealloc_items.len == 8); | |
| 81 | } | |
| 82 | ||
| 83 | test "generic struct" { | |
| 84 | var a1 = GenNode(i32){ | |
| 85 | .value = 13, | |
| 86 | .next = null, | |
| 87 | }; | |
| 88 | var b1 = GenNode(bool){ | |
| 89 | .value = true, | |
| 90 | .next = null, | |
| 91 | }; | |
| 92 | assert(a1.value == 13); | |
| 93 | assert(a1.value == a1.getVal()); | |
| 94 | assert(b1.getVal()); | |
| 95 | } | |
| 96 | fn GenNode(comptime T: type) type { | |
| 97 | return struct { | |
| 98 | value: T, | |
| 99 | next: ?*GenNode(T), | |
| 100 | fn getVal(n: *const GenNode(T)) T { | |
| 101 | return n.value; | |
| 102 | } | |
| 103 | }; | |
| 104 | } | |
| 105 | ||
| 106 | test "const decls in struct" { | |
| 107 | assert(GenericDataThing(3).count_plus_one == 4); | |
| 108 | } | |
| 109 | fn GenericDataThing(comptime count: isize) type { | |
| 110 | return struct { | |
| 111 | const count_plus_one = count + 1; | |
| 112 | }; | |
| 113 | } | |
| 114 | ||
| 115 | test "use generic param in generic param" { | |
| 116 | assert(aGenericFn(i32, 3, 4) == 7); | |
| 117 | } | |
| 118 | fn aGenericFn(comptime T: type, comptime a: T, b: T) T { | |
| 119 | return a + b; | |
| 120 | } | |
| 121 | ||
| 122 | test "generic fn with implicit cast" { | |
| 123 | assert(getFirstByte(u8, []u8{13}) == 13); | |
| 124 | assert(getFirstByte(u16, []u16{ | |
| 125 | 0, | |
| 126 | 13, | |
| 127 | }) == 0); | |
| 128 | } | |
| 129 | fn getByte(ptr: ?*const u8) u8 { | |
| 130 | return ptr.?.*; | |
| 131 | } | |
| 132 | fn getFirstByte(comptime T: type, mem: []const T) u8 { | |
| 133 | return getByte(@ptrCast(*const u8, &mem[0])); | |
| 134 | } | |
| 135 | ||
| 136 | const foos = []fn (var) bool{ | |
| 137 | foo1, | |
| 138 | foo2, | |
| 139 | }; | |
| 140 | ||
| 141 | fn foo1(arg: var) bool { | |
| 142 | return arg; | |
| 143 | } | |
| 144 | fn foo2(arg: var) bool { | |
| 145 | return !arg; | |
| 146 | } | |
| 147 | ||
| 148 | test "array of generic fns" { | |
| 149 | assert(foos[0](true)); | |
| 150 | assert(!foos[1](true)); | |
| 151 | } |
test/cases/if.zig deleted-37| ... | ... | @@ -1,37 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "if statements" { | |
| 4 | shouldBeEqual(1, 1); | |
| 5 | firstEqlThird(2, 1, 2); | |
| 6 | } | |
| 7 | fn shouldBeEqual(a: i32, b: i32) void { | |
| 8 | if (a != b) { | |
| 9 | unreachable; | |
| 10 | } else { | |
| 11 | return; | |
| 12 | } | |
| 13 | } | |
| 14 | fn firstEqlThird(a: i32, b: i32, c: i32) void { | |
| 15 | if (a == b) { | |
| 16 | unreachable; | |
| 17 | } else if (b == c) { | |
| 18 | unreachable; | |
| 19 | } else if (a == c) { | |
| 20 | return; | |
| 21 | } else { | |
| 22 | unreachable; | |
| 23 | } | |
| 24 | } | |
| 25 | ||
| 26 | test "else if expression" { | |
| 27 | assert(elseIfExpressionF(1) == 1); | |
| 28 | } | |
| 29 | fn elseIfExpressionF(c: u8) u8 { | |
| 30 | if (c == 0) { | |
| 31 | return 0; | |
| 32 | } else if (c == 1) { | |
| 33 | return 1; | |
| 34 | } else { | |
| 35 | return u8(2); | |
| 36 | } | |
| 37 | } |
test/cases/import.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | const a_namespace = @import("import/a_namespace.zig"); | |
| 3 | ||
| 4 | test "call fn via namespace lookup" { | |
| 5 | assert(a_namespace.foo() == 1234); | |
| 6 | } | |
| 7 | ||
| 8 | test "importing the same thing gives the same import" { | |
| 9 | assert(@import("std") == @import("std")); | |
| 10 | } |
test/cases/import/a_namespace.zig deleted-3| ... | ... | @@ -1,3 +0,0 @@ |
| 1 | pub fn foo() i32 { | |
| 2 | return 1234; | |
| 3 | } |
test/cases/incomplete_struct_param_tld.zig deleted-30| ... | ... | @@ -1,30 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | const A = struct { | |
| 4 | b: B, | |
| 5 | }; | |
| 6 | ||
| 7 | const B = struct { | |
| 8 | c: C, | |
| 9 | }; | |
| 10 | ||
| 11 | const C = struct { | |
| 12 | x: i32, | |
| 13 | ||
| 14 | fn d(c: *const C) i32 { | |
| 15 | return c.x; | |
| 16 | } | |
| 17 | }; | |
| 18 | ||
| 19 | fn foo(a: A) i32 { | |
| 20 | return a.b.c.d(); | |
| 21 | } | |
| 22 | ||
| 23 | test "incomplete struct param top level declaration" { | |
| 24 | const a = A{ | |
| 25 | .b = B{ | |
| 26 | .c = C{ .x = 13 }, | |
| 27 | }, | |
| 28 | }; | |
| 29 | assert(foo(a) == 13); | |
| 30 | } |
test/cases/inttoptr.zig deleted-27| ... | ... | @@ -1,27 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std"); | |
| 3 | const assertOrPanic = std.debug.assertOrPanic; | |
| 4 | ||
| 5 | test "casting random address to function pointer" { | |
| 6 | randomAddressToFunction(); | |
| 7 | comptime randomAddressToFunction(); | |
| 8 | } | |
| 9 | ||
| 10 | fn randomAddressToFunction() void { | |
| 11 | var addr: usize = 0xdeadbeef; | |
| 12 | var ptr = @intToPtr(fn () void, addr); | |
| 13 | } | |
| 14 | ||
| 15 | test "mutate through ptr initialized with constant intToPtr value" { | |
| 16 | forceCompilerAnalyzeBranchHardCodedPtrDereference(false); | |
| 17 | } | |
| 18 | ||
| 19 | fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void { | |
| 20 | const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef); | |
| 21 | if (x) { | |
| 22 | hardCodedP.* = hardCodedP.* | 10; | |
| 23 | } else { | |
| 24 | return; | |
| 25 | } | |
| 26 | } | |
| 27 |
test/cases/ir_block_deps.zig deleted-21| ... | ... | @@ -1,21 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | fn foo(id: u64) !i32 { | |
| 4 | return switch (id) { | |
| 5 | 1 => getErrInt(), | |
| 6 | 2 => { | |
| 7 | const size = try getErrInt(); | |
| 8 | return try getErrInt(); | |
| 9 | }, | |
| 10 | else => error.ItBroke, | |
| 11 | }; | |
| 12 | } | |
| 13 | ||
| 14 | fn getErrInt() anyerror!i32 { | |
| 15 | return 0; | |
| 16 | } | |
| 17 | ||
| 18 | test "ir block deps" { | |
| 19 | assert((foo(1) catch unreachable) == 0); | |
| 20 | assert((foo(2) catch unreachable) == 0); | |
| 21 | } |
test/cases/math.zig deleted-500| ... | ... | @@ -1,500 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const maxInt = std.math.maxInt; | |
| 4 | const minInt = std.math.minInt; | |
| 5 | ||
| 6 | test "division" { | |
| 7 | testDivision(); | |
| 8 | comptime testDivision(); | |
| 9 | } | |
| 10 | fn testDivision() void { | |
| 11 | assert(div(u32, 13, 3) == 4); | |
| 12 | assert(div(f16, 1.0, 2.0) == 0.5); | |
| 13 | assert(div(f32, 1.0, 2.0) == 0.5); | |
| 14 | ||
| 15 | assert(divExact(u32, 55, 11) == 5); | |
| 16 | assert(divExact(i32, -55, 11) == -5); | |
| 17 | assert(divExact(f16, 55.0, 11.0) == 5.0); | |
| 18 | assert(divExact(f16, -55.0, 11.0) == -5.0); | |
| 19 | assert(divExact(f32, 55.0, 11.0) == 5.0); | |
| 20 | assert(divExact(f32, -55.0, 11.0) == -5.0); | |
| 21 | ||
| 22 | assert(divFloor(i32, 5, 3) == 1); | |
| 23 | assert(divFloor(i32, -5, 3) == -2); | |
| 24 | assert(divFloor(f16, 5.0, 3.0) == 1.0); | |
| 25 | assert(divFloor(f16, -5.0, 3.0) == -2.0); | |
| 26 | assert(divFloor(f32, 5.0, 3.0) == 1.0); | |
| 27 | assert(divFloor(f32, -5.0, 3.0) == -2.0); | |
| 28 | assert(divFloor(i32, -0x80000000, -2) == 0x40000000); | |
| 29 | assert(divFloor(i32, 0, -0x80000000) == 0); | |
| 30 | assert(divFloor(i32, -0x40000001, 0x40000000) == -2); | |
| 31 | assert(divFloor(i32, -0x80000000, 1) == -0x80000000); | |
| 32 | ||
| 33 | assert(divTrunc(i32, 5, 3) == 1); | |
| 34 | assert(divTrunc(i32, -5, 3) == -1); | |
| 35 | assert(divTrunc(f16, 5.0, 3.0) == 1.0); | |
| 36 | assert(divTrunc(f16, -5.0, 3.0) == -1.0); | |
| 37 | assert(divTrunc(f32, 5.0, 3.0) == 1.0); | |
| 38 | assert(divTrunc(f32, -5.0, 3.0) == -1.0); | |
| 39 | assert(divTrunc(f64, 5.0, 3.0) == 1.0); | |
| 40 | assert(divTrunc(f64, -5.0, 3.0) == -1.0); | |
| 41 | ||
| 42 | comptime { | |
| 43 | assert( | |
| 44 | 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600, | |
| 45 | ); | |
| 46 | assert( | |
| 47 | @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600, | |
| 48 | ); | |
| 49 | assert( | |
| 50 | 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2, | |
| 51 | ); | |
| 52 | assert( | |
| 53 | @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2, | |
| 54 | ); | |
| 55 | assert( | |
| 56 | @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2, | |
| 57 | ); | |
| 58 | assert( | |
| 59 | @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2, | |
| 60 | ); | |
| 61 | assert( | |
| 62 | 4126227191251978491697987544882340798050766755606969681711 % 10 == 1, | |
| 63 | ); | |
| 64 | } | |
| 65 | } | |
| 66 | fn div(comptime T: type, a: T, b: T) T { | |
| 67 | return a / b; | |
| 68 | } | |
| 69 | fn divExact(comptime T: type, a: T, b: T) T { | |
| 70 | return @divExact(a, b); | |
| 71 | } | |
| 72 | fn divFloor(comptime T: type, a: T, b: T) T { | |
| 73 | return @divFloor(a, b); | |
| 74 | } | |
| 75 | fn divTrunc(comptime T: type, a: T, b: T) T { | |
| 76 | return @divTrunc(a, b); | |
| 77 | } | |
| 78 | ||
| 79 | test "@addWithOverflow" { | |
| 80 | var result: u8 = undefined; | |
| 81 | assert(@addWithOverflow(u8, 250, 100, &result)); | |
| 82 | assert(!@addWithOverflow(u8, 100, 150, &result)); | |
| 83 | assert(result == 250); | |
| 84 | } | |
| 85 | ||
| 86 | // TODO test mulWithOverflow | |
| 87 | // TODO test subWithOverflow | |
| 88 | ||
| 89 | test "@shlWithOverflow" { | |
| 90 | var result: u16 = undefined; | |
| 91 | assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result)); | |
| 92 | assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result)); | |
| 93 | assert(result == 0b1011111111111100); | |
| 94 | } | |
| 95 | ||
| 96 | test "@clz" { | |
| 97 | testClz(); | |
| 98 | comptime testClz(); | |
| 99 | } | |
| 100 | ||
| 101 | fn testClz() void { | |
| 102 | assert(clz(u8(0b00001010)) == 4); | |
| 103 | assert(clz(u8(0b10001010)) == 0); | |
| 104 | assert(clz(u8(0b00000000)) == 8); | |
| 105 | assert(clz(u128(0xffffffffffffffff)) == 64); | |
| 106 | assert(clz(u128(0x10000000000000000)) == 63); | |
| 107 | } | |
| 108 | ||
| 109 | fn clz(x: var) usize { | |
| 110 | return @clz(x); | |
| 111 | } | |
| 112 | ||
| 113 | test "@ctz" { | |
| 114 | testCtz(); | |
| 115 | comptime testCtz(); | |
| 116 | } | |
| 117 | ||
| 118 | fn testCtz() void { | |
| 119 | assert(ctz(u8(0b10100000)) == 5); | |
| 120 | assert(ctz(u8(0b10001010)) == 1); | |
| 121 | assert(ctz(u8(0b00000000)) == 8); | |
| 122 | } | |
| 123 | ||
| 124 | fn ctz(x: var) usize { | |
| 125 | return @ctz(x); | |
| 126 | } | |
| 127 | ||
| 128 | test "assignment operators" { | |
| 129 | var i: u32 = 0; | |
| 130 | i += 5; | |
| 131 | assert(i == 5); | |
| 132 | i -= 2; | |
| 133 | assert(i == 3); | |
| 134 | i *= 20; | |
| 135 | assert(i == 60); | |
| 136 | i /= 3; | |
| 137 | assert(i == 20); | |
| 138 | i %= 11; | |
| 139 | assert(i == 9); | |
| 140 | i <<= 1; | |
| 141 | assert(i == 18); | |
| 142 | i >>= 2; | |
| 143 | assert(i == 4); | |
| 144 | i = 6; | |
| 145 | i &= 5; | |
| 146 | assert(i == 4); | |
| 147 | i ^= 6; | |
| 148 | assert(i == 2); | |
| 149 | i = 6; | |
| 150 | i |= 3; | |
| 151 | assert(i == 7); | |
| 152 | } | |
| 153 | ||
| 154 | test "three expr in a row" { | |
| 155 | testThreeExprInARow(false, true); | |
| 156 | comptime testThreeExprInARow(false, true); | |
| 157 | } | |
| 158 | fn testThreeExprInARow(f: bool, t: bool) void { | |
| 159 | assertFalse(f or f or f); | |
| 160 | assertFalse(t and t and f); | |
| 161 | assertFalse(1 | 2 | 4 != 7); | |
| 162 | assertFalse(3 ^ 6 ^ 8 != 13); | |
| 163 | assertFalse(7 & 14 & 28 != 4); | |
| 164 | assertFalse(9 << 1 << 2 != 9 << 3); | |
| 165 | assertFalse(90 >> 1 >> 2 != 90 >> 3); | |
| 166 | assertFalse(100 - 1 + 1000 != 1099); | |
| 167 | assertFalse(5 * 4 / 2 % 3 != 1); | |
| 168 | assertFalse(i32(i32(5)) != 5); | |
| 169 | assertFalse(!!false); | |
| 170 | assertFalse(i32(7) != --(i32(7))); | |
| 171 | } | |
| 172 | fn assertFalse(b: bool) void { | |
| 173 | assert(!b); | |
| 174 | } | |
| 175 | ||
| 176 | test "const number literal" { | |
| 177 | const one = 1; | |
| 178 | const eleven = ten + one; | |
| 179 | ||
| 180 | assert(eleven == 11); | |
| 181 | } | |
| 182 | const ten = 10; | |
| 183 | ||
| 184 | test "unsigned wrapping" { | |
| 185 | testUnsignedWrappingEval(maxInt(u32)); | |
| 186 | comptime testUnsignedWrappingEval(maxInt(u32)); | |
| 187 | } | |
| 188 | fn testUnsignedWrappingEval(x: u32) void { | |
| 189 | const zero = x +% 1; | |
| 190 | assert(zero == 0); | |
| 191 | const orig = zero -% 1; | |
| 192 | assert(orig == maxInt(u32)); | |
| 193 | } | |
| 194 | ||
| 195 | test "signed wrapping" { | |
| 196 | testSignedWrappingEval(maxInt(i32)); | |
| 197 | comptime testSignedWrappingEval(maxInt(i32)); | |
| 198 | } | |
| 199 | fn testSignedWrappingEval(x: i32) void { | |
| 200 | const min_val = x +% 1; | |
| 201 | assert(min_val == minInt(i32)); | |
| 202 | const max_val = min_val -% 1; | |
| 203 | assert(max_val == maxInt(i32)); | |
| 204 | } | |
| 205 | ||
| 206 | test "negation wrapping" { | |
| 207 | testNegationWrappingEval(minInt(i16)); | |
| 208 | comptime testNegationWrappingEval(minInt(i16)); | |
| 209 | } | |
| 210 | fn testNegationWrappingEval(x: i16) void { | |
| 211 | assert(x == -32768); | |
| 212 | const neg = -%x; | |
| 213 | assert(neg == -32768); | |
| 214 | } | |
| 215 | ||
| 216 | test "unsigned 64-bit division" { | |
| 217 | test_u64_div(); | |
| 218 | comptime test_u64_div(); | |
| 219 | } | |
| 220 | fn test_u64_div() void { | |
| 221 | const result = divWithResult(1152921504606846976, 34359738365); | |
| 222 | assert(result.quotient == 33554432); | |
| 223 | assert(result.remainder == 100663296); | |
| 224 | } | |
| 225 | fn divWithResult(a: u64, b: u64) DivResult { | |
| 226 | return DivResult{ | |
| 227 | .quotient = a / b, | |
| 228 | .remainder = a % b, | |
| 229 | }; | |
| 230 | } | |
| 231 | const DivResult = struct { | |
| 232 | quotient: u64, | |
| 233 | remainder: u64, | |
| 234 | }; | |
| 235 | ||
| 236 | test "binary not" { | |
| 237 | assert(comptime x: { | |
| 238 | break :x ~u16(0b1010101010101010) == 0b0101010101010101; | |
| 239 | }); | |
| 240 | assert(comptime x: { | |
| 241 | break :x ~u64(2147483647) == 18446744071562067968; | |
| 242 | }); | |
| 243 | testBinaryNot(0b1010101010101010); | |
| 244 | } | |
| 245 | ||
| 246 | fn testBinaryNot(x: u16) void { | |
| 247 | assert(~x == 0b0101010101010101); | |
| 248 | } | |
| 249 | ||
| 250 | test "small int addition" { | |
| 251 | var x: @IntType(false, 2) = 0; | |
| 252 | assert(x == 0); | |
| 253 | ||
| 254 | x += 1; | |
| 255 | assert(x == 1); | |
| 256 | ||
| 257 | x += 1; | |
| 258 | assert(x == 2); | |
| 259 | ||
| 260 | x += 1; | |
| 261 | assert(x == 3); | |
| 262 | ||
| 263 | var result: @typeOf(x) = 3; | |
| 264 | assert(@addWithOverflow(@typeOf(x), x, 1, &result)); | |
| 265 | ||
| 266 | assert(result == 0); | |
| 267 | } | |
| 268 | ||
| 269 | test "float equality" { | |
| 270 | const x: f64 = 0.012; | |
| 271 | const y: f64 = x + 1.0; | |
| 272 | ||
| 273 | testFloatEqualityImpl(x, y); | |
| 274 | comptime testFloatEqualityImpl(x, y); | |
| 275 | } | |
| 276 | ||
| 277 | fn testFloatEqualityImpl(x: f64, y: f64) void { | |
| 278 | const y2 = x + 1.0; | |
| 279 | assert(y == y2); | |
| 280 | } | |
| 281 | ||
| 282 | test "allow signed integer division/remainder when values are comptime known and positive or exact" { | |
| 283 | assert(5 / 3 == 1); | |
| 284 | assert(-5 / -3 == 1); | |
| 285 | assert(-6 / 3 == -2); | |
| 286 | ||
| 287 | assert(5 % 3 == 2); | |
| 288 | assert(-6 % 3 == 0); | |
| 289 | } | |
| 290 | ||
| 291 | test "hex float literal parsing" { | |
| 292 | comptime assert(0x1.0 == 1.0); | |
| 293 | } | |
| 294 | ||
| 295 | test "quad hex float literal parsing in range" { | |
| 296 | const a = 0x1.af23456789bbaaab347645365cdep+5; | |
| 297 | const b = 0x1.dedafcff354b6ae9758763545432p-9; | |
| 298 | const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534; | |
| 299 | const d = 0x1.edcbff8ad76ab5bf46463233214fp-435; | |
| 300 | } | |
| 301 | ||
| 302 | test "quad hex float literal parsing accurate" { | |
| 303 | const a: f128 = 0x1.1111222233334444555566667777p+0; | |
| 304 | ||
| 305 | // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing. | |
| 306 | const expected: u128 = 0x3fff1111222233334444555566667777; | |
| 307 | assert(@bitCast(u128, a) == expected); | |
| 308 | } | |
| 309 | ||
| 310 | test "hex float literal within range" { | |
| 311 | const a = 0x1.0p16383; | |
| 312 | const b = 0x0.1p16387; | |
| 313 | const c = 0x1.0p-16382; | |
| 314 | } | |
| 315 | ||
| 316 | test "truncating shift left" { | |
| 317 | testShlTrunc(maxInt(u16)); | |
| 318 | comptime testShlTrunc(maxInt(u16)); | |
| 319 | } | |
| 320 | fn testShlTrunc(x: u16) void { | |
| 321 | const shifted = x << 1; | |
| 322 | assert(shifted == 65534); | |
| 323 | } | |
| 324 | ||
| 325 | test "truncating shift right" { | |
| 326 | testShrTrunc(maxInt(u16)); | |
| 327 | comptime testShrTrunc(maxInt(u16)); | |
| 328 | } | |
| 329 | fn testShrTrunc(x: u16) void { | |
| 330 | const shifted = x >> 1; | |
| 331 | assert(shifted == 32767); | |
| 332 | } | |
| 333 | ||
| 334 | test "exact shift left" { | |
| 335 | testShlExact(0b00110101); | |
| 336 | comptime testShlExact(0b00110101); | |
| 337 | } | |
| 338 | fn testShlExact(x: u8) void { | |
| 339 | const shifted = @shlExact(x, 2); | |
| 340 | assert(shifted == 0b11010100); | |
| 341 | } | |
| 342 | ||
| 343 | test "exact shift right" { | |
| 344 | testShrExact(0b10110100); | |
| 345 | comptime testShrExact(0b10110100); | |
| 346 | } | |
| 347 | fn testShrExact(x: u8) void { | |
| 348 | const shifted = @shrExact(x, 2); | |
| 349 | assert(shifted == 0b00101101); | |
| 350 | } | |
| 351 | ||
| 352 | test "comptime_int addition" { | |
| 353 | comptime { | |
| 354 | assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950); | |
| 355 | assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380); | |
| 356 | } | |
| 357 | } | |
| 358 | ||
| 359 | test "comptime_int multiplication" { | |
| 360 | comptime { | |
| 361 | assert( | |
| 362 | 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567, | |
| 363 | ); | |
| 364 | assert( | |
| 365 | 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016, | |
| 366 | ); | |
| 367 | } | |
| 368 | } | |
| 369 | ||
| 370 | test "comptime_int shifting" { | |
| 371 | comptime { | |
| 372 | assert((u128(1) << 127) == 0x80000000000000000000000000000000); | |
| 373 | } | |
| 374 | } | |
| 375 | ||
| 376 | test "comptime_int multi-limb shift and mask" { | |
| 377 | comptime { | |
| 378 | var a = 0xefffffffa0000001eeeeeeefaaaaaaab; | |
| 379 | ||
| 380 | assert(u32(a & 0xffffffff) == 0xaaaaaaab); | |
| 381 | a >>= 32; | |
| 382 | assert(u32(a & 0xffffffff) == 0xeeeeeeef); | |
| 383 | a >>= 32; | |
| 384 | assert(u32(a & 0xffffffff) == 0xa0000001); | |
| 385 | a >>= 32; | |
| 386 | assert(u32(a & 0xffffffff) == 0xefffffff); | |
| 387 | a >>= 32; | |
| 388 | ||
| 389 | assert(a == 0); | |
| 390 | } | |
| 391 | } | |
| 392 | ||
| 393 | test "comptime_int multi-limb partial shift right" { | |
| 394 | comptime { | |
| 395 | var a = 0x1ffffffffeeeeeeee; | |
| 396 | a >>= 16; | |
| 397 | assert(a == 0x1ffffffffeeee); | |
| 398 | } | |
| 399 | } | |
| 400 | ||
| 401 | test "xor" { | |
| 402 | test_xor(); | |
| 403 | comptime test_xor(); | |
| 404 | } | |
| 405 | ||
| 406 | fn test_xor() void { | |
| 407 | assert(0xFF ^ 0x00 == 0xFF); | |
| 408 | assert(0xF0 ^ 0x0F == 0xFF); | |
| 409 | assert(0xFF ^ 0xF0 == 0x0F); | |
| 410 | assert(0xFF ^ 0x0F == 0xF0); | |
| 411 | assert(0xFF ^ 0xFF == 0x00); | |
| 412 | } | |
| 413 | ||
| 414 | test "comptime_int xor" { | |
| 415 | comptime { | |
| 416 | assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 417 | assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 418 | assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF); | |
| 419 | assert(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000); | |
| 420 | assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000); | |
| 421 | assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 422 | assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF); | |
| 423 | assert(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000); | |
| 424 | } | |
| 425 | } | |
| 426 | ||
| 427 | test "f128" { | |
| 428 | test_f128(); | |
| 429 | comptime test_f128(); | |
| 430 | } | |
| 431 | ||
| 432 | fn make_f128(x: f128) f128 { | |
| 433 | return x; | |
| 434 | } | |
| 435 | ||
| 436 | fn test_f128() void { | |
| 437 | assert(@sizeOf(f128) == 16); | |
| 438 | assert(make_f128(1.0) == 1.0); | |
| 439 | assert(make_f128(1.0) != 1.1); | |
| 440 | assert(make_f128(1.0) > 0.9); | |
| 441 | assert(make_f128(1.0) >= 0.9); | |
| 442 | assert(make_f128(1.0) >= 1.0); | |
| 443 | should_not_be_zero(1.0); | |
| 444 | } | |
| 445 | ||
| 446 | fn should_not_be_zero(x: f128) void { | |
| 447 | assert(x != 0.0); | |
| 448 | } | |
| 449 | ||
| 450 | test "comptime float rem int" { | |
| 451 | comptime { | |
| 452 | var x = f32(1) % 2; | |
| 453 | assert(x == 1.0); | |
| 454 | } | |
| 455 | } | |
| 456 | ||
| 457 | test "remainder division" { | |
| 458 | comptime remdiv(f16); | |
| 459 | comptime remdiv(f32); | |
| 460 | comptime remdiv(f64); | |
| 461 | comptime remdiv(f128); | |
| 462 | remdiv(f16); | |
| 463 | remdiv(f64); | |
| 464 | remdiv(f128); | |
| 465 | } | |
| 466 | ||
| 467 | fn remdiv(comptime T: type) void { | |
| 468 | assert(T(1) == T(1) % T(2)); | |
| 469 | assert(T(1) == T(7) % T(3)); | |
| 470 | } | |
| 471 | ||
| 472 | test "@sqrt" { | |
| 473 | testSqrt(f64, 12.0); | |
| 474 | comptime testSqrt(f64, 12.0); | |
| 475 | testSqrt(f32, 13.0); | |
| 476 | comptime testSqrt(f32, 13.0); | |
| 477 | testSqrt(f16, 13.0); | |
| 478 | comptime testSqrt(f16, 13.0); | |
| 479 | ||
| 480 | const x = 14.0; | |
| 481 | const y = x * x; | |
| 482 | const z = @sqrt(@typeOf(y), y); | |
| 483 | comptime assert(z == x); | |
| 484 | } | |
| 485 | ||
| 486 | fn testSqrt(comptime T: type, x: T) void { | |
| 487 | assert(@sqrt(T, x * x) == x); | |
| 488 | } | |
| 489 | ||
| 490 | test "comptime_int param and return" { | |
| 491 | const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702); | |
| 492 | assert(a == 137114567242441932203689521744947848950); | |
| 493 | ||
| 494 | const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768); | |
| 495 | assert(b == 985095453608931032642182098849559179469148836107390954364380); | |
| 496 | } | |
| 497 | ||
| 498 | fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int { | |
| 499 | return a + b; | |
| 500 | } |
test/cases/merge_error_sets.zig deleted-21| ... | ... | @@ -1,21 +0,0 @@ |
| 1 | const A = error{ | |
| 2 | FileNotFound, | |
| 3 | NotDir, | |
| 4 | }; | |
| 5 | const B = error{OutOfMemory}; | |
| 6 | ||
| 7 | const C = A || B; | |
| 8 | ||
| 9 | fn foo() C!void { | |
| 10 | return error.NotDir; | |
| 11 | } | |
| 12 | ||
| 13 | test "merge error sets" { | |
| 14 | if (foo()) { | |
| 15 | @panic("unexpected"); | |
| 16 | } else |err| switch (err) { | |
| 17 | error.OutOfMemory => @panic("unexpected"), | |
| 18 | error.FileNotFound => @panic("unexpected"), | |
| 19 | error.NotDir => {}, | |
| 20 | } | |
| 21 | } |
test/cases/misc.zig deleted-681| ... | ... | @@ -1,681 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const mem = std.mem; | |
| 4 | const cstr = std.cstr; | |
| 5 | const builtin = @import("builtin"); | |
| 6 | const maxInt = std.math.maxInt; | |
| 7 | ||
| 8 | // normal comment | |
| 9 | ||
| 10 | /// this is a documentation comment | |
| 11 | /// doc comment line 2 | |
| 12 | fn emptyFunctionWithComments() void {} | |
| 13 | ||
| 14 | test "empty function with comments" { | |
| 15 | emptyFunctionWithComments(); | |
| 16 | } | |
| 17 | ||
| 18 | comptime { | |
| 19 | @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal); | |
| 20 | } | |
| 21 | ||
| 22 | extern fn disabledExternFn() void {} | |
| 23 | ||
| 24 | test "call disabled extern fn" { | |
| 25 | disabledExternFn(); | |
| 26 | } | |
| 27 | ||
| 28 | test "@IntType builtin" { | |
| 29 | assert(@IntType(true, 8) == i8); | |
| 30 | assert(@IntType(true, 16) == i16); | |
| 31 | assert(@IntType(true, 32) == i32); | |
| 32 | assert(@IntType(true, 64) == i64); | |
| 33 | ||
| 34 | assert(@IntType(false, 8) == u8); | |
| 35 | assert(@IntType(false, 16) == u16); | |
| 36 | assert(@IntType(false, 32) == u32); | |
| 37 | assert(@IntType(false, 64) == u64); | |
| 38 | ||
| 39 | assert(i8.bit_count == 8); | |
| 40 | assert(i16.bit_count == 16); | |
| 41 | assert(i32.bit_count == 32); | |
| 42 | assert(i64.bit_count == 64); | |
| 43 | ||
| 44 | assert(i8.is_signed); | |
| 45 | assert(i16.is_signed); | |
| 46 | assert(i32.is_signed); | |
| 47 | assert(i64.is_signed); | |
| 48 | assert(isize.is_signed); | |
| 49 | ||
| 50 | assert(!u8.is_signed); | |
| 51 | assert(!u16.is_signed); | |
| 52 | assert(!u32.is_signed); | |
| 53 | assert(!u64.is_signed); | |
| 54 | assert(!usize.is_signed); | |
| 55 | } | |
| 56 | ||
| 57 | test "floating point primitive bit counts" { | |
| 58 | assert(f16.bit_count == 16); | |
| 59 | assert(f32.bit_count == 32); | |
| 60 | assert(f64.bit_count == 64); | |
| 61 | } | |
| 62 | ||
| 63 | test "short circuit" { | |
| 64 | testShortCircuit(false, true); | |
| 65 | comptime testShortCircuit(false, true); | |
| 66 | } | |
| 67 | ||
| 68 | fn testShortCircuit(f: bool, t: bool) void { | |
| 69 | var hit_1 = f; | |
| 70 | var hit_2 = f; | |
| 71 | var hit_3 = f; | |
| 72 | var hit_4 = f; | |
| 73 | ||
| 74 | if (t or x: { | |
| 75 | assert(f); | |
| 76 | break :x f; | |
| 77 | }) { | |
| 78 | hit_1 = t; | |
| 79 | } | |
| 80 | if (f or x: { | |
| 81 | hit_2 = t; | |
| 82 | break :x f; | |
| 83 | }) { | |
| 84 | assert(f); | |
| 85 | } | |
| 86 | ||
| 87 | if (t and x: { | |
| 88 | hit_3 = t; | |
| 89 | break :x f; | |
| 90 | }) { | |
| 91 | assert(f); | |
| 92 | } | |
| 93 | if (f and x: { | |
| 94 | assert(f); | |
| 95 | break :x f; | |
| 96 | }) { | |
| 97 | assert(f); | |
| 98 | } else { | |
| 99 | hit_4 = t; | |
| 100 | } | |
| 101 | assert(hit_1); | |
| 102 | assert(hit_2); | |
| 103 | assert(hit_3); | |
| 104 | assert(hit_4); | |
| 105 | } | |
| 106 | ||
| 107 | test "truncate" { | |
| 108 | assert(testTruncate(0x10fd) == 0xfd); | |
| 109 | } | |
| 110 | fn testTruncate(x: u32) u8 { | |
| 111 | return @truncate(u8, x); | |
| 112 | } | |
| 113 | ||
| 114 | fn first4KeysOfHomeRow() []const u8 { | |
| 115 | return "aoeu"; | |
| 116 | } | |
| 117 | ||
| 118 | test "return string from function" { | |
| 119 | assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); | |
| 120 | } | |
| 121 | ||
| 122 | const g1: i32 = 1233 + 1; | |
| 123 | var g2: i32 = 0; | |
| 124 | ||
| 125 | test "global variables" { | |
| 126 | assert(g2 == 0); | |
| 127 | g2 = g1; | |
| 128 | assert(g2 == 1234); | |
| 129 | } | |
| 130 | ||
| 131 | test "memcpy and memset intrinsics" { | |
| 132 | var foo: [20]u8 = undefined; | |
| 133 | var bar: [20]u8 = undefined; | |
| 134 | ||
| 135 | @memset(foo[0..].ptr, 'A', foo.len); | |
| 136 | @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len); | |
| 137 | ||
| 138 | if (bar[11] != 'A') unreachable; | |
| 139 | } | |
| 140 | ||
| 141 | test "builtin static eval" { | |
| 142 | const x: i32 = comptime x: { | |
| 143 | break :x 1 + 2 + 3; | |
| 144 | }; | |
| 145 | assert(x == comptime 6); | |
| 146 | } | |
| 147 | ||
| 148 | test "slicing" { | |
| 149 | var array: [20]i32 = undefined; | |
| 150 | ||
| 151 | array[5] = 1234; | |
| 152 | ||
| 153 | var slice = array[5..10]; | |
| 154 | ||
| 155 | if (slice.len != 5) unreachable; | |
| 156 | ||
| 157 | const ptr = &slice[0]; | |
| 158 | if (ptr.* != 1234) unreachable; | |
| 159 | ||
| 160 | var slice_rest = array[10..]; | |
| 161 | if (slice_rest.len != 10) unreachable; | |
| 162 | } | |
| 163 | ||
| 164 | test "constant equal function pointers" { | |
| 165 | const alias = emptyFn; | |
| 166 | assert(comptime x: { | |
| 167 | break :x emptyFn == alias; | |
| 168 | }); | |
| 169 | } | |
| 170 | ||
| 171 | fn emptyFn() void {} | |
| 172 | ||
| 173 | test "hex escape" { | |
| 174 | assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); | |
| 175 | } | |
| 176 | ||
| 177 | test "string concatenation" { | |
| 178 | assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); | |
| 179 | } | |
| 180 | ||
| 181 | test "array mult operator" { | |
| 182 | assert(mem.eql(u8, "ab" ** 5, "ababababab")); | |
| 183 | } | |
| 184 | ||
| 185 | test "string escapes" { | |
| 186 | assert(mem.eql(u8, "\"", "\x22")); | |
| 187 | assert(mem.eql(u8, "\'", "\x27")); | |
| 188 | assert(mem.eql(u8, "\n", "\x0a")); | |
| 189 | assert(mem.eql(u8, "\r", "\x0d")); | |
| 190 | assert(mem.eql(u8, "\t", "\x09")); | |
| 191 | assert(mem.eql(u8, "\\", "\x5c")); | |
| 192 | assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69")); | |
| 193 | } | |
| 194 | ||
| 195 | test "multiline string" { | |
| 196 | const s1 = | |
| 197 | \\one | |
| 198 | \\two) | |
| 199 | \\three | |
| 200 | ; | |
| 201 | const s2 = "one\ntwo)\nthree"; | |
| 202 | assert(mem.eql(u8, s1, s2)); | |
| 203 | } | |
| 204 | ||
| 205 | test "multiline C string" { | |
| 206 | const s1 = | |
| 207 | c\\one | |
| 208 | c\\two) | |
| 209 | c\\three | |
| 210 | ; | |
| 211 | const s2 = c"one\ntwo)\nthree"; | |
| 212 | assert(cstr.cmp(s1, s2) == 0); | |
| 213 | } | |
| 214 | ||
| 215 | test "type equality" { | |
| 216 | assert(*const u8 != *u8); | |
| 217 | } | |
| 218 | ||
| 219 | const global_a: i32 = 1234; | |
| 220 | const global_b: *const i32 = &global_a; | |
| 221 | const global_c: *const f32 = @ptrCast(*const f32, global_b); | |
| 222 | test "compile time global reinterpret" { | |
| 223 | const d = @ptrCast(*const i32, global_c); | |
| 224 | assert(d.* == 1234); | |
| 225 | } | |
| 226 | ||
| 227 | test "explicit cast maybe pointers" { | |
| 228 | const a: ?*i32 = undefined; | |
| 229 | const b: ?*f32 = @ptrCast(?*f32, a); | |
| 230 | } | |
| 231 | ||
| 232 | test "generic malloc free" { | |
| 233 | const a = memAlloc(u8, 10) catch unreachable; | |
| 234 | memFree(u8, a); | |
| 235 | } | |
| 236 | var some_mem: [100]u8 = undefined; | |
| 237 | fn memAlloc(comptime T: type, n: usize) anyerror![]T { | |
| 238 | return @ptrCast([*]T, &some_mem[0])[0..n]; | |
| 239 | } | |
| 240 | fn memFree(comptime T: type, memory: []T) void {} | |
| 241 | ||
| 242 | test "cast undefined" { | |
| 243 | const array: [100]u8 = undefined; | |
| 244 | const slice = ([]const u8)(array); | |
| 245 | testCastUndefined(slice); | |
| 246 | } | |
| 247 | fn testCastUndefined(x: []const u8) void {} | |
| 248 | ||
| 249 | test "cast small unsigned to larger signed" { | |
| 250 | assert(castSmallUnsignedToLargerSigned1(200) == i16(200)); | |
| 251 | assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); | |
| 252 | } | |
| 253 | fn castSmallUnsignedToLargerSigned1(x: u8) i16 { | |
| 254 | return x; | |
| 255 | } | |
| 256 | fn castSmallUnsignedToLargerSigned2(x: u16) i64 { | |
| 257 | return x; | |
| 258 | } | |
| 259 | ||
| 260 | test "implicit cast after unreachable" { | |
| 261 | assert(outer() == 1234); | |
| 262 | } | |
| 263 | fn inner() i32 { | |
| 264 | return 1234; | |
| 265 | } | |
| 266 | fn outer() i64 { | |
| 267 | return inner(); | |
| 268 | } | |
| 269 | ||
| 270 | test "pointer dereferencing" { | |
| 271 | var x = i32(3); | |
| 272 | const y = &x; | |
| 273 | ||
| 274 | y.* += 1; | |
| 275 | ||
| 276 | assert(x == 4); | |
| 277 | assert(y.* == 4); | |
| 278 | } | |
| 279 | ||
| 280 | test "call result of if else expression" { | |
| 281 | assert(mem.eql(u8, f2(true), "a")); | |
| 282 | assert(mem.eql(u8, f2(false), "b")); | |
| 283 | } | |
| 284 | fn f2(x: bool) []const u8 { | |
| 285 | return (if (x) fA else fB)(); | |
| 286 | } | |
| 287 | fn fA() []const u8 { | |
| 288 | return "a"; | |
| 289 | } | |
| 290 | fn fB() []const u8 { | |
| 291 | return "b"; | |
| 292 | } | |
| 293 | ||
| 294 | test "const expression eval handling of variables" { | |
| 295 | var x = true; | |
| 296 | while (x) { | |
| 297 | x = false; | |
| 298 | } | |
| 299 | } | |
| 300 | ||
| 301 | test "constant enum initialization with differing sizes" { | |
| 302 | test3_1(test3_foo); | |
| 303 | test3_2(test3_bar); | |
| 304 | } | |
| 305 | const Test3Foo = union(enum) { | |
| 306 | One: void, | |
| 307 | Two: f32, | |
| 308 | Three: Test3Point, | |
| 309 | }; | |
| 310 | const Test3Point = struct { | |
| 311 | x: i32, | |
| 312 | y: i32, | |
| 313 | }; | |
| 314 | const test3_foo = Test3Foo{ | |
| 315 | .Three = Test3Point{ | |
| 316 | .x = 3, | |
| 317 | .y = 4, | |
| 318 | }, | |
| 319 | }; | |
| 320 | const test3_bar = Test3Foo{ .Two = 13 }; | |
| 321 | fn test3_1(f: Test3Foo) void { | |
| 322 | switch (f) { | |
| 323 | Test3Foo.Three => |pt| { | |
| 324 | assert(pt.x == 3); | |
| 325 | assert(pt.y == 4); | |
| 326 | }, | |
| 327 | else => unreachable, | |
| 328 | } | |
| 329 | } | |
| 330 | fn test3_2(f: Test3Foo) void { | |
| 331 | switch (f) { | |
| 332 | Test3Foo.Two => |x| { | |
| 333 | assert(x == 13); | |
| 334 | }, | |
| 335 | else => unreachable, | |
| 336 | } | |
| 337 | } | |
| 338 | ||
| 339 | test "character literals" { | |
| 340 | assert('\'' == single_quote); | |
| 341 | } | |
| 342 | const single_quote = '\''; | |
| 343 | ||
| 344 | test "take address of parameter" { | |
| 345 | testTakeAddressOfParameter(12.34); | |
| 346 | } | |
| 347 | fn testTakeAddressOfParameter(f: f32) void { | |
| 348 | const f_ptr = &f; | |
| 349 | assert(f_ptr.* == 12.34); | |
| 350 | } | |
| 351 | ||
| 352 | test "pointer comparison" { | |
| 353 | const a = ([]const u8)("a"); | |
| 354 | const b = &a; | |
| 355 | assert(ptrEql(b, b)); | |
| 356 | } | |
| 357 | fn ptrEql(a: *const []const u8, b: *const []const u8) bool { | |
| 358 | return a == b; | |
| 359 | } | |
| 360 | ||
| 361 | test "C string concatenation" { | |
| 362 | const a = c"OK" ++ c" IT " ++ c"WORKED"; | |
| 363 | const b = c"OK IT WORKED"; | |
| 364 | ||
| 365 | const len = cstr.len(b); | |
| 366 | const len_with_null = len + 1; | |
| 367 | { | |
| 368 | var i: u32 = 0; | |
| 369 | while (i < len_with_null) : (i += 1) { | |
| 370 | assert(a[i] == b[i]); | |
| 371 | } | |
| 372 | } | |
| 373 | assert(a[len] == 0); | |
| 374 | assert(b[len] == 0); | |
| 375 | } | |
| 376 | ||
| 377 | test "cast slice to u8 slice" { | |
| 378 | assert(@sizeOf(i32) == 4); | |
| 379 | var big_thing_array = []i32{ | |
| 380 | 1, | |
| 381 | 2, | |
| 382 | 3, | |
| 383 | 4, | |
| 384 | }; | |
| 385 | const big_thing_slice: []i32 = big_thing_array[0..]; | |
| 386 | const bytes = @sliceToBytes(big_thing_slice); | |
| 387 | assert(bytes.len == 4 * 4); | |
| 388 | bytes[4] = 0; | |
| 389 | bytes[5] = 0; | |
| 390 | bytes[6] = 0; | |
| 391 | bytes[7] = 0; | |
| 392 | assert(big_thing_slice[1] == 0); | |
| 393 | const big_thing_again = @bytesToSlice(i32, bytes); | |
| 394 | assert(big_thing_again[2] == 3); | |
| 395 | big_thing_again[2] = -1; | |
| 396 | assert(bytes[8] == maxInt(u8)); | |
| 397 | assert(bytes[9] == maxInt(u8)); | |
| 398 | assert(bytes[10] == maxInt(u8)); | |
| 399 | assert(bytes[11] == maxInt(u8)); | |
| 400 | } | |
| 401 | ||
| 402 | test "pointer to void return type" { | |
| 403 | testPointerToVoidReturnType() catch unreachable; | |
| 404 | } | |
| 405 | fn testPointerToVoidReturnType() anyerror!void { | |
| 406 | const a = testPointerToVoidReturnType2(); | |
| 407 | return a.*; | |
| 408 | } | |
| 409 | const test_pointer_to_void_return_type_x = void{}; | |
| 410 | fn testPointerToVoidReturnType2() *const void { | |
| 411 | return &test_pointer_to_void_return_type_x; | |
| 412 | } | |
| 413 | ||
| 414 | test "non const ptr to aliased type" { | |
| 415 | const int = i32; | |
| 416 | assert(?*int == ?*i32); | |
| 417 | } | |
| 418 | ||
| 419 | test "array 2D const double ptr" { | |
| 420 | const rect_2d_vertexes = [][1]f32{ | |
| 421 | []f32{1.0}, | |
| 422 | []f32{2.0}, | |
| 423 | }; | |
| 424 | testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); | |
| 425 | } | |
| 426 | ||
| 427 | fn testArray2DConstDoublePtr(ptr: *const f32) void { | |
| 428 | const ptr2 = @ptrCast([*]const f32, ptr); | |
| 429 | assert(ptr2[0] == 1.0); | |
| 430 | assert(ptr2[1] == 2.0); | |
| 431 | } | |
| 432 | ||
| 433 | const Tid = builtin.TypeId; | |
| 434 | const AStruct = struct { | |
| 435 | x: i32, | |
| 436 | }; | |
| 437 | const AnEnum = enum { | |
| 438 | One, | |
| 439 | Two, | |
| 440 | }; | |
| 441 | const AUnionEnum = union(enum) { | |
| 442 | One: i32, | |
| 443 | Two: void, | |
| 444 | }; | |
| 445 | const AUnion = union { | |
| 446 | One: void, | |
| 447 | Two: void, | |
| 448 | }; | |
| 449 | ||
| 450 | test "@typeId" { | |
| 451 | comptime { | |
| 452 | assert(@typeId(type) == Tid.Type); | |
| 453 | assert(@typeId(void) == Tid.Void); | |
| 454 | assert(@typeId(bool) == Tid.Bool); | |
| 455 | assert(@typeId(noreturn) == Tid.NoReturn); | |
| 456 | assert(@typeId(i8) == Tid.Int); | |
| 457 | assert(@typeId(u8) == Tid.Int); | |
| 458 | assert(@typeId(i64) == Tid.Int); | |
| 459 | assert(@typeId(u64) == Tid.Int); | |
| 460 | assert(@typeId(f32) == Tid.Float); | |
| 461 | assert(@typeId(f64) == Tid.Float); | |
| 462 | assert(@typeId(*f32) == Tid.Pointer); | |
| 463 | assert(@typeId([2]u8) == Tid.Array); | |
| 464 | assert(@typeId(AStruct) == Tid.Struct); | |
| 465 | assert(@typeId(@typeOf(1)) == Tid.ComptimeInt); | |
| 466 | assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat); | |
| 467 | assert(@typeId(@typeOf(undefined)) == Tid.Undefined); | |
| 468 | assert(@typeId(@typeOf(null)) == Tid.Null); | |
| 469 | assert(@typeId(?i32) == Tid.Optional); | |
| 470 | assert(@typeId(anyerror!i32) == Tid.ErrorUnion); | |
| 471 | assert(@typeId(anyerror) == Tid.ErrorSet); | |
| 472 | assert(@typeId(AnEnum) == Tid.Enum); | |
| 473 | assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); | |
| 474 | assert(@typeId(AUnionEnum) == Tid.Union); | |
| 475 | assert(@typeId(AUnion) == Tid.Union); | |
| 476 | assert(@typeId(fn () void) == Tid.Fn); | |
| 477 | assert(@typeId(@typeOf(builtin)) == Tid.Namespace); | |
| 478 | // TODO bound fn | |
| 479 | // TODO arg tuple | |
| 480 | // TODO opaque | |
| 481 | } | |
| 482 | } | |
| 483 | ||
| 484 | test "@typeName" { | |
| 485 | const Struct = struct {}; | |
| 486 | const Union = union { | |
| 487 | unused: u8, | |
| 488 | }; | |
| 489 | const Enum = enum { | |
| 490 | Unused, | |
| 491 | }; | |
| 492 | comptime { | |
| 493 | assert(mem.eql(u8, @typeName(i64), "i64")); | |
| 494 | assert(mem.eql(u8, @typeName(*usize), "*usize")); | |
| 495 | // https://github.com/ziglang/zig/issues/675 | |
| 496 | assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)")); | |
| 497 | assert(mem.eql(u8, @typeName(Struct), "Struct")); | |
| 498 | assert(mem.eql(u8, @typeName(Union), "Union")); | |
| 499 | assert(mem.eql(u8, @typeName(Enum), "Enum")); | |
| 500 | } | |
| 501 | } | |
| 502 | ||
| 503 | fn TypeFromFn(comptime T: type) type { | |
| 504 | return struct {}; | |
| 505 | } | |
| 506 | ||
| 507 | test "volatile load and store" { | |
| 508 | var number: i32 = 1234; | |
| 509 | const ptr = (*volatile i32)(&number); | |
| 510 | ptr.* += 1; | |
| 511 | assert(ptr.* == 1235); | |
| 512 | } | |
| 513 | ||
| 514 | test "slice string literal has type []const u8" { | |
| 515 | comptime { | |
| 516 | assert(@typeOf("aoeu"[0..]) == []const u8); | |
| 517 | const array = []i32{ | |
| 518 | 1, | |
| 519 | 2, | |
| 520 | 3, | |
| 521 | 4, | |
| 522 | }; | |
| 523 | assert(@typeOf(array[0..]) == []const i32); | |
| 524 | } | |
| 525 | } | |
| 526 | ||
| 527 | test "global variable initialized to global variable array element" { | |
| 528 | assert(global_ptr == &gdt[0]); | |
| 529 | } | |
| 530 | const GDTEntry = struct { | |
| 531 | field: i32, | |
| 532 | }; | |
| 533 | var gdt = []GDTEntry{ | |
| 534 | GDTEntry{ .field = 1 }, | |
| 535 | GDTEntry{ .field = 2 }, | |
| 536 | }; | |
| 537 | var global_ptr = &gdt[0]; | |
| 538 | ||
| 539 | // can't really run this test but we can make sure it has no compile error | |
| 540 | // and generates code | |
| 541 | const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000]; | |
| 542 | export fn writeToVRam() void { | |
| 543 | vram[0] = 'X'; | |
| 544 | } | |
| 545 | ||
| 546 | test "pointer child field" { | |
| 547 | assert((*u32).Child == u32); | |
| 548 | } | |
| 549 | ||
| 550 | const OpaqueA = @OpaqueType(); | |
| 551 | const OpaqueB = @OpaqueType(); | |
| 552 | test "@OpaqueType" { | |
| 553 | assert(*OpaqueA != *OpaqueB); | |
| 554 | assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA")); | |
| 555 | assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB")); | |
| 556 | } | |
| 557 | ||
| 558 | test "variable is allowed to be a pointer to an opaque type" { | |
| 559 | var x: i32 = 1234; | |
| 560 | _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x)); | |
| 561 | } | |
| 562 | fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA { | |
| 563 | var a = ptr; | |
| 564 | return a; | |
| 565 | } | |
| 566 | ||
| 567 | test "comptime if inside runtime while which unconditionally breaks" { | |
| 568 | testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | |
| 569 | comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | |
| 570 | } | |
| 571 | fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { | |
| 572 | while (cond) { | |
| 573 | if (false) {} | |
| 574 | break; | |
| 575 | } | |
| 576 | } | |
| 577 | ||
| 578 | test "implicit comptime while" { | |
| 579 | while (false) { | |
| 580 | @compileError("bad"); | |
| 581 | } | |
| 582 | } | |
| 583 | ||
| 584 | test "struct inside function" { | |
| 585 | testStructInFn(); | |
| 586 | comptime testStructInFn(); | |
| 587 | } | |
| 588 | ||
| 589 | fn testStructInFn() void { | |
| 590 | const BlockKind = u32; | |
| 591 | ||
| 592 | const Block = struct { | |
| 593 | kind: BlockKind, | |
| 594 | }; | |
| 595 | ||
| 596 | var block = Block{ .kind = 1234 }; | |
| 597 | ||
| 598 | block.kind += 1; | |
| 599 | ||
| 600 | assert(block.kind == 1235); | |
| 601 | } | |
| 602 | ||
| 603 | fn fnThatClosesOverLocalConst() type { | |
| 604 | const c = 1; | |
| 605 | return struct { | |
| 606 | fn g() i32 { | |
| 607 | return c; | |
| 608 | } | |
| 609 | }; | |
| 610 | } | |
| 611 | ||
| 612 | test "function closes over local const" { | |
| 613 | const x = fnThatClosesOverLocalConst().g(); | |
| 614 | assert(x == 1); | |
| 615 | } | |
| 616 | ||
| 617 | test "cold function" { | |
| 618 | thisIsAColdFn(); | |
| 619 | comptime thisIsAColdFn(); | |
| 620 | } | |
| 621 | ||
| 622 | fn thisIsAColdFn() void { | |
| 623 | @setCold(true); | |
| 624 | } | |
| 625 | ||
| 626 | const PackedStruct = packed struct { | |
| 627 | a: u8, | |
| 628 | b: u8, | |
| 629 | }; | |
| 630 | const PackedUnion = packed union { | |
| 631 | a: u8, | |
| 632 | b: u32, | |
| 633 | }; | |
| 634 | const PackedEnum = packed enum { | |
| 635 | A, | |
| 636 | B, | |
| 637 | }; | |
| 638 | ||
| 639 | test "packed struct, enum, union parameters in extern function" { | |
| 640 | testPackedStuff(&(PackedStruct{ | |
| 641 | .a = 1, | |
| 642 | .b = 2, | |
| 643 | }), &(PackedUnion{ .a = 1 }), PackedEnum.A); | |
| 644 | } | |
| 645 | ||
| 646 | export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {} | |
| 647 | ||
| 648 | test "slicing zero length array" { | |
| 649 | const s1 = ""[0..]; | |
| 650 | const s2 = ([]u32{})[0..]; | |
| 651 | assert(s1.len == 0); | |
| 652 | assert(s2.len == 0); | |
| 653 | assert(mem.eql(u8, s1, "")); | |
| 654 | assert(mem.eql(u32, s2, []u32{})); | |
| 655 | } | |
| 656 | ||
| 657 | const addr1 = @ptrCast(*const u8, emptyFn); | |
| 658 | test "comptime cast fn to ptr" { | |
| 659 | const addr2 = @ptrCast(*const u8, emptyFn); | |
| 660 | comptime assert(addr1 == addr2); | |
| 661 | } | |
| 662 | ||
| 663 | test "equality compare fn ptrs" { | |
| 664 | var a = emptyFn; | |
| 665 | assert(a == a); | |
| 666 | } | |
| 667 | ||
| 668 | test "self reference through fn ptr field" { | |
| 669 | const S = struct { | |
| 670 | const A = struct { | |
| 671 | f: fn (A) u8, | |
| 672 | }; | |
| 673 | ||
| 674 | fn foo(a: A) u8 { | |
| 675 | return 12; | |
| 676 | } | |
| 677 | }; | |
| 678 | var a: S.A = undefined; | |
| 679 | a.f = S.foo; | |
| 680 | assert(a.f(a) == 12); | |
| 681 | } |
test/cases/namespace_depends_on_compile_var/a.zig deleted-1| ... | ... | @@ -1 +0,0 @@ |
| 1 | pub const a_bool = true; |
test/cases/namespace_depends_on_compile_var/b.zig deleted-1| ... | ... | @@ -1 +0,0 @@ |
| 1 | pub const a_bool = false; |
test/cases/namespace_depends_on_compile_var/index.zig deleted-14| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const assert = @import("std").debug.assert; | |
| 3 | ||
| 4 | test "namespace depends on compile var" { | |
| 5 | if (some_namespace.a_bool) { | |
| 6 | assert(some_namespace.a_bool); | |
| 7 | } else { | |
| 8 | assert(!some_namespace.a_bool); | |
| 9 | } | |
| 10 | } | |
| 11 | const some_namespace = switch (builtin.os) { | |
| 12 | builtin.Os.linux => @import("a.zig"), | |
| 13 | else => @import("b.zig"), | |
| 14 | }; |
test/cases/new_stack_call.zig deleted-26| ... | ... | @@ -1,26 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | ||
| 4 | var new_stack_bytes: [1024]u8 = undefined; | |
| 5 | ||
| 6 | test "calling a function with a new stack" { | |
| 7 | const arg = 1234; | |
| 8 | ||
| 9 | const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg); | |
| 10 | const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg); | |
| 11 | _ = targetFunction(arg); | |
| 12 | ||
| 13 | assert(arg == 1234); | |
| 14 | assert(a < b); | |
| 15 | } | |
| 16 | ||
| 17 | fn targetFunction(x: i32) usize { | |
| 18 | assert(x == 1234); | |
| 19 | ||
| 20 | var local_variable: i32 = 42; | |
| 21 | const ptr = &local_variable; | |
| 22 | ptr.* += 1; | |
| 23 | ||
| 24 | assert(local_variable == 43); | |
| 25 | return @ptrToInt(ptr); | |
| 26 | } |
test/cases/null.zig deleted-162| ... | ... | @@ -1,162 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "optional type" { | |
| 4 | const x: ?bool = true; | |
| 5 | ||
| 6 | if (x) |y| { | |
| 7 | if (y) { | |
| 8 | // OK | |
| 9 | } else { | |
| 10 | unreachable; | |
| 11 | } | |
| 12 | } else { | |
| 13 | unreachable; | |
| 14 | } | |
| 15 | ||
| 16 | const next_x: ?i32 = null; | |
| 17 | ||
| 18 | const z = next_x orelse 1234; | |
| 19 | ||
| 20 | assert(z == 1234); | |
| 21 | ||
| 22 | const final_x: ?i32 = 13; | |
| 23 | ||
| 24 | const num = final_x orelse unreachable; | |
| 25 | ||
| 26 | assert(num == 13); | |
| 27 | } | |
| 28 | ||
| 29 | test "test maybe object and get a pointer to the inner value" { | |
| 30 | var maybe_bool: ?bool = true; | |
| 31 | ||
| 32 | if (maybe_bool) |*b| { | |
| 33 | b.* = false; | |
| 34 | } | |
| 35 | ||
| 36 | assert(maybe_bool.? == false); | |
| 37 | } | |
| 38 | ||
| 39 | test "rhs maybe unwrap return" { | |
| 40 | const x: ?bool = true; | |
| 41 | const y = x orelse return; | |
| 42 | } | |
| 43 | ||
| 44 | test "maybe return" { | |
| 45 | maybeReturnImpl(); | |
| 46 | comptime maybeReturnImpl(); | |
| 47 | } | |
| 48 | ||
| 49 | fn maybeReturnImpl() void { | |
| 50 | assert(foo(1235).?); | |
| 51 | if (foo(null) != null) unreachable; | |
| 52 | assert(!foo(1234).?); | |
| 53 | } | |
| 54 | ||
| 55 | fn foo(x: ?i32) ?bool { | |
| 56 | const value = x orelse return null; | |
| 57 | return value > 1234; | |
| 58 | } | |
| 59 | ||
| 60 | test "if var maybe pointer" { | |
| 61 | assert(shouldBeAPlus1(Particle{ | |
| 62 | .a = 14, | |
| 63 | .b = 1, | |
| 64 | .c = 1, | |
| 65 | .d = 1, | |
| 66 | }) == 15); | |
| 67 | } | |
| 68 | fn shouldBeAPlus1(p: Particle) u64 { | |
| 69 | var maybe_particle: ?Particle = p; | |
| 70 | if (maybe_particle) |*particle| { | |
| 71 | particle.a += 1; | |
| 72 | } | |
| 73 | if (maybe_particle) |particle| { | |
| 74 | return particle.a; | |
| 75 | } | |
| 76 | return 0; | |
| 77 | } | |
| 78 | const Particle = struct { | |
| 79 | a: u64, | |
| 80 | b: u64, | |
| 81 | c: u64, | |
| 82 | d: u64, | |
| 83 | }; | |
| 84 | ||
| 85 | test "null literal outside function" { | |
| 86 | const is_null = here_is_a_null_literal.context == null; | |
| 87 | assert(is_null); | |
| 88 | ||
| 89 | const is_non_null = here_is_a_null_literal.context != null; | |
| 90 | assert(!is_non_null); | |
| 91 | } | |
| 92 | const SillyStruct = struct { | |
| 93 | context: ?i32, | |
| 94 | }; | |
| 95 | const here_is_a_null_literal = SillyStruct{ .context = null }; | |
| 96 | ||
| 97 | test "test null runtime" { | |
| 98 | testTestNullRuntime(null); | |
| 99 | } | |
| 100 | fn testTestNullRuntime(x: ?i32) void { | |
| 101 | assert(x == null); | |
| 102 | assert(!(x != null)); | |
| 103 | } | |
| 104 | ||
| 105 | test "optional void" { | |
| 106 | optionalVoidImpl(); | |
| 107 | comptime optionalVoidImpl(); | |
| 108 | } | |
| 109 | ||
| 110 | fn optionalVoidImpl() void { | |
| 111 | assert(bar(null) == null); | |
| 112 | assert(bar({}) != null); | |
| 113 | } | |
| 114 | ||
| 115 | fn bar(x: ?void) ?void { | |
| 116 | if (x) |_| { | |
| 117 | return {}; | |
| 118 | } else { | |
| 119 | return null; | |
| 120 | } | |
| 121 | } | |
| 122 | ||
| 123 | const StructWithOptional = struct { | |
| 124 | field: ?i32, | |
| 125 | }; | |
| 126 | ||
| 127 | var struct_with_optional: StructWithOptional = undefined; | |
| 128 | ||
| 129 | test "unwrap optional which is field of global var" { | |
| 130 | struct_with_optional.field = null; | |
| 131 | if (struct_with_optional.field) |payload| { | |
| 132 | unreachable; | |
| 133 | } | |
| 134 | struct_with_optional.field = 1234; | |
| 135 | if (struct_with_optional.field) |payload| { | |
| 136 | assert(payload == 1234); | |
| 137 | } else { | |
| 138 | unreachable; | |
| 139 | } | |
| 140 | } | |
| 141 | ||
| 142 | test "null with default unwrap" { | |
| 143 | const x: i32 = null orelse 1; | |
| 144 | assert(x == 1); | |
| 145 | } | |
| 146 | ||
| 147 | test "optional types" { | |
| 148 | comptime { | |
| 149 | const opt_type_struct = StructWithOptionalType{ .t = u8 }; | |
| 150 | assert(opt_type_struct.t != null and opt_type_struct.t.? == u8); | |
| 151 | } | |
| 152 | } | |
| 153 | ||
| 154 | const StructWithOptionalType = struct { | |
| 155 | t: ?type, | |
| 156 | }; | |
| 157 | ||
| 158 | test "optional pointer to 0 bit type null value at runtime" { | |
| 159 | const EmptyStruct = struct {}; | |
| 160 | var x: ?*EmptyStruct = null; | |
| 161 | assert(x == null); | |
| 162 | } |
test/cases/optional.zig deleted-30| ... | ... | @@ -1,30 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | pub const EmptyStruct = struct {}; | |
| 4 | ||
| 5 | test "optional pointer to size zero struct" { | |
| 6 | var e = EmptyStruct{}; | |
| 7 | var o: ?*EmptyStruct = &e; | |
| 8 | assert(o != null); | |
| 9 | } | |
| 10 | ||
| 11 | test "equality compare nullable pointers" { | |
| 12 | testNullPtrsEql(); | |
| 13 | comptime testNullPtrsEql(); | |
| 14 | } | |
| 15 | ||
| 16 | fn testNullPtrsEql() void { | |
| 17 | var number: i32 = 1234; | |
| 18 | ||
| 19 | var x: ?*i32 = null; | |
| 20 | var y: ?*i32 = null; | |
| 21 | assert(x == y); | |
| 22 | y = &number; | |
| 23 | assert(x != y); | |
| 24 | assert(x != &number); | |
| 25 | assert(&number != x); | |
| 26 | x = &number; | |
| 27 | assert(x == y); | |
| 28 | assert(x == &number); | |
| 29 | assert(&number == x); | |
| 30 | } |
test/cases/pointers.zig deleted-44| ... | ... | @@ -1,44 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | ||
| 4 | test "dereference pointer" { | |
| 5 | comptime testDerefPtr(); | |
| 6 | testDerefPtr(); | |
| 7 | } | |
| 8 | ||
| 9 | fn testDerefPtr() void { | |
| 10 | var x: i32 = 1234; | |
| 11 | var y = &x; | |
| 12 | y.* += 1; | |
| 13 | assert(x == 1235); | |
| 14 | } | |
| 15 | ||
| 16 | test "pointer arithmetic" { | |
| 17 | var ptr = c"abcd"; | |
| 18 | ||
| 19 | assert(ptr[0] == 'a'); | |
| 20 | ptr += 1; | |
| 21 | assert(ptr[0] == 'b'); | |
| 22 | ptr += 1; | |
| 23 | assert(ptr[0] == 'c'); | |
| 24 | ptr += 1; | |
| 25 | assert(ptr[0] == 'd'); | |
| 26 | ptr += 1; | |
| 27 | assert(ptr[0] == 0); | |
| 28 | ptr -= 1; | |
| 29 | assert(ptr[0] == 'd'); | |
| 30 | ptr -= 1; | |
| 31 | assert(ptr[0] == 'c'); | |
| 32 | ptr -= 1; | |
| 33 | assert(ptr[0] == 'b'); | |
| 34 | ptr -= 1; | |
| 35 | assert(ptr[0] == 'a'); | |
| 36 | } | |
| 37 | ||
| 38 | test "double pointer parsing" { | |
| 39 | comptime assert(PtrOf(PtrOf(i32)) == **i32); | |
| 40 | } | |
| 41 | ||
| 42 | fn PtrOf(comptime T: type) type { | |
| 43 | return *T; | |
| 44 | } |
test/cases/popcount.zig deleted-24| ... | ... | @@ -1,24 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "@popCount" { | |
| 4 | comptime testPopCount(); | |
| 5 | testPopCount(); | |
| 6 | } | |
| 7 | ||
| 8 | fn testPopCount() void { | |
| 9 | { | |
| 10 | var x: u32 = 0xaa; | |
| 11 | assert(@popCount(x) == 4); | |
| 12 | } | |
| 13 | { | |
| 14 | var x: u32 = 0xaaaaaaaa; | |
| 15 | assert(@popCount(x) == 16); | |
| 16 | } | |
| 17 | { | |
| 18 | var x: i16 = -1; | |
| 19 | assert(@popCount(x) == 16); | |
| 20 | } | |
| 21 | comptime { | |
| 22 | assert(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24); | |
| 23 | } | |
| 24 | } |
test/cases/ptrcast.zig deleted-52| ... | ... | @@ -1,52 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std"); | |
| 3 | const assertOrPanic = std.debug.assertOrPanic; | |
| 4 | ||
| 5 | test "reinterpret bytes as integer with nonzero offset" { | |
| 6 | testReinterpretBytesAsInteger(); | |
| 7 | comptime testReinterpretBytesAsInteger(); | |
| 8 | } | |
| 9 | ||
| 10 | fn testReinterpretBytesAsInteger() void { | |
| 11 | const bytes = "\x12\x34\x56\x78\xab"; | |
| 12 | const expected = switch (builtin.endian) { | |
| 13 | builtin.Endian.Little => 0xab785634, | |
| 14 | builtin.Endian.Big => 0x345678ab, | |
| 15 | }; | |
| 16 | assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected); | |
| 17 | } | |
| 18 | ||
| 19 | test "reinterpret bytes of an array into an extern struct" { | |
| 20 | testReinterpretBytesAsExternStruct(); | |
| 21 | comptime testReinterpretBytesAsExternStruct(); | |
| 22 | } | |
| 23 | ||
| 24 | fn testReinterpretBytesAsExternStruct() void { | |
| 25 | var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 }; | |
| 26 | ||
| 27 | const S = extern struct { | |
| 28 | a: u8, | |
| 29 | b: u16, | |
| 30 | c: u8, | |
| 31 | }; | |
| 32 | ||
| 33 | var ptr = @ptrCast(*const S, &bytes); | |
| 34 | var val = ptr.c; | |
| 35 | assertOrPanic(val == 5); | |
| 36 | } | |
| 37 | ||
| 38 | test "reinterpret struct field at comptime" { | |
| 39 | const numLittle = comptime Bytes.init(0x12345678); | |
| 40 | assertOrPanic(std.mem.eql(u8, []u8{ 0x78, 0x56, 0x34, 0x12 }, numLittle.bytes)); | |
| 41 | } | |
| 42 | ||
| 43 | const Bytes = struct { | |
| 44 | bytes: [4]u8, | |
| 45 | ||
| 46 | pub fn init(v: u32) Bytes { | |
| 47 | var res: Bytes = undefined; | |
| 48 | @ptrCast(*align(1) u32, &res.bytes).* = v; | |
| 49 | ||
| 50 | return res; | |
| 51 | } | |
| 52 | }; |
test/cases/pub_enum/index.zig deleted-13| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | const other = @import("other.zig"); | |
| 2 | const assert = @import("std").debug.assert; | |
| 3 | ||
| 4 | test "pub enum" { | |
| 5 | pubEnumTest(other.APubEnum.Two); | |
| 6 | } | |
| 7 | fn pubEnumTest(foo: other.APubEnum) void { | |
| 8 | assert(foo == other.APubEnum.Two); | |
| 9 | } | |
| 10 | ||
| 11 | test "cast with imported symbol" { | |
| 12 | assert(other.size_t(42) == 42); | |
| 13 | } |
test/cases/pub_enum/other.zig deleted-6| ... | ... | @@ -1,6 +0,0 @@ |
| 1 | pub const APubEnum = enum { | |
| 2 | One, | |
| 3 | Two, | |
| 4 | Three, | |
| 5 | }; | |
| 6 | pub const size_t = u64; |
test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig deleted-37| ... | ... | @@ -1,37 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | const mem = @import("std").mem; | |
| 3 | ||
| 4 | var ok: bool = false; | |
| 5 | test "reference a variable in an if after an if in the 2nd switch prong" { | |
| 6 | foo(true, Num.Two, false, "aoeu"); | |
| 7 | assert(!ok); | |
| 8 | foo(false, Num.One, false, "aoeu"); | |
| 9 | assert(!ok); | |
| 10 | foo(true, Num.One, false, "aoeu"); | |
| 11 | assert(ok); | |
| 12 | } | |
| 13 | ||
| 14 | const Num = enum { | |
| 15 | One, | |
| 16 | Two, | |
| 17 | }; | |
| 18 | ||
| 19 | fn foo(c: bool, k: Num, c2: bool, b: []const u8) void { | |
| 20 | switch (k) { | |
| 21 | Num.Two => {}, | |
| 22 | Num.One => { | |
| 23 | if (c) { | |
| 24 | const output_path = b; | |
| 25 | ||
| 26 | if (c2) {} | |
| 27 | ||
| 28 | a(output_path); | |
| 29 | } | |
| 30 | }, | |
| 31 | } | |
| 32 | } | |
| 33 | ||
| 34 | fn a(x: []const u8) void { | |
| 35 | assert(mem.eql(u8, x, "aoeu")); | |
| 36 | ok = true; | |
| 37 | } |
test/cases/reflection.zig deleted-95| ... | ... | @@ -1,95 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | const mem = @import("std").mem; | |
| 3 | const reflection = @This(); | |
| 4 | ||
| 5 | test "reflection: array, pointer, optional, error union type child" { | |
| 6 | comptime { | |
| 7 | assert(([10]u8).Child == u8); | |
| 8 | assert((*u8).Child == u8); | |
| 9 | assert((anyerror!u8).Payload == u8); | |
| 10 | assert((?u8).Child == u8); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | test "reflection: function return type, var args, and param types" { | |
| 15 | comptime { | |
| 16 | assert(@typeOf(dummy).ReturnType == i32); | |
| 17 | assert(!@typeOf(dummy).is_var_args); | |
| 18 | assert(@typeOf(dummy_varargs).is_var_args); | |
| 19 | assert(@typeOf(dummy).arg_count == 3); | |
| 20 | assert(@ArgType(@typeOf(dummy), 0) == bool); | |
| 21 | assert(@ArgType(@typeOf(dummy), 1) == i32); | |
| 22 | assert(@ArgType(@typeOf(dummy), 2) == f32); | |
| 23 | } | |
| 24 | } | |
| 25 | ||
| 26 | fn dummy(a: bool, b: i32, c: f32) i32 { | |
| 27 | return 1234; | |
| 28 | } | |
| 29 | fn dummy_varargs(args: ...) void {} | |
| 30 | ||
| 31 | test "reflection: struct member types and names" { | |
| 32 | comptime { | |
| 33 | assert(@memberCount(Foo) == 3); | |
| 34 | ||
| 35 | assert(@memberType(Foo, 0) == i32); | |
| 36 | assert(@memberType(Foo, 1) == bool); | |
| 37 | assert(@memberType(Foo, 2) == void); | |
| 38 | ||
| 39 | assert(mem.eql(u8, @memberName(Foo, 0), "one")); | |
| 40 | assert(mem.eql(u8, @memberName(Foo, 1), "two")); | |
| 41 | assert(mem.eql(u8, @memberName(Foo, 2), "three")); | |
| 42 | } | |
| 43 | } | |
| 44 | ||
| 45 | test "reflection: enum member types and names" { | |
| 46 | comptime { | |
| 47 | assert(@memberCount(Bar) == 4); | |
| 48 | ||
| 49 | assert(@memberType(Bar, 0) == void); | |
| 50 | assert(@memberType(Bar, 1) == i32); | |
| 51 | assert(@memberType(Bar, 2) == bool); | |
| 52 | assert(@memberType(Bar, 3) == f64); | |
| 53 | ||
| 54 | assert(mem.eql(u8, @memberName(Bar, 0), "One")); | |
| 55 | assert(mem.eql(u8, @memberName(Bar, 1), "Two")); | |
| 56 | assert(mem.eql(u8, @memberName(Bar, 2), "Three")); | |
| 57 | assert(mem.eql(u8, @memberName(Bar, 3), "Four")); | |
| 58 | } | |
| 59 | } | |
| 60 | ||
| 61 | test "reflection: @field" { | |
| 62 | var f = Foo{ | |
| 63 | .one = 42, | |
| 64 | .two = true, | |
| 65 | .three = void{}, | |
| 66 | }; | |
| 67 | ||
| 68 | assert(f.one == f.one); | |
| 69 | assert(@field(f, "o" ++ "ne") == f.one); | |
| 70 | assert(@field(f, "t" ++ "wo") == f.two); | |
| 71 | assert(@field(f, "th" ++ "ree") == f.three); | |
| 72 | assert(@field(Foo, "const" ++ "ant") == Foo.constant); | |
| 73 | assert(@field(Bar, "O" ++ "ne") == Bar.One); | |
| 74 | assert(@field(Bar, "T" ++ "wo") == Bar.Two); | |
| 75 | assert(@field(Bar, "Th" ++ "ree") == Bar.Three); | |
| 76 | assert(@field(Bar, "F" ++ "our") == Bar.Four); | |
| 77 | assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2)); | |
| 78 | @field(f, "o" ++ "ne") = 4; | |
| 79 | assert(f.one == 4); | |
| 80 | } | |
| 81 | ||
| 82 | const Foo = struct { | |
| 83 | const constant = 52; | |
| 84 | ||
| 85 | one: i32, | |
| 86 | two: bool, | |
| 87 | three: void, | |
| 88 | }; | |
| 89 | ||
| 90 | const Bar = union(enum) { | |
| 91 | One: void, | |
| 92 | Two: i32, | |
| 93 | Three: bool, | |
| 94 | Four: f64, | |
| 95 | }; |
test/cases/sizeof_and_typeof.zig deleted-69| ... | ... | @@ -1,69 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const assert = @import("std").debug.assert; | |
| 3 | ||
| 4 | test "@sizeOf and @typeOf" { | |
| 5 | const y: @typeOf(x) = 120; | |
| 6 | assert(@sizeOf(@typeOf(y)) == 2); | |
| 7 | } | |
| 8 | const x: u16 = 13; | |
| 9 | const z: @typeOf(x) = 19; | |
| 10 | ||
| 11 | const A = struct { | |
| 12 | a: u8, | |
| 13 | b: u32, | |
| 14 | c: u8, | |
| 15 | d: u3, | |
| 16 | e: u5, | |
| 17 | f: u16, | |
| 18 | g: u16, | |
| 19 | }; | |
| 20 | ||
| 21 | const P = packed struct { | |
| 22 | a: u8, | |
| 23 | b: u32, | |
| 24 | c: u8, | |
| 25 | d: u3, | |
| 26 | e: u5, | |
| 27 | f: u16, | |
| 28 | g: u16, | |
| 29 | }; | |
| 30 | ||
| 31 | test "@byteOffsetOf" { | |
| 32 | // Packed structs have fixed memory layout | |
| 33 | assert(@byteOffsetOf(P, "a") == 0); | |
| 34 | assert(@byteOffsetOf(P, "b") == 1); | |
| 35 | assert(@byteOffsetOf(P, "c") == 5); | |
| 36 | assert(@byteOffsetOf(P, "d") == 6); | |
| 37 | assert(@byteOffsetOf(P, "e") == 6); | |
| 38 | assert(@byteOffsetOf(P, "f") == 7); | |
| 39 | assert(@byteOffsetOf(P, "g") == 9); | |
| 40 | ||
| 41 | // Normal struct fields can be moved/padded | |
| 42 | var a: A = undefined; | |
| 43 | assert(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a")); | |
| 44 | assert(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b")); | |
| 45 | assert(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c")); | |
| 46 | assert(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d")); | |
| 47 | assert(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e")); | |
| 48 | assert(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f")); | |
| 49 | assert(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g")); | |
| 50 | } | |
| 51 | ||
| 52 | test "@bitOffsetOf" { | |
| 53 | // Packed structs have fixed memory layout | |
| 54 | assert(@bitOffsetOf(P, "a") == 0); | |
| 55 | assert(@bitOffsetOf(P, "b") == 8); | |
| 56 | assert(@bitOffsetOf(P, "c") == 40); | |
| 57 | assert(@bitOffsetOf(P, "d") == 48); | |
| 58 | assert(@bitOffsetOf(P, "e") == 51); | |
| 59 | assert(@bitOffsetOf(P, "f") == 56); | |
| 60 | assert(@bitOffsetOf(P, "g") == 72); | |
| 61 | ||
| 62 | assert(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a")); | |
| 63 | assert(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b")); | |
| 64 | assert(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c")); | |
| 65 | assert(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d")); | |
| 66 | assert(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e")); | |
| 67 | assert(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); | |
| 68 | assert(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); | |
| 69 | } |
test/cases/slice.zig deleted-40| ... | ... | @@ -1,40 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | const mem = @import("std").mem; | |
| 3 | ||
| 4 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; | |
| 5 | const y = x[0x100..]; | |
| 6 | test "compile time slice of pointer to hard coded address" { | |
| 7 | assert(@ptrToInt(x.ptr) == 0x1000); | |
| 8 | assert(x.len == 0x500); | |
| 9 | ||
| 10 | assert(@ptrToInt(y.ptr) == 0x1100); | |
| 11 | assert(y.len == 0x400); | |
| 12 | } | |
| 13 | ||
| 14 | test "slice child property" { | |
| 15 | var array: [5]i32 = undefined; | |
| 16 | var slice = array[0..]; | |
| 17 | assert(@typeOf(slice).Child == i32); | |
| 18 | } | |
| 19 | ||
| 20 | test "runtime safety lets us slice from len..len" { | |
| 21 | var an_array = []u8{ | |
| 22 | 1, | |
| 23 | 2, | |
| 24 | 3, | |
| 25 | }; | |
| 26 | assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); | |
| 27 | } | |
| 28 | ||
| 29 | fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { | |
| 30 | return a_slice[start..end]; | |
| 31 | } | |
| 32 | ||
| 33 | test "implicitly cast array of size 0 to slice" { | |
| 34 | var msg = []u8{}; | |
| 35 | assertLenIsZero(msg); | |
| 36 | } | |
| 37 | ||
| 38 | fn assertLenIsZero(msg: []const u8) void { | |
| 39 | assert(msg.len == 0); | |
| 40 | } |
test/cases/struct.zig deleted-470| ... | ... | @@ -1,470 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | const maxInt = std.math.maxInt; | |
| 5 | ||
| 6 | const StructWithNoFields = struct { | |
| 7 | fn add(a: i32, b: i32) i32 { | |
| 8 | return a + b; | |
| 9 | } | |
| 10 | }; | |
| 11 | const empty_global_instance = StructWithNoFields{}; | |
| 12 | ||
| 13 | test "call struct static method" { | |
| 14 | const result = StructWithNoFields.add(3, 4); | |
| 15 | assert(result == 7); | |
| 16 | } | |
| 17 | ||
| 18 | test "return empty struct instance" { | |
| 19 | _ = returnEmptyStructInstance(); | |
| 20 | } | |
| 21 | fn returnEmptyStructInstance() StructWithNoFields { | |
| 22 | return empty_global_instance; | |
| 23 | } | |
| 24 | ||
| 25 | const should_be_11 = StructWithNoFields.add(5, 6); | |
| 26 | ||
| 27 | test "invake static method in global scope" { | |
| 28 | assert(should_be_11 == 11); | |
| 29 | } | |
| 30 | ||
| 31 | test "void struct fields" { | |
| 32 | const foo = VoidStructFieldsFoo{ | |
| 33 | .a = void{}, | |
| 34 | .b = 1, | |
| 35 | .c = void{}, | |
| 36 | }; | |
| 37 | assert(foo.b == 1); | |
| 38 | assert(@sizeOf(VoidStructFieldsFoo) == 4); | |
| 39 | } | |
| 40 | const VoidStructFieldsFoo = struct { | |
| 41 | a: void, | |
| 42 | b: i32, | |
| 43 | c: void, | |
| 44 | }; | |
| 45 | ||
| 46 | test "structs" { | |
| 47 | var foo: StructFoo = undefined; | |
| 48 | @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); | |
| 49 | foo.a += 1; | |
| 50 | foo.b = foo.a == 1; | |
| 51 | testFoo(foo); | |
| 52 | testMutation(&foo); | |
| 53 | assert(foo.c == 100); | |
| 54 | } | |
| 55 | const StructFoo = struct { | |
| 56 | a: i32, | |
| 57 | b: bool, | |
| 58 | c: f32, | |
| 59 | }; | |
| 60 | fn testFoo(foo: StructFoo) void { | |
| 61 | assert(foo.b); | |
| 62 | } | |
| 63 | fn testMutation(foo: *StructFoo) void { | |
| 64 | foo.c = 100; | |
| 65 | } | |
| 66 | ||
| 67 | const Node = struct { | |
| 68 | val: Val, | |
| 69 | next: *Node, | |
| 70 | }; | |
| 71 | ||
| 72 | const Val = struct { | |
| 73 | x: i32, | |
| 74 | }; | |
| 75 | ||
| 76 | test "struct point to self" { | |
| 77 | var root: Node = undefined; | |
| 78 | root.val.x = 1; | |
| 79 | ||
| 80 | var node: Node = undefined; | |
| 81 | node.next = &root; | |
| 82 | node.val.x = 2; | |
| 83 | ||
| 84 | root.next = &node; | |
| 85 | ||
| 86 | assert(node.next.next.next.val.x == 1); | |
| 87 | } | |
| 88 | ||
| 89 | test "struct byval assign" { | |
| 90 | var foo1: StructFoo = undefined; | |
| 91 | var foo2: StructFoo = undefined; | |
| 92 | ||
| 93 | foo1.a = 1234; | |
| 94 | foo2.a = 0; | |
| 95 | assert(foo2.a == 0); | |
| 96 | foo2 = foo1; | |
| 97 | assert(foo2.a == 1234); | |
| 98 | } | |
| 99 | ||
| 100 | fn structInitializer() void { | |
| 101 | const val = Val{ .x = 42 }; | |
| 102 | assert(val.x == 42); | |
| 103 | } | |
| 104 | ||
| 105 | test "fn call of struct field" { | |
| 106 | assert(callStructField(Foo{ .ptr = aFunc }) == 13); | |
| 107 | } | |
| 108 | ||
| 109 | const Foo = struct { | |
| 110 | ptr: fn () i32, | |
| 111 | }; | |
| 112 | ||
| 113 | fn aFunc() i32 { | |
| 114 | return 13; | |
| 115 | } | |
| 116 | ||
| 117 | fn callStructField(foo: Foo) i32 { | |
| 118 | return foo.ptr(); | |
| 119 | } | |
| 120 | ||
| 121 | test "store member function in variable" { | |
| 122 | const instance = MemberFnTestFoo{ .x = 1234 }; | |
| 123 | const memberFn = MemberFnTestFoo.member; | |
| 124 | const result = memberFn(instance); | |
| 125 | assert(result == 1234); | |
| 126 | } | |
| 127 | const MemberFnTestFoo = struct { | |
| 128 | x: i32, | |
| 129 | fn member(foo: MemberFnTestFoo) i32 { | |
| 130 | return foo.x; | |
| 131 | } | |
| 132 | }; | |
| 133 | ||
| 134 | test "call member function directly" { | |
| 135 | const instance = MemberFnTestFoo{ .x = 1234 }; | |
| 136 | const result = MemberFnTestFoo.member(instance); | |
| 137 | assert(result == 1234); | |
| 138 | } | |
| 139 | ||
| 140 | test "member functions" { | |
| 141 | const r = MemberFnRand{ .seed = 1234 }; | |
| 142 | assert(r.getSeed() == 1234); | |
| 143 | } | |
| 144 | const MemberFnRand = struct { | |
| 145 | seed: u32, | |
| 146 | pub fn getSeed(r: *const MemberFnRand) u32 { | |
| 147 | return r.seed; | |
| 148 | } | |
| 149 | }; | |
| 150 | ||
| 151 | test "return struct byval from function" { | |
| 152 | const bar = makeBar(1234, 5678); | |
| 153 | assert(bar.y == 5678); | |
| 154 | } | |
| 155 | const Bar = struct { | |
| 156 | x: i32, | |
| 157 | y: i32, | |
| 158 | }; | |
| 159 | fn makeBar(x: i32, y: i32) Bar { | |
| 160 | return Bar{ | |
| 161 | .x = x, | |
| 162 | .y = y, | |
| 163 | }; | |
| 164 | } | |
| 165 | ||
| 166 | test "empty struct method call" { | |
| 167 | const es = EmptyStruct{}; | |
| 168 | assert(es.method() == 1234); | |
| 169 | } | |
| 170 | const EmptyStruct = struct { | |
| 171 | fn method(es: *const EmptyStruct) i32 { | |
| 172 | return 1234; | |
| 173 | } | |
| 174 | }; | |
| 175 | ||
| 176 | test "return empty struct from fn" { | |
| 177 | _ = testReturnEmptyStructFromFn(); | |
| 178 | } | |
| 179 | const EmptyStruct2 = struct {}; | |
| 180 | fn testReturnEmptyStructFromFn() EmptyStruct2 { | |
| 181 | return EmptyStruct2{}; | |
| 182 | } | |
| 183 | ||
| 184 | test "pass slice of empty struct to fn" { | |
| 185 | assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1); | |
| 186 | } | |
| 187 | fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { | |
| 188 | return slice.len; | |
| 189 | } | |
| 190 | ||
| 191 | const APackedStruct = packed struct { | |
| 192 | x: u8, | |
| 193 | y: u8, | |
| 194 | }; | |
| 195 | ||
| 196 | test "packed struct" { | |
| 197 | var foo = APackedStruct{ | |
| 198 | .x = 1, | |
| 199 | .y = 2, | |
| 200 | }; | |
| 201 | foo.y += 1; | |
| 202 | const four = foo.x + foo.y; | |
| 203 | assert(four == 4); | |
| 204 | } | |
| 205 | ||
| 206 | const BitField1 = packed struct { | |
| 207 | a: u3, | |
| 208 | b: u3, | |
| 209 | c: u2, | |
| 210 | }; | |
| 211 | ||
| 212 | const bit_field_1 = BitField1{ | |
| 213 | .a = 1, | |
| 214 | .b = 2, | |
| 215 | .c = 3, | |
| 216 | }; | |
| 217 | ||
| 218 | test "bit field access" { | |
| 219 | var data = bit_field_1; | |
| 220 | assert(getA(&data) == 1); | |
| 221 | assert(getB(&data) == 2); | |
| 222 | assert(getC(&data) == 3); | |
| 223 | comptime assert(@sizeOf(BitField1) == 1); | |
| 224 | ||
| 225 | data.b += 1; | |
| 226 | assert(data.b == 3); | |
| 227 | ||
| 228 | data.a += 1; | |
| 229 | assert(data.a == 2); | |
| 230 | assert(data.b == 3); | |
| 231 | } | |
| 232 | ||
| 233 | fn getA(data: *const BitField1) u3 { | |
| 234 | return data.a; | |
| 235 | } | |
| 236 | ||
| 237 | fn getB(data: *const BitField1) u3 { | |
| 238 | return data.b; | |
| 239 | } | |
| 240 | ||
| 241 | fn getC(data: *const BitField1) u2 { | |
| 242 | return data.c; | |
| 243 | } | |
| 244 | ||
| 245 | const Foo24Bits = packed struct { | |
| 246 | field: u24, | |
| 247 | }; | |
| 248 | const Foo96Bits = packed struct { | |
| 249 | a: u24, | |
| 250 | b: u24, | |
| 251 | c: u24, | |
| 252 | d: u24, | |
| 253 | }; | |
| 254 | ||
| 255 | test "packed struct 24bits" { | |
| 256 | comptime { | |
| 257 | assert(@sizeOf(Foo24Bits) == 3); | |
| 258 | assert(@sizeOf(Foo96Bits) == 12); | |
| 259 | } | |
| 260 | ||
| 261 | var value = Foo96Bits{ | |
| 262 | .a = 0, | |
| 263 | .b = 0, | |
| 264 | .c = 0, | |
| 265 | .d = 0, | |
| 266 | }; | |
| 267 | value.a += 1; | |
| 268 | assert(value.a == 1); | |
| 269 | assert(value.b == 0); | |
| 270 | assert(value.c == 0); | |
| 271 | assert(value.d == 0); | |
| 272 | ||
| 273 | value.b += 1; | |
| 274 | assert(value.a == 1); | |
| 275 | assert(value.b == 1); | |
| 276 | assert(value.c == 0); | |
| 277 | assert(value.d == 0); | |
| 278 | ||
| 279 | value.c += 1; | |
| 280 | assert(value.a == 1); | |
| 281 | assert(value.b == 1); | |
| 282 | assert(value.c == 1); | |
| 283 | assert(value.d == 0); | |
| 284 | ||
| 285 | value.d += 1; | |
| 286 | assert(value.a == 1); | |
| 287 | assert(value.b == 1); | |
| 288 | assert(value.c == 1); | |
| 289 | assert(value.d == 1); | |
| 290 | } | |
| 291 | ||
| 292 | const FooArray24Bits = packed struct { | |
| 293 | a: u16, | |
| 294 | b: [2]Foo24Bits, | |
| 295 | c: u16, | |
| 296 | }; | |
| 297 | ||
| 298 | test "packed array 24bits" { | |
| 299 | comptime { | |
| 300 | assert(@sizeOf([9]Foo24Bits) == 9 * 3); | |
| 301 | assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); | |
| 302 | } | |
| 303 | ||
| 304 | var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1); | |
| 305 | bytes[bytes.len - 1] = 0xaa; | |
| 306 | const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; | |
| 307 | assert(ptr.a == 0); | |
| 308 | assert(ptr.b[0].field == 0); | |
| 309 | assert(ptr.b[1].field == 0); | |
| 310 | assert(ptr.c == 0); | |
| 311 | ||
| 312 | ptr.a = maxInt(u16); | |
| 313 | assert(ptr.a == maxInt(u16)); | |
| 314 | assert(ptr.b[0].field == 0); | |
| 315 | assert(ptr.b[1].field == 0); | |
| 316 | assert(ptr.c == 0); | |
| 317 | ||
| 318 | ptr.b[0].field = maxInt(u24); | |
| 319 | assert(ptr.a == maxInt(u16)); | |
| 320 | assert(ptr.b[0].field == maxInt(u24)); | |
| 321 | assert(ptr.b[1].field == 0); | |
| 322 | assert(ptr.c == 0); | |
| 323 | ||
| 324 | ptr.b[1].field = maxInt(u24); | |
| 325 | assert(ptr.a == maxInt(u16)); | |
| 326 | assert(ptr.b[0].field == maxInt(u24)); | |
| 327 | assert(ptr.b[1].field == maxInt(u24)); | |
| 328 | assert(ptr.c == 0); | |
| 329 | ||
| 330 | ptr.c = maxInt(u16); | |
| 331 | assert(ptr.a == maxInt(u16)); | |
| 332 | assert(ptr.b[0].field == maxInt(u24)); | |
| 333 | assert(ptr.b[1].field == maxInt(u24)); | |
| 334 | assert(ptr.c == maxInt(u16)); | |
| 335 | ||
| 336 | assert(bytes[bytes.len - 1] == 0xaa); | |
| 337 | } | |
| 338 | ||
| 339 | const FooStructAligned = packed struct { | |
| 340 | a: u8, | |
| 341 | b: u8, | |
| 342 | }; | |
| 343 | ||
| 344 | const FooArrayOfAligned = packed struct { | |
| 345 | a: [2]FooStructAligned, | |
| 346 | }; | |
| 347 | ||
| 348 | test "aligned array of packed struct" { | |
| 349 | comptime { | |
| 350 | assert(@sizeOf(FooStructAligned) == 2); | |
| 351 | assert(@sizeOf(FooArrayOfAligned) == 2 * 2); | |
| 352 | } | |
| 353 | ||
| 354 | var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned); | |
| 355 | const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0]; | |
| 356 | ||
| 357 | assert(ptr.a[0].a == 0xbb); | |
| 358 | assert(ptr.a[0].b == 0xbb); | |
| 359 | assert(ptr.a[1].a == 0xbb); | |
| 360 | assert(ptr.a[1].b == 0xbb); | |
| 361 | } | |
| 362 | ||
| 363 | test "runtime struct initialization of bitfield" { | |
| 364 | const s1 = Nibbles{ | |
| 365 | .x = x1, | |
| 366 | .y = x1, | |
| 367 | }; | |
| 368 | const s2 = Nibbles{ | |
| 369 | .x = @intCast(u4, x2), | |
| 370 | .y = @intCast(u4, x2), | |
| 371 | }; | |
| 372 | ||
| 373 | assert(s1.x == x1); | |
| 374 | assert(s1.y == x1); | |
| 375 | assert(s2.x == @intCast(u4, x2)); | |
| 376 | assert(s2.y == @intCast(u4, x2)); | |
| 377 | } | |
| 378 | ||
| 379 | var x1 = u4(1); | |
| 380 | var x2 = u8(2); | |
| 381 | ||
| 382 | const Nibbles = packed struct { | |
| 383 | x: u4, | |
| 384 | y: u4, | |
| 385 | }; | |
| 386 | ||
| 387 | const Bitfields = packed struct { | |
| 388 | f1: u16, | |
| 389 | f2: u16, | |
| 390 | f3: u8, | |
| 391 | f4: u8, | |
| 392 | f5: u4, | |
| 393 | f6: u4, | |
| 394 | f7: u8, | |
| 395 | }; | |
| 396 | ||
| 397 | test "native bit field understands endianness" { | |
| 398 | var all: u64 = 0x7765443322221111; | |
| 399 | var bytes: [8]u8 = undefined; | |
| 400 | @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8); | |
| 401 | var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*; | |
| 402 | ||
| 403 | assert(bitfields.f1 == 0x1111); | |
| 404 | assert(bitfields.f2 == 0x2222); | |
| 405 | assert(bitfields.f3 == 0x33); | |
| 406 | assert(bitfields.f4 == 0x44); | |
| 407 | assert(bitfields.f5 == 0x5); | |
| 408 | assert(bitfields.f6 == 0x6); | |
| 409 | assert(bitfields.f7 == 0x77); | |
| 410 | } | |
| 411 | ||
| 412 | test "align 1 field before self referential align 8 field as slice return type" { | |
| 413 | const result = alloc(Expr); | |
| 414 | assert(result.len == 0); | |
| 415 | } | |
| 416 | ||
| 417 | const Expr = union(enum) { | |
| 418 | Literal: u8, | |
| 419 | Question: *Expr, | |
| 420 | }; | |
| 421 | ||
| 422 | fn alloc(comptime T: type) []T { | |
| 423 | return []T{}; | |
| 424 | } | |
| 425 | ||
| 426 | test "call method with mutable reference to struct with no fields" { | |
| 427 | const S = struct { | |
| 428 | fn doC(s: *const @This()) bool { | |
| 429 | return true; | |
| 430 | } | |
| 431 | fn do(s: *@This()) bool { | |
| 432 | return true; | |
| 433 | } | |
| 434 | }; | |
| 435 | ||
| 436 | var s = S{}; | |
| 437 | assert(S.doC(&s)); | |
| 438 | assert(s.doC()); | |
| 439 | assert(S.do(&s)); | |
| 440 | assert(s.do()); | |
| 441 | } | |
| 442 | ||
| 443 | test "implicit cast packed struct field to const ptr" { | |
| 444 | const LevelUpMove = packed struct { | |
| 445 | move_id: u9, | |
| 446 | level: u7, | |
| 447 | ||
| 448 | fn toInt(value: u7) u7 { | |
| 449 | return value; | |
| 450 | } | |
| 451 | }; | |
| 452 | ||
| 453 | var lup: LevelUpMove = undefined; | |
| 454 | lup.level = 12; | |
| 455 | const res = LevelUpMove.toInt(lup.level); | |
| 456 | assert(res == 12); | |
| 457 | } | |
| 458 | ||
| 459 | test "pointer to packed struct member in a stack variable" { | |
| 460 | const S = packed struct { | |
| 461 | a: u2, | |
| 462 | b: u2, | |
| 463 | }; | |
| 464 | ||
| 465 | var s = S{ .a = 2, .b = 0 }; | |
| 466 | var b_ptr = &s.b; | |
| 467 | assert(s.b == 0); | |
| 468 | b_ptr.* = 2; | |
| 469 | assert(s.b == 2); | |
| 470 | } |
test/cases/struct_contains_null_ptr_itself.zig deleted-21| ... | ... | @@ -1,21 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | ||
| 4 | test "struct contains null pointer which contains original struct" { | |
| 5 | var x: ?*NodeLineComment = null; | |
| 6 | assert(x == null); | |
| 7 | } | |
| 8 | ||
| 9 | pub const Node = struct { | |
| 10 | id: Id, | |
| 11 | comment: ?*NodeLineComment, | |
| 12 | ||
| 13 | pub const Id = enum { | |
| 14 | Root, | |
| 15 | LineComment, | |
| 16 | }; | |
| 17 | }; | |
| 18 | ||
| 19 | pub const NodeLineComment = struct { | |
| 20 | base: Node, | |
| 21 | }; |
test/cases/struct_contains_slice_of_itself.zig deleted-85| ... | ... | @@ -1,85 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | const Node = struct { | |
| 4 | payload: i32, | |
| 5 | children: []Node, | |
| 6 | }; | |
| 7 | ||
| 8 | const NodeAligned = struct { | |
| 9 | payload: i32, | |
| 10 | children: []align(@alignOf(NodeAligned)) NodeAligned, | |
| 11 | }; | |
| 12 | ||
| 13 | test "struct contains slice of itself" { | |
| 14 | var other_nodes = []Node{ | |
| 15 | Node{ | |
| 16 | .payload = 31, | |
| 17 | .children = []Node{}, | |
| 18 | }, | |
| 19 | Node{ | |
| 20 | .payload = 32, | |
| 21 | .children = []Node{}, | |
| 22 | }, | |
| 23 | }; | |
| 24 | var nodes = []Node{ | |
| 25 | Node{ | |
| 26 | .payload = 1, | |
| 27 | .children = []Node{}, | |
| 28 | }, | |
| 29 | Node{ | |
| 30 | .payload = 2, | |
| 31 | .children = []Node{}, | |
| 32 | }, | |
| 33 | Node{ | |
| 34 | .payload = 3, | |
| 35 | .children = other_nodes[0..], | |
| 36 | }, | |
| 37 | }; | |
| 38 | const root = Node{ | |
| 39 | .payload = 1234, | |
| 40 | .children = nodes[0..], | |
| 41 | }; | |
| 42 | assert(root.payload == 1234); | |
| 43 | assert(root.children[0].payload == 1); | |
| 44 | assert(root.children[1].payload == 2); | |
| 45 | assert(root.children[2].payload == 3); | |
| 46 | assert(root.children[2].children[0].payload == 31); | |
| 47 | assert(root.children[2].children[1].payload == 32); | |
| 48 | } | |
| 49 | ||
| 50 | test "struct contains aligned slice of itself" { | |
| 51 | var other_nodes = []NodeAligned{ | |
| 52 | NodeAligned{ | |
| 53 | .payload = 31, | |
| 54 | .children = []NodeAligned{}, | |
| 55 | }, | |
| 56 | NodeAligned{ | |
| 57 | .payload = 32, | |
| 58 | .children = []NodeAligned{}, | |
| 59 | }, | |
| 60 | }; | |
| 61 | var nodes = []NodeAligned{ | |
| 62 | NodeAligned{ | |
| 63 | .payload = 1, | |
| 64 | .children = []NodeAligned{}, | |
| 65 | }, | |
| 66 | NodeAligned{ | |
| 67 | .payload = 2, | |
| 68 | .children = []NodeAligned{}, | |
| 69 | }, | |
| 70 | NodeAligned{ | |
| 71 | .payload = 3, | |
| 72 | .children = other_nodes[0..], | |
| 73 | }, | |
| 74 | }; | |
| 75 | const root = NodeAligned{ | |
| 76 | .payload = 1234, | |
| 77 | .children = nodes[0..], | |
| 78 | }; | |
| 79 | assert(root.payload == 1234); | |
| 80 | assert(root.children[0].payload == 1); | |
| 81 | assert(root.children[1].payload == 2); | |
| 82 | assert(root.children[2].payload == 3); | |
| 83 | assert(root.children[2].children[0].payload == 31); | |
| 84 | assert(root.children[2].children[1].payload == 32); | |
| 85 | } |
test/cases/switch.zig deleted-271| ... | ... | @@ -1,271 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "switch with numbers" { | |
| 4 | testSwitchWithNumbers(13); | |
| 5 | } | |
| 6 | ||
| 7 | fn testSwitchWithNumbers(x: u32) void { | |
| 8 | const result = switch (x) { | |
| 9 | 1, 2, 3, 4...8 => false, | |
| 10 | 13 => true, | |
| 11 | else => false, | |
| 12 | }; | |
| 13 | assert(result); | |
| 14 | } | |
| 15 | ||
| 16 | test "switch with all ranges" { | |
| 17 | assert(testSwitchWithAllRanges(50, 3) == 1); | |
| 18 | assert(testSwitchWithAllRanges(101, 0) == 2); | |
| 19 | assert(testSwitchWithAllRanges(300, 5) == 3); | |
| 20 | assert(testSwitchWithAllRanges(301, 6) == 6); | |
| 21 | } | |
| 22 | ||
| 23 | fn testSwitchWithAllRanges(x: u32, y: u32) u32 { | |
| 24 | return switch (x) { | |
| 25 | 0...100 => 1, | |
| 26 | 101...200 => 2, | |
| 27 | 201...300 => 3, | |
| 28 | else => y, | |
| 29 | }; | |
| 30 | } | |
| 31 | ||
| 32 | test "implicit comptime switch" { | |
| 33 | const x = 3 + 4; | |
| 34 | const result = switch (x) { | |
| 35 | 3 => 10, | |
| 36 | 4 => 11, | |
| 37 | 5, 6 => 12, | |
| 38 | 7, 8 => 13, | |
| 39 | else => 14, | |
| 40 | }; | |
| 41 | ||
| 42 | comptime { | |
| 43 | assert(result + 1 == 14); | |
| 44 | } | |
| 45 | } | |
| 46 | ||
| 47 | test "switch on enum" { | |
| 48 | const fruit = Fruit.Orange; | |
| 49 | nonConstSwitchOnEnum(fruit); | |
| 50 | } | |
| 51 | const Fruit = enum { | |
| 52 | Apple, | |
| 53 | Orange, | |
| 54 | Banana, | |
| 55 | }; | |
| 56 | fn nonConstSwitchOnEnum(fruit: Fruit) void { | |
| 57 | switch (fruit) { | |
| 58 | Fruit.Apple => unreachable, | |
| 59 | Fruit.Orange => {}, | |
| 60 | Fruit.Banana => unreachable, | |
| 61 | } | |
| 62 | } | |
| 63 | ||
| 64 | test "switch statement" { | |
| 65 | nonConstSwitch(SwitchStatmentFoo.C); | |
| 66 | } | |
| 67 | fn nonConstSwitch(foo: SwitchStatmentFoo) void { | |
| 68 | const val = switch (foo) { | |
| 69 | SwitchStatmentFoo.A => i32(1), | |
| 70 | SwitchStatmentFoo.B => 2, | |
| 71 | SwitchStatmentFoo.C => 3, | |
| 72 | SwitchStatmentFoo.D => 4, | |
| 73 | }; | |
| 74 | assert(val == 3); | |
| 75 | } | |
| 76 | const SwitchStatmentFoo = enum { | |
| 77 | A, | |
| 78 | B, | |
| 79 | C, | |
| 80 | D, | |
| 81 | }; | |
| 82 | ||
| 83 | test "switch prong with variable" { | |
| 84 | switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 }); | |
| 85 | switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 }); | |
| 86 | switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} }); | |
| 87 | } | |
| 88 | const SwitchProngWithVarEnum = union(enum) { | |
| 89 | One: i32, | |
| 90 | Two: f32, | |
| 91 | Meh: void, | |
| 92 | }; | |
| 93 | fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void { | |
| 94 | switch (a) { | |
| 95 | SwitchProngWithVarEnum.One => |x| { | |
| 96 | assert(x == 13); | |
| 97 | }, | |
| 98 | SwitchProngWithVarEnum.Two => |x| { | |
| 99 | assert(x == 13.0); | |
| 100 | }, | |
| 101 | SwitchProngWithVarEnum.Meh => |x| { | |
| 102 | const v: void = x; | |
| 103 | }, | |
| 104 | } | |
| 105 | } | |
| 106 | ||
| 107 | test "switch on enum using pointer capture" { | |
| 108 | testSwitchEnumPtrCapture(); | |
| 109 | comptime testSwitchEnumPtrCapture(); | |
| 110 | } | |
| 111 | ||
| 112 | fn testSwitchEnumPtrCapture() void { | |
| 113 | var value = SwitchProngWithVarEnum{ .One = 1234 }; | |
| 114 | switch (value) { | |
| 115 | SwitchProngWithVarEnum.One => |*x| x.* += 1, | |
| 116 | else => unreachable, | |
| 117 | } | |
| 118 | switch (value) { | |
| 119 | SwitchProngWithVarEnum.One => |x| assert(x == 1235), | |
| 120 | else => unreachable, | |
| 121 | } | |
| 122 | } | |
| 123 | ||
| 124 | test "switch with multiple expressions" { | |
| 125 | const x = switch (returnsFive()) { | |
| 126 | 1, 2, 3 => 1, | |
| 127 | 4, 5, 6 => 2, | |
| 128 | else => i32(3), | |
| 129 | }; | |
| 130 | assert(x == 2); | |
| 131 | } | |
| 132 | fn returnsFive() i32 { | |
| 133 | return 5; | |
| 134 | } | |
| 135 | ||
| 136 | const Number = union(enum) { | |
| 137 | One: u64, | |
| 138 | Two: u8, | |
| 139 | Three: f32, | |
| 140 | }; | |
| 141 | ||
| 142 | const number = Number{ .Three = 1.23 }; | |
| 143 | ||
| 144 | fn returnsFalse() bool { | |
| 145 | switch (number) { | |
| 146 | Number.One => |x| return x > 1234, | |
| 147 | Number.Two => |x| return x == 'a', | |
| 148 | Number.Three => |x| return x > 12.34, | |
| 149 | } | |
| 150 | } | |
| 151 | test "switch on const enum with var" { | |
| 152 | assert(!returnsFalse()); | |
| 153 | } | |
| 154 | ||
| 155 | test "switch on type" { | |
| 156 | assert(trueIfBoolFalseOtherwise(bool)); | |
| 157 | assert(!trueIfBoolFalseOtherwise(i32)); | |
| 158 | } | |
| 159 | ||
| 160 | fn trueIfBoolFalseOtherwise(comptime T: type) bool { | |
| 161 | return switch (T) { | |
| 162 | bool => true, | |
| 163 | else => false, | |
| 164 | }; | |
| 165 | } | |
| 166 | ||
| 167 | test "switch handles all cases of number" { | |
| 168 | testSwitchHandleAllCases(); | |
| 169 | comptime testSwitchHandleAllCases(); | |
| 170 | } | |
| 171 | ||
| 172 | fn testSwitchHandleAllCases() void { | |
| 173 | assert(testSwitchHandleAllCasesExhaustive(0) == 3); | |
| 174 | assert(testSwitchHandleAllCasesExhaustive(1) == 2); | |
| 175 | assert(testSwitchHandleAllCasesExhaustive(2) == 1); | |
| 176 | assert(testSwitchHandleAllCasesExhaustive(3) == 0); | |
| 177 | ||
| 178 | assert(testSwitchHandleAllCasesRange(100) == 0); | |
| 179 | assert(testSwitchHandleAllCasesRange(200) == 1); | |
| 180 | assert(testSwitchHandleAllCasesRange(201) == 2); | |
| 181 | assert(testSwitchHandleAllCasesRange(202) == 4); | |
| 182 | assert(testSwitchHandleAllCasesRange(230) == 3); | |
| 183 | } | |
| 184 | ||
| 185 | fn testSwitchHandleAllCasesExhaustive(x: u2) u2 { | |
| 186 | return switch (x) { | |
| 187 | 0 => u2(3), | |
| 188 | 1 => 2, | |
| 189 | 2 => 1, | |
| 190 | 3 => 0, | |
| 191 | }; | |
| 192 | } | |
| 193 | ||
| 194 | fn testSwitchHandleAllCasesRange(x: u8) u8 { | |
| 195 | return switch (x) { | |
| 196 | 0...100 => u8(0), | |
| 197 | 101...200 => 1, | |
| 198 | 201, 203 => 2, | |
| 199 | 202 => 4, | |
| 200 | 204...255 => 3, | |
| 201 | }; | |
| 202 | } | |
| 203 | ||
| 204 | test "switch all prongs unreachable" { | |
| 205 | testAllProngsUnreachable(); | |
| 206 | comptime testAllProngsUnreachable(); | |
| 207 | } | |
| 208 | ||
| 209 | fn testAllProngsUnreachable() void { | |
| 210 | assert(switchWithUnreachable(1) == 2); | |
| 211 | assert(switchWithUnreachable(2) == 10); | |
| 212 | } | |
| 213 | ||
| 214 | fn switchWithUnreachable(x: i32) i32 { | |
| 215 | while (true) { | |
| 216 | switch (x) { | |
| 217 | 1 => return 2, | |
| 218 | 2 => break, | |
| 219 | else => continue, | |
| 220 | } | |
| 221 | } | |
| 222 | return 10; | |
| 223 | } | |
| 224 | ||
| 225 | fn return_a_number() anyerror!i32 { | |
| 226 | return 1; | |
| 227 | } | |
| 228 | ||
| 229 | test "capture value of switch with all unreachable prongs" { | |
| 230 | const x = return_a_number() catch |err| switch (err) { | |
| 231 | else => unreachable, | |
| 232 | }; | |
| 233 | assert(x == 1); | |
| 234 | } | |
| 235 | ||
| 236 | test "switching on booleans" { | |
| 237 | testSwitchOnBools(); | |
| 238 | comptime testSwitchOnBools(); | |
| 239 | } | |
| 240 | ||
| 241 | fn testSwitchOnBools() void { | |
| 242 | assert(testSwitchOnBoolsTrueAndFalse(true) == false); | |
| 243 | assert(testSwitchOnBoolsTrueAndFalse(false) == true); | |
| 244 | ||
| 245 | assert(testSwitchOnBoolsTrueWithElse(true) == false); | |
| 246 | assert(testSwitchOnBoolsTrueWithElse(false) == true); | |
| 247 | ||
| 248 | assert(testSwitchOnBoolsFalseWithElse(true) == false); | |
| 249 | assert(testSwitchOnBoolsFalseWithElse(false) == true); | |
| 250 | } | |
| 251 | ||
| 252 | fn testSwitchOnBoolsTrueAndFalse(x: bool) bool { | |
| 253 | return switch (x) { | |
| 254 | true => false, | |
| 255 | false => true, | |
| 256 | }; | |
| 257 | } | |
| 258 | ||
| 259 | fn testSwitchOnBoolsTrueWithElse(x: bool) bool { | |
| 260 | return switch (x) { | |
| 261 | true => false, | |
| 262 | else => true, | |
| 263 | }; | |
| 264 | } | |
| 265 | ||
| 266 | fn testSwitchOnBoolsFalseWithElse(x: bool) bool { | |
| 267 | return switch (x) { | |
| 268 | false => true, | |
| 269 | else => false, | |
| 270 | }; | |
| 271 | } |
test/cases/switch_prong_err_enum.zig deleted-30| ... | ... | @@ -1,30 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | var read_count: u64 = 0; | |
| 4 | ||
| 5 | fn readOnce() anyerror!u64 { | |
| 6 | read_count += 1; | |
| 7 | return read_count; | |
| 8 | } | |
| 9 | ||
| 10 | const FormValue = union(enum) { | |
| 11 | Address: u64, | |
| 12 | Other: bool, | |
| 13 | }; | |
| 14 | ||
| 15 | fn doThing(form_id: u64) anyerror!FormValue { | |
| 16 | return switch (form_id) { | |
| 17 | 17 => FormValue{ .Address = try readOnce() }, | |
| 18 | else => error.InvalidDebugInfo, | |
| 19 | }; | |
| 20 | } | |
| 21 | ||
| 22 | test "switch prong returns error enum" { | |
| 23 | switch (doThing(17) catch unreachable) { | |
| 24 | FormValue.Address => |payload| { | |
| 25 | assert(payload == 1); | |
| 26 | }, | |
| 27 | else => unreachable, | |
| 28 | } | |
| 29 | assert(read_count == 1); | |
| 30 | } |
test/cases/switch_prong_implicit_cast.zig deleted-22| ... | ... | @@ -1,22 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | const FormValue = union(enum) { | |
| 4 | One: void, | |
| 5 | Two: bool, | |
| 6 | }; | |
| 7 | ||
| 8 | fn foo(id: u64) !FormValue { | |
| 9 | return switch (id) { | |
| 10 | 2 => FormValue{ .Two = true }, | |
| 11 | 1 => FormValue{ .One = {} }, | |
| 12 | else => return error.Whatever, | |
| 13 | }; | |
| 14 | } | |
| 15 | ||
| 16 | test "switch prong implicit cast" { | |
| 17 | const result = switch (foo(2) catch unreachable) { | |
| 18 | FormValue.One => false, | |
| 19 | FormValue.Two => |x| x, | |
| 20 | }; | |
| 21 | assert(result); | |
| 22 | } |
test/cases/syntax.zig deleted-59| ... | ... | @@ -1,59 +0,0 @@ |
| 1 | // Test trailing comma syntax | |
| 2 | // zig fmt: off | |
| 3 | ||
| 4 | const struct_trailing_comma = struct { x: i32, y: i32, }; | |
| 5 | const struct_no_comma = struct { x: i32, y: i32 }; | |
| 6 | const struct_fn_no_comma = struct { fn m() void {} y: i32 }; | |
| 7 | ||
| 8 | const enum_no_comma = enum { A, B }; | |
| 9 | ||
| 10 | fn container_init() void { | |
| 11 | const S = struct { x: i32, y: i32 }; | |
| 12 | _ = S { .x = 1, .y = 2 }; | |
| 13 | _ = S { .x = 1, .y = 2, }; | |
| 14 | } | |
| 15 | ||
| 16 | fn type_expr_return1() if (true) A {} | |
| 17 | fn type_expr_return2() for (true) |_| A {} | |
| 18 | fn type_expr_return3() while (true) A {} | |
| 19 | fn type_expr_return4() comptime A {} | |
| 20 | ||
| 21 | fn switch_cases(x: i32) void { | |
| 22 | switch (x) { | |
| 23 | 1,2,3 => {}, | |
| 24 | 4,5, => {}, | |
| 25 | 6...8, => {}, | |
| 26 | else => {}, | |
| 27 | } | |
| 28 | } | |
| 29 | ||
| 30 | fn switch_prongs(x: i32) void { | |
| 31 | switch (x) { | |
| 32 | 0 => {}, | |
| 33 | else => {}, | |
| 34 | } | |
| 35 | switch (x) { | |
| 36 | 0 => {}, | |
| 37 | else => {} | |
| 38 | } | |
| 39 | } | |
| 40 | ||
| 41 | const fn_no_comma = fn(i32, i32)void; | |
| 42 | const fn_trailing_comma = fn(i32, i32,)void; | |
| 43 | ||
| 44 | fn fn_calls() void { | |
| 45 | fn add(x: i32, y: i32,) i32 { x + y }; | |
| 46 | _ = add(1, 2); | |
| 47 | _ = add(1, 2,); | |
| 48 | } | |
| 49 | ||
| 50 | fn asm_lists() void { | |
| 51 | if (false) { // Build AST but don't analyze | |
| 52 | asm ("not real assembly" | |
| 53 | :[a] "x" (x),); | |
| 54 | asm ("not real assembly" | |
| 55 | :[a] "x" (->i32),:[a] "x" (1),); | |
| 56 | asm ("still not real assembly" | |
| 57 | :::"a","b",); | |
| 58 | } | |
| 59 | } |
test/cases/this.zig deleted-34| ... | ... | @@ -1,34 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | const module = @This(); | |
| 4 | ||
| 5 | fn Point(comptime T: type) type { | |
| 6 | return struct { | |
| 7 | const Self = @This(); | |
| 8 | x: T, | |
| 9 | y: T, | |
| 10 | ||
| 11 | fn addOne(self: *Self) void { | |
| 12 | self.x += 1; | |
| 13 | self.y += 1; | |
| 14 | } | |
| 15 | }; | |
| 16 | } | |
| 17 | ||
| 18 | fn add(x: i32, y: i32) i32 { | |
| 19 | return x + y; | |
| 20 | } | |
| 21 | ||
| 22 | test "this refer to module call private fn" { | |
| 23 | assert(module.add(1, 2) == 3); | |
| 24 | } | |
| 25 | ||
| 26 | test "this refer to container" { | |
| 27 | var pt = Point(i32){ | |
| 28 | .x = 12, | |
| 29 | .y = 34, | |
| 30 | }; | |
| 31 | pt.addOne(); | |
| 32 | assert(pt.x == 13); | |
| 33 | assert(pt.y == 35); | |
| 34 | } |
test/cases/truncate.zig deleted-8| ... | ... | @@ -1,8 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | ||
| 4 | test "truncate u0 to larger integer allowed and has comptime known result" { | |
| 5 | var x: u0 = 0; | |
| 6 | const y = @truncate(u8, x); | |
| 7 | comptime assert(y == 0); | |
| 8 | } |
test/cases/try.zig deleted-43| ... | ... | @@ -1,43 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "try on error union" { | |
| 4 | tryOnErrorUnionImpl(); | |
| 5 | comptime tryOnErrorUnionImpl(); | |
| 6 | } | |
| 7 | ||
| 8 | fn tryOnErrorUnionImpl() void { | |
| 9 | const x = if (returnsTen()) |val| val + 1 else |err| switch (err) { | |
| 10 | error.ItBroke, error.NoMem => 1, | |
| 11 | error.CrappedOut => i32(2), | |
| 12 | else => unreachable, | |
| 13 | }; | |
| 14 | assert(x == 11); | |
| 15 | } | |
| 16 | ||
| 17 | fn returnsTen() anyerror!i32 { | |
| 18 | return 10; | |
| 19 | } | |
| 20 | ||
| 21 | test "try without vars" { | |
| 22 | const result1 = if (failIfTrue(true)) 1 else |_| i32(2); | |
| 23 | assert(result1 == 2); | |
| 24 | ||
| 25 | const result2 = if (failIfTrue(false)) 1 else |_| i32(2); | |
| 26 | assert(result2 == 1); | |
| 27 | } | |
| 28 | ||
| 29 | fn failIfTrue(ok: bool) anyerror!void { | |
| 30 | if (ok) { | |
| 31 | return error.ItBroke; | |
| 32 | } else { | |
| 33 | return; | |
| 34 | } | |
| 35 | } | |
| 36 | ||
| 37 | test "try then not executed with assignment" { | |
| 38 | if (failIfTrue(true)) { | |
| 39 | unreachable; | |
| 40 | } else |err| { | |
| 41 | assert(err == error.ItBroke); | |
| 42 | } | |
| 43 | } |
test/cases/type_info.zig deleted-264| ... | ... | @@ -1,264 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | const mem = @import("std").mem; | |
| 3 | const TypeInfo = @import("builtin").TypeInfo; | |
| 4 | const TypeId = @import("builtin").TypeId; | |
| 5 | ||
| 6 | test "type info: tag type, void info" { | |
| 7 | testBasic(); | |
| 8 | comptime testBasic(); | |
| 9 | } | |
| 10 | ||
| 11 | fn testBasic() void { | |
| 12 | assert(@TagType(TypeInfo) == TypeId); | |
| 13 | const void_info = @typeInfo(void); | |
| 14 | assert(TypeId(void_info) == TypeId.Void); | |
| 15 | assert(void_info.Void == {}); | |
| 16 | } | |
| 17 | ||
| 18 | test "type info: integer, floating point type info" { | |
| 19 | testIntFloat(); | |
| 20 | comptime testIntFloat(); | |
| 21 | } | |
| 22 | ||
| 23 | fn testIntFloat() void { | |
| 24 | const u8_info = @typeInfo(u8); | |
| 25 | assert(TypeId(u8_info) == TypeId.Int); | |
| 26 | assert(!u8_info.Int.is_signed); | |
| 27 | assert(u8_info.Int.bits == 8); | |
| 28 | ||
| 29 | const f64_info = @typeInfo(f64); | |
| 30 | assert(TypeId(f64_info) == TypeId.Float); | |
| 31 | assert(f64_info.Float.bits == 64); | |
| 32 | } | |
| 33 | ||
| 34 | test "type info: pointer type info" { | |
| 35 | testPointer(); | |
| 36 | comptime testPointer(); | |
| 37 | } | |
| 38 | ||
| 39 | fn testPointer() void { | |
| 40 | const u32_ptr_info = @typeInfo(*u32); | |
| 41 | assert(TypeId(u32_ptr_info) == TypeId.Pointer); | |
| 42 | assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); | |
| 43 | assert(u32_ptr_info.Pointer.is_const == false); | |
| 44 | assert(u32_ptr_info.Pointer.is_volatile == false); | |
| 45 | assert(u32_ptr_info.Pointer.alignment == @alignOf(u32)); | |
| 46 | assert(u32_ptr_info.Pointer.child == u32); | |
| 47 | } | |
| 48 | ||
| 49 | test "type info: unknown length pointer type info" { | |
| 50 | testUnknownLenPtr(); | |
| 51 | comptime testUnknownLenPtr(); | |
| 52 | } | |
| 53 | ||
| 54 | fn testUnknownLenPtr() void { | |
| 55 | const u32_ptr_info = @typeInfo([*]const volatile f64); | |
| 56 | assert(TypeId(u32_ptr_info) == TypeId.Pointer); | |
| 57 | assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); | |
| 58 | assert(u32_ptr_info.Pointer.is_const == true); | |
| 59 | assert(u32_ptr_info.Pointer.is_volatile == true); | |
| 60 | assert(u32_ptr_info.Pointer.alignment == @alignOf(f64)); | |
| 61 | assert(u32_ptr_info.Pointer.child == f64); | |
| 62 | } | |
| 63 | ||
| 64 | test "type info: slice type info" { | |
| 65 | testSlice(); | |
| 66 | comptime testSlice(); | |
| 67 | } | |
| 68 | ||
| 69 | fn testSlice() void { | |
| 70 | const u32_slice_info = @typeInfo([]u32); | |
| 71 | assert(TypeId(u32_slice_info) == TypeId.Pointer); | |
| 72 | assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); | |
| 73 | assert(u32_slice_info.Pointer.is_const == false); | |
| 74 | assert(u32_slice_info.Pointer.is_volatile == false); | |
| 75 | assert(u32_slice_info.Pointer.alignment == 4); | |
| 76 | assert(u32_slice_info.Pointer.child == u32); | |
| 77 | } | |
| 78 | ||
| 79 | test "type info: array type info" { | |
| 80 | testArray(); | |
| 81 | comptime testArray(); | |
| 82 | } | |
| 83 | ||
| 84 | fn testArray() void { | |
| 85 | const arr_info = @typeInfo([42]bool); | |
| 86 | assert(TypeId(arr_info) == TypeId.Array); | |
| 87 | assert(arr_info.Array.len == 42); | |
| 88 | assert(arr_info.Array.child == bool); | |
| 89 | } | |
| 90 | ||
| 91 | test "type info: optional type info" { | |
| 92 | testOptional(); | |
| 93 | comptime testOptional(); | |
| 94 | } | |
| 95 | ||
| 96 | fn testOptional() void { | |
| 97 | const null_info = @typeInfo(?void); | |
| 98 | assert(TypeId(null_info) == TypeId.Optional); | |
| 99 | assert(null_info.Optional.child == void); | |
| 100 | } | |
| 101 | ||
| 102 | test "type info: promise info" { | |
| 103 | testPromise(); | |
| 104 | comptime testPromise(); | |
| 105 | } | |
| 106 | ||
| 107 | fn testPromise() void { | |
| 108 | const null_promise_info = @typeInfo(promise); | |
| 109 | assert(TypeId(null_promise_info) == TypeId.Promise); | |
| 110 | assert(null_promise_info.Promise.child == null); | |
| 111 | ||
| 112 | const promise_info = @typeInfo(promise->usize); | |
| 113 | assert(TypeId(promise_info) == TypeId.Promise); | |
| 114 | assert(promise_info.Promise.child.? == usize); | |
| 115 | } | |
| 116 | ||
| 117 | test "type info: error set, error union info" { | |
| 118 | testErrorSet(); | |
| 119 | comptime testErrorSet(); | |
| 120 | } | |
| 121 | ||
| 122 | fn testErrorSet() void { | |
| 123 | const TestErrorSet = error{ | |
| 124 | First, | |
| 125 | Second, | |
| 126 | Third, | |
| 127 | }; | |
| 128 | ||
| 129 | const error_set_info = @typeInfo(TestErrorSet); | |
| 130 | assert(TypeId(error_set_info) == TypeId.ErrorSet); | |
| 131 | assert(error_set_info.ErrorSet.errors.len == 3); | |
| 132 | assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); | |
| 133 | assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third)); | |
| 134 | ||
| 135 | const error_union_info = @typeInfo(TestErrorSet!usize); | |
| 136 | assert(TypeId(error_union_info) == TypeId.ErrorUnion); | |
| 137 | assert(error_union_info.ErrorUnion.error_set == TestErrorSet); | |
| 138 | assert(error_union_info.ErrorUnion.payload == usize); | |
| 139 | } | |
| 140 | ||
| 141 | test "type info: enum info" { | |
| 142 | testEnum(); | |
| 143 | comptime testEnum(); | |
| 144 | } | |
| 145 | ||
| 146 | fn testEnum() void { | |
| 147 | const Os = enum { | |
| 148 | Windows, | |
| 149 | Macos, | |
| 150 | Linux, | |
| 151 | FreeBSD, | |
| 152 | }; | |
| 153 | ||
| 154 | const os_info = @typeInfo(Os); | |
| 155 | assert(TypeId(os_info) == TypeId.Enum); | |
| 156 | assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); | |
| 157 | assert(os_info.Enum.fields.len == 4); | |
| 158 | assert(mem.eql(u8, os_info.Enum.fields[1].name, "Macos")); | |
| 159 | assert(os_info.Enum.fields[3].value == 3); | |
| 160 | assert(os_info.Enum.tag_type == u2); | |
| 161 | assert(os_info.Enum.defs.len == 0); | |
| 162 | } | |
| 163 | ||
| 164 | test "type info: union info" { | |
| 165 | testUnion(); | |
| 166 | comptime testUnion(); | |
| 167 | } | |
| 168 | ||
| 169 | fn testUnion() void { | |
| 170 | const typeinfo_info = @typeInfo(TypeInfo); | |
| 171 | assert(TypeId(typeinfo_info) == TypeId.Union); | |
| 172 | assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); | |
| 173 | assert(typeinfo_info.Union.tag_type.? == TypeId); | |
| 174 | assert(typeinfo_info.Union.fields.len == 24); | |
| 175 | assert(typeinfo_info.Union.fields[4].enum_field != null); | |
| 176 | assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4); | |
| 177 | assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); | |
| 178 | assert(typeinfo_info.Union.defs.len == 20); | |
| 179 | ||
| 180 | const TestNoTagUnion = union { | |
| 181 | Foo: void, | |
| 182 | Bar: u32, | |
| 183 | }; | |
| 184 | ||
| 185 | const notag_union_info = @typeInfo(TestNoTagUnion); | |
| 186 | assert(TypeId(notag_union_info) == TypeId.Union); | |
| 187 | assert(notag_union_info.Union.tag_type == null); | |
| 188 | assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); | |
| 189 | assert(notag_union_info.Union.fields.len == 2); | |
| 190 | assert(notag_union_info.Union.fields[0].enum_field == null); | |
| 191 | assert(notag_union_info.Union.fields[1].field_type == u32); | |
| 192 | ||
| 193 | const TestExternUnion = extern union { | |
| 194 | foo: *c_void, | |
| 195 | }; | |
| 196 | ||
| 197 | const extern_union_info = @typeInfo(TestExternUnion); | |
| 198 | assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); | |
| 199 | assert(extern_union_info.Union.tag_type == null); | |
| 200 | assert(extern_union_info.Union.fields[0].enum_field == null); | |
| 201 | assert(extern_union_info.Union.fields[0].field_type == *c_void); | |
| 202 | } | |
| 203 | ||
| 204 | test "type info: struct info" { | |
| 205 | testStruct(); | |
| 206 | comptime testStruct(); | |
| 207 | } | |
| 208 | ||
| 209 | fn testStruct() void { | |
| 210 | const struct_info = @typeInfo(TestStruct); | |
| 211 | assert(TypeId(struct_info) == TypeId.Struct); | |
| 212 | assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); | |
| 213 | assert(struct_info.Struct.fields.len == 3); | |
| 214 | assert(struct_info.Struct.fields[1].offset == null); | |
| 215 | assert(struct_info.Struct.fields[2].field_type == *TestStruct); | |
| 216 | assert(struct_info.Struct.defs.len == 2); | |
| 217 | assert(struct_info.Struct.defs[0].is_pub); | |
| 218 | assert(!struct_info.Struct.defs[0].data.Fn.is_extern); | |
| 219 | assert(struct_info.Struct.defs[0].data.Fn.lib_name == null); | |
| 220 | assert(struct_info.Struct.defs[0].data.Fn.return_type == void); | |
| 221 | assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void); | |
| 222 | } | |
| 223 | ||
| 224 | const TestStruct = packed struct { | |
| 225 | const Self = @This(); | |
| 226 | ||
| 227 | fieldA: usize, | |
| 228 | fieldB: void, | |
| 229 | fieldC: *Self, | |
| 230 | ||
| 231 | pub fn foo(self: *const Self) void {} | |
| 232 | }; | |
| 233 | ||
| 234 | test "type info: function type info" { | |
| 235 | testFunction(); | |
| 236 | comptime testFunction(); | |
| 237 | } | |
| 238 | ||
| 239 | fn testFunction() void { | |
| 240 | const fn_info = @typeInfo(@typeOf(foo)); | |
| 241 | assert(TypeId(fn_info) == TypeId.Fn); | |
| 242 | assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); | |
| 243 | assert(fn_info.Fn.is_generic); | |
| 244 | assert(fn_info.Fn.args.len == 2); | |
| 245 | assert(fn_info.Fn.is_var_args); | |
| 246 | assert(fn_info.Fn.return_type == null); | |
| 247 | assert(fn_info.Fn.async_allocator_type == null); | |
| 248 | ||
| 249 | const test_instance: TestStruct = undefined; | |
| 250 | const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); | |
| 251 | assert(TypeId(bound_fn_info) == TypeId.BoundFn); | |
| 252 | assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct); | |
| 253 | } | |
| 254 | ||
| 255 | fn foo(comptime a: usize, b: bool, args: ...) usize { | |
| 256 | return 0; | |
| 257 | } | |
| 258 | ||
| 259 | test "typeInfo with comptime parameter in struct fn def" { | |
| 260 | const S = struct { | |
| 261 | pub fn func(comptime x: f32) void {} | |
| 262 | }; | |
| 263 | comptime var info = @typeInfo(S); | |
| 264 | } |
test/cases/undefined.zig deleted-68| ... | ... | @@ -1,68 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | const mem = @import("std").mem; | |
| 3 | ||
| 4 | fn initStaticArray() [10]i32 { | |
| 5 | var array: [10]i32 = undefined; | |
| 6 | array[0] = 1; | |
| 7 | array[4] = 2; | |
| 8 | array[7] = 3; | |
| 9 | array[9] = 4; | |
| 10 | return array; | |
| 11 | } | |
| 12 | const static_array = initStaticArray(); | |
| 13 | test "init static array to undefined" { | |
| 14 | assert(static_array[0] == 1); | |
| 15 | assert(static_array[4] == 2); | |
| 16 | assert(static_array[7] == 3); | |
| 17 | assert(static_array[9] == 4); | |
| 18 | ||
| 19 | comptime { | |
| 20 | assert(static_array[0] == 1); | |
| 21 | assert(static_array[4] == 2); | |
| 22 | assert(static_array[7] == 3); | |
| 23 | assert(static_array[9] == 4); | |
| 24 | } | |
| 25 | } | |
| 26 | ||
| 27 | const Foo = struct { | |
| 28 | x: i32, | |
| 29 | ||
| 30 | fn setFooXMethod(foo: *Foo) void { | |
| 31 | foo.x = 3; | |
| 32 | } | |
| 33 | }; | |
| 34 | ||
| 35 | fn setFooX(foo: *Foo) void { | |
| 36 | foo.x = 2; | |
| 37 | } | |
| 38 | ||
| 39 | test "assign undefined to struct" { | |
| 40 | comptime { | |
| 41 | var foo: Foo = undefined; | |
| 42 | setFooX(&foo); | |
| 43 | assert(foo.x == 2); | |
| 44 | } | |
| 45 | { | |
| 46 | var foo: Foo = undefined; | |
| 47 | setFooX(&foo); | |
| 48 | assert(foo.x == 2); | |
| 49 | } | |
| 50 | } | |
| 51 | ||
| 52 | test "assign undefined to struct with method" { | |
| 53 | comptime { | |
| 54 | var foo: Foo = undefined; | |
| 55 | foo.setFooXMethod(); | |
| 56 | assert(foo.x == 3); | |
| 57 | } | |
| 58 | { | |
| 59 | var foo: Foo = undefined; | |
| 60 | foo.setFooXMethod(); | |
| 61 | assert(foo.x == 3); | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 65 | test "type name of undefined" { | |
| 66 | const x = undefined; | |
| 67 | assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)")); | |
| 68 | } |
test/cases/underscore.zig deleted-28| ... | ... | @@ -1,28 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | ||
| 4 | test "ignore lval with underscore" { | |
| 5 | _ = false; | |
| 6 | } | |
| 7 | ||
| 8 | test "ignore lval with underscore (for loop)" { | |
| 9 | for ([]void{}) |_, i| { | |
| 10 | for ([]void{}) |_, j| { | |
| 11 | break; | |
| 12 | } | |
| 13 | break; | |
| 14 | } | |
| 15 | } | |
| 16 | ||
| 17 | test "ignore lval with underscore (while loop)" { | |
| 18 | while (optionalReturnError()) |_| { | |
| 19 | while (optionalReturnError()) |_| { | |
| 20 | break; | |
| 21 | } else |_| {} | |
| 22 | break; | |
| 23 | } else |_| {} | |
| 24 | } | |
| 25 | ||
| 26 | fn optionalReturnError() !?u32 { | |
| 27 | return error.optionalReturnError; | |
| 28 | } |
test/cases/union.zig deleted-352| ... | ... | @@ -1,352 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | const Value = union(enum) { | |
| 4 | Int: u64, | |
| 5 | Array: [9]u8, | |
| 6 | }; | |
| 7 | ||
| 8 | const Agg = struct { | |
| 9 | val1: Value, | |
| 10 | val2: Value, | |
| 11 | }; | |
| 12 | ||
| 13 | const v1 = Value{ .Int = 1234 }; | |
| 14 | const v2 = Value{ .Array = []u8{3} ** 9 }; | |
| 15 | ||
| 16 | const err = (anyerror!Agg)(Agg{ | |
| 17 | .val1 = v1, | |
| 18 | .val2 = v2, | |
| 19 | }); | |
| 20 | ||
| 21 | const array = []Value{ | |
| 22 | v1, | |
| 23 | v2, | |
| 24 | v1, | |
| 25 | v2, | |
| 26 | }; | |
| 27 | ||
| 28 | test "unions embedded in aggregate types" { | |
| 29 | switch (array[1]) { | |
| 30 | Value.Array => |arr| assert(arr[4] == 3), | |
| 31 | else => unreachable, | |
| 32 | } | |
| 33 | switch ((err catch unreachable).val1) { | |
| 34 | Value.Int => |x| assert(x == 1234), | |
| 35 | else => unreachable, | |
| 36 | } | |
| 37 | } | |
| 38 | ||
| 39 | const Foo = union { | |
| 40 | float: f64, | |
| 41 | int: i32, | |
| 42 | }; | |
| 43 | ||
| 44 | test "basic unions" { | |
| 45 | var foo = Foo{ .int = 1 }; | |
| 46 | assert(foo.int == 1); | |
| 47 | foo = Foo{ .float = 12.34 }; | |
| 48 | assert(foo.float == 12.34); | |
| 49 | } | |
| 50 | ||
| 51 | test "comptime union field access" { | |
| 52 | comptime { | |
| 53 | var foo = Foo{ .int = 0 }; | |
| 54 | assert(foo.int == 0); | |
| 55 | ||
| 56 | foo = Foo{ .float = 42.42 }; | |
| 57 | assert(foo.float == 42.42); | |
| 58 | } | |
| 59 | } | |
| 60 | ||
| 61 | test "init union with runtime value" { | |
| 62 | var foo: Foo = undefined; | |
| 63 | ||
| 64 | setFloat(&foo, 12.34); | |
| 65 | assert(foo.float == 12.34); | |
| 66 | ||
| 67 | setInt(&foo, 42); | |
| 68 | assert(foo.int == 42); | |
| 69 | } | |
| 70 | ||
| 71 | fn setFloat(foo: *Foo, x: f64) void { | |
| 72 | foo.* = Foo{ .float = x }; | |
| 73 | } | |
| 74 | ||
| 75 | fn setInt(foo: *Foo, x: i32) void { | |
| 76 | foo.* = Foo{ .int = x }; | |
| 77 | } | |
| 78 | ||
| 79 | const FooExtern = extern union { | |
| 80 | float: f64, | |
| 81 | int: i32, | |
| 82 | }; | |
| 83 | ||
| 84 | test "basic extern unions" { | |
| 85 | var foo = FooExtern{ .int = 1 }; | |
| 86 | assert(foo.int == 1); | |
| 87 | foo.float = 12.34; | |
| 88 | assert(foo.float == 12.34); | |
| 89 | } | |
| 90 | ||
| 91 | const Letter = enum { | |
| 92 | A, | |
| 93 | B, | |
| 94 | C, | |
| 95 | }; | |
| 96 | const Payload = union(Letter) { | |
| 97 | A: i32, | |
| 98 | B: f64, | |
| 99 | C: bool, | |
| 100 | }; | |
| 101 | ||
| 102 | test "union with specified enum tag" { | |
| 103 | doTest(); | |
| 104 | comptime doTest(); | |
| 105 | } | |
| 106 | ||
| 107 | fn doTest() void { | |
| 108 | assert(bar(Payload{ .A = 1234 }) == -10); | |
| 109 | } | |
| 110 | ||
| 111 | fn bar(value: Payload) i32 { | |
| 112 | assert(Letter(value) == Letter.A); | |
| 113 | return switch (value) { | |
| 114 | Payload.A => |x| return x - 1244, | |
| 115 | Payload.B => |x| if (x == 12.34) i32(20) else 21, | |
| 116 | Payload.C => |x| if (x) i32(30) else 31, | |
| 117 | }; | |
| 118 | } | |
| 119 | ||
| 120 | const MultipleChoice = union(enum(u32)) { | |
| 121 | A = 20, | |
| 122 | B = 40, | |
| 123 | C = 60, | |
| 124 | D = 1000, | |
| 125 | }; | |
| 126 | test "simple union(enum(u32))" { | |
| 127 | var x = MultipleChoice.C; | |
| 128 | assert(x == MultipleChoice.C); | |
| 129 | assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60); | |
| 130 | } | |
| 131 | ||
| 132 | const MultipleChoice2 = union(enum(u32)) { | |
| 133 | Unspecified1: i32, | |
| 134 | A: f32 = 20, | |
| 135 | Unspecified2: void, | |
| 136 | B: bool = 40, | |
| 137 | Unspecified3: i32, | |
| 138 | C: i8 = 60, | |
| 139 | Unspecified4: void, | |
| 140 | D: void = 1000, | |
| 141 | Unspecified5: i32, | |
| 142 | }; | |
| 143 | ||
| 144 | test "union(enum(u32)) with specified and unspecified tag values" { | |
| 145 | comptime assert(@TagType(@TagType(MultipleChoice2)) == u32); | |
| 146 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | |
| 147 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | |
| 148 | } | |
| 149 | ||
| 150 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { | |
| 151 | assert(@enumToInt(@TagType(MultipleChoice2)(x)) == 60); | |
| 152 | assert(1123 == switch (x) { | |
| 153 | MultipleChoice2.A => 1, | |
| 154 | MultipleChoice2.B => 2, | |
| 155 | MultipleChoice2.C => |v| i32(1000) + v, | |
| 156 | MultipleChoice2.D => 4, | |
| 157 | MultipleChoice2.Unspecified1 => 5, | |
| 158 | MultipleChoice2.Unspecified2 => 6, | |
| 159 | MultipleChoice2.Unspecified3 => 7, | |
| 160 | MultipleChoice2.Unspecified4 => 8, | |
| 161 | MultipleChoice2.Unspecified5 => 9, | |
| 162 | }); | |
| 163 | } | |
| 164 | ||
| 165 | const ExternPtrOrInt = extern union { | |
| 166 | ptr: *u8, | |
| 167 | int: u64, | |
| 168 | }; | |
| 169 | test "extern union size" { | |
| 170 | comptime assert(@sizeOf(ExternPtrOrInt) == 8); | |
| 171 | } | |
| 172 | ||
| 173 | const PackedPtrOrInt = packed union { | |
| 174 | ptr: *u8, | |
| 175 | int: u64, | |
| 176 | }; | |
| 177 | test "extern union size" { | |
| 178 | comptime assert(@sizeOf(PackedPtrOrInt) == 8); | |
| 179 | } | |
| 180 | ||
| 181 | const ZeroBits = union { | |
| 182 | OnlyField: void, | |
| 183 | }; | |
| 184 | test "union with only 1 field which is void should be zero bits" { | |
| 185 | comptime assert(@sizeOf(ZeroBits) == 0); | |
| 186 | } | |
| 187 | ||
| 188 | const TheTag = enum { | |
| 189 | A, | |
| 190 | B, | |
| 191 | C, | |
| 192 | }; | |
| 193 | const TheUnion = union(TheTag) { | |
| 194 | A: i32, | |
| 195 | B: i32, | |
| 196 | C: i32, | |
| 197 | }; | |
| 198 | test "union field access gives the enum values" { | |
| 199 | assert(TheUnion.A == TheTag.A); | |
| 200 | assert(TheUnion.B == TheTag.B); | |
| 201 | assert(TheUnion.C == TheTag.C); | |
| 202 | } | |
| 203 | ||
| 204 | test "cast union to tag type of union" { | |
| 205 | testCastUnionToTagType(TheUnion{ .B = 1234 }); | |
| 206 | comptime testCastUnionToTagType(TheUnion{ .B = 1234 }); | |
| 207 | } | |
| 208 | ||
| 209 | fn testCastUnionToTagType(x: TheUnion) void { | |
| 210 | assert(TheTag(x) == TheTag.B); | |
| 211 | } | |
| 212 | ||
| 213 | test "cast tag type of union to union" { | |
| 214 | var x: Value2 = Letter2.B; | |
| 215 | assert(Letter2(x) == Letter2.B); | |
| 216 | } | |
| 217 | const Letter2 = enum { | |
| 218 | A, | |
| 219 | B, | |
| 220 | C, | |
| 221 | }; | |
| 222 | const Value2 = union(Letter2) { | |
| 223 | A: i32, | |
| 224 | B, | |
| 225 | C, | |
| 226 | }; | |
| 227 | ||
| 228 | test "implicit cast union to its tag type" { | |
| 229 | var x: Value2 = Letter2.B; | |
| 230 | assert(x == Letter2.B); | |
| 231 | giveMeLetterB(x); | |
| 232 | } | |
| 233 | fn giveMeLetterB(x: Letter2) void { | |
| 234 | assert(x == Value2.B); | |
| 235 | } | |
| 236 | ||
| 237 | pub const PackThis = union(enum) { | |
| 238 | Invalid: bool, | |
| 239 | StringLiteral: u2, | |
| 240 | }; | |
| 241 | ||
| 242 | test "constant packed union" { | |
| 243 | testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }}); | |
| 244 | } | |
| 245 | ||
| 246 | fn testConstPackedUnion(expected_tokens: []const PackThis) void { | |
| 247 | assert(expected_tokens[0].StringLiteral == 1); | |
| 248 | } | |
| 249 | ||
| 250 | test "switch on union with only 1 field" { | |
| 251 | var r: PartialInst = undefined; | |
| 252 | r = PartialInst.Compiled; | |
| 253 | switch (r) { | |
| 254 | PartialInst.Compiled => { | |
| 255 | var z: PartialInstWithPayload = undefined; | |
| 256 | z = PartialInstWithPayload{ .Compiled = 1234 }; | |
| 257 | switch (z) { | |
| 258 | PartialInstWithPayload.Compiled => |x| { | |
| 259 | assert(x == 1234); | |
| 260 | return; | |
| 261 | }, | |
| 262 | } | |
| 263 | }, | |
| 264 | } | |
| 265 | unreachable; | |
| 266 | } | |
| 267 | ||
| 268 | const PartialInst = union(enum) { | |
| 269 | Compiled, | |
| 270 | }; | |
| 271 | ||
| 272 | const PartialInstWithPayload = union(enum) { | |
| 273 | Compiled: i32, | |
| 274 | }; | |
| 275 | ||
| 276 | test "access a member of tagged union with conflicting enum tag name" { | |
| 277 | const Bar = union(enum) { | |
| 278 | A: A, | |
| 279 | B: B, | |
| 280 | ||
| 281 | const A = u8; | |
| 282 | const B = void; | |
| 283 | }; | |
| 284 | ||
| 285 | comptime assert(Bar.A == u8); | |
| 286 | } | |
| 287 | ||
| 288 | test "tagged union initialization with runtime void" { | |
| 289 | assert(testTaggedUnionInit({})); | |
| 290 | } | |
| 291 | ||
| 292 | const TaggedUnionWithAVoid = union(enum) { | |
| 293 | A, | |
| 294 | B: i32, | |
| 295 | }; | |
| 296 | ||
| 297 | fn testTaggedUnionInit(x: var) bool { | |
| 298 | const y = TaggedUnionWithAVoid{ .A = x }; | |
| 299 | return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A; | |
| 300 | } | |
| 301 | ||
| 302 | pub const UnionEnumNoPayloads = union(enum) { | |
| 303 | A, | |
| 304 | B, | |
| 305 | }; | |
| 306 | ||
| 307 | test "tagged union with no payloads" { | |
| 308 | const a = UnionEnumNoPayloads{ .B = {} }; | |
| 309 | switch (a) { | |
| 310 | @TagType(UnionEnumNoPayloads).A => @panic("wrong"), | |
| 311 | @TagType(UnionEnumNoPayloads).B => {}, | |
| 312 | } | |
| 313 | } | |
| 314 | ||
| 315 | test "union with only 1 field casted to its enum type" { | |
| 316 | const Literal = union(enum) { | |
| 317 | Number: f64, | |
| 318 | Bool: bool, | |
| 319 | }; | |
| 320 | ||
| 321 | const Expr = union(enum) { | |
| 322 | Literal: Literal, | |
| 323 | }; | |
| 324 | ||
| 325 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | |
| 326 | const Tag = @TagType(Expr); | |
| 327 | comptime assert(@TagType(Tag) == comptime_int); | |
| 328 | var t = Tag(e); | |
| 329 | assert(t == Expr.Literal); | |
| 330 | } | |
| 331 | ||
| 332 | test "union with only 1 field casted to its enum type which has enum value specified" { | |
| 333 | const Literal = union(enum) { | |
| 334 | Number: f64, | |
| 335 | Bool: bool, | |
| 336 | }; | |
| 337 | ||
| 338 | const Tag = enum { | |
| 339 | Literal = 33, | |
| 340 | }; | |
| 341 | ||
| 342 | const Expr = union(Tag) { | |
| 343 | Literal: Literal, | |
| 344 | }; | |
| 345 | ||
| 346 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | |
| 347 | comptime assert(@TagType(Tag) == comptime_int); | |
| 348 | var t = Tag(e); | |
| 349 | assert(t == Expr.Literal); | |
| 350 | assert(@enumToInt(t) == 33); | |
| 351 | comptime assert(@enumToInt(t) == 33); | |
| 352 | } |
test/cases/var_args.zig deleted-84| ... | ... | @@ -1,84 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | fn add(args: ...) i32 { | |
| 4 | var sum = i32(0); | |
| 5 | { | |
| 6 | comptime var i: usize = 0; | |
| 7 | inline while (i < args.len) : (i += 1) { | |
| 8 | sum += args[i]; | |
| 9 | } | |
| 10 | } | |
| 11 | return sum; | |
| 12 | } | |
| 13 | ||
| 14 | test "add arbitrary args" { | |
| 15 | assert(add(i32(1), i32(2), i32(3), i32(4)) == 10); | |
| 16 | assert(add(i32(1234)) == 1234); | |
| 17 | assert(add() == 0); | |
| 18 | } | |
| 19 | ||
| 20 | fn readFirstVarArg(args: ...) void { | |
| 21 | const value = args[0]; | |
| 22 | } | |
| 23 | ||
| 24 | test "send void arg to var args" { | |
| 25 | readFirstVarArg({}); | |
| 26 | } | |
| 27 | ||
| 28 | test "pass args directly" { | |
| 29 | assert(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10); | |
| 30 | assert(addSomeStuff(i32(1234)) == 1234); | |
| 31 | assert(addSomeStuff() == 0); | |
| 32 | } | |
| 33 | ||
| 34 | fn addSomeStuff(args: ...) i32 { | |
| 35 | return add(args); | |
| 36 | } | |
| 37 | ||
| 38 | test "runtime parameter before var args" { | |
| 39 | assert(extraFn(10) == 0); | |
| 40 | assert(extraFn(10, false) == 1); | |
| 41 | assert(extraFn(10, false, true) == 2); | |
| 42 | ||
| 43 | // TODO issue #313 | |
| 44 | //comptime { | |
| 45 | // assert(extraFn(10) == 0); | |
| 46 | // assert(extraFn(10, false) == 1); | |
| 47 | // assert(extraFn(10, false, true) == 2); | |
| 48 | //} | |
| 49 | } | |
| 50 | ||
| 51 | fn extraFn(extra: u32, args: ...) usize { | |
| 52 | if (args.len >= 1) { | |
| 53 | assert(args[0] == false); | |
| 54 | } | |
| 55 | if (args.len >= 2) { | |
| 56 | assert(args[1] == true); | |
| 57 | } | |
| 58 | return args.len; | |
| 59 | } | |
| 60 | ||
| 61 | const foos = []fn (...) bool{ | |
| 62 | foo1, | |
| 63 | foo2, | |
| 64 | }; | |
| 65 | ||
| 66 | fn foo1(args: ...) bool { | |
| 67 | return true; | |
| 68 | } | |
| 69 | fn foo2(args: ...) bool { | |
| 70 | return false; | |
| 71 | } | |
| 72 | ||
| 73 | test "array of var args functions" { | |
| 74 | assert(foos[0]()); | |
| 75 | assert(!foos[1]()); | |
| 76 | } | |
| 77 | ||
| 78 | test "pass zero length array to var args param" { | |
| 79 | doNothingWithFirstArg(""); | |
| 80 | } | |
| 81 | ||
| 82 | fn doNothingWithFirstArg(args: ...) void { | |
| 83 | const a = args[0]; | |
| 84 | } |
test/cases/void.zig deleted-30| ... | ... | @@ -1,30 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | const Foo = struct { | |
| 4 | a: void, | |
| 5 | b: i32, | |
| 6 | c: void, | |
| 7 | }; | |
| 8 | ||
| 9 | test "compare void with void compile time known" { | |
| 10 | comptime { | |
| 11 | const foo = Foo{ | |
| 12 | .a = {}, | |
| 13 | .b = 1, | |
| 14 | .c = {}, | |
| 15 | }; | |
| 16 | assert(foo.a == {}); | |
| 17 | } | |
| 18 | } | |
| 19 | ||
| 20 | test "iterate over a void slice" { | |
| 21 | var j: usize = 0; | |
| 22 | for (times(10)) |_, i| { | |
| 23 | assert(i == j); | |
| 24 | j += 1; | |
| 25 | } | |
| 26 | } | |
| 27 | ||
| 28 | fn times(n: usize) []const void { | |
| 29 | return ([*]void)(undefined)[0..n]; | |
| 30 | } |
test/cases/while.zig deleted-227| ... | ... | @@ -1,227 +0,0 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 2 | ||
| 3 | test "while loop" { | |
| 4 | var i: i32 = 0; | |
| 5 | while (i < 4) { | |
| 6 | i += 1; | |
| 7 | } | |
| 8 | assert(i == 4); | |
| 9 | assert(whileLoop1() == 1); | |
| 10 | } | |
| 11 | fn whileLoop1() i32 { | |
| 12 | return whileLoop2(); | |
| 13 | } | |
| 14 | fn whileLoop2() i32 { | |
| 15 | while (true) { | |
| 16 | return 1; | |
| 17 | } | |
| 18 | } | |
| 19 | test "static eval while" { | |
| 20 | assert(static_eval_while_number == 1); | |
| 21 | } | |
| 22 | const static_eval_while_number = staticWhileLoop1(); | |
| 23 | fn staticWhileLoop1() i32 { | |
| 24 | return whileLoop2(); | |
| 25 | } | |
| 26 | fn staticWhileLoop2() i32 { | |
| 27 | while (true) { | |
| 28 | return 1; | |
| 29 | } | |
| 30 | } | |
| 31 | ||
| 32 | test "continue and break" { | |
| 33 | runContinueAndBreakTest(); | |
| 34 | assert(continue_and_break_counter == 8); | |
| 35 | } | |
| 36 | var continue_and_break_counter: i32 = 0; | |
| 37 | fn runContinueAndBreakTest() void { | |
| 38 | var i: i32 = 0; | |
| 39 | while (true) { | |
| 40 | continue_and_break_counter += 2; | |
| 41 | i += 1; | |
| 42 | if (i < 4) { | |
| 43 | continue; | |
| 44 | } | |
| 45 | break; | |
| 46 | } | |
| 47 | assert(i == 4); | |
| 48 | } | |
| 49 | ||
| 50 | test "return with implicit cast from while loop" { | |
| 51 | returnWithImplicitCastFromWhileLoopTest() catch unreachable; | |
| 52 | } | |
| 53 | fn returnWithImplicitCastFromWhileLoopTest() anyerror!void { | |
| 54 | while (true) { | |
| 55 | return; | |
| 56 | } | |
| 57 | } | |
| 58 | ||
| 59 | test "while with continue expression" { | |
| 60 | var sum: i32 = 0; | |
| 61 | { | |
| 62 | var i: i32 = 0; | |
| 63 | while (i < 10) : (i += 1) { | |
| 64 | if (i == 5) continue; | |
| 65 | sum += i; | |
| 66 | } | |
| 67 | } | |
| 68 | assert(sum == 40); | |
| 69 | } | |
| 70 | ||
| 71 | test "while with else" { | |
| 72 | var sum: i32 = 0; | |
| 73 | var i: i32 = 0; | |
| 74 | var got_else: i32 = 0; | |
| 75 | while (i < 10) : (i += 1) { | |
| 76 | sum += 1; | |
| 77 | } else { | |
| 78 | got_else += 1; | |
| 79 | } | |
| 80 | assert(sum == 10); | |
| 81 | assert(got_else == 1); | |
| 82 | } | |
| 83 | ||
| 84 | test "while with optional as condition" { | |
| 85 | numbers_left = 10; | |
| 86 | var sum: i32 = 0; | |
| 87 | while (getNumberOrNull()) |value| { | |
| 88 | sum += value; | |
| 89 | } | |
| 90 | assert(sum == 45); | |
| 91 | } | |
| 92 | ||
| 93 | test "while with optional as condition with else" { | |
| 94 | numbers_left = 10; | |
| 95 | var sum: i32 = 0; | |
| 96 | var got_else: i32 = 0; | |
| 97 | while (getNumberOrNull()) |value| { | |
| 98 | sum += value; | |
| 99 | assert(got_else == 0); | |
| 100 | } else { | |
| 101 | got_else += 1; | |
| 102 | } | |
| 103 | assert(sum == 45); | |
| 104 | assert(got_else == 1); | |
| 105 | } | |
| 106 | ||
| 107 | test "while with error union condition" { | |
| 108 | numbers_left = 10; | |
| 109 | var sum: i32 = 0; | |
| 110 | var got_else: i32 = 0; | |
| 111 | while (getNumberOrErr()) |value| { | |
| 112 | sum += value; | |
| 113 | } else |err| { | |
| 114 | assert(err == error.OutOfNumbers); | |
| 115 | got_else += 1; | |
| 116 | } | |
| 117 | assert(sum == 45); | |
| 118 | assert(got_else == 1); | |
| 119 | } | |
| 120 | ||
| 121 | var numbers_left: i32 = undefined; | |
| 122 | fn getNumberOrErr() anyerror!i32 { | |
| 123 | return if (numbers_left == 0) error.OutOfNumbers else x: { | |
| 124 | numbers_left -= 1; | |
| 125 | break :x numbers_left; | |
| 126 | }; | |
| 127 | } | |
| 128 | fn getNumberOrNull() ?i32 { | |
| 129 | return if (numbers_left == 0) null else x: { | |
| 130 | numbers_left -= 1; | |
| 131 | break :x numbers_left; | |
| 132 | }; | |
| 133 | } | |
| 134 | ||
| 135 | test "while on optional with else result follow else prong" { | |
| 136 | const result = while (returnNull()) |value| { | |
| 137 | break value; | |
| 138 | } else | |
| 139 | i32(2); | |
| 140 | assert(result == 2); | |
| 141 | } | |
| 142 | ||
| 143 | test "while on optional with else result follow break prong" { | |
| 144 | const result = while (returnOptional(10)) |value| { | |
| 145 | break value; | |
| 146 | } else | |
| 147 | i32(2); | |
| 148 | assert(result == 10); | |
| 149 | } | |
| 150 | ||
| 151 | test "while on error union with else result follow else prong" { | |
| 152 | const result = while (returnError()) |value| { | |
| 153 | break value; | |
| 154 | } else |err| | |
| 155 | i32(2); | |
| 156 | assert(result == 2); | |
| 157 | } | |
| 158 | ||
| 159 | test "while on error union with else result follow break prong" { | |
| 160 | const result = while (returnSuccess(10)) |value| { | |
| 161 | break value; | |
| 162 | } else |err| | |
| 163 | i32(2); | |
| 164 | assert(result == 10); | |
| 165 | } | |
| 166 | ||
| 167 | test "while on bool with else result follow else prong" { | |
| 168 | const result = while (returnFalse()) { | |
| 169 | break i32(10); | |
| 170 | } else | |
| 171 | i32(2); | |
| 172 | assert(result == 2); | |
| 173 | } | |
| 174 | ||
| 175 | test "while on bool with else result follow break prong" { | |
| 176 | const result = while (returnTrue()) { | |
| 177 | break i32(10); | |
| 178 | } else | |
| 179 | i32(2); | |
| 180 | assert(result == 10); | |
| 181 | } | |
| 182 | ||
| 183 | test "break from outer while loop" { | |
| 184 | testBreakOuter(); | |
| 185 | comptime testBreakOuter(); | |
| 186 | } | |
| 187 | ||
| 188 | fn testBreakOuter() void { | |
| 189 | outer: while (true) { | |
| 190 | while (true) { | |
| 191 | break :outer; | |
| 192 | } | |
| 193 | } | |
| 194 | } | |
| 195 | ||
| 196 | test "continue outer while loop" { | |
| 197 | testContinueOuter(); | |
| 198 | comptime testContinueOuter(); | |
| 199 | } | |
| 200 | ||
| 201 | fn testContinueOuter() void { | |
| 202 | var i: usize = 0; | |
| 203 | outer: while (i < 10) : (i += 1) { | |
| 204 | while (true) { | |
| 205 | continue :outer; | |
| 206 | } | |
| 207 | } | |
| 208 | } | |
| 209 | ||
| 210 | fn returnNull() ?i32 { | |
| 211 | return null; | |
| 212 | } | |
| 213 | fn returnOptional(x: i32) ?i32 { | |
| 214 | return x; | |
| 215 | } | |
| 216 | fn returnError() anyerror!i32 { | |
| 217 | return error.YouWantedAnError; | |
| 218 | } | |
| 219 | fn returnSuccess(x: i32) anyerror!i32 { | |
| 220 | return x; | |
| 221 | } | |
| 222 | fn returnFalse() bool { | |
| 223 | return false; | |
| 224 | } | |
| 225 | fn returnTrue() bool { | |
| 226 | return true; | |
| 227 | } |
test/cases/widening.zig deleted-27| ... | ... | @@ -1,27 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | const mem = std.mem; | |
| 4 | ||
| 5 | test "integer widening" { | |
| 6 | var a: u8 = 250; | |
| 7 | var b: u16 = a; | |
| 8 | var c: u32 = b; | |
| 9 | var d: u64 = c; | |
| 10 | var e: u64 = d; | |
| 11 | var f: u128 = e; | |
| 12 | assert(f == a); | |
| 13 | } | |
| 14 | ||
| 15 | test "implicit unsigned integer to signed integer" { | |
| 16 | var a: u8 = 250; | |
| 17 | var b: i16 = a; | |
| 18 | assert(b == 250); | |
| 19 | } | |
| 20 | ||
| 21 | test "float widening" { | |
| 22 | var a: f16 = 12.34; | |
| 23 | var b: f32 = a; | |
| 24 | var c: f64 = b; | |
| 25 | var d: f128 = c; | |
| 26 | assert(d == a); | |
| 27 | } |
test/compile_errors.zig+2-2| ... | ... | @@ -3220,7 +3220,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3220 | 3220 | \\ return 2; |
| 3221 | 3221 | \\} |
| 3222 | 3222 | , |
| 3223 | ".tmp_source.zig:2:15: error: unable to infer expression type", | |
| 3223 | ".tmp_source.zig:2:15: error: values of type 'comptime_int' must be comptime known", | |
| 3224 | 3224 | ); |
| 3225 | 3225 | |
| 3226 | 3226 | cases.add( |
| ... | ... | @@ -3566,7 +3566,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3566 | 3566 | \\ |
| 3567 | 3567 | \\export fn entry() usize { return @sizeOf(@typeOf(a)); } |
| 3568 | 3568 | , |
| 3569 | ".tmp_source.zig:2:11: error: expected type, found 'i32'", | |
| 3569 | ".tmp_source.zig:2:11: error: expected type 'type', found 'i32'", | |
| 3570 | 3570 | ); |
| 3571 | 3571 | |
| 3572 | 3572 | cases.add( |
test/stage1/behavior.zig created+80| ... | ... | @@ -0,0 +1,80 @@ |
| 1 | comptime { | |
| 2 | _ = @import("behavior/align.zig"); | |
| 3 | _ = @import("behavior/alignof.zig"); | |
| 4 | _ = @import("behavior/array.zig"); | |
| 5 | _ = @import("behavior/asm.zig"); | |
| 6 | _ = @import("behavior/atomics.zig"); | |
| 7 | _ = @import("behavior/bit_shifting.zig"); | |
| 8 | _ = @import("behavior/bitcast.zig"); | |
| 9 | _ = @import("behavior/bitreverse.zig"); | |
| 10 | _ = @import("behavior/bool.zig"); | |
| 11 | _ = @import("behavior/bswap.zig"); | |
| 12 | _ = @import("behavior/bugs/1076.zig"); | |
| 13 | _ = @import("behavior/bugs/1111.zig"); | |
| 14 | _ = @import("behavior/bugs/1277.zig"); | |
| 15 | _ = @import("behavior/bugs/1322.zig"); | |
| 16 | _ = @import("behavior/bugs/1381.zig"); | |
| 17 | _ = @import("behavior/bugs/1421.zig"); | |
| 18 | _ = @import("behavior/bugs/1442.zig"); | |
| 19 | _ = @import("behavior/bugs/1486.zig"); | |
| 20 | _ = @import("behavior/bugs/394.zig"); | |
| 21 | _ = @import("behavior/bugs/655.zig"); | |
| 22 | _ = @import("behavior/bugs/656.zig"); | |
| 23 | _ = @import("behavior/bugs/726.zig"); | |
| 24 | _ = @import("behavior/bugs/828.zig"); | |
| 25 | _ = @import("behavior/bugs/920.zig"); | |
| 26 | _ = @import("behavior/byval_arg_var.zig"); | |
| 27 | _ = @import("behavior/cancel.zig"); | |
| 28 | _ = @import("behavior/cast.zig"); | |
| 29 | _ = @import("behavior/const_slice_child.zig"); | |
| 30 | _ = @import("behavior/coroutine_await_struct.zig"); | |
| 31 | _ = @import("behavior/coroutines.zig"); | |
| 32 | _ = @import("behavior/defer.zig"); | |
| 33 | _ = @import("behavior/enum.zig"); | |
| 34 | _ = @import("behavior/enum_with_members.zig"); | |
| 35 | _ = @import("behavior/error.zig"); | |
| 36 | _ = @import("behavior/eval.zig"); | |
| 37 | _ = @import("behavior/field_parent_ptr.zig"); | |
| 38 | _ = @import("behavior/fn.zig"); | |
| 39 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); | |
| 40 | _ = @import("behavior/for.zig"); | |
| 41 | _ = @import("behavior/generics.zig"); | |
| 42 | _ = @import("behavior/if.zig"); | |
| 43 | _ = @import("behavior/import.zig"); | |
| 44 | _ = @import("behavior/incomplete_struct_param_tld.zig"); | |
| 45 | _ = @import("behavior/inttoptr.zig"); | |
| 46 | _ = @import("behavior/ir_block_deps.zig"); | |
| 47 | _ = @import("behavior/math.zig"); | |
| 48 | _ = @import("behavior/merge_error_sets.zig"); | |
| 49 | _ = @import("behavior/misc.zig"); | |
| 50 | _ = @import("behavior/namespace_depends_on_compile_var/index.zig"); | |
| 51 | _ = @import("behavior/new_stack_call.zig"); | |
| 52 | _ = @import("behavior/null.zig"); | |
| 53 | _ = @import("behavior/optional.zig"); | |
| 54 | _ = @import("behavior/pointers.zig"); | |
| 55 | _ = @import("behavior/popcount.zig"); | |
| 56 | _ = @import("behavior/ptrcast.zig"); | |
| 57 | _ = @import("behavior/pub_enum/index.zig"); | |
| 58 | _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig"); | |
| 59 | _ = @import("behavior/reflection.zig"); | |
| 60 | _ = @import("behavior/sizeof_and_typeof.zig"); | |
| 61 | _ = @import("behavior/slice.zig"); | |
| 62 | _ = @import("behavior/struct.zig"); | |
| 63 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); | |
| 64 | _ = @import("behavior/struct_contains_slice_of_itself.zig"); | |
| 65 | _ = @import("behavior/switch.zig"); | |
| 66 | _ = @import("behavior/switch_prong_err_enum.zig"); | |
| 67 | _ = @import("behavior/switch_prong_implicit_cast.zig"); | |
| 68 | _ = @import("behavior/syntax.zig"); | |
| 69 | _ = @import("behavior/this.zig"); | |
| 70 | _ = @import("behavior/truncate.zig"); | |
| 71 | _ = @import("behavior/try.zig"); | |
| 72 | _ = @import("behavior/type_info.zig"); | |
| 73 | _ = @import("behavior/undefined.zig"); | |
| 74 | _ = @import("behavior/underscore.zig"); | |
| 75 | _ = @import("behavior/union.zig"); | |
| 76 | _ = @import("behavior/var_args.zig"); | |
| 77 | _ = @import("behavior/void.zig"); | |
| 78 | _ = @import("behavior/while.zig"); | |
| 79 | _ = @import("behavior/widening.zig"); | |
| 80 | } |
test/stage1/behavior/align.zig created+230| ... | ... | @@ -0,0 +1,230 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | const builtin = @import("builtin"); | |
| 3 | ||
| 4 | var foo: u8 align(4) = 100; | |
| 5 | ||
| 6 | test "global variable alignment" { | |
| 7 | assertOrPanic(@typeOf(&foo).alignment == 4); | |
| 8 | assertOrPanic(@typeOf(&foo) == *align(4) u8); | |
| 9 | const slice = (*[1]u8)(&foo)[0..]; | |
| 10 | assertOrPanic(@typeOf(slice) == []align(4) u8); | |
| 11 | } | |
| 12 | ||
| 13 | fn derp() align(@sizeOf(usize) * 2) i32 { | |
| 14 | return 1234; | |
| 15 | } | |
| 16 | fn noop1() align(1) void {} | |
| 17 | fn noop4() align(4) void {} | |
| 18 | ||
| 19 | test "function alignment" { | |
| 20 | assertOrPanic(derp() == 1234); | |
| 21 | assertOrPanic(@typeOf(noop1) == fn () align(1) void); | |
| 22 | assertOrPanic(@typeOf(noop4) == fn () align(4) void); | |
| 23 | noop1(); | |
| 24 | noop4(); | |
| 25 | } | |
| 26 | ||
| 27 | var baz: packed struct { | |
| 28 | a: u32, | |
| 29 | b: u32, | |
| 30 | } = undefined; | |
| 31 | ||
| 32 | test "packed struct alignment" { | |
| 33 | assertOrPanic(@typeOf(&baz.b) == *align(1) u32); | |
| 34 | } | |
| 35 | ||
| 36 | const blah: packed struct { | |
| 37 | a: u3, | |
| 38 | b: u3, | |
| 39 | c: u2, | |
| 40 | } = undefined; | |
| 41 | ||
| 42 | test "bit field alignment" { | |
| 43 | assertOrPanic(@typeOf(&blah.b) == *align(1:3:1) const u3); | |
| 44 | } | |
| 45 | ||
| 46 | test "default alignment allows unspecified in type syntax" { | |
| 47 | assertOrPanic(*u32 == *align(@alignOf(u32)) u32); | |
| 48 | } | |
| 49 | ||
| 50 | test "implicitly decreasing pointer alignment" { | |
| 51 | const a: u32 align(4) = 3; | |
| 52 | const b: u32 align(8) = 4; | |
| 53 | assertOrPanic(addUnaligned(&a, &b) == 7); | |
| 54 | } | |
| 55 | ||
| 56 | fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { | |
| 57 | return a.* + b.*; | |
| 58 | } | |
| 59 | ||
| 60 | test "implicitly decreasing slice alignment" { | |
| 61 | const a: u32 align(4) = 3; | |
| 62 | const b: u32 align(8) = 4; | |
| 63 | assertOrPanic(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7); | |
| 64 | } | |
| 65 | fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { | |
| 66 | return a[0] + b[0]; | |
| 67 | } | |
| 68 | ||
| 69 | test "specifying alignment allows pointer cast" { | |
| 70 | testBytesAlign(0x33); | |
| 71 | } | |
| 72 | fn testBytesAlign(b: u8) void { | |
| 73 | var bytes align(4) = []u8{ | |
| 74 | b, | |
| 75 | b, | |
| 76 | b, | |
| 77 | b, | |
| 78 | }; | |
| 79 | const ptr = @ptrCast(*u32, &bytes[0]); | |
| 80 | assertOrPanic(ptr.* == 0x33333333); | |
| 81 | } | |
| 82 | ||
| 83 | test "specifying alignment allows slice cast" { | |
| 84 | testBytesAlignSlice(0x33); | |
| 85 | } | |
| 86 | fn testBytesAlignSlice(b: u8) void { | |
| 87 | var bytes align(4) = []u8{ | |
| 88 | b, | |
| 89 | b, | |
| 90 | b, | |
| 91 | b, | |
| 92 | }; | |
| 93 | const slice: []u32 = @bytesToSlice(u32, bytes[0..]); | |
| 94 | assertOrPanic(slice[0] == 0x33333333); | |
| 95 | } | |
| 96 | ||
| 97 | test "@alignCast pointers" { | |
| 98 | var x: u32 align(4) = 1; | |
| 99 | expectsOnly1(&x); | |
| 100 | assertOrPanic(x == 2); | |
| 101 | } | |
| 102 | fn expectsOnly1(x: *align(1) u32) void { | |
| 103 | expects4(@alignCast(4, x)); | |
| 104 | } | |
| 105 | fn expects4(x: *align(4) u32) void { | |
| 106 | x.* += 1; | |
| 107 | } | |
| 108 | ||
| 109 | test "@alignCast slices" { | |
| 110 | var array align(4) = []u32{ | |
| 111 | 1, | |
| 112 | 1, | |
| 113 | }; | |
| 114 | const slice = array[0..]; | |
| 115 | sliceExpectsOnly1(slice); | |
| 116 | assertOrPanic(slice[0] == 2); | |
| 117 | } | |
| 118 | fn sliceExpectsOnly1(slice: []align(1) u32) void { | |
| 119 | sliceExpects4(@alignCast(4, slice)); | |
| 120 | } | |
| 121 | fn sliceExpects4(slice: []align(4) u32) void { | |
| 122 | slice[0] += 1; | |
| 123 | } | |
| 124 | ||
| 125 | test "implicitly decreasing fn alignment" { | |
| 126 | testImplicitlyDecreaseFnAlign(alignedSmall, 1234); | |
| 127 | testImplicitlyDecreaseFnAlign(alignedBig, 5678); | |
| 128 | } | |
| 129 | ||
| 130 | fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void { | |
| 131 | assertOrPanic(ptr() == answer); | |
| 132 | } | |
| 133 | ||
| 134 | fn alignedSmall() align(8) i32 { | |
| 135 | return 1234; | |
| 136 | } | |
| 137 | fn alignedBig() align(16) i32 { | |
| 138 | return 5678; | |
| 139 | } | |
| 140 | ||
| 141 | test "@alignCast functions" { | |
| 142 | assertOrPanic(fnExpectsOnly1(simple4) == 0x19); | |
| 143 | } | |
| 144 | fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 { | |
| 145 | return fnExpects4(@alignCast(4, ptr)); | |
| 146 | } | |
| 147 | fn fnExpects4(ptr: fn () align(4) i32) i32 { | |
| 148 | return ptr(); | |
| 149 | } | |
| 150 | fn simple4() align(4) i32 { | |
| 151 | return 0x19; | |
| 152 | } | |
| 153 | ||
| 154 | test "generic function with align param" { | |
| 155 | assertOrPanic(whyWouldYouEverDoThis(1) == 0x1); | |
| 156 | assertOrPanic(whyWouldYouEverDoThis(4) == 0x1); | |
| 157 | assertOrPanic(whyWouldYouEverDoThis(8) == 0x1); | |
| 158 | } | |
| 159 | ||
| 160 | fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 { | |
| 161 | return 0x1; | |
| 162 | } | |
| 163 | ||
| 164 | test "@ptrCast preserves alignment of bigger source" { | |
| 165 | var x: u32 align(16) = 1234; | |
| 166 | const ptr = @ptrCast(*u8, &x); | |
| 167 | assertOrPanic(@typeOf(ptr) == *align(16) u8); | |
| 168 | } | |
| 169 | ||
| 170 | test "runtime known array index has best alignment possible" { | |
| 171 | // take full advantage of over-alignment | |
| 172 | var array align(4) = []u8{ 1, 2, 3, 4 }; | |
| 173 | assertOrPanic(@typeOf(&array[0]) == *align(4) u8); | |
| 174 | assertOrPanic(@typeOf(&array[1]) == *u8); | |
| 175 | assertOrPanic(@typeOf(&array[2]) == *align(2) u8); | |
| 176 | assertOrPanic(@typeOf(&array[3]) == *u8); | |
| 177 | ||
| 178 | // because align is too small but we still figure out to use 2 | |
| 179 | var bigger align(2) = []u64{ 1, 2, 3, 4 }; | |
| 180 | assertOrPanic(@typeOf(&bigger[0]) == *align(2) u64); | |
| 181 | assertOrPanic(@typeOf(&bigger[1]) == *align(2) u64); | |
| 182 | assertOrPanic(@typeOf(&bigger[2]) == *align(2) u64); | |
| 183 | assertOrPanic(@typeOf(&bigger[3]) == *align(2) u64); | |
| 184 | ||
| 185 | // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2 | |
| 186 | var smaller align(2) = []u32{ 1, 2, 3, 4 }; | |
| 187 | comptime assertOrPanic(@typeOf(smaller[0..]) == []align(2) u32); | |
| 188 | comptime assertOrPanic(@typeOf(smaller[0..].ptr) == [*]align(2) u32); | |
| 189 | testIndex(smaller[0..].ptr, 0, *align(2) u32); | |
| 190 | testIndex(smaller[0..].ptr, 1, *align(2) u32); | |
| 191 | testIndex(smaller[0..].ptr, 2, *align(2) u32); | |
| 192 | testIndex(smaller[0..].ptr, 3, *align(2) u32); | |
| 193 | ||
| 194 | // has to use ABI alignment because index known at runtime only | |
| 195 | testIndex2(array[0..].ptr, 0, *u8); | |
| 196 | testIndex2(array[0..].ptr, 1, *u8); | |
| 197 | testIndex2(array[0..].ptr, 2, *u8); | |
| 198 | testIndex2(array[0..].ptr, 3, *u8); | |
| 199 | } | |
| 200 | fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void { | |
| 201 | comptime assertOrPanic(@typeOf(&smaller[index]) == T); | |
| 202 | } | |
| 203 | fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void { | |
| 204 | comptime assertOrPanic(@typeOf(&ptr[index]) == T); | |
| 205 | } | |
| 206 | ||
| 207 | test "alignstack" { | |
| 208 | assertOrPanic(fnWithAlignedStack() == 1234); | |
| 209 | } | |
| 210 | ||
| 211 | fn fnWithAlignedStack() i32 { | |
| 212 | @setAlignStack(256); | |
| 213 | return 1234; | |
| 214 | } | |
| 215 | ||
| 216 | test "alignment of structs" { | |
| 217 | assertOrPanic(@alignOf(struct { | |
| 218 | a: i32, | |
| 219 | b: *i32, | |
| 220 | }) == @alignOf(usize)); | |
| 221 | } | |
| 222 | ||
| 223 | test "alignment of extern() void" { | |
| 224 | var runtime_nothing = nothing; | |
| 225 | const casted1 = @ptrCast(*const u8, runtime_nothing); | |
| 226 | const casted2 = @ptrCast(extern fn () void, casted1); | |
| 227 | casted2(); | |
| 228 | } | |
| 229 | ||
| 230 | extern fn nothing() void {} |
test/stage1/behavior/alignof.zig created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | const maxInt = std.math.maxInt; | |
| 5 | ||
| 6 | const Foo = struct { | |
| 7 | x: u32, | |
| 8 | y: u32, | |
| 9 | z: u32, | |
| 10 | }; | |
| 11 | ||
| 12 | test "@alignOf(T) before referencing T" { | |
| 13 | comptime assertOrPanic(@alignOf(Foo) != maxInt(usize)); | |
| 14 | if (builtin.arch == builtin.Arch.x86_64) { | |
| 15 | comptime assertOrPanic(@alignOf(Foo) == 4); | |
| 16 | } | |
| 17 | } | |
| 18 |
test/stage1/behavior/array.zig created+270| ... | ... | @@ -0,0 +1,270 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | const mem = @import("std").mem; | |
| 3 | ||
| 4 | test "arrays" { | |
| 5 | var array: [5]u32 = undefined; | |
| 6 | ||
| 7 | var i: u32 = 0; | |
| 8 | while (i < 5) { | |
| 9 | array[i] = i + 1; | |
| 10 | i = array[i]; | |
| 11 | } | |
| 12 | ||
| 13 | i = 0; | |
| 14 | var accumulator = u32(0); | |
| 15 | while (i < 5) { | |
| 16 | accumulator += array[i]; | |
| 17 | ||
| 18 | i += 1; | |
| 19 | } | |
| 20 | ||
| 21 | assertOrPanic(accumulator == 15); | |
| 22 | assertOrPanic(getArrayLen(array) == 5); | |
| 23 | } | |
| 24 | fn getArrayLen(a: []const u32) usize { | |
| 25 | return a.len; | |
| 26 | } | |
| 27 | ||
| 28 | test "void arrays" { | |
| 29 | var array: [4]void = undefined; | |
| 30 | array[0] = void{}; | |
| 31 | array[1] = array[2]; | |
| 32 | assertOrPanic(@sizeOf(@typeOf(array)) == 0); | |
| 33 | assertOrPanic(array.len == 4); | |
| 34 | } | |
| 35 | ||
| 36 | test "array literal" { | |
| 37 | const hex_mult = []u16{ | |
| 38 | 4096, | |
| 39 | 256, | |
| 40 | 16, | |
| 41 | 1, | |
| 42 | }; | |
| 43 | ||
| 44 | assertOrPanic(hex_mult.len == 4); | |
| 45 | assertOrPanic(hex_mult[1] == 256); | |
| 46 | } | |
| 47 | ||
| 48 | test "array dot len const expr" { | |
| 49 | assertOrPanic(comptime x: { | |
| 50 | break :x some_array.len == 4; | |
| 51 | }); | |
| 52 | } | |
| 53 | ||
| 54 | const ArrayDotLenConstExpr = struct { | |
| 55 | y: [some_array.len]u8, | |
| 56 | }; | |
| 57 | const some_array = []u8{ | |
| 58 | 0, | |
| 59 | 1, | |
| 60 | 2, | |
| 61 | 3, | |
| 62 | }; | |
| 63 | ||
| 64 | test "nested arrays" { | |
| 65 | const array_of_strings = [][]const u8{ | |
| 66 | "hello", | |
| 67 | "this", | |
| 68 | "is", | |
| 69 | "my", | |
| 70 | "thing", | |
| 71 | }; | |
| 72 | for (array_of_strings) |s, i| { | |
| 73 | if (i == 0) assertOrPanic(mem.eql(u8, s, "hello")); | |
| 74 | if (i == 1) assertOrPanic(mem.eql(u8, s, "this")); | |
| 75 | if (i == 2) assertOrPanic(mem.eql(u8, s, "is")); | |
| 76 | if (i == 3) assertOrPanic(mem.eql(u8, s, "my")); | |
| 77 | if (i == 4) assertOrPanic(mem.eql(u8, s, "thing")); | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 81 | var s_array: [8]Sub = undefined; | |
| 82 | const Sub = struct { | |
| 83 | b: u8, | |
| 84 | }; | |
| 85 | const Str = struct { | |
| 86 | a: []Sub, | |
| 87 | }; | |
| 88 | test "set global var array via slice embedded in struct" { | |
| 89 | var s = Str{ .a = s_array[0..] }; | |
| 90 | ||
| 91 | s.a[0].b = 1; | |
| 92 | s.a[1].b = 2; | |
| 93 | s.a[2].b = 3; | |
| 94 | ||
| 95 | assertOrPanic(s_array[0].b == 1); | |
| 96 | assertOrPanic(s_array[1].b == 2); | |
| 97 | assertOrPanic(s_array[2].b == 3); | |
| 98 | } | |
| 99 | ||
| 100 | test "array literal with specified size" { | |
| 101 | var array = [2]u8{ | |
| 102 | 1, | |
| 103 | 2, | |
| 104 | }; | |
| 105 | assertOrPanic(array[0] == 1); | |
| 106 | assertOrPanic(array[1] == 2); | |
| 107 | } | |
| 108 | ||
| 109 | test "array child property" { | |
| 110 | var x: [5]i32 = undefined; | |
| 111 | assertOrPanic(@typeOf(x).Child == i32); | |
| 112 | } | |
| 113 | ||
| 114 | test "array len property" { | |
| 115 | var x: [5]i32 = undefined; | |
| 116 | assertOrPanic(@typeOf(x).len == 5); | |
| 117 | } | |
| 118 | ||
| 119 | test "array len field" { | |
| 120 | var arr = [4]u8{ 0, 0, 0, 0 }; | |
| 121 | var ptr = &arr; | |
| 122 | assertOrPanic(arr.len == 4); | |
| 123 | comptime assertOrPanic(arr.len == 4); | |
| 124 | assertOrPanic(ptr.len == 4); | |
| 125 | comptime assertOrPanic(ptr.len == 4); | |
| 126 | } | |
| 127 | ||
| 128 | test "single-item pointer to array indexing and slicing" { | |
| 129 | testSingleItemPtrArrayIndexSlice(); | |
| 130 | comptime testSingleItemPtrArrayIndexSlice(); | |
| 131 | } | |
| 132 | ||
| 133 | fn testSingleItemPtrArrayIndexSlice() void { | |
| 134 | var array = "aaaa"; | |
| 135 | doSomeMangling(&array); | |
| 136 | assertOrPanic(mem.eql(u8, "azya", array)); | |
| 137 | } | |
| 138 | ||
| 139 | fn doSomeMangling(array: *[4]u8) void { | |
| 140 | array[1] = 'z'; | |
| 141 | array[2..3][0] = 'y'; | |
| 142 | } | |
| 143 | ||
| 144 | test "implicit cast single-item pointer" { | |
| 145 | testImplicitCastSingleItemPtr(); | |
| 146 | comptime testImplicitCastSingleItemPtr(); | |
| 147 | } | |
| 148 | ||
| 149 | fn testImplicitCastSingleItemPtr() void { | |
| 150 | var byte: u8 = 100; | |
| 151 | const slice = (*[1]u8)(&byte)[0..]; | |
| 152 | slice[0] += 1; | |
| 153 | assertOrPanic(byte == 101); | |
| 154 | } | |
| 155 | ||
| 156 | fn testArrayByValAtComptime(b: [2]u8) u8 { | |
| 157 | return b[0]; | |
| 158 | } | |
| 159 | ||
| 160 | test "comptime evalutating function that takes array by value" { | |
| 161 | const arr = []u8{ 0, 1 }; | |
| 162 | _ = comptime testArrayByValAtComptime(arr); | |
| 163 | _ = comptime testArrayByValAtComptime(arr); | |
| 164 | } | |
| 165 | ||
| 166 | test "implicit comptime in array type size" { | |
| 167 | var arr: [plusOne(10)]bool = undefined; | |
| 168 | assertOrPanic(arr.len == 11); | |
| 169 | } | |
| 170 | ||
| 171 | fn plusOne(x: u32) u32 { | |
| 172 | return x + 1; | |
| 173 | } | |
| 174 | ||
| 175 | test "array literal as argument to function" { | |
| 176 | const S = struct { | |
| 177 | fn entry(two: i32) void { | |
| 178 | foo([]i32{ | |
| 179 | 1, | |
| 180 | 2, | |
| 181 | 3, | |
| 182 | }); | |
| 183 | foo([]i32{ | |
| 184 | 1, | |
| 185 | two, | |
| 186 | 3, | |
| 187 | }); | |
| 188 | foo2(true, []i32{ | |
| 189 | 1, | |
| 190 | 2, | |
| 191 | 3, | |
| 192 | }); | |
| 193 | foo2(true, []i32{ | |
| 194 | 1, | |
| 195 | two, | |
| 196 | 3, | |
| 197 | }); | |
| 198 | } | |
| 199 | fn foo(x: []const i32) void { | |
| 200 | assertOrPanic(x[0] == 1); | |
| 201 | assertOrPanic(x[1] == 2); | |
| 202 | assertOrPanic(x[2] == 3); | |
| 203 | } | |
| 204 | fn foo2(trash: bool, x: []const i32) void { | |
| 205 | assertOrPanic(trash); | |
| 206 | assertOrPanic(x[0] == 1); | |
| 207 | assertOrPanic(x[1] == 2); | |
| 208 | assertOrPanic(x[2] == 3); | |
| 209 | } | |
| 210 | }; | |
| 211 | S.entry(2); | |
| 212 | comptime S.entry(2); | |
| 213 | } | |
| 214 | ||
| 215 | test "double nested array to const slice cast in array literal" { | |
| 216 | const S = struct { | |
| 217 | fn entry(two: i32) void { | |
| 218 | const cases = [][]const []const i32{ | |
| 219 | [][]const i32{[]i32{1}}, | |
| 220 | [][]const i32{[]i32{ 2, 3 }}, | |
| 221 | [][]const i32{ | |
| 222 | []i32{4}, | |
| 223 | []i32{ 5, 6, 7 }, | |
| 224 | }, | |
| 225 | }; | |
| 226 | check(cases); | |
| 227 | ||
| 228 | const cases2 = [][]const i32{ | |
| 229 | []i32{1}, | |
| 230 | []i32{ two, 3 }, | |
| 231 | }; | |
| 232 | assertOrPanic(cases2.len == 2); | |
| 233 | assertOrPanic(cases2[0].len == 1); | |
| 234 | assertOrPanic(cases2[0][0] == 1); | |
| 235 | assertOrPanic(cases2[1].len == 2); | |
| 236 | assertOrPanic(cases2[1][0] == 2); | |
| 237 | assertOrPanic(cases2[1][1] == 3); | |
| 238 | ||
| 239 | const cases3 = [][]const []const i32{ | |
| 240 | [][]const i32{[]i32{1}}, | |
| 241 | [][]const i32{[]i32{ two, 3 }}, | |
| 242 | [][]const i32{ | |
| 243 | []i32{4}, | |
| 244 | []i32{ 5, 6, 7 }, | |
| 245 | }, | |
| 246 | }; | |
| 247 | check(cases3); | |
| 248 | } | |
| 249 | ||
| 250 | fn check(cases: []const []const []const i32) void { | |
| 251 | assertOrPanic(cases.len == 3); | |
| 252 | assertOrPanic(cases[0].len == 1); | |
| 253 | assertOrPanic(cases[0][0].len == 1); | |
| 254 | assertOrPanic(cases[0][0][0] == 1); | |
| 255 | assertOrPanic(cases[1].len == 1); | |
| 256 | assertOrPanic(cases[1][0].len == 2); | |
| 257 | assertOrPanic(cases[1][0][0] == 2); | |
| 258 | assertOrPanic(cases[1][0][1] == 3); | |
| 259 | assertOrPanic(cases[2].len == 2); | |
| 260 | assertOrPanic(cases[2][0].len == 1); | |
| 261 | assertOrPanic(cases[2][0][0] == 4); | |
| 262 | assertOrPanic(cases[2][1].len == 3); | |
| 263 | assertOrPanic(cases[2][1][0] == 5); | |
| 264 | assertOrPanic(cases[2][1][1] == 6); | |
| 265 | assertOrPanic(cases[2][1][2] == 7); | |
| 266 | } | |
| 267 | }; | |
| 268 | S.entry(2); | |
| 269 | comptime S.entry(2); | |
| 270 | } |
test/stage1/behavior/asm.zig created+92| ... | ... | @@ -0,0 +1,92 @@ |
| 1 | const config = @import("builtin"); | |
| 2 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 3 | ||
| 4 | comptime { | |
| 5 | if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { | |
| 6 | asm volatile ( | |
| 7 | \\.globl aoeu; | |
| 8 | \\.type aoeu, @function; | |
| 9 | \\.set aoeu, derp; | |
| 10 | ); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | test "module level assembly" { | |
| 15 | if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { | |
| 16 | assertOrPanic(aoeu() == 1234); | |
| 17 | } | |
| 18 | } | |
| 19 | ||
| 20 | test "output constraint modifiers" { | |
| 21 | // This is only testing compilation. | |
| 22 | var a: u32 = 3; | |
| 23 | asm volatile ("" | |
| 24 | : [_] "=m,r" (a) | |
| 25 | : | |
| 26 | : "" | |
| 27 | ); | |
| 28 | asm volatile ("" | |
| 29 | : [_] "=r,m" (a) | |
| 30 | : | |
| 31 | : "" | |
| 32 | ); | |
| 33 | } | |
| 34 | ||
| 35 | test "alternative constraints" { | |
| 36 | // Make sure we allow commas as a separator for alternative constraints. | |
| 37 | var a: u32 = 3; | |
| 38 | asm volatile ("" | |
| 39 | : [_] "=r,m" (a) | |
| 40 | : [_] "r,m" (a) | |
| 41 | : "" | |
| 42 | ); | |
| 43 | } | |
| 44 | ||
| 45 | test "sized integer/float in asm input" { | |
| 46 | asm volatile ("" | |
| 47 | : | |
| 48 | : [_] "m" (usize(3)) | |
| 49 | : "" | |
| 50 | ); | |
| 51 | asm volatile ("" | |
| 52 | : | |
| 53 | : [_] "m" (i15(-3)) | |
| 54 | : "" | |
| 55 | ); | |
| 56 | asm volatile ("" | |
| 57 | : | |
| 58 | : [_] "m" (u3(3)) | |
| 59 | : "" | |
| 60 | ); | |
| 61 | asm volatile ("" | |
| 62 | : | |
| 63 | : [_] "m" (i3(3)) | |
| 64 | : "" | |
| 65 | ); | |
| 66 | asm volatile ("" | |
| 67 | : | |
| 68 | : [_] "m" (u121(3)) | |
| 69 | : "" | |
| 70 | ); | |
| 71 | asm volatile ("" | |
| 72 | : | |
| 73 | : [_] "m" (i121(3)) | |
| 74 | : "" | |
| 75 | ); | |
| 76 | asm volatile ("" | |
| 77 | : | |
| 78 | : [_] "m" (f32(3.17)) | |
| 79 | : "" | |
| 80 | ); | |
| 81 | asm volatile ("" | |
| 82 | : | |
| 83 | : [_] "m" (f64(3.17)) | |
| 84 | : "" | |
| 85 | ); | |
| 86 | } | |
| 87 | ||
| 88 | extern fn aoeu() i32; | |
| 89 | ||
| 90 | export fn derp() i32 { | |
| 91 | return 1234; | |
| 92 | } |
test/stage1/behavior/atomics.zig created+71| ... | ... | @@ -0,0 +1,71 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | const AtomicRmwOp = builtin.AtomicRmwOp; | |
| 5 | const AtomicOrder = builtin.AtomicOrder; | |
| 6 | ||
| 7 | test "cmpxchg" { | |
| 8 | var x: i32 = 1234; | |
| 9 | if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | |
| 10 | assertOrPanic(x1 == 1234); | |
| 11 | } else { | |
| 12 | @panic("cmpxchg should have failed"); | |
| 13 | } | |
| 14 | ||
| 15 | while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | |
| 16 | assertOrPanic(x1 == 1234); | |
| 17 | } | |
| 18 | assertOrPanic(x == 5678); | |
| 19 | ||
| 20 | assertOrPanic(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); | |
| 21 | assertOrPanic(x == 42); | |
| 22 | } | |
| 23 | ||
| 24 | test "fence" { | |
| 25 | var x: i32 = 1234; | |
| 26 | @fence(AtomicOrder.SeqCst); | |
| 27 | x = 5678; | |
| 28 | } | |
| 29 | ||
| 30 | test "atomicrmw and atomicload" { | |
| 31 | var data: u8 = 200; | |
| 32 | testAtomicRmw(&data); | |
| 33 | assertOrPanic(data == 42); | |
| 34 | testAtomicLoad(&data); | |
| 35 | } | |
| 36 | ||
| 37 | fn testAtomicRmw(ptr: *u8) void { | |
| 38 | const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst); | |
| 39 | assertOrPanic(prev_value == 200); | |
| 40 | comptime { | |
| 41 | var x: i32 = 1234; | |
| 42 | const y: i32 = 12345; | |
| 43 | assertOrPanic(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234); | |
| 44 | assertOrPanic(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345); | |
| 45 | } | |
| 46 | } | |
| 47 | ||
| 48 | fn testAtomicLoad(ptr: *u8) void { | |
| 49 | const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst); | |
| 50 | assertOrPanic(x == 42); | |
| 51 | } | |
| 52 | ||
| 53 | test "cmpxchg with ptr" { | |
| 54 | var data1: i32 = 1234; | |
| 55 | var data2: i32 = 5678; | |
| 56 | var data3: i32 = 9101; | |
| 57 | var x: *i32 = &data1; | |
| 58 | if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | |
| 59 | assertOrPanic(x1 == &data1); | |
| 60 | } else { | |
| 61 | @panic("cmpxchg should have failed"); | |
| 62 | } | |
| 63 | ||
| 64 | while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| { | |
| 65 | assertOrPanic(x1 == &data1); | |
| 66 | } | |
| 67 | assertOrPanic(x == &data3); | |
| 68 | ||
| 69 | assertOrPanic(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null); | |
| 70 | assertOrPanic(x == &data2); | |
| 71 | } |
test/stage1/behavior/bit_shifting.zig created+88| ... | ... | @@ -0,0 +1,88 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | ||
| 4 | fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type { | |
| 5 | assertOrPanic(Key == @IntType(false, Key.bit_count)); | |
| 6 | assertOrPanic(Key.bit_count >= mask_bit_count); | |
| 7 | const ShardKey = @IntType(false, mask_bit_count); | |
| 8 | const shift_amount = Key.bit_count - ShardKey.bit_count; | |
| 9 | return struct { | |
| 10 | const Self = @This(); | |
| 11 | shards: [1 << ShardKey.bit_count]?*Node, | |
| 12 | ||
| 13 | pub fn create() Self { | |
| 14 | return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) }; | |
| 15 | } | |
| 16 | ||
| 17 | fn getShardKey(key: Key) ShardKey { | |
| 18 | // https://github.com/ziglang/zig/issues/1544 | |
| 19 | // this special case is needed because you can't u32 >> 32. | |
| 20 | if (ShardKey == u0) return 0; | |
| 21 | ||
| 22 | // this can be u1 >> u0 | |
| 23 | const shard_key = key >> shift_amount; | |
| 24 | ||
| 25 | // TODO: https://github.com/ziglang/zig/issues/1544 | |
| 26 | // This cast could be implicit if we teach the compiler that | |
| 27 | // u32 >> 30 -> u2 | |
| 28 | return @intCast(ShardKey, shard_key); | |
| 29 | } | |
| 30 | ||
| 31 | pub fn put(self: *Self, node: *Node) void { | |
| 32 | const shard_key = Self.getShardKey(node.key); | |
| 33 | node.next = self.shards[shard_key]; | |
| 34 | self.shards[shard_key] = node; | |
| 35 | } | |
| 36 | ||
| 37 | pub fn get(self: *Self, key: Key) ?*Node { | |
| 38 | const shard_key = Self.getShardKey(key); | |
| 39 | var maybe_node = self.shards[shard_key]; | |
| 40 | while (maybe_node) |node| : (maybe_node = node.next) { | |
| 41 | if (node.key == key) return node; | |
| 42 | } | |
| 43 | return null; | |
| 44 | } | |
| 45 | ||
| 46 | pub const Node = struct { | |
| 47 | key: Key, | |
| 48 | value: V, | |
| 49 | next: ?*Node, | |
| 50 | ||
| 51 | pub fn init(self: *Node, key: Key, value: V) void { | |
| 52 | self.key = key; | |
| 53 | self.value = value; | |
| 54 | self.next = null; | |
| 55 | } | |
| 56 | }; | |
| 57 | }; | |
| 58 | } | |
| 59 | ||
| 60 | test "sharded table" { | |
| 61 | // realistic 16-way sharding | |
| 62 | testShardedTable(u32, 4, 8); | |
| 63 | ||
| 64 | testShardedTable(u5, 0, 32); // ShardKey == u0 | |
| 65 | testShardedTable(u5, 2, 32); | |
| 66 | testShardedTable(u5, 5, 32); | |
| 67 | ||
| 68 | testShardedTable(u1, 0, 2); | |
| 69 | testShardedTable(u1, 1, 2); // this does u1 >> u0 | |
| 70 | ||
| 71 | testShardedTable(u0, 0, 1); | |
| 72 | } | |
| 73 | fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void { | |
| 74 | const Table = ShardedTable(Key, mask_bit_count, void); | |
| 75 | ||
| 76 | var table = Table.create(); | |
| 77 | var node_buffer: [node_count]Table.Node = undefined; | |
| 78 | for (node_buffer) |*node, i| { | |
| 79 | const key = @intCast(Key, i); | |
| 80 | assertOrPanic(table.get(key) == null); | |
| 81 | node.init(key, {}); | |
| 82 | table.put(node); | |
| 83 | } | |
| 84 | ||
| 85 | for (node_buffer) |*node, i| { | |
| 86 | assertOrPanic(table.get(@intCast(Key, i)) == node); | |
| 87 | } | |
| 88 | } |
test/stage1/behavior/bitcast.zig created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const maxInt = std.math.maxInt; | |
| 4 | ||
| 5 | test "@bitCast i32 -> u32" { | |
| 6 | testBitCast_i32_u32(); | |
| 7 | comptime testBitCast_i32_u32(); | |
| 8 | } | |
| 9 | ||
| 10 | fn testBitCast_i32_u32() void { | |
| 11 | assertOrPanic(conv(-1) == maxInt(u32)); | |
| 12 | assertOrPanic(conv2(maxInt(u32)) == -1); | |
| 13 | } | |
| 14 | ||
| 15 | fn conv(x: i32) u32 { | |
| 16 | return @bitCast(u32, x); | |
| 17 | } | |
| 18 | fn conv2(x: u32) i32 { | |
| 19 | return @bitCast(i32, x); | |
| 20 | } | |
| 21 | ||
| 22 | test "@bitCast extern enum to its integer type" { | |
| 23 | const SOCK = extern enum { | |
| 24 | A, | |
| 25 | B, | |
| 26 | ||
| 27 | fn testBitCastExternEnum() void { | |
| 28 | var SOCK_DGRAM = @This().B; | |
| 29 | var sock_dgram = @bitCast(c_int, SOCK_DGRAM); | |
| 30 | assertOrPanic(sock_dgram == 1); | |
| 31 | } | |
| 32 | }; | |
| 33 | ||
| 34 | SOCK.testBitCastExternEnum(); | |
| 35 | comptime SOCK.testBitCastExternEnum(); | |
| 36 | } |
test/stage1/behavior/bitreverse.zig created+81| ... | ... | @@ -0,0 +1,81 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const minInt = std.math.minInt; | |
| 4 | ||
| 5 | test "@bitreverse" { | |
| 6 | comptime testBitReverse(); | |
| 7 | testBitReverse(); | |
| 8 | } | |
| 9 | ||
| 10 | fn testBitReverse() void { | |
| 11 | // using comptime_ints, unsigned | |
| 12 | assertOrPanic(@bitreverse(u0, 0) == 0); | |
| 13 | assertOrPanic(@bitreverse(u5, 0x12) == 0x9); | |
| 14 | assertOrPanic(@bitreverse(u8, 0x12) == 0x48); | |
| 15 | assertOrPanic(@bitreverse(u16, 0x1234) == 0x2c48); | |
| 16 | assertOrPanic(@bitreverse(u24, 0x123456) == 0x6a2c48); | |
| 17 | assertOrPanic(@bitreverse(u32, 0x12345678) == 0x1e6a2c48); | |
| 18 | assertOrPanic(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48); | |
| 19 | assertOrPanic(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48); | |
| 20 | assertOrPanic(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48); | |
| 21 | assertOrPanic(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48); | |
| 22 | assertOrPanic(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48); | |
| 23 | ||
| 24 | // using runtime uints, unsigned | |
| 25 | var num0: u0 = 0; | |
| 26 | assertOrPanic(@bitreverse(u0, num0) == 0); | |
| 27 | var num5: u5 = 0x12; | |
| 28 | assertOrPanic(@bitreverse(u5, num5) == 0x9); | |
| 29 | var num8: u8 = 0x12; | |
| 30 | assertOrPanic(@bitreverse(u8, num8) == 0x48); | |
| 31 | var num16: u16 = 0x1234; | |
| 32 | assertOrPanic(@bitreverse(u16, num16) == 0x2c48); | |
| 33 | var num24: u24 = 0x123456; | |
| 34 | assertOrPanic(@bitreverse(u24, num24) == 0x6a2c48); | |
| 35 | var num32: u32 = 0x12345678; | |
| 36 | assertOrPanic(@bitreverse(u32, num32) == 0x1e6a2c48); | |
| 37 | var num40: u40 = 0x123456789a; | |
| 38 | assertOrPanic(@bitreverse(u40, num40) == 0x591e6a2c48); | |
| 39 | var num48: u48 = 0x123456789abc; | |
| 40 | assertOrPanic(@bitreverse(u48, num48) == 0x3d591e6a2c48); | |
| 41 | var num56: u56 = 0x123456789abcde; | |
| 42 | assertOrPanic(@bitreverse(u56, num56) == 0x7b3d591e6a2c48); | |
| 43 | var num64: u64 = 0x123456789abcdef1; | |
| 44 | assertOrPanic(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48); | |
| 45 | var num128: u128 = 0x123456789abcdef11121314151617181; | |
| 46 | assertOrPanic(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48); | |
| 47 | ||
| 48 | // using comptime_ints, signed, positive | |
| 49 | assertOrPanic(@bitreverse(i0, 0) == 0); | |
| 50 | assertOrPanic(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49))); | |
| 51 | assertOrPanic(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48))); | |
| 52 | assertOrPanic(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48))); | |
| 53 | assertOrPanic(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48))); | |
| 54 | assertOrPanic(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48))); | |
| 55 | assertOrPanic(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48))); | |
| 56 | assertOrPanic(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48))); | |
| 57 | assertOrPanic(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48))); | |
| 58 | assertOrPanic(@bitreverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48))); | |
| 59 | ||
| 60 | // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm. | |
| 61 | var neg5: i5 = minInt(i5) + 1; | |
| 62 | assertOrPanic(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5)); | |
| 63 | var neg8: i8 = -18; | |
| 64 | assertOrPanic(@bitreverse(i8, -18) == @bitreverse(i8, neg8)); | |
| 65 | var neg16: i16 = -32694; | |
| 66 | assertOrPanic(@bitreverse(i16, -32694) == @bitreverse(i16, neg16)); | |
| 67 | var neg24: i24 = -6773785; | |
| 68 | assertOrPanic(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24)); | |
| 69 | var neg32: i32 = -16773785; | |
| 70 | assertOrPanic(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32)); | |
| 71 | var neg40: i40 = minInt(i40) + 12345; | |
| 72 | assertOrPanic(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40)); | |
| 73 | var neg48: i48 = minInt(i48) + 12345; | |
| 74 | assertOrPanic(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48)); | |
| 75 | var neg56: i56 = minInt(i56) + 12345; | |
| 76 | assertOrPanic(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56)); | |
| 77 | var neg64: i64 = minInt(i64) + 12345; | |
| 78 | assertOrPanic(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64)); | |
| 79 | var neg128: i128 = minInt(i128) + 12345; | |
| 80 | assertOrPanic(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128)); | |
| 81 | } |
test/stage1/behavior/bool.zig created+35| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "bool literals" { | |
| 4 | assertOrPanic(true); | |
| 5 | assertOrPanic(!false); | |
| 6 | } | |
| 7 | ||
| 8 | test "cast bool to int" { | |
| 9 | const t = true; | |
| 10 | const f = false; | |
| 11 | assertOrPanic(@boolToInt(t) == u32(1)); | |
| 12 | assertOrPanic(@boolToInt(f) == u32(0)); | |
| 13 | nonConstCastBoolToInt(t, f); | |
| 14 | } | |
| 15 | ||
| 16 | fn nonConstCastBoolToInt(t: bool, f: bool) void { | |
| 17 | assertOrPanic(@boolToInt(t) == u32(1)); | |
| 18 | assertOrPanic(@boolToInt(f) == u32(0)); | |
| 19 | } | |
| 20 | ||
| 21 | test "bool cmp" { | |
| 22 | assertOrPanic(testBoolCmp(true, false) == false); | |
| 23 | } | |
| 24 | fn testBoolCmp(a: bool, b: bool) bool { | |
| 25 | return a == b; | |
| 26 | } | |
| 27 | ||
| 28 | const global_f = false; | |
| 29 | const global_t = true; | |
| 30 | const not_global_f = !global_f; | |
| 31 | const not_global_t = !global_t; | |
| 32 | test "compile time bool not" { | |
| 33 | assertOrPanic(not_global_f); | |
| 34 | assertOrPanic(!not_global_t); | |
| 35 | } |
test/stage1/behavior/bswap.zig created+32| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | ||
| 4 | test "@bswap" { | |
| 5 | comptime testByteSwap(); | |
| 6 | testByteSwap(); | |
| 7 | } | |
| 8 | ||
| 9 | fn testByteSwap() void { | |
| 10 | assertOrPanic(@bswap(u0, 0) == 0); | |
| 11 | assertOrPanic(@bswap(u8, 0x12) == 0x12); | |
| 12 | assertOrPanic(@bswap(u16, 0x1234) == 0x3412); | |
| 13 | assertOrPanic(@bswap(u24, 0x123456) == 0x563412); | |
| 14 | assertOrPanic(@bswap(u32, 0x12345678) == 0x78563412); | |
| 15 | assertOrPanic(@bswap(u40, 0x123456789a) == 0x9a78563412); | |
| 16 | assertOrPanic(@bswap(u48, 0x123456789abc) == 0xbc9a78563412); | |
| 17 | assertOrPanic(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412); | |
| 18 | assertOrPanic(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412); | |
| 19 | assertOrPanic(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412); | |
| 20 | ||
| 21 | assertOrPanic(@bswap(i0, 0) == 0); | |
| 22 | assertOrPanic(@bswap(i8, -50) == -50); | |
| 23 | assertOrPanic(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412))); | |
| 24 | assertOrPanic(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412))); | |
| 25 | assertOrPanic(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412))); | |
| 26 | assertOrPanic(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412))); | |
| 27 | assertOrPanic(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412))); | |
| 28 | assertOrPanic(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412))); | |
| 29 | assertOrPanic(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412))); | |
| 30 | assertOrPanic(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == | |
| 31 | @bitCast(i128, u128(0x8171615141312111f1debc9a78563412))); | |
| 32 | } |
test/stage1/behavior/bugs/1076.zig created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | const std = @import("std"); | |
| 2 | const mem = std.mem; | |
| 3 | const assertOrPanic = std.debug.assertOrPanic; | |
| 4 | ||
| 5 | test "comptime code should not modify constant data" { | |
| 6 | testCastPtrOfArrayToSliceAndPtr(); | |
| 7 | comptime testCastPtrOfArrayToSliceAndPtr(); | |
| 8 | } | |
| 9 | ||
| 10 | fn testCastPtrOfArrayToSliceAndPtr() void { | |
| 11 | var array = "aoeu"; | |
| 12 | const x: [*]u8 = &array; | |
| 13 | x[0] += 1; | |
| 14 | assertOrPanic(mem.eql(u8, array[0..], "boeu")); | |
| 15 | } | |
| 16 |
test/stage1/behavior/bugs/1111.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const Foo = extern enum { | |
| 2 | Bar = -1, | |
| 3 | }; | |
| 4 | ||
| 5 | test "issue 1111 fixed" { | |
| 6 | const v = Foo.Bar; | |
| 7 | ||
| 8 | switch (v) { | |
| 9 | Foo.Bar => return, | |
| 10 | else => return, | |
| 11 | } | |
| 12 | } |
test/stage1/behavior/bugs/1277.zig created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | const S = struct { | |
| 4 | f: ?fn () i32, | |
| 5 | }; | |
| 6 | ||
| 7 | const s = S{ .f = f }; | |
| 8 | ||
| 9 | fn f() i32 { | |
| 10 | return 1234; | |
| 11 | } | |
| 12 | ||
| 13 | test "don't emit an LLVM global for a const function when it's in an optional in a struct" { | |
| 14 | std.debug.assertOrPanic(s.f.?() == 1234); | |
| 15 | } |
test/stage1/behavior/bugs/1322.zig created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | const B = union(enum) { | |
| 4 | c: C, | |
| 5 | None, | |
| 6 | }; | |
| 7 | ||
| 8 | const A = struct { | |
| 9 | b: B, | |
| 10 | }; | |
| 11 | ||
| 12 | const C = struct {}; | |
| 13 | ||
| 14 | test "tagged union with all void fields but a meaningful tag" { | |
| 15 | var a: A = A{ .b = B{ .c = C{} } }; | |
| 16 | std.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).c); | |
| 17 | a = A{ .b = B.None }; | |
| 18 | std.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).None); | |
| 19 | } |
test/stage1/behavior/bugs/1381.zig created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | const B = union(enum) { | |
| 4 | D: u8, | |
| 5 | E: u16, | |
| 6 | }; | |
| 7 | ||
| 8 | const A = union(enum) { | |
| 9 | B: B, | |
| 10 | C: u8, | |
| 11 | }; | |
| 12 | ||
| 13 | test "union that needs padding bytes inside an array" { | |
| 14 | var as = []A{ | |
| 15 | A{ .B = B{ .D = 1 } }, | |
| 16 | A{ .B = B{ .D = 1 } }, | |
| 17 | }; | |
| 18 | ||
| 19 | const a = as[0].B; | |
| 20 | std.debug.assertOrPanic(a.D == 1); | |
| 21 | } |
test/stage1/behavior/bugs/1421.zig created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const assertOrPanic = std.debug.assertOrPanic; | |
| 4 | ||
| 5 | const S = struct { | |
| 6 | fn method() builtin.TypeInfo { | |
| 7 | return @typeInfo(S); | |
| 8 | } | |
| 9 | }; | |
| 10 | ||
| 11 | test "functions with return type required to be comptime are generic" { | |
| 12 | const ti = S.method(); | |
| 13 | assertOrPanic(builtin.TypeId(ti) == builtin.TypeId.Struct); | |
| 14 | } |
test/stage1/behavior/bugs/1442.zig created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | const Union = union(enum) { | |
| 4 | Text: []const u8, | |
| 5 | Color: u32, | |
| 6 | }; | |
| 7 | ||
| 8 | test "const error union field alignment" { | |
| 9 | var union_or_err: anyerror!Union = Union{ .Color = 1234 }; | |
| 10 | std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234); | |
| 11 | } |
test/stage1/behavior/bugs/1486.zig created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | const ptr = &global; | |
| 4 | var global: u64 = 123; | |
| 5 | ||
| 6 | test "constant pointer to global variable causes runtime load" { | |
| 7 | global = 1234; | |
| 8 | assertOrPanic(&global == ptr); | |
| 9 | assertOrPanic(ptr.* == 1234); | |
| 10 | } | |
| 11 |
test/stage1/behavior/bugs/394.zig created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | const E = union(enum) { | |
| 2 | A: [9]u8, | |
| 3 | B: u64, | |
| 4 | }; | |
| 5 | const S = struct { | |
| 6 | x: u8, | |
| 7 | y: E, | |
| 8 | }; | |
| 9 | ||
| 10 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 11 | ||
| 12 | test "bug 394 fixed" { | |
| 13 | const x = S{ | |
| 14 | .x = 3, | |
| 15 | .y = E{ .B = 1 }, | |
| 16 | }; | |
| 17 | assertOrPanic(x.x == 3); | |
| 18 | } |
test/stage1/behavior/bugs/655.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const std = @import("std"); | |
| 2 | const other_file = @import("655_other_file.zig"); | |
| 3 | ||
| 4 | test "function with *const parameter with type dereferenced by namespace" { | |
| 5 | const x: other_file.Integer = 1234; | |
| 6 | comptime std.debug.assertOrPanic(@typeOf(&x) == *const other_file.Integer); | |
| 7 | foo(&x); | |
| 8 | } | |
| 9 | ||
| 10 | fn foo(x: *const other_file.Integer) void { | |
| 11 | std.debug.assertOrPanic(x.* == 1234); | |
| 12 | } |
test/stage1/behavior/bugs/655_other_file.zig created+1| ... | ... | @@ -0,0 +1 @@ |
| 1 | pub const Integer = u32; |
test/stage1/behavior/bugs/656.zig created+31| ... | ... | @@ -0,0 +1,31 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | const PrefixOp = union(enum) { | |
| 4 | Return, | |
| 5 | AddrOf: Value, | |
| 6 | }; | |
| 7 | ||
| 8 | const Value = struct { | |
| 9 | align_expr: ?u32, | |
| 10 | }; | |
| 11 | ||
| 12 | test "optional if after an if in a switch prong of a switch with 2 prongs in an else" { | |
| 13 | foo(false, true); | |
| 14 | } | |
| 15 | ||
| 16 | fn foo(a: bool, b: bool) void { | |
| 17 | var prefix_op = PrefixOp{ | |
| 18 | .AddrOf = Value{ .align_expr = 1234 }, | |
| 19 | }; | |
| 20 | if (a) {} else { | |
| 21 | switch (prefix_op) { | |
| 22 | PrefixOp.AddrOf => |addr_of_info| { | |
| 23 | if (b) {} | |
| 24 | if (addr_of_info.align_expr) |align_expr| { | |
| 25 | assertOrPanic(align_expr == 1234); | |
| 26 | } | |
| 27 | }, | |
| 28 | PrefixOp.Return => {}, | |
| 29 | } | |
| 30 | } | |
| 31 | } |
test/stage1/behavior/bugs/726.zig created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "@ptrCast from const to nullable" { | |
| 4 | const c: u8 = 4; | |
| 5 | var x: ?*const u8 = @ptrCast(?*const u8, &c); | |
| 6 | assertOrPanic(x.?.* == 4); | |
| 7 | } | |
| 8 | ||
| 9 | test "@ptrCast from var in empty struct to nullable" { | |
| 10 | const container = struct { | |
| 11 | var c: u8 = 4; | |
| 12 | }; | |
| 13 | var x: ?*const u8 = @ptrCast(?*const u8, &container.c); | |
| 14 | assertOrPanic(x.?.* == 4); | |
| 15 | } | |
| 16 |
test/stage1/behavior/bugs/828.zig created+33| ... | ... | @@ -0,0 +1,33 @@ |
| 1 | const CountBy = struct { | |
| 2 | a: usize, | |
| 3 | ||
| 4 | const One = CountBy{ .a = 1 }; | |
| 5 | ||
| 6 | pub fn counter(self: *const CountBy) Counter { | |
| 7 | return Counter{ .i = 0 }; | |
| 8 | } | |
| 9 | }; | |
| 10 | ||
| 11 | const Counter = struct { | |
| 12 | i: usize, | |
| 13 | ||
| 14 | pub fn count(self: *Counter) bool { | |
| 15 | self.i += 1; | |
| 16 | return self.i <= 10; | |
| 17 | } | |
| 18 | }; | |
| 19 | ||
| 20 | fn constCount(comptime cb: *const CountBy, comptime unused: u32) void { | |
| 21 | comptime { | |
| 22 | var cnt = cb.counter(); | |
| 23 | if (cnt.i != 0) @compileError("Counter instance reused!"); | |
| 24 | while (cnt.count()) {} | |
| 25 | } | |
| 26 | } | |
| 27 | ||
| 28 | test "comptime struct return should not return the same instance" { | |
| 29 | //the first parameter must be passed by reference to trigger the bug | |
| 30 | //a second parameter is required to trigger the bug | |
| 31 | const ValA = constCount(&CountBy.One, 12); | |
| 32 | const ValB = constCount(&CountBy.One, 15); | |
| 33 | } |
test/stage1/behavior/bugs/920.zig created+65| ... | ... | @@ -0,0 +1,65 @@ |
| 1 | const std = @import("std"); | |
| 2 | const math = std.math; | |
| 3 | const Random = std.rand.Random; | |
| 4 | ||
| 5 | const ZigTable = struct { | |
| 6 | r: f64, | |
| 7 | x: [257]f64, | |
| 8 | f: [257]f64, | |
| 9 | ||
| 10 | pdf: fn (f64) f64, | |
| 11 | is_symmetric: bool, | |
| 12 | zero_case: fn (*Random, f64) f64, | |
| 13 | }; | |
| 14 | ||
| 15 | fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable { | |
| 16 | var tables: ZigTable = undefined; | |
| 17 | ||
| 18 | tables.is_symmetric = is_symmetric; | |
| 19 | tables.r = r; | |
| 20 | tables.pdf = f; | |
| 21 | tables.zero_case = zero_case; | |
| 22 | ||
| 23 | tables.x[0] = v / f(r); | |
| 24 | tables.x[1] = r; | |
| 25 | ||
| 26 | for (tables.x[2..256]) |*entry, i| { | |
| 27 | const last = tables.x[2 + i - 1]; | |
| 28 | entry.* = f_inv(v / last + f(last)); | |
| 29 | } | |
| 30 | tables.x[256] = 0; | |
| 31 | ||
| 32 | for (tables.f[0..]) |*entry, i| { | |
| 33 | entry.* = f(tables.x[i]); | |
| 34 | } | |
| 35 | ||
| 36 | return tables; | |
| 37 | } | |
| 38 | ||
| 39 | const norm_r = 3.6541528853610088; | |
| 40 | const norm_v = 0.00492867323399; | |
| 41 | ||
| 42 | fn norm_f(x: f64) f64 { | |
| 43 | return math.exp(-x * x / 2.0); | |
| 44 | } | |
| 45 | fn norm_f_inv(y: f64) f64 { | |
| 46 | return math.sqrt(-2.0 * math.ln(y)); | |
| 47 | } | |
| 48 | fn norm_zero_case(random: *Random, u: f64) f64 { | |
| 49 | return 0.0; | |
| 50 | } | |
| 51 | ||
| 52 | const NormalDist = blk: { | |
| 53 | @setEvalBranchQuota(30000); | |
| 54 | break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case); | |
| 55 | }; | |
| 56 | ||
| 57 | test "bug 920 fixed" { | |
| 58 | const NormalDist1 = blk: { | |
| 59 | break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case); | |
| 60 | }; | |
| 61 | ||
| 62 | for (NormalDist1.f) |_, i| { | |
| 63 | std.debug.assertOrPanic(NormalDist1.f[i] == NormalDist.f[i]); | |
| 64 | } | |
| 65 | } |
test/stage1/behavior/byval_arg_var.zig created+27| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | var result: []const u8 = "wrong"; | |
| 4 | ||
| 5 | test "pass string literal byvalue to a generic var param" { | |
| 6 | start(); | |
| 7 | blowUpStack(10); | |
| 8 | ||
| 9 | std.debug.assertOrPanic(std.mem.eql(u8, result, "string literal")); | |
| 10 | } | |
| 11 | ||
| 12 | fn start() void { | |
| 13 | foo("string literal"); | |
| 14 | } | |
| 15 | ||
| 16 | fn foo(x: var) void { | |
| 17 | bar(x); | |
| 18 | } | |
| 19 | ||
| 20 | fn bar(x: var) void { | |
| 21 | result = x; | |
| 22 | } | |
| 23 | ||
| 24 | fn blowUpStack(x: u32) void { | |
| 25 | if (x == 0) return; | |
| 26 | blowUpStack(x - 1); | |
| 27 | } |
test/stage1/behavior/cancel.zig created+92| ... | ... | @@ -0,0 +1,92 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | var defer_f1: bool = false; | |
| 4 | var defer_f2: bool = false; | |
| 5 | var defer_f3: bool = false; | |
| 6 | ||
| 7 | test "cancel forwards" { | |
| 8 | var da = std.heap.DirectAllocator.init(); | |
| 9 | defer da.deinit(); | |
| 10 | ||
| 11 | const p = async<&da.allocator> f1() catch unreachable; | |
| 12 | cancel p; | |
| 13 | std.debug.assertOrPanic(defer_f1); | |
| 14 | std.debug.assertOrPanic(defer_f2); | |
| 15 | std.debug.assertOrPanic(defer_f3); | |
| 16 | } | |
| 17 | ||
| 18 | async fn f1() void { | |
| 19 | defer { | |
| 20 | defer_f1 = true; | |
| 21 | } | |
| 22 | await (async f2() catch unreachable); | |
| 23 | } | |
| 24 | ||
| 25 | async fn f2() void { | |
| 26 | defer { | |
| 27 | defer_f2 = true; | |
| 28 | } | |
| 29 | await (async f3() catch unreachable); | |
| 30 | } | |
| 31 | ||
| 32 | async fn f3() void { | |
| 33 | defer { | |
| 34 | defer_f3 = true; | |
| 35 | } | |
| 36 | suspend; | |
| 37 | } | |
| 38 | ||
| 39 | var defer_b1: bool = false; | |
| 40 | var defer_b2: bool = false; | |
| 41 | var defer_b3: bool = false; | |
| 42 | var defer_b4: bool = false; | |
| 43 | ||
| 44 | test "cancel backwards" { | |
| 45 | var da = std.heap.DirectAllocator.init(); | |
| 46 | defer da.deinit(); | |
| 47 | ||
| 48 | const p = async<&da.allocator> b1() catch unreachable; | |
| 49 | cancel p; | |
| 50 | std.debug.assertOrPanic(defer_b1); | |
| 51 | std.debug.assertOrPanic(defer_b2); | |
| 52 | std.debug.assertOrPanic(defer_b3); | |
| 53 | std.debug.assertOrPanic(defer_b4); | |
| 54 | } | |
| 55 | ||
| 56 | async fn b1() void { | |
| 57 | defer { | |
| 58 | defer_b1 = true; | |
| 59 | } | |
| 60 | await (async b2() catch unreachable); | |
| 61 | } | |
| 62 | ||
| 63 | var b4_handle: promise = undefined; | |
| 64 | ||
| 65 | async fn b2() void { | |
| 66 | const b3_handle = async b3() catch unreachable; | |
| 67 | resume b4_handle; | |
| 68 | cancel b4_handle; | |
| 69 | defer { | |
| 70 | defer_b2 = true; | |
| 71 | } | |
| 72 | const value = await b3_handle; | |
| 73 | @panic("unreachable"); | |
| 74 | } | |
| 75 | ||
| 76 | async fn b3() i32 { | |
| 77 | defer { | |
| 78 | defer_b3 = true; | |
| 79 | } | |
| 80 | await (async b4() catch unreachable); | |
| 81 | return 1234; | |
| 82 | } | |
| 83 | ||
| 84 | async fn b4() void { | |
| 85 | defer { | |
| 86 | defer_b4 = true; | |
| 87 | } | |
| 88 | suspend { | |
| 89 | b4_handle = @handle(); | |
| 90 | } | |
| 91 | suspend; | |
| 92 | } |
test/stage1/behavior/cast.zig created+473| ... | ... | @@ -0,0 +1,473 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const mem = std.mem; | |
| 4 | const maxInt = std.math.maxInt; | |
| 5 | ||
| 6 | test "int to ptr cast" { | |
| 7 | const x = usize(13); | |
| 8 | const y = @intToPtr(*u8, x); | |
| 9 | const z = @ptrToInt(y); | |
| 10 | assertOrPanic(z == 13); | |
| 11 | } | |
| 12 | ||
| 13 | test "integer literal to pointer cast" { | |
| 14 | const vga_mem = @intToPtr(*u16, 0xB8000); | |
| 15 | assertOrPanic(@ptrToInt(vga_mem) == 0xB8000); | |
| 16 | } | |
| 17 | ||
| 18 | test "pointer reinterpret const float to int" { | |
| 19 | const float: f64 = 5.99999999999994648725e-01; | |
| 20 | const float_ptr = &float; | |
| 21 | const int_ptr = @ptrCast(*const i32, float_ptr); | |
| 22 | const int_val = int_ptr.*; | |
| 23 | assertOrPanic(int_val == 858993411); | |
| 24 | } | |
| 25 | ||
| 26 | test "implicitly cast indirect pointer to maybe-indirect pointer" { | |
| 27 | const S = struct { | |
| 28 | const Self = @This(); | |
| 29 | x: u8, | |
| 30 | fn constConst(p: *const *const Self) u8 { | |
| 31 | return p.*.x; | |
| 32 | } | |
| 33 | fn maybeConstConst(p: ?*const *const Self) u8 { | |
| 34 | return p.?.*.x; | |
| 35 | } | |
| 36 | fn constConstConst(p: *const *const *const Self) u8 { | |
| 37 | return p.*.*.x; | |
| 38 | } | |
| 39 | fn maybeConstConstConst(p: ?*const *const *const Self) u8 { | |
| 40 | return p.?.*.*.x; | |
| 41 | } | |
| 42 | }; | |
| 43 | const s = S{ .x = 42 }; | |
| 44 | const p = &s; | |
| 45 | const q = &p; | |
| 46 | const r = &q; | |
| 47 | assertOrPanic(42 == S.constConst(q)); | |
| 48 | assertOrPanic(42 == S.maybeConstConst(q)); | |
| 49 | assertOrPanic(42 == S.constConstConst(r)); | |
| 50 | assertOrPanic(42 == S.maybeConstConstConst(r)); | |
| 51 | } | |
| 52 | ||
| 53 | test "explicit cast from integer to error type" { | |
| 54 | testCastIntToErr(error.ItBroke); | |
| 55 | comptime testCastIntToErr(error.ItBroke); | |
| 56 | } | |
| 57 | fn testCastIntToErr(err: anyerror) void { | |
| 58 | const x = @errorToInt(err); | |
| 59 | const y = @intToError(x); | |
| 60 | assertOrPanic(error.ItBroke == y); | |
| 61 | } | |
| 62 | ||
| 63 | test "peer resolve arrays of different size to const slice" { | |
| 64 | assertOrPanic(mem.eql(u8, boolToStr(true), "true")); | |
| 65 | assertOrPanic(mem.eql(u8, boolToStr(false), "false")); | |
| 66 | comptime assertOrPanic(mem.eql(u8, boolToStr(true), "true")); | |
| 67 | comptime assertOrPanic(mem.eql(u8, boolToStr(false), "false")); | |
| 68 | } | |
| 69 | fn boolToStr(b: bool) []const u8 { | |
| 70 | return if (b) "true" else "false"; | |
| 71 | } | |
| 72 | ||
| 73 | test "peer resolve array and const slice" { | |
| 74 | testPeerResolveArrayConstSlice(true); | |
| 75 | comptime testPeerResolveArrayConstSlice(true); | |
| 76 | } | |
| 77 | fn testPeerResolveArrayConstSlice(b: bool) void { | |
| 78 | const value1 = if (b) "aoeu" else ([]const u8)("zz"); | |
| 79 | const value2 = if (b) ([]const u8)("zz") else "aoeu"; | |
| 80 | assertOrPanic(mem.eql(u8, value1, "aoeu")); | |
| 81 | assertOrPanic(mem.eql(u8, value2, "zz")); | |
| 82 | } | |
| 83 | ||
| 84 | test "implicitly cast from T to anyerror!?T" { | |
| 85 | castToOptionalTypeError(1); | |
| 86 | comptime castToOptionalTypeError(1); | |
| 87 | } | |
| 88 | ||
| 89 | const A = struct { | |
| 90 | a: i32, | |
| 91 | }; | |
| 92 | fn castToOptionalTypeError(z: i32) void { | |
| 93 | const x = i32(1); | |
| 94 | const y: anyerror!?i32 = x; | |
| 95 | assertOrPanic((try y).? == 1); | |
| 96 | ||
| 97 | const f = z; | |
| 98 | const g: anyerror!?i32 = f; | |
| 99 | ||
| 100 | const a = A{ .a = z }; | |
| 101 | const b: anyerror!?A = a; | |
| 102 | assertOrPanic((b catch unreachable).?.a == 1); | |
| 103 | } | |
| 104 | ||
| 105 | test "implicitly cast from int to anyerror!?T" { | |
| 106 | implicitIntLitToOptional(); | |
| 107 | comptime implicitIntLitToOptional(); | |
| 108 | } | |
| 109 | fn implicitIntLitToOptional() void { | |
| 110 | const f: ?i32 = 1; | |
| 111 | const g: anyerror!?i32 = 1; | |
| 112 | } | |
| 113 | ||
| 114 | test "return null from fn() anyerror!?&T" { | |
| 115 | const a = returnNullFromOptionalTypeErrorRef(); | |
| 116 | const b = returnNullLitFromOptionalTypeErrorRef(); | |
| 117 | assertOrPanic((try a) == null and (try b) == null); | |
| 118 | } | |
| 119 | fn returnNullFromOptionalTypeErrorRef() anyerror!?*A { | |
| 120 | const a: ?*A = null; | |
| 121 | return a; | |
| 122 | } | |
| 123 | fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A { | |
| 124 | return null; | |
| 125 | } | |
| 126 | ||
| 127 | test "peer type resolution: ?T and T" { | |
| 128 | assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0); | |
| 129 | assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3); | |
| 130 | comptime { | |
| 131 | assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0); | |
| 132 | assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3); | |
| 133 | } | |
| 134 | } | |
| 135 | fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { | |
| 136 | if (c) { | |
| 137 | return if (b) null else usize(0); | |
| 138 | } | |
| 139 | ||
| 140 | return usize(3); | |
| 141 | } | |
| 142 | ||
| 143 | test "peer type resolution: [0]u8 and []const u8" { | |
| 144 | assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | |
| 145 | assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | |
| 146 | comptime { | |
| 147 | assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0); | |
| 148 | assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1); | |
| 149 | } | |
| 150 | } | |
| 151 | fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 { | |
| 152 | if (a) { | |
| 153 | return []const u8{}; | |
| 154 | } | |
| 155 | ||
| 156 | return slice[0..1]; | |
| 157 | } | |
| 158 | ||
| 159 | test "implicitly cast from [N]T to ?[]const T" { | |
| 160 | assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi")); | |
| 161 | comptime assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi")); | |
| 162 | } | |
| 163 | ||
| 164 | fn castToOptionalSlice() ?[]const u8 { | |
| 165 | return "hi"; | |
| 166 | } | |
| 167 | ||
| 168 | test "implicitly cast from [0]T to anyerror![]T" { | |
| 169 | testCastZeroArrayToErrSliceMut(); | |
| 170 | comptime testCastZeroArrayToErrSliceMut(); | |
| 171 | } | |
| 172 | ||
| 173 | fn testCastZeroArrayToErrSliceMut() void { | |
| 174 | assertOrPanic((gimmeErrOrSlice() catch unreachable).len == 0); | |
| 175 | } | |
| 176 | ||
| 177 | fn gimmeErrOrSlice() anyerror![]u8 { | |
| 178 | return []u8{}; | |
| 179 | } | |
| 180 | ||
| 181 | test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" { | |
| 182 | { | |
| 183 | var data = "hi"; | |
| 184 | const slice = data[0..]; | |
| 185 | assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); | |
| 186 | assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); | |
| 187 | } | |
| 188 | comptime { | |
| 189 | var data = "hi"; | |
| 190 | const slice = data[0..]; | |
| 191 | assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); | |
| 192 | assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); | |
| 193 | } | |
| 194 | } | |
| 195 | fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { | |
| 196 | if (a) { | |
| 197 | return []u8{}; | |
| 198 | } | |
| 199 | ||
| 200 | return slice[0..1]; | |
| 201 | } | |
| 202 | ||
| 203 | test "resolve undefined with integer" { | |
| 204 | testResolveUndefWithInt(true, 1234); | |
| 205 | comptime testResolveUndefWithInt(true, 1234); | |
| 206 | } | |
| 207 | fn testResolveUndefWithInt(b: bool, x: i32) void { | |
| 208 | const value = if (b) x else undefined; | |
| 209 | if (b) { | |
| 210 | assertOrPanic(value == x); | |
| 211 | } | |
| 212 | } | |
| 213 | ||
| 214 | test "implicit cast from &const [N]T to []const T" { | |
| 215 | testCastConstArrayRefToConstSlice(); | |
| 216 | comptime testCastConstArrayRefToConstSlice(); | |
| 217 | } | |
| 218 | ||
| 219 | fn testCastConstArrayRefToConstSlice() void { | |
| 220 | const blah = "aoeu"; | |
| 221 | const const_array_ref = &blah; | |
| 222 | assertOrPanic(@typeOf(const_array_ref) == *const [4]u8); | |
| 223 | const slice: []const u8 = const_array_ref; | |
| 224 | assertOrPanic(mem.eql(u8, slice, "aoeu")); | |
| 225 | } | |
| 226 | ||
| 227 | test "peer type resolution: error and [N]T" { | |
| 228 | // TODO: implicit error!T to error!U where T can implicitly cast to U | |
| 229 | //assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); | |
| 230 | //comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK")); | |
| 231 | assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); | |
| 232 | comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK")); | |
| 233 | } | |
| 234 | ||
| 235 | //fn testPeerErrorAndArray(x: u8) error![]const u8 { | |
| 236 | // return switch (x) { | |
| 237 | // 0x00 => "OK", | |
| 238 | // else => error.BadValue, | |
| 239 | // }; | |
| 240 | //} | |
| 241 | fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 { | |
| 242 | return switch (x) { | |
| 243 | 0x00 => "OK", | |
| 244 | 0x01 => "OKK", | |
| 245 | else => error.BadValue, | |
| 246 | }; | |
| 247 | } | |
| 248 | ||
| 249 | test "@floatToInt" { | |
| 250 | testFloatToInts(); | |
| 251 | comptime testFloatToInts(); | |
| 252 | } | |
| 253 | ||
| 254 | fn testFloatToInts() void { | |
| 255 | const x = i32(1e4); | |
| 256 | assertOrPanic(x == 10000); | |
| 257 | const y = @floatToInt(i32, f32(1e4)); | |
| 258 | assertOrPanic(y == 10000); | |
| 259 | expectFloatToInt(f16, 255.1, u8, 255); | |
| 260 | expectFloatToInt(f16, 127.2, i8, 127); | |
| 261 | expectFloatToInt(f16, -128.2, i8, -128); | |
| 262 | expectFloatToInt(f32, 255.1, u8, 255); | |
| 263 | expectFloatToInt(f32, 127.2, i8, 127); | |
| 264 | expectFloatToInt(f32, -128.2, i8, -128); | |
| 265 | expectFloatToInt(comptime_int, 1234, i16, 1234); | |
| 266 | } | |
| 267 | ||
| 268 | fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void { | |
| 269 | assertOrPanic(@floatToInt(I, f) == i); | |
| 270 | } | |
| 271 | ||
| 272 | test "cast u128 to f128 and back" { | |
| 273 | comptime testCast128(); | |
| 274 | testCast128(); | |
| 275 | } | |
| 276 | ||
| 277 | fn testCast128() void { | |
| 278 | assertOrPanic(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000); | |
| 279 | } | |
| 280 | ||
| 281 | fn cast128Int(x: f128) u128 { | |
| 282 | return @bitCast(u128, x); | |
| 283 | } | |
| 284 | ||
| 285 | fn cast128Float(x: u128) f128 { | |
| 286 | return @bitCast(f128, x); | |
| 287 | } | |
| 288 | ||
| 289 | test "const slice widen cast" { | |
| 290 | const bytes align(4) = []u8{ | |
| 291 | 0x12, | |
| 292 | 0x12, | |
| 293 | 0x12, | |
| 294 | 0x12, | |
| 295 | }; | |
| 296 | ||
| 297 | const u32_value = @bytesToSlice(u32, bytes[0..])[0]; | |
| 298 | assertOrPanic(u32_value == 0x12121212); | |
| 299 | ||
| 300 | assertOrPanic(@bitCast(u32, bytes) == 0x12121212); | |
| 301 | } | |
| 302 | ||
| 303 | test "single-item pointer of array to slice and to unknown length pointer" { | |
| 304 | testCastPtrOfArrayToSliceAndPtr(); | |
| 305 | comptime testCastPtrOfArrayToSliceAndPtr(); | |
| 306 | } | |
| 307 | ||
| 308 | fn testCastPtrOfArrayToSliceAndPtr() void { | |
| 309 | var array = "aoeu"; | |
| 310 | const x: [*]u8 = &array; | |
| 311 | x[0] += 1; | |
| 312 | assertOrPanic(mem.eql(u8, array[0..], "boeu")); | |
| 313 | const y: []u8 = &array; | |
| 314 | y[0] += 1; | |
| 315 | assertOrPanic(mem.eql(u8, array[0..], "coeu")); | |
| 316 | } | |
| 317 | ||
| 318 | test "cast *[1][*]const u8 to [*]const ?[*]const u8" { | |
| 319 | const window_name = [1][*]const u8{c"window name"}; | |
| 320 | const x: [*]const ?[*]const u8 = &window_name; | |
| 321 | assertOrPanic(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name")); | |
| 322 | } | |
| 323 | ||
| 324 | test "@intCast comptime_int" { | |
| 325 | const result = @intCast(i32, 1234); | |
| 326 | assertOrPanic(@typeOf(result) == i32); | |
| 327 | assertOrPanic(result == 1234); | |
| 328 | } | |
| 329 | ||
| 330 | test "@floatCast comptime_int and comptime_float" { | |
| 331 | { | |
| 332 | const result = @floatCast(f16, 1234); | |
| 333 | assertOrPanic(@typeOf(result) == f16); | |
| 334 | assertOrPanic(result == 1234.0); | |
| 335 | } | |
| 336 | { | |
| 337 | const result = @floatCast(f16, 1234.0); | |
| 338 | assertOrPanic(@typeOf(result) == f16); | |
| 339 | assertOrPanic(result == 1234.0); | |
| 340 | } | |
| 341 | { | |
| 342 | const result = @floatCast(f32, 1234); | |
| 343 | assertOrPanic(@typeOf(result) == f32); | |
| 344 | assertOrPanic(result == 1234.0); | |
| 345 | } | |
| 346 | { | |
| 347 | const result = @floatCast(f32, 1234.0); | |
| 348 | assertOrPanic(@typeOf(result) == f32); | |
| 349 | assertOrPanic(result == 1234.0); | |
| 350 | } | |
| 351 | } | |
| 352 | ||
| 353 | test "comptime_int @intToFloat" { | |
| 354 | { | |
| 355 | const result = @intToFloat(f16, 1234); | |
| 356 | assertOrPanic(@typeOf(result) == f16); | |
| 357 | assertOrPanic(result == 1234.0); | |
| 358 | } | |
| 359 | { | |
| 360 | const result = @intToFloat(f32, 1234); | |
| 361 | assertOrPanic(@typeOf(result) == f32); | |
| 362 | assertOrPanic(result == 1234.0); | |
| 363 | } | |
| 364 | } | |
| 365 | ||
| 366 | test "@bytesToSlice keeps pointer alignment" { | |
| 367 | var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 }; | |
| 368 | const numbers = @bytesToSlice(u32, bytes[0..]); | |
| 369 | comptime assertOrPanic(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32); | |
| 370 | } | |
| 371 | ||
| 372 | test "@intCast i32 to u7" { | |
| 373 | var x: u128 = maxInt(u128); | |
| 374 | var y: i32 = 120; | |
| 375 | var z = x >> @intCast(u7, y); | |
| 376 | assertOrPanic(z == 0xff); | |
| 377 | } | |
| 378 | ||
| 379 | test "implicit cast undefined to optional" { | |
| 380 | assertOrPanic(MakeType(void).getNull() == null); | |
| 381 | assertOrPanic(MakeType(void).getNonNull() != null); | |
| 382 | } | |
| 383 | ||
| 384 | fn MakeType(comptime T: type) type { | |
| 385 | return struct { | |
| 386 | fn getNull() ?T { | |
| 387 | return null; | |
| 388 | } | |
| 389 | ||
| 390 | fn getNonNull() ?T { | |
| 391 | return T(undefined); | |
| 392 | } | |
| 393 | }; | |
| 394 | } | |
| 395 | ||
| 396 | test "implicit cast from *[N]T to ?[*]T" { | |
| 397 | var x: ?[*]u16 = null; | |
| 398 | var y: [4]u16 = [4]u16{ 0, 1, 2, 3 }; | |
| 399 | ||
| 400 | x = &y; | |
| 401 | assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4])); | |
| 402 | x.?[0] = 8; | |
| 403 | y[3] = 6; | |
| 404 | assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4])); | |
| 405 | } | |
| 406 | ||
| 407 | test "implicit cast from *T to ?*c_void" { | |
| 408 | var a: u8 = 1; | |
| 409 | incrementVoidPtrValue(&a); | |
| 410 | std.debug.assertOrPanic(a == 2); | |
| 411 | } | |
| 412 | ||
| 413 | fn incrementVoidPtrValue(value: ?*c_void) void { | |
| 414 | @ptrCast(*u8, value.?).* += 1; | |
| 415 | } | |
| 416 | ||
| 417 | test "implicit cast from [*]T to ?*c_void" { | |
| 418 | var a = []u8{ 3, 2, 1 }; | |
| 419 | incrementVoidPtrArray(a[0..].ptr, 3); | |
| 420 | assertOrPanic(std.mem.eql(u8, a, []u8{ 4, 3, 2 })); | |
| 421 | } | |
| 422 | ||
| 423 | fn incrementVoidPtrArray(array: ?*c_void, len: usize) void { | |
| 424 | var n: usize = 0; | |
| 425 | while (n < len) : (n += 1) { | |
| 426 | @ptrCast([*]u8, array.?)[n] += 1; | |
| 427 | } | |
| 428 | } | |
| 429 | ||
| 430 | test "*usize to *void" { | |
| 431 | var i = usize(0); | |
| 432 | var v = @ptrCast(*void, &i); | |
| 433 | v.* = {}; | |
| 434 | } | |
| 435 | ||
| 436 | test "compile time int to ptr of function" { | |
| 437 | foobar(FUNCTION_CONSTANT); | |
| 438 | } | |
| 439 | ||
| 440 | pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize)); | |
| 441 | pub const PFN_void = extern fn (*c_void) void; | |
| 442 | ||
| 443 | fn foobar(func: PFN_void) void { | |
| 444 | std.debug.assertOrPanic(@ptrToInt(func) == maxInt(usize)); | |
| 445 | } | |
| 446 | ||
| 447 | test "implicit ptr to *c_void" { | |
| 448 | var a: u32 = 1; | |
| 449 | var ptr: *c_void = &a; | |
| 450 | var b: *u32 = @ptrCast(*u32, ptr); | |
| 451 | assertOrPanic(b.* == 1); | |
| 452 | var ptr2: ?*c_void = &a; | |
| 453 | var c: *u32 = @ptrCast(*u32, ptr2.?); | |
| 454 | assertOrPanic(c.* == 1); | |
| 455 | } | |
| 456 | ||
| 457 | test "@intCast to comptime_int" { | |
| 458 | assertOrPanic(@intCast(comptime_int, 0) == 0); | |
| 459 | } | |
| 460 | ||
| 461 | test "implicit cast comptime numbers to any type when the value fits" { | |
| 462 | const a: u64 = 255; | |
| 463 | var b: u8 = a; | |
| 464 | assertOrPanic(b == 255); | |
| 465 | } | |
| 466 | ||
| 467 | test "@intToEnum passed a comptime_int to an enum with one item" { | |
| 468 | const E = enum { | |
| 469 | A, | |
| 470 | }; | |
| 471 | const x = @intToEnum(E, 0); | |
| 472 | assertOrPanic(x == E.A); | |
| 473 | } |
test/stage1/behavior/const_slice_child.zig created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | const debug = @import("std").debug; | |
| 2 | const assertOrPanic = debug.assertOrPanic; | |
| 3 | ||
| 4 | var argv: [*]const [*]const u8 = undefined; | |
| 5 | ||
| 6 | test "const slice child" { | |
| 7 | const strs = ([][*]const u8){ | |
| 8 | c"one", | |
| 9 | c"two", | |
| 10 | c"three", | |
| 11 | }; | |
| 12 | // TODO this should implicitly cast | |
| 13 | argv = @ptrCast([*]const [*]const u8, &strs); | |
| 14 | bar(strs.len); | |
| 15 | } | |
| 16 | ||
| 17 | fn foo(args: [][]const u8) void { | |
| 18 | assertOrPanic(args.len == 3); | |
| 19 | assertOrPanic(streql(args[0], "one")); | |
| 20 | assertOrPanic(streql(args[1], "two")); | |
| 21 | assertOrPanic(streql(args[2], "three")); | |
| 22 | } | |
| 23 | ||
| 24 | fn bar(argc: usize) void { | |
| 25 | const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable; | |
| 26 | for (args) |_, i| { | |
| 27 | const ptr = argv[i]; | |
| 28 | args[i] = ptr[0..strlen(ptr)]; | |
| 29 | } | |
| 30 | foo(args); | |
| 31 | } | |
| 32 | ||
| 33 | fn strlen(ptr: [*]const u8) usize { | |
| 34 | var count: usize = 0; | |
| 35 | while (ptr[count] != 0) : (count += 1) {} | |
| 36 | return count; | |
| 37 | } | |
| 38 | ||
| 39 | fn streql(a: []const u8, b: []const u8) bool { | |
| 40 | if (a.len != b.len) return false; | |
| 41 | for (a) |item, index| { | |
| 42 | if (b[index] != item) return false; | |
| 43 | } | |
| 44 | return true; | |
| 45 | } |
test/stage1/behavior/coroutine_await_struct.zig created+47| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const assertOrPanic = std.debug.assertOrPanic; | |
| 4 | ||
| 5 | const Foo = struct { | |
| 6 | x: i32, | |
| 7 | }; | |
| 8 | ||
| 9 | var await_a_promise: promise = undefined; | |
| 10 | var await_final_result = Foo{ .x = 0 }; | |
| 11 | ||
| 12 | test "coroutine await struct" { | |
| 13 | var da = std.heap.DirectAllocator.init(); | |
| 14 | defer da.deinit(); | |
| 15 | ||
| 16 | await_seq('a'); | |
| 17 | const p = async<&da.allocator> await_amain() catch unreachable; | |
| 18 | await_seq('f'); | |
| 19 | resume await_a_promise; | |
| 20 | await_seq('i'); | |
| 21 | assertOrPanic(await_final_result.x == 1234); | |
| 22 | assertOrPanic(std.mem.eql(u8, await_points, "abcdefghi")); | |
| 23 | } | |
| 24 | async fn await_amain() void { | |
| 25 | await_seq('b'); | |
| 26 | const p = async await_another() catch unreachable; | |
| 27 | await_seq('e'); | |
| 28 | await_final_result = await p; | |
| 29 | await_seq('h'); | |
| 30 | } | |
| 31 | async fn await_another() Foo { | |
| 32 | await_seq('c'); | |
| 33 | suspend { | |
| 34 | await_seq('d'); | |
| 35 | await_a_promise = @handle(); | |
| 36 | } | |
| 37 | await_seq('g'); | |
| 38 | return Foo{ .x = 1234 }; | |
| 39 | } | |
| 40 | ||
| 41 | var await_points = []u8{0} ** "abcdefghi".len; | |
| 42 | var await_seq_index: usize = 0; | |
| 43 | ||
| 44 | fn await_seq(c: u8) void { | |
| 45 | await_points[await_seq_index] = c; | |
| 46 | await_seq_index += 1; | |
| 47 | } |
test/stage1/behavior/coroutines.zig created+258| ... | ... | @@ -0,0 +1,258 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const assertOrPanic = std.debug.assertOrPanic; | |
| 4 | ||
| 5 | var x: i32 = 1; | |
| 6 | ||
| 7 | test "create a coroutine and cancel it" { | |
| 8 | var da = std.heap.DirectAllocator.init(); | |
| 9 | defer da.deinit(); | |
| 10 | ||
| 11 | const p = try async<&da.allocator> simpleAsyncFn(); | |
| 12 | comptime assertOrPanic(@typeOf(p) == promise->void); | |
| 13 | cancel p; | |
| 14 | assertOrPanic(x == 2); | |
| 15 | } | |
| 16 | async fn simpleAsyncFn() void { | |
| 17 | x += 1; | |
| 18 | suspend; | |
| 19 | x += 1; | |
| 20 | } | |
| 21 | ||
| 22 | test "coroutine suspend, resume, cancel" { | |
| 23 | var da = std.heap.DirectAllocator.init(); | |
| 24 | defer da.deinit(); | |
| 25 | ||
| 26 | seq('a'); | |
| 27 | const p = try async<&da.allocator> testAsyncSeq(); | |
| 28 | seq('c'); | |
| 29 | resume p; | |
| 30 | seq('f'); | |
| 31 | cancel p; | |
| 32 | seq('g'); | |
| 33 | ||
| 34 | assertOrPanic(std.mem.eql(u8, points, "abcdefg")); | |
| 35 | } | |
| 36 | async fn testAsyncSeq() void { | |
| 37 | defer seq('e'); | |
| 38 | ||
| 39 | seq('b'); | |
| 40 | suspend; | |
| 41 | seq('d'); | |
| 42 | } | |
| 43 | var points = []u8{0} ** "abcdefg".len; | |
| 44 | var index: usize = 0; | |
| 45 | ||
| 46 | fn seq(c: u8) void { | |
| 47 | points[index] = c; | |
| 48 | index += 1; | |
| 49 | } | |
| 50 | ||
| 51 | test "coroutine suspend with block" { | |
| 52 | var da = std.heap.DirectAllocator.init(); | |
| 53 | defer da.deinit(); | |
| 54 | ||
| 55 | const p = try async<&da.allocator> testSuspendBlock(); | |
| 56 | std.debug.assertOrPanic(!result); | |
| 57 | resume a_promise; | |
| 58 | std.debug.assertOrPanic(result); | |
| 59 | cancel p; | |
| 60 | } | |
| 61 | ||
| 62 | var a_promise: promise = undefined; | |
| 63 | var result = false; | |
| 64 | async fn testSuspendBlock() void { | |
| 65 | suspend { | |
| 66 | comptime assertOrPanic(@typeOf(@handle()) == promise->void); | |
| 67 | a_promise = @handle(); | |
| 68 | } | |
| 69 | ||
| 70 | //Test to make sure that @handle() works as advertised (issue #1296) | |
| 71 | //var our_handle: promise = @handle(); | |
| 72 | assertOrPanic(a_promise == @handle()); | |
| 73 | ||
| 74 | result = true; | |
| 75 | } | |
| 76 | ||
| 77 | var await_a_promise: promise = undefined; | |
| 78 | var await_final_result: i32 = 0; | |
| 79 | ||
| 80 | test "coroutine await" { | |
| 81 | var da = std.heap.DirectAllocator.init(); | |
| 82 | defer da.deinit(); | |
| 83 | ||
| 84 | await_seq('a'); | |
| 85 | const p = async<&da.allocator> await_amain() catch unreachable; | |
| 86 | await_seq('f'); | |
| 87 | resume await_a_promise; | |
| 88 | await_seq('i'); | |
| 89 | assertOrPanic(await_final_result == 1234); | |
| 90 | assertOrPanic(std.mem.eql(u8, await_points, "abcdefghi")); | |
| 91 | } | |
| 92 | async fn await_amain() void { | |
| 93 | await_seq('b'); | |
| 94 | const p = async await_another() catch unreachable; | |
| 95 | await_seq('e'); | |
| 96 | await_final_result = await p; | |
| 97 | await_seq('h'); | |
| 98 | } | |
| 99 | async fn await_another() i32 { | |
| 100 | await_seq('c'); | |
| 101 | suspend { | |
| 102 | await_seq('d'); | |
| 103 | await_a_promise = @handle(); | |
| 104 | } | |
| 105 | await_seq('g'); | |
| 106 | return 1234; | |
| 107 | } | |
| 108 | ||
| 109 | var await_points = []u8{0} ** "abcdefghi".len; | |
| 110 | var await_seq_index: usize = 0; | |
| 111 | ||
| 112 | fn await_seq(c: u8) void { | |
| 113 | await_points[await_seq_index] = c; | |
| 114 | await_seq_index += 1; | |
| 115 | } | |
| 116 | ||
| 117 | var early_final_result: i32 = 0; | |
| 118 | ||
| 119 | test "coroutine await early return" { | |
| 120 | var da = std.heap.DirectAllocator.init(); | |
| 121 | defer da.deinit(); | |
| 122 | ||
| 123 | early_seq('a'); | |
| 124 | const p = async<&da.allocator> early_amain() catch @panic("out of memory"); | |
| 125 | early_seq('f'); | |
| 126 | assertOrPanic(early_final_result == 1234); | |
| 127 | assertOrPanic(std.mem.eql(u8, early_points, "abcdef")); | |
| 128 | } | |
| 129 | async fn early_amain() void { | |
| 130 | early_seq('b'); | |
| 131 | const p = async early_another() catch @panic("out of memory"); | |
| 132 | early_seq('d'); | |
| 133 | early_final_result = await p; | |
| 134 | early_seq('e'); | |
| 135 | } | |
| 136 | async fn early_another() i32 { | |
| 137 | early_seq('c'); | |
| 138 | return 1234; | |
| 139 | } | |
| 140 | ||
| 141 | var early_points = []u8{0} ** "abcdef".len; | |
| 142 | var early_seq_index: usize = 0; | |
| 143 | ||
| 144 | fn early_seq(c: u8) void { | |
| 145 | early_points[early_seq_index] = c; | |
| 146 | early_seq_index += 1; | |
| 147 | } | |
| 148 | ||
| 149 | test "coro allocation failure" { | |
| 150 | var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0); | |
| 151 | if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) { | |
| 152 | @panic("expected allocation failure"); | |
| 153 | } else |err| switch (err) { | |
| 154 | error.OutOfMemory => {}, | |
| 155 | } | |
| 156 | } | |
| 157 | async fn asyncFuncThatNeverGetsRun() void { | |
| 158 | @panic("coro frame allocation should fail"); | |
| 159 | } | |
| 160 | ||
| 161 | test "async function with dot syntax" { | |
| 162 | const S = struct { | |
| 163 | var y: i32 = 1; | |
| 164 | async fn foo() void { | |
| 165 | y += 1; | |
| 166 | suspend; | |
| 167 | } | |
| 168 | }; | |
| 169 | var da = std.heap.DirectAllocator.init(); | |
| 170 | defer da.deinit(); | |
| 171 | const p = try async<&da.allocator> S.foo(); | |
| 172 | cancel p; | |
| 173 | assertOrPanic(S.y == 2); | |
| 174 | } | |
| 175 | ||
| 176 | test "async fn pointer in a struct field" { | |
| 177 | var data: i32 = 1; | |
| 178 | const Foo = struct { | |
| 179 | bar: async<*std.mem.Allocator> fn (*i32) void, | |
| 180 | }; | |
| 181 | var foo = Foo{ .bar = simpleAsyncFn2 }; | |
| 182 | var da = std.heap.DirectAllocator.init(); | |
| 183 | defer da.deinit(); | |
| 184 | const p = (async<&da.allocator> foo.bar(&data)) catch unreachable; | |
| 185 | assertOrPanic(data == 2); | |
| 186 | cancel p; | |
| 187 | assertOrPanic(data == 4); | |
| 188 | } | |
| 189 | async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void { | |
| 190 | defer y.* += 2; | |
| 191 | y.* += 1; | |
| 192 | suspend; | |
| 193 | } | |
| 194 | ||
| 195 | test "async fn with inferred error set" { | |
| 196 | var da = std.heap.DirectAllocator.init(); | |
| 197 | defer da.deinit(); | |
| 198 | const p = (async<&da.allocator> failing()) catch unreachable; | |
| 199 | resume p; | |
| 200 | cancel p; | |
| 201 | } | |
| 202 | ||
| 203 | async fn failing() !void { | |
| 204 | suspend; | |
| 205 | return error.Fail; | |
| 206 | } | |
| 207 | ||
| 208 | test "error return trace across suspend points - early return" { | |
| 209 | const p = nonFailing(); | |
| 210 | resume p; | |
| 211 | var da = std.heap.DirectAllocator.init(); | |
| 212 | defer da.deinit(); | |
| 213 | const p2 = try async<&da.allocator> printTrace(p); | |
| 214 | cancel p2; | |
| 215 | } | |
| 216 | ||
| 217 | test "error return trace across suspend points - async return" { | |
| 218 | const p = nonFailing(); | |
| 219 | const p2 = try async<std.debug.global_allocator> printTrace(p); | |
| 220 | resume p; | |
| 221 | cancel p2; | |
| 222 | } | |
| 223 | ||
| 224 | fn nonFailing() (promise->anyerror!void) { | |
| 225 | return async<std.debug.global_allocator> suspendThenFail() catch unreachable; | |
| 226 | } | |
| 227 | async fn suspendThenFail() anyerror!void { | |
| 228 | suspend; | |
| 229 | return error.Fail; | |
| 230 | } | |
| 231 | async fn printTrace(p: promise->(anyerror!void)) void { | |
| 232 | (await p) catch |e| { | |
| 233 | std.debug.assertOrPanic(e == error.Fail); | |
| 234 | if (@errorReturnTrace()) |trace| { | |
| 235 | assertOrPanic(trace.index == 1); | |
| 236 | } else switch (builtin.mode) { | |
| 237 | builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"), | |
| 238 | builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {}, | |
| 239 | } | |
| 240 | }; | |
| 241 | } | |
| 242 | ||
| 243 | test "break from suspend" { | |
| 244 | var buf: [500]u8 = undefined; | |
| 245 | var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator; | |
| 246 | var my_result: i32 = 1; | |
| 247 | const p = try async<a> testBreakFromSuspend(&my_result); | |
| 248 | cancel p; | |
| 249 | std.debug.assertOrPanic(my_result == 2); | |
| 250 | } | |
| 251 | async fn testBreakFromSuspend(my_result: *i32) void { | |
| 252 | suspend { | |
| 253 | resume @handle(); | |
| 254 | } | |
| 255 | my_result.* += 1; | |
| 256 | suspend; | |
| 257 | my_result.* += 1; | |
| 258 | } |
test/stage1/behavior/defer.zig created+78| ... | ... | @@ -0,0 +1,78 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | var result: [3]u8 = undefined; | |
| 4 | var index: usize = undefined; | |
| 5 | ||
| 6 | fn runSomeErrorDefers(x: bool) !bool { | |
| 7 | index = 0; | |
| 8 | defer { | |
| 9 | result[index] = 'a'; | |
| 10 | index += 1; | |
| 11 | } | |
| 12 | errdefer { | |
| 13 | result[index] = 'b'; | |
| 14 | index += 1; | |
| 15 | } | |
| 16 | defer { | |
| 17 | result[index] = 'c'; | |
| 18 | index += 1; | |
| 19 | } | |
| 20 | return if (x) x else error.FalseNotAllowed; | |
| 21 | } | |
| 22 | ||
| 23 | test "mixing normal and error defers" { | |
| 24 | assertOrPanic(runSomeErrorDefers(true) catch unreachable); | |
| 25 | assertOrPanic(result[0] == 'c'); | |
| 26 | assertOrPanic(result[1] == 'a'); | |
| 27 | ||
| 28 | const ok = runSomeErrorDefers(false) catch |err| x: { | |
| 29 | assertOrPanic(err == error.FalseNotAllowed); | |
| 30 | break :x true; | |
| 31 | }; | |
| 32 | assertOrPanic(ok); | |
| 33 | assertOrPanic(result[0] == 'c'); | |
| 34 | assertOrPanic(result[1] == 'b'); | |
| 35 | assertOrPanic(result[2] == 'a'); | |
| 36 | } | |
| 37 | ||
| 38 | test "break and continue inside loop inside defer expression" { | |
| 39 | testBreakContInDefer(10); | |
| 40 | comptime testBreakContInDefer(10); | |
| 41 | } | |
| 42 | ||
| 43 | fn testBreakContInDefer(x: usize) void { | |
| 44 | defer { | |
| 45 | var i: usize = 0; | |
| 46 | while (i < x) : (i += 1) { | |
| 47 | if (i < 5) continue; | |
| 48 | if (i == 5) break; | |
| 49 | } | |
| 50 | assertOrPanic(i == 5); | |
| 51 | } | |
| 52 | } | |
| 53 | ||
| 54 | test "defer and labeled break" { | |
| 55 | var i = usize(0); | |
| 56 | ||
| 57 | blk: { | |
| 58 | defer i += 1; | |
| 59 | break :blk; | |
| 60 | } | |
| 61 | ||
| 62 | assertOrPanic(i == 1); | |
| 63 | } | |
| 64 | ||
| 65 | test "errdefer does not apply to fn inside fn" { | |
| 66 | if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assertOrPanic(e == error.Bad); | |
| 67 | } | |
| 68 | ||
| 69 | fn testNestedFnErrDefer() anyerror!void { | |
| 70 | var a: i32 = 0; | |
| 71 | errdefer a += 1; | |
| 72 | const S = struct { | |
| 73 | fn baz() anyerror { | |
| 74 | return error.Bad; | |
| 75 | } | |
| 76 | }; | |
| 77 | return S.baz(); | |
| 78 | } |
test/stage1/behavior/enum.zig created+894| ... | ... | @@ -0,0 +1,894 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | const mem = @import("std").mem; | |
| 3 | ||
| 4 | test "enum type" { | |
| 5 | const foo1 = Foo{ .One = 13 }; | |
| 6 | const foo2 = Foo{ | |
| 7 | .Two = Point{ | |
| 8 | .x = 1234, | |
| 9 | .y = 5678, | |
| 10 | }, | |
| 11 | }; | |
| 12 | const bar = Bar.B; | |
| 13 | ||
| 14 | assertOrPanic(bar == Bar.B); | |
| 15 | assertOrPanic(@memberCount(Foo) == 3); | |
| 16 | assertOrPanic(@memberCount(Bar) == 4); | |
| 17 | assertOrPanic(@sizeOf(Foo) == @sizeOf(FooNoVoid)); | |
| 18 | assertOrPanic(@sizeOf(Bar) == 1); | |
| 19 | } | |
| 20 | ||
| 21 | test "enum as return value" { | |
| 22 | switch (returnAnInt(13)) { | |
| 23 | Foo.One => |value| assertOrPanic(value == 13), | |
| 24 | else => unreachable, | |
| 25 | } | |
| 26 | } | |
| 27 | ||
| 28 | const Point = struct { | |
| 29 | x: u64, | |
| 30 | y: u64, | |
| 31 | }; | |
| 32 | const Foo = union(enum) { | |
| 33 | One: i32, | |
| 34 | Two: Point, | |
| 35 | Three: void, | |
| 36 | }; | |
| 37 | const FooNoVoid = union(enum) { | |
| 38 | One: i32, | |
| 39 | Two: Point, | |
| 40 | }; | |
| 41 | const Bar = enum { | |
| 42 | A, | |
| 43 | B, | |
| 44 | C, | |
| 45 | D, | |
| 46 | }; | |
| 47 | ||
| 48 | fn returnAnInt(x: i32) Foo { | |
| 49 | return Foo{ .One = x }; | |
| 50 | } | |
| 51 | ||
| 52 | test "constant enum with payload" { | |
| 53 | var empty = AnEnumWithPayload{ .Empty = {} }; | |
| 54 | var full = AnEnumWithPayload{ .Full = 13 }; | |
| 55 | shouldBeEmpty(empty); | |
| 56 | shouldBeNotEmpty(full); | |
| 57 | } | |
| 58 | ||
| 59 | fn shouldBeEmpty(x: AnEnumWithPayload) void { | |
| 60 | switch (x) { | |
| 61 | AnEnumWithPayload.Empty => {}, | |
| 62 | else => unreachable, | |
| 63 | } | |
| 64 | } | |
| 65 | ||
| 66 | fn shouldBeNotEmpty(x: AnEnumWithPayload) void { | |
| 67 | switch (x) { | |
| 68 | AnEnumWithPayload.Empty => unreachable, | |
| 69 | else => {}, | |
| 70 | } | |
| 71 | } | |
| 72 | ||
| 73 | const AnEnumWithPayload = union(enum) { | |
| 74 | Empty: void, | |
| 75 | Full: i32, | |
| 76 | }; | |
| 77 | ||
| 78 | const Number = enum { | |
| 79 | Zero, | |
| 80 | One, | |
| 81 | Two, | |
| 82 | Three, | |
| 83 | Four, | |
| 84 | }; | |
| 85 | ||
| 86 | test "enum to int" { | |
| 87 | shouldEqual(Number.Zero, 0); | |
| 88 | shouldEqual(Number.One, 1); | |
| 89 | shouldEqual(Number.Two, 2); | |
| 90 | shouldEqual(Number.Three, 3); | |
| 91 | shouldEqual(Number.Four, 4); | |
| 92 | } | |
| 93 | ||
| 94 | fn shouldEqual(n: Number, expected: u3) void { | |
| 95 | assertOrPanic(@enumToInt(n) == expected); | |
| 96 | } | |
| 97 | ||
| 98 | test "int to enum" { | |
| 99 | testIntToEnumEval(3); | |
| 100 | } | |
| 101 | fn testIntToEnumEval(x: i32) void { | |
| 102 | assertOrPanic(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three); | |
| 103 | } | |
| 104 | const IntToEnumNumber = enum { | |
| 105 | Zero, | |
| 106 | One, | |
| 107 | Two, | |
| 108 | Three, | |
| 109 | Four, | |
| 110 | }; | |
| 111 | ||
| 112 | test "@tagName" { | |
| 113 | assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | |
| 114 | comptime assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three")); | |
| 115 | } | |
| 116 | ||
| 117 | fn testEnumTagNameBare(n: BareNumber) []const u8 { | |
| 118 | return @tagName(n); | |
| 119 | } | |
| 120 | ||
| 121 | const BareNumber = enum { | |
| 122 | One, | |
| 123 | Two, | |
| 124 | Three, | |
| 125 | }; | |
| 126 | ||
| 127 | test "enum alignment" { | |
| 128 | comptime { | |
| 129 | assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf([9]u8)); | |
| 130 | assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf(u64)); | |
| 131 | } | |
| 132 | } | |
| 133 | ||
| 134 | const AlignTestEnum = union(enum) { | |
| 135 | A: [9]u8, | |
| 136 | B: u64, | |
| 137 | }; | |
| 138 | ||
| 139 | const ValueCount1 = enum { | |
| 140 | I0, | |
| 141 | }; | |
| 142 | const ValueCount2 = enum { | |
| 143 | I0, | |
| 144 | I1, | |
| 145 | }; | |
| 146 | const ValueCount256 = enum { | |
| 147 | I0, | |
| 148 | I1, | |
| 149 | I2, | |
| 150 | I3, | |
| 151 | I4, | |
| 152 | I5, | |
| 153 | I6, | |
| 154 | I7, | |
| 155 | I8, | |
| 156 | I9, | |
| 157 | I10, | |
| 158 | I11, | |
| 159 | I12, | |
| 160 | I13, | |
| 161 | I14, | |
| 162 | I15, | |
| 163 | I16, | |
| 164 | I17, | |
| 165 | I18, | |
| 166 | I19, | |
| 167 | I20, | |
| 168 | I21, | |
| 169 | I22, | |
| 170 | I23, | |
| 171 | I24, | |
| 172 | I25, | |
| 173 | I26, | |
| 174 | I27, | |
| 175 | I28, | |
| 176 | I29, | |
| 177 | I30, | |
| 178 | I31, | |
| 179 | I32, | |
| 180 | I33, | |
| 181 | I34, | |
| 182 | I35, | |
| 183 | I36, | |
| 184 | I37, | |
| 185 | I38, | |
| 186 | I39, | |
| 187 | I40, | |
| 188 | I41, | |
| 189 | I42, | |
| 190 | I43, | |
| 191 | I44, | |
| 192 | I45, | |
| 193 | I46, | |
| 194 | I47, | |
| 195 | I48, | |
| 196 | I49, | |
| 197 | I50, | |
| 198 | I51, | |
| 199 | I52, | |
| 200 | I53, | |
| 201 | I54, | |
| 202 | I55, | |
| 203 | I56, | |
| 204 | I57, | |
| 205 | I58, | |
| 206 | I59, | |
| 207 | I60, | |
| 208 | I61, | |
| 209 | I62, | |
| 210 | I63, | |
| 211 | I64, | |
| 212 | I65, | |
| 213 | I66, | |
| 214 | I67, | |
| 215 | I68, | |
| 216 | I69, | |
| 217 | I70, | |
| 218 | I71, | |
| 219 | I72, | |
| 220 | I73, | |
| 221 | I74, | |
| 222 | I75, | |
| 223 | I76, | |
| 224 | I77, | |
| 225 | I78, | |
| 226 | I79, | |
| 227 | I80, | |
| 228 | I81, | |
| 229 | I82, | |
| 230 | I83, | |
| 231 | I84, | |
| 232 | I85, | |
| 233 | I86, | |
| 234 | I87, | |
| 235 | I88, | |
| 236 | I89, | |
| 237 | I90, | |
| 238 | I91, | |
| 239 | I92, | |
| 240 | I93, | |
| 241 | I94, | |
| 242 | I95, | |
| 243 | I96, | |
| 244 | I97, | |
| 245 | I98, | |
| 246 | I99, | |
| 247 | I100, | |
| 248 | I101, | |
| 249 | I102, | |
| 250 | I103, | |
| 251 | I104, | |
| 252 | I105, | |
| 253 | I106, | |
| 254 | I107, | |
| 255 | I108, | |
| 256 | I109, | |
| 257 | I110, | |
| 258 | I111, | |
| 259 | I112, | |
| 260 | I113, | |
| 261 | I114, | |
| 262 | I115, | |
| 263 | I116, | |
| 264 | I117, | |
| 265 | I118, | |
| 266 | I119, | |
| 267 | I120, | |
| 268 | I121, | |
| 269 | I122, | |
| 270 | I123, | |
| 271 | I124, | |
| 272 | I125, | |
| 273 | I126, | |
| 274 | I127, | |
| 275 | I128, | |
| 276 | I129, | |
| 277 | I130, | |
| 278 | I131, | |
| 279 | I132, | |
| 280 | I133, | |
| 281 | I134, | |
| 282 | I135, | |
| 283 | I136, | |
| 284 | I137, | |
| 285 | I138, | |
| 286 | I139, | |
| 287 | I140, | |
| 288 | I141, | |
| 289 | I142, | |
| 290 | I143, | |
| 291 | I144, | |
| 292 | I145, | |
| 293 | I146, | |
| 294 | I147, | |
| 295 | I148, | |
| 296 | I149, | |
| 297 | I150, | |
| 298 | I151, | |
| 299 | I152, | |
| 300 | I153, | |
| 301 | I154, | |
| 302 | I155, | |
| 303 | I156, | |
| 304 | I157, | |
| 305 | I158, | |
| 306 | I159, | |
| 307 | I160, | |
| 308 | I161, | |
| 309 | I162, | |
| 310 | I163, | |
| 311 | I164, | |
| 312 | I165, | |
| 313 | I166, | |
| 314 | I167, | |
| 315 | I168, | |
| 316 | I169, | |
| 317 | I170, | |
| 318 | I171, | |
| 319 | I172, | |
| 320 | I173, | |
| 321 | I174, | |
| 322 | I175, | |
| 323 | I176, | |
| 324 | I177, | |
| 325 | I178, | |
| 326 | I179, | |
| 327 | I180, | |
| 328 | I181, | |
| 329 | I182, | |
| 330 | I183, | |
| 331 | I184, | |
| 332 | I185, | |
| 333 | I186, | |
| 334 | I187, | |
| 335 | I188, | |
| 336 | I189, | |
| 337 | I190, | |
| 338 | I191, | |
| 339 | I192, | |
| 340 | I193, | |
| 341 | I194, | |
| 342 | I195, | |
| 343 | I196, | |
| 344 | I197, | |
| 345 | I198, | |
| 346 | I199, | |
| 347 | I200, | |
| 348 | I201, | |
| 349 | I202, | |
| 350 | I203, | |
| 351 | I204, | |
| 352 | I205, | |
| 353 | I206, | |
| 354 | I207, | |
| 355 | I208, | |
| 356 | I209, | |
| 357 | I210, | |
| 358 | I211, | |
| 359 | I212, | |
| 360 | I213, | |
| 361 | I214, | |
| 362 | I215, | |
| 363 | I216, | |
| 364 | I217, | |
| 365 | I218, | |
| 366 | I219, | |
| 367 | I220, | |
| 368 | I221, | |
| 369 | I222, | |
| 370 | I223, | |
| 371 | I224, | |
| 372 | I225, | |
| 373 | I226, | |
| 374 | I227, | |
| 375 | I228, | |
| 376 | I229, | |
| 377 | I230, | |
| 378 | I231, | |
| 379 | I232, | |
| 380 | I233, | |
| 381 | I234, | |
| 382 | I235, | |
| 383 | I236, | |
| 384 | I237, | |
| 385 | I238, | |
| 386 | I239, | |
| 387 | I240, | |
| 388 | I241, | |
| 389 | I242, | |
| 390 | I243, | |
| 391 | I244, | |
| 392 | I245, | |
| 393 | I246, | |
| 394 | I247, | |
| 395 | I248, | |
| 396 | I249, | |
| 397 | I250, | |
| 398 | I251, | |
| 399 | I252, | |
| 400 | I253, | |
| 401 | I254, | |
| 402 | I255, | |
| 403 | }; | |
| 404 | const ValueCount257 = enum { | |
| 405 | I0, | |
| 406 | I1, | |
| 407 | I2, | |
| 408 | I3, | |
| 409 | I4, | |
| 410 | I5, | |
| 411 | I6, | |
| 412 | I7, | |
| 413 | I8, | |
| 414 | I9, | |
| 415 | I10, | |
| 416 | I11, | |
| 417 | I12, | |
| 418 | I13, | |
| 419 | I14, | |
| 420 | I15, | |
| 421 | I16, | |
| 422 | I17, | |
| 423 | I18, | |
| 424 | I19, | |
| 425 | I20, | |
| 426 | I21, | |
| 427 | I22, | |
| 428 | I23, | |
| 429 | I24, | |
| 430 | I25, | |
| 431 | I26, | |
| 432 | I27, | |
| 433 | I28, | |
| 434 | I29, | |
| 435 | I30, | |
| 436 | I31, | |
| 437 | I32, | |
| 438 | I33, | |
| 439 | I34, | |
| 440 | I35, | |
| 441 | I36, | |
| 442 | I37, | |
| 443 | I38, | |
| 444 | I39, | |
| 445 | I40, | |
| 446 | I41, | |
| 447 | I42, | |
| 448 | I43, | |
| 449 | I44, | |
| 450 | I45, | |
| 451 | I46, | |
| 452 | I47, | |
| 453 | I48, | |
| 454 | I49, | |
| 455 | I50, | |
| 456 | I51, | |
| 457 | I52, | |
| 458 | I53, | |
| 459 | I54, | |
| 460 | I55, | |
| 461 | I56, | |
| 462 | I57, | |
| 463 | I58, | |
| 464 | I59, | |
| 465 | I60, | |
| 466 | I61, | |
| 467 | I62, | |
| 468 | I63, | |
| 469 | I64, | |
| 470 | I65, | |
| 471 | I66, | |
| 472 | I67, | |
| 473 | I68, | |
| 474 | I69, | |
| 475 | I70, | |
| 476 | I71, | |
| 477 | I72, | |
| 478 | I73, | |
| 479 | I74, | |
| 480 | I75, | |
| 481 | I76, | |
| 482 | I77, | |
| 483 | I78, | |
| 484 | I79, | |
| 485 | I80, | |
| 486 | I81, | |
| 487 | I82, | |
| 488 | I83, | |
| 489 | I84, | |
| 490 | I85, | |
| 491 | I86, | |
| 492 | I87, | |
| 493 | I88, | |
| 494 | I89, | |
| 495 | I90, | |
| 496 | I91, | |
| 497 | I92, | |
| 498 | I93, | |
| 499 | I94, | |
| 500 | I95, | |
| 501 | I96, | |
| 502 | I97, | |
| 503 | I98, | |
| 504 | I99, | |
| 505 | I100, | |
| 506 | I101, | |
| 507 | I102, | |
| 508 | I103, | |
| 509 | I104, | |
| 510 | I105, | |
| 511 | I106, | |
| 512 | I107, | |
| 513 | I108, | |
| 514 | I109, | |
| 515 | I110, | |
| 516 | I111, | |
| 517 | I112, | |
| 518 | I113, | |
| 519 | I114, | |
| 520 | I115, | |
| 521 | I116, | |
| 522 | I117, | |
| 523 | I118, | |
| 524 | I119, | |
| 525 | I120, | |
| 526 | I121, | |
| 527 | I122, | |
| 528 | I123, | |
| 529 | I124, | |
| 530 | I125, | |
| 531 | I126, | |
| 532 | I127, | |
| 533 | I128, | |
| 534 | I129, | |
| 535 | I130, | |
| 536 | I131, | |
| 537 | I132, | |
| 538 | I133, | |
| 539 | I134, | |
| 540 | I135, | |
| 541 | I136, | |
| 542 | I137, | |
| 543 | I138, | |
| 544 | I139, | |
| 545 | I140, | |
| 546 | I141, | |
| 547 | I142, | |
| 548 | I143, | |
| 549 | I144, | |
| 550 | I145, | |
| 551 | I146, | |
| 552 | I147, | |
| 553 | I148, | |
| 554 | I149, | |
| 555 | I150, | |
| 556 | I151, | |
| 557 | I152, | |
| 558 | I153, | |
| 559 | I154, | |
| 560 | I155, | |
| 561 | I156, | |
| 562 | I157, | |
| 563 | I158, | |
| 564 | I159, | |
| 565 | I160, | |
| 566 | I161, | |
| 567 | I162, | |
| 568 | I163, | |
| 569 | I164, | |
| 570 | I165, | |
| 571 | I166, | |
| 572 | I167, | |
| 573 | I168, | |
| 574 | I169, | |
| 575 | I170, | |
| 576 | I171, | |
| 577 | I172, | |
| 578 | I173, | |
| 579 | I174, | |
| 580 | I175, | |
| 581 | I176, | |
| 582 | I177, | |
| 583 | I178, | |
| 584 | I179, | |
| 585 | I180, | |
| 586 | I181, | |
| 587 | I182, | |
| 588 | I183, | |
| 589 | I184, | |
| 590 | I185, | |
| 591 | I186, | |
| 592 | I187, | |
| 593 | I188, | |
| 594 | I189, | |
| 595 | I190, | |
| 596 | I191, | |
| 597 | I192, | |
| 598 | I193, | |
| 599 | I194, | |
| 600 | I195, | |
| 601 | I196, | |
| 602 | I197, | |
| 603 | I198, | |
| 604 | I199, | |
| 605 | I200, | |
| 606 | I201, | |
| 607 | I202, | |
| 608 | I203, | |
| 609 | I204, | |
| 610 | I205, | |
| 611 | I206, | |
| 612 | I207, | |
| 613 | I208, | |
| 614 | I209, | |
| 615 | I210, | |
| 616 | I211, | |
| 617 | I212, | |
| 618 | I213, | |
| 619 | I214, | |
| 620 | I215, | |
| 621 | I216, | |
| 622 | I217, | |
| 623 | I218, | |
| 624 | I219, | |
| 625 | I220, | |
| 626 | I221, | |
| 627 | I222, | |
| 628 | I223, | |
| 629 | I224, | |
| 630 | I225, | |
| 631 | I226, | |
| 632 | I227, | |
| 633 | I228, | |
| 634 | I229, | |
| 635 | I230, | |
| 636 | I231, | |
| 637 | I232, | |
| 638 | I233, | |
| 639 | I234, | |
| 640 | I235, | |
| 641 | I236, | |
| 642 | I237, | |
| 643 | I238, | |
| 644 | I239, | |
| 645 | I240, | |
| 646 | I241, | |
| 647 | I242, | |
| 648 | I243, | |
| 649 | I244, | |
| 650 | I245, | |
| 651 | I246, | |
| 652 | I247, | |
| 653 | I248, | |
| 654 | I249, | |
| 655 | I250, | |
| 656 | I251, | |
| 657 | I252, | |
| 658 | I253, | |
| 659 | I254, | |
| 660 | I255, | |
| 661 | I256, | |
| 662 | }; | |
| 663 | ||
| 664 | test "enum sizes" { | |
| 665 | comptime { | |
| 666 | assertOrPanic(@sizeOf(ValueCount1) == 0); | |
| 667 | assertOrPanic(@sizeOf(ValueCount2) == 1); | |
| 668 | assertOrPanic(@sizeOf(ValueCount256) == 1); | |
| 669 | assertOrPanic(@sizeOf(ValueCount257) == 2); | |
| 670 | } | |
| 671 | } | |
| 672 | ||
| 673 | const Small2 = enum(u2) { | |
| 674 | One, | |
| 675 | Two, | |
| 676 | }; | |
| 677 | const Small = enum(u2) { | |
| 678 | One, | |
| 679 | Two, | |
| 680 | Three, | |
| 681 | Four, | |
| 682 | }; | |
| 683 | ||
| 684 | test "set enum tag type" { | |
| 685 | { | |
| 686 | var x = Small.One; | |
| 687 | x = Small.Two; | |
| 688 | comptime assertOrPanic(@TagType(Small) == u2); | |
| 689 | } | |
| 690 | { | |
| 691 | var x = Small2.One; | |
| 692 | x = Small2.Two; | |
| 693 | comptime assertOrPanic(@TagType(Small2) == u2); | |
| 694 | } | |
| 695 | } | |
| 696 | ||
| 697 | const A = enum(u3) { | |
| 698 | One, | |
| 699 | Two, | |
| 700 | Three, | |
| 701 | Four, | |
| 702 | One2, | |
| 703 | Two2, | |
| 704 | Three2, | |
| 705 | Four2, | |
| 706 | }; | |
| 707 | ||
| 708 | const B = enum(u3) { | |
| 709 | One3, | |
| 710 | Two3, | |
| 711 | Three3, | |
| 712 | Four3, | |
| 713 | One23, | |
| 714 | Two23, | |
| 715 | Three23, | |
| 716 | Four23, | |
| 717 | }; | |
| 718 | ||
| 719 | const C = enum(u2) { | |
| 720 | One4, | |
| 721 | Two4, | |
| 722 | Three4, | |
| 723 | Four4, | |
| 724 | }; | |
| 725 | ||
| 726 | const BitFieldOfEnums = packed struct { | |
| 727 | a: A, | |
| 728 | b: B, | |
| 729 | c: C, | |
| 730 | }; | |
| 731 | ||
| 732 | const bit_field_1 = BitFieldOfEnums{ | |
| 733 | .a = A.Two, | |
| 734 | .b = B.Three3, | |
| 735 | .c = C.Four4, | |
| 736 | }; | |
| 737 | ||
| 738 | test "bit field access with enum fields" { | |
| 739 | var data = bit_field_1; | |
| 740 | assertOrPanic(getA(&data) == A.Two); | |
| 741 | assertOrPanic(getB(&data) == B.Three3); | |
| 742 | assertOrPanic(getC(&data) == C.Four4); | |
| 743 | comptime assertOrPanic(@sizeOf(BitFieldOfEnums) == 1); | |
| 744 | ||
| 745 | data.b = B.Four3; | |
| 746 | assertOrPanic(data.b == B.Four3); | |
| 747 | ||
| 748 | data.a = A.Three; | |
| 749 | assertOrPanic(data.a == A.Three); | |
| 750 | assertOrPanic(data.b == B.Four3); | |
| 751 | } | |
| 752 | ||
| 753 | fn getA(data: *const BitFieldOfEnums) A { | |
| 754 | return data.a; | |
| 755 | } | |
| 756 | ||
| 757 | fn getB(data: *const BitFieldOfEnums) B { | |
| 758 | return data.b; | |
| 759 | } | |
| 760 | ||
| 761 | fn getC(data: *const BitFieldOfEnums) C { | |
| 762 | return data.c; | |
| 763 | } | |
| 764 | ||
| 765 | test "casting enum to its tag type" { | |
| 766 | testCastEnumToTagType(Small2.Two); | |
| 767 | comptime testCastEnumToTagType(Small2.Two); | |
| 768 | } | |
| 769 | ||
| 770 | fn testCastEnumToTagType(value: Small2) void { | |
| 771 | assertOrPanic(@enumToInt(value) == 1); | |
| 772 | } | |
| 773 | ||
| 774 | const MultipleChoice = enum(u32) { | |
| 775 | A = 20, | |
| 776 | B = 40, | |
| 777 | C = 60, | |
| 778 | D = 1000, | |
| 779 | }; | |
| 780 | ||
| 781 | test "enum with specified tag values" { | |
| 782 | testEnumWithSpecifiedTagValues(MultipleChoice.C); | |
| 783 | comptime testEnumWithSpecifiedTagValues(MultipleChoice.C); | |
| 784 | } | |
| 785 | ||
| 786 | fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void { | |
| 787 | assertOrPanic(@enumToInt(x) == 60); | |
| 788 | assertOrPanic(1234 == switch (x) { | |
| 789 | MultipleChoice.A => 1, | |
| 790 | MultipleChoice.B => 2, | |
| 791 | MultipleChoice.C => u32(1234), | |
| 792 | MultipleChoice.D => 4, | |
| 793 | }); | |
| 794 | } | |
| 795 | ||
| 796 | const MultipleChoice2 = enum(u32) { | |
| 797 | Unspecified1, | |
| 798 | A = 20, | |
| 799 | Unspecified2, | |
| 800 | B = 40, | |
| 801 | Unspecified3, | |
| 802 | C = 60, | |
| 803 | Unspecified4, | |
| 804 | D = 1000, | |
| 805 | Unspecified5, | |
| 806 | }; | |
| 807 | ||
| 808 | test "enum with specified and unspecified tag values" { | |
| 809 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | |
| 810 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D); | |
| 811 | } | |
| 812 | ||
| 813 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { | |
| 814 | assertOrPanic(@enumToInt(x) == 1000); | |
| 815 | assertOrPanic(1234 == switch (x) { | |
| 816 | MultipleChoice2.A => 1, | |
| 817 | MultipleChoice2.B => 2, | |
| 818 | MultipleChoice2.C => 3, | |
| 819 | MultipleChoice2.D => u32(1234), | |
| 820 | MultipleChoice2.Unspecified1 => 5, | |
| 821 | MultipleChoice2.Unspecified2 => 6, | |
| 822 | MultipleChoice2.Unspecified3 => 7, | |
| 823 | MultipleChoice2.Unspecified4 => 8, | |
| 824 | MultipleChoice2.Unspecified5 => 9, | |
| 825 | }); | |
| 826 | } | |
| 827 | ||
| 828 | test "cast integer literal to enum" { | |
| 829 | assertOrPanic(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1); | |
| 830 | assertOrPanic(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B); | |
| 831 | } | |
| 832 | ||
| 833 | const EnumWithOneMember = enum { | |
| 834 | Eof, | |
| 835 | }; | |
| 836 | ||
| 837 | fn doALoopThing(id: EnumWithOneMember) void { | |
| 838 | while (true) { | |
| 839 | if (id == EnumWithOneMember.Eof) { | |
| 840 | break; | |
| 841 | } | |
| 842 | @compileError("above if condition should be comptime"); | |
| 843 | } | |
| 844 | } | |
| 845 | ||
| 846 | test "comparison operator on enum with one member is comptime known" { | |
| 847 | doALoopThing(EnumWithOneMember.Eof); | |
| 848 | } | |
| 849 | ||
| 850 | const State = enum { | |
| 851 | Start, | |
| 852 | }; | |
| 853 | test "switch on enum with one member is comptime known" { | |
| 854 | var state = State.Start; | |
| 855 | switch (state) { | |
| 856 | State.Start => return, | |
| 857 | } | |
| 858 | @compileError("analysis should not reach here"); | |
| 859 | } | |
| 860 | ||
| 861 | const EnumWithTagValues = enum(u4) { | |
| 862 | A = 1 << 0, | |
| 863 | B = 1 << 1, | |
| 864 | C = 1 << 2, | |
| 865 | D = 1 << 3, | |
| 866 | }; | |
| 867 | test "enum with tag values don't require parens" { | |
| 868 | assertOrPanic(@enumToInt(EnumWithTagValues.C) == 0b0100); | |
| 869 | } | |
| 870 | ||
| 871 | test "enum with 1 field but explicit tag type should still have the tag type" { | |
| 872 | const Enum = enum(u8) { | |
| 873 | B = 2, | |
| 874 | }; | |
| 875 | comptime @import("std").debug.assertOrPanic(@sizeOf(Enum) == @sizeOf(u8)); | |
| 876 | } | |
| 877 | ||
| 878 | test "empty extern enum with members" { | |
| 879 | const E = extern enum { | |
| 880 | A, | |
| 881 | B, | |
| 882 | C, | |
| 883 | }; | |
| 884 | assertOrPanic(@sizeOf(E) == @sizeOf(c_int)); | |
| 885 | } | |
| 886 | ||
| 887 | test "tag name with assigned enum values" { | |
| 888 | const LocalFoo = enum { | |
| 889 | A = 1, | |
| 890 | B = 0, | |
| 891 | }; | |
| 892 | var b = LocalFoo.B; | |
| 893 | assertOrPanic(mem.eql(u8, @tagName(b), "B")); | |
| 894 | } |
test/stage1/behavior/enum_with_members.zig created+27| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | const mem = @import("std").mem; | |
| 3 | const fmt = @import("std").fmt; | |
| 4 | ||
| 5 | const ET = union(enum) { | |
| 6 | SINT: i32, | |
| 7 | UINT: u32, | |
| 8 | ||
| 9 | pub fn print(a: *const ET, buf: []u8) anyerror!usize { | |
| 10 | return switch (a.*) { | |
| 11 | ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), | |
| 12 | ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0), | |
| 13 | }; | |
| 14 | } | |
| 15 | }; | |
| 16 | ||
| 17 | test "enum with members" { | |
| 18 | const a = ET{ .SINT = -42 }; | |
| 19 | const b = ET{ .UINT = 42 }; | |
| 20 | var buf: [20]u8 = undefined; | |
| 21 | ||
| 22 | assertOrPanic((a.print(buf[0..]) catch unreachable) == 3); | |
| 23 | assertOrPanic(mem.eql(u8, buf[0..3], "-42")); | |
| 24 | ||
| 25 | assertOrPanic((b.print(buf[0..]) catch unreachable) == 2); | |
| 26 | assertOrPanic(mem.eql(u8, buf[0..2], "42")); | |
| 27 | } |
test/stage1/behavior/error.zig created+332| ... | ... | @@ -0,0 +1,332 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const assertError = std.debug.assertError; | |
| 4 | const mem = std.mem; | |
| 5 | const builtin = @import("builtin"); | |
| 6 | ||
| 7 | pub fn foo() anyerror!i32 { | |
| 8 | const x = try bar(); | |
| 9 | return x + 1; | |
| 10 | } | |
| 11 | ||
| 12 | pub fn bar() anyerror!i32 { | |
| 13 | return 13; | |
| 14 | } | |
| 15 | ||
| 16 | pub fn baz() anyerror!i32 { | |
| 17 | const y = foo() catch 1234; | |
| 18 | return y + 1; | |
| 19 | } | |
| 20 | ||
| 21 | test "error wrapping" { | |
| 22 | assertOrPanic((baz() catch unreachable) == 15); | |
| 23 | } | |
| 24 | ||
| 25 | fn gimmeItBroke() []const u8 { | |
| 26 | return @errorName(error.ItBroke); | |
| 27 | } | |
| 28 | ||
| 29 | test "@errorName" { | |
| 30 | assertOrPanic(mem.eql(u8, @errorName(error.AnError), "AnError")); | |
| 31 | assertOrPanic(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); | |
| 32 | } | |
| 33 | ||
| 34 | test "error values" { | |
| 35 | const a = @errorToInt(error.err1); | |
| 36 | const b = @errorToInt(error.err2); | |
| 37 | assertOrPanic(a != b); | |
| 38 | } | |
| 39 | ||
| 40 | test "redefinition of error values allowed" { | |
| 41 | shouldBeNotEqual(error.AnError, error.SecondError); | |
| 42 | } | |
| 43 | fn shouldBeNotEqual(a: anyerror, b: anyerror) void { | |
| 44 | if (a == b) unreachable; | |
| 45 | } | |
| 46 | ||
| 47 | test "error binary operator" { | |
| 48 | const a = errBinaryOperatorG(true) catch 3; | |
| 49 | const b = errBinaryOperatorG(false) catch 3; | |
| 50 | assertOrPanic(a == 3); | |
| 51 | assertOrPanic(b == 10); | |
| 52 | } | |
| 53 | fn errBinaryOperatorG(x: bool) anyerror!isize { | |
| 54 | return if (x) error.ItBroke else isize(10); | |
| 55 | } | |
| 56 | ||
| 57 | test "unwrap simple value from error" { | |
| 58 | const i = unwrapSimpleValueFromErrorDo() catch unreachable; | |
| 59 | assertOrPanic(i == 13); | |
| 60 | } | |
| 61 | fn unwrapSimpleValueFromErrorDo() anyerror!isize { | |
| 62 | return 13; | |
| 63 | } | |
| 64 | ||
| 65 | test "error return in assignment" { | |
| 66 | doErrReturnInAssignment() catch unreachable; | |
| 67 | } | |
| 68 | ||
| 69 | fn doErrReturnInAssignment() anyerror!void { | |
| 70 | var x: i32 = undefined; | |
| 71 | x = try makeANonErr(); | |
| 72 | } | |
| 73 | ||
| 74 | fn makeANonErr() anyerror!i32 { | |
| 75 | return 1; | |
| 76 | } | |
| 77 | ||
| 78 | test "error union type " { | |
| 79 | testErrorUnionType(); | |
| 80 | comptime testErrorUnionType(); | |
| 81 | } | |
| 82 | ||
| 83 | fn testErrorUnionType() void { | |
| 84 | const x: anyerror!i32 = 1234; | |
| 85 | if (x) |value| assertOrPanic(value == 1234) else |_| unreachable; | |
| 86 | assertOrPanic(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion); | |
| 87 | assertOrPanic(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet); | |
| 88 | assertOrPanic(@typeOf(x).ErrorSet == anyerror); | |
| 89 | } | |
| 90 | ||
| 91 | test "error set type" { | |
| 92 | testErrorSetType(); | |
| 93 | comptime testErrorSetType(); | |
| 94 | } | |
| 95 | ||
| 96 | const MyErrSet = error{ | |
| 97 | OutOfMemory, | |
| 98 | FileNotFound, | |
| 99 | }; | |
| 100 | ||
| 101 | fn testErrorSetType() void { | |
| 102 | assertOrPanic(@memberCount(MyErrSet) == 2); | |
| 103 | ||
| 104 | const a: MyErrSet!i32 = 5678; | |
| 105 | const b: MyErrSet!i32 = MyErrSet.OutOfMemory; | |
| 106 | ||
| 107 | if (a) |value| assertOrPanic(value == 5678) else |err| switch (err) { | |
| 108 | error.OutOfMemory => unreachable, | |
| 109 | error.FileNotFound => unreachable, | |
| 110 | } | |
| 111 | } | |
| 112 | ||
| 113 | test "explicit error set cast" { | |
| 114 | testExplicitErrorSetCast(Set1.A); | |
| 115 | comptime testExplicitErrorSetCast(Set1.A); | |
| 116 | } | |
| 117 | ||
| 118 | const Set1 = error{ | |
| 119 | A, | |
| 120 | B, | |
| 121 | }; | |
| 122 | const Set2 = error{ | |
| 123 | A, | |
| 124 | C, | |
| 125 | }; | |
| 126 | ||
| 127 | fn testExplicitErrorSetCast(set1: Set1) void { | |
| 128 | var x = @errSetCast(Set2, set1); | |
| 129 | var y = @errSetCast(Set1, x); | |
| 130 | assertOrPanic(y == error.A); | |
| 131 | } | |
| 132 | ||
| 133 | test "comptime test error for empty error set" { | |
| 134 | testComptimeTestErrorEmptySet(1234); | |
| 135 | comptime testComptimeTestErrorEmptySet(1234); | |
| 136 | } | |
| 137 | ||
| 138 | const EmptyErrorSet = error{}; | |
| 139 | ||
| 140 | fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void { | |
| 141 | if (x) |v| assertOrPanic(v == 1234) else |err| @compileError("bad"); | |
| 142 | } | |
| 143 | ||
| 144 | test "syntax: optional operator in front of error union operator" { | |
| 145 | comptime { | |
| 146 | assertOrPanic(?(anyerror!i32) == ?(anyerror!i32)); | |
| 147 | } | |
| 148 | } | |
| 149 | ||
| 150 | test "comptime err to int of error set with only 1 possible value" { | |
| 151 | testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A)); | |
| 152 | comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A)); | |
| 153 | } | |
| 154 | fn testErrToIntWithOnePossibleValue( | |
| 155 | x: error{A}, | |
| 156 | comptime value: u32, | |
| 157 | ) void { | |
| 158 | if (@errorToInt(x) != value) { | |
| 159 | @compileError("bad"); | |
| 160 | } | |
| 161 | } | |
| 162 | ||
| 163 | test "error union peer type resolution" { | |
| 164 | testErrorUnionPeerTypeResolution(1); | |
| 165 | } | |
| 166 | ||
| 167 | fn testErrorUnionPeerTypeResolution(x: i32) void { | |
| 168 | const y = switch (x) { | |
| 169 | 1 => bar_1(), | |
| 170 | 2 => baz_1(), | |
| 171 | else => quux_1(), | |
| 172 | }; | |
| 173 | if (y) |_| { | |
| 174 | @panic("expected error"); | |
| 175 | } else |e| { | |
| 176 | assertOrPanic(e == error.A); | |
| 177 | } | |
| 178 | } | |
| 179 | ||
| 180 | fn bar_1() anyerror { | |
| 181 | return error.A; | |
| 182 | } | |
| 183 | ||
| 184 | fn baz_1() !i32 { | |
| 185 | return error.B; | |
| 186 | } | |
| 187 | ||
| 188 | fn quux_1() !i32 { | |
| 189 | return error.C; | |
| 190 | } | |
| 191 | ||
| 192 | test "error: fn returning empty error set can be passed as fn returning any error" { | |
| 193 | entry(); | |
| 194 | comptime entry(); | |
| 195 | } | |
| 196 | ||
| 197 | fn entry() void { | |
| 198 | foo2(bar2); | |
| 199 | } | |
| 200 | ||
| 201 | fn foo2(f: fn () anyerror!void) void { | |
| 202 | const x = f(); | |
| 203 | } | |
| 204 | ||
| 205 | fn bar2() (error{}!void) {} | |
| 206 | ||
| 207 | test "error: Zero sized error set returned with value payload crash" { | |
| 208 | _ = foo3(0); | |
| 209 | _ = comptime foo3(0); | |
| 210 | } | |
| 211 | ||
| 212 | const Error = error{}; | |
| 213 | fn foo3(b: usize) Error!usize { | |
| 214 | return b; | |
| 215 | } | |
| 216 | ||
| 217 | test "error: Infer error set from literals" { | |
| 218 | _ = nullLiteral("n") catch |err| handleErrors(err); | |
| 219 | _ = floatLiteral("n") catch |err| handleErrors(err); | |
| 220 | _ = intLiteral("n") catch |err| handleErrors(err); | |
| 221 | _ = comptime nullLiteral("n") catch |err| handleErrors(err); | |
| 222 | _ = comptime floatLiteral("n") catch |err| handleErrors(err); | |
| 223 | _ = comptime intLiteral("n") catch |err| handleErrors(err); | |
| 224 | } | |
| 225 | ||
| 226 | fn handleErrors(err: var) noreturn { | |
| 227 | switch (err) { | |
| 228 | error.T => {}, | |
| 229 | } | |
| 230 | ||
| 231 | unreachable; | |
| 232 | } | |
| 233 | ||
| 234 | fn nullLiteral(str: []const u8) !?i64 { | |
| 235 | if (str[0] == 'n') return null; | |
| 236 | ||
| 237 | return error.T; | |
| 238 | } | |
| 239 | ||
| 240 | fn floatLiteral(str: []const u8) !?f64 { | |
| 241 | if (str[0] == 'n') return 1.0; | |
| 242 | ||
| 243 | return error.T; | |
| 244 | } | |
| 245 | ||
| 246 | fn intLiteral(str: []const u8) !?i64 { | |
| 247 | if (str[0] == 'n') return 1; | |
| 248 | ||
| 249 | return error.T; | |
| 250 | } | |
| 251 | ||
| 252 | test "nested error union function call in optional unwrap" { | |
| 253 | const S = struct { | |
| 254 | const Foo = struct { | |
| 255 | a: i32, | |
| 256 | }; | |
| 257 | ||
| 258 | fn errorable() !i32 { | |
| 259 | var x: Foo = (try getFoo()) orelse return error.Other; | |
| 260 | return x.a; | |
| 261 | } | |
| 262 | ||
| 263 | fn errorable2() !i32 { | |
| 264 | var x: Foo = (try getFoo2()) orelse return error.Other; | |
| 265 | return x.a; | |
| 266 | } | |
| 267 | ||
| 268 | fn errorable3() !i32 { | |
| 269 | var x: Foo = (try getFoo3()) orelse return error.Other; | |
| 270 | return x.a; | |
| 271 | } | |
| 272 | ||
| 273 | fn getFoo() anyerror!?Foo { | |
| 274 | return Foo{ .a = 1234 }; | |
| 275 | } | |
| 276 | ||
| 277 | fn getFoo2() anyerror!?Foo { | |
| 278 | return error.Failure; | |
| 279 | } | |
| 280 | ||
| 281 | fn getFoo3() anyerror!?Foo { | |
| 282 | return null; | |
| 283 | } | |
| 284 | }; | |
| 285 | assertOrPanic((try S.errorable()) == 1234); | |
| 286 | assertError(S.errorable2(), error.Failure); | |
| 287 | assertError(S.errorable3(), error.Other); | |
| 288 | comptime { | |
| 289 | assertOrPanic((try S.errorable()) == 1234); | |
| 290 | assertError(S.errorable2(), error.Failure); | |
| 291 | assertError(S.errorable3(), error.Other); | |
| 292 | } | |
| 293 | } | |
| 294 | ||
| 295 | test "widen cast integer payload of error union function call" { | |
| 296 | const S = struct { | |
| 297 | fn errorable() !u64 { | |
| 298 | var x = u64(try number()); | |
| 299 | return x; | |
| 300 | } | |
| 301 | ||
| 302 | fn number() anyerror!u32 { | |
| 303 | return 1234; | |
| 304 | } | |
| 305 | }; | |
| 306 | assertOrPanic((try S.errorable()) == 1234); | |
| 307 | } | |
| 308 | ||
| 309 | test "return function call to error set from error union function" { | |
| 310 | const S = struct { | |
| 311 | fn errorable() anyerror!i32 { | |
| 312 | return fail(); | |
| 313 | } | |
| 314 | ||
| 315 | fn fail() anyerror { | |
| 316 | return error.Failure; | |
| 317 | } | |
| 318 | }; | |
| 319 | assertError(S.errorable(), error.Failure); | |
| 320 | comptime assertError(S.errorable(), error.Failure); | |
| 321 | } | |
| 322 | ||
| 323 | test "optional error set is the same size as error set" { | |
| 324 | comptime assertOrPanic(@sizeOf(?anyerror) == @sizeOf(anyerror)); | |
| 325 | const S = struct { | |
| 326 | fn returnsOptErrSet() ?anyerror { | |
| 327 | return null; | |
| 328 | } | |
| 329 | }; | |
| 330 | assertOrPanic(S.returnsOptErrSet() == null); | |
| 331 | comptime assertOrPanic(S.returnsOptErrSet() == null); | |
| 332 | } |
test/stage1/behavior/eval.zig created+784| ... | ... | @@ -0,0 +1,784 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | ||
| 5 | test "compile time recursion" { | |
| 6 | assertOrPanic(some_data.len == 21); | |
| 7 | } | |
| 8 | var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined; | |
| 9 | fn fibonacci(x: i32) i32 { | |
| 10 | if (x <= 1) return 1; | |
| 11 | return fibonacci(x - 1) + fibonacci(x - 2); | |
| 12 | } | |
| 13 | ||
| 14 | fn unwrapAndAddOne(blah: ?i32) i32 { | |
| 15 | return blah.? + 1; | |
| 16 | } | |
| 17 | const should_be_1235 = unwrapAndAddOne(1234); | |
| 18 | test "static add one" { | |
| 19 | assertOrPanic(should_be_1235 == 1235); | |
| 20 | } | |
| 21 | ||
| 22 | test "inlined loop" { | |
| 23 | comptime var i = 0; | |
| 24 | comptime var sum = 0; | |
| 25 | inline while (i <= 5) : (i += 1) | |
| 26 | sum += i; | |
| 27 | assertOrPanic(sum == 15); | |
| 28 | } | |
| 29 | ||
| 30 | fn gimme1or2(comptime a: bool) i32 { | |
| 31 | const x: i32 = 1; | |
| 32 | const y: i32 = 2; | |
| 33 | comptime var z: i32 = if (a) x else y; | |
| 34 | return z; | |
| 35 | } | |
| 36 | test "inline variable gets result of const if" { | |
| 37 | assertOrPanic(gimme1or2(true) == 1); | |
| 38 | assertOrPanic(gimme1or2(false) == 2); | |
| 39 | } | |
| 40 | ||
| 41 | test "static function evaluation" { | |
| 42 | assertOrPanic(statically_added_number == 3); | |
| 43 | } | |
| 44 | const statically_added_number = staticAdd(1, 2); | |
| 45 | fn staticAdd(a: i32, b: i32) i32 { | |
| 46 | return a + b; | |
| 47 | } | |
| 48 | ||
| 49 | test "const expr eval on single expr blocks" { | |
| 50 | assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3); | |
| 51 | comptime assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3); | |
| 52 | } | |
| 53 | ||
| 54 | fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 { | |
| 55 | const literal = 3; | |
| 56 | ||
| 57 | const result = if (b) b: { | |
| 58 | break :b literal; | |
| 59 | } else b: { | |
| 60 | break :b x; | |
| 61 | }; | |
| 62 | ||
| 63 | return result; | |
| 64 | } | |
| 65 | ||
| 66 | test "statically initialized list" { | |
| 67 | assertOrPanic(static_point_list[0].x == 1); | |
| 68 | assertOrPanic(static_point_list[0].y == 2); | |
| 69 | assertOrPanic(static_point_list[1].x == 3); | |
| 70 | assertOrPanic(static_point_list[1].y == 4); | |
| 71 | } | |
| 72 | const Point = struct { | |
| 73 | x: i32, | |
| 74 | y: i32, | |
| 75 | }; | |
| 76 | const static_point_list = []Point{ | |
| 77 | makePoint(1, 2), | |
| 78 | makePoint(3, 4), | |
| 79 | }; | |
| 80 | fn makePoint(x: i32, y: i32) Point { | |
| 81 | return Point{ | |
| 82 | .x = x, | |
| 83 | .y = y, | |
| 84 | }; | |
| 85 | } | |
| 86 | ||
| 87 | test "static eval list init" { | |
| 88 | assertOrPanic(static_vec3.data[2] == 1.0); | |
| 89 | assertOrPanic(vec3(0.0, 0.0, 3.0).data[2] == 3.0); | |
| 90 | } | |
| 91 | const static_vec3 = vec3(0.0, 0.0, 1.0); | |
| 92 | pub const Vec3 = struct { | |
| 93 | data: [3]f32, | |
| 94 | }; | |
| 95 | pub fn vec3(x: f32, y: f32, z: f32) Vec3 { | |
| 96 | return Vec3{ .data = []f32{ | |
| 97 | x, | |
| 98 | y, | |
| 99 | z, | |
| 100 | } }; | |
| 101 | } | |
| 102 | ||
| 103 | test "constant expressions" { | |
| 104 | var array: [array_size]u8 = undefined; | |
| 105 | assertOrPanic(@sizeOf(@typeOf(array)) == 20); | |
| 106 | } | |
| 107 | const array_size: u8 = 20; | |
| 108 | ||
| 109 | test "constant struct with negation" { | |
| 110 | assertOrPanic(vertices[0].x == -0.6); | |
| 111 | } | |
| 112 | const Vertex = struct { | |
| 113 | x: f32, | |
| 114 | y: f32, | |
| 115 | r: f32, | |
| 116 | g: f32, | |
| 117 | b: f32, | |
| 118 | }; | |
| 119 | const vertices = []Vertex{ | |
| 120 | Vertex{ | |
| 121 | .x = -0.6, | |
| 122 | .y = -0.4, | |
| 123 | .r = 1.0, | |
| 124 | .g = 0.0, | |
| 125 | .b = 0.0, | |
| 126 | }, | |
| 127 | Vertex{ | |
| 128 | .x = 0.6, | |
| 129 | .y = -0.4, | |
| 130 | .r = 0.0, | |
| 131 | .g = 1.0, | |
| 132 | .b = 0.0, | |
| 133 | }, | |
| 134 | Vertex{ | |
| 135 | .x = 0.0, | |
| 136 | .y = 0.6, | |
| 137 | .r = 0.0, | |
| 138 | .g = 0.0, | |
| 139 | .b = 1.0, | |
| 140 | }, | |
| 141 | }; | |
| 142 | ||
| 143 | test "statically initialized struct" { | |
| 144 | st_init_str_foo.x += 1; | |
| 145 | assertOrPanic(st_init_str_foo.x == 14); | |
| 146 | } | |
| 147 | const StInitStrFoo = struct { | |
| 148 | x: i32, | |
| 149 | y: bool, | |
| 150 | }; | |
| 151 | var st_init_str_foo = StInitStrFoo{ | |
| 152 | .x = 13, | |
| 153 | .y = true, | |
| 154 | }; | |
| 155 | ||
| 156 | test "statically initalized array literal" { | |
| 157 | const y: [4]u8 = st_init_arr_lit_x; | |
| 158 | assertOrPanic(y[3] == 4); | |
| 159 | } | |
| 160 | const st_init_arr_lit_x = []u8{ | |
| 161 | 1, | |
| 162 | 2, | |
| 163 | 3, | |
| 164 | 4, | |
| 165 | }; | |
| 166 | ||
| 167 | test "const slice" { | |
| 168 | comptime { | |
| 169 | const a = "1234567890"; | |
| 170 | assertOrPanic(a.len == 10); | |
| 171 | const b = a[1..2]; | |
| 172 | assertOrPanic(b.len == 1); | |
| 173 | assertOrPanic(b[0] == '2'); | |
| 174 | } | |
| 175 | } | |
| 176 | ||
| 177 | test "try to trick eval with runtime if" { | |
| 178 | assertOrPanic(testTryToTrickEvalWithRuntimeIf(true) == 10); | |
| 179 | } | |
| 180 | ||
| 181 | fn testTryToTrickEvalWithRuntimeIf(b: bool) usize { | |
| 182 | comptime var i: usize = 0; | |
| 183 | inline while (i < 10) : (i += 1) { | |
| 184 | const result = if (b) false else true; | |
| 185 | } | |
| 186 | comptime { | |
| 187 | return i; | |
| 188 | } | |
| 189 | } | |
| 190 | ||
| 191 | fn max(comptime T: type, a: T, b: T) T { | |
| 192 | if (T == bool) { | |
| 193 | return a or b; | |
| 194 | } else if (a > b) { | |
| 195 | return a; | |
| 196 | } else { | |
| 197 | return b; | |
| 198 | } | |
| 199 | } | |
| 200 | fn letsTryToCompareBools(a: bool, b: bool) bool { | |
| 201 | return max(bool, a, b); | |
| 202 | } | |
| 203 | test "inlined block and runtime block phi" { | |
| 204 | assertOrPanic(letsTryToCompareBools(true, true)); | |
| 205 | assertOrPanic(letsTryToCompareBools(true, false)); | |
| 206 | assertOrPanic(letsTryToCompareBools(false, true)); | |
| 207 | assertOrPanic(!letsTryToCompareBools(false, false)); | |
| 208 | ||
| 209 | comptime { | |
| 210 | assertOrPanic(letsTryToCompareBools(true, true)); | |
| 211 | assertOrPanic(letsTryToCompareBools(true, false)); | |
| 212 | assertOrPanic(letsTryToCompareBools(false, true)); | |
| 213 | assertOrPanic(!letsTryToCompareBools(false, false)); | |
| 214 | } | |
| 215 | } | |
| 216 | ||
| 217 | const CmdFn = struct { | |
| 218 | name: []const u8, | |
| 219 | func: fn (i32) i32, | |
| 220 | }; | |
| 221 | ||
| 222 | const cmd_fns = []CmdFn{ | |
| 223 | CmdFn{ | |
| 224 | .name = "one", | |
| 225 | .func = one, | |
| 226 | }, | |
| 227 | CmdFn{ | |
| 228 | .name = "two", | |
| 229 | .func = two, | |
| 230 | }, | |
| 231 | CmdFn{ | |
| 232 | .name = "three", | |
| 233 | .func = three, | |
| 234 | }, | |
| 235 | }; | |
| 236 | fn one(value: i32) i32 { | |
| 237 | return value + 1; | |
| 238 | } | |
| 239 | fn two(value: i32) i32 { | |
| 240 | return value + 2; | |
| 241 | } | |
| 242 | fn three(value: i32) i32 { | |
| 243 | return value + 3; | |
| 244 | } | |
| 245 | ||
| 246 | fn performFn(comptime prefix_char: u8, start_value: i32) i32 { | |
| 247 | var result: i32 = start_value; | |
| 248 | comptime var i = 0; | |
| 249 | inline while (i < cmd_fns.len) : (i += 1) { | |
| 250 | if (cmd_fns[i].name[0] == prefix_char) { | |
| 251 | result = cmd_fns[i].func(result); | |
| 252 | } | |
| 253 | } | |
| 254 | return result; | |
| 255 | } | |
| 256 | ||
| 257 | test "comptime iterate over fn ptr list" { | |
| 258 | assertOrPanic(performFn('t', 1) == 6); | |
| 259 | assertOrPanic(performFn('o', 0) == 1); | |
| 260 | assertOrPanic(performFn('w', 99) == 99); | |
| 261 | } | |
| 262 | ||
| 263 | test "eval @setRuntimeSafety at compile-time" { | |
| 264 | const result = comptime fnWithSetRuntimeSafety(); | |
| 265 | assertOrPanic(result == 1234); | |
| 266 | } | |
| 267 | ||
| 268 | fn fnWithSetRuntimeSafety() i32 { | |
| 269 | @setRuntimeSafety(true); | |
| 270 | return 1234; | |
| 271 | } | |
| 272 | ||
| 273 | test "eval @setFloatMode at compile-time" { | |
| 274 | const result = comptime fnWithFloatMode(); | |
| 275 | assertOrPanic(result == 1234.0); | |
| 276 | } | |
| 277 | ||
| 278 | fn fnWithFloatMode() f32 { | |
| 279 | @setFloatMode(builtin.FloatMode.Strict); | |
| 280 | return 1234.0; | |
| 281 | } | |
| 282 | ||
| 283 | const SimpleStruct = struct { | |
| 284 | field: i32, | |
| 285 | ||
| 286 | fn method(self: *const SimpleStruct) i32 { | |
| 287 | return self.field + 3; | |
| 288 | } | |
| 289 | }; | |
| 290 | ||
| 291 | var simple_struct = SimpleStruct{ .field = 1234 }; | |
| 292 | ||
| 293 | const bound_fn = simple_struct.method; | |
| 294 | ||
| 295 | test "call method on bound fn referring to var instance" { | |
| 296 | assertOrPanic(bound_fn() == 1237); | |
| 297 | } | |
| 298 | ||
| 299 | test "ptr to local array argument at comptime" { | |
| 300 | comptime { | |
| 301 | var bytes: [10]u8 = undefined; | |
| 302 | modifySomeBytes(bytes[0..]); | |
| 303 | assertOrPanic(bytes[0] == 'a'); | |
| 304 | assertOrPanic(bytes[9] == 'b'); | |
| 305 | } | |
| 306 | } | |
| 307 | ||
| 308 | fn modifySomeBytes(bytes: []u8) void { | |
| 309 | bytes[0] = 'a'; | |
| 310 | bytes[9] = 'b'; | |
| 311 | } | |
| 312 | ||
| 313 | test "comparisons 0 <= uint and 0 > uint should be comptime" { | |
| 314 | testCompTimeUIntComparisons(1234); | |
| 315 | } | |
| 316 | fn testCompTimeUIntComparisons(x: u32) void { | |
| 317 | if (!(0 <= x)) { | |
| 318 | @compileError("this condition should be comptime known"); | |
| 319 | } | |
| 320 | if (0 > x) { | |
| 321 | @compileError("this condition should be comptime known"); | |
| 322 | } | |
| 323 | if (!(x >= 0)) { | |
| 324 | @compileError("this condition should be comptime known"); | |
| 325 | } | |
| 326 | if (x < 0) { | |
| 327 | @compileError("this condition should be comptime known"); | |
| 328 | } | |
| 329 | } | |
| 330 | ||
| 331 | test "const ptr to variable data changes at runtime" { | |
| 332 | assertOrPanic(foo_ref.name[0] == 'a'); | |
| 333 | foo_ref.name = "b"; | |
| 334 | assertOrPanic(foo_ref.name[0] == 'b'); | |
| 335 | } | |
| 336 | ||
| 337 | const Foo = struct { | |
| 338 | name: []const u8, | |
| 339 | }; | |
| 340 | ||
| 341 | var foo_contents = Foo{ .name = "a" }; | |
| 342 | const foo_ref = &foo_contents; | |
| 343 | ||
| 344 | test "create global array with for loop" { | |
| 345 | assertOrPanic(global_array[5] == 5 * 5); | |
| 346 | assertOrPanic(global_array[9] == 9 * 9); | |
| 347 | } | |
| 348 | ||
| 349 | const global_array = x: { | |
| 350 | var result: [10]usize = undefined; | |
| 351 | for (result) |*item, index| { | |
| 352 | item.* = index * index; | |
| 353 | } | |
| 354 | break :x result; | |
| 355 | }; | |
| 356 | ||
| 357 | test "compile-time downcast when the bits fit" { | |
| 358 | comptime { | |
| 359 | const spartan_count: u16 = 255; | |
| 360 | const byte = @intCast(u8, spartan_count); | |
| 361 | assertOrPanic(byte == 255); | |
| 362 | } | |
| 363 | } | |
| 364 | ||
| 365 | const hi1 = "hi"; | |
| 366 | const hi2 = hi1; | |
| 367 | test "const global shares pointer with other same one" { | |
| 368 | assertEqualPtrs(&hi1[0], &hi2[0]); | |
| 369 | comptime assertOrPanic(&hi1[0] == &hi2[0]); | |
| 370 | } | |
| 371 | fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void { | |
| 372 | assertOrPanic(ptr1 == ptr2); | |
| 373 | } | |
| 374 | ||
| 375 | test "@setEvalBranchQuota" { | |
| 376 | comptime { | |
| 377 | // 1001 for the loop and then 1 more for the assertOrPanic fn call | |
| 378 | @setEvalBranchQuota(1002); | |
| 379 | var i = 0; | |
| 380 | var sum = 0; | |
| 381 | while (i < 1001) : (i += 1) { | |
| 382 | sum += i; | |
| 383 | } | |
| 384 | assertOrPanic(sum == 500500); | |
| 385 | } | |
| 386 | } | |
| 387 | ||
| 388 | // TODO test "float literal at compile time not lossy" { | |
| 389 | // TODO assertOrPanic(16777216.0 + 1.0 == 16777217.0); | |
| 390 | // TODO assertOrPanic(9007199254740992.0 + 1.0 == 9007199254740993.0); | |
| 391 | // TODO } | |
| 392 | ||
| 393 | test "f32 at compile time is lossy" { | |
| 394 | assertOrPanic(f32(1 << 24) + 1 == 1 << 24); | |
| 395 | } | |
| 396 | ||
| 397 | test "f64 at compile time is lossy" { | |
| 398 | assertOrPanic(f64(1 << 53) + 1 == 1 << 53); | |
| 399 | } | |
| 400 | ||
| 401 | test "f128 at compile time is lossy" { | |
| 402 | assertOrPanic(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); | |
| 403 | } | |
| 404 | ||
| 405 | comptime { | |
| 406 | assertOrPanic(f128(1 << 113) == 10384593717069655257060992658440192); | |
| 407 | } | |
| 408 | ||
| 409 | pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { | |
| 410 | return struct { | |
| 411 | pub const Node = struct {}; | |
| 412 | }; | |
| 413 | } | |
| 414 | ||
| 415 | test "string literal used as comptime slice is memoized" { | |
| 416 | const a = "link"; | |
| 417 | const b = "link"; | |
| 418 | comptime assertOrPanic(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node); | |
| 419 | comptime assertOrPanic(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node); | |
| 420 | } | |
| 421 | ||
| 422 | test "comptime slice of undefined pointer of length 0" { | |
| 423 | const slice1 = ([*]i32)(undefined)[0..0]; | |
| 424 | assertOrPanic(slice1.len == 0); | |
| 425 | const slice2 = ([*]i32)(undefined)[100..100]; | |
| 426 | assertOrPanic(slice2.len == 0); | |
| 427 | } | |
| 428 | ||
| 429 | fn copyWithPartialInline(s: []u32, b: []u8) void { | |
| 430 | comptime var i: usize = 0; | |
| 431 | inline while (i < 4) : (i += 1) { | |
| 432 | s[i] = 0; | |
| 433 | s[i] |= u32(b[i * 4 + 0]) << 24; | |
| 434 | s[i] |= u32(b[i * 4 + 1]) << 16; | |
| 435 | s[i] |= u32(b[i * 4 + 2]) << 8; | |
| 436 | s[i] |= u32(b[i * 4 + 3]) << 0; | |
| 437 | } | |
| 438 | } | |
| 439 | ||
| 440 | test "binary math operator in partially inlined function" { | |
| 441 | var s: [4]u32 = undefined; | |
| 442 | var b: [16]u8 = undefined; | |
| 443 | ||
| 444 | for (b) |*r, i| | |
| 445 | r.* = @intCast(u8, i + 1); | |
| 446 | ||
| 447 | copyWithPartialInline(s[0..], b[0..]); | |
| 448 | assertOrPanic(s[0] == 0x1020304); | |
| 449 | assertOrPanic(s[1] == 0x5060708); | |
| 450 | assertOrPanic(s[2] == 0x90a0b0c); | |
| 451 | assertOrPanic(s[3] == 0xd0e0f10); | |
| 452 | } | |
| 453 | ||
| 454 | test "comptime function with the same args is memoized" { | |
| 455 | comptime { | |
| 456 | assertOrPanic(MakeType(i32) == MakeType(i32)); | |
| 457 | assertOrPanic(MakeType(i32) != MakeType(f64)); | |
| 458 | } | |
| 459 | } | |
| 460 | ||
| 461 | fn MakeType(comptime T: type) type { | |
| 462 | return struct { | |
| 463 | field: T, | |
| 464 | }; | |
| 465 | } | |
| 466 | ||
| 467 | test "comptime function with mutable pointer is not memoized" { | |
| 468 | comptime { | |
| 469 | var x: i32 = 1; | |
| 470 | const ptr = &x; | |
| 471 | increment(ptr); | |
| 472 | increment(ptr); | |
| 473 | assertOrPanic(x == 3); | |
| 474 | } | |
| 475 | } | |
| 476 | ||
| 477 | fn increment(value: *i32) void { | |
| 478 | value.* += 1; | |
| 479 | } | |
| 480 | ||
| 481 | fn generateTable(comptime T: type) [1010]T { | |
| 482 | var res: [1010]T = undefined; | |
| 483 | var i: usize = 0; | |
| 484 | while (i < 1010) : (i += 1) { | |
| 485 | res[i] = @intCast(T, i); | |
| 486 | } | |
| 487 | return res; | |
| 488 | } | |
| 489 | ||
| 490 | fn doesAlotT(comptime T: type, value: usize) T { | |
| 491 | @setEvalBranchQuota(5000); | |
| 492 | const table = comptime blk: { | |
| 493 | break :blk generateTable(T); | |
| 494 | }; | |
| 495 | return table[value]; | |
| 496 | } | |
| 497 | ||
| 498 | test "@setEvalBranchQuota at same scope as generic function call" { | |
| 499 | assertOrPanic(doesAlotT(u32, 2) == 2); | |
| 500 | } | |
| 501 | ||
| 502 | test "comptime slice of slice preserves comptime var" { | |
| 503 | comptime { | |
| 504 | var buff: [10]u8 = undefined; | |
| 505 | buff[0..][0..][0] = 1; | |
| 506 | assertOrPanic(buff[0..][0..][0] == 1); | |
| 507 | } | |
| 508 | } | |
| 509 | ||
| 510 | test "comptime slice of pointer preserves comptime var" { | |
| 511 | comptime { | |
| 512 | var buff: [10]u8 = undefined; | |
| 513 | var a = buff[0..].ptr; | |
| 514 | a[0..1][0] = 1; | |
| 515 | assertOrPanic(buff[0..][0..][0] == 1); | |
| 516 | } | |
| 517 | } | |
| 518 | ||
| 519 | const SingleFieldStruct = struct { | |
| 520 | x: i32, | |
| 521 | ||
| 522 | fn read_x(self: *const SingleFieldStruct) i32 { | |
| 523 | return self.x; | |
| 524 | } | |
| 525 | }; | |
| 526 | test "const ptr to comptime mutable data is not memoized" { | |
| 527 | comptime { | |
| 528 | var foo = SingleFieldStruct{ .x = 1 }; | |
| 529 | assertOrPanic(foo.read_x() == 1); | |
| 530 | foo.x = 2; | |
| 531 | assertOrPanic(foo.read_x() == 2); | |
| 532 | } | |
| 533 | } | |
| 534 | ||
| 535 | test "array concat of slices gives slice" { | |
| 536 | comptime { | |
| 537 | var a: []const u8 = "aoeu"; | |
| 538 | var b: []const u8 = "asdf"; | |
| 539 | const c = a ++ b; | |
| 540 | assertOrPanic(std.mem.eql(u8, c, "aoeuasdf")); | |
| 541 | } | |
| 542 | } | |
| 543 | ||
| 544 | test "comptime shlWithOverflow" { | |
| 545 | const ct_shifted: u64 = comptime amt: { | |
| 546 | var amt = u64(0); | |
| 547 | _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); | |
| 548 | break :amt amt; | |
| 549 | }; | |
| 550 | ||
| 551 | const rt_shifted: u64 = amt: { | |
| 552 | var amt = u64(0); | |
| 553 | _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); | |
| 554 | break :amt amt; | |
| 555 | }; | |
| 556 | ||
| 557 | assertOrPanic(ct_shifted == rt_shifted); | |
| 558 | } | |
| 559 | ||
| 560 | test "runtime 128 bit integer division" { | |
| 561 | var a: u128 = 152313999999999991610955792383; | |
| 562 | var b: u128 = 10000000000000000000; | |
| 563 | var c = a / b; | |
| 564 | assertOrPanic(c == 15231399999); | |
| 565 | } | |
| 566 | ||
| 567 | pub const Info = struct { | |
| 568 | version: u8, | |
| 569 | }; | |
| 570 | ||
| 571 | pub const diamond_info = Info{ .version = 0 }; | |
| 572 | ||
| 573 | test "comptime modification of const struct field" { | |
| 574 | comptime { | |
| 575 | var res = diamond_info; | |
| 576 | res.version = 1; | |
| 577 | assertOrPanic(diamond_info.version == 0); | |
| 578 | assertOrPanic(res.version == 1); | |
| 579 | } | |
| 580 | } | |
| 581 | ||
| 582 | test "pointer to type" { | |
| 583 | comptime { | |
| 584 | var T: type = i32; | |
| 585 | assertOrPanic(T == i32); | |
| 586 | var ptr = &T; | |
| 587 | assertOrPanic(@typeOf(ptr) == *type); | |
| 588 | ptr.* = f32; | |
| 589 | assertOrPanic(T == f32); | |
| 590 | assertOrPanic(*T == *f32); | |
| 591 | } | |
| 592 | } | |
| 593 | ||
| 594 | test "slice of type" { | |
| 595 | comptime { | |
| 596 | var types_array = []type{ i32, f64, type }; | |
| 597 | for (types_array) |T, i| { | |
| 598 | switch (i) { | |
| 599 | 0 => assertOrPanic(T == i32), | |
| 600 | 1 => assertOrPanic(T == f64), | |
| 601 | 2 => assertOrPanic(T == type), | |
| 602 | else => unreachable, | |
| 603 | } | |
| 604 | } | |
| 605 | for (types_array[0..]) |T, i| { | |
| 606 | switch (i) { | |
| 607 | 0 => assertOrPanic(T == i32), | |
| 608 | 1 => assertOrPanic(T == f64), | |
| 609 | 2 => assertOrPanic(T == type), | |
| 610 | else => unreachable, | |
| 611 | } | |
| 612 | } | |
| 613 | } | |
| 614 | } | |
| 615 | ||
| 616 | const Wrapper = struct { | |
| 617 | T: type, | |
| 618 | }; | |
| 619 | ||
| 620 | fn wrap(comptime T: type) Wrapper { | |
| 621 | return Wrapper{ .T = T }; | |
| 622 | } | |
| 623 | ||
| 624 | test "function which returns struct with type field causes implicit comptime" { | |
| 625 | const ty = wrap(i32).T; | |
| 626 | assertOrPanic(ty == i32); | |
| 627 | } | |
| 628 | ||
| 629 | test "call method with comptime pass-by-non-copying-value self parameter" { | |
| 630 | const S = struct { | |
| 631 | a: u8, | |
| 632 | ||
| 633 | fn b(comptime s: @This()) u8 { | |
| 634 | return s.a; | |
| 635 | } | |
| 636 | }; | |
| 637 | ||
| 638 | const s = S{ .a = 2 }; | |
| 639 | var b = s.b(); | |
| 640 | assertOrPanic(b == 2); | |
| 641 | } | |
| 642 | ||
| 643 | test "@tagName of @typeId" { | |
| 644 | const str = @tagName(@typeId(u8)); | |
| 645 | assertOrPanic(std.mem.eql(u8, str, "Int")); | |
| 646 | } | |
| 647 | ||
| 648 | test "setting backward branch quota just before a generic fn call" { | |
| 649 | @setEvalBranchQuota(1001); | |
| 650 | loopNTimes(1001); | |
| 651 | } | |
| 652 | ||
| 653 | fn loopNTimes(comptime n: usize) void { | |
| 654 | comptime var i = 0; | |
| 655 | inline while (i < n) : (i += 1) {} | |
| 656 | } | |
| 657 | ||
| 658 | test "variable inside inline loop that has different types on different iterations" { | |
| 659 | testVarInsideInlineLoop(true, u32(42)); | |
| 660 | } | |
| 661 | ||
| 662 | fn testVarInsideInlineLoop(args: ...) void { | |
| 663 | comptime var i = 0; | |
| 664 | inline while (i < args.len) : (i += 1) { | |
| 665 | const x = args[i]; | |
| 666 | if (i == 0) assertOrPanic(x); | |
| 667 | if (i == 1) assertOrPanic(x == 42); | |
| 668 | } | |
| 669 | } | |
| 670 | ||
| 671 | test "inline for with same type but different values" { | |
| 672 | var res: usize = 0; | |
| 673 | inline for ([]type{ [2]u8, [1]u8, [2]u8 }) |T| { | |
| 674 | var a: T = undefined; | |
| 675 | res += a.len; | |
| 676 | } | |
| 677 | assertOrPanic(res == 5); | |
| 678 | } | |
| 679 | ||
| 680 | test "refer to the type of a generic function" { | |
| 681 | const Func = fn (type) void; | |
| 682 | const f: Func = doNothingWithType; | |
| 683 | f(i32); | |
| 684 | } | |
| 685 | ||
| 686 | fn doNothingWithType(comptime T: type) void {} | |
| 687 | ||
| 688 | test "zero extend from u0 to u1" { | |
| 689 | var zero_u0: u0 = 0; | |
| 690 | var zero_u1: u1 = zero_u0; | |
| 691 | assertOrPanic(zero_u1 == 0); | |
| 692 | } | |
| 693 | ||
| 694 | test "bit shift a u1" { | |
| 695 | var x: u1 = 1; | |
| 696 | var y = x << 0; | |
| 697 | assertOrPanic(y == 1); | |
| 698 | } | |
| 699 | ||
| 700 | test "@intCast to a u0" { | |
| 701 | var x: u8 = 0; | |
| 702 | var y: u0 = @intCast(u0, x); | |
| 703 | assertOrPanic(y == 0); | |
| 704 | } | |
| 705 | ||
| 706 | test "@bytesToslice on a packed struct" { | |
| 707 | const F = packed struct { | |
| 708 | a: u8, | |
| 709 | }; | |
| 710 | ||
| 711 | var b = [1]u8{9}; | |
| 712 | var f = @bytesToSlice(F, b); | |
| 713 | assertOrPanic(f[0].a == 9); | |
| 714 | } | |
| 715 | ||
| 716 | test "comptime pointer cast array and then slice" { | |
| 717 | const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; | |
| 718 | ||
| 719 | const ptrA: [*]const u8 = @ptrCast([*]const u8, &array); | |
| 720 | const sliceA: []const u8 = ptrA[0..2]; | |
| 721 | ||
| 722 | const ptrB: [*]const u8 = &array; | |
| 723 | const sliceB: []const u8 = ptrB[0..2]; | |
| 724 | ||
| 725 | assertOrPanic(sliceA[1] == 2); | |
| 726 | assertOrPanic(sliceB[1] == 2); | |
| 727 | } | |
| 728 | ||
| 729 | test "slice bounds in comptime concatenation" { | |
| 730 | const bs = comptime blk: { | |
| 731 | const b = c"11"; | |
| 732 | break :blk b[0..1]; | |
| 733 | }; | |
| 734 | const str = "" ++ bs; | |
| 735 | assertOrPanic(str.len == 1); | |
| 736 | assertOrPanic(std.mem.eql(u8, str, "1")); | |
| 737 | ||
| 738 | const str2 = bs ++ ""; | |
| 739 | assertOrPanic(str2.len == 1); | |
| 740 | assertOrPanic(std.mem.eql(u8, str2, "1")); | |
| 741 | } | |
| 742 | ||
| 743 | test "comptime bitwise operators" { | |
| 744 | comptime { | |
| 745 | assertOrPanic(3 & 1 == 1); | |
| 746 | assertOrPanic(3 & -1 == 3); | |
| 747 | assertOrPanic(-3 & -1 == -3); | |
| 748 | assertOrPanic(3 | -1 == -1); | |
| 749 | assertOrPanic(-3 | -1 == -1); | |
| 750 | assertOrPanic(3 ^ -1 == -4); | |
| 751 | assertOrPanic(-3 ^ -1 == 2); | |
| 752 | assertOrPanic(~i8(-1) == 0); | |
| 753 | assertOrPanic(~i128(-1) == 0); | |
| 754 | assertOrPanic(18446744073709551615 & 18446744073709551611 == 18446744073709551611); | |
| 755 | assertOrPanic(-18446744073709551615 & -18446744073709551611 == -18446744073709551615); | |
| 756 | assertOrPanic(~u128(0) == 0xffffffffffffffffffffffffffffffff); | |
| 757 | } | |
| 758 | } | |
| 759 | ||
| 760 | test "*align(1) u16 is the same as *align(1:0:2) u16" { | |
| 761 | comptime { | |
| 762 | assertOrPanic(*align(1:0:2) u16 == *align(1) u16); | |
| 763 | // TODO add parsing support for this syntax | |
| 764 | //assertOrPanic(*align(:0:2) u16 == *u16); | |
| 765 | } | |
| 766 | } | |
| 767 | ||
| 768 | test "array concatenation forces comptime" { | |
| 769 | var a = oneItem(3) ++ oneItem(4); | |
| 770 | assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 4 })); | |
| 771 | } | |
| 772 | ||
| 773 | test "array multiplication forces comptime" { | |
| 774 | var a = oneItem(3) ** scalar(2); | |
| 775 | assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 3 })); | |
| 776 | } | |
| 777 | ||
| 778 | fn oneItem(x: i32) [1]i32 { | |
| 779 | return []i32{x}; | |
| 780 | } | |
| 781 | ||
| 782 | fn scalar(x: u32) u32 { | |
| 783 | return x; | |
| 784 | } |
test/stage1/behavior/field_parent_ptr.zig created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "@fieldParentPtr non-first field" { | |
| 4 | testParentFieldPtr(&foo.c); | |
| 5 | comptime testParentFieldPtr(&foo.c); | |
| 6 | } | |
| 7 | ||
| 8 | test "@fieldParentPtr first field" { | |
| 9 | testParentFieldPtrFirst(&foo.a); | |
| 10 | comptime testParentFieldPtrFirst(&foo.a); | |
| 11 | } | |
| 12 | ||
| 13 | const Foo = struct { | |
| 14 | a: bool, | |
| 15 | b: f32, | |
| 16 | c: i32, | |
| 17 | d: i32, | |
| 18 | }; | |
| 19 | ||
| 20 | const foo = Foo{ | |
| 21 | .a = true, | |
| 22 | .b = 0.123, | |
| 23 | .c = 1234, | |
| 24 | .d = -10, | |
| 25 | }; | |
| 26 | ||
| 27 | fn testParentFieldPtr(c: *const i32) void { | |
| 28 | assertOrPanic(c == &foo.c); | |
| 29 | ||
| 30 | const base = @fieldParentPtr(Foo, "c", c); | |
| 31 | assertOrPanic(base == &foo); | |
| 32 | assertOrPanic(&base.c == c); | |
| 33 | } | |
| 34 | ||
| 35 | fn testParentFieldPtrFirst(a: *const bool) void { | |
| 36 | assertOrPanic(a == &foo.a); | |
| 37 | ||
| 38 | const base = @fieldParentPtr(Foo, "a", a); | |
| 39 | assertOrPanic(base == &foo); | |
| 40 | assertOrPanic(&base.a == a); | |
| 41 | } |
test/stage1/behavior/fn.zig created+208| ... | ... | @@ -0,0 +1,208 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "params" { | |
| 4 | assertOrPanic(testParamsAdd(22, 11) == 33); | |
| 5 | } | |
| 6 | fn testParamsAdd(a: i32, b: i32) i32 { | |
| 7 | return a + b; | |
| 8 | } | |
| 9 | ||
| 10 | test "local variables" { | |
| 11 | testLocVars(2); | |
| 12 | } | |
| 13 | fn testLocVars(b: i32) void { | |
| 14 | const a: i32 = 1; | |
| 15 | if (a + b != 3) unreachable; | |
| 16 | } | |
| 17 | ||
| 18 | test "void parameters" { | |
| 19 | voidFun(1, void{}, 2, {}); | |
| 20 | } | |
| 21 | fn voidFun(a: i32, b: void, c: i32, d: void) void { | |
| 22 | const v = b; | |
| 23 | const vv: void = if (a == 1) v else {}; | |
| 24 | assertOrPanic(a + c == 3); | |
| 25 | return vv; | |
| 26 | } | |
| 27 | ||
| 28 | test "mutable local variables" { | |
| 29 | var zero: i32 = 0; | |
| 30 | assertOrPanic(zero == 0); | |
| 31 | ||
| 32 | var i = i32(0); | |
| 33 | while (i != 3) { | |
| 34 | i += 1; | |
| 35 | } | |
| 36 | assertOrPanic(i == 3); | |
| 37 | } | |
| 38 | ||
| 39 | test "separate block scopes" { | |
| 40 | { | |
| 41 | const no_conflict: i32 = 5; | |
| 42 | assertOrPanic(no_conflict == 5); | |
| 43 | } | |
| 44 | ||
| 45 | const c = x: { | |
| 46 | const no_conflict = i32(10); | |
| 47 | break :x no_conflict; | |
| 48 | }; | |
| 49 | assertOrPanic(c == 10); | |
| 50 | } | |
| 51 | ||
| 52 | test "call function with empty string" { | |
| 53 | acceptsString(""); | |
| 54 | } | |
| 55 | ||
| 56 | fn acceptsString(foo: []u8) void {} | |
| 57 | ||
| 58 | fn @"weird function name"() i32 { | |
| 59 | return 1234; | |
| 60 | } | |
| 61 | test "weird function name" { | |
| 62 | assertOrPanic(@"weird function name"() == 1234); | |
| 63 | } | |
| 64 | ||
| 65 | test "implicit cast function unreachable return" { | |
| 66 | wantsFnWithVoid(fnWithUnreachable); | |
| 67 | } | |
| 68 | ||
| 69 | fn wantsFnWithVoid(f: fn () void) void {} | |
| 70 | ||
| 71 | fn fnWithUnreachable() noreturn { | |
| 72 | unreachable; | |
| 73 | } | |
| 74 | ||
| 75 | test "function pointers" { | |
| 76 | const fns = []@typeOf(fn1){ | |
| 77 | fn1, | |
| 78 | fn2, | |
| 79 | fn3, | |
| 80 | fn4, | |
| 81 | }; | |
| 82 | for (fns) |f, i| { | |
| 83 | assertOrPanic(f() == @intCast(u32, i) + 5); | |
| 84 | } | |
| 85 | } | |
| 86 | fn fn1() u32 { | |
| 87 | return 5; | |
| 88 | } | |
| 89 | fn fn2() u32 { | |
| 90 | return 6; | |
| 91 | } | |
| 92 | fn fn3() u32 { | |
| 93 | return 7; | |
| 94 | } | |
| 95 | fn fn4() u32 { | |
| 96 | return 8; | |
| 97 | } | |
| 98 | ||
| 99 | test "inline function call" { | |
| 100 | assertOrPanic(@inlineCall(add, 3, 9) == 12); | |
| 101 | } | |
| 102 | ||
| 103 | fn add(a: i32, b: i32) i32 { | |
| 104 | return a + b; | |
| 105 | } | |
| 106 | ||
| 107 | test "number literal as an argument" { | |
| 108 | numberLiteralArg(3); | |
| 109 | comptime numberLiteralArg(3); | |
| 110 | } | |
| 111 | ||
| 112 | fn numberLiteralArg(a: var) void { | |
| 113 | assertOrPanic(a == 3); | |
| 114 | } | |
| 115 | ||
| 116 | test "assign inline fn to const variable" { | |
| 117 | const a = inlineFn; | |
| 118 | a(); | |
| 119 | } | |
| 120 | ||
| 121 | inline fn inlineFn() void {} | |
| 122 | ||
| 123 | test "pass by non-copying value" { | |
| 124 | assertOrPanic(addPointCoords(Point{ .x = 1, .y = 2 }) == 3); | |
| 125 | } | |
| 126 | ||
| 127 | const Point = struct { | |
| 128 | x: i32, | |
| 129 | y: i32, | |
| 130 | }; | |
| 131 | ||
| 132 | fn addPointCoords(pt: Point) i32 { | |
| 133 | return pt.x + pt.y; | |
| 134 | } | |
| 135 | ||
| 136 | test "pass by non-copying value through var arg" { | |
| 137 | assertOrPanic(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3); | |
| 138 | } | |
| 139 | ||
| 140 | fn addPointCoordsVar(pt: var) i32 { | |
| 141 | comptime assertOrPanic(@typeOf(pt) == Point); | |
| 142 | return pt.x + pt.y; | |
| 143 | } | |
| 144 | ||
| 145 | test "pass by non-copying value as method" { | |
| 146 | var pt = Point2{ .x = 1, .y = 2 }; | |
| 147 | assertOrPanic(pt.addPointCoords() == 3); | |
| 148 | } | |
| 149 | ||
| 150 | const Point2 = struct { | |
| 151 | x: i32, | |
| 152 | y: i32, | |
| 153 | ||
| 154 | fn addPointCoords(self: Point2) i32 { | |
| 155 | return self.x + self.y; | |
| 156 | } | |
| 157 | }; | |
| 158 | ||
| 159 | test "pass by non-copying value as method, which is generic" { | |
| 160 | var pt = Point3{ .x = 1, .y = 2 }; | |
| 161 | assertOrPanic(pt.addPointCoords(i32) == 3); | |
| 162 | } | |
| 163 | ||
| 164 | const Point3 = struct { | |
| 165 | x: i32, | |
| 166 | y: i32, | |
| 167 | ||
| 168 | fn addPointCoords(self: Point3, comptime T: type) i32 { | |
| 169 | return self.x + self.y; | |
| 170 | } | |
| 171 | }; | |
| 172 | ||
| 173 | test "pass by non-copying value as method, at comptime" { | |
| 174 | comptime { | |
| 175 | var pt = Point2{ .x = 1, .y = 2 }; | |
| 176 | assertOrPanic(pt.addPointCoords() == 3); | |
| 177 | } | |
| 178 | } | |
| 179 | ||
| 180 | fn outer(y: u32) fn (u32) u32 { | |
| 181 | const Y = @typeOf(y); | |
| 182 | const st = struct { | |
| 183 | fn get(z: u32) u32 { | |
| 184 | return z + @sizeOf(Y); | |
| 185 | } | |
| 186 | }; | |
| 187 | return st.get; | |
| 188 | } | |
| 189 | ||
| 190 | test "return inner function which references comptime variable of outer function" { | |
| 191 | var func = outer(10); | |
| 192 | assertOrPanic(func(3) == 7); | |
| 193 | } | |
| 194 | ||
| 195 | test "extern struct with stdcallcc fn pointer" { | |
| 196 | const S = extern struct { | |
| 197 | ptr: stdcallcc fn () i32, | |
| 198 | ||
| 199 | stdcallcc fn foo() i32 { | |
| 200 | return 1234; | |
| 201 | } | |
| 202 | }; | |
| 203 | ||
| 204 | var s: S = undefined; | |
| 205 | s.ptr = S.foo; | |
| 206 | assertOrPanic(s.ptr() == 1234); | |
| 207 | } | |
| 208 |
test/stage1/behavior/fn_in_struct_in_comptime.zig created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | fn get_foo() fn (*u8) usize { | |
| 4 | comptime { | |
| 5 | return struct { | |
| 6 | fn func(ptr: *u8) usize { | |
| 7 | var u = @ptrToInt(ptr); | |
| 8 | return u; | |
| 9 | } | |
| 10 | }.func; | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | test "define a function in an anonymous struct in comptime" { | |
| 15 | const foo = get_foo(); | |
| 16 | assertOrPanic(foo(@intToPtr(*u8, 12345)) == 12345); | |
| 17 | } |
test/stage1/behavior/for.zig created+106| ... | ... | @@ -0,0 +1,106 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const mem = std.mem; | |
| 4 | ||
| 5 | test "continue in for loop" { | |
| 6 | const array = []i32{ | |
| 7 | 1, | |
| 8 | 2, | |
| 9 | 3, | |
| 10 | 4, | |
| 11 | 5, | |
| 12 | }; | |
| 13 | var sum: i32 = 0; | |
| 14 | for (array) |x| { | |
| 15 | sum += x; | |
| 16 | if (x < 3) { | |
| 17 | continue; | |
| 18 | } | |
| 19 | break; | |
| 20 | } | |
| 21 | if (sum != 6) unreachable; | |
| 22 | } | |
| 23 | ||
| 24 | test "for loop with pointer elem var" { | |
| 25 | const source = "abcdefg"; | |
| 26 | var target: [source.len]u8 = undefined; | |
| 27 | mem.copy(u8, target[0..], source); | |
| 28 | mangleString(target[0..]); | |
| 29 | assertOrPanic(mem.eql(u8, target, "bcdefgh")); | |
| 30 | } | |
| 31 | fn mangleString(s: []u8) void { | |
| 32 | for (s) |*c| { | |
| 33 | c.* += 1; | |
| 34 | } | |
| 35 | } | |
| 36 | ||
| 37 | test "basic for loop" { | |
| 38 | const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3; | |
| 39 | ||
| 40 | var buffer: [expected_result.len]u8 = undefined; | |
| 41 | var buf_index: usize = 0; | |
| 42 | ||
| 43 | const array = []u8{ 9, 8, 7, 6 }; | |
| 44 | for (array) |item| { | |
| 45 | buffer[buf_index] = item; | |
| 46 | buf_index += 1; | |
| 47 | } | |
| 48 | for (array) |item, index| { | |
| 49 | buffer[buf_index] = @intCast(u8, index); | |
| 50 | buf_index += 1; | |
| 51 | } | |
| 52 | const array_ptr = &array; | |
| 53 | for (array_ptr) |item| { | |
| 54 | buffer[buf_index] = item; | |
| 55 | buf_index += 1; | |
| 56 | } | |
| 57 | for (array_ptr) |item, index| { | |
| 58 | buffer[buf_index] = @intCast(u8, index); | |
| 59 | buf_index += 1; | |
| 60 | } | |
| 61 | const unknown_size: []const u8 = array; | |
| 62 | for (unknown_size) |item| { | |
| 63 | buffer[buf_index] = item; | |
| 64 | buf_index += 1; | |
| 65 | } | |
| 66 | for (unknown_size) |item, index| { | |
| 67 | buffer[buf_index] = @intCast(u8, index); | |
| 68 | buf_index += 1; | |
| 69 | } | |
| 70 | ||
| 71 | assertOrPanic(mem.eql(u8, buffer[0..buf_index], expected_result)); | |
| 72 | } | |
| 73 | ||
| 74 | test "break from outer for loop" { | |
| 75 | testBreakOuter(); | |
| 76 | comptime testBreakOuter(); | |
| 77 | } | |
| 78 | ||
| 79 | fn testBreakOuter() void { | |
| 80 | var array = "aoeu"; | |
| 81 | var count: usize = 0; | |
| 82 | outer: for (array) |_| { | |
| 83 | for (array) |_| { | |
| 84 | count += 1; | |
| 85 | break :outer; | |
| 86 | } | |
| 87 | } | |
| 88 | assertOrPanic(count == 1); | |
| 89 | } | |
| 90 | ||
| 91 | test "continue outer for loop" { | |
| 92 | testContinueOuter(); | |
| 93 | comptime testContinueOuter(); | |
| 94 | } | |
| 95 | ||
| 96 | fn testContinueOuter() void { | |
| 97 | var array = "aoeu"; | |
| 98 | var counter: usize = 0; | |
| 99 | outer: for (array) |_| { | |
| 100 | for (array) |_| { | |
| 101 | counter += 1; | |
| 102 | continue :outer; | |
| 103 | } | |
| 104 | } | |
| 105 | assertOrPanic(counter == array.len); | |
| 106 | } |
test/stage1/behavior/generics.zig created+151| ... | ... | @@ -0,0 +1,151 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "simple generic fn" { | |
| 4 | assertOrPanic(max(i32, 3, -1) == 3); | |
| 5 | assertOrPanic(max(f32, 0.123, 0.456) == 0.456); | |
| 6 | assertOrPanic(add(2, 3) == 5); | |
| 7 | } | |
| 8 | ||
| 9 | fn max(comptime T: type, a: T, b: T) T { | |
| 10 | return if (a > b) a else b; | |
| 11 | } | |
| 12 | ||
| 13 | fn add(comptime a: i32, b: i32) i32 { | |
| 14 | return (comptime a) + b; | |
| 15 | } | |
| 16 | ||
| 17 | const the_max = max(u32, 1234, 5678); | |
| 18 | test "compile time generic eval" { | |
| 19 | assertOrPanic(the_max == 5678); | |
| 20 | } | |
| 21 | ||
| 22 | fn gimmeTheBigOne(a: u32, b: u32) u32 { | |
| 23 | return max(u32, a, b); | |
| 24 | } | |
| 25 | ||
| 26 | fn shouldCallSameInstance(a: u32, b: u32) u32 { | |
| 27 | return max(u32, a, b); | |
| 28 | } | |
| 29 | ||
| 30 | fn sameButWithFloats(a: f64, b: f64) f64 { | |
| 31 | return max(f64, a, b); | |
| 32 | } | |
| 33 | ||
| 34 | test "fn with comptime args" { | |
| 35 | assertOrPanic(gimmeTheBigOne(1234, 5678) == 5678); | |
| 36 | assertOrPanic(shouldCallSameInstance(34, 12) == 34); | |
| 37 | assertOrPanic(sameButWithFloats(0.43, 0.49) == 0.49); | |
| 38 | } | |
| 39 | ||
| 40 | test "var params" { | |
| 41 | assertOrPanic(max_i32(12, 34) == 34); | |
| 42 | assertOrPanic(max_f64(1.2, 3.4) == 3.4); | |
| 43 | } | |
| 44 | ||
| 45 | comptime { | |
| 46 | assertOrPanic(max_i32(12, 34) == 34); | |
| 47 | assertOrPanic(max_f64(1.2, 3.4) == 3.4); | |
| 48 | } | |
| 49 | ||
| 50 | fn max_var(a: var, b: var) @typeOf(a + b) { | |
| 51 | return if (a > b) a else b; | |
| 52 | } | |
| 53 | ||
| 54 | fn max_i32(a: i32, b: i32) i32 { | |
| 55 | return max_var(a, b); | |
| 56 | } | |
| 57 | ||
| 58 | fn max_f64(a: f64, b: f64) f64 { | |
| 59 | return max_var(a, b); | |
| 60 | } | |
| 61 | ||
| 62 | pub fn List(comptime T: type) type { | |
| 63 | return SmallList(T, 8); | |
| 64 | } | |
| 65 | ||
| 66 | pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type { | |
| 67 | return struct { | |
| 68 | items: []T, | |
| 69 | length: usize, | |
| 70 | prealloc_items: [STATIC_SIZE]T, | |
| 71 | }; | |
| 72 | } | |
| 73 | ||
| 74 | test "function with return type type" { | |
| 75 | var list: List(i32) = undefined; | |
| 76 | var list2: List(i32) = undefined; | |
| 77 | list.length = 10; | |
| 78 | list2.length = 10; | |
| 79 | assertOrPanic(list.prealloc_items.len == 8); | |
| 80 | assertOrPanic(list2.prealloc_items.len == 8); | |
| 81 | } | |
| 82 | ||
| 83 | test "generic struct" { | |
| 84 | var a1 = GenNode(i32){ | |
| 85 | .value = 13, | |
| 86 | .next = null, | |
| 87 | }; | |
| 88 | var b1 = GenNode(bool){ | |
| 89 | .value = true, | |
| 90 | .next = null, | |
| 91 | }; | |
| 92 | assertOrPanic(a1.value == 13); | |
| 93 | assertOrPanic(a1.value == a1.getVal()); | |
| 94 | assertOrPanic(b1.getVal()); | |
| 95 | } | |
| 96 | fn GenNode(comptime T: type) type { | |
| 97 | return struct { | |
| 98 | value: T, | |
| 99 | next: ?*GenNode(T), | |
| 100 | fn getVal(n: *const GenNode(T)) T { | |
| 101 | return n.value; | |
| 102 | } | |
| 103 | }; | |
| 104 | } | |
| 105 | ||
| 106 | test "const decls in struct" { | |
| 107 | assertOrPanic(GenericDataThing(3).count_plus_one == 4); | |
| 108 | } | |
| 109 | fn GenericDataThing(comptime count: isize) type { | |
| 110 | return struct { | |
| 111 | const count_plus_one = count + 1; | |
| 112 | }; | |
| 113 | } | |
| 114 | ||
| 115 | test "use generic param in generic param" { | |
| 116 | assertOrPanic(aGenericFn(i32, 3, 4) == 7); | |
| 117 | } | |
| 118 | fn aGenericFn(comptime T: type, comptime a: T, b: T) T { | |
| 119 | return a + b; | |
| 120 | } | |
| 121 | ||
| 122 | test "generic fn with implicit cast" { | |
| 123 | assertOrPanic(getFirstByte(u8, []u8{13}) == 13); | |
| 124 | assertOrPanic(getFirstByte(u16, []u16{ | |
| 125 | 0, | |
| 126 | 13, | |
| 127 | }) == 0); | |
| 128 | } | |
| 129 | fn getByte(ptr: ?*const u8) u8 { | |
| 130 | return ptr.?.*; | |
| 131 | } | |
| 132 | fn getFirstByte(comptime T: type, mem: []const T) u8 { | |
| 133 | return getByte(@ptrCast(*const u8, &mem[0])); | |
| 134 | } | |
| 135 | ||
| 136 | const foos = []fn (var) bool{ | |
| 137 | foo1, | |
| 138 | foo2, | |
| 139 | }; | |
| 140 | ||
| 141 | fn foo1(arg: var) bool { | |
| 142 | return arg; | |
| 143 | } | |
| 144 | fn foo2(arg: var) bool { | |
| 145 | return !arg; | |
| 146 | } | |
| 147 | ||
| 148 | test "array of generic fns" { | |
| 149 | assertOrPanic(foos[0](true)); | |
| 150 | assertOrPanic(!foos[1](true)); | |
| 151 | } |
test/stage1/behavior/if.zig created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "if statements" { | |
| 4 | shouldBeEqual(1, 1); | |
| 5 | firstEqlThird(2, 1, 2); | |
| 6 | } | |
| 7 | fn shouldBeEqual(a: i32, b: i32) void { | |
| 8 | if (a != b) { | |
| 9 | unreachable; | |
| 10 | } else { | |
| 11 | return; | |
| 12 | } | |
| 13 | } | |
| 14 | fn firstEqlThird(a: i32, b: i32, c: i32) void { | |
| 15 | if (a == b) { | |
| 16 | unreachable; | |
| 17 | } else if (b == c) { | |
| 18 | unreachable; | |
| 19 | } else if (a == c) { | |
| 20 | return; | |
| 21 | } else { | |
| 22 | unreachable; | |
| 23 | } | |
| 24 | } | |
| 25 | ||
| 26 | test "else if expression" { | |
| 27 | assertOrPanic(elseIfExpressionF(1) == 1); | |
| 28 | } | |
| 29 | fn elseIfExpressionF(c: u8) u8 { | |
| 30 | if (c == 0) { | |
| 31 | return 0; | |
| 32 | } else if (c == 1) { | |
| 33 | return 1; | |
| 34 | } else { | |
| 35 | return u8(2); | |
| 36 | } | |
| 37 | } |
test/stage1/behavior/import.zig created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | const a_namespace = @import("import/a_namespace.zig"); | |
| 3 | ||
| 4 | test "call fn via namespace lookup" { | |
| 5 | assertOrPanic(a_namespace.foo() == 1234); | |
| 6 | } | |
| 7 | ||
| 8 | test "importing the same thing gives the same import" { | |
| 9 | assertOrPanic(@import("std") == @import("std")); | |
| 10 | } |
test/stage1/behavior/import/a_namespace.zig created+3| ... | ... | @@ -0,0 +1,3 @@ |
| 1 | pub fn foo() i32 { | |
| 2 | return 1234; | |
| 3 | } |
test/stage1/behavior/incomplete_struct_param_tld.zig created+30| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | const A = struct { | |
| 4 | b: B, | |
| 5 | }; | |
| 6 | ||
| 7 | const B = struct { | |
| 8 | c: C, | |
| 9 | }; | |
| 10 | ||
| 11 | const C = struct { | |
| 12 | x: i32, | |
| 13 | ||
| 14 | fn d(c: *const C) i32 { | |
| 15 | return c.x; | |
| 16 | } | |
| 17 | }; | |
| 18 | ||
| 19 | fn foo(a: A) i32 { | |
| 20 | return a.b.c.d(); | |
| 21 | } | |
| 22 | ||
| 23 | test "incomplete struct param top level declaration" { | |
| 24 | const a = A{ | |
| 25 | .b = B{ | |
| 26 | .c = C{ .x = 13 }, | |
| 27 | }, | |
| 28 | }; | |
| 29 | assertOrPanic(foo(a) == 13); | |
| 30 | } |
test/stage1/behavior/inttoptr.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std"); | |
| 3 | const assertOrPanic = std.debug.assertOrPanic; | |
| 4 | ||
| 5 | test "casting random address to function pointer" { | |
| 6 | randomAddressToFunction(); | |
| 7 | comptime randomAddressToFunction(); | |
| 8 | } | |
| 9 | ||
| 10 | fn randomAddressToFunction() void { | |
| 11 | var addr: usize = 0xdeadbeef; | |
| 12 | var ptr = @intToPtr(fn () void, addr); | |
| 13 | } | |
| 14 | ||
| 15 | test "mutate through ptr initialized with constant intToPtr value" { | |
| 16 | forceCompilerAnalyzeBranchHardCodedPtrDereference(false); | |
| 17 | } | |
| 18 | ||
| 19 | fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void { | |
| 20 | const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef); | |
| 21 | if (x) { | |
| 22 | hardCodedP.* = hardCodedP.* | 10; | |
| 23 | } else { | |
| 24 | return; | |
| 25 | } | |
| 26 | } |
test/stage1/behavior/ir_block_deps.zig created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | fn foo(id: u64) !i32 { | |
| 4 | return switch (id) { | |
| 5 | 1 => getErrInt(), | |
| 6 | 2 => { | |
| 7 | const size = try getErrInt(); | |
| 8 | return try getErrInt(); | |
| 9 | }, | |
| 10 | else => error.ItBroke, | |
| 11 | }; | |
| 12 | } | |
| 13 | ||
| 14 | fn getErrInt() anyerror!i32 { | |
| 15 | return 0; | |
| 16 | } | |
| 17 | ||
| 18 | test "ir block deps" { | |
| 19 | assertOrPanic((foo(1) catch unreachable) == 0); | |
| 20 | assertOrPanic((foo(2) catch unreachable) == 0); | |
| 21 | } |
test/stage1/behavior/math.zig created+500| ... | ... | @@ -0,0 +1,500 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const maxInt = std.math.maxInt; | |
| 4 | const minInt = std.math.minInt; | |
| 5 | ||
| 6 | test "division" { | |
| 7 | testDivision(); | |
| 8 | comptime testDivision(); | |
| 9 | } | |
| 10 | fn testDivision() void { | |
| 11 | assertOrPanic(div(u32, 13, 3) == 4); | |
| 12 | assertOrPanic(div(f16, 1.0, 2.0) == 0.5); | |
| 13 | assertOrPanic(div(f32, 1.0, 2.0) == 0.5); | |
| 14 | ||
| 15 | assertOrPanic(divExact(u32, 55, 11) == 5); | |
| 16 | assertOrPanic(divExact(i32, -55, 11) == -5); | |
| 17 | assertOrPanic(divExact(f16, 55.0, 11.0) == 5.0); | |
| 18 | assertOrPanic(divExact(f16, -55.0, 11.0) == -5.0); | |
| 19 | assertOrPanic(divExact(f32, 55.0, 11.0) == 5.0); | |
| 20 | assertOrPanic(divExact(f32, -55.0, 11.0) == -5.0); | |
| 21 | ||
| 22 | assertOrPanic(divFloor(i32, 5, 3) == 1); | |
| 23 | assertOrPanic(divFloor(i32, -5, 3) == -2); | |
| 24 | assertOrPanic(divFloor(f16, 5.0, 3.0) == 1.0); | |
| 25 | assertOrPanic(divFloor(f16, -5.0, 3.0) == -2.0); | |
| 26 | assertOrPanic(divFloor(f32, 5.0, 3.0) == 1.0); | |
| 27 | assertOrPanic(divFloor(f32, -5.0, 3.0) == -2.0); | |
| 28 | assertOrPanic(divFloor(i32, -0x80000000, -2) == 0x40000000); | |
| 29 | assertOrPanic(divFloor(i32, 0, -0x80000000) == 0); | |
| 30 | assertOrPanic(divFloor(i32, -0x40000001, 0x40000000) == -2); | |
| 31 | assertOrPanic(divFloor(i32, -0x80000000, 1) == -0x80000000); | |
| 32 | ||
| 33 | assertOrPanic(divTrunc(i32, 5, 3) == 1); | |
| 34 | assertOrPanic(divTrunc(i32, -5, 3) == -1); | |
| 35 | assertOrPanic(divTrunc(f16, 5.0, 3.0) == 1.0); | |
| 36 | assertOrPanic(divTrunc(f16, -5.0, 3.0) == -1.0); | |
| 37 | assertOrPanic(divTrunc(f32, 5.0, 3.0) == 1.0); | |
| 38 | assertOrPanic(divTrunc(f32, -5.0, 3.0) == -1.0); | |
| 39 | assertOrPanic(divTrunc(f64, 5.0, 3.0) == 1.0); | |
| 40 | assertOrPanic(divTrunc(f64, -5.0, 3.0) == -1.0); | |
| 41 | ||
| 42 | comptime { | |
| 43 | assertOrPanic( | |
| 44 | 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600, | |
| 45 | ); | |
| 46 | assertOrPanic( | |
| 47 | @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600, | |
| 48 | ); | |
| 49 | assertOrPanic( | |
| 50 | 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2, | |
| 51 | ); | |
| 52 | assertOrPanic( | |
| 53 | @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2, | |
| 54 | ); | |
| 55 | assertOrPanic( | |
| 56 | @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2, | |
| 57 | ); | |
| 58 | assertOrPanic( | |
| 59 | @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2, | |
| 60 | ); | |
| 61 | assertOrPanic( | |
| 62 | 4126227191251978491697987544882340798050766755606969681711 % 10 == 1, | |
| 63 | ); | |
| 64 | } | |
| 65 | } | |
| 66 | fn div(comptime T: type, a: T, b: T) T { | |
| 67 | return a / b; | |
| 68 | } | |
| 69 | fn divExact(comptime T: type, a: T, b: T) T { | |
| 70 | return @divExact(a, b); | |
| 71 | } | |
| 72 | fn divFloor(comptime T: type, a: T, b: T) T { | |
| 73 | return @divFloor(a, b); | |
| 74 | } | |
| 75 | fn divTrunc(comptime T: type, a: T, b: T) T { | |
| 76 | return @divTrunc(a, b); | |
| 77 | } | |
| 78 | ||
| 79 | test "@addWithOverflow" { | |
| 80 | var result: u8 = undefined; | |
| 81 | assertOrPanic(@addWithOverflow(u8, 250, 100, &result)); | |
| 82 | assertOrPanic(!@addWithOverflow(u8, 100, 150, &result)); | |
| 83 | assertOrPanic(result == 250); | |
| 84 | } | |
| 85 | ||
| 86 | // TODO test mulWithOverflow | |
| 87 | // TODO test subWithOverflow | |
| 88 | ||
| 89 | test "@shlWithOverflow" { | |
| 90 | var result: u16 = undefined; | |
| 91 | assertOrPanic(@shlWithOverflow(u16, 0b0010111111111111, 3, &result)); | |
| 92 | assertOrPanic(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result)); | |
| 93 | assertOrPanic(result == 0b1011111111111100); | |
| 94 | } | |
| 95 | ||
| 96 | test "@clz" { | |
| 97 | testClz(); | |
| 98 | comptime testClz(); | |
| 99 | } | |
| 100 | ||
| 101 | fn testClz() void { | |
| 102 | assertOrPanic(clz(u8(0b00001010)) == 4); | |
| 103 | assertOrPanic(clz(u8(0b10001010)) == 0); | |
| 104 | assertOrPanic(clz(u8(0b00000000)) == 8); | |
| 105 | assertOrPanic(clz(u128(0xffffffffffffffff)) == 64); | |
| 106 | assertOrPanic(clz(u128(0x10000000000000000)) == 63); | |
| 107 | } | |
| 108 | ||
| 109 | fn clz(x: var) usize { | |
| 110 | return @clz(x); | |
| 111 | } | |
| 112 | ||
| 113 | test "@ctz" { | |
| 114 | testCtz(); | |
| 115 | comptime testCtz(); | |
| 116 | } | |
| 117 | ||
| 118 | fn testCtz() void { | |
| 119 | assertOrPanic(ctz(u8(0b10100000)) == 5); | |
| 120 | assertOrPanic(ctz(u8(0b10001010)) == 1); | |
| 121 | assertOrPanic(ctz(u8(0b00000000)) == 8); | |
| 122 | } | |
| 123 | ||
| 124 | fn ctz(x: var) usize { | |
| 125 | return @ctz(x); | |
| 126 | } | |
| 127 | ||
| 128 | test "assignment operators" { | |
| 129 | var i: u32 = 0; | |
| 130 | i += 5; | |
| 131 | assertOrPanic(i == 5); | |
| 132 | i -= 2; | |
| 133 | assertOrPanic(i == 3); | |
| 134 | i *= 20; | |
| 135 | assertOrPanic(i == 60); | |
| 136 | i /= 3; | |
| 137 | assertOrPanic(i == 20); | |
| 138 | i %= 11; | |
| 139 | assertOrPanic(i == 9); | |
| 140 | i <<= 1; | |
| 141 | assertOrPanic(i == 18); | |
| 142 | i >>= 2; | |
| 143 | assertOrPanic(i == 4); | |
| 144 | i = 6; | |
| 145 | i &= 5; | |
| 146 | assertOrPanic(i == 4); | |
| 147 | i ^= 6; | |
| 148 | assertOrPanic(i == 2); | |
| 149 | i = 6; | |
| 150 | i |= 3; | |
| 151 | assertOrPanic(i == 7); | |
| 152 | } | |
| 153 | ||
| 154 | test "three expr in a row" { | |
| 155 | testThreeExprInARow(false, true); | |
| 156 | comptime testThreeExprInARow(false, true); | |
| 157 | } | |
| 158 | fn testThreeExprInARow(f: bool, t: bool) void { | |
| 159 | assertFalse(f or f or f); | |
| 160 | assertFalse(t and t and f); | |
| 161 | assertFalse(1 | 2 | 4 != 7); | |
| 162 | assertFalse(3 ^ 6 ^ 8 != 13); | |
| 163 | assertFalse(7 & 14 & 28 != 4); | |
| 164 | assertFalse(9 << 1 << 2 != 9 << 3); | |
| 165 | assertFalse(90 >> 1 >> 2 != 90 >> 3); | |
| 166 | assertFalse(100 - 1 + 1000 != 1099); | |
| 167 | assertFalse(5 * 4 / 2 % 3 != 1); | |
| 168 | assertFalse(i32(i32(5)) != 5); | |
| 169 | assertFalse(!!false); | |
| 170 | assertFalse(i32(7) != --(i32(7))); | |
| 171 | } | |
| 172 | fn assertFalse(b: bool) void { | |
| 173 | assertOrPanic(!b); | |
| 174 | } | |
| 175 | ||
| 176 | test "const number literal" { | |
| 177 | const one = 1; | |
| 178 | const eleven = ten + one; | |
| 179 | ||
| 180 | assertOrPanic(eleven == 11); | |
| 181 | } | |
| 182 | const ten = 10; | |
| 183 | ||
| 184 | test "unsigned wrapping" { | |
| 185 | testUnsignedWrappingEval(maxInt(u32)); | |
| 186 | comptime testUnsignedWrappingEval(maxInt(u32)); | |
| 187 | } | |
| 188 | fn testUnsignedWrappingEval(x: u32) void { | |
| 189 | const zero = x +% 1; | |
| 190 | assertOrPanic(zero == 0); | |
| 191 | const orig = zero -% 1; | |
| 192 | assertOrPanic(orig == maxInt(u32)); | |
| 193 | } | |
| 194 | ||
| 195 | test "signed wrapping" { | |
| 196 | testSignedWrappingEval(maxInt(i32)); | |
| 197 | comptime testSignedWrappingEval(maxInt(i32)); | |
| 198 | } | |
| 199 | fn testSignedWrappingEval(x: i32) void { | |
| 200 | const min_val = x +% 1; | |
| 201 | assertOrPanic(min_val == minInt(i32)); | |
| 202 | const max_val = min_val -% 1; | |
| 203 | assertOrPanic(max_val == maxInt(i32)); | |
| 204 | } | |
| 205 | ||
| 206 | test "negation wrapping" { | |
| 207 | testNegationWrappingEval(minInt(i16)); | |
| 208 | comptime testNegationWrappingEval(minInt(i16)); | |
| 209 | } | |
| 210 | fn testNegationWrappingEval(x: i16) void { | |
| 211 | assertOrPanic(x == -32768); | |
| 212 | const neg = -%x; | |
| 213 | assertOrPanic(neg == -32768); | |
| 214 | } | |
| 215 | ||
| 216 | test "unsigned 64-bit division" { | |
| 217 | test_u64_div(); | |
| 218 | comptime test_u64_div(); | |
| 219 | } | |
| 220 | fn test_u64_div() void { | |
| 221 | const result = divWithResult(1152921504606846976, 34359738365); | |
| 222 | assertOrPanic(result.quotient == 33554432); | |
| 223 | assertOrPanic(result.remainder == 100663296); | |
| 224 | } | |
| 225 | fn divWithResult(a: u64, b: u64) DivResult { | |
| 226 | return DivResult{ | |
| 227 | .quotient = a / b, | |
| 228 | .remainder = a % b, | |
| 229 | }; | |
| 230 | } | |
| 231 | const DivResult = struct { | |
| 232 | quotient: u64, | |
| 233 | remainder: u64, | |
| 234 | }; | |
| 235 | ||
| 236 | test "binary not" { | |
| 237 | assertOrPanic(comptime x: { | |
| 238 | break :x ~u16(0b1010101010101010) == 0b0101010101010101; | |
| 239 | }); | |
| 240 | assertOrPanic(comptime x: { | |
| 241 | break :x ~u64(2147483647) == 18446744071562067968; | |
| 242 | }); | |
| 243 | testBinaryNot(0b1010101010101010); | |
| 244 | } | |
| 245 | ||
| 246 | fn testBinaryNot(x: u16) void { | |
| 247 | assertOrPanic(~x == 0b0101010101010101); | |
| 248 | } | |
| 249 | ||
| 250 | test "small int addition" { | |
| 251 | var x: @IntType(false, 2) = 0; | |
| 252 | assertOrPanic(x == 0); | |
| 253 | ||
| 254 | x += 1; | |
| 255 | assertOrPanic(x == 1); | |
| 256 | ||
| 257 | x += 1; | |
| 258 | assertOrPanic(x == 2); | |
| 259 | ||
| 260 | x += 1; | |
| 261 | assertOrPanic(x == 3); | |
| 262 | ||
| 263 | var result: @typeOf(x) = 3; | |
| 264 | assertOrPanic(@addWithOverflow(@typeOf(x), x, 1, &result)); | |
| 265 | ||
| 266 | assertOrPanic(result == 0); | |
| 267 | } | |
| 268 | ||
| 269 | test "float equality" { | |
| 270 | const x: f64 = 0.012; | |
| 271 | const y: f64 = x + 1.0; | |
| 272 | ||
| 273 | testFloatEqualityImpl(x, y); | |
| 274 | comptime testFloatEqualityImpl(x, y); | |
| 275 | } | |
| 276 | ||
| 277 | fn testFloatEqualityImpl(x: f64, y: f64) void { | |
| 278 | const y2 = x + 1.0; | |
| 279 | assertOrPanic(y == y2); | |
| 280 | } | |
| 281 | ||
| 282 | test "allow signed integer division/remainder when values are comptime known and positive or exact" { | |
| 283 | assertOrPanic(5 / 3 == 1); | |
| 284 | assertOrPanic(-5 / -3 == 1); | |
| 285 | assertOrPanic(-6 / 3 == -2); | |
| 286 | ||
| 287 | assertOrPanic(5 % 3 == 2); | |
| 288 | assertOrPanic(-6 % 3 == 0); | |
| 289 | } | |
| 290 | ||
| 291 | test "hex float literal parsing" { | |
| 292 | comptime assertOrPanic(0x1.0 == 1.0); | |
| 293 | } | |
| 294 | ||
| 295 | test "quad hex float literal parsing in range" { | |
| 296 | const a = 0x1.af23456789bbaaab347645365cdep+5; | |
| 297 | const b = 0x1.dedafcff354b6ae9758763545432p-9; | |
| 298 | const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534; | |
| 299 | const d = 0x1.edcbff8ad76ab5bf46463233214fp-435; | |
| 300 | } | |
| 301 | ||
| 302 | test "quad hex float literal parsing accurate" { | |
| 303 | const a: f128 = 0x1.1111222233334444555566667777p+0; | |
| 304 | ||
| 305 | // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing. | |
| 306 | const expected: u128 = 0x3fff1111222233334444555566667777; | |
| 307 | assertOrPanic(@bitCast(u128, a) == expected); | |
| 308 | } | |
| 309 | ||
| 310 | test "hex float literal within range" { | |
| 311 | const a = 0x1.0p16383; | |
| 312 | const b = 0x0.1p16387; | |
| 313 | const c = 0x1.0p-16382; | |
| 314 | } | |
| 315 | ||
| 316 | test "truncating shift left" { | |
| 317 | testShlTrunc(maxInt(u16)); | |
| 318 | comptime testShlTrunc(maxInt(u16)); | |
| 319 | } | |
| 320 | fn testShlTrunc(x: u16) void { | |
| 321 | const shifted = x << 1; | |
| 322 | assertOrPanic(shifted == 65534); | |
| 323 | } | |
| 324 | ||
| 325 | test "truncating shift right" { | |
| 326 | testShrTrunc(maxInt(u16)); | |
| 327 | comptime testShrTrunc(maxInt(u16)); | |
| 328 | } | |
| 329 | fn testShrTrunc(x: u16) void { | |
| 330 | const shifted = x >> 1; | |
| 331 | assertOrPanic(shifted == 32767); | |
| 332 | } | |
| 333 | ||
| 334 | test "exact shift left" { | |
| 335 | testShlExact(0b00110101); | |
| 336 | comptime testShlExact(0b00110101); | |
| 337 | } | |
| 338 | fn testShlExact(x: u8) void { | |
| 339 | const shifted = @shlExact(x, 2); | |
| 340 | assertOrPanic(shifted == 0b11010100); | |
| 341 | } | |
| 342 | ||
| 343 | test "exact shift right" { | |
| 344 | testShrExact(0b10110100); | |
| 345 | comptime testShrExact(0b10110100); | |
| 346 | } | |
| 347 | fn testShrExact(x: u8) void { | |
| 348 | const shifted = @shrExact(x, 2); | |
| 349 | assertOrPanic(shifted == 0b00101101); | |
| 350 | } | |
| 351 | ||
| 352 | test "comptime_int addition" { | |
| 353 | comptime { | |
| 354 | assertOrPanic(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950); | |
| 355 | assertOrPanic(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380); | |
| 356 | } | |
| 357 | } | |
| 358 | ||
| 359 | test "comptime_int multiplication" { | |
| 360 | comptime { | |
| 361 | assertOrPanic( | |
| 362 | 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567, | |
| 363 | ); | |
| 364 | assertOrPanic( | |
| 365 | 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016, | |
| 366 | ); | |
| 367 | } | |
| 368 | } | |
| 369 | ||
| 370 | test "comptime_int shifting" { | |
| 371 | comptime { | |
| 372 | assertOrPanic((u128(1) << 127) == 0x80000000000000000000000000000000); | |
| 373 | } | |
| 374 | } | |
| 375 | ||
| 376 | test "comptime_int multi-limb shift and mask" { | |
| 377 | comptime { | |
| 378 | var a = 0xefffffffa0000001eeeeeeefaaaaaaab; | |
| 379 | ||
| 380 | assertOrPanic(u32(a & 0xffffffff) == 0xaaaaaaab); | |
| 381 | a >>= 32; | |
| 382 | assertOrPanic(u32(a & 0xffffffff) == 0xeeeeeeef); | |
| 383 | a >>= 32; | |
| 384 | assertOrPanic(u32(a & 0xffffffff) == 0xa0000001); | |
| 385 | a >>= 32; | |
| 386 | assertOrPanic(u32(a & 0xffffffff) == 0xefffffff); | |
| 387 | a >>= 32; | |
| 388 | ||
| 389 | assertOrPanic(a == 0); | |
| 390 | } | |
| 391 | } | |
| 392 | ||
| 393 | test "comptime_int multi-limb partial shift right" { | |
| 394 | comptime { | |
| 395 | var a = 0x1ffffffffeeeeeeee; | |
| 396 | a >>= 16; | |
| 397 | assertOrPanic(a == 0x1ffffffffeeee); | |
| 398 | } | |
| 399 | } | |
| 400 | ||
| 401 | test "xor" { | |
| 402 | test_xor(); | |
| 403 | comptime test_xor(); | |
| 404 | } | |
| 405 | ||
| 406 | fn test_xor() void { | |
| 407 | assertOrPanic(0xFF ^ 0x00 == 0xFF); | |
| 408 | assertOrPanic(0xF0 ^ 0x0F == 0xFF); | |
| 409 | assertOrPanic(0xFF ^ 0xF0 == 0x0F); | |
| 410 | assertOrPanic(0xFF ^ 0x0F == 0xF0); | |
| 411 | assertOrPanic(0xFF ^ 0xFF == 0x00); | |
| 412 | } | |
| 413 | ||
| 414 | test "comptime_int xor" { | |
| 415 | comptime { | |
| 416 | assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 417 | assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 418 | assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF); | |
| 419 | assertOrPanic(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000); | |
| 420 | assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000); | |
| 421 | assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 422 | assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF); | |
| 423 | assertOrPanic(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000); | |
| 424 | } | |
| 425 | } | |
| 426 | ||
| 427 | test "f128" { | |
| 428 | test_f128(); | |
| 429 | comptime test_f128(); | |
| 430 | } | |
| 431 | ||
| 432 | fn make_f128(x: f128) f128 { | |
| 433 | return x; | |
| 434 | } | |
| 435 | ||
| 436 | fn test_f128() void { | |
| 437 | assertOrPanic(@sizeOf(f128) == 16); | |
| 438 | assertOrPanic(make_f128(1.0) == 1.0); | |
| 439 | assertOrPanic(make_f128(1.0) != 1.1); | |
| 440 | assertOrPanic(make_f128(1.0) > 0.9); | |
| 441 | assertOrPanic(make_f128(1.0) >= 0.9); | |
| 442 | assertOrPanic(make_f128(1.0) >= 1.0); | |
| 443 | should_not_be_zero(1.0); | |
| 444 | } | |
| 445 | ||
| 446 | fn should_not_be_zero(x: f128) void { | |
| 447 | assertOrPanic(x != 0.0); | |
| 448 | } | |
| 449 | ||
| 450 | test "comptime float rem int" { | |
| 451 | comptime { | |
| 452 | var x = f32(1) % 2; | |
| 453 | assertOrPanic(x == 1.0); | |
| 454 | } | |
| 455 | } | |
| 456 | ||
| 457 | test "remainder division" { | |
| 458 | comptime remdiv(f16); | |
| 459 | comptime remdiv(f32); | |
| 460 | comptime remdiv(f64); | |
| 461 | comptime remdiv(f128); | |
| 462 | remdiv(f16); | |
| 463 | remdiv(f64); | |
| 464 | remdiv(f128); | |
| 465 | } | |
| 466 | ||
| 467 | fn remdiv(comptime T: type) void { | |
| 468 | assertOrPanic(T(1) == T(1) % T(2)); | |
| 469 | assertOrPanic(T(1) == T(7) % T(3)); | |
| 470 | } | |
| 471 | ||
| 472 | test "@sqrt" { | |
| 473 | testSqrt(f64, 12.0); | |
| 474 | comptime testSqrt(f64, 12.0); | |
| 475 | testSqrt(f32, 13.0); | |
| 476 | comptime testSqrt(f32, 13.0); | |
| 477 | testSqrt(f16, 13.0); | |
| 478 | comptime testSqrt(f16, 13.0); | |
| 479 | ||
| 480 | const x = 14.0; | |
| 481 | const y = x * x; | |
| 482 | const z = @sqrt(@typeOf(y), y); | |
| 483 | comptime assertOrPanic(z == x); | |
| 484 | } | |
| 485 | ||
| 486 | fn testSqrt(comptime T: type, x: T) void { | |
| 487 | assertOrPanic(@sqrt(T, x * x) == x); | |
| 488 | } | |
| 489 | ||
| 490 | test "comptime_int param and return" { | |
| 491 | const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702); | |
| 492 | assertOrPanic(a == 137114567242441932203689521744947848950); | |
| 493 | ||
| 494 | const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768); | |
| 495 | assertOrPanic(b == 985095453608931032642182098849559179469148836107390954364380); | |
| 496 | } | |
| 497 | ||
| 498 | fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int { | |
| 499 | return a + b; | |
| 500 | } |
test/stage1/behavior/merge_error_sets.zig created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | const A = error{ | |
| 2 | FileNotFound, | |
| 3 | NotDir, | |
| 4 | }; | |
| 5 | const B = error{OutOfMemory}; | |
| 6 | ||
| 7 | const C = A || B; | |
| 8 | ||
| 9 | fn foo() C!void { | |
| 10 | return error.NotDir; | |
| 11 | } | |
| 12 | ||
| 13 | test "merge error sets" { | |
| 14 | if (foo()) { | |
| 15 | @panic("unexpected"); | |
| 16 | } else |err| switch (err) { | |
| 17 | error.OutOfMemory => @panic("unexpected"), | |
| 18 | error.FileNotFound => @panic("unexpected"), | |
| 19 | error.NotDir => {}, | |
| 20 | } | |
| 21 | } |
test/stage1/behavior/misc.zig created+687| ... | ... | @@ -0,0 +1,687 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const mem = std.mem; | |
| 4 | const cstr = std.cstr; | |
| 5 | const builtin = @import("builtin"); | |
| 6 | const maxInt = std.math.maxInt; | |
| 7 | ||
| 8 | // normal comment | |
| 9 | ||
| 10 | /// this is a documentation comment | |
| 11 | /// doc comment line 2 | |
| 12 | fn emptyFunctionWithComments() void {} | |
| 13 | ||
| 14 | test "empty function with comments" { | |
| 15 | emptyFunctionWithComments(); | |
| 16 | } | |
| 17 | ||
| 18 | comptime { | |
| 19 | @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal); | |
| 20 | } | |
| 21 | ||
| 22 | extern fn disabledExternFn() void {} | |
| 23 | ||
| 24 | test "call disabled extern fn" { | |
| 25 | disabledExternFn(); | |
| 26 | } | |
| 27 | ||
| 28 | test "@IntType builtin" { | |
| 29 | assertOrPanic(@IntType(true, 8) == i8); | |
| 30 | assertOrPanic(@IntType(true, 16) == i16); | |
| 31 | assertOrPanic(@IntType(true, 32) == i32); | |
| 32 | assertOrPanic(@IntType(true, 64) == i64); | |
| 33 | ||
| 34 | assertOrPanic(@IntType(false, 8) == u8); | |
| 35 | assertOrPanic(@IntType(false, 16) == u16); | |
| 36 | assertOrPanic(@IntType(false, 32) == u32); | |
| 37 | assertOrPanic(@IntType(false, 64) == u64); | |
| 38 | ||
| 39 | assertOrPanic(i8.bit_count == 8); | |
| 40 | assertOrPanic(i16.bit_count == 16); | |
| 41 | assertOrPanic(i32.bit_count == 32); | |
| 42 | assertOrPanic(i64.bit_count == 64); | |
| 43 | ||
| 44 | assertOrPanic(i8.is_signed); | |
| 45 | assertOrPanic(i16.is_signed); | |
| 46 | assertOrPanic(i32.is_signed); | |
| 47 | assertOrPanic(i64.is_signed); | |
| 48 | assertOrPanic(isize.is_signed); | |
| 49 | ||
| 50 | assertOrPanic(!u8.is_signed); | |
| 51 | assertOrPanic(!u16.is_signed); | |
| 52 | assertOrPanic(!u32.is_signed); | |
| 53 | assertOrPanic(!u64.is_signed); | |
| 54 | assertOrPanic(!usize.is_signed); | |
| 55 | } | |
| 56 | ||
| 57 | test "floating point primitive bit counts" { | |
| 58 | assertOrPanic(f16.bit_count == 16); | |
| 59 | assertOrPanic(f32.bit_count == 32); | |
| 60 | assertOrPanic(f64.bit_count == 64); | |
| 61 | } | |
| 62 | ||
| 63 | test "short circuit" { | |
| 64 | testShortCircuit(false, true); | |
| 65 | comptime testShortCircuit(false, true); | |
| 66 | } | |
| 67 | ||
| 68 | fn testShortCircuit(f: bool, t: bool) void { | |
| 69 | var hit_1 = f; | |
| 70 | var hit_2 = f; | |
| 71 | var hit_3 = f; | |
| 72 | var hit_4 = f; | |
| 73 | ||
| 74 | if (t or x: { | |
| 75 | assertOrPanic(f); | |
| 76 | break :x f; | |
| 77 | }) { | |
| 78 | hit_1 = t; | |
| 79 | } | |
| 80 | if (f or x: { | |
| 81 | hit_2 = t; | |
| 82 | break :x f; | |
| 83 | }) { | |
| 84 | assertOrPanic(f); | |
| 85 | } | |
| 86 | ||
| 87 | if (t and x: { | |
| 88 | hit_3 = t; | |
| 89 | break :x f; | |
| 90 | }) { | |
| 91 | assertOrPanic(f); | |
| 92 | } | |
| 93 | if (f and x: { | |
| 94 | assertOrPanic(f); | |
| 95 | break :x f; | |
| 96 | }) { | |
| 97 | assertOrPanic(f); | |
| 98 | } else { | |
| 99 | hit_4 = t; | |
| 100 | } | |
| 101 | assertOrPanic(hit_1); | |
| 102 | assertOrPanic(hit_2); | |
| 103 | assertOrPanic(hit_3); | |
| 104 | assertOrPanic(hit_4); | |
| 105 | } | |
| 106 | ||
| 107 | test "truncate" { | |
| 108 | assertOrPanic(testTruncate(0x10fd) == 0xfd); | |
| 109 | } | |
| 110 | fn testTruncate(x: u32) u8 { | |
| 111 | return @truncate(u8, x); | |
| 112 | } | |
| 113 | ||
| 114 | fn first4KeysOfHomeRow() []const u8 { | |
| 115 | return "aoeu"; | |
| 116 | } | |
| 117 | ||
| 118 | test "return string from function" { | |
| 119 | assertOrPanic(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); | |
| 120 | } | |
| 121 | ||
| 122 | const g1: i32 = 1233 + 1; | |
| 123 | var g2: i32 = 0; | |
| 124 | ||
| 125 | test "global variables" { | |
| 126 | assertOrPanic(g2 == 0); | |
| 127 | g2 = g1; | |
| 128 | assertOrPanic(g2 == 1234); | |
| 129 | } | |
| 130 | ||
| 131 | test "memcpy and memset intrinsics" { | |
| 132 | var foo: [20]u8 = undefined; | |
| 133 | var bar: [20]u8 = undefined; | |
| 134 | ||
| 135 | @memset(foo[0..].ptr, 'A', foo.len); | |
| 136 | @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len); | |
| 137 | ||
| 138 | if (bar[11] != 'A') unreachable; | |
| 139 | } | |
| 140 | ||
| 141 | test "builtin static eval" { | |
| 142 | const x: i32 = comptime x: { | |
| 143 | break :x 1 + 2 + 3; | |
| 144 | }; | |
| 145 | assertOrPanic(x == comptime 6); | |
| 146 | } | |
| 147 | ||
| 148 | test "slicing" { | |
| 149 | var array: [20]i32 = undefined; | |
| 150 | ||
| 151 | array[5] = 1234; | |
| 152 | ||
| 153 | var slice = array[5..10]; | |
| 154 | ||
| 155 | if (slice.len != 5) unreachable; | |
| 156 | ||
| 157 | const ptr = &slice[0]; | |
| 158 | if (ptr.* != 1234) unreachable; | |
| 159 | ||
| 160 | var slice_rest = array[10..]; | |
| 161 | if (slice_rest.len != 10) unreachable; | |
| 162 | } | |
| 163 | ||
| 164 | test "constant equal function pointers" { | |
| 165 | const alias = emptyFn; | |
| 166 | assertOrPanic(comptime x: { | |
| 167 | break :x emptyFn == alias; | |
| 168 | }); | |
| 169 | } | |
| 170 | ||
| 171 | fn emptyFn() void {} | |
| 172 | ||
| 173 | test "hex escape" { | |
| 174 | assertOrPanic(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); | |
| 175 | } | |
| 176 | ||
| 177 | test "string concatenation" { | |
| 178 | assertOrPanic(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); | |
| 179 | } | |
| 180 | ||
| 181 | test "array mult operator" { | |
| 182 | assertOrPanic(mem.eql(u8, "ab" ** 5, "ababababab")); | |
| 183 | } | |
| 184 | ||
| 185 | test "string escapes" { | |
| 186 | assertOrPanic(mem.eql(u8, "\"", "\x22")); | |
| 187 | assertOrPanic(mem.eql(u8, "\'", "\x27")); | |
| 188 | assertOrPanic(mem.eql(u8, "\n", "\x0a")); | |
| 189 | assertOrPanic(mem.eql(u8, "\r", "\x0d")); | |
| 190 | assertOrPanic(mem.eql(u8, "\t", "\x09")); | |
| 191 | assertOrPanic(mem.eql(u8, "\\", "\x5c")); | |
| 192 | assertOrPanic(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69")); | |
| 193 | } | |
| 194 | ||
| 195 | test "multiline string" { | |
| 196 | const s1 = | |
| 197 | \\one | |
| 198 | \\two) | |
| 199 | \\three | |
| 200 | ; | |
| 201 | const s2 = "one\ntwo)\nthree"; | |
| 202 | assertOrPanic(mem.eql(u8, s1, s2)); | |
| 203 | } | |
| 204 | ||
| 205 | test "multiline C string" { | |
| 206 | const s1 = | |
| 207 | c\\one | |
| 208 | c\\two) | |
| 209 | c\\three | |
| 210 | ; | |
| 211 | const s2 = c"one\ntwo)\nthree"; | |
| 212 | assertOrPanic(cstr.cmp(s1, s2) == 0); | |
| 213 | } | |
| 214 | ||
| 215 | test "type equality" { | |
| 216 | assertOrPanic(*const u8 != *u8); | |
| 217 | } | |
| 218 | ||
| 219 | const global_a: i32 = 1234; | |
| 220 | const global_b: *const i32 = &global_a; | |
| 221 | const global_c: *const f32 = @ptrCast(*const f32, global_b); | |
| 222 | test "compile time global reinterpret" { | |
| 223 | const d = @ptrCast(*const i32, global_c); | |
| 224 | assertOrPanic(d.* == 1234); | |
| 225 | } | |
| 226 | ||
| 227 | test "explicit cast maybe pointers" { | |
| 228 | const a: ?*i32 = undefined; | |
| 229 | const b: ?*f32 = @ptrCast(?*f32, a); | |
| 230 | } | |
| 231 | ||
| 232 | test "generic malloc free" { | |
| 233 | const a = memAlloc(u8, 10) catch unreachable; | |
| 234 | memFree(u8, a); | |
| 235 | } | |
| 236 | var some_mem: [100]u8 = undefined; | |
| 237 | fn memAlloc(comptime T: type, n: usize) anyerror![]T { | |
| 238 | return @ptrCast([*]T, &some_mem[0])[0..n]; | |
| 239 | } | |
| 240 | fn memFree(comptime T: type, memory: []T) void {} | |
| 241 | ||
| 242 | test "cast undefined" { | |
| 243 | const array: [100]u8 = undefined; | |
| 244 | const slice = ([]const u8)(array); | |
| 245 | testCastUndefined(slice); | |
| 246 | } | |
| 247 | fn testCastUndefined(x: []const u8) void {} | |
| 248 | ||
| 249 | test "cast small unsigned to larger signed" { | |
| 250 | assertOrPanic(castSmallUnsignedToLargerSigned1(200) == i16(200)); | |
| 251 | assertOrPanic(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); | |
| 252 | } | |
| 253 | fn castSmallUnsignedToLargerSigned1(x: u8) i16 { | |
| 254 | return x; | |
| 255 | } | |
| 256 | fn castSmallUnsignedToLargerSigned2(x: u16) i64 { | |
| 257 | return x; | |
| 258 | } | |
| 259 | ||
| 260 | test "implicit cast after unreachable" { | |
| 261 | assertOrPanic(outer() == 1234); | |
| 262 | } | |
| 263 | fn inner() i32 { | |
| 264 | return 1234; | |
| 265 | } | |
| 266 | fn outer() i64 { | |
| 267 | return inner(); | |
| 268 | } | |
| 269 | ||
| 270 | test "pointer dereferencing" { | |
| 271 | var x = i32(3); | |
| 272 | const y = &x; | |
| 273 | ||
| 274 | y.* += 1; | |
| 275 | ||
| 276 | assertOrPanic(x == 4); | |
| 277 | assertOrPanic(y.* == 4); | |
| 278 | } | |
| 279 | ||
| 280 | test "call result of if else expression" { | |
| 281 | assertOrPanic(mem.eql(u8, f2(true), "a")); | |
| 282 | assertOrPanic(mem.eql(u8, f2(false), "b")); | |
| 283 | } | |
| 284 | fn f2(x: bool) []const u8 { | |
| 285 | return (if (x) fA else fB)(); | |
| 286 | } | |
| 287 | fn fA() []const u8 { | |
| 288 | return "a"; | |
| 289 | } | |
| 290 | fn fB() []const u8 { | |
| 291 | return "b"; | |
| 292 | } | |
| 293 | ||
| 294 | test "const expression eval handling of variables" { | |
| 295 | var x = true; | |
| 296 | while (x) { | |
| 297 | x = false; | |
| 298 | } | |
| 299 | } | |
| 300 | ||
| 301 | test "constant enum initialization with differing sizes" { | |
| 302 | test3_1(test3_foo); | |
| 303 | test3_2(test3_bar); | |
| 304 | } | |
| 305 | const Test3Foo = union(enum) { | |
| 306 | One: void, | |
| 307 | Two: f32, | |
| 308 | Three: Test3Point, | |
| 309 | }; | |
| 310 | const Test3Point = struct { | |
| 311 | x: i32, | |
| 312 | y: i32, | |
| 313 | }; | |
| 314 | const test3_foo = Test3Foo{ | |
| 315 | .Three = Test3Point{ | |
| 316 | .x = 3, | |
| 317 | .y = 4, | |
| 318 | }, | |
| 319 | }; | |
| 320 | const test3_bar = Test3Foo{ .Two = 13 }; | |
| 321 | fn test3_1(f: Test3Foo) void { | |
| 322 | switch (f) { | |
| 323 | Test3Foo.Three => |pt| { | |
| 324 | assertOrPanic(pt.x == 3); | |
| 325 | assertOrPanic(pt.y == 4); | |
| 326 | }, | |
| 327 | else => unreachable, | |
| 328 | } | |
| 329 | } | |
| 330 | fn test3_2(f: Test3Foo) void { | |
| 331 | switch (f) { | |
| 332 | Test3Foo.Two => |x| { | |
| 333 | assertOrPanic(x == 13); | |
| 334 | }, | |
| 335 | else => unreachable, | |
| 336 | } | |
| 337 | } | |
| 338 | ||
| 339 | test "character literals" { | |
| 340 | assertOrPanic('\'' == single_quote); | |
| 341 | } | |
| 342 | const single_quote = '\''; | |
| 343 | ||
| 344 | test "take address of parameter" { | |
| 345 | testTakeAddressOfParameter(12.34); | |
| 346 | } | |
| 347 | fn testTakeAddressOfParameter(f: f32) void { | |
| 348 | const f_ptr = &f; | |
| 349 | assertOrPanic(f_ptr.* == 12.34); | |
| 350 | } | |
| 351 | ||
| 352 | test "pointer comparison" { | |
| 353 | const a = ([]const u8)("a"); | |
| 354 | const b = &a; | |
| 355 | assertOrPanic(ptrEql(b, b)); | |
| 356 | } | |
| 357 | fn ptrEql(a: *const []const u8, b: *const []const u8) bool { | |
| 358 | return a == b; | |
| 359 | } | |
| 360 | ||
| 361 | test "C string concatenation" { | |
| 362 | const a = c"OK" ++ c" IT " ++ c"WORKED"; | |
| 363 | const b = c"OK IT WORKED"; | |
| 364 | ||
| 365 | const len = cstr.len(b); | |
| 366 | const len_with_null = len + 1; | |
| 367 | { | |
| 368 | var i: u32 = 0; | |
| 369 | while (i < len_with_null) : (i += 1) { | |
| 370 | assertOrPanic(a[i] == b[i]); | |
| 371 | } | |
| 372 | } | |
| 373 | assertOrPanic(a[len] == 0); | |
| 374 | assertOrPanic(b[len] == 0); | |
| 375 | } | |
| 376 | ||
| 377 | test "cast slice to u8 slice" { | |
| 378 | assertOrPanic(@sizeOf(i32) == 4); | |
| 379 | var big_thing_array = []i32{ 1, 2, 3, 4 }; | |
| 380 | const big_thing_slice: []i32 = big_thing_array[0..]; | |
| 381 | const bytes = @sliceToBytes(big_thing_slice); | |
| 382 | assertOrPanic(bytes.len == 4 * 4); | |
| 383 | bytes[4] = 0; | |
| 384 | bytes[5] = 0; | |
| 385 | bytes[6] = 0; | |
| 386 | bytes[7] = 0; | |
| 387 | assertOrPanic(big_thing_slice[1] == 0); | |
| 388 | const big_thing_again = @bytesToSlice(i32, bytes); | |
| 389 | assertOrPanic(big_thing_again[2] == 3); | |
| 390 | big_thing_again[2] = -1; | |
| 391 | assertOrPanic(bytes[8] == maxInt(u8)); | |
| 392 | assertOrPanic(bytes[9] == maxInt(u8)); | |
| 393 | assertOrPanic(bytes[10] == maxInt(u8)); | |
| 394 | assertOrPanic(bytes[11] == maxInt(u8)); | |
| 395 | } | |
| 396 | ||
| 397 | test "pointer to void return type" { | |
| 398 | testPointerToVoidReturnType() catch unreachable; | |
| 399 | } | |
| 400 | fn testPointerToVoidReturnType() anyerror!void { | |
| 401 | const a = testPointerToVoidReturnType2(); | |
| 402 | return a.*; | |
| 403 | } | |
| 404 | const test_pointer_to_void_return_type_x = void{}; | |
| 405 | fn testPointerToVoidReturnType2() *const void { | |
| 406 | return &test_pointer_to_void_return_type_x; | |
| 407 | } | |
| 408 | ||
| 409 | test "non const ptr to aliased type" { | |
| 410 | const int = i32; | |
| 411 | assertOrPanic(?*int == ?*i32); | |
| 412 | } | |
| 413 | ||
| 414 | test "array 2D const double ptr" { | |
| 415 | const rect_2d_vertexes = [][1]f32{ | |
| 416 | []f32{1.0}, | |
| 417 | []f32{2.0}, | |
| 418 | }; | |
| 419 | testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); | |
| 420 | } | |
| 421 | ||
| 422 | fn testArray2DConstDoublePtr(ptr: *const f32) void { | |
| 423 | const ptr2 = @ptrCast([*]const f32, ptr); | |
| 424 | assertOrPanic(ptr2[0] == 1.0); | |
| 425 | assertOrPanic(ptr2[1] == 2.0); | |
| 426 | } | |
| 427 | ||
| 428 | const Tid = builtin.TypeId; | |
| 429 | const AStruct = struct { | |
| 430 | x: i32, | |
| 431 | }; | |
| 432 | const AnEnum = enum { | |
| 433 | One, | |
| 434 | Two, | |
| 435 | }; | |
| 436 | const AUnionEnum = union(enum) { | |
| 437 | One: i32, | |
| 438 | Two: void, | |
| 439 | }; | |
| 440 | const AUnion = union { | |
| 441 | One: void, | |
| 442 | Two: void, | |
| 443 | }; | |
| 444 | ||
| 445 | test "@typeId" { | |
| 446 | comptime { | |
| 447 | assertOrPanic(@typeId(type) == Tid.Type); | |
| 448 | assertOrPanic(@typeId(void) == Tid.Void); | |
| 449 | assertOrPanic(@typeId(bool) == Tid.Bool); | |
| 450 | assertOrPanic(@typeId(noreturn) == Tid.NoReturn); | |
| 451 | assertOrPanic(@typeId(i8) == Tid.Int); | |
| 452 | assertOrPanic(@typeId(u8) == Tid.Int); | |
| 453 | assertOrPanic(@typeId(i64) == Tid.Int); | |
| 454 | assertOrPanic(@typeId(u64) == Tid.Int); | |
| 455 | assertOrPanic(@typeId(f32) == Tid.Float); | |
| 456 | assertOrPanic(@typeId(f64) == Tid.Float); | |
| 457 | assertOrPanic(@typeId(*f32) == Tid.Pointer); | |
| 458 | assertOrPanic(@typeId([2]u8) == Tid.Array); | |
| 459 | assertOrPanic(@typeId(AStruct) == Tid.Struct); | |
| 460 | assertOrPanic(@typeId(@typeOf(1)) == Tid.ComptimeInt); | |
| 461 | assertOrPanic(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat); | |
| 462 | assertOrPanic(@typeId(@typeOf(undefined)) == Tid.Undefined); | |
| 463 | assertOrPanic(@typeId(@typeOf(null)) == Tid.Null); | |
| 464 | assertOrPanic(@typeId(?i32) == Tid.Optional); | |
| 465 | assertOrPanic(@typeId(anyerror!i32) == Tid.ErrorUnion); | |
| 466 | assertOrPanic(@typeId(anyerror) == Tid.ErrorSet); | |
| 467 | assertOrPanic(@typeId(AnEnum) == Tid.Enum); | |
| 468 | assertOrPanic(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum); | |
| 469 | assertOrPanic(@typeId(AUnionEnum) == Tid.Union); | |
| 470 | assertOrPanic(@typeId(AUnion) == Tid.Union); | |
| 471 | assertOrPanic(@typeId(fn () void) == Tid.Fn); | |
| 472 | assertOrPanic(@typeId(@typeOf(builtin)) == Tid.Namespace); | |
| 473 | // TODO bound fn | |
| 474 | // TODO arg tuple | |
| 475 | // TODO opaque | |
| 476 | } | |
| 477 | } | |
| 478 | ||
| 479 | test "@typeName" { | |
| 480 | const Struct = struct {}; | |
| 481 | const Union = union { | |
| 482 | unused: u8, | |
| 483 | }; | |
| 484 | const Enum = enum { | |
| 485 | Unused, | |
| 486 | }; | |
| 487 | comptime { | |
| 488 | assertOrPanic(mem.eql(u8, @typeName(i64), "i64")); | |
| 489 | assertOrPanic(mem.eql(u8, @typeName(*usize), "*usize")); | |
| 490 | // https://github.com/ziglang/zig/issues/675 | |
| 491 | assertOrPanic(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)")); | |
| 492 | assertOrPanic(mem.eql(u8, @typeName(Struct), "Struct")); | |
| 493 | assertOrPanic(mem.eql(u8, @typeName(Union), "Union")); | |
| 494 | assertOrPanic(mem.eql(u8, @typeName(Enum), "Enum")); | |
| 495 | } | |
| 496 | } | |
| 497 | ||
| 498 | fn TypeFromFn(comptime T: type) type { | |
| 499 | return struct {}; | |
| 500 | } | |
| 501 | ||
| 502 | test "double implicit cast in same expression" { | |
| 503 | var x = i32(u16(nine())); | |
| 504 | assertOrPanic(x == 9); | |
| 505 | } | |
| 506 | fn nine() u8 { | |
| 507 | return 9; | |
| 508 | } | |
| 509 | ||
| 510 | test "global variable initialized to global variable array element" { | |
| 511 | assertOrPanic(global_ptr == &gdt[0]); | |
| 512 | } | |
| 513 | const GDTEntry = struct { | |
| 514 | field: i32, | |
| 515 | }; | |
| 516 | var gdt = []GDTEntry{ | |
| 517 | GDTEntry{ .field = 1 }, | |
| 518 | GDTEntry{ .field = 2 }, | |
| 519 | }; | |
| 520 | var global_ptr = &gdt[0]; | |
| 521 | ||
| 522 | // can't really run this test but we can make sure it has no compile error | |
| 523 | // and generates code | |
| 524 | const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000]; | |
| 525 | export fn writeToVRam() void { | |
| 526 | vram[0] = 'X'; | |
| 527 | } | |
| 528 | ||
| 529 | const OpaqueA = @OpaqueType(); | |
| 530 | const OpaqueB = @OpaqueType(); | |
| 531 | test "@OpaqueType" { | |
| 532 | assertOrPanic(*OpaqueA != *OpaqueB); | |
| 533 | assertOrPanic(mem.eql(u8, @typeName(OpaqueA), "OpaqueA")); | |
| 534 | assertOrPanic(mem.eql(u8, @typeName(OpaqueB), "OpaqueB")); | |
| 535 | } | |
| 536 | ||
| 537 | test "variable is allowed to be a pointer to an opaque type" { | |
| 538 | var x: i32 = 1234; | |
| 539 | _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x)); | |
| 540 | } | |
| 541 | fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA { | |
| 542 | var a = ptr; | |
| 543 | return a; | |
| 544 | } | |
| 545 | ||
| 546 | test "comptime if inside runtime while which unconditionally breaks" { | |
| 547 | testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | |
| 548 | comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); | |
| 549 | } | |
| 550 | fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { | |
| 551 | while (cond) { | |
| 552 | if (false) {} | |
| 553 | break; | |
| 554 | } | |
| 555 | } | |
| 556 | ||
| 557 | test "implicit comptime while" { | |
| 558 | while (false) { | |
| 559 | @compileError("bad"); | |
| 560 | } | |
| 561 | } | |
| 562 | ||
| 563 | fn fnThatClosesOverLocalConst() type { | |
| 564 | const c = 1; | |
| 565 | return struct { | |
| 566 | fn g() i32 { | |
| 567 | return c; | |
| 568 | } | |
| 569 | }; | |
| 570 | } | |
| 571 | ||
| 572 | test "function closes over local const" { | |
| 573 | const x = fnThatClosesOverLocalConst().g(); | |
| 574 | assertOrPanic(x == 1); | |
| 575 | } | |
| 576 | ||
| 577 | test "cold function" { | |
| 578 | thisIsAColdFn(); | |
| 579 | comptime thisIsAColdFn(); | |
| 580 | } | |
| 581 | ||
| 582 | fn thisIsAColdFn() void { | |
| 583 | @setCold(true); | |
| 584 | } | |
| 585 | ||
| 586 | const PackedStruct = packed struct { | |
| 587 | a: u8, | |
| 588 | b: u8, | |
| 589 | }; | |
| 590 | const PackedUnion = packed union { | |
| 591 | a: u8, | |
| 592 | b: u32, | |
| 593 | }; | |
| 594 | const PackedEnum = packed enum { | |
| 595 | A, | |
| 596 | B, | |
| 597 | }; | |
| 598 | ||
| 599 | test "packed struct, enum, union parameters in extern function" { | |
| 600 | testPackedStuff(&(PackedStruct{ | |
| 601 | .a = 1, | |
| 602 | .b = 2, | |
| 603 | }), &(PackedUnion{ .a = 1 }), PackedEnum.A); | |
| 604 | } | |
| 605 | ||
| 606 | export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {} | |
| 607 | ||
| 608 | test "slicing zero length array" { | |
| 609 | const s1 = ""[0..]; | |
| 610 | const s2 = ([]u32{})[0..]; | |
| 611 | assertOrPanic(s1.len == 0); | |
| 612 | assertOrPanic(s2.len == 0); | |
| 613 | assertOrPanic(mem.eql(u8, s1, "")); | |
| 614 | assertOrPanic(mem.eql(u32, s2, []u32{})); | |
| 615 | } | |
| 616 | ||
| 617 | const addr1 = @ptrCast(*const u8, emptyFn); | |
| 618 | test "comptime cast fn to ptr" { | |
| 619 | const addr2 = @ptrCast(*const u8, emptyFn); | |
| 620 | comptime assertOrPanic(addr1 == addr2); | |
| 621 | } | |
| 622 | ||
| 623 | test "equality compare fn ptrs" { | |
| 624 | var a = emptyFn; | |
| 625 | assertOrPanic(a == a); | |
| 626 | } | |
| 627 | ||
| 628 | test "self reference through fn ptr field" { | |
| 629 | const S = struct { | |
| 630 | const A = struct { | |
| 631 | f: fn (A) u8, | |
| 632 | }; | |
| 633 | ||
| 634 | fn foo(a: A) u8 { | |
| 635 | return 12; | |
| 636 | } | |
| 637 | }; | |
| 638 | var a: S.A = undefined; | |
| 639 | a.f = S.foo; | |
| 640 | assertOrPanic(a.f(a) == 12); | |
| 641 | } | |
| 642 | ||
| 643 | test "volatile load and store" { | |
| 644 | var number: i32 = 1234; | |
| 645 | const ptr = (*volatile i32)(&number); | |
| 646 | ptr.* += 1; | |
| 647 | assertOrPanic(ptr.* == 1235); | |
| 648 | } | |
| 649 | ||
| 650 | test "slice string literal has type []const u8" { | |
| 651 | comptime { | |
| 652 | assertOrPanic(@typeOf("aoeu"[0..]) == []const u8); | |
| 653 | const array = []i32{ 1, 2, 3, 4 }; | |
| 654 | assertOrPanic(@typeOf(array[0..]) == []const i32); | |
| 655 | } | |
| 656 | } | |
| 657 | ||
| 658 | test "pointer child field" { | |
| 659 | assertOrPanic((*u32).Child == u32); | |
| 660 | } | |
| 661 | ||
| 662 | test "struct inside function" { | |
| 663 | testStructInFn(); | |
| 664 | comptime testStructInFn(); | |
| 665 | } | |
| 666 | ||
| 667 | fn testStructInFn() void { | |
| 668 | const BlockKind = u32; | |
| 669 | ||
| 670 | const Block = struct { | |
| 671 | kind: BlockKind, | |
| 672 | }; | |
| 673 | ||
| 674 | var block = Block{ .kind = 1234 }; | |
| 675 | ||
| 676 | block.kind += 1; | |
| 677 | ||
| 678 | assertOrPanic(block.kind == 1235); | |
| 679 | } | |
| 680 | ||
| 681 | test "fn call returning scalar optional in equality expression" { | |
| 682 | assertOrPanic(getNull() == null); | |
| 683 | } | |
| 684 | ||
| 685 | fn getNull() ?*i32 { | |
| 686 | return null; | |
| 687 | } |
test/stage1/behavior/namespace_depends_on_compile_var/a.zig created+1| ... | ... | @@ -0,0 +1 @@ |
| 1 | pub const a_bool = true; |
test/stage1/behavior/namespace_depends_on_compile_var/b.zig created+1| ... | ... | @@ -0,0 +1 @@ |
| 1 | pub const a_bool = false; |
test/stage1/behavior/namespace_depends_on_compile_var/index.zig created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 3 | ||
| 4 | test "namespace depends on compile var" { | |
| 5 | if (some_namespace.a_bool) { | |
| 6 | assertOrPanic(some_namespace.a_bool); | |
| 7 | } else { | |
| 8 | assertOrPanic(!some_namespace.a_bool); | |
| 9 | } | |
| 10 | } | |
| 11 | const some_namespace = switch (builtin.os) { | |
| 12 | builtin.Os.linux => @import("a.zig"), | |
| 13 | else => @import("b.zig"), | |
| 14 | }; |
test/stage1/behavior/new_stack_call.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | ||
| 4 | var new_stack_bytes: [1024]u8 = undefined; | |
| 5 | ||
| 6 | test "calling a function with a new stack" { | |
| 7 | const arg = 1234; | |
| 8 | ||
| 9 | const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg); | |
| 10 | const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg); | |
| 11 | _ = targetFunction(arg); | |
| 12 | ||
| 13 | assertOrPanic(arg == 1234); | |
| 14 | assertOrPanic(a < b); | |
| 15 | } | |
| 16 | ||
| 17 | fn targetFunction(x: i32) usize { | |
| 18 | assertOrPanic(x == 1234); | |
| 19 | ||
| 20 | var local_variable: i32 = 42; | |
| 21 | const ptr = &local_variable; | |
| 22 | ptr.* += 1; | |
| 23 | ||
| 24 | assertOrPanic(local_variable == 43); | |
| 25 | return @ptrToInt(ptr); | |
| 26 | } |
test/stage1/behavior/null.zig created+162| ... | ... | @@ -0,0 +1,162 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "optional type" { | |
| 4 | const x: ?bool = true; | |
| 5 | ||
| 6 | if (x) |y| { | |
| 7 | if (y) { | |
| 8 | // OK | |
| 9 | } else { | |
| 10 | unreachable; | |
| 11 | } | |
| 12 | } else { | |
| 13 | unreachable; | |
| 14 | } | |
| 15 | ||
| 16 | const next_x: ?i32 = null; | |
| 17 | ||
| 18 | const z = next_x orelse 1234; | |
| 19 | ||
| 20 | assertOrPanic(z == 1234); | |
| 21 | ||
| 22 | const final_x: ?i32 = 13; | |
| 23 | ||
| 24 | const num = final_x orelse unreachable; | |
| 25 | ||
| 26 | assertOrPanic(num == 13); | |
| 27 | } | |
| 28 | ||
| 29 | test "test maybe object and get a pointer to the inner value" { | |
| 30 | var maybe_bool: ?bool = true; | |
| 31 | ||
| 32 | if (maybe_bool) |*b| { | |
| 33 | b.* = false; | |
| 34 | } | |
| 35 | ||
| 36 | assertOrPanic(maybe_bool.? == false); | |
| 37 | } | |
| 38 | ||
| 39 | test "rhs maybe unwrap return" { | |
| 40 | const x: ?bool = true; | |
| 41 | const y = x orelse return; | |
| 42 | } | |
| 43 | ||
| 44 | test "maybe return" { | |
| 45 | maybeReturnImpl(); | |
| 46 | comptime maybeReturnImpl(); | |
| 47 | } | |
| 48 | ||
| 49 | fn maybeReturnImpl() void { | |
| 50 | assertOrPanic(foo(1235).?); | |
| 51 | if (foo(null) != null) unreachable; | |
| 52 | assertOrPanic(!foo(1234).?); | |
| 53 | } | |
| 54 | ||
| 55 | fn foo(x: ?i32) ?bool { | |
| 56 | const value = x orelse return null; | |
| 57 | return value > 1234; | |
| 58 | } | |
| 59 | ||
| 60 | test "if var maybe pointer" { | |
| 61 | assertOrPanic(shouldBeAPlus1(Particle{ | |
| 62 | .a = 14, | |
| 63 | .b = 1, | |
| 64 | .c = 1, | |
| 65 | .d = 1, | |
| 66 | }) == 15); | |
| 67 | } | |
| 68 | fn shouldBeAPlus1(p: Particle) u64 { | |
| 69 | var maybe_particle: ?Particle = p; | |
| 70 | if (maybe_particle) |*particle| { | |
| 71 | particle.a += 1; | |
| 72 | } | |
| 73 | if (maybe_particle) |particle| { | |
| 74 | return particle.a; | |
| 75 | } | |
| 76 | return 0; | |
| 77 | } | |
| 78 | const Particle = struct { | |
| 79 | a: u64, | |
| 80 | b: u64, | |
| 81 | c: u64, | |
| 82 | d: u64, | |
| 83 | }; | |
| 84 | ||
| 85 | test "null literal outside function" { | |
| 86 | const is_null = here_is_a_null_literal.context == null; | |
| 87 | assertOrPanic(is_null); | |
| 88 | ||
| 89 | const is_non_null = here_is_a_null_literal.context != null; | |
| 90 | assertOrPanic(!is_non_null); | |
| 91 | } | |
| 92 | const SillyStruct = struct { | |
| 93 | context: ?i32, | |
| 94 | }; | |
| 95 | const here_is_a_null_literal = SillyStruct{ .context = null }; | |
| 96 | ||
| 97 | test "test null runtime" { | |
| 98 | testTestNullRuntime(null); | |
| 99 | } | |
| 100 | fn testTestNullRuntime(x: ?i32) void { | |
| 101 | assertOrPanic(x == null); | |
| 102 | assertOrPanic(!(x != null)); | |
| 103 | } | |
| 104 | ||
| 105 | test "optional void" { | |
| 106 | optionalVoidImpl(); | |
| 107 | comptime optionalVoidImpl(); | |
| 108 | } | |
| 109 | ||
| 110 | fn optionalVoidImpl() void { | |
| 111 | assertOrPanic(bar(null) == null); | |
| 112 | assertOrPanic(bar({}) != null); | |
| 113 | } | |
| 114 | ||
| 115 | fn bar(x: ?void) ?void { | |
| 116 | if (x) |_| { | |
| 117 | return {}; | |
| 118 | } else { | |
| 119 | return null; | |
| 120 | } | |
| 121 | } | |
| 122 | ||
| 123 | const StructWithOptional = struct { | |
| 124 | field: ?i32, | |
| 125 | }; | |
| 126 | ||
| 127 | var struct_with_optional: StructWithOptional = undefined; | |
| 128 | ||
| 129 | test "unwrap optional which is field of global var" { | |
| 130 | struct_with_optional.field = null; | |
| 131 | if (struct_with_optional.field) |payload| { | |
| 132 | unreachable; | |
| 133 | } | |
| 134 | struct_with_optional.field = 1234; | |
| 135 | if (struct_with_optional.field) |payload| { | |
| 136 | assertOrPanic(payload == 1234); | |
| 137 | } else { | |
| 138 | unreachable; | |
| 139 | } | |
| 140 | } | |
| 141 | ||
| 142 | test "null with default unwrap" { | |
| 143 | const x: i32 = null orelse 1; | |
| 144 | assertOrPanic(x == 1); | |
| 145 | } | |
| 146 | ||
| 147 | test "optional types" { | |
| 148 | comptime { | |
| 149 | const opt_type_struct = StructWithOptionalType{ .t = u8 }; | |
| 150 | assertOrPanic(opt_type_struct.t != null and opt_type_struct.t.? == u8); | |
| 151 | } | |
| 152 | } | |
| 153 | ||
| 154 | const StructWithOptionalType = struct { | |
| 155 | t: ?type, | |
| 156 | }; | |
| 157 | ||
| 158 | test "optional pointer to 0 bit type null value at runtime" { | |
| 159 | const EmptyStruct = struct {}; | |
| 160 | var x: ?*EmptyStruct = null; | |
| 161 | assertOrPanic(x == null); | |
| 162 | } |
test/stage1/behavior/optional.zig created+81| ... | ... | @@ -0,0 +1,81 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | pub const EmptyStruct = struct {}; | |
| 4 | ||
| 5 | test "optional pointer to size zero struct" { | |
| 6 | var e = EmptyStruct{}; | |
| 7 | var o: ?*EmptyStruct = &e; | |
| 8 | assertOrPanic(o != null); | |
| 9 | } | |
| 10 | ||
| 11 | test "equality compare nullable pointers" { | |
| 12 | testNullPtrsEql(); | |
| 13 | comptime testNullPtrsEql(); | |
| 14 | } | |
| 15 | ||
| 16 | fn testNullPtrsEql() void { | |
| 17 | var number: i32 = 1234; | |
| 18 | ||
| 19 | var x: ?*i32 = null; | |
| 20 | var y: ?*i32 = null; | |
| 21 | assertOrPanic(x == y); | |
| 22 | y = &number; | |
| 23 | assertOrPanic(x != y); | |
| 24 | assertOrPanic(x != &number); | |
| 25 | assertOrPanic(&number != x); | |
| 26 | x = &number; | |
| 27 | assertOrPanic(x == y); | |
| 28 | assertOrPanic(x == &number); | |
| 29 | assertOrPanic(&number == x); | |
| 30 | } | |
| 31 | ||
| 32 | test "address of unwrap optional" { | |
| 33 | const S = struct { | |
| 34 | const Foo = struct { | |
| 35 | a: i32, | |
| 36 | }; | |
| 37 | ||
| 38 | var global: ?Foo = null; | |
| 39 | ||
| 40 | pub fn getFoo() anyerror!*Foo { | |
| 41 | return &global.?; | |
| 42 | } | |
| 43 | }; | |
| 44 | S.global = S.Foo{ .a = 1234 }; | |
| 45 | const foo = S.getFoo() catch unreachable; | |
| 46 | assertOrPanic(foo.a == 1234); | |
| 47 | } | |
| 48 | ||
| 49 | test "passing an optional integer as a parameter" { | |
| 50 | const S = struct { | |
| 51 | fn entry() bool { | |
| 52 | var x: i32 = 1234; | |
| 53 | return foo(x); | |
| 54 | } | |
| 55 | ||
| 56 | fn foo(x: ?i32) bool { | |
| 57 | return x.? == 1234; | |
| 58 | } | |
| 59 | }; | |
| 60 | assertOrPanic(S.entry()); | |
| 61 | comptime assertOrPanic(S.entry()); | |
| 62 | } | |
| 63 | ||
| 64 | test "unwrap function call with optional pointer return value" { | |
| 65 | const S = struct { | |
| 66 | fn entry() void { | |
| 67 | assertOrPanic(foo().?.* == 1234); | |
| 68 | assertOrPanic(bar() == null); | |
| 69 | } | |
| 70 | const global: i32 = 1234; | |
| 71 | fn foo() ?*const i32 { | |
| 72 | return &global; | |
| 73 | } | |
| 74 | fn bar() ?*i32 { | |
| 75 | return null; | |
| 76 | } | |
| 77 | }; | |
| 78 | S.entry(); | |
| 79 | // TODO https://github.com/ziglang/zig/issues/1901 | |
| 80 | //comptime S.entry(); | |
| 81 | } |
test/stage1/behavior/pointers.zig created+44| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | ||
| 4 | test "dereference pointer" { | |
| 5 | comptime testDerefPtr(); | |
| 6 | testDerefPtr(); | |
| 7 | } | |
| 8 | ||
| 9 | fn testDerefPtr() void { | |
| 10 | var x: i32 = 1234; | |
| 11 | var y = &x; | |
| 12 | y.* += 1; | |
| 13 | assertOrPanic(x == 1235); | |
| 14 | } | |
| 15 | ||
| 16 | test "pointer arithmetic" { | |
| 17 | var ptr = c"abcd"; | |
| 18 | ||
| 19 | assertOrPanic(ptr[0] == 'a'); | |
| 20 | ptr += 1; | |
| 21 | assertOrPanic(ptr[0] == 'b'); | |
| 22 | ptr += 1; | |
| 23 | assertOrPanic(ptr[0] == 'c'); | |
| 24 | ptr += 1; | |
| 25 | assertOrPanic(ptr[0] == 'd'); | |
| 26 | ptr += 1; | |
| 27 | assertOrPanic(ptr[0] == 0); | |
| 28 | ptr -= 1; | |
| 29 | assertOrPanic(ptr[0] == 'd'); | |
| 30 | ptr -= 1; | |
| 31 | assertOrPanic(ptr[0] == 'c'); | |
| 32 | ptr -= 1; | |
| 33 | assertOrPanic(ptr[0] == 'b'); | |
| 34 | ptr -= 1; | |
| 35 | assertOrPanic(ptr[0] == 'a'); | |
| 36 | } | |
| 37 | ||
| 38 | test "double pointer parsing" { | |
| 39 | comptime assertOrPanic(PtrOf(PtrOf(i32)) == **i32); | |
| 40 | } | |
| 41 | ||
| 42 | fn PtrOf(comptime T: type) type { | |
| 43 | return *T; | |
| 44 | } |
test/stage1/behavior/popcount.zig created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "@popCount" { | |
| 4 | comptime testPopCount(); | |
| 5 | testPopCount(); | |
| 6 | } | |
| 7 | ||
| 8 | fn testPopCount() void { | |
| 9 | { | |
| 10 | var x: u32 = 0xaa; | |
| 11 | assertOrPanic(@popCount(x) == 4); | |
| 12 | } | |
| 13 | { | |
| 14 | var x: u32 = 0xaaaaaaaa; | |
| 15 | assertOrPanic(@popCount(x) == 16); | |
| 16 | } | |
| 17 | { | |
| 18 | var x: i16 = -1; | |
| 19 | assertOrPanic(@popCount(x) == 16); | |
| 20 | } | |
| 21 | comptime { | |
| 22 | assertOrPanic(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24); | |
| 23 | } | |
| 24 | } | |
| 25 |
test/stage1/behavior/ptrcast.zig created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const std = @import("std"); | |
| 3 | const assertOrPanic = std.debug.assertOrPanic; | |
| 4 | ||
| 5 | test "reinterpret bytes as integer with nonzero offset" { | |
| 6 | testReinterpretBytesAsInteger(); | |
| 7 | comptime testReinterpretBytesAsInteger(); | |
| 8 | } | |
| 9 | ||
| 10 | fn testReinterpretBytesAsInteger() void { | |
| 11 | const bytes = "\x12\x34\x56\x78\xab"; | |
| 12 | const expected = switch (builtin.endian) { | |
| 13 | builtin.Endian.Little => 0xab785634, | |
| 14 | builtin.Endian.Big => 0x345678ab, | |
| 15 | }; | |
| 16 | assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected); | |
| 17 | } | |
| 18 | ||
| 19 | test "reinterpret bytes of an array into an extern struct" { | |
| 20 | testReinterpretBytesAsExternStruct(); | |
| 21 | comptime testReinterpretBytesAsExternStruct(); | |
| 22 | } | |
| 23 | ||
| 24 | fn testReinterpretBytesAsExternStruct() void { | |
| 25 | var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 }; | |
| 26 | ||
| 27 | const S = extern struct { | |
| 28 | a: u8, | |
| 29 | b: u16, | |
| 30 | c: u8, | |
| 31 | }; | |
| 32 | ||
| 33 | var ptr = @ptrCast(*const S, &bytes); | |
| 34 | var val = ptr.c; | |
| 35 | assertOrPanic(val == 5); | |
| 36 | } | |
| 37 | ||
| 38 | test "reinterpret struct field at comptime" { | |
| 39 | const numLittle = comptime Bytes.init(0x12345678); | |
| 40 | assertOrPanic(std.mem.eql(u8, []u8{ 0x78, 0x56, 0x34, 0x12 }, numLittle.bytes)); | |
| 41 | } | |
| 42 | ||
| 43 | const Bytes = struct { | |
| 44 | bytes: [4]u8, | |
| 45 | ||
| 46 | pub fn init(v: u32) Bytes { | |
| 47 | var res: Bytes = undefined; | |
| 48 | @ptrCast(*align(1) u32, &res.bytes).* = v; | |
| 49 | ||
| 50 | return res; | |
| 51 | } | |
| 52 | }; |
test/stage1/behavior/pub_enum/index.zig created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | const other = @import("other.zig"); | |
| 2 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 3 | ||
| 4 | test "pub enum" { | |
| 5 | pubEnumTest(other.APubEnum.Two); | |
| 6 | } | |
| 7 | fn pubEnumTest(foo: other.APubEnum) void { | |
| 8 | assertOrPanic(foo == other.APubEnum.Two); | |
| 9 | } | |
| 10 | ||
| 11 | test "cast with imported symbol" { | |
| 12 | assertOrPanic(other.size_t(42) == 42); | |
| 13 | } |
test/stage1/behavior/pub_enum/other.zig created+6| ... | ... | @@ -0,0 +1,6 @@ |
| 1 | pub const APubEnum = enum { | |
| 2 | One, | |
| 3 | Two, | |
| 4 | Three, | |
| 5 | }; | |
| 6 | pub const size_t = u64; |
test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | const mem = @import("std").mem; | |
| 3 | ||
| 4 | var ok: bool = false; | |
| 5 | test "reference a variable in an if after an if in the 2nd switch prong" { | |
| 6 | foo(true, Num.Two, false, "aoeu"); | |
| 7 | assertOrPanic(!ok); | |
| 8 | foo(false, Num.One, false, "aoeu"); | |
| 9 | assertOrPanic(!ok); | |
| 10 | foo(true, Num.One, false, "aoeu"); | |
| 11 | assertOrPanic(ok); | |
| 12 | } | |
| 13 | ||
| 14 | const Num = enum { | |
| 15 | One, | |
| 16 | Two, | |
| 17 | }; | |
| 18 | ||
| 19 | fn foo(c: bool, k: Num, c2: bool, b: []const u8) void { | |
| 20 | switch (k) { | |
| 21 | Num.Two => {}, | |
| 22 | Num.One => { | |
| 23 | if (c) { | |
| 24 | const output_path = b; | |
| 25 | ||
| 26 | if (c2) {} | |
| 27 | ||
| 28 | a(output_path); | |
| 29 | } | |
| 30 | }, | |
| 31 | } | |
| 32 | } | |
| 33 | ||
| 34 | fn a(x: []const u8) void { | |
| 35 | assertOrPanic(mem.eql(u8, x, "aoeu")); | |
| 36 | ok = true; | |
| 37 | } |
test/stage1/behavior/reflection.zig created+96| ... | ... | @@ -0,0 +1,96 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | const mem = @import("std").mem; | |
| 3 | const reflection = @This(); | |
| 4 | ||
| 5 | test "reflection: array, pointer, optional, error union type child" { | |
| 6 | comptime { | |
| 7 | assertOrPanic(([10]u8).Child == u8); | |
| 8 | assertOrPanic((*u8).Child == u8); | |
| 9 | assertOrPanic((anyerror!u8).Payload == u8); | |
| 10 | assertOrPanic((?u8).Child == u8); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | test "reflection: function return type, var args, and param types" { | |
| 15 | comptime { | |
| 16 | assertOrPanic(@typeOf(dummy).ReturnType == i32); | |
| 17 | assertOrPanic(!@typeOf(dummy).is_var_args); | |
| 18 | assertOrPanic(@typeOf(dummy_varargs).is_var_args); | |
| 19 | assertOrPanic(@typeOf(dummy).arg_count == 3); | |
| 20 | assertOrPanic(@ArgType(@typeOf(dummy), 0) == bool); | |
| 21 | assertOrPanic(@ArgType(@typeOf(dummy), 1) == i32); | |
| 22 | assertOrPanic(@ArgType(@typeOf(dummy), 2) == f32); | |
| 23 | } | |
| 24 | } | |
| 25 | ||
| 26 | fn dummy(a: bool, b: i32, c: f32) i32 { | |
| 27 | return 1234; | |
| 28 | } | |
| 29 | fn dummy_varargs(args: ...) void {} | |
| 30 | ||
| 31 | test "reflection: struct member types and names" { | |
| 32 | comptime { | |
| 33 | assertOrPanic(@memberCount(Foo) == 3); | |
| 34 | ||
| 35 | assertOrPanic(@memberType(Foo, 0) == i32); | |
| 36 | assertOrPanic(@memberType(Foo, 1) == bool); | |
| 37 | assertOrPanic(@memberType(Foo, 2) == void); | |
| 38 | ||
| 39 | assertOrPanic(mem.eql(u8, @memberName(Foo, 0), "one")); | |
| 40 | assertOrPanic(mem.eql(u8, @memberName(Foo, 1), "two")); | |
| 41 | assertOrPanic(mem.eql(u8, @memberName(Foo, 2), "three")); | |
| 42 | } | |
| 43 | } | |
| 44 | ||
| 45 | test "reflection: enum member types and names" { | |
| 46 | comptime { | |
| 47 | assertOrPanic(@memberCount(Bar) == 4); | |
| 48 | ||
| 49 | assertOrPanic(@memberType(Bar, 0) == void); | |
| 50 | assertOrPanic(@memberType(Bar, 1) == i32); | |
| 51 | assertOrPanic(@memberType(Bar, 2) == bool); | |
| 52 | assertOrPanic(@memberType(Bar, 3) == f64); | |
| 53 | ||
| 54 | assertOrPanic(mem.eql(u8, @memberName(Bar, 0), "One")); | |
| 55 | assertOrPanic(mem.eql(u8, @memberName(Bar, 1), "Two")); | |
| 56 | assertOrPanic(mem.eql(u8, @memberName(Bar, 2), "Three")); | |
| 57 | assertOrPanic(mem.eql(u8, @memberName(Bar, 3), "Four")); | |
| 58 | } | |
| 59 | } | |
| 60 | ||
| 61 | test "reflection: @field" { | |
| 62 | var f = Foo{ | |
| 63 | .one = 42, | |
| 64 | .two = true, | |
| 65 | .three = void{}, | |
| 66 | }; | |
| 67 | ||
| 68 | assertOrPanic(f.one == f.one); | |
| 69 | assertOrPanic(@field(f, "o" ++ "ne") == f.one); | |
| 70 | assertOrPanic(@field(f, "t" ++ "wo") == f.two); | |
| 71 | assertOrPanic(@field(f, "th" ++ "ree") == f.three); | |
| 72 | assertOrPanic(@field(Foo, "const" ++ "ant") == Foo.constant); | |
| 73 | assertOrPanic(@field(Bar, "O" ++ "ne") == Bar.One); | |
| 74 | assertOrPanic(@field(Bar, "T" ++ "wo") == Bar.Two); | |
| 75 | assertOrPanic(@field(Bar, "Th" ++ "ree") == Bar.Three); | |
| 76 | assertOrPanic(@field(Bar, "F" ++ "our") == Bar.Four); | |
| 77 | assertOrPanic(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2)); | |
| 78 | @field(f, "o" ++ "ne") = 4; | |
| 79 | assertOrPanic(f.one == 4); | |
| 80 | } | |
| 81 | ||
| 82 | const Foo = struct { | |
| 83 | const constant = 52; | |
| 84 | ||
| 85 | one: i32, | |
| 86 | two: bool, | |
| 87 | three: void, | |
| 88 | }; | |
| 89 | ||
| 90 | const Bar = union(enum) { | |
| 91 | One: void, | |
| 92 | Two: i32, | |
| 93 | Three: bool, | |
| 94 | Four: f64, | |
| 95 | }; | |
| 96 |
test/stage1/behavior/sizeof_and_typeof.zig created+69| ... | ... | @@ -0,0 +1,69 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 3 | ||
| 4 | test "@sizeOf and @typeOf" { | |
| 5 | const y: @typeOf(x) = 120; | |
| 6 | assertOrPanic(@sizeOf(@typeOf(y)) == 2); | |
| 7 | } | |
| 8 | const x: u16 = 13; | |
| 9 | const z: @typeOf(x) = 19; | |
| 10 | ||
| 11 | const A = struct { | |
| 12 | a: u8, | |
| 13 | b: u32, | |
| 14 | c: u8, | |
| 15 | d: u3, | |
| 16 | e: u5, | |
| 17 | f: u16, | |
| 18 | g: u16, | |
| 19 | }; | |
| 20 | ||
| 21 | const P = packed struct { | |
| 22 | a: u8, | |
| 23 | b: u32, | |
| 24 | c: u8, | |
| 25 | d: u3, | |
| 26 | e: u5, | |
| 27 | f: u16, | |
| 28 | g: u16, | |
| 29 | }; | |
| 30 | ||
| 31 | test "@byteOffsetOf" { | |
| 32 | // Packed structs have fixed memory layout | |
| 33 | assertOrPanic(@byteOffsetOf(P, "a") == 0); | |
| 34 | assertOrPanic(@byteOffsetOf(P, "b") == 1); | |
| 35 | assertOrPanic(@byteOffsetOf(P, "c") == 5); | |
| 36 | assertOrPanic(@byteOffsetOf(P, "d") == 6); | |
| 37 | assertOrPanic(@byteOffsetOf(P, "e") == 6); | |
| 38 | assertOrPanic(@byteOffsetOf(P, "f") == 7); | |
| 39 | assertOrPanic(@byteOffsetOf(P, "g") == 9); | |
| 40 | ||
| 41 | // Normal struct fields can be moved/padded | |
| 42 | var a: A = undefined; | |
| 43 | assertOrPanic(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a")); | |
| 44 | assertOrPanic(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b")); | |
| 45 | assertOrPanic(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c")); | |
| 46 | assertOrPanic(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d")); | |
| 47 | assertOrPanic(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e")); | |
| 48 | assertOrPanic(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f")); | |
| 49 | assertOrPanic(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g")); | |
| 50 | } | |
| 51 | ||
| 52 | test "@bitOffsetOf" { | |
| 53 | // Packed structs have fixed memory layout | |
| 54 | assertOrPanic(@bitOffsetOf(P, "a") == 0); | |
| 55 | assertOrPanic(@bitOffsetOf(P, "b") == 8); | |
| 56 | assertOrPanic(@bitOffsetOf(P, "c") == 40); | |
| 57 | assertOrPanic(@bitOffsetOf(P, "d") == 48); | |
| 58 | assertOrPanic(@bitOffsetOf(P, "e") == 51); | |
| 59 | assertOrPanic(@bitOffsetOf(P, "f") == 56); | |
| 60 | assertOrPanic(@bitOffsetOf(P, "g") == 72); | |
| 61 | ||
| 62 | assertOrPanic(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a")); | |
| 63 | assertOrPanic(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b")); | |
| 64 | assertOrPanic(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c")); | |
| 65 | assertOrPanic(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d")); | |
| 66 | assertOrPanic(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e")); | |
| 67 | assertOrPanic(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f")); | |
| 68 | assertOrPanic(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g")); | |
| 69 | } |
test/stage1/behavior/slice.zig created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | const mem = @import("std").mem; | |
| 3 | ||
| 4 | const x = @intToPtr([*]i32, 0x1000)[0..0x500]; | |
| 5 | const y = x[0x100..]; | |
| 6 | test "compile time slice of pointer to hard coded address" { | |
| 7 | assertOrPanic(@ptrToInt(x.ptr) == 0x1000); | |
| 8 | assertOrPanic(x.len == 0x500); | |
| 9 | ||
| 10 | assertOrPanic(@ptrToInt(y.ptr) == 0x1100); | |
| 11 | assertOrPanic(y.len == 0x400); | |
| 12 | } | |
| 13 | ||
| 14 | test "slice child property" { | |
| 15 | var array: [5]i32 = undefined; | |
| 16 | var slice = array[0..]; | |
| 17 | assertOrPanic(@typeOf(slice).Child == i32); | |
| 18 | } | |
| 19 | ||
| 20 | test "runtime safety lets us slice from len..len" { | |
| 21 | var an_array = []u8{ | |
| 22 | 1, | |
| 23 | 2, | |
| 24 | 3, | |
| 25 | }; | |
| 26 | assertOrPanic(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), "")); | |
| 27 | } | |
| 28 | ||
| 29 | fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 { | |
| 30 | return a_slice[start..end]; | |
| 31 | } | |
| 32 | ||
| 33 | test "implicitly cast array of size 0 to slice" { | |
| 34 | var msg = []u8{}; | |
| 35 | assertLenIsZero(msg); | |
| 36 | } | |
| 37 | ||
| 38 | fn assertLenIsZero(msg: []const u8) void { | |
| 39 | assertOrPanic(msg.len == 0); | |
| 40 | } |
test/stage1/behavior/struct.zig created+470| ... | ... | @@ -0,0 +1,470 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | const maxInt = std.math.maxInt; | |
| 5 | ||
| 6 | const StructWithNoFields = struct { | |
| 7 | fn add(a: i32, b: i32) i32 { | |
| 8 | return a + b; | |
| 9 | } | |
| 10 | }; | |
| 11 | const empty_global_instance = StructWithNoFields{}; | |
| 12 | ||
| 13 | test "call struct static method" { | |
| 14 | const result = StructWithNoFields.add(3, 4); | |
| 15 | assertOrPanic(result == 7); | |
| 16 | } | |
| 17 | ||
| 18 | test "return empty struct instance" { | |
| 19 | _ = returnEmptyStructInstance(); | |
| 20 | } | |
| 21 | fn returnEmptyStructInstance() StructWithNoFields { | |
| 22 | return empty_global_instance; | |
| 23 | } | |
| 24 | ||
| 25 | const should_be_11 = StructWithNoFields.add(5, 6); | |
| 26 | ||
| 27 | test "invoke static method in global scope" { | |
| 28 | assertOrPanic(should_be_11 == 11); | |
| 29 | } | |
| 30 | ||
| 31 | test "void struct fields" { | |
| 32 | const foo = VoidStructFieldsFoo{ | |
| 33 | .a = void{}, | |
| 34 | .b = 1, | |
| 35 | .c = void{}, | |
| 36 | }; | |
| 37 | assertOrPanic(foo.b == 1); | |
| 38 | assertOrPanic(@sizeOf(VoidStructFieldsFoo) == 4); | |
| 39 | } | |
| 40 | const VoidStructFieldsFoo = struct { | |
| 41 | a: void, | |
| 42 | b: i32, | |
| 43 | c: void, | |
| 44 | }; | |
| 45 | ||
| 46 | test "structs" { | |
| 47 | var foo: StructFoo = undefined; | |
| 48 | @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo)); | |
| 49 | foo.a += 1; | |
| 50 | foo.b = foo.a == 1; | |
| 51 | testFoo(foo); | |
| 52 | testMutation(&foo); | |
| 53 | assertOrPanic(foo.c == 100); | |
| 54 | } | |
| 55 | const StructFoo = struct { | |
| 56 | a: i32, | |
| 57 | b: bool, | |
| 58 | c: f32, | |
| 59 | }; | |
| 60 | fn testFoo(foo: StructFoo) void { | |
| 61 | assertOrPanic(foo.b); | |
| 62 | } | |
| 63 | fn testMutation(foo: *StructFoo) void { | |
| 64 | foo.c = 100; | |
| 65 | } | |
| 66 | ||
| 67 | const Node = struct { | |
| 68 | val: Val, | |
| 69 | next: *Node, | |
| 70 | }; | |
| 71 | ||
| 72 | const Val = struct { | |
| 73 | x: i32, | |
| 74 | }; | |
| 75 | ||
| 76 | test "struct point to self" { | |
| 77 | var root: Node = undefined; | |
| 78 | root.val.x = 1; | |
| 79 | ||
| 80 | var node: Node = undefined; | |
| 81 | node.next = &root; | |
| 82 | node.val.x = 2; | |
| 83 | ||
| 84 | root.next = &node; | |
| 85 | ||
| 86 | assertOrPanic(node.next.next.next.val.x == 1); | |
| 87 | } | |
| 88 | ||
| 89 | test "struct byval assign" { | |
| 90 | var foo1: StructFoo = undefined; | |
| 91 | var foo2: StructFoo = undefined; | |
| 92 | ||
| 93 | foo1.a = 1234; | |
| 94 | foo2.a = 0; | |
| 95 | assertOrPanic(foo2.a == 0); | |
| 96 | foo2 = foo1; | |
| 97 | assertOrPanic(foo2.a == 1234); | |
| 98 | } | |
| 99 | ||
| 100 | fn structInitializer() void { | |
| 101 | const val = Val{ .x = 42 }; | |
| 102 | assertOrPanic(val.x == 42); | |
| 103 | } | |
| 104 | ||
| 105 | test "fn call of struct field" { | |
| 106 | assertOrPanic(callStructField(Foo{ .ptr = aFunc }) == 13); | |
| 107 | } | |
| 108 | ||
| 109 | const Foo = struct { | |
| 110 | ptr: fn () i32, | |
| 111 | }; | |
| 112 | ||
| 113 | fn aFunc() i32 { | |
| 114 | return 13; | |
| 115 | } | |
| 116 | ||
| 117 | fn callStructField(foo: Foo) i32 { | |
| 118 | return foo.ptr(); | |
| 119 | } | |
| 120 | ||
| 121 | test "store member function in variable" { | |
| 122 | const instance = MemberFnTestFoo{ .x = 1234 }; | |
| 123 | const memberFn = MemberFnTestFoo.member; | |
| 124 | const result = memberFn(instance); | |
| 125 | assertOrPanic(result == 1234); | |
| 126 | } | |
| 127 | const MemberFnTestFoo = struct { | |
| 128 | x: i32, | |
| 129 | fn member(foo: MemberFnTestFoo) i32 { | |
| 130 | return foo.x; | |
| 131 | } | |
| 132 | }; | |
| 133 | ||
| 134 | test "call member function directly" { | |
| 135 | const instance = MemberFnTestFoo{ .x = 1234 }; | |
| 136 | const result = MemberFnTestFoo.member(instance); | |
| 137 | assertOrPanic(result == 1234); | |
| 138 | } | |
| 139 | ||
| 140 | test "member functions" { | |
| 141 | const r = MemberFnRand{ .seed = 1234 }; | |
| 142 | assertOrPanic(r.getSeed() == 1234); | |
| 143 | } | |
| 144 | const MemberFnRand = struct { | |
| 145 | seed: u32, | |
| 146 | pub fn getSeed(r: *const MemberFnRand) u32 { | |
| 147 | return r.seed; | |
| 148 | } | |
| 149 | }; | |
| 150 | ||
| 151 | test "return struct byval from function" { | |
| 152 | const bar = makeBar(1234, 5678); | |
| 153 | assertOrPanic(bar.y == 5678); | |
| 154 | } | |
| 155 | const Bar = struct { | |
| 156 | x: i32, | |
| 157 | y: i32, | |
| 158 | }; | |
| 159 | fn makeBar(x: i32, y: i32) Bar { | |
| 160 | return Bar{ | |
| 161 | .x = x, | |
| 162 | .y = y, | |
| 163 | }; | |
| 164 | } | |
| 165 | ||
| 166 | test "empty struct method call" { | |
| 167 | const es = EmptyStruct{}; | |
| 168 | assertOrPanic(es.method() == 1234); | |
| 169 | } | |
| 170 | const EmptyStruct = struct { | |
| 171 | fn method(es: *const EmptyStruct) i32 { | |
| 172 | return 1234; | |
| 173 | } | |
| 174 | }; | |
| 175 | ||
| 176 | test "return empty struct from fn" { | |
| 177 | _ = testReturnEmptyStructFromFn(); | |
| 178 | } | |
| 179 | const EmptyStruct2 = struct {}; | |
| 180 | fn testReturnEmptyStructFromFn() EmptyStruct2 { | |
| 181 | return EmptyStruct2{}; | |
| 182 | } | |
| 183 | ||
| 184 | test "pass slice of empty struct to fn" { | |
| 185 | assertOrPanic(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1); | |
| 186 | } | |
| 187 | fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize { | |
| 188 | return slice.len; | |
| 189 | } | |
| 190 | ||
| 191 | const APackedStruct = packed struct { | |
| 192 | x: u8, | |
| 193 | y: u8, | |
| 194 | }; | |
| 195 | ||
| 196 | test "packed struct" { | |
| 197 | var foo = APackedStruct{ | |
| 198 | .x = 1, | |
| 199 | .y = 2, | |
| 200 | }; | |
| 201 | foo.y += 1; | |
| 202 | const four = foo.x + foo.y; | |
| 203 | assertOrPanic(four == 4); | |
| 204 | } | |
| 205 | ||
| 206 | const BitField1 = packed struct { | |
| 207 | a: u3, | |
| 208 | b: u3, | |
| 209 | c: u2, | |
| 210 | }; | |
| 211 | ||
| 212 | const bit_field_1 = BitField1{ | |
| 213 | .a = 1, | |
| 214 | .b = 2, | |
| 215 | .c = 3, | |
| 216 | }; | |
| 217 | ||
| 218 | test "bit field access" { | |
| 219 | var data = bit_field_1; | |
| 220 | assertOrPanic(getA(&data) == 1); | |
| 221 | assertOrPanic(getB(&data) == 2); | |
| 222 | assertOrPanic(getC(&data) == 3); | |
| 223 | comptime assertOrPanic(@sizeOf(BitField1) == 1); | |
| 224 | ||
| 225 | data.b += 1; | |
| 226 | assertOrPanic(data.b == 3); | |
| 227 | ||
| 228 | data.a += 1; | |
| 229 | assertOrPanic(data.a == 2); | |
| 230 | assertOrPanic(data.b == 3); | |
| 231 | } | |
| 232 | ||
| 233 | fn getA(data: *const BitField1) u3 { | |
| 234 | return data.a; | |
| 235 | } | |
| 236 | ||
| 237 | fn getB(data: *const BitField1) u3 { | |
| 238 | return data.b; | |
| 239 | } | |
| 240 | ||
| 241 | fn getC(data: *const BitField1) u2 { | |
| 242 | return data.c; | |
| 243 | } | |
| 244 | ||
| 245 | const Foo24Bits = packed struct { | |
| 246 | field: u24, | |
| 247 | }; | |
| 248 | const Foo96Bits = packed struct { | |
| 249 | a: u24, | |
| 250 | b: u24, | |
| 251 | c: u24, | |
| 252 | d: u24, | |
| 253 | }; | |
| 254 | ||
| 255 | test "packed struct 24bits" { | |
| 256 | comptime { | |
| 257 | assertOrPanic(@sizeOf(Foo24Bits) == 3); | |
| 258 | assertOrPanic(@sizeOf(Foo96Bits) == 12); | |
| 259 | } | |
| 260 | ||
| 261 | var value = Foo96Bits{ | |
| 262 | .a = 0, | |
| 263 | .b = 0, | |
| 264 | .c = 0, | |
| 265 | .d = 0, | |
| 266 | }; | |
| 267 | value.a += 1; | |
| 268 | assertOrPanic(value.a == 1); | |
| 269 | assertOrPanic(value.b == 0); | |
| 270 | assertOrPanic(value.c == 0); | |
| 271 | assertOrPanic(value.d == 0); | |
| 272 | ||
| 273 | value.b += 1; | |
| 274 | assertOrPanic(value.a == 1); | |
| 275 | assertOrPanic(value.b == 1); | |
| 276 | assertOrPanic(value.c == 0); | |
| 277 | assertOrPanic(value.d == 0); | |
| 278 | ||
| 279 | value.c += 1; | |
| 280 | assertOrPanic(value.a == 1); | |
| 281 | assertOrPanic(value.b == 1); | |
| 282 | assertOrPanic(value.c == 1); | |
| 283 | assertOrPanic(value.d == 0); | |
| 284 | ||
| 285 | value.d += 1; | |
| 286 | assertOrPanic(value.a == 1); | |
| 287 | assertOrPanic(value.b == 1); | |
| 288 | assertOrPanic(value.c == 1); | |
| 289 | assertOrPanic(value.d == 1); | |
| 290 | } | |
| 291 | ||
| 292 | const FooArray24Bits = packed struct { | |
| 293 | a: u16, | |
| 294 | b: [2]Foo24Bits, | |
| 295 | c: u16, | |
| 296 | }; | |
| 297 | ||
| 298 | test "packed array 24bits" { | |
| 299 | comptime { | |
| 300 | assertOrPanic(@sizeOf([9]Foo24Bits) == 9 * 3); | |
| 301 | assertOrPanic(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); | |
| 302 | } | |
| 303 | ||
| 304 | var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1); | |
| 305 | bytes[bytes.len - 1] = 0xaa; | |
| 306 | const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; | |
| 307 | assertOrPanic(ptr.a == 0); | |
| 308 | assertOrPanic(ptr.b[0].field == 0); | |
| 309 | assertOrPanic(ptr.b[1].field == 0); | |
| 310 | assertOrPanic(ptr.c == 0); | |
| 311 | ||
| 312 | ptr.a = maxInt(u16); | |
| 313 | assertOrPanic(ptr.a == maxInt(u16)); | |
| 314 | assertOrPanic(ptr.b[0].field == 0); | |
| 315 | assertOrPanic(ptr.b[1].field == 0); | |
| 316 | assertOrPanic(ptr.c == 0); | |
| 317 | ||
| 318 | ptr.b[0].field = maxInt(u24); | |
| 319 | assertOrPanic(ptr.a == maxInt(u16)); | |
| 320 | assertOrPanic(ptr.b[0].field == maxInt(u24)); | |
| 321 | assertOrPanic(ptr.b[1].field == 0); | |
| 322 | assertOrPanic(ptr.c == 0); | |
| 323 | ||
| 324 | ptr.b[1].field = maxInt(u24); | |
| 325 | assertOrPanic(ptr.a == maxInt(u16)); | |
| 326 | assertOrPanic(ptr.b[0].field == maxInt(u24)); | |
| 327 | assertOrPanic(ptr.b[1].field == maxInt(u24)); | |
| 328 | assertOrPanic(ptr.c == 0); | |
| 329 | ||
| 330 | ptr.c = maxInt(u16); | |
| 331 | assertOrPanic(ptr.a == maxInt(u16)); | |
| 332 | assertOrPanic(ptr.b[0].field == maxInt(u24)); | |
| 333 | assertOrPanic(ptr.b[1].field == maxInt(u24)); | |
| 334 | assertOrPanic(ptr.c == maxInt(u16)); | |
| 335 | ||
| 336 | assertOrPanic(bytes[bytes.len - 1] == 0xaa); | |
| 337 | } | |
| 338 | ||
| 339 | const FooStructAligned = packed struct { | |
| 340 | a: u8, | |
| 341 | b: u8, | |
| 342 | }; | |
| 343 | ||
| 344 | const FooArrayOfAligned = packed struct { | |
| 345 | a: [2]FooStructAligned, | |
| 346 | }; | |
| 347 | ||
| 348 | test "aligned array of packed struct" { | |
| 349 | comptime { | |
| 350 | assertOrPanic(@sizeOf(FooStructAligned) == 2); | |
| 351 | assertOrPanic(@sizeOf(FooArrayOfAligned) == 2 * 2); | |
| 352 | } | |
| 353 | ||
| 354 | var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned); | |
| 355 | const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0]; | |
| 356 | ||
| 357 | assertOrPanic(ptr.a[0].a == 0xbb); | |
| 358 | assertOrPanic(ptr.a[0].b == 0xbb); | |
| 359 | assertOrPanic(ptr.a[1].a == 0xbb); | |
| 360 | assertOrPanic(ptr.a[1].b == 0xbb); | |
| 361 | } | |
| 362 | ||
| 363 | test "runtime struct initialization of bitfield" { | |
| 364 | const s1 = Nibbles{ | |
| 365 | .x = x1, | |
| 366 | .y = x1, | |
| 367 | }; | |
| 368 | const s2 = Nibbles{ | |
| 369 | .x = @intCast(u4, x2), | |
| 370 | .y = @intCast(u4, x2), | |
| 371 | }; | |
| 372 | ||
| 373 | assertOrPanic(s1.x == x1); | |
| 374 | assertOrPanic(s1.y == x1); | |
| 375 | assertOrPanic(s2.x == @intCast(u4, x2)); | |
| 376 | assertOrPanic(s2.y == @intCast(u4, x2)); | |
| 377 | } | |
| 378 | ||
| 379 | var x1 = u4(1); | |
| 380 | var x2 = u8(2); | |
| 381 | ||
| 382 | const Nibbles = packed struct { | |
| 383 | x: u4, | |
| 384 | y: u4, | |
| 385 | }; | |
| 386 | ||
| 387 | const Bitfields = packed struct { | |
| 388 | f1: u16, | |
| 389 | f2: u16, | |
| 390 | f3: u8, | |
| 391 | f4: u8, | |
| 392 | f5: u4, | |
| 393 | f6: u4, | |
| 394 | f7: u8, | |
| 395 | }; | |
| 396 | ||
| 397 | test "native bit field understands endianness" { | |
| 398 | var all: u64 = 0x7765443322221111; | |
| 399 | var bytes: [8]u8 = undefined; | |
| 400 | @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8); | |
| 401 | var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*; | |
| 402 | ||
| 403 | assertOrPanic(bitfields.f1 == 0x1111); | |
| 404 | assertOrPanic(bitfields.f2 == 0x2222); | |
| 405 | assertOrPanic(bitfields.f3 == 0x33); | |
| 406 | assertOrPanic(bitfields.f4 == 0x44); | |
| 407 | assertOrPanic(bitfields.f5 == 0x5); | |
| 408 | assertOrPanic(bitfields.f6 == 0x6); | |
| 409 | assertOrPanic(bitfields.f7 == 0x77); | |
| 410 | } | |
| 411 | ||
| 412 | test "align 1 field before self referential align 8 field as slice return type" { | |
| 413 | const result = alloc(Expr); | |
| 414 | assertOrPanic(result.len == 0); | |
| 415 | } | |
| 416 | ||
| 417 | const Expr = union(enum) { | |
| 418 | Literal: u8, | |
| 419 | Question: *Expr, | |
| 420 | }; | |
| 421 | ||
| 422 | fn alloc(comptime T: type) []T { | |
| 423 | return []T{}; | |
| 424 | } | |
| 425 | ||
| 426 | test "call method with mutable reference to struct with no fields" { | |
| 427 | const S = struct { | |
| 428 | fn doC(s: *const @This()) bool { | |
| 429 | return true; | |
| 430 | } | |
| 431 | fn do(s: *@This()) bool { | |
| 432 | return true; | |
| 433 | } | |
| 434 | }; | |
| 435 | ||
| 436 | var s = S{}; | |
| 437 | assertOrPanic(S.doC(&s)); | |
| 438 | assertOrPanic(s.doC()); | |
| 439 | assertOrPanic(S.do(&s)); | |
| 440 | assertOrPanic(s.do()); | |
| 441 | } | |
| 442 | ||
| 443 | test "implicit cast packed struct field to const ptr" { | |
| 444 | const LevelUpMove = packed struct { | |
| 445 | move_id: u9, | |
| 446 | level: u7, | |
| 447 | ||
| 448 | fn toInt(value: u7) u7 { | |
| 449 | return value; | |
| 450 | } | |
| 451 | }; | |
| 452 | ||
| 453 | var lup: LevelUpMove = undefined; | |
| 454 | lup.level = 12; | |
| 455 | const res = LevelUpMove.toInt(lup.level); | |
| 456 | assertOrPanic(res == 12); | |
| 457 | } | |
| 458 | ||
| 459 | test "pointer to packed struct member in a stack variable" { | |
| 460 | const S = packed struct { | |
| 461 | a: u2, | |
| 462 | b: u2, | |
| 463 | }; | |
| 464 | ||
| 465 | var s = S{ .a = 2, .b = 0 }; | |
| 466 | var b_ptr = &s.b; | |
| 467 | assertOrPanic(s.b == 0); | |
| 468 | b_ptr.* = 2; | |
| 469 | assertOrPanic(s.b == 2); | |
| 470 | } |
test/stage1/behavior/struct_contains_null_ptr_itself.zig created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | ||
| 4 | test "struct contains null pointer which contains original struct" { | |
| 5 | var x: ?*NodeLineComment = null; | |
| 6 | assertOrPanic(x == null); | |
| 7 | } | |
| 8 | ||
| 9 | pub const Node = struct { | |
| 10 | id: Id, | |
| 11 | comment: ?*NodeLineComment, | |
| 12 | ||
| 13 | pub const Id = enum { | |
| 14 | Root, | |
| 15 | LineComment, | |
| 16 | }; | |
| 17 | }; | |
| 18 | ||
| 19 | pub const NodeLineComment = struct { | |
| 20 | base: Node, | |
| 21 | }; |
test/stage1/behavior/struct_contains_slice_of_itself.zig created+85| ... | ... | @@ -0,0 +1,85 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | const Node = struct { | |
| 4 | payload: i32, | |
| 5 | children: []Node, | |
| 6 | }; | |
| 7 | ||
| 8 | const NodeAligned = struct { | |
| 9 | payload: i32, | |
| 10 | children: []align(@alignOf(NodeAligned)) NodeAligned, | |
| 11 | }; | |
| 12 | ||
| 13 | test "struct contains slice of itself" { | |
| 14 | var other_nodes = []Node{ | |
| 15 | Node{ | |
| 16 | .payload = 31, | |
| 17 | .children = []Node{}, | |
| 18 | }, | |
| 19 | Node{ | |
| 20 | .payload = 32, | |
| 21 | .children = []Node{}, | |
| 22 | }, | |
| 23 | }; | |
| 24 | var nodes = []Node{ | |
| 25 | Node{ | |
| 26 | .payload = 1, | |
| 27 | .children = []Node{}, | |
| 28 | }, | |
| 29 | Node{ | |
| 30 | .payload = 2, | |
| 31 | .children = []Node{}, | |
| 32 | }, | |
| 33 | Node{ | |
| 34 | .payload = 3, | |
| 35 | .children = other_nodes[0..], | |
| 36 | }, | |
| 37 | }; | |
| 38 | const root = Node{ | |
| 39 | .payload = 1234, | |
| 40 | .children = nodes[0..], | |
| 41 | }; | |
| 42 | assertOrPanic(root.payload == 1234); | |
| 43 | assertOrPanic(root.children[0].payload == 1); | |
| 44 | assertOrPanic(root.children[1].payload == 2); | |
| 45 | assertOrPanic(root.children[2].payload == 3); | |
| 46 | assertOrPanic(root.children[2].children[0].payload == 31); | |
| 47 | assertOrPanic(root.children[2].children[1].payload == 32); | |
| 48 | } | |
| 49 | ||
| 50 | test "struct contains aligned slice of itself" { | |
| 51 | var other_nodes = []NodeAligned{ | |
| 52 | NodeAligned{ | |
| 53 | .payload = 31, | |
| 54 | .children = []NodeAligned{}, | |
| 55 | }, | |
| 56 | NodeAligned{ | |
| 57 | .payload = 32, | |
| 58 | .children = []NodeAligned{}, | |
| 59 | }, | |
| 60 | }; | |
| 61 | var nodes = []NodeAligned{ | |
| 62 | NodeAligned{ | |
| 63 | .payload = 1, | |
| 64 | .children = []NodeAligned{}, | |
| 65 | }, | |
| 66 | NodeAligned{ | |
| 67 | .payload = 2, | |
| 68 | .children = []NodeAligned{}, | |
| 69 | }, | |
| 70 | NodeAligned{ | |
| 71 | .payload = 3, | |
| 72 | .children = other_nodes[0..], | |
| 73 | }, | |
| 74 | }; | |
| 75 | const root = NodeAligned{ | |
| 76 | .payload = 1234, | |
| 77 | .children = nodes[0..], | |
| 78 | }; | |
| 79 | assertOrPanic(root.payload == 1234); | |
| 80 | assertOrPanic(root.children[0].payload == 1); | |
| 81 | assertOrPanic(root.children[1].payload == 2); | |
| 82 | assertOrPanic(root.children[2].payload == 3); | |
| 83 | assertOrPanic(root.children[2].children[0].payload == 31); | |
| 84 | assertOrPanic(root.children[2].children[1].payload == 32); | |
| 85 | } |
test/stage1/behavior/switch.zig created+271| ... | ... | @@ -0,0 +1,271 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "switch with numbers" { | |
| 4 | testSwitchWithNumbers(13); | |
| 5 | } | |
| 6 | ||
| 7 | fn testSwitchWithNumbers(x: u32) void { | |
| 8 | const result = switch (x) { | |
| 9 | 1, 2, 3, 4...8 => false, | |
| 10 | 13 => true, | |
| 11 | else => false, | |
| 12 | }; | |
| 13 | assertOrPanic(result); | |
| 14 | } | |
| 15 | ||
| 16 | test "switch with all ranges" { | |
| 17 | assertOrPanic(testSwitchWithAllRanges(50, 3) == 1); | |
| 18 | assertOrPanic(testSwitchWithAllRanges(101, 0) == 2); | |
| 19 | assertOrPanic(testSwitchWithAllRanges(300, 5) == 3); | |
| 20 | assertOrPanic(testSwitchWithAllRanges(301, 6) == 6); | |
| 21 | } | |
| 22 | ||
| 23 | fn testSwitchWithAllRanges(x: u32, y: u32) u32 { | |
| 24 | return switch (x) { | |
| 25 | 0...100 => 1, | |
| 26 | 101...200 => 2, | |
| 27 | 201...300 => 3, | |
| 28 | else => y, | |
| 29 | }; | |
| 30 | } | |
| 31 | ||
| 32 | test "implicit comptime switch" { | |
| 33 | const x = 3 + 4; | |
| 34 | const result = switch (x) { | |
| 35 | 3 => 10, | |
| 36 | 4 => 11, | |
| 37 | 5, 6 => 12, | |
| 38 | 7, 8 => 13, | |
| 39 | else => 14, | |
| 40 | }; | |
| 41 | ||
| 42 | comptime { | |
| 43 | assertOrPanic(result + 1 == 14); | |
| 44 | } | |
| 45 | } | |
| 46 | ||
| 47 | test "switch on enum" { | |
| 48 | const fruit = Fruit.Orange; | |
| 49 | nonConstSwitchOnEnum(fruit); | |
| 50 | } | |
| 51 | const Fruit = enum { | |
| 52 | Apple, | |
| 53 | Orange, | |
| 54 | Banana, | |
| 55 | }; | |
| 56 | fn nonConstSwitchOnEnum(fruit: Fruit) void { | |
| 57 | switch (fruit) { | |
| 58 | Fruit.Apple => unreachable, | |
| 59 | Fruit.Orange => {}, | |
| 60 | Fruit.Banana => unreachable, | |
| 61 | } | |
| 62 | } | |
| 63 | ||
| 64 | test "switch statement" { | |
| 65 | nonConstSwitch(SwitchStatmentFoo.C); | |
| 66 | } | |
| 67 | fn nonConstSwitch(foo: SwitchStatmentFoo) void { | |
| 68 | const val = switch (foo) { | |
| 69 | SwitchStatmentFoo.A => i32(1), | |
| 70 | SwitchStatmentFoo.B => 2, | |
| 71 | SwitchStatmentFoo.C => 3, | |
| 72 | SwitchStatmentFoo.D => 4, | |
| 73 | }; | |
| 74 | assertOrPanic(val == 3); | |
| 75 | } | |
| 76 | const SwitchStatmentFoo = enum { | |
| 77 | A, | |
| 78 | B, | |
| 79 | C, | |
| 80 | D, | |
| 81 | }; | |
| 82 | ||
| 83 | test "switch prong with variable" { | |
| 84 | switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 }); | |
| 85 | switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 }); | |
| 86 | switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} }); | |
| 87 | } | |
| 88 | const SwitchProngWithVarEnum = union(enum) { | |
| 89 | One: i32, | |
| 90 | Two: f32, | |
| 91 | Meh: void, | |
| 92 | }; | |
| 93 | fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void { | |
| 94 | switch (a) { | |
| 95 | SwitchProngWithVarEnum.One => |x| { | |
| 96 | assertOrPanic(x == 13); | |
| 97 | }, | |
| 98 | SwitchProngWithVarEnum.Two => |x| { | |
| 99 | assertOrPanic(x == 13.0); | |
| 100 | }, | |
| 101 | SwitchProngWithVarEnum.Meh => |x| { | |
| 102 | const v: void = x; | |
| 103 | }, | |
| 104 | } | |
| 105 | } | |
| 106 | ||
| 107 | test "switch on enum using pointer capture" { | |
| 108 | testSwitchEnumPtrCapture(); | |
| 109 | comptime testSwitchEnumPtrCapture(); | |
| 110 | } | |
| 111 | ||
| 112 | fn testSwitchEnumPtrCapture() void { | |
| 113 | var value = SwitchProngWithVarEnum{ .One = 1234 }; | |
| 114 | switch (value) { | |
| 115 | SwitchProngWithVarEnum.One => |*x| x.* += 1, | |
| 116 | else => unreachable, | |
| 117 | } | |
| 118 | switch (value) { | |
| 119 | SwitchProngWithVarEnum.One => |x| assertOrPanic(x == 1235), | |
| 120 | else => unreachable, | |
| 121 | } | |
| 122 | } | |
| 123 | ||
| 124 | test "switch with multiple expressions" { | |
| 125 | const x = switch (returnsFive()) { | |
| 126 | 1, 2, 3 => 1, | |
| 127 | 4, 5, 6 => 2, | |
| 128 | else => i32(3), | |
| 129 | }; | |
| 130 | assertOrPanic(x == 2); | |
| 131 | } | |
| 132 | fn returnsFive() i32 { | |
| 133 | return 5; | |
| 134 | } | |
| 135 | ||
| 136 | const Number = union(enum) { | |
| 137 | One: u64, | |
| 138 | Two: u8, | |
| 139 | Three: f32, | |
| 140 | }; | |
| 141 | ||
| 142 | const number = Number{ .Three = 1.23 }; | |
| 143 | ||
| 144 | fn returnsFalse() bool { | |
| 145 | switch (number) { | |
| 146 | Number.One => |x| return x > 1234, | |
| 147 | Number.Two => |x| return x == 'a', | |
| 148 | Number.Three => |x| return x > 12.34, | |
| 149 | } | |
| 150 | } | |
| 151 | test "switch on const enum with var" { | |
| 152 | assertOrPanic(!returnsFalse()); | |
| 153 | } | |
| 154 | ||
| 155 | test "switch on type" { | |
| 156 | assertOrPanic(trueIfBoolFalseOtherwise(bool)); | |
| 157 | assertOrPanic(!trueIfBoolFalseOtherwise(i32)); | |
| 158 | } | |
| 159 | ||
| 160 | fn trueIfBoolFalseOtherwise(comptime T: type) bool { | |
| 161 | return switch (T) { | |
| 162 | bool => true, | |
| 163 | else => false, | |
| 164 | }; | |
| 165 | } | |
| 166 | ||
| 167 | test "switch handles all cases of number" { | |
| 168 | testSwitchHandleAllCases(); | |
| 169 | comptime testSwitchHandleAllCases(); | |
| 170 | } | |
| 171 | ||
| 172 | fn testSwitchHandleAllCases() void { | |
| 173 | assertOrPanic(testSwitchHandleAllCasesExhaustive(0) == 3); | |
| 174 | assertOrPanic(testSwitchHandleAllCasesExhaustive(1) == 2); | |
| 175 | assertOrPanic(testSwitchHandleAllCasesExhaustive(2) == 1); | |
| 176 | assertOrPanic(testSwitchHandleAllCasesExhaustive(3) == 0); | |
| 177 | ||
| 178 | assertOrPanic(testSwitchHandleAllCasesRange(100) == 0); | |
| 179 | assertOrPanic(testSwitchHandleAllCasesRange(200) == 1); | |
| 180 | assertOrPanic(testSwitchHandleAllCasesRange(201) == 2); | |
| 181 | assertOrPanic(testSwitchHandleAllCasesRange(202) == 4); | |
| 182 | assertOrPanic(testSwitchHandleAllCasesRange(230) == 3); | |
| 183 | } | |
| 184 | ||
| 185 | fn testSwitchHandleAllCasesExhaustive(x: u2) u2 { | |
| 186 | return switch (x) { | |
| 187 | 0 => u2(3), | |
| 188 | 1 => 2, | |
| 189 | 2 => 1, | |
| 190 | 3 => 0, | |
| 191 | }; | |
| 192 | } | |
| 193 | ||
| 194 | fn testSwitchHandleAllCasesRange(x: u8) u8 { | |
| 195 | return switch (x) { | |
| 196 | 0...100 => u8(0), | |
| 197 | 101...200 => 1, | |
| 198 | 201, 203 => 2, | |
| 199 | 202 => 4, | |
| 200 | 204...255 => 3, | |
| 201 | }; | |
| 202 | } | |
| 203 | ||
| 204 | test "switch all prongs unreachable" { | |
| 205 | testAllProngsUnreachable(); | |
| 206 | comptime testAllProngsUnreachable(); | |
| 207 | } | |
| 208 | ||
| 209 | fn testAllProngsUnreachable() void { | |
| 210 | assertOrPanic(switchWithUnreachable(1) == 2); | |
| 211 | assertOrPanic(switchWithUnreachable(2) == 10); | |
| 212 | } | |
| 213 | ||
| 214 | fn switchWithUnreachable(x: i32) i32 { | |
| 215 | while (true) { | |
| 216 | switch (x) { | |
| 217 | 1 => return 2, | |
| 218 | 2 => break, | |
| 219 | else => continue, | |
| 220 | } | |
| 221 | } | |
| 222 | return 10; | |
| 223 | } | |
| 224 | ||
| 225 | fn return_a_number() anyerror!i32 { | |
| 226 | return 1; | |
| 227 | } | |
| 228 | ||
| 229 | test "capture value of switch with all unreachable prongs" { | |
| 230 | const x = return_a_number() catch |err| switch (err) { | |
| 231 | else => unreachable, | |
| 232 | }; | |
| 233 | assertOrPanic(x == 1); | |
| 234 | } | |
| 235 | ||
| 236 | test "switching on booleans" { | |
| 237 | testSwitchOnBools(); | |
| 238 | comptime testSwitchOnBools(); | |
| 239 | } | |
| 240 | ||
| 241 | fn testSwitchOnBools() void { | |
| 242 | assertOrPanic(testSwitchOnBoolsTrueAndFalse(true) == false); | |
| 243 | assertOrPanic(testSwitchOnBoolsTrueAndFalse(false) == true); | |
| 244 | ||
| 245 | assertOrPanic(testSwitchOnBoolsTrueWithElse(true) == false); | |
| 246 | assertOrPanic(testSwitchOnBoolsTrueWithElse(false) == true); | |
| 247 | ||
| 248 | assertOrPanic(testSwitchOnBoolsFalseWithElse(true) == false); | |
| 249 | assertOrPanic(testSwitchOnBoolsFalseWithElse(false) == true); | |
| 250 | } | |
| 251 | ||
| 252 | fn testSwitchOnBoolsTrueAndFalse(x: bool) bool { | |
| 253 | return switch (x) { | |
| 254 | true => false, | |
| 255 | false => true, | |
| 256 | }; | |
| 257 | } | |
| 258 | ||
| 259 | fn testSwitchOnBoolsTrueWithElse(x: bool) bool { | |
| 260 | return switch (x) { | |
| 261 | true => false, | |
| 262 | else => true, | |
| 263 | }; | |
| 264 | } | |
| 265 | ||
| 266 | fn testSwitchOnBoolsFalseWithElse(x: bool) bool { | |
| 267 | return switch (x) { | |
| 268 | false => true, | |
| 269 | else => false, | |
| 270 | }; | |
| 271 | } |
test/stage1/behavior/switch_prong_err_enum.zig created+30| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | var read_count: u64 = 0; | |
| 4 | ||
| 5 | fn readOnce() anyerror!u64 { | |
| 6 | read_count += 1; | |
| 7 | return read_count; | |
| 8 | } | |
| 9 | ||
| 10 | const FormValue = union(enum) { | |
| 11 | Address: u64, | |
| 12 | Other: bool, | |
| 13 | }; | |
| 14 | ||
| 15 | fn doThing(form_id: u64) anyerror!FormValue { | |
| 16 | return switch (form_id) { | |
| 17 | 17 => FormValue{ .Address = try readOnce() }, | |
| 18 | else => error.InvalidDebugInfo, | |
| 19 | }; | |
| 20 | } | |
| 21 | ||
| 22 | test "switch prong returns error enum" { | |
| 23 | switch (doThing(17) catch unreachable) { | |
| 24 | FormValue.Address => |payload| { | |
| 25 | assertOrPanic(payload == 1); | |
| 26 | }, | |
| 27 | else => unreachable, | |
| 28 | } | |
| 29 | assertOrPanic(read_count == 1); | |
| 30 | } |
test/stage1/behavior/switch_prong_implicit_cast.zig created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | const FormValue = union(enum) { | |
| 4 | One: void, | |
| 5 | Two: bool, | |
| 6 | }; | |
| 7 | ||
| 8 | fn foo(id: u64) !FormValue { | |
| 9 | return switch (id) { | |
| 10 | 2 => FormValue{ .Two = true }, | |
| 11 | 1 => FormValue{ .One = {} }, | |
| 12 | else => return error.Whatever, | |
| 13 | }; | |
| 14 | } | |
| 15 | ||
| 16 | test "switch prong implicit cast" { | |
| 17 | const result = switch (foo(2) catch unreachable) { | |
| 18 | FormValue.One => false, | |
| 19 | FormValue.Two => |x| x, | |
| 20 | }; | |
| 21 | assertOrPanic(result); | |
| 22 | } |
test/stage1/behavior/syntax.zig created+60| ... | ... | @@ -0,0 +1,60 @@ |
| 1 | // Test trailing comma syntax | |
| 2 | // zig fmt: off | |
| 3 | ||
| 4 | const struct_trailing_comma = struct { x: i32, y: i32, }; | |
| 5 | const struct_no_comma = struct { x: i32, y: i32 }; | |
| 6 | const struct_fn_no_comma = struct { fn m() void {} y: i32 }; | |
| 7 | ||
| 8 | const enum_no_comma = enum { A, B }; | |
| 9 | ||
| 10 | fn container_init() void { | |
| 11 | const S = struct { x: i32, y: i32 }; | |
| 12 | _ = S { .x = 1, .y = 2 }; | |
| 13 | _ = S { .x = 1, .y = 2, }; | |
| 14 | } | |
| 15 | ||
| 16 | fn type_expr_return1() if (true) A {} | |
| 17 | fn type_expr_return2() for (true) |_| A {} | |
| 18 | fn type_expr_return3() while (true) A {} | |
| 19 | fn type_expr_return4() comptime A {} | |
| 20 | ||
| 21 | fn switch_cases(x: i32) void { | |
| 22 | switch (x) { | |
| 23 | 1,2,3 => {}, | |
| 24 | 4,5, => {}, | |
| 25 | 6...8, => {}, | |
| 26 | else => {}, | |
| 27 | } | |
| 28 | } | |
| 29 | ||
| 30 | fn switch_prongs(x: i32) void { | |
| 31 | switch (x) { | |
| 32 | 0 => {}, | |
| 33 | else => {}, | |
| 34 | } | |
| 35 | switch (x) { | |
| 36 | 0 => {}, | |
| 37 | else => {} | |
| 38 | } | |
| 39 | } | |
| 40 | ||
| 41 | const fn_no_comma = fn(i32, i32)void; | |
| 42 | const fn_trailing_comma = fn(i32, i32,)void; | |
| 43 | ||
| 44 | fn fn_calls() void { | |
| 45 | fn add(x: i32, y: i32,) i32 { x + y }; | |
| 46 | _ = add(1, 2); | |
| 47 | _ = add(1, 2,); | |
| 48 | } | |
| 49 | ||
| 50 | fn asm_lists() void { | |
| 51 | if (false) { // Build AST but don't analyze | |
| 52 | asm ("not real assembly" | |
| 53 | :[a] "x" (x),); | |
| 54 | asm ("not real assembly" | |
| 55 | :[a] "x" (->i32),:[a] "x" (1),); | |
| 56 | asm ("still not real assembly" | |
| 57 | :::"a","b",); | |
| 58 | } | |
| 59 | } | |
| 60 |
test/stage1/behavior/this.zig created+35| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | const module = @This(); | |
| 4 | ||
| 5 | fn Point(comptime T: type) type { | |
| 6 | return struct { | |
| 7 | const Self = @This(); | |
| 8 | x: T, | |
| 9 | y: T, | |
| 10 | ||
| 11 | fn addOne(self: *Self) void { | |
| 12 | self.x += 1; | |
| 13 | self.y += 1; | |
| 14 | } | |
| 15 | }; | |
| 16 | } | |
| 17 | ||
| 18 | fn add(x: i32, y: i32) i32 { | |
| 19 | return x + y; | |
| 20 | } | |
| 21 | ||
| 22 | test "this refer to module call private fn" { | |
| 23 | assertOrPanic(module.add(1, 2) == 3); | |
| 24 | } | |
| 25 | ||
| 26 | test "this refer to container" { | |
| 27 | var pt = Point(i32){ | |
| 28 | .x = 12, | |
| 29 | .y = 34, | |
| 30 | }; | |
| 31 | pt.addOne(); | |
| 32 | assertOrPanic(pt.x == 13); | |
| 33 | assertOrPanic(pt.y == 35); | |
| 34 | } | |
| 35 |
test/stage1/behavior/truncate.zig created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | ||
| 4 | test "truncate u0 to larger integer allowed and has comptime known result" { | |
| 5 | var x: u0 = 0; | |
| 6 | const y = @truncate(u8, x); | |
| 7 | comptime assertOrPanic(y == 0); | |
| 8 | } |
test/stage1/behavior/try.zig created+43| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "try on error union" { | |
| 4 | tryOnErrorUnionImpl(); | |
| 5 | comptime tryOnErrorUnionImpl(); | |
| 6 | } | |
| 7 | ||
| 8 | fn tryOnErrorUnionImpl() void { | |
| 9 | const x = if (returnsTen()) |val| val + 1 else |err| switch (err) { | |
| 10 | error.ItBroke, error.NoMem => 1, | |
| 11 | error.CrappedOut => i32(2), | |
| 12 | else => unreachable, | |
| 13 | }; | |
| 14 | assertOrPanic(x == 11); | |
| 15 | } | |
| 16 | ||
| 17 | fn returnsTen() anyerror!i32 { | |
| 18 | return 10; | |
| 19 | } | |
| 20 | ||
| 21 | test "try without vars" { | |
| 22 | const result1 = if (failIfTrue(true)) 1 else |_| i32(2); | |
| 23 | assertOrPanic(result1 == 2); | |
| 24 | ||
| 25 | const result2 = if (failIfTrue(false)) 1 else |_| i32(2); | |
| 26 | assertOrPanic(result2 == 1); | |
| 27 | } | |
| 28 | ||
| 29 | fn failIfTrue(ok: bool) anyerror!void { | |
| 30 | if (ok) { | |
| 31 | return error.ItBroke; | |
| 32 | } else { | |
| 33 | return; | |
| 34 | } | |
| 35 | } | |
| 36 | ||
| 37 | test "try then not executed with assignment" { | |
| 38 | if (failIfTrue(true)) { | |
| 39 | unreachable; | |
| 40 | } else |err| { | |
| 41 | assertOrPanic(err == error.ItBroke); | |
| 42 | } | |
| 43 | } |
test/stage1/behavior/type_info.zig created+264| ... | ... | @@ -0,0 +1,264 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | const mem = @import("std").mem; | |
| 3 | const TypeInfo = @import("builtin").TypeInfo; | |
| 4 | const TypeId = @import("builtin").TypeId; | |
| 5 | ||
| 6 | test "type info: tag type, void info" { | |
| 7 | testBasic(); | |
| 8 | comptime testBasic(); | |
| 9 | } | |
| 10 | ||
| 11 | fn testBasic() void { | |
| 12 | assertOrPanic(@TagType(TypeInfo) == TypeId); | |
| 13 | const void_info = @typeInfo(void); | |
| 14 | assertOrPanic(TypeId(void_info) == TypeId.Void); | |
| 15 | assertOrPanic(void_info.Void == {}); | |
| 16 | } | |
| 17 | ||
| 18 | test "type info: integer, floating point type info" { | |
| 19 | testIntFloat(); | |
| 20 | comptime testIntFloat(); | |
| 21 | } | |
| 22 | ||
| 23 | fn testIntFloat() void { | |
| 24 | const u8_info = @typeInfo(u8); | |
| 25 | assertOrPanic(TypeId(u8_info) == TypeId.Int); | |
| 26 | assertOrPanic(!u8_info.Int.is_signed); | |
| 27 | assertOrPanic(u8_info.Int.bits == 8); | |
| 28 | ||
| 29 | const f64_info = @typeInfo(f64); | |
| 30 | assertOrPanic(TypeId(f64_info) == TypeId.Float); | |
| 31 | assertOrPanic(f64_info.Float.bits == 64); | |
| 32 | } | |
| 33 | ||
| 34 | test "type info: pointer type info" { | |
| 35 | testPointer(); | |
| 36 | comptime testPointer(); | |
| 37 | } | |
| 38 | ||
| 39 | fn testPointer() void { | |
| 40 | const u32_ptr_info = @typeInfo(*u32); | |
| 41 | assertOrPanic(TypeId(u32_ptr_info) == TypeId.Pointer); | |
| 42 | assertOrPanic(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); | |
| 43 | assertOrPanic(u32_ptr_info.Pointer.is_const == false); | |
| 44 | assertOrPanic(u32_ptr_info.Pointer.is_volatile == false); | |
| 45 | assertOrPanic(u32_ptr_info.Pointer.alignment == @alignOf(u32)); | |
| 46 | assertOrPanic(u32_ptr_info.Pointer.child == u32); | |
| 47 | } | |
| 48 | ||
| 49 | test "type info: unknown length pointer type info" { | |
| 50 | testUnknownLenPtr(); | |
| 51 | comptime testUnknownLenPtr(); | |
| 52 | } | |
| 53 | ||
| 54 | fn testUnknownLenPtr() void { | |
| 55 | const u32_ptr_info = @typeInfo([*]const volatile f64); | |
| 56 | assertOrPanic(TypeId(u32_ptr_info) == TypeId.Pointer); | |
| 57 | assertOrPanic(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); | |
| 58 | assertOrPanic(u32_ptr_info.Pointer.is_const == true); | |
| 59 | assertOrPanic(u32_ptr_info.Pointer.is_volatile == true); | |
| 60 | assertOrPanic(u32_ptr_info.Pointer.alignment == @alignOf(f64)); | |
| 61 | assertOrPanic(u32_ptr_info.Pointer.child == f64); | |
| 62 | } | |
| 63 | ||
| 64 | test "type info: slice type info" { | |
| 65 | testSlice(); | |
| 66 | comptime testSlice(); | |
| 67 | } | |
| 68 | ||
| 69 | fn testSlice() void { | |
| 70 | const u32_slice_info = @typeInfo([]u32); | |
| 71 | assertOrPanic(TypeId(u32_slice_info) == TypeId.Pointer); | |
| 72 | assertOrPanic(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); | |
| 73 | assertOrPanic(u32_slice_info.Pointer.is_const == false); | |
| 74 | assertOrPanic(u32_slice_info.Pointer.is_volatile == false); | |
| 75 | assertOrPanic(u32_slice_info.Pointer.alignment == 4); | |
| 76 | assertOrPanic(u32_slice_info.Pointer.child == u32); | |
| 77 | } | |
| 78 | ||
| 79 | test "type info: array type info" { | |
| 80 | testArray(); | |
| 81 | comptime testArray(); | |
| 82 | } | |
| 83 | ||
| 84 | fn testArray() void { | |
| 85 | const arr_info = @typeInfo([42]bool); | |
| 86 | assertOrPanic(TypeId(arr_info) == TypeId.Array); | |
| 87 | assertOrPanic(arr_info.Array.len == 42); | |
| 88 | assertOrPanic(arr_info.Array.child == bool); | |
| 89 | } | |
| 90 | ||
| 91 | test "type info: optional type info" { | |
| 92 | testOptional(); | |
| 93 | comptime testOptional(); | |
| 94 | } | |
| 95 | ||
| 96 | fn testOptional() void { | |
| 97 | const null_info = @typeInfo(?void); | |
| 98 | assertOrPanic(TypeId(null_info) == TypeId.Optional); | |
| 99 | assertOrPanic(null_info.Optional.child == void); | |
| 100 | } | |
| 101 | ||
| 102 | test "type info: promise info" { | |
| 103 | testPromise(); | |
| 104 | comptime testPromise(); | |
| 105 | } | |
| 106 | ||
| 107 | fn testPromise() void { | |
| 108 | const null_promise_info = @typeInfo(promise); | |
| 109 | assertOrPanic(TypeId(null_promise_info) == TypeId.Promise); | |
| 110 | assertOrPanic(null_promise_info.Promise.child == null); | |
| 111 | ||
| 112 | const promise_info = @typeInfo(promise->usize); | |
| 113 | assertOrPanic(TypeId(promise_info) == TypeId.Promise); | |
| 114 | assertOrPanic(promise_info.Promise.child.? == usize); | |
| 115 | } | |
| 116 | ||
| 117 | test "type info: error set, error union info" { | |
| 118 | testErrorSet(); | |
| 119 | comptime testErrorSet(); | |
| 120 | } | |
| 121 | ||
| 122 | fn testErrorSet() void { | |
| 123 | const TestErrorSet = error{ | |
| 124 | First, | |
| 125 | Second, | |
| 126 | Third, | |
| 127 | }; | |
| 128 | ||
| 129 | const error_set_info = @typeInfo(TestErrorSet); | |
| 130 | assertOrPanic(TypeId(error_set_info) == TypeId.ErrorSet); | |
| 131 | assertOrPanic(error_set_info.ErrorSet.errors.len == 3); | |
| 132 | assertOrPanic(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First")); | |
| 133 | assertOrPanic(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third)); | |
| 134 | ||
| 135 | const error_union_info = @typeInfo(TestErrorSet!usize); | |
| 136 | assertOrPanic(TypeId(error_union_info) == TypeId.ErrorUnion); | |
| 137 | assertOrPanic(error_union_info.ErrorUnion.error_set == TestErrorSet); | |
| 138 | assertOrPanic(error_union_info.ErrorUnion.payload == usize); | |
| 139 | } | |
| 140 | ||
| 141 | test "type info: enum info" { | |
| 142 | testEnum(); | |
| 143 | comptime testEnum(); | |
| 144 | } | |
| 145 | ||
| 146 | fn testEnum() void { | |
| 147 | const Os = enum { | |
| 148 | Windows, | |
| 149 | Macos, | |
| 150 | Linux, | |
| 151 | FreeBSD, | |
| 152 | }; | |
| 153 | ||
| 154 | const os_info = @typeInfo(Os); | |
| 155 | assertOrPanic(TypeId(os_info) == TypeId.Enum); | |
| 156 | assertOrPanic(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); | |
| 157 | assertOrPanic(os_info.Enum.fields.len == 4); | |
| 158 | assertOrPanic(mem.eql(u8, os_info.Enum.fields[1].name, "Macos")); | |
| 159 | assertOrPanic(os_info.Enum.fields[3].value == 3); | |
| 160 | assertOrPanic(os_info.Enum.tag_type == u2); | |
| 161 | assertOrPanic(os_info.Enum.defs.len == 0); | |
| 162 | } | |
| 163 | ||
| 164 | test "type info: union info" { | |
| 165 | testUnion(); | |
| 166 | comptime testUnion(); | |
| 167 | } | |
| 168 | ||
| 169 | fn testUnion() void { | |
| 170 | const typeinfo_info = @typeInfo(TypeInfo); | |
| 171 | assertOrPanic(TypeId(typeinfo_info) == TypeId.Union); | |
| 172 | assertOrPanic(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); | |
| 173 | assertOrPanic(typeinfo_info.Union.tag_type.? == TypeId); | |
| 174 | assertOrPanic(typeinfo_info.Union.fields.len == 24); | |
| 175 | assertOrPanic(typeinfo_info.Union.fields[4].enum_field != null); | |
| 176 | assertOrPanic(typeinfo_info.Union.fields[4].enum_field.?.value == 4); | |
| 177 | assertOrPanic(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int)); | |
| 178 | assertOrPanic(typeinfo_info.Union.defs.len == 20); | |
| 179 | ||
| 180 | const TestNoTagUnion = union { | |
| 181 | Foo: void, | |
| 182 | Bar: u32, | |
| 183 | }; | |
| 184 | ||
| 185 | const notag_union_info = @typeInfo(TestNoTagUnion); | |
| 186 | assertOrPanic(TypeId(notag_union_info) == TypeId.Union); | |
| 187 | assertOrPanic(notag_union_info.Union.tag_type == null); | |
| 188 | assertOrPanic(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); | |
| 189 | assertOrPanic(notag_union_info.Union.fields.len == 2); | |
| 190 | assertOrPanic(notag_union_info.Union.fields[0].enum_field == null); | |
| 191 | assertOrPanic(notag_union_info.Union.fields[1].field_type == u32); | |
| 192 | ||
| 193 | const TestExternUnion = extern union { | |
| 194 | foo: *c_void, | |
| 195 | }; | |
| 196 | ||
| 197 | const extern_union_info = @typeInfo(TestExternUnion); | |
| 198 | assertOrPanic(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern); | |
| 199 | assertOrPanic(extern_union_info.Union.tag_type == null); | |
| 200 | assertOrPanic(extern_union_info.Union.fields[0].enum_field == null); | |
| 201 | assertOrPanic(extern_union_info.Union.fields[0].field_type == *c_void); | |
| 202 | } | |
| 203 | ||
| 204 | test "type info: struct info" { | |
| 205 | testStruct(); | |
| 206 | comptime testStruct(); | |
| 207 | } | |
| 208 | ||
| 209 | fn testStruct() void { | |
| 210 | const struct_info = @typeInfo(TestStruct); | |
| 211 | assertOrPanic(TypeId(struct_info) == TypeId.Struct); | |
| 212 | assertOrPanic(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); | |
| 213 | assertOrPanic(struct_info.Struct.fields.len == 3); | |
| 214 | assertOrPanic(struct_info.Struct.fields[1].offset == null); | |
| 215 | assertOrPanic(struct_info.Struct.fields[2].field_type == *TestStruct); | |
| 216 | assertOrPanic(struct_info.Struct.defs.len == 2); | |
| 217 | assertOrPanic(struct_info.Struct.defs[0].is_pub); | |
| 218 | assertOrPanic(!struct_info.Struct.defs[0].data.Fn.is_extern); | |
| 219 | assertOrPanic(struct_info.Struct.defs[0].data.Fn.lib_name == null); | |
| 220 | assertOrPanic(struct_info.Struct.defs[0].data.Fn.return_type == void); | |
| 221 | assertOrPanic(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void); | |
| 222 | } | |
| 223 | ||
| 224 | const TestStruct = packed struct { | |
| 225 | const Self = @This(); | |
| 226 | ||
| 227 | fieldA: usize, | |
| 228 | fieldB: void, | |
| 229 | fieldC: *Self, | |
| 230 | ||
| 231 | pub fn foo(self: *const Self) void {} | |
| 232 | }; | |
| 233 | ||
| 234 | test "type info: function type info" { | |
| 235 | testFunction(); | |
| 236 | comptime testFunction(); | |
| 237 | } | |
| 238 | ||
| 239 | fn testFunction() void { | |
| 240 | const fn_info = @typeInfo(@typeOf(foo)); | |
| 241 | assertOrPanic(TypeId(fn_info) == TypeId.Fn); | |
| 242 | assertOrPanic(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); | |
| 243 | assertOrPanic(fn_info.Fn.is_generic); | |
| 244 | assertOrPanic(fn_info.Fn.args.len == 2); | |
| 245 | assertOrPanic(fn_info.Fn.is_var_args); | |
| 246 | assertOrPanic(fn_info.Fn.return_type == null); | |
| 247 | assertOrPanic(fn_info.Fn.async_allocator_type == null); | |
| 248 | ||
| 249 | const test_instance: TestStruct = undefined; | |
| 250 | const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); | |
| 251 | assertOrPanic(TypeId(bound_fn_info) == TypeId.BoundFn); | |
| 252 | assertOrPanic(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct); | |
| 253 | } | |
| 254 | ||
| 255 | fn foo(comptime a: usize, b: bool, args: ...) usize { | |
| 256 | return 0; | |
| 257 | } | |
| 258 | ||
| 259 | test "typeInfo with comptime parameter in struct fn def" { | |
| 260 | const S = struct { | |
| 261 | pub fn func(comptime x: f32) void {} | |
| 262 | }; | |
| 263 | comptime var info = @typeInfo(S); | |
| 264 | } |
test/stage1/behavior/undefined.zig created+69| ... | ... | @@ -0,0 +1,69 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | const mem = @import("std").mem; | |
| 3 | ||
| 4 | fn initStaticArray() [10]i32 { | |
| 5 | var array: [10]i32 = undefined; | |
| 6 | array[0] = 1; | |
| 7 | array[4] = 2; | |
| 8 | array[7] = 3; | |
| 9 | array[9] = 4; | |
| 10 | return array; | |
| 11 | } | |
| 12 | const static_array = initStaticArray(); | |
| 13 | test "init static array to undefined" { | |
| 14 | assertOrPanic(static_array[0] == 1); | |
| 15 | assertOrPanic(static_array[4] == 2); | |
| 16 | assertOrPanic(static_array[7] == 3); | |
| 17 | assertOrPanic(static_array[9] == 4); | |
| 18 | ||
| 19 | comptime { | |
| 20 | assertOrPanic(static_array[0] == 1); | |
| 21 | assertOrPanic(static_array[4] == 2); | |
| 22 | assertOrPanic(static_array[7] == 3); | |
| 23 | assertOrPanic(static_array[9] == 4); | |
| 24 | } | |
| 25 | } | |
| 26 | ||
| 27 | const Foo = struct { | |
| 28 | x: i32, | |
| 29 | ||
| 30 | fn setFooXMethod(foo: *Foo) void { | |
| 31 | foo.x = 3; | |
| 32 | } | |
| 33 | }; | |
| 34 | ||
| 35 | fn setFooX(foo: *Foo) void { | |
| 36 | foo.x = 2; | |
| 37 | } | |
| 38 | ||
| 39 | test "assign undefined to struct" { | |
| 40 | comptime { | |
| 41 | var foo: Foo = undefined; | |
| 42 | setFooX(&foo); | |
| 43 | assertOrPanic(foo.x == 2); | |
| 44 | } | |
| 45 | { | |
| 46 | var foo: Foo = undefined; | |
| 47 | setFooX(&foo); | |
| 48 | assertOrPanic(foo.x == 2); | |
| 49 | } | |
| 50 | } | |
| 51 | ||
| 52 | test "assign undefined to struct with method" { | |
| 53 | comptime { | |
| 54 | var foo: Foo = undefined; | |
| 55 | foo.setFooXMethod(); | |
| 56 | assertOrPanic(foo.x == 3); | |
| 57 | } | |
| 58 | { | |
| 59 | var foo: Foo = undefined; | |
| 60 | foo.setFooXMethod(); | |
| 61 | assertOrPanic(foo.x == 3); | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 65 | test "type name of undefined" { | |
| 66 | const x = undefined; | |
| 67 | assertOrPanic(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)")); | |
| 68 | } | |
| 69 |
test/stage1/behavior/underscore.zig created+28| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | ||
| 4 | test "ignore lval with underscore" { | |
| 5 | _ = false; | |
| 6 | } | |
| 7 | ||
| 8 | test "ignore lval with underscore (for loop)" { | |
| 9 | for ([]void{}) |_, i| { | |
| 10 | for ([]void{}) |_, j| { | |
| 11 | break; | |
| 12 | } | |
| 13 | break; | |
| 14 | } | |
| 15 | } | |
| 16 | ||
| 17 | test "ignore lval with underscore (while loop)" { | |
| 18 | while (optionalReturnError()) |_| { | |
| 19 | while (optionalReturnError()) |_| { | |
| 20 | break; | |
| 21 | } else |_| {} | |
| 22 | break; | |
| 23 | } else |_| {} | |
| 24 | } | |
| 25 | ||
| 26 | fn optionalReturnError() !?u32 { | |
| 27 | return error.optionalReturnError; | |
| 28 | } |
test/stage1/behavior/union.zig created+352| ... | ... | @@ -0,0 +1,352 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | const Value = union(enum) { | |
| 4 | Int: u64, | |
| 5 | Array: [9]u8, | |
| 6 | }; | |
| 7 | ||
| 8 | const Agg = struct { | |
| 9 | val1: Value, | |
| 10 | val2: Value, | |
| 11 | }; | |
| 12 | ||
| 13 | const v1 = Value{ .Int = 1234 }; | |
| 14 | const v2 = Value{ .Array = []u8{3} ** 9 }; | |
| 15 | ||
| 16 | const err = (anyerror!Agg)(Agg{ | |
| 17 | .val1 = v1, | |
| 18 | .val2 = v2, | |
| 19 | }); | |
| 20 | ||
| 21 | const array = []Value{ | |
| 22 | v1, | |
| 23 | v2, | |
| 24 | v1, | |
| 25 | v2, | |
| 26 | }; | |
| 27 | ||
| 28 | test "unions embedded in aggregate types" { | |
| 29 | switch (array[1]) { | |
| 30 | Value.Array => |arr| assertOrPanic(arr[4] == 3), | |
| 31 | else => unreachable, | |
| 32 | } | |
| 33 | switch ((err catch unreachable).val1) { | |
| 34 | Value.Int => |x| assertOrPanic(x == 1234), | |
| 35 | else => unreachable, | |
| 36 | } | |
| 37 | } | |
| 38 | ||
| 39 | const Foo = union { | |
| 40 | float: f64, | |
| 41 | int: i32, | |
| 42 | }; | |
| 43 | ||
| 44 | test "basic unions" { | |
| 45 | var foo = Foo{ .int = 1 }; | |
| 46 | assertOrPanic(foo.int == 1); | |
| 47 | foo = Foo{ .float = 12.34 }; | |
| 48 | assertOrPanic(foo.float == 12.34); | |
| 49 | } | |
| 50 | ||
| 51 | test "comptime union field access" { | |
| 52 | comptime { | |
| 53 | var foo = Foo{ .int = 0 }; | |
| 54 | assertOrPanic(foo.int == 0); | |
| 55 | ||
| 56 | foo = Foo{ .float = 42.42 }; | |
| 57 | assertOrPanic(foo.float == 42.42); | |
| 58 | } | |
| 59 | } | |
| 60 | ||
| 61 | test "init union with runtime value" { | |
| 62 | var foo: Foo = undefined; | |
| 63 | ||
| 64 | setFloat(&foo, 12.34); | |
| 65 | assertOrPanic(foo.float == 12.34); | |
| 66 | ||
| 67 | setInt(&foo, 42); | |
| 68 | assertOrPanic(foo.int == 42); | |
| 69 | } | |
| 70 | ||
| 71 | fn setFloat(foo: *Foo, x: f64) void { | |
| 72 | foo.* = Foo{ .float = x }; | |
| 73 | } | |
| 74 | ||
| 75 | fn setInt(foo: *Foo, x: i32) void { | |
| 76 | foo.* = Foo{ .int = x }; | |
| 77 | } | |
| 78 | ||
| 79 | const FooExtern = extern union { | |
| 80 | float: f64, | |
| 81 | int: i32, | |
| 82 | }; | |
| 83 | ||
| 84 | test "basic extern unions" { | |
| 85 | var foo = FooExtern{ .int = 1 }; | |
| 86 | assertOrPanic(foo.int == 1); | |
| 87 | foo.float = 12.34; | |
| 88 | assertOrPanic(foo.float == 12.34); | |
| 89 | } | |
| 90 | ||
| 91 | const Letter = enum { | |
| 92 | A, | |
| 93 | B, | |
| 94 | C, | |
| 95 | }; | |
| 96 | const Payload = union(Letter) { | |
| 97 | A: i32, | |
| 98 | B: f64, | |
| 99 | C: bool, | |
| 100 | }; | |
| 101 | ||
| 102 | test "union with specified enum tag" { | |
| 103 | doTest(); | |
| 104 | comptime doTest(); | |
| 105 | } | |
| 106 | ||
| 107 | fn doTest() void { | |
| 108 | assertOrPanic(bar(Payload{ .A = 1234 }) == -10); | |
| 109 | } | |
| 110 | ||
| 111 | fn bar(value: Payload) i32 { | |
| 112 | assertOrPanic(Letter(value) == Letter.A); | |
| 113 | return switch (value) { | |
| 114 | Payload.A => |x| return x - 1244, | |
| 115 | Payload.B => |x| if (x == 12.34) i32(20) else 21, | |
| 116 | Payload.C => |x| if (x) i32(30) else 31, | |
| 117 | }; | |
| 118 | } | |
| 119 | ||
| 120 | const MultipleChoice = union(enum(u32)) { | |
| 121 | A = 20, | |
| 122 | B = 40, | |
| 123 | C = 60, | |
| 124 | D = 1000, | |
| 125 | }; | |
| 126 | test "simple union(enum(u32))" { | |
| 127 | var x = MultipleChoice.C; | |
| 128 | assertOrPanic(x == MultipleChoice.C); | |
| 129 | assertOrPanic(@enumToInt(@TagType(MultipleChoice)(x)) == 60); | |
| 130 | } | |
| 131 | ||
| 132 | const MultipleChoice2 = union(enum(u32)) { | |
| 133 | Unspecified1: i32, | |
| 134 | A: f32 = 20, | |
| 135 | Unspecified2: void, | |
| 136 | B: bool = 40, | |
| 137 | Unspecified3: i32, | |
| 138 | C: i8 = 60, | |
| 139 | Unspecified4: void, | |
| 140 | D: void = 1000, | |
| 141 | Unspecified5: i32, | |
| 142 | }; | |
| 143 | ||
| 144 | test "union(enum(u32)) with specified and unspecified tag values" { | |
| 145 | comptime assertOrPanic(@TagType(@TagType(MultipleChoice2)) == u32); | |
| 146 | testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | |
| 147 | comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 }); | |
| 148 | } | |
| 149 | ||
| 150 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { | |
| 151 | assertOrPanic(@enumToInt(@TagType(MultipleChoice2)(x)) == 60); | |
| 152 | assertOrPanic(1123 == switch (x) { | |
| 153 | MultipleChoice2.A => 1, | |
| 154 | MultipleChoice2.B => 2, | |
| 155 | MultipleChoice2.C => |v| i32(1000) + v, | |
| 156 | MultipleChoice2.D => 4, | |
| 157 | MultipleChoice2.Unspecified1 => 5, | |
| 158 | MultipleChoice2.Unspecified2 => 6, | |
| 159 | MultipleChoice2.Unspecified3 => 7, | |
| 160 | MultipleChoice2.Unspecified4 => 8, | |
| 161 | MultipleChoice2.Unspecified5 => 9, | |
| 162 | }); | |
| 163 | } | |
| 164 | ||
| 165 | const ExternPtrOrInt = extern union { | |
| 166 | ptr: *u8, | |
| 167 | int: u64, | |
| 168 | }; | |
| 169 | test "extern union size" { | |
| 170 | comptime assertOrPanic(@sizeOf(ExternPtrOrInt) == 8); | |
| 171 | } | |
| 172 | ||
| 173 | const PackedPtrOrInt = packed union { | |
| 174 | ptr: *u8, | |
| 175 | int: u64, | |
| 176 | }; | |
| 177 | test "extern union size" { | |
| 178 | comptime assertOrPanic(@sizeOf(PackedPtrOrInt) == 8); | |
| 179 | } | |
| 180 | ||
| 181 | const ZeroBits = union { | |
| 182 | OnlyField: void, | |
| 183 | }; | |
| 184 | test "union with only 1 field which is void should be zero bits" { | |
| 185 | comptime assertOrPanic(@sizeOf(ZeroBits) == 0); | |
| 186 | } | |
| 187 | ||
| 188 | const TheTag = enum { | |
| 189 | A, | |
| 190 | B, | |
| 191 | C, | |
| 192 | }; | |
| 193 | const TheUnion = union(TheTag) { | |
| 194 | A: i32, | |
| 195 | B: i32, | |
| 196 | C: i32, | |
| 197 | }; | |
| 198 | test "union field access gives the enum values" { | |
| 199 | assertOrPanic(TheUnion.A == TheTag.A); | |
| 200 | assertOrPanic(TheUnion.B == TheTag.B); | |
| 201 | assertOrPanic(TheUnion.C == TheTag.C); | |
| 202 | } | |
| 203 | ||
| 204 | test "cast union to tag type of union" { | |
| 205 | testCastUnionToTagType(TheUnion{ .B = 1234 }); | |
| 206 | comptime testCastUnionToTagType(TheUnion{ .B = 1234 }); | |
| 207 | } | |
| 208 | ||
| 209 | fn testCastUnionToTagType(x: TheUnion) void { | |
| 210 | assertOrPanic(TheTag(x) == TheTag.B); | |
| 211 | } | |
| 212 | ||
| 213 | test "cast tag type of union to union" { | |
| 214 | var x: Value2 = Letter2.B; | |
| 215 | assertOrPanic(Letter2(x) == Letter2.B); | |
| 216 | } | |
| 217 | const Letter2 = enum { | |
| 218 | A, | |
| 219 | B, | |
| 220 | C, | |
| 221 | }; | |
| 222 | const Value2 = union(Letter2) { | |
| 223 | A: i32, | |
| 224 | B, | |
| 225 | C, | |
| 226 | }; | |
| 227 | ||
| 228 | test "implicit cast union to its tag type" { | |
| 229 | var x: Value2 = Letter2.B; | |
| 230 | assertOrPanic(x == Letter2.B); | |
| 231 | giveMeLetterB(x); | |
| 232 | } | |
| 233 | fn giveMeLetterB(x: Letter2) void { | |
| 234 | assertOrPanic(x == Value2.B); | |
| 235 | } | |
| 236 | ||
| 237 | pub const PackThis = union(enum) { | |
| 238 | Invalid: bool, | |
| 239 | StringLiteral: u2, | |
| 240 | }; | |
| 241 | ||
| 242 | test "constant packed union" { | |
| 243 | testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }}); | |
| 244 | } | |
| 245 | ||
| 246 | fn testConstPackedUnion(expected_tokens: []const PackThis) void { | |
| 247 | assertOrPanic(expected_tokens[0].StringLiteral == 1); | |
| 248 | } | |
| 249 | ||
| 250 | test "switch on union with only 1 field" { | |
| 251 | var r: PartialInst = undefined; | |
| 252 | r = PartialInst.Compiled; | |
| 253 | switch (r) { | |
| 254 | PartialInst.Compiled => { | |
| 255 | var z: PartialInstWithPayload = undefined; | |
| 256 | z = PartialInstWithPayload{ .Compiled = 1234 }; | |
| 257 | switch (z) { | |
| 258 | PartialInstWithPayload.Compiled => |x| { | |
| 259 | assertOrPanic(x == 1234); | |
| 260 | return; | |
| 261 | }, | |
| 262 | } | |
| 263 | }, | |
| 264 | } | |
| 265 | unreachable; | |
| 266 | } | |
| 267 | ||
| 268 | const PartialInst = union(enum) { | |
| 269 | Compiled, | |
| 270 | }; | |
| 271 | ||
| 272 | const PartialInstWithPayload = union(enum) { | |
| 273 | Compiled: i32, | |
| 274 | }; | |
| 275 | ||
| 276 | test "access a member of tagged union with conflicting enum tag name" { | |
| 277 | const Bar = union(enum) { | |
| 278 | A: A, | |
| 279 | B: B, | |
| 280 | ||
| 281 | const A = u8; | |
| 282 | const B = void; | |
| 283 | }; | |
| 284 | ||
| 285 | comptime assertOrPanic(Bar.A == u8); | |
| 286 | } | |
| 287 | ||
| 288 | test "tagged union initialization with runtime void" { | |
| 289 | assertOrPanic(testTaggedUnionInit({})); | |
| 290 | } | |
| 291 | ||
| 292 | const TaggedUnionWithAVoid = union(enum) { | |
| 293 | A, | |
| 294 | B: i32, | |
| 295 | }; | |
| 296 | ||
| 297 | fn testTaggedUnionInit(x: var) bool { | |
| 298 | const y = TaggedUnionWithAVoid{ .A = x }; | |
| 299 | return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A; | |
| 300 | } | |
| 301 | ||
| 302 | pub const UnionEnumNoPayloads = union(enum) { | |
| 303 | A, | |
| 304 | B, | |
| 305 | }; | |
| 306 | ||
| 307 | test "tagged union with no payloads" { | |
| 308 | const a = UnionEnumNoPayloads{ .B = {} }; | |
| 309 | switch (a) { | |
| 310 | @TagType(UnionEnumNoPayloads).A => @panic("wrong"), | |
| 311 | @TagType(UnionEnumNoPayloads).B => {}, | |
| 312 | } | |
| 313 | } | |
| 314 | ||
| 315 | test "union with only 1 field casted to its enum type" { | |
| 316 | const Literal = union(enum) { | |
| 317 | Number: f64, | |
| 318 | Bool: bool, | |
| 319 | }; | |
| 320 | ||
| 321 | const Expr = union(enum) { | |
| 322 | Literal: Literal, | |
| 323 | }; | |
| 324 | ||
| 325 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | |
| 326 | const Tag = @TagType(Expr); | |
| 327 | comptime assertOrPanic(@TagType(Tag) == comptime_int); | |
| 328 | var t = Tag(e); | |
| 329 | assertOrPanic(t == Expr.Literal); | |
| 330 | } | |
| 331 | ||
| 332 | test "union with only 1 field casted to its enum type which has enum value specified" { | |
| 333 | const Literal = union(enum) { | |
| 334 | Number: f64, | |
| 335 | Bool: bool, | |
| 336 | }; | |
| 337 | ||
| 338 | const Tag = enum { | |
| 339 | Literal = 33, | |
| 340 | }; | |
| 341 | ||
| 342 | const Expr = union(Tag) { | |
| 343 | Literal: Literal, | |
| 344 | }; | |
| 345 | ||
| 346 | var e = Expr{ .Literal = Literal{ .Bool = true } }; | |
| 347 | comptime assertOrPanic(@TagType(Tag) == comptime_int); | |
| 348 | var t = Tag(e); | |
| 349 | assertOrPanic(t == Expr.Literal); | |
| 350 | assertOrPanic(@enumToInt(t) == 33); | |
| 351 | comptime assertOrPanic(@enumToInt(t) == 33); | |
| 352 | } |
test/stage1/behavior/var_args.zig created+84| ... | ... | @@ -0,0 +1,84 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | fn add(args: ...) i32 { | |
| 4 | var sum = i32(0); | |
| 5 | { | |
| 6 | comptime var i: usize = 0; | |
| 7 | inline while (i < args.len) : (i += 1) { | |
| 8 | sum += args[i]; | |
| 9 | } | |
| 10 | } | |
| 11 | return sum; | |
| 12 | } | |
| 13 | ||
| 14 | test "add arbitrary args" { | |
| 15 | assertOrPanic(add(i32(1), i32(2), i32(3), i32(4)) == 10); | |
| 16 | assertOrPanic(add(i32(1234)) == 1234); | |
| 17 | assertOrPanic(add() == 0); | |
| 18 | } | |
| 19 | ||
| 20 | fn readFirstVarArg(args: ...) void { | |
| 21 | const value = args[0]; | |
| 22 | } | |
| 23 | ||
| 24 | test "send void arg to var args" { | |
| 25 | readFirstVarArg({}); | |
| 26 | } | |
| 27 | ||
| 28 | test "pass args directly" { | |
| 29 | assertOrPanic(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10); | |
| 30 | assertOrPanic(addSomeStuff(i32(1234)) == 1234); | |
| 31 | assertOrPanic(addSomeStuff() == 0); | |
| 32 | } | |
| 33 | ||
| 34 | fn addSomeStuff(args: ...) i32 { | |
| 35 | return add(args); | |
| 36 | } | |
| 37 | ||
| 38 | test "runtime parameter before var args" { | |
| 39 | assertOrPanic(extraFn(10) == 0); | |
| 40 | assertOrPanic(extraFn(10, false) == 1); | |
| 41 | assertOrPanic(extraFn(10, false, true) == 2); | |
| 42 | ||
| 43 | // TODO issue #313 | |
| 44 | //comptime { | |
| 45 | // assertOrPanic(extraFn(10) == 0); | |
| 46 | // assertOrPanic(extraFn(10, false) == 1); | |
| 47 | // assertOrPanic(extraFn(10, false, true) == 2); | |
| 48 | //} | |
| 49 | } | |
| 50 | ||
| 51 | fn extraFn(extra: u32, args: ...) usize { | |
| 52 | if (args.len >= 1) { | |
| 53 | assertOrPanic(args[0] == false); | |
| 54 | } | |
| 55 | if (args.len >= 2) { | |
| 56 | assertOrPanic(args[1] == true); | |
| 57 | } | |
| 58 | return args.len; | |
| 59 | } | |
| 60 | ||
| 61 | const foos = []fn (...) bool{ | |
| 62 | foo1, | |
| 63 | foo2, | |
| 64 | }; | |
| 65 | ||
| 66 | fn foo1(args: ...) bool { | |
| 67 | return true; | |
| 68 | } | |
| 69 | fn foo2(args: ...) bool { | |
| 70 | return false; | |
| 71 | } | |
| 72 | ||
| 73 | test "array of var args functions" { | |
| 74 | assertOrPanic(foos[0]()); | |
| 75 | assertOrPanic(!foos[1]()); | |
| 76 | } | |
| 77 | ||
| 78 | test "pass zero length array to var args param" { | |
| 79 | doNothingWithFirstArg(""); | |
| 80 | } | |
| 81 | ||
| 82 | fn doNothingWithFirstArg(args: ...) void { | |
| 83 | const a = args[0]; | |
| 84 | } |
test/stage1/behavior/void.zig created+35| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | const Foo = struct { | |
| 4 | a: void, | |
| 5 | b: i32, | |
| 6 | c: void, | |
| 7 | }; | |
| 8 | ||
| 9 | test "compare void with void compile time known" { | |
| 10 | comptime { | |
| 11 | const foo = Foo{ | |
| 12 | .a = {}, | |
| 13 | .b = 1, | |
| 14 | .c = {}, | |
| 15 | }; | |
| 16 | assertOrPanic(foo.a == {}); | |
| 17 | } | |
| 18 | } | |
| 19 | ||
| 20 | test "iterate over a void slice" { | |
| 21 | var j: usize = 0; | |
| 22 | for (times(10)) |_, i| { | |
| 23 | assertOrPanic(i == j); | |
| 24 | j += 1; | |
| 25 | } | |
| 26 | } | |
| 27 | ||
| 28 | fn times(n: usize) []const void { | |
| 29 | return ([*]void)(undefined)[0..n]; | |
| 30 | } | |
| 31 | ||
| 32 | test "void optional" { | |
| 33 | var x: ?void = {}; | |
| 34 | assertOrPanic(x != null); | |
| 35 | } |
test/stage1/behavior/while.zig created+228| ... | ... | @@ -0,0 +1,228 @@ |
| 1 | const assertOrPanic = @import("std").debug.assertOrPanic; | |
| 2 | ||
| 3 | test "while loop" { | |
| 4 | var i: i32 = 0; | |
| 5 | while (i < 4) { | |
| 6 | i += 1; | |
| 7 | } | |
| 8 | assertOrPanic(i == 4); | |
| 9 | assertOrPanic(whileLoop1() == 1); | |
| 10 | } | |
| 11 | fn whileLoop1() i32 { | |
| 12 | return whileLoop2(); | |
| 13 | } | |
| 14 | fn whileLoop2() i32 { | |
| 15 | while (true) { | |
| 16 | return 1; | |
| 17 | } | |
| 18 | } | |
| 19 | ||
| 20 | test "static eval while" { | |
| 21 | assertOrPanic(static_eval_while_number == 1); | |
| 22 | } | |
| 23 | const static_eval_while_number = staticWhileLoop1(); | |
| 24 | fn staticWhileLoop1() i32 { | |
| 25 | return whileLoop2(); | |
| 26 | } | |
| 27 | fn staticWhileLoop2() i32 { | |
| 28 | while (true) { | |
| 29 | return 1; | |
| 30 | } | |
| 31 | } | |
| 32 | ||
| 33 | test "continue and break" { | |
| 34 | runContinueAndBreakTest(); | |
| 35 | assertOrPanic(continue_and_break_counter == 8); | |
| 36 | } | |
| 37 | var continue_and_break_counter: i32 = 0; | |
| 38 | fn runContinueAndBreakTest() void { | |
| 39 | var i: i32 = 0; | |
| 40 | while (true) { | |
| 41 | continue_and_break_counter += 2; | |
| 42 | i += 1; | |
| 43 | if (i < 4) { | |
| 44 | continue; | |
| 45 | } | |
| 46 | break; | |
| 47 | } | |
| 48 | assertOrPanic(i == 4); | |
| 49 | } | |
| 50 | ||
| 51 | test "return with implicit cast from while loop" { | |
| 52 | returnWithImplicitCastFromWhileLoopTest() catch unreachable; | |
| 53 | } | |
| 54 | fn returnWithImplicitCastFromWhileLoopTest() anyerror!void { | |
| 55 | while (true) { | |
| 56 | return; | |
| 57 | } | |
| 58 | } | |
| 59 | ||
| 60 | test "while with continue expression" { | |
| 61 | var sum: i32 = 0; | |
| 62 | { | |
| 63 | var i: i32 = 0; | |
| 64 | while (i < 10) : (i += 1) { | |
| 65 | if (i == 5) continue; | |
| 66 | sum += i; | |
| 67 | } | |
| 68 | } | |
| 69 | assertOrPanic(sum == 40); | |
| 70 | } | |
| 71 | ||
| 72 | test "while with else" { | |
| 73 | var sum: i32 = 0; | |
| 74 | var i: i32 = 0; | |
| 75 | var got_else: i32 = 0; | |
| 76 | while (i < 10) : (i += 1) { | |
| 77 | sum += 1; | |
| 78 | } else { | |
| 79 | got_else += 1; | |
| 80 | } | |
| 81 | assertOrPanic(sum == 10); | |
| 82 | assertOrPanic(got_else == 1); | |
| 83 | } | |
| 84 | ||
| 85 | test "while with optional as condition" { | |
| 86 | numbers_left = 10; | |
| 87 | var sum: i32 = 0; | |
| 88 | while (getNumberOrNull()) |value| { | |
| 89 | sum += value; | |
| 90 | } | |
| 91 | assertOrPanic(sum == 45); | |
| 92 | } | |
| 93 | ||
| 94 | test "while with optional as condition with else" { | |
| 95 | numbers_left = 10; | |
| 96 | var sum: i32 = 0; | |
| 97 | var got_else: i32 = 0; | |
| 98 | while (getNumberOrNull()) |value| { | |
| 99 | sum += value; | |
| 100 | assertOrPanic(got_else == 0); | |
| 101 | } else { | |
| 102 | got_else += 1; | |
| 103 | } | |
| 104 | assertOrPanic(sum == 45); | |
| 105 | assertOrPanic(got_else == 1); | |
| 106 | } | |
| 107 | ||
| 108 | test "while with error union condition" { | |
| 109 | numbers_left = 10; | |
| 110 | var sum: i32 = 0; | |
| 111 | var got_else: i32 = 0; | |
| 112 | while (getNumberOrErr()) |value| { | |
| 113 | sum += value; | |
| 114 | } else |err| { | |
| 115 | assertOrPanic(err == error.OutOfNumbers); | |
| 116 | got_else += 1; | |
| 117 | } | |
| 118 | assertOrPanic(sum == 45); | |
| 119 | assertOrPanic(got_else == 1); | |
| 120 | } | |
| 121 | ||
| 122 | var numbers_left: i32 = undefined; | |
| 123 | fn getNumberOrErr() anyerror!i32 { | |
| 124 | return if (numbers_left == 0) error.OutOfNumbers else x: { | |
| 125 | numbers_left -= 1; | |
| 126 | break :x numbers_left; | |
| 127 | }; | |
| 128 | } | |
| 129 | fn getNumberOrNull() ?i32 { | |
| 130 | return if (numbers_left == 0) null else x: { | |
| 131 | numbers_left -= 1; | |
| 132 | break :x numbers_left; | |
| 133 | }; | |
| 134 | } | |
| 135 | ||
| 136 | test "while on optional with else result follow else prong" { | |
| 137 | const result = while (returnNull()) |value| { | |
| 138 | break value; | |
| 139 | } else | |
| 140 | i32(2); | |
| 141 | assertOrPanic(result == 2); | |
| 142 | } | |
| 143 | ||
| 144 | test "while on optional with else result follow break prong" { | |
| 145 | const result = while (returnOptional(10)) |value| { | |
| 146 | break value; | |
| 147 | } else | |
| 148 | i32(2); | |
| 149 | assertOrPanic(result == 10); | |
| 150 | } | |
| 151 | ||
| 152 | test "while on error union with else result follow else prong" { | |
| 153 | const result = while (returnError()) |value| { | |
| 154 | break value; | |
| 155 | } else |err| | |
| 156 | i32(2); | |
| 157 | assertOrPanic(result == 2); | |
| 158 | } | |
| 159 | ||
| 160 | test "while on error union with else result follow break prong" { | |
| 161 | const result = while (returnSuccess(10)) |value| { | |
| 162 | break value; | |
| 163 | } else |err| | |
| 164 | i32(2); | |
| 165 | assertOrPanic(result == 10); | |
| 166 | } | |
| 167 | ||
| 168 | test "while on bool with else result follow else prong" { | |
| 169 | const result = while (returnFalse()) { | |
| 170 | break i32(10); | |
| 171 | } else | |
| 172 | i32(2); | |
| 173 | assertOrPanic(result == 2); | |
| 174 | } | |
| 175 | ||
| 176 | test "while on bool with else result follow break prong" { | |
| 177 | const result = while (returnTrue()) { | |
| 178 | break i32(10); | |
| 179 | } else | |
| 180 | i32(2); | |
| 181 | assertOrPanic(result == 10); | |
| 182 | } | |
| 183 | ||
| 184 | test "break from outer while loop" { | |
| 185 | testBreakOuter(); | |
| 186 | comptime testBreakOuter(); | |
| 187 | } | |
| 188 | ||
| 189 | fn testBreakOuter() void { | |
| 190 | outer: while (true) { | |
| 191 | while (true) { | |
| 192 | break :outer; | |
| 193 | } | |
| 194 | } | |
| 195 | } | |
| 196 | ||
| 197 | test "continue outer while loop" { | |
| 198 | testContinueOuter(); | |
| 199 | comptime testContinueOuter(); | |
| 200 | } | |
| 201 | ||
| 202 | fn testContinueOuter() void { | |
| 203 | var i: usize = 0; | |
| 204 | outer: while (i < 10) : (i += 1) { | |
| 205 | while (true) { | |
| 206 | continue :outer; | |
| 207 | } | |
| 208 | } | |
| 209 | } | |
| 210 | ||
| 211 | fn returnNull() ?i32 { | |
| 212 | return null; | |
| 213 | } | |
| 214 | fn returnOptional(x: i32) ?i32 { | |
| 215 | return x; | |
| 216 | } | |
| 217 | fn returnError() anyerror!i32 { | |
| 218 | return error.YouWantedAnError; | |
| 219 | } | |
| 220 | fn returnSuccess(x: i32) anyerror!i32 { | |
| 221 | return x; | |
| 222 | } | |
| 223 | fn returnFalse() bool { | |
| 224 | return false; | |
| 225 | } | |
| 226 | fn returnTrue() bool { | |
| 227 | return true; | |
| 228 | } |
test/stage1/behavior/widening.zig created+28| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | const mem = std.mem; | |
| 4 | ||
| 5 | test "integer widening" { | |
| 6 | var a: u8 = 250; | |
| 7 | var b: u16 = a; | |
| 8 | var c: u32 = b; | |
| 9 | var d: u64 = c; | |
| 10 | var e: u64 = d; | |
| 11 | var f: u128 = e; | |
| 12 | assertOrPanic(f == a); | |
| 13 | } | |
| 14 | ||
| 15 | test "implicit unsigned integer to signed integer" { | |
| 16 | var a: u8 = 250; | |
| 17 | var b: i16 = a; | |
| 18 | assertOrPanic(b == 250); | |
| 19 | } | |
| 20 | ||
| 21 | test "float widening" { | |
| 22 | var a: f16 = 12.34; | |
| 23 | var b: f32 = a; | |
| 24 | var c: f64 = b; | |
| 25 | var d: f128 = c; | |
| 26 | assertOrPanic(d == a); | |
| 27 | } | |
| 28 |