| author | |
| committer | |
| log | d92ae20f459c3ac491a0f5ef8aa42e8ac37634c8 |
| tree | 178cba215ccb255b88bc7b1b487f1836f5f2f196 |
| parent | f1e5be96860406d7a4239b174c896799d8fd6545 |
closes #227 files changed, 115 insertions(+), 55 deletions(-)
CMakeLists.txt+1| ... | @@ -216,6 +216,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/linux_x86_64.zig" DESTINATION "${ZIG_STD_ | ... | @@ -216,6 +216,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/linux_x86_64.zig" DESTINATION "${ZIG_STD_ |
| 216 | install(FILES "${CMAKE_SOURCE_DIR}/std/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}") | 216 | install(FILES "${CMAKE_SOURCE_DIR}/std/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}") |
| 217 | install(FILES "${CMAKE_SOURCE_DIR}/std/mem.zig" DESTINATION "${ZIG_STD_DEST}") | 217 | install(FILES "${CMAKE_SOURCE_DIR}/std/mem.zig" DESTINATION "${ZIG_STD_DEST}") |
| 218 | install(FILES "${CMAKE_SOURCE_DIR}/std/list.zig" DESTINATION "${ZIG_STD_DEST}") | 218 | install(FILES "${CMAKE_SOURCE_DIR}/std/list.zig" DESTINATION "${ZIG_STD_DEST}") |
| 219 | install(FILES "${CMAKE_SOURCE_DIR}/std/hash_map.zig" DESTINATION "${ZIG_STD_DEST}") | ||
| 219 | 220 | ||
| 220 | add_executable(run_tests ${TEST_SOURCES}) | 221 | add_executable(run_tests ${TEST_SOURCES}) |
| 221 | target_link_libraries(run_tests) | 222 | target_link_libraries(run_tests) |
src/analyze.cpp+18-5| ... | @@ -4014,15 +4014,28 @@ static TypeTableEntry *analyze_if(CodeGen *g, ImportTableEntry *import, BlockCon | ... | @@ -4014,15 +4014,28 @@ static TypeTableEntry *analyze_if(CodeGen *g, ImportTableEntry *import, BlockCon |
| 4014 | else_context = parent_context; | 4014 | else_context = parent_context; |
| 4015 | } | 4015 | } |
| 4016 | 4016 | ||
| 4017 | TypeTableEntry *then_type = analyze_expression(g, import, then_context, expected_type, *then_node); | 4017 | TypeTableEntry *then_type = nullptr; |
| 4018 | TypeTableEntry *else_type = analyze_expression(g, import, else_context, expected_type, *else_node); | 4018 | TypeTableEntry *else_type = nullptr; |
| 4019 | 4019 | ||
| 4020 | if (then_type->id == TypeTableEntryIdInvalid || else_type->id == TypeTableEntryIdInvalid) { | 4020 | if (!then_context->codegen_excluded) { |
| 4021 | return g->builtin_types.entry_invalid; | 4021 | then_type = analyze_expression(g, import, then_context, expected_type, *then_node); |
| 4022 | if (then_type->id == TypeTableEntryIdInvalid) { | ||
| 4023 | return g->builtin_types.entry_invalid; | ||
| 4024 | } | ||
| 4025 | } | ||
| 4026 | if (!else_context->codegen_excluded) { | ||
| 4027 | else_type = analyze_expression(g, import, else_context, expected_type, *else_node); | ||
| 4028 | if (else_type->id == TypeTableEntryIdInvalid) { | ||
| 4029 | return g->builtin_types.entry_invalid; | ||
| 4030 | } | ||
| 4022 | } | 4031 | } |
| 4023 | 4032 | ||
| 4024 | TypeTableEntry *result_type; | 4033 | TypeTableEntry *result_type; |
| 4025 | if (expected_type) { | 4034 | if (then_context->codegen_excluded) { |
| 4035 | result_type = else_type; | ||
| 4036 | } else if (else_context->codegen_excluded) { | ||
| 4037 | result_type = then_type; | ||
| 4038 | } else if (expected_type) { | ||
| 4026 | result_type = (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type; | 4039 | result_type = (then_type->id == TypeTableEntryIdUnreachable) ? else_type : then_type; |
| 4027 | } else { | 4040 | } else { |
| 4028 | AstNode *op_nodes[] = {*then_node, *else_node}; | 4041 | AstNode *op_nodes[] = {*then_node, *else_node}; |
src/codegen.cpp+42-25| ... | @@ -2501,6 +2501,33 @@ static void gen_var_debug_decl(CodeGen *g, VariableTableEntry *var) { | ... | @@ -2501,6 +2501,33 @@ static void gen_var_debug_decl(CodeGen *g, VariableTableEntry *var) { |
| 2501 | LLVMGetInsertBlock(g->builder)); | 2501 | LLVMGetInsertBlock(g->builder)); |
| 2502 | } | 2502 | } |
| 2503 | 2503 | ||
| 2504 | static LLVMValueRef gen_if_var_then_block(CodeGen *g, AstNode *node, VariableTableEntry *variable, bool maybe_is_ptr, | ||
| 2505 | LLVMValueRef init_val, TypeTableEntry *child_type, AstNode *then_node) | ||
| 2506 | { | ||
| 2507 | if (node->data.if_var_expr.var_is_ptr) { | ||
| 2508 | LLVMValueRef payload_ptr; | ||
| 2509 | if (maybe_is_ptr) { | ||
| 2510 | zig_panic("TODO"); | ||
| 2511 | } else { | ||
| 2512 | payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, ""); | ||
| 2513 | } | ||
| 2514 | LLVMBuildStore(g->builder, payload_ptr, variable->value_ref); | ||
| 2515 | } else { | ||
| 2516 | LLVMValueRef payload_val; | ||
| 2517 | if (maybe_is_ptr) { | ||
| 2518 | payload_val = init_val; | ||
| 2519 | } else { | ||
| 2520 | LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, ""); | ||
| 2521 | payload_val = get_handle_value(g, node, payload_ptr, child_type); | ||
| 2522 | } | ||
| 2523 | gen_assign_raw(g, node, BinOpTypeAssign, variable->value_ref, payload_val, | ||
| 2524 | variable->type, child_type); | ||
| 2525 | } | ||
| 2526 | gen_var_debug_decl(g, variable); | ||
| 2527 | |||
| 2528 | return gen_expr(g, then_node); | ||
| 2529 | } | ||
| 2530 | |||
| 2504 | static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { | 2531 | static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { |
| 2505 | assert(node->type == NodeTypeIfVarExpr); | 2532 | assert(node->type == NodeTypeIfVarExpr); |
| 2506 | assert(node->data.if_var_expr.var_decl.expr); | 2533 | assert(node->data.if_var_expr.var_decl.expr); |
| ... | @@ -2514,8 +2541,21 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { | ... | @@ -2514,8 +2541,21 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { |
| 2514 | 2541 | ||
| 2515 | LLVMValueRef init_val = gen_expr(g, var_decl->expr); | 2542 | LLVMValueRef init_val = gen_expr(g, var_decl->expr); |
| 2516 | 2543 | ||
| 2517 | LLVMValueRef cond_value; | 2544 | |
| 2545 | AstNode *then_node = node->data.if_var_expr.then_block; | ||
| 2546 | AstNode *else_node = node->data.if_var_expr.else_node; | ||
| 2518 | bool maybe_is_ptr = child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; | 2547 | bool maybe_is_ptr = child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn; |
| 2548 | |||
| 2549 | ConstExprValue *const_val = &get_resolved_expr(var_decl->expr)->const_val; | ||
| 2550 | if (const_val->ok) { | ||
| 2551 | if (const_val->data.x_maybe) { | ||
| 2552 | return gen_if_var_then_block(g, node, variable, maybe_is_ptr, init_val, child_type, then_node); | ||
| 2553 | } else { | ||
| 2554 | return gen_expr(g, else_node); | ||
| 2555 | } | ||
| 2556 | } | ||
| 2557 | |||
| 2558 | LLVMValueRef cond_value; | ||
| 2519 | if (maybe_is_ptr) { | 2559 | if (maybe_is_ptr) { |
| 2520 | set_debug_source_node(g, node); | 2560 | set_debug_source_node(g, node); |
| 2521 | cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), ""); | 2561 | cond_value = LLVMBuildICmp(g->builder, LLVMIntNE, init_val, LLVMConstNull(child_type->type_ref), ""); |
| ... | @@ -2525,9 +2565,6 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { | ... | @@ -2525,9 +2565,6 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { |
| 2525 | cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, ""); | 2565 | cond_value = LLVMBuildLoad(g->builder, maybe_field_ptr, ""); |
| 2526 | } | 2566 | } |
| 2527 | 2567 | ||
| 2528 | AstNode *then_node = node->data.if_var_expr.then_block; | ||
| 2529 | AstNode *else_node = node->data.if_var_expr.else_node; | ||
| 2530 | |||
| 2531 | TypeTableEntry *then_type = get_expr_type(then_node); | 2568 | TypeTableEntry *then_type = get_expr_type(then_node); |
| 2532 | TypeTableEntry *else_type = get_expr_type(else_node); | 2569 | TypeTableEntry *else_type = get_expr_type(else_node); |
| 2533 | 2570 | ||
| ... | @@ -2548,28 +2585,8 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { | ... | @@ -2548,28 +2585,8 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) { |
| 2548 | LLVMBuildCondBr(g->builder, cond_value, then_block, else_block); | 2585 | LLVMBuildCondBr(g->builder, cond_value, then_block, else_block); |
| 2549 | 2586 | ||
| 2550 | LLVMPositionBuilderAtEnd(g->builder, then_block); | 2587 | LLVMPositionBuilderAtEnd(g->builder, then_block); |
| 2551 | if (node->data.if_var_expr.var_is_ptr) { | 2588 | LLVMValueRef then_expr_result = gen_if_var_then_block(g, node, variable, maybe_is_ptr, init_val, child_type, then_node); |
| 2552 | LLVMValueRef payload_ptr; | ||
| 2553 | if (maybe_is_ptr) { | ||
| 2554 | zig_panic("TODO"); | ||
| 2555 | } else { | ||
| 2556 | payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, ""); | ||
| 2557 | } | ||
| 2558 | LLVMBuildStore(g->builder, payload_ptr, variable->value_ref); | ||
| 2559 | } else { | ||
| 2560 | LLVMValueRef payload_val; | ||
| 2561 | if (maybe_is_ptr) { | ||
| 2562 | payload_val = init_val; | ||
| 2563 | } else { | ||
| 2564 | LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, init_val, 0, ""); | ||
| 2565 | payload_val = get_handle_value(g, node, payload_ptr, child_type); | ||
| 2566 | } | ||
| 2567 | gen_assign_raw(g, node, BinOpTypeAssign, variable->value_ref, payload_val, | ||
| 2568 | variable->type, child_type); | ||
| 2569 | } | ||
| 2570 | gen_var_debug_decl(g, variable); | ||
| 2571 | 2589 | ||
| 2572 | LLVMValueRef then_expr_result = gen_expr(g, then_node); | ||
| 2573 | if (then_endif_reachable) { | 2590 | if (then_endif_reachable) { |
| 2574 | LLVMBuildBr(g->builder, endif_block); | 2591 | LLVMBuildBr(g->builder, endif_block); |
| 2575 | } | 2592 | } |
std/hash_map.zig+49-21| ... | @@ -4,17 +4,20 @@ const mem = @import("mem.zig"); | ... | @@ -4,17 +4,20 @@ const mem = @import("mem.zig"); |
| 4 | const Allocator = mem.Allocator; | 4 | const Allocator = mem.Allocator; |
| 5 | 5 | ||
| 6 | const want_modification_safety = !@compile_var("is_release"); | 6 | const want_modification_safety = !@compile_var("is_release"); |
| 7 | const debug_u32 = if (want_modification_safety) void else u32; | 7 | const debug_u32 = if (want_modification_safety) u32 else void; |
| 8 | 8 | ||
| 9 | pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)->bool) { | 9 | pub struct SmallHashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)->bool, STATIC_SIZE: isize) { |
| 10 | entries: []Entry, | 10 | entries: []Entry, |
| 11 | size: isize, | 11 | size: isize, |
| 12 | max_distance_from_start_index: isize, | 12 | max_distance_from_start_index: isize, |
| 13 | allocator: &Allocator, | 13 | allocator: &Allocator, |
| 14 | // if the hash map is small enough, we use linear search through these | ||
| 15 | // entries instead of allocating memory | ||
| 16 | prealloc_entries: [STATIC_SIZE]Entry, | ||
| 14 | // this is used to detect bugs where a hashtable is edited while an iterator is running. | 17 | // this is used to detect bugs where a hashtable is edited while an iterator is running. |
| 15 | modification_count: debug_u32, | 18 | modification_count: debug_u32, |
| 16 | 19 | ||
| 17 | const Self = HashMap(K, V, hash, eql); | 20 | const Self = SmallHashMap(K, V, hash, eql, STATIC_SIZE); |
| 18 | 21 | ||
| 19 | pub struct Entry { | 22 | pub struct Entry { |
| 20 | used: bool, | 23 | used: bool, |
| ... | @@ -49,14 +52,20 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- | ... | @@ -49,14 +52,20 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- |
| 49 | } | 52 | } |
| 50 | } | 53 | } |
| 51 | 54 | ||
| 52 | pub fn init(hm: &Self, allocator: &Allocator, capacity: isize) { | 55 | pub fn init(hm: &Self, allocator: &Allocator) { |
| 53 | assert(capacity > 0); | 56 | hm.entries = hm.prealloc_entries[0...]; |
| 54 | hm.allocator = allocator; | 57 | hm.allocator = allocator; |
| 55 | hm.init_capacity(capacity); | 58 | hm.size = 0; |
| 59 | hm.max_distance_from_start_index = 0; | ||
| 60 | for (hm.entries) |*entry| { | ||
| 61 | entry.used = false; | ||
| 62 | } | ||
| 56 | } | 63 | } |
| 57 | 64 | ||
| 58 | pub fn deinit(hm: &Self) { | 65 | pub fn deinit(hm: &Self) { |
| 59 | hm.allocator.free(hm.allocator, ([]u8)(hm.entries)); | 66 | if (hm.entries.ptr != &hm.prealloc_entries[0]) { |
| 67 | hm.allocator.free(hm.allocator, ([]u8)(hm.entries)); | ||
| 68 | } | ||
| 60 | } | 69 | } |
| 61 | 70 | ||
| 62 | pub fn clear(hm: &Self) { | 71 | pub fn clear(hm: &Self) { |
| ... | @@ -68,26 +77,35 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- | ... | @@ -68,26 +77,35 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- |
| 68 | hm.increment_modification_count(); | 77 | hm.increment_modification_count(); |
| 69 | } | 78 | } |
| 70 | 79 | ||
| 71 | pub fn put(hm: &Self, key: K, value: V) { | 80 | pub fn put(hm: &Self, key: K, value: V) -> %void { |
| 72 | hm.increment_modification_count(); | 81 | hm.increment_modification_count(); |
| 73 | hm.internal_put(key, value); | ||
| 74 | 82 | ||
| 75 | // if we get too full (60%), double the capacity | 83 | const resize = if (hm.entries.ptr == &hm.prealloc_entries[0]) { |
| 76 | if (hm.size * 5 >= hm.entries.len * 3) { | 84 | // preallocated entries table is full |
| 85 | hm.size == hm.entries.len | ||
| 86 | } else { | ||
| 87 | // if we get too full (60%), double the capacity | ||
| 88 | hm.size * 5 >= hm.entries.len * 3 | ||
| 89 | }; | ||
| 90 | if (resize) { | ||
| 77 | const old_entries = hm.entries; | 91 | const old_entries = hm.entries; |
| 78 | hm.init_capacity(hm.entries.len * 2); | 92 | %return hm.init_capacity(hm.entries.len * 2); |
| 79 | // dump all of the old elements into the new table | 93 | // dump all of the old elements into the new table |
| 80 | for (old_entries) |*old_entry| { | 94 | for (old_entries) |*old_entry| { |
| 81 | if (old_entry.used) { | 95 | if (old_entry.used) { |
| 82 | hm.internal_put(old_entry.key, old_entry.value); | 96 | hm.internal_put(old_entry.key, old_entry.value); |
| 83 | } | 97 | } |
| 84 | } | 98 | } |
| 85 | hm.allocator.free(hm.allocator, ([]u8)(old_entries)); | 99 | if (old_entries.ptr != &hm.prealloc_entries[0]) { |
| 100 | hm.allocator.free(hm.allocator, ([]u8)(old_entries)); | ||
| 101 | } | ||
| 86 | } | 102 | } |
| 103 | |||
| 104 | hm.internal_put(key, value); | ||
| 87 | } | 105 | } |
| 88 | 106 | ||
| 89 | pub fn get(hm: &Self, key: K) { | 107 | pub fn get(hm: &Self, key: K) -> ?&Entry { |
| 90 | return internal_get(key); | 108 | return hm.internal_get(key); |
| 91 | } | 109 | } |
| 92 | 110 | ||
| 93 | pub fn remove(hm: &Self, key: K) { | 111 | pub fn remove(hm: &Self, key: K) { |
| ... | @@ -95,7 +113,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- | ... | @@ -95,7 +113,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- |
| 95 | const start_index = hm.key_to_index(key); | 113 | const start_index = hm.key_to_index(key); |
| 96 | {var roll_over: isize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) { | 114 | {var roll_over: isize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) { |
| 97 | const index = (start_index + roll_over) % hm.entries.len; | 115 | const index = (start_index + roll_over) % hm.entries.len; |
| 98 | const entry = &hm.entries[index]; | 116 | var entry = &hm.entries[index]; |
| 99 | 117 | ||
| 100 | assert(entry.used); // key not found | 118 | assert(entry.used); // key not found |
| 101 | 119 | ||
| ... | @@ -127,7 +145,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- | ... | @@ -127,7 +145,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- |
| 127 | }; | 145 | }; |
| 128 | } | 146 | } |
| 129 | 147 | ||
| 130 | fn init_capacity(hm: &Self, capacity: isize) { | 148 | fn init_capacity(hm: &Self, capacity: isize) -> %void { |
| 131 | hm.entries = ([]Entry)(%return hm.allocator.alloc(hm.allocator, capacity * @sizeof(Entry))); | 149 | hm.entries = ([]Entry)(%return hm.allocator.alloc(hm.allocator, capacity * @sizeof(Entry))); |
| 132 | hm.size = 0; | 150 | hm.size = 0; |
| 133 | hm.max_distance_from_start_index = 0; | 151 | hm.max_distance_from_start_index = 0; |
| ... | @@ -145,7 +163,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- | ... | @@ -145,7 +163,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- |
| 145 | fn internal_put(hm: &Self, orig_key: K, orig_value: V) { | 163 | fn internal_put(hm: &Self, orig_key: K, orig_value: V) { |
| 146 | var key = orig_key; | 164 | var key = orig_key; |
| 147 | var value = orig_value; | 165 | var value = orig_value; |
| 148 | const start_index = key_to_index(key); | 166 | const start_index = hm.key_to_index(key); |
| 149 | var roll_over: isize = 0; | 167 | var roll_over: isize = 0; |
| 150 | var distance_from_start_index: isize = 0; | 168 | var distance_from_start_index: isize = 0; |
| 151 | while (roll_over < hm.entries.len; {roll_over += 1; distance_from_start_index += 1}) { | 169 | while (roll_over < hm.entries.len; {roll_over += 1; distance_from_start_index += 1}) { |
| ... | @@ -190,7 +208,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- | ... | @@ -190,7 +208,7 @@ pub struct HashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)- |
| 190 | } | 208 | } |
| 191 | 209 | ||
| 192 | fn internal_get(hm: &Self, key: K) -> ?&Entry { | 210 | fn internal_get(hm: &Self, key: K) -> ?&Entry { |
| 193 | const start_index = key_to_index(key); | 211 | const start_index = hm.key_to_index(key); |
| 194 | {var roll_over: isize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) { | 212 | {var roll_over: isize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) { |
| 195 | const index = (start_index + roll_over) % hm.entries.len; | 213 | const index = (start_index + roll_over) % hm.entries.len; |
| 196 | const entry = &hm.entries[index]; | 214 | const entry = &hm.entries[index]; |
| ... | @@ -233,9 +251,19 @@ fn global_free(self: &Allocator, old_mem: []u8) { | ... | @@ -233,9 +251,19 @@ fn global_free(self: &Allocator, old_mem: []u8) { |
| 233 | 251 | ||
| 234 | #attribute("test") | 252 | #attribute("test") |
| 235 | fn basic_hash_map_test() { | 253 | fn basic_hash_map_test() { |
| 236 | var map: HashMap(i32, i32, hash_i32, eql_i32) = undefined; | 254 | var map: SmallHashMap(i32, i32, hash_i32, eql_i32, 4) = undefined; |
| 237 | map.init(&global_allocator, 4); | 255 | map.init(&global_allocator); |
| 238 | defer map.deinit(); | 256 | defer map.deinit(); |
| 257 | |||
| 258 | %%map.put(1, 11); | ||
| 259 | %%map.put(2, 22); | ||
| 260 | %%map.put(3, 33); | ||
| 261 | %%map.put(4, 44); | ||
| 262 | %%map.put(5, 55); | ||
| 263 | |||
| 264 | assert((??map.get(2)).value == 22); | ||
| 265 | map.remove(2); | ||
| 266 | assert(if (const entry ?= map.get(2)) false else true); | ||
| 239 | } | 267 | } |
| 240 | 268 | ||
| 241 | fn hash_i32(x: i32) -> u32 { | 269 | fn hash_i32(x: i32) -> u32 { |
std/index.zig+1| ... | @@ -6,6 +6,7 @@ pub const str = @import("str.zig"); | ... | @@ -6,6 +6,7 @@ pub const str = @import("str.zig"); |
| 6 | pub const cstr = @import("cstr.zig"); | 6 | pub const cstr = @import("cstr.zig"); |
| 7 | pub const net = @import("net.zig"); | 7 | pub const net = @import("net.zig"); |
| 8 | pub const list = @import("list.zig"); | 8 | pub const list = @import("list.zig"); |
| 9 | pub const hash_map = @import("hash_map.zig"); | ||
| 9 | pub const mem = @import("mem.zig"); | 10 | pub const mem = @import("mem.zig"); |
| 10 | 11 | ||
| 11 | pub fn assert(b: bool) { | 12 | pub fn assert(b: bool) { |
std/list.zig+1-1| ... | @@ -21,7 +21,7 @@ pub struct SmallList(T: type, STATIC_SIZE: isize) { | ... | @@ -21,7 +21,7 @@ pub struct SmallList(T: type, STATIC_SIZE: isize) { |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | pub fn deinit(l: &SmallList(T, STATIC_SIZE)) { | 23 | pub fn deinit(l: &SmallList(T, STATIC_SIZE)) { |
| 24 | if (l.items.ptr == &l.prealloc_items[0]) { | 24 | if (l.items.ptr != &l.prealloc_items[0]) { |
| 25 | l.allocator.free(l.allocator, ([]u8)(l.items)); | 25 | l.allocator.free(l.allocator, ([]u8)(l.items)); |
| 26 | } | 26 | } |
| 27 | } | 27 | } |
test/run_tests.cpp+3-3| ... | @@ -831,9 +831,9 @@ fn f() { | ... | @@ -831,9 +831,9 @@ fn f() { |
| 831 | 831 | ||
| 832 | 832 | ||
| 833 | add_compile_fail_case("missing else clause", R"SOURCE( | 833 | add_compile_fail_case("missing else clause", R"SOURCE( |
| 834 | fn f() { | 834 | fn f(b: bool) { |
| 835 | const x : i32 = if (true) { 1 }; | 835 | const x : i32 = if (b) { 1 }; |
| 836 | const y = if (true) { i32(1) }; | 836 | const y = if (b) { i32(1) }; |
| 837 | } | 837 | } |
| 838 | )SOURCE", 2, ".tmp_source.zig:3:21: error: expected type 'i32', got 'void'", | 838 | )SOURCE", 2, ".tmp_source.zig:3:21: error: expected type 'i32', got 'void'", |
| 839 | ".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'"); | 839 | ".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'"); |