| author | |
| committer | |
| log | a71fbe49cbbf068e00300533d5f3874efadb8c18 |
| tree | 57c6c4150b910efce96251b14003d46f00cf6afa |
| parent | f12fbce0f51d58b429afd8a359aeb8a3b27a4eb0 |
12 files changed, 416 insertions(+), 300 deletions(-)
CMakeLists.txt+1-1| ... | @@ -52,11 +52,11 @@ set(ZIG_SOURCES | ... | @@ -52,11 +52,11 @@ set(ZIG_SOURCES |
| 52 | "${CMAKE_SOURCE_DIR}/src/link.cpp" | 52 | "${CMAKE_SOURCE_DIR}/src/link.cpp" |
| 53 | "${CMAKE_SOURCE_DIR}/src/main.cpp" | 53 | "${CMAKE_SOURCE_DIR}/src/main.cpp" |
| 54 | "${CMAKE_SOURCE_DIR}/src/os.cpp" | 54 | "${CMAKE_SOURCE_DIR}/src/os.cpp" |
| 55 | "${CMAKE_SOURCE_DIR}/src/parseh.cpp" | ||
| 56 | "${CMAKE_SOURCE_DIR}/src/parser.cpp" | 55 | "${CMAKE_SOURCE_DIR}/src/parser.cpp" |
| 57 | "${CMAKE_SOURCE_DIR}/src/target.cpp" | 56 | "${CMAKE_SOURCE_DIR}/src/target.cpp" |
| 58 | "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp" | 57 | "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp" |
| 59 | "${CMAKE_SOURCE_DIR}/src/util.cpp" | 58 | "${CMAKE_SOURCE_DIR}/src/util.cpp" |
| 59 | "${CMAKE_SOURCE_DIR}/src/parseh.cpp" | ||
| 60 | "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" | 60 | "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" |
| 61 | ) | 61 | ) |
| 62 | 62 |
src/all_types.hpp+8| ... | @@ -1448,6 +1448,7 @@ enum IrInstructionId { | ... | @@ -1448,6 +1448,7 @@ enum IrInstructionId { |
| 1448 | IrInstructionIdUnwrapErrPayload, | 1448 | IrInstructionIdUnwrapErrPayload, |
| 1449 | IrInstructionIdErrWrapCode, | 1449 | IrInstructionIdErrWrapCode, |
| 1450 | IrInstructionIdErrWrapPayload, | 1450 | IrInstructionIdErrWrapPayload, |
| 1451 | IrInstructionIdFnProto, | ||
| 1451 | }; | 1452 | }; |
| 1452 | 1453 | ||
| 1453 | struct IrInstruction { | 1454 | struct IrInstruction { |
| ... | @@ -2060,6 +2061,13 @@ struct IrInstructionErrWrapCode { | ... | @@ -2060,6 +2061,13 @@ struct IrInstructionErrWrapCode { |
| 2060 | LLVMValueRef tmp_ptr; | 2061 | LLVMValueRef tmp_ptr; |
| 2061 | }; | 2062 | }; |
| 2062 | 2063 | ||
| 2064 | struct IrInstructionFnProto { | ||
| 2065 | IrInstruction base; | ||
| 2066 | |||
| 2067 | IrInstruction **param_types; | ||
| 2068 | IrInstruction *return_type; | ||
| 2069 | }; | ||
| 2070 | |||
| 2063 | enum LValPurpose { | 2071 | enum LValPurpose { |
| 2064 | LValPurposeNone, | 2072 | LValPurposeNone, |
| 2065 | LValPurposeAssign, | 2073 | LValPurposeAssign, |
src/codegen.cpp+1| ... | @@ -2196,6 +2196,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -2196,6 +2196,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2196 | case IrInstructionIdIntType: | 2196 | case IrInstructionIdIntType: |
| 2197 | case IrInstructionIdMemberCount: | 2197 | case IrInstructionIdMemberCount: |
| 2198 | case IrInstructionIdAlignOf: | 2198 | case IrInstructionIdAlignOf: |
| 2199 | case IrInstructionIdFnProto: | ||
| 2199 | zig_unreachable(); | 2200 | zig_unreachable(); |
| 2200 | case IrInstructionIdReturn: | 2201 | case IrInstructionIdReturn: |
| 2201 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); | 2202 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
src/ir.cpp+85-1| ... | @@ -439,6 +439,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapCode *) { | ... | @@ -439,6 +439,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapCode *) { |
| 439 | return IrInstructionIdErrWrapCode; | 439 | return IrInstructionIdErrWrapCode; |
| 440 | } | 440 | } |
| 441 | 441 | ||
| 442 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFnProto *) { | ||
| 443 | return IrInstructionIdFnProto; | ||
| 444 | } | ||
| 445 | |||
| 442 | template<typename T> | 446 | template<typename T> |
| 443 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { | 447 | static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) { |
| 444 | T *special_instruction = allocate<T>(1); | 448 | T *special_instruction = allocate<T>(1); |
| ... | @@ -1826,6 +1830,22 @@ static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruc | ... | @@ -1826,6 +1830,22 @@ static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruc |
| 1826 | return new_instruction; | 1830 | return new_instruction; |
| 1827 | } | 1831 | } |
| 1828 | 1832 | ||
| 1833 | static IrInstruction *ir_build_fn_proto(IrBuilder *irb, Scope *scope, AstNode *source_node, | ||
| 1834 | IrInstruction **param_types, IrInstruction *return_type) | ||
| 1835 | { | ||
| 1836 | IrInstructionFnProto *instruction = ir_build_instruction<IrInstructionFnProto>(irb, scope, source_node); | ||
| 1837 | instruction->param_types = param_types; | ||
| 1838 | instruction->return_type = return_type; | ||
| 1839 | |||
| 1840 | assert(source_node->type == NodeTypeFnProto); | ||
| 1841 | for (size_t i = 0; i < source_node->data.fn_proto.params.length; i += 1) { | ||
| 1842 | ir_ref_instruction(param_types[i]); | ||
| 1843 | } | ||
| 1844 | ir_ref_instruction(return_type); | ||
| 1845 | |||
| 1846 | return &instruction->base; | ||
| 1847 | } | ||
| 1848 | |||
| 1829 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 1849 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 1830 | results[ReturnKindUnconditional] = 0; | 1850 | results[ReturnKindUnconditional] = 0; |
| 1831 | results[ReturnKindError] = 0; | 1851 | results[ReturnKindError] = 0; |
| ... | @@ -3894,6 +3914,28 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, | ... | @@ -3894,6 +3914,28 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, |
| 3894 | return ir_build_const_type(irb, parent_scope, node, container_type); | 3914 | return ir_build_const_type(irb, parent_scope, node, container_type); |
| 3895 | } | 3915 | } |
| 3896 | 3916 | ||
| 3917 | static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNode *node) { | ||
| 3918 | assert(node->type == NodeTypeFnProto); | ||
| 3919 | |||
| 3920 | size_t param_count = node->data.fn_proto.params.length; | ||
| 3921 | IrInstruction **param_types = allocate<IrInstruction*>(param_count); | ||
| 3922 | |||
| 3923 | for (size_t i = 0; i < param_count; i += 1) { | ||
| 3924 | AstNode *param_node = node->data.fn_proto.params.at(i); | ||
| 3925 | AstNode *type_node = param_node->data.param_decl.type; | ||
| 3926 | IrInstruction *type_value = ir_gen_node(irb, type_node, parent_scope); | ||
| 3927 | if (type_value == irb->codegen->invalid_instruction) | ||
| 3928 | return irb->codegen->invalid_instruction; | ||
| 3929 | param_types[i] = type_value; | ||
| 3930 | } | ||
| 3931 | |||
| 3932 | IrInstruction *return_type = ir_gen_node(irb, node->data.fn_proto.return_type, parent_scope); | ||
| 3933 | if (return_type == irb->codegen->invalid_instruction) | ||
| 3934 | return irb->codegen->invalid_instruction; | ||
| 3935 | |||
| 3936 | return ir_build_fn_proto(irb, parent_scope, node, param_types, return_type); | ||
| 3937 | } | ||
| 3938 | |||
| 3897 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, | 3939 | static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, |
| 3898 | LValPurpose lval) | 3940 | LValPurpose lval) |
| 3899 | { | 3941 | { |
| ... | @@ -3978,11 +4020,15 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop | ... | @@ -3978,11 +4020,15 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 3978 | case NodeTypeContainerDecl: | 4020 | case NodeTypeContainerDecl: |
| 3979 | return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); | 4021 | return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); |
| 3980 | case NodeTypeFnProto: | 4022 | case NodeTypeFnProto: |
| 4023 | return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval); | ||
| 3981 | case NodeTypeFnDef: | 4024 | case NodeTypeFnDef: |
| 4025 | zig_panic("TODO IR gen NodeTypeFnDef"); | ||
| 3982 | case NodeTypeFnDecl: | 4026 | case NodeTypeFnDecl: |
| 4027 | zig_panic("TODO IR gen NodeTypeFnDecl"); | ||
| 3983 | case NodeTypeErrorValueDecl: | 4028 | case NodeTypeErrorValueDecl: |
| 4029 | zig_panic("TODO IR gen NodeTypeErrorValueDecl"); | ||
| 3984 | case NodeTypeTypeDecl: | 4030 | case NodeTypeTypeDecl: |
| 3985 | zig_panic("TODO more IR gen for node types"); | 4031 | zig_panic("TODO IR gen NodeTypeTypeDecl"); |
| 3986 | case NodeTypeZeroesLiteral: | 4032 | case NodeTypeZeroesLiteral: |
| 3987 | zig_panic("TODO zeroes is deprecated"); | 4033 | zig_panic("TODO zeroes is deprecated"); |
| 3988 | } | 4034 | } |
| ... | @@ -9377,6 +9423,41 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, | ... | @@ -9377,6 +9423,41 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira, |
| 9377 | 9423 | ||
| 9378 | } | 9424 | } |
| 9379 | 9425 | ||
| 9426 | static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) { | ||
| 9427 | AstNode *proto_node = instruction->base.source_node; | ||
| 9428 | assert(proto_node->type == NodeTypeFnProto); | ||
| 9429 | |||
| 9430 | FnTypeId fn_type_id = {0}; | ||
| 9431 | init_fn_type_id(&fn_type_id, proto_node); | ||
| 9432 | |||
| 9433 | bool depends_on_compile_var = false; | ||
| 9434 | |||
| 9435 | for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { | ||
| 9436 | AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); | ||
| 9437 | assert(param_node->type == NodeTypeParamDecl); | ||
| 9438 | |||
| 9439 | IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other; | ||
| 9440 | |||
| 9441 | FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; | ||
| 9442 | param_info->is_noalias = param_node->data.param_decl.is_noalias; | ||
| 9443 | param_info->type = ir_resolve_type(ira, param_type_value); | ||
| 9444 | if (param_info->type->id == TypeTableEntryIdInvalid) | ||
| 9445 | return ira->codegen->builtin_types.entry_invalid; | ||
| 9446 | |||
| 9447 | depends_on_compile_var = depends_on_compile_var || param_type_value->static_value.depends_on_compile_var; | ||
| 9448 | } | ||
| 9449 | |||
| 9450 | IrInstruction *return_type_value = instruction->return_type->other; | ||
| 9451 | fn_type_id.return_type = ir_resolve_type(ira, return_type_value); | ||
| 9452 | if (fn_type_id.return_type->id == TypeTableEntryIdInvalid) | ||
| 9453 | return ira->codegen->builtin_types.entry_invalid; | ||
| 9454 | depends_on_compile_var = depends_on_compile_var || return_type_value->static_value.depends_on_compile_var; | ||
| 9455 | |||
| 9456 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var); | ||
| 9457 | out_val->data.x_type = get_fn_type(ira->codegen, &fn_type_id); | ||
| 9458 | return ira->codegen->builtin_types.entry_type; | ||
| 9459 | } | ||
| 9460 | |||
| 9380 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 9461 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 9381 | switch (instruction->id) { | 9462 | switch (instruction->id) { |
| 9382 | case IrInstructionIdInvalid: | 9463 | case IrInstructionIdInvalid: |
| ... | @@ -9517,6 +9598,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -9517,6 +9598,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 9517 | return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction); | 9598 | return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction); |
| 9518 | case IrInstructionIdUnwrapErrPayload: | 9599 | case IrInstructionIdUnwrapErrPayload: |
| 9519 | return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstructionUnwrapErrPayload *)instruction); | 9600 | return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstructionUnwrapErrPayload *)instruction); |
| 9601 | case IrInstructionIdFnProto: | ||
| 9602 | return ir_analyze_instruction_fn_proto(ira, (IrInstructionFnProto *)instruction); | ||
| 9520 | case IrInstructionIdMaybeWrap: | 9603 | case IrInstructionIdMaybeWrap: |
| 9521 | case IrInstructionIdErrWrapCode: | 9604 | case IrInstructionIdErrWrapCode: |
| 9522 | case IrInstructionIdErrWrapPayload: | 9605 | case IrInstructionIdErrWrapPayload: |
| ... | @@ -9677,6 +9760,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -9677,6 +9760,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 9677 | case IrInstructionIdMaybeWrap: | 9760 | case IrInstructionIdMaybeWrap: |
| 9678 | case IrInstructionIdErrWrapCode: | 9761 | case IrInstructionIdErrWrapCode: |
| 9679 | case IrInstructionIdErrWrapPayload: | 9762 | case IrInstructionIdErrWrapPayload: |
| 9763 | case IrInstructionIdFnProto: | ||
| 9680 | return false; | 9764 | return false; |
| 9681 | case IrInstructionIdAsm: | 9765 | case IrInstructionIdAsm: |
| 9682 | { | 9766 | { |
src/ir_print.cpp+14| ... | @@ -882,6 +882,17 @@ static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload | ... | @@ -882,6 +882,17 @@ static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload |
| 882 | fprintf(irp->f, ")"); | 882 | fprintf(irp->f, ")"); |
| 883 | } | 883 | } |
| 884 | 884 | ||
| 885 | static void ir_print_fn_proto(IrPrint *irp, IrInstructionFnProto *instruction) { | ||
| 886 | fprintf(irp->f, "fn("); | ||
| 887 | for (size_t i = 0; i < instruction->base.source_node->data.fn_proto.params.length; i += 1) { | ||
| 888 | if (i != 0) | ||
| 889 | fprintf(irp->f, ","); | ||
| 890 | ir_print_other_instruction(irp, instruction->param_types[i]); | ||
| 891 | } | ||
| 892 | fprintf(irp->f, ")->"); | ||
| 893 | ir_print_other_instruction(irp, instruction->return_type); | ||
| 894 | } | ||
| 895 | |||
| 885 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 896 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 886 | ir_print_prefix(irp, instruction); | 897 | ir_print_prefix(irp, instruction); |
| 887 | switch (instruction->id) { | 898 | switch (instruction->id) { |
| ... | @@ -1112,6 +1123,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1112,6 +1123,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1112 | case IrInstructionIdErrWrapPayload: | 1123 | case IrInstructionIdErrWrapPayload: |
| 1113 | ir_print_err_wrap_payload(irp, (IrInstructionErrWrapPayload *)instruction); | 1124 | ir_print_err_wrap_payload(irp, (IrInstructionErrWrapPayload *)instruction); |
| 1114 | break; | 1125 | break; |
| 1126 | case IrInstructionIdFnProto: | ||
| 1127 | ir_print_fn_proto(irp, (IrInstructionFnProto *)instruction); | ||
| 1128 | break; | ||
| 1115 | } | 1129 | } |
| 1116 | fprintf(irp->f, "\n"); | 1130 | fprintf(irp->f, "\n"); |
| 1117 | } | 1131 | } |
std/debug.zig+18-18| ... | @@ -69,7 +69,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void { | ... | @@ -69,7 +69,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void { |
| 69 | } | 69 | } |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | struct ElfStackTrace { | 72 | const ElfStackTrace = struct { |
| 73 | self_exe_stream: io.InStream, | 73 | self_exe_stream: io.InStream, |
| 74 | elf: elf.Elf, | 74 | elf: elf.Elf, |
| 75 | debug_info: &elf.SectionHeader, | 75 | debug_info: &elf.SectionHeader, |
| ... | @@ -77,36 +77,36 @@ struct ElfStackTrace { | ... | @@ -77,36 +77,36 @@ struct ElfStackTrace { |
| 77 | debug_str: &elf.SectionHeader, | 77 | debug_str: &elf.SectionHeader, |
| 78 | abbrev_table_list: List(AbbrevTableHeader), | 78 | abbrev_table_list: List(AbbrevTableHeader), |
| 79 | compile_unit_list: List(CompileUnit), | 79 | compile_unit_list: List(CompileUnit), |
| 80 | } | 80 | }; |
| 81 | 81 | ||
| 82 | struct CompileUnit { | 82 | const CompileUnit = struct { |
| 83 | is_64: bool, | 83 | is_64: bool, |
| 84 | die: &Die, | 84 | die: &Die, |
| 85 | pc_start: u64, | 85 | pc_start: u64, |
| 86 | pc_end: u64, | 86 | pc_end: u64, |
| 87 | } | 87 | }; |
| 88 | 88 | ||
| 89 | const AbbrevTable = List(AbbrevTableEntry); | 89 | const AbbrevTable = List(AbbrevTableEntry); |
| 90 | 90 | ||
| 91 | struct AbbrevTableHeader { | 91 | const AbbrevTableHeader = struct { |
| 92 | // offset from .debug_abbrev | 92 | // offset from .debug_abbrev |
| 93 | offset: u64, | 93 | offset: u64, |
| 94 | table: AbbrevTable, | 94 | table: AbbrevTable, |
| 95 | } | 95 | }; |
| 96 | 96 | ||
| 97 | struct AbbrevTableEntry { | 97 | const AbbrevTableEntry = struct { |
| 98 | has_children: bool, | 98 | has_children: bool, |
| 99 | abbrev_code: u64, | 99 | abbrev_code: u64, |
| 100 | tag_id: u64, | 100 | tag_id: u64, |
| 101 | attrs: List(AbbrevAttr), | 101 | attrs: List(AbbrevAttr), |
| 102 | } | 102 | }; |
| 103 | 103 | ||
| 104 | struct AbbrevAttr { | 104 | const AbbrevAttr = struct { |
| 105 | attr_id: u64, | 105 | attr_id: u64, |
| 106 | form_id: u64, | 106 | form_id: u64, |
| 107 | } | 107 | }; |
| 108 | 108 | ||
| 109 | enum FormValue { | 109 | const FormValue = enum { |
| 110 | Address: u64, | 110 | Address: u64, |
| 111 | Block: []u8, | 111 | Block: []u8, |
| 112 | Const: Constant, | 112 | Const: Constant, |
| ... | @@ -118,9 +118,9 @@ enum FormValue { | ... | @@ -118,9 +118,9 @@ enum FormValue { |
| 118 | RefSig8: u64, | 118 | RefSig8: u64, |
| 119 | String: []u8, | 119 | String: []u8, |
| 120 | StrPtr: u64, | 120 | StrPtr: u64, |
| 121 | } | 121 | }; |
| 122 | 122 | ||
| 123 | struct Constant { | 123 | const Constant = struct { |
| 124 | payload: []u8, | 124 | payload: []u8, |
| 125 | signed: bool, | 125 | signed: bool, |
| 126 | 126 | ||
| ... | @@ -131,17 +131,17 @@ struct Constant { | ... | @@ -131,17 +131,17 @@ struct Constant { |
| 131 | return error.InvalidDebugInfo; | 131 | return error.InvalidDebugInfo; |
| 132 | return mem.sliceAsInt(self.payload, false, u64); | 132 | return mem.sliceAsInt(self.payload, false, u64); |
| 133 | } | 133 | } |
| 134 | } | 134 | }; |
| 135 | 135 | ||
| 136 | struct Die { | 136 | const Die = struct { |
| 137 | tag_id: u64, | 137 | tag_id: u64, |
| 138 | has_children: bool, | 138 | has_children: bool, |
| 139 | attrs: List(Attr), | 139 | attrs: List(Attr), |
| 140 | 140 | ||
| 141 | struct Attr { | 141 | const Attr = struct { |
| 142 | id: u64, | 142 | id: u64, |
| 143 | value: FormValue, | 143 | value: FormValue, |
| 144 | } | 144 | }; |
| 145 | 145 | ||
| 146 | fn getAttr(self: &const Die, id: u64) -> ?&const FormValue { | 146 | fn getAttr(self: &const Die, id: u64) -> ?&const FormValue { |
| 147 | for (self.attrs.toSlice()) |*attr| { | 147 | for (self.attrs.toSlice()) |*attr| { |
| ... | @@ -175,7 +175,7 @@ struct Die { | ... | @@ -175,7 +175,7 @@ struct Die { |
| 175 | else => error.InvalidDebugInfo, | 175 | else => error.InvalidDebugInfo, |
| 176 | } | 176 | } |
| 177 | } | 177 | } |
| 178 | } | 178 | }; |
| 179 | 179 | ||
| 180 | fn readString(in_stream: &io.InStream) -> %[]u8 { | 180 | fn readString(in_stream: &io.InStream) -> %[]u8 { |
| 181 | var buf = List(u8).init(&global_allocator); | 181 | var buf = List(u8).init(&global_allocator); |
std/elf.zig+8-8| ... | @@ -30,14 +30,14 @@ pub const SHT_HIPROC = 0x7fffffff; | ... | @@ -30,14 +30,14 @@ pub const SHT_HIPROC = 0x7fffffff; |
| 30 | pub const SHT_LOUSER = 0x80000000; | 30 | pub const SHT_LOUSER = 0x80000000; |
| 31 | pub const SHT_HIUSER = 0xffffffff; | 31 | pub const SHT_HIUSER = 0xffffffff; |
| 32 | 32 | ||
| 33 | pub enum FileType { | 33 | pub const FileType = enum { |
| 34 | Relocatable, | 34 | Relocatable, |
| 35 | Executable, | 35 | Executable, |
| 36 | Shared, | 36 | Shared, |
| 37 | Core, | 37 | Core, |
| 38 | } | 38 | }; |
| 39 | 39 | ||
| 40 | pub enum Arch { | 40 | pub const Arch = enum { |
| 41 | Sparc, | 41 | Sparc, |
| 42 | x86, | 42 | x86, |
| 43 | Mips, | 43 | Mips, |
| ... | @@ -47,9 +47,9 @@ pub enum Arch { | ... | @@ -47,9 +47,9 @@ pub enum Arch { |
| 47 | IA_64, | 47 | IA_64, |
| 48 | x86_64, | 48 | x86_64, |
| 49 | AArch64, | 49 | AArch64, |
| 50 | } | 50 | }; |
| 51 | 51 | ||
| 52 | pub struct SectionHeader { | 52 | pub const SectionHeader = struct { |
| 53 | name: u32, | 53 | name: u32, |
| 54 | sh_type: u32, | 54 | sh_type: u32, |
| 55 | flags: u64, | 55 | flags: u64, |
| ... | @@ -60,9 +60,9 @@ pub struct SectionHeader { | ... | @@ -60,9 +60,9 @@ pub struct SectionHeader { |
| 60 | info: u32, | 60 | info: u32, |
| 61 | addr_align: u64, | 61 | addr_align: u64, |
| 62 | ent_size: u64, | 62 | ent_size: u64, |
| 63 | } | 63 | }; |
| 64 | 64 | ||
| 65 | pub struct Elf { | 65 | pub const Elf = struct { |
| 66 | in_stream: &io.InStream, | 66 | in_stream: &io.InStream, |
| 67 | auto_close_stream: bool, | 67 | auto_close_stream: bool, |
| 68 | is_64: bool, | 68 | is_64: bool, |
| ... | @@ -258,4 +258,4 @@ pub struct Elf { | ... | @@ -258,4 +258,4 @@ pub struct Elf { |
| 258 | pub fn seekToSection(elf: &Elf, section: &SectionHeader) -> %void { | 258 | pub fn seekToSection(elf: &Elf, section: &SectionHeader) -> %void { |
| 259 | %return elf.in_stream.seekTo(section.offset); | 259 | %return elf.in_stream.seekTo(section.offset); |
| 260 | } | 260 | } |
| 261 | } | 261 | }; |
std/hash_map.zig+190-185| ... | @@ -13,220 +13,225 @@ pub fn HashMap(inline K: type, inline V: type, inline hash: fn(key: K)->u32, | ... | @@ -13,220 +13,225 @@ pub fn HashMap(inline K: type, inline V: type, inline hash: fn(key: K)->u32, |
| 13 | SmallHashMap(K, V, hash, eql, @sizeOf(usize)) | 13 | SmallHashMap(K, V, hash, eql, @sizeOf(usize)) |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | pub struct SmallHashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)->bool, static_size: usize) { | 16 | pub fn SmallHashMap(inline K: type, inline V: type, |
| 17 | entries: []Entry, | 17 | inline hash: fn(key: K)->u32, inline eql: fn(a: K, b: K)->bool, |
| 18 | size: usize, | 18 | inline static_size: usize) -> type |
| 19 | max_distance_from_start_index: usize, | 19 | { |
| 20 | allocator: &Allocator, | 20 | struct { |
| 21 | // if the hash map is small enough, we use linear search through these | 21 | entries: []Entry, |
| 22 | // entries instead of allocating memory | 22 | size: usize, |
| 23 | prealloc_entries: [static_size]Entry, | 23 | max_distance_from_start_index: usize, |
| 24 | // this is used to detect bugs where a hashtable is edited while an iterator is running. | 24 | allocator: &Allocator, |
| 25 | modification_count: debug_u32, | 25 | // if the hash map is small enough, we use linear search through these |
| 26 | 26 | // entries instead of allocating memory | |
| 27 | const Self = this; | 27 | prealloc_entries: [static_size]Entry, |
| 28 | 28 | // this is used to detect bugs where a hashtable is edited while an iterator is running. | |
| 29 | pub struct Entry { | 29 | modification_count: debug_u32, |
| 30 | used: bool, | 30 | |
| 31 | distance_from_start_index: usize, | 31 | const Self = this; |
| 32 | key: K, | 32 | |
| 33 | value: V, | 33 | pub const Entry = struct { |
| 34 | } | 34 | used: bool, |
| 35 | 35 | distance_from_start_index: usize, | |
| 36 | pub struct Iterator { | 36 | key: K, |
| 37 | hm: &Self, | 37 | value: V, |
| 38 | // how many items have we returned | 38 | }; |
| 39 | count: usize, | ||
| 40 | // iterator through the entry array | ||
| 41 | index: usize, | ||
| 42 | // used to detect concurrent modification | ||
| 43 | initial_modification_count: debug_u32, | ||
| 44 | 39 | ||
| 45 | pub fn next(it: &Iterator) -> ?&Entry { | 40 | pub const Iterator = struct { |
| 46 | if (want_modification_safety) { | 41 | hm: &Self, |
| 47 | assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification | 42 | // how many items have we returned |
| 48 | } | 43 | count: usize, |
| 49 | if (it.count >= it.hm.size) return null; | 44 | // iterator through the entry array |
| 50 | while (it.index < it.hm.entries.len; it.index += 1) { | 45 | index: usize, |
| 51 | const entry = &it.hm.entries[it.index]; | 46 | // used to detect concurrent modification |
| 52 | if (entry.used) { | 47 | initial_modification_count: debug_u32, |
| 53 | it.index += 1; | 48 | |
| 54 | it.count += 1; | 49 | pub fn next(it: &Iterator) -> ?&Entry { |
| 55 | return entry; | 50 | if (want_modification_safety) { |
| 51 | assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification | ||
| 56 | } | 52 | } |
| 53 | if (it.count >= it.hm.size) return null; | ||
| 54 | while (it.index < it.hm.entries.len; it.index += 1) { | ||
| 55 | const entry = &it.hm.entries[it.index]; | ||
| 56 | if (entry.used) { | ||
| 57 | it.index += 1; | ||
| 58 | it.count += 1; | ||
| 59 | return entry; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | @unreachable() // no next item | ||
| 57 | } | 63 | } |
| 58 | @unreachable() // no next item | 64 | }; |
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | pub fn init(hm: &Self, allocator: &Allocator) { | ||
| 63 | hm.entries = hm.prealloc_entries[0...]; | ||
| 64 | hm.allocator = allocator; | ||
| 65 | hm.size = 0; | ||
| 66 | hm.max_distance_from_start_index = 0; | ||
| 67 | hm.prealloc_entries = zeroes; // sets used to false for all entries | ||
| 68 | hm.modification_count = zeroes; | ||
| 69 | } | ||
| 70 | 65 | ||
| 71 | pub fn deinit(hm: &Self) { | 66 | pub fn init(hm: &Self, allocator: &Allocator) { |
| 72 | if (hm.entries.ptr != &hm.prealloc_entries[0]) { | 67 | hm.entries = hm.prealloc_entries[0...]; |
| 73 | hm.allocator.free(Entry, hm.entries); | 68 | hm.allocator = allocator; |
| 69 | hm.size = 0; | ||
| 70 | hm.max_distance_from_start_index = 0; | ||
| 71 | hm.prealloc_entries = zeroes; // sets used to false for all entries | ||
| 72 | hm.modification_count = zeroes; | ||
| 74 | } | 73 | } |
| 75 | } | ||
| 76 | 74 | ||
| 77 | pub fn clear(hm: &Self) { | 75 | pub fn deinit(hm: &Self) { |
| 78 | for (hm.entries) |*entry| { | 76 | if (hm.entries.ptr != &hm.prealloc_entries[0]) { |
| 79 | entry.used = false; | 77 | hm.allocator.free(Entry, hm.entries); |
| 78 | } | ||
| 80 | } | 79 | } |
| 81 | hm.size = 0; | ||
| 82 | hm.max_distance_from_start_index = 0; | ||
| 83 | hm.incrementModificationCount(); | ||
| 84 | } | ||
| 85 | |||
| 86 | pub fn put(hm: &Self, key: K, value: V) -> %void { | ||
| 87 | hm.incrementModificationCount(); | ||
| 88 | 80 | ||
| 89 | const resize = if (hm.entries.ptr == &hm.prealloc_entries[0]) { | 81 | pub fn clear(hm: &Self) { |
| 90 | // preallocated entries table is full | 82 | for (hm.entries) |*entry| { |
| 91 | hm.size == hm.entries.len | 83 | entry.used = false; |
| 92 | } else { | ||
| 93 | // if we get too full (60%), double the capacity | ||
| 94 | hm.size * 5 >= hm.entries.len * 3 | ||
| 95 | }; | ||
| 96 | if (resize) { | ||
| 97 | const old_entries = hm.entries; | ||
| 98 | %return hm.initCapacity(hm.entries.len * 2); | ||
| 99 | // dump all of the old elements into the new table | ||
| 100 | for (old_entries) |*old_entry| { | ||
| 101 | if (old_entry.used) { | ||
| 102 | hm.internalPut(old_entry.key, old_entry.value); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | if (old_entries.ptr != &hm.prealloc_entries[0]) { | ||
| 106 | hm.allocator.free(Entry, old_entries); | ||
| 107 | } | 84 | } |
| 85 | hm.size = 0; | ||
| 86 | hm.max_distance_from_start_index = 0; | ||
| 87 | hm.incrementModificationCount(); | ||
| 108 | } | 88 | } |
| 109 | 89 | ||
| 110 | hm.internalPut(key, value); | 90 | pub fn put(hm: &Self, key: K, value: V) -> %void { |
| 111 | } | 91 | hm.incrementModificationCount(); |
| 112 | |||
| 113 | pub fn get(hm: &Self, key: K) -> ?&Entry { | ||
| 114 | return hm.internalGet(key); | ||
| 115 | } | ||
| 116 | 92 | ||
| 117 | pub fn remove(hm: &Self, key: K) { | 93 | const resize = if (hm.entries.ptr == &hm.prealloc_entries[0]) { |
| 118 | hm.incrementModificationCount(); | 94 | // preallocated entries table is full |
| 119 | const start_index = hm.keyToIndex(key); | 95 | hm.size == hm.entries.len |
| 120 | {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) { | 96 | } else { |
| 121 | const index = (start_index + roll_over) % hm.entries.len; | 97 | // if we get too full (60%), double the capacity |
| 122 | var entry = &hm.entries[index]; | 98 | hm.size * 5 >= hm.entries.len * 3 |
| 99 | }; | ||
| 100 | if (resize) { | ||
| 101 | const old_entries = hm.entries; | ||
| 102 | %return hm.initCapacity(hm.entries.len * 2); | ||
| 103 | // dump all of the old elements into the new table | ||
| 104 | for (old_entries) |*old_entry| { | ||
| 105 | if (old_entry.used) { | ||
| 106 | hm.internalPut(old_entry.key, old_entry.value); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | if (old_entries.ptr != &hm.prealloc_entries[0]) { | ||
| 110 | hm.allocator.free(Entry, old_entries); | ||
| 111 | } | ||
| 112 | } | ||
| 123 | 113 | ||
| 124 | assert(entry.used); // key not found | 114 | hm.internalPut(key, value); |
| 115 | } | ||
| 125 | 116 | ||
| 126 | if (!eql(entry.key, key)) continue; | 117 | pub fn get(hm: &Self, key: K) -> ?&Entry { |
| 118 | return hm.internalGet(key); | ||
| 119 | } | ||
| 127 | 120 | ||
| 128 | while (roll_over < hm.entries.len; roll_over += 1) { | 121 | pub fn remove(hm: &Self, key: K) { |
| 129 | const next_index = (start_index + roll_over + 1) % hm.entries.len; | 122 | hm.incrementModificationCount(); |
| 130 | const next_entry = &hm.entries[next_index]; | 123 | const start_index = hm.keyToIndex(key); |
| 131 | if (!next_entry.used || next_entry.distance_from_start_index == 0) { | 124 | {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) { |
| 132 | entry.used = false; | 125 | const index = (start_index + roll_over) % hm.entries.len; |
| 133 | hm.size -= 1; | 126 | var entry = &hm.entries[index]; |
| 134 | return; | 127 | |
| 128 | assert(entry.used); // key not found | ||
| 129 | |||
| 130 | if (!eql(entry.key, key)) continue; | ||
| 131 | |||
| 132 | while (roll_over < hm.entries.len; roll_over += 1) { | ||
| 133 | const next_index = (start_index + roll_over + 1) % hm.entries.len; | ||
| 134 | const next_entry = &hm.entries[next_index]; | ||
| 135 | if (!next_entry.used || next_entry.distance_from_start_index == 0) { | ||
| 136 | entry.used = false; | ||
| 137 | hm.size -= 1; | ||
| 138 | return; | ||
| 139 | } | ||
| 140 | *entry = *next_entry; | ||
| 141 | entry.distance_from_start_index -= 1; | ||
| 142 | entry = next_entry; | ||
| 135 | } | 143 | } |
| 136 | *entry = *next_entry; | 144 | @unreachable() // shifting everything in the table |
| 137 | entry.distance_from_start_index -= 1; | 145 | }} |
| 138 | entry = next_entry; | 146 | @unreachable() // key not found |
| 139 | } | 147 | } |
| 140 | @unreachable() // shifting everything in the table | ||
| 141 | }} | ||
| 142 | @unreachable() // key not found | ||
| 143 | } | ||
| 144 | 148 | ||
| 145 | pub fn entryIterator(hm: &Self) -> Iterator { | 149 | pub fn entryIterator(hm: &Self) -> Iterator { |
| 146 | return Iterator { | 150 | return Iterator { |
| 147 | .hm = hm, | 151 | .hm = hm, |
| 148 | .count = 0, | 152 | .count = 0, |
| 149 | .index = 0, | 153 | .index = 0, |
| 150 | .initial_modification_count = hm.modification_count, | 154 | .initial_modification_count = hm.modification_count, |
| 151 | }; | 155 | }; |
| 152 | } | 156 | } |
| 153 | 157 | ||
| 154 | fn initCapacity(hm: &Self, capacity: usize) -> %void { | 158 | fn initCapacity(hm: &Self, capacity: usize) -> %void { |
| 155 | hm.entries = %return hm.allocator.alloc(Entry, capacity); | 159 | hm.entries = %return hm.allocator.alloc(Entry, capacity); |
| 156 | hm.size = 0; | 160 | hm.size = 0; |
| 157 | hm.max_distance_from_start_index = 0; | 161 | hm.max_distance_from_start_index = 0; |
| 158 | for (hm.entries) |*entry| { | 162 | for (hm.entries) |*entry| { |
| 159 | entry.used = false; | 163 | entry.used = false; |
| 164 | } | ||
| 160 | } | 165 | } |
| 161 | } | ||
| 162 | 166 | ||
| 163 | fn incrementModificationCount(hm: &Self) { | 167 | fn incrementModificationCount(hm: &Self) { |
| 164 | if (want_modification_safety) { | 168 | if (want_modification_safety) { |
| 165 | hm.modification_count +%= 1; | 169 | hm.modification_count +%= 1; |
| 170 | } | ||
| 166 | } | 171 | } |
| 167 | } | ||
| 168 | 172 | ||
| 169 | fn internalPut(hm: &Self, orig_key: K, orig_value: V) { | 173 | fn internalPut(hm: &Self, orig_key: K, orig_value: V) { |
| 170 | var key = orig_key; | 174 | var key = orig_key; |
| 171 | var value = orig_value; | 175 | var value = orig_value; |
| 172 | const start_index = hm.keyToIndex(key); | 176 | const start_index = hm.keyToIndex(key); |
| 173 | var roll_over: usize = 0; | 177 | var roll_over: usize = 0; |
| 174 | var distance_from_start_index: usize = 0; | 178 | var distance_from_start_index: usize = 0; |
| 175 | while (roll_over < hm.entries.len; {roll_over += 1; distance_from_start_index += 1}) { | 179 | while (roll_over < hm.entries.len; {roll_over += 1; distance_from_start_index += 1}) { |
| 176 | const index = (start_index + roll_over) % hm.entries.len; | 180 | const index = (start_index + roll_over) % hm.entries.len; |
| 177 | const entry = &hm.entries[index]; | 181 | const entry = &hm.entries[index]; |
| 178 | 182 | ||
| 179 | if (entry.used && !eql(entry.key, key)) { | 183 | if (entry.used && !eql(entry.key, key)) { |
| 180 | if (entry.distance_from_start_index < distance_from_start_index) { | 184 | if (entry.distance_from_start_index < distance_from_start_index) { |
| 181 | // robin hood to the rescue | 185 | // robin hood to the rescue |
| 182 | const tmp = *entry; | 186 | const tmp = *entry; |
| 183 | hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index, | 187 | hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index, |
| 184 | distance_from_start_index); | 188 | distance_from_start_index); |
| 185 | *entry = Entry { | 189 | *entry = Entry { |
| 186 | .used = true, | 190 | .used = true, |
| 187 | .distance_from_start_index = distance_from_start_index, | 191 | .distance_from_start_index = distance_from_start_index, |
| 188 | .key = key, | 192 | .key = key, |
| 189 | .value = value, | 193 | .value = value, |
| 190 | }; | 194 | }; |
| 191 | key = tmp.key; | 195 | key = tmp.key; |
| 192 | value = tmp.value; | 196 | value = tmp.value; |
| 193 | distance_from_start_index = tmp.distance_from_start_index; | 197 | distance_from_start_index = tmp.distance_from_start_index; |
| 198 | } | ||
| 199 | continue; | ||
| 194 | } | 200 | } |
| 195 | continue; | ||
| 196 | } | ||
| 197 | 201 | ||
| 198 | if (!entry.used) { | 202 | if (!entry.used) { |
| 199 | // adding an entry. otherwise overwriting old value with | 203 | // adding an entry. otherwise overwriting old value with |
| 200 | // same key | 204 | // same key |
| 201 | hm.size += 1; | 205 | hm.size += 1; |
| 202 | } | 206 | } |
| 203 | 207 | ||
| 204 | hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index); | 208 | hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index); |
| 205 | *entry = Entry { | 209 | *entry = Entry { |
| 206 | .used = true, | 210 | .used = true, |
| 207 | .distance_from_start_index = distance_from_start_index, | 211 | .distance_from_start_index = distance_from_start_index, |
| 208 | .key = key, | 212 | .key = key, |
| 209 | .value = value, | 213 | .value = value, |
| 210 | }; | 214 | }; |
| 211 | return; | 215 | return; |
| 216 | } | ||
| 217 | @unreachable() // put into a full map | ||
| 212 | } | 218 | } |
| 213 | @unreachable() // put into a full map | ||
| 214 | } | ||
| 215 | 219 | ||
| 216 | fn internalGet(hm: &Self, key: K) -> ?&Entry { | 220 | fn internalGet(hm: &Self, key: K) -> ?&Entry { |
| 217 | const start_index = hm.keyToIndex(key); | 221 | const start_index = hm.keyToIndex(key); |
| 218 | {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) { | 222 | {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) { |
| 219 | const index = (start_index + roll_over) % hm.entries.len; | 223 | const index = (start_index + roll_over) % hm.entries.len; |
| 220 | const entry = &hm.entries[index]; | 224 | const entry = &hm.entries[index]; |
| 221 | 225 | ||
| 222 | if (!entry.used) return null; | 226 | if (!entry.used) return null; |
| 223 | if (eql(entry.key, key)) return entry; | 227 | if (eql(entry.key, key)) return entry; |
| 224 | }} | 228 | }} |
| 225 | return null; | 229 | return null; |
| 226 | } | 230 | } |
| 227 | 231 | ||
| 228 | fn keyToIndex(hm: &Self, key: K) -> usize { | 232 | fn keyToIndex(hm: &Self, key: K) -> usize { |
| 229 | return usize(hash(key)) % hm.entries.len; | 233 | return usize(hash(key)) % hm.entries.len; |
| 234 | } | ||
| 230 | } | 235 | } |
| 231 | } | 236 | } |
| 232 | 237 |
std/list.zig+36-34| ... | @@ -3,49 +3,51 @@ const assert = debug.assert; | ... | @@ -3,49 +3,51 @@ const assert = debug.assert; |
| 3 | const mem = @import("mem.zig"); | 3 | const mem = @import("mem.zig"); |
| 4 | const Allocator = mem.Allocator; | 4 | const Allocator = mem.Allocator; |
| 5 | 5 | ||
| 6 | pub struct List(T: type) { | 6 | pub fn List(inline T: type) -> type{ |
| 7 | const Self = this; | 7 | struct { |
| 8 | const Self = this; | ||
| 8 | 9 | ||
| 9 | items: []T, | 10 | items: []T, |
| 10 | len: usize, | 11 | len: usize, |
| 11 | allocator: &Allocator, | 12 | allocator: &Allocator, |
| 12 | 13 | ||
| 13 | pub fn init(allocator: &Allocator) -> Self { | 14 | pub fn init(allocator: &Allocator) -> Self { |
| 14 | Self { | 15 | Self { |
| 15 | .items = zeroes, | 16 | .items = zeroes, |
| 16 | .len = 0, | 17 | .len = 0, |
| 17 | .allocator = allocator, | 18 | .allocator = allocator, |
| 19 | } | ||
| 18 | } | 20 | } |
| 19 | } | ||
| 20 | 21 | ||
| 21 | pub fn deinit(l: &Self) { | 22 | pub fn deinit(l: &Self) { |
| 22 | l.allocator.free(T, l.items); | 23 | l.allocator.free(T, l.items); |
| 23 | } | 24 | } |
| 24 | 25 | ||
| 25 | pub fn toSlice(l: &Self) -> []T { | 26 | pub fn toSlice(l: &Self) -> []T { |
| 26 | return l.items[0...l.len]; | 27 | return l.items[0...l.len]; |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | pub fn append(l: &Self, item: T) -> %void { | 30 | pub fn append(l: &Self, item: T) -> %void { |
| 30 | const new_length = l.len + 1; | 31 | const new_length = l.len + 1; |
| 31 | %return l.ensureCapacity(new_length); | 32 | %return l.ensureCapacity(new_length); |
| 32 | l.items[l.len] = item; | 33 | l.items[l.len] = item; |
| 33 | l.len = new_length; | 34 | l.len = new_length; |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | pub fn resize(l: &Self, new_len: usize) -> %void { | 37 | pub fn resize(l: &Self, new_len: usize) -> %void { |
| 37 | %return l.ensureCapacity(new_len); | 38 | %return l.ensureCapacity(new_len); |
| 38 | l.len = new_len; | 39 | l.len = new_len; |
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | pub fn ensureCapacity(l: &Self, new_capacity: usize) -> %void { | 42 | pub fn ensureCapacity(l: &Self, new_capacity: usize) -> %void { |
| 42 | var better_capacity = l.items.len; | 43 | var better_capacity = l.items.len; |
| 43 | if (better_capacity >= new_capacity) return; | 44 | if (better_capacity >= new_capacity) return; |
| 44 | while (true) { | 45 | while (true) { |
| 45 | better_capacity += better_capacity / 2 + 8; | 46 | better_capacity += better_capacity / 2 + 8; |
| 46 | if (better_capacity >= new_capacity) break; | 47 | if (better_capacity >= new_capacity) break; |
| 48 | } | ||
| 49 | l.items = %return l.allocator.realloc(T, l.items, better_capacity); | ||
| 47 | } | 50 | } |
| 48 | l.items = %return l.allocator.realloc(T, l.items, better_capacity); | ||
| 49 | } | 51 | } |
| 50 | } | 52 | } |
| 51 | 53 |
std/mem.zig+2-2| ... | @@ -8,7 +8,7 @@ pub const Cmp = math.Cmp; | ... | @@ -8,7 +8,7 @@ pub const Cmp = math.Cmp; |
| 8 | pub error NoMem; | 8 | pub error NoMem; |
| 9 | 9 | ||
| 10 | pub type Context = u8; | 10 | pub type Context = u8; |
| 11 | pub struct Allocator { | 11 | pub const Allocator = struct { |
| 12 | allocFn: fn (self: &Allocator, n: usize) -> %[]u8, | 12 | allocFn: fn (self: &Allocator, n: usize) -> %[]u8, |
| 13 | reallocFn: fn (self: &Allocator, old_mem: []u8, new_size: usize) -> %[]u8, | 13 | reallocFn: fn (self: &Allocator, old_mem: []u8, new_size: usize) -> %[]u8, |
| 14 | freeFn: fn (self: &Allocator, mem: []u8), | 14 | freeFn: fn (self: &Allocator, mem: []u8), |
| ... | @@ -39,7 +39,7 @@ pub struct Allocator { | ... | @@ -39,7 +39,7 @@ pub struct Allocator { |
| 39 | fn free(self: &Allocator, inline T: type, mem: []T) { | 39 | fn free(self: &Allocator, inline T: type, mem: []T) { |
| 40 | self.freeFn(self, ([]u8)(mem)); | 40 | self.freeFn(self, ([]u8)(mem)); |
| 41 | } | 41 | } |
| 42 | } | 42 | }; |
| 43 | 43 | ||
| 44 | /// Copy all of source into dest at position 0. | 44 | /// Copy all of source into dest at position 0. |
| 45 | /// dest.len must be >= source.len. | 45 | /// dest.len must be >= source.len. |
std/net.zig+4-4| ... | @@ -13,7 +13,7 @@ pub error NoMem; | ... | @@ -13,7 +13,7 @@ pub error NoMem; |
| 13 | pub error NotSocket; | 13 | pub error NotSocket; |
| 14 | pub error BadFd; | 14 | pub error BadFd; |
| 15 | 15 | ||
| 16 | struct Connection { | 16 | const Connection = struct { |
| 17 | socket_fd: i32, | 17 | socket_fd: i32, |
| 18 | 18 | ||
| 19 | pub fn send(c: Connection, buf: []const u8) -> %usize { | 19 | pub fn send(c: Connection, buf: []const u8) -> %usize { |
| ... | @@ -56,14 +56,14 @@ struct Connection { | ... | @@ -56,14 +56,14 @@ struct Connection { |
| 56 | else => return error.Unexpected, | 56 | else => return error.Unexpected, |
| 57 | } | 57 | } |
| 58 | } | 58 | } |
| 59 | } | 59 | }; |
| 60 | 60 | ||
| 61 | struct Address { | 61 | const Address = struct { |
| 62 | family: u16, | 62 | family: u16, |
| 63 | scope_id: u32, | 63 | scope_id: u32, |
| 64 | addr: [16]u8, | 64 | addr: [16]u8, |
| 65 | sort_key: i32, | 65 | sort_key: i32, |
| 66 | } | 66 | }; |
| 67 | 67 | ||
| 68 | pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address { | 68 | pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address { |
| 69 | if (hostname.len == 0) { | 69 | if (hostname.len == 0) { |
std/rand.zig+49-47| ... | @@ -18,7 +18,7 @@ pub const MT19937_64 = MersenneTwister( | ... | @@ -18,7 +18,7 @@ pub const MT19937_64 = MersenneTwister( |
| 18 | 43, 6364136223846793005); | 18 | 43, 6364136223846793005); |
| 19 | 19 | ||
| 20 | /// Use `init` to initialize this state. | 20 | /// Use `init` to initialize this state. |
| 21 | pub struct Rand { | 21 | pub const Rand = struct { |
| 22 | const Rng = if (@sizeOf(usize) >= 8) MT19937_64 else MT19937_32; | 22 | const Rng = if (@sizeOf(usize) >= 8) MT19937_64 else MT19937_32; |
| 23 | 23 | ||
| 24 | rng: Rng, | 24 | rng: Rng, |
| ... | @@ -91,65 +91,67 @@ pub struct Rand { | ... | @@ -91,65 +91,67 @@ pub struct Rand { |
| 91 | }; | 91 | }; |
| 92 | return T(r.rangeUnsigned(int_type, 0, precision)) / T(precision); | 92 | return T(r.rangeUnsigned(int_type, 0, precision)) / T(precision); |
| 93 | } | 93 | } |
| 94 | } | 94 | }; |
| 95 | 95 | ||
| 96 | struct MersenneTwister( | 96 | fn MersenneTwister( |
| 97 | int: type, n: usize, m: usize, r: int, | 97 | inline int: type, inline n: usize, inline m: usize, inline r: int, |
| 98 | a: int, | 98 | inline a: int, |
| 99 | u: int, d: int, | 99 | inline u: int, inline d: int, |
| 100 | s: int, b: int, | 100 | inline s: int, inline b: int, |
| 101 | t: int, c: int, | 101 | inline t: int, inline c: int, |
| 102 | l: int, f: int) | 102 | inline l: int, inline f: int) -> type |
| 103 | { | 103 | { |
| 104 | const Self = this; | 104 | struct { |
| 105 | const Self = this; | ||
| 105 | 106 | ||
| 106 | array: [n]int, | 107 | array: [n]int, |
| 107 | index: usize, | 108 | index: usize, |
| 108 | 109 | ||
| 109 | pub fn init(mt: &Self, seed: int) { | 110 | pub fn init(mt: &Self, seed: int) { |
| 110 | mt.index = n; | 111 | mt.index = n; |
| 111 | 112 | ||
| 112 | var prev_value = seed; | 113 | var prev_value = seed; |
| 113 | mt.array[0] = prev_value; | 114 | mt.array[0] = prev_value; |
| 114 | {var i: usize = 1; while (i < n; i += 1) { | 115 | {var i: usize = 1; while (i < n; i += 1) { |
| 115 | prev_value = int(i) +% f *% (prev_value ^ (prev_value >> (int.bit_count - 2))); | 116 | prev_value = int(i) +% f *% (prev_value ^ (prev_value >> (int.bit_count - 2))); |
| 116 | mt.array[i] = prev_value; | 117 | mt.array[i] = prev_value; |
| 117 | }}; | 118 | }}; |
| 118 | } | 119 | } |
| 119 | 120 | ||
| 120 | pub fn get(mt: &Self) -> int { | 121 | pub fn get(mt: &Self) -> int { |
| 121 | const mag01 = []int{0, a}; | 122 | const mag01 = []int{0, a}; |
| 122 | const LM: int = (1 << r) - 1; | 123 | const LM: int = (1 << r) - 1; |
| 123 | const UM = ~LM; | 124 | const UM = ~LM; |
| 124 | 125 | ||
| 125 | if (mt.index >= n) { | 126 | if (mt.index >= n) { |
| 126 | var i: usize = 0; | 127 | var i: usize = 0; |
| 127 | 128 | ||
| 128 | while (i < n - m; i += 1) { | 129 | while (i < n - m; i += 1) { |
| 129 | const x = (mt.array[i] & UM) | (mt.array[i + 1] & LM); | 130 | const x = (mt.array[i] & UM) | (mt.array[i + 1] & LM); |
| 130 | mt.array[i] = mt.array[i + m] ^ (x >> 1) ^ mag01[x & 0x1]; | 131 | mt.array[i] = mt.array[i + m] ^ (x >> 1) ^ mag01[x & 0x1]; |
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | while (i < n - 1; i += 1) { | 134 | while (i < n - 1; i += 1) { |
| 134 | const x = (mt.array[i] & UM) | (mt.array[i + 1] & LM); | 135 | const x = (mt.array[i] & UM) | (mt.array[i + 1] & LM); |
| 135 | mt.array[i] = mt.array[i + m - n] ^ (x >> 1) ^ mag01[x & 0x1]; | 136 | mt.array[i] = mt.array[i + m - n] ^ (x >> 1) ^ mag01[x & 0x1]; |
| 136 | 137 | ||
| 137 | } | 138 | } |
| 138 | const x = (mt.array[i] & UM) | (mt.array[0] & LM); | 139 | const x = (mt.array[i] & UM) | (mt.array[0] & LM); |
| 139 | mt.array[i] = mt.array[m - 1] ^ (x >> 1) ^ mag01[x & 0x1]; | 140 | mt.array[i] = mt.array[m - 1] ^ (x >> 1) ^ mag01[x & 0x1]; |
| 140 | 141 | ||
| 141 | mt.index = 0; | 142 | mt.index = 0; |
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | var x = mt.array[mt.index]; | 145 | var x = mt.array[mt.index]; |
| 145 | mt.index += 1; | 146 | mt.index += 1; |
| 146 | 147 | ||
| 147 | x ^= ((x >> u) & d); | 148 | x ^= ((x >> u) & d); |
| 148 | x ^= ((x <<% s) & b); | 149 | x ^= ((x <<% s) & b); |
| 149 | x ^= ((x <<% t) & c); | 150 | x ^= ((x <<% t) & c); |
| 150 | x ^= (x >> l); | 151 | x ^= (x >> l); |
| 151 | 152 | ||
| 152 | return x; | 153 | return x; |
| 154 | } | ||
| 153 | } | 155 | } |
| 154 | } | 156 | } |
| 155 | 157 |