authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-18 19:40:26-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-18 19:40:26-05:00
loga71fbe49cbbf068e00300533d5f3874efadb8c18
tree57c6c4150b910efce96251b14003d46f00cf6afa
parentf12fbce0f51d58b429afd8a359aeb8a3b27a4eb0

IR: add FnProto instruction


12 files changed, 416 insertions(+), 300 deletions(-)

CMakeLists.txt+1-1
......@@ -52,11 +52,11 @@ set(ZIG_SOURCES
5252 "${CMAKE_SOURCE_DIR}/src/link.cpp"
5353 "${CMAKE_SOURCE_DIR}/src/main.cpp"
5454 "${CMAKE_SOURCE_DIR}/src/os.cpp"
55 "${CMAKE_SOURCE_DIR}/src/parseh.cpp"
5655 "${CMAKE_SOURCE_DIR}/src/parser.cpp"
5756 "${CMAKE_SOURCE_DIR}/src/target.cpp"
5857 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
5958 "${CMAKE_SOURCE_DIR}/src/util.cpp"
59 "${CMAKE_SOURCE_DIR}/src/parseh.cpp"
6060 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
6161)
6262
src/all_types.hpp+8
......@@ -1448,6 +1448,7 @@ enum IrInstructionId {
14481448 IrInstructionIdUnwrapErrPayload,
14491449 IrInstructionIdErrWrapCode,
14501450 IrInstructionIdErrWrapPayload,
1451 IrInstructionIdFnProto,
14511452};
14521453
14531454struct IrInstruction {
......@@ -2060,6 +2061,13 @@ struct IrInstructionErrWrapCode {
20602061 LLVMValueRef tmp_ptr;
20612062};
20622063
2064struct IrInstructionFnProto {
2065 IrInstruction base;
2066
2067 IrInstruction **param_types;
2068 IrInstruction *return_type;
2069};
2070
20632071enum LValPurpose {
20642072 LValPurposeNone,
20652073 LValPurposeAssign,
src/codegen.cpp+1
......@@ -2196,6 +2196,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
21962196 case IrInstructionIdIntType:
21972197 case IrInstructionIdMemberCount:
21982198 case IrInstructionIdAlignOf:
2199 case IrInstructionIdFnProto:
21992200 zig_unreachable();
22002201 case IrInstructionIdReturn:
22012202 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/ir.cpp+85-1
......@@ -439,6 +439,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrWrapCode *) {
439439 return IrInstructionIdErrWrapCode;
440440}
441441
442static constexpr IrInstructionId ir_instruction_id(IrInstructionFnProto *) {
443 return IrInstructionIdFnProto;
444}
445
442446template<typename T>
443447static T *ir_create_instruction(IrExecutable *exec, Scope *scope, AstNode *source_node) {
444448 T *special_instruction = allocate<T>(1);
......@@ -1826,6 +1830,22 @@ static IrInstruction *ir_build_unwrap_err_payload_from(IrBuilder *irb, IrInstruc
18261830 return new_instruction;
18271831}
18281832
1833static 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
18291849static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
18301850 results[ReturnKindUnconditional] = 0;
18311851 results[ReturnKindError] = 0;
......@@ -3894,6 +3914,28 @@ static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope,
38943914 return ir_build_const_type(irb, parent_scope, node, container_type);
38953915}
38963916
3917static 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
38973939static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
38983940 LValPurpose lval)
38993941{
......@@ -3978,11 +4020,15 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
39784020 case NodeTypeContainerDecl:
39794021 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
39804022 case NodeTypeFnProto:
4023 return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval);
39814024 case NodeTypeFnDef:
4025 zig_panic("TODO IR gen NodeTypeFnDef");
39824026 case NodeTypeFnDecl:
4027 zig_panic("TODO IR gen NodeTypeFnDecl");
39834028 case NodeTypeErrorValueDecl:
4029 zig_panic("TODO IR gen NodeTypeErrorValueDecl");
39844030 case NodeTypeTypeDecl:
3985 zig_panic("TODO more IR gen for node types");
4031 zig_panic("TODO IR gen NodeTypeTypeDecl");
39864032 case NodeTypeZeroesLiteral:
39874033 zig_panic("TODO zeroes is deprecated");
39884034 }
......@@ -9377,6 +9423,41 @@ static TypeTableEntry *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
93779423
93789424}
93799425
9426static 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
93809461static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
93819462 switch (instruction->id) {
93829463 case IrInstructionIdInvalid:
......@@ -9517,6 +9598,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
95179598 return ir_analyze_instruction_unwrap_err_code(ira, (IrInstructionUnwrapErrCode *)instruction);
95189599 case IrInstructionIdUnwrapErrPayload:
95199600 return ir_analyze_instruction_unwrap_err_payload(ira, (IrInstructionUnwrapErrPayload *)instruction);
9601 case IrInstructionIdFnProto:
9602 return ir_analyze_instruction_fn_proto(ira, (IrInstructionFnProto *)instruction);
95209603 case IrInstructionIdMaybeWrap:
95219604 case IrInstructionIdErrWrapCode:
95229605 case IrInstructionIdErrWrapPayload:
......@@ -9677,6 +9760,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
96779760 case IrInstructionIdMaybeWrap:
96789761 case IrInstructionIdErrWrapCode:
96799762 case IrInstructionIdErrWrapPayload:
9763 case IrInstructionIdFnProto:
96809764 return false;
96819765 case IrInstructionIdAsm:
96829766 {
src/ir_print.cpp+14
......@@ -882,6 +882,17 @@ static void ir_print_err_wrap_payload(IrPrint *irp, IrInstructionErrWrapPayload
882882 fprintf(irp->f, ")");
883883}
884884
885static 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
885896static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
886897 ir_print_prefix(irp, instruction);
887898 switch (instruction->id) {
......@@ -1112,6 +1123,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
11121123 case IrInstructionIdErrWrapPayload:
11131124 ir_print_err_wrap_payload(irp, (IrInstructionErrWrapPayload *)instruction);
11141125 break;
1126 case IrInstructionIdFnProto:
1127 ir_print_fn_proto(irp, (IrInstructionFnProto *)instruction);
1128 break;
11151129 }
11161130 fprintf(irp->f, "\n");
11171131}
std/debug.zig+18-18
......@@ -69,7 +69,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void {
6969 }
7070}
7171
72struct ElfStackTrace {
72const ElfStackTrace = struct {
7373 self_exe_stream: io.InStream,
7474 elf: elf.Elf,
7575 debug_info: &elf.SectionHeader,
......@@ -77,36 +77,36 @@ struct ElfStackTrace {
7777 debug_str: &elf.SectionHeader,
7878 abbrev_table_list: List(AbbrevTableHeader),
7979 compile_unit_list: List(CompileUnit),
80}
80};
8181
82struct CompileUnit {
82const CompileUnit = struct {
8383 is_64: bool,
8484 die: &Die,
8585 pc_start: u64,
8686 pc_end: u64,
87}
87};
8888
8989const AbbrevTable = List(AbbrevTableEntry);
9090
91struct AbbrevTableHeader {
91const AbbrevTableHeader = struct {
9292 // offset from .debug_abbrev
9393 offset: u64,
9494 table: AbbrevTable,
95}
95};
9696
97struct AbbrevTableEntry {
97const AbbrevTableEntry = struct {
9898 has_children: bool,
9999 abbrev_code: u64,
100100 tag_id: u64,
101101 attrs: List(AbbrevAttr),
102}
102};
103103
104struct AbbrevAttr {
104const AbbrevAttr = struct {
105105 attr_id: u64,
106106 form_id: u64,
107}
107};
108108
109enum FormValue {
109const FormValue = enum {
110110 Address: u64,
111111 Block: []u8,
112112 Const: Constant,
......@@ -118,9 +118,9 @@ enum FormValue {
118118 RefSig8: u64,
119119 String: []u8,
120120 StrPtr: u64,
121}
121};
122122
123struct Constant {
123const Constant = struct {
124124 payload: []u8,
125125 signed: bool,
126126
......@@ -131,17 +131,17 @@ struct Constant {
131131 return error.InvalidDebugInfo;
132132 return mem.sliceAsInt(self.payload, false, u64);
133133 }
134}
134};
135135
136struct Die {
136const Die = struct {
137137 tag_id: u64,
138138 has_children: bool,
139139 attrs: List(Attr),
140140
141 struct Attr {
141 const Attr = struct {
142142 id: u64,
143143 value: FormValue,
144 }
144 };
145145
146146 fn getAttr(self: &const Die, id: u64) -> ?&const FormValue {
147147 for (self.attrs.toSlice()) |*attr| {
......@@ -175,7 +175,7 @@ struct Die {
175175 else => error.InvalidDebugInfo,
176176 }
177177 }
178}
178};
179179
180180fn readString(in_stream: &io.InStream) -> %[]u8 {
181181 var buf = List(u8).init(&global_allocator);
std/elf.zig+8-8
......@@ -30,14 +30,14 @@ pub const SHT_HIPROC = 0x7fffffff;
3030pub const SHT_LOUSER = 0x80000000;
3131pub const SHT_HIUSER = 0xffffffff;
3232
33pub enum FileType {
33pub const FileType = enum {
3434 Relocatable,
3535 Executable,
3636 Shared,
3737 Core,
38}
38};
3939
40pub enum Arch {
40pub const Arch = enum {
4141 Sparc,
4242 x86,
4343 Mips,
......@@ -47,9 +47,9 @@ pub enum Arch {
4747 IA_64,
4848 x86_64,
4949 AArch64,
50}
50};
5151
52pub struct SectionHeader {
52pub const SectionHeader = struct {
5353 name: u32,
5454 sh_type: u32,
5555 flags: u64,
......@@ -60,9 +60,9 @@ pub struct SectionHeader {
6060 info: u32,
6161 addr_align: u64,
6262 ent_size: u64,
63}
63};
6464
65pub struct Elf {
65pub const Elf = struct {
6666 in_stream: &io.InStream,
6767 auto_close_stream: bool,
6868 is_64: bool,
......@@ -258,4 +258,4 @@ pub struct Elf {
258258 pub fn seekToSection(elf: &Elf, section: &SectionHeader) -> %void {
259259 %return elf.in_stream.seekTo(section.offset);
260260 }
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,
1313 SmallHashMap(K, V, hash, eql, @sizeOf(usize))
1414}
1515
16pub struct SmallHashMap(K: type, V: type, hash: fn(key: K)->u32, eql: fn(a: K, b: K)->bool, static_size: usize) {
17 entries: []Entry,
18 size: usize,
19 max_distance_from_start_index: usize,
20 allocator: &Allocator,
21 // if the hash map is small enough, we use linear search through these
22 // entries instead of allocating memory
23 prealloc_entries: [static_size]Entry,
24 // this is used to detect bugs where a hashtable is edited while an iterator is running.
25 modification_count: debug_u32,
26
27 const Self = this;
28
29 pub struct Entry {
30 used: bool,
31 distance_from_start_index: usize,
32 key: K,
33 value: V,
34 }
35
36 pub struct Iterator {
37 hm: &Self,
38 // how many items have we returned
39 count: usize,
40 // iterator through the entry array
41 index: usize,
42 // used to detect concurrent modification
43 initial_modification_count: debug_u32,
16pub fn SmallHashMap(inline K: type, inline V: type,
17 inline hash: fn(key: K)->u32, inline eql: fn(a: K, b: K)->bool,
18 inline static_size: usize) -> type
19{
20 struct {
21 entries: []Entry,
22 size: usize,
23 max_distance_from_start_index: usize,
24 allocator: &Allocator,
25 // if the hash map is small enough, we use linear search through these
26 // entries instead of allocating memory
27 prealloc_entries: [static_size]Entry,
28 // this is used to detect bugs where a hashtable is edited while an iterator is running.
29 modification_count: debug_u32,
30
31 const Self = this;
32
33 pub const Entry = struct {
34 used: bool,
35 distance_from_start_index: usize,
36 key: K,
37 value: V,
38 };
4439
45 pub fn next(it: &Iterator) -> ?&Entry {
46 if (want_modification_safety) {
47 assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification
48 }
49 if (it.count >= it.hm.size) return null;
50 while (it.index < it.hm.entries.len; it.index += 1) {
51 const entry = &it.hm.entries[it.index];
52 if (entry.used) {
53 it.index += 1;
54 it.count += 1;
55 return entry;
40 pub const Iterator = struct {
41 hm: &Self,
42 // how many items have we returned
43 count: usize,
44 // iterator through the entry array
45 index: usize,
46 // used to detect concurrent modification
47 initial_modification_count: debug_u32,
48
49 pub fn next(it: &Iterator) -> ?&Entry {
50 if (want_modification_safety) {
51 assert(it.initial_modification_count == it.hm.modification_count); // concurrent modification
5652 }
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
5763 }
58 @unreachable() // no next item
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 }
64 };
7065
71 pub fn deinit(hm: &Self) {
72 if (hm.entries.ptr != &hm.prealloc_entries[0]) {
73 hm.allocator.free(Entry, hm.entries);
66 pub fn init(hm: &Self, allocator: &Allocator) {
67 hm.entries = hm.prealloc_entries[0...];
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;
7473 }
75 }
7674
77 pub fn clear(hm: &Self) {
78 for (hm.entries) |*entry| {
79 entry.used = false;
75 pub fn deinit(hm: &Self) {
76 if (hm.entries.ptr != &hm.prealloc_entries[0]) {
77 hm.allocator.free(Entry, hm.entries);
78 }
8079 }
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();
8880
89 const resize = if (hm.entries.ptr == &hm.prealloc_entries[0]) {
90 // preallocated entries table is full
91 hm.size == hm.entries.len
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);
81 pub fn clear(hm: &Self) {
82 for (hm.entries) |*entry| {
83 entry.used = false;
10784 }
85 hm.size = 0;
86 hm.max_distance_from_start_index = 0;
87 hm.incrementModificationCount();
10888 }
10989
110 hm.internalPut(key, value);
111 }
112
113 pub fn get(hm: &Self, key: K) -> ?&Entry {
114 return hm.internalGet(key);
115 }
90 pub fn put(hm: &Self, key: K, value: V) -> %void {
91 hm.incrementModificationCount();
11692
117 pub fn remove(hm: &Self, key: K) {
118 hm.incrementModificationCount();
119 const start_index = hm.keyToIndex(key);
120 {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) {
121 const index = (start_index + roll_over) % hm.entries.len;
122 var entry = &hm.entries[index];
93 const resize = if (hm.entries.ptr == &hm.prealloc_entries[0]) {
94 // preallocated entries table is full
95 hm.size == hm.entries.len
96 } else {
97 // if we get too full (60%), double the capacity
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 }
123113
124 assert(entry.used); // key not found
114 hm.internalPut(key, value);
115 }
125116
126 if (!eql(entry.key, key)) continue;
117 pub fn get(hm: &Self, key: K) -> ?&Entry {
118 return hm.internalGet(key);
119 }
127120
128 while (roll_over < hm.entries.len; roll_over += 1) {
129 const next_index = (start_index + roll_over + 1) % hm.entries.len;
130 const next_entry = &hm.entries[next_index];
131 if (!next_entry.used || next_entry.distance_from_start_index == 0) {
132 entry.used = false;
133 hm.size -= 1;
134 return;
121 pub fn remove(hm: &Self, key: K) {
122 hm.incrementModificationCount();
123 const start_index = hm.keyToIndex(key);
124 {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) {
125 const index = (start_index + roll_over) % hm.entries.len;
126 var entry = &hm.entries[index];
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;
135143 }
136 *entry = *next_entry;
137 entry.distance_from_start_index -= 1;
138 entry = next_entry;
139 }
140 @unreachable() // shifting everything in the table
141 }}
142 @unreachable() // key not found
143 }
144 @unreachable() // shifting everything in the table
145 }}
146 @unreachable() // key not found
147 }
144148
145 pub fn entryIterator(hm: &Self) -> Iterator {
146 return Iterator {
147 .hm = hm,
148 .count = 0,
149 .index = 0,
150 .initial_modification_count = hm.modification_count,
151 };
152 }
149 pub fn entryIterator(hm: &Self) -> Iterator {
150 return Iterator {
151 .hm = hm,
152 .count = 0,
153 .index = 0,
154 .initial_modification_count = hm.modification_count,
155 };
156 }
153157
154 fn initCapacity(hm: &Self, capacity: usize) -> %void {
155 hm.entries = %return hm.allocator.alloc(Entry, capacity);
156 hm.size = 0;
157 hm.max_distance_from_start_index = 0;
158 for (hm.entries) |*entry| {
159 entry.used = false;
158 fn initCapacity(hm: &Self, capacity: usize) -> %void {
159 hm.entries = %return hm.allocator.alloc(Entry, capacity);
160 hm.size = 0;
161 hm.max_distance_from_start_index = 0;
162 for (hm.entries) |*entry| {
163 entry.used = false;
164 }
160165 }
161 }
162166
163 fn incrementModificationCount(hm: &Self) {
164 if (want_modification_safety) {
165 hm.modification_count +%= 1;
167 fn incrementModificationCount(hm: &Self) {
168 if (want_modification_safety) {
169 hm.modification_count +%= 1;
170 }
166171 }
167 }
168172
169 fn internalPut(hm: &Self, orig_key: K, orig_value: V) {
170 var key = orig_key;
171 var value = orig_value;
172 const start_index = hm.keyToIndex(key);
173 var roll_over: usize = 0;
174 var distance_from_start_index: usize = 0;
175 while (roll_over < hm.entries.len; {roll_over += 1; distance_from_start_index += 1}) {
176 const index = (start_index + roll_over) % hm.entries.len;
177 const entry = &hm.entries[index];
178
179 if (entry.used && !eql(entry.key, key)) {
180 if (entry.distance_from_start_index < distance_from_start_index) {
181 // robin hood to the rescue
182 const tmp = *entry;
183 hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index,
184 distance_from_start_index);
185 *entry = Entry {
186 .used = true,
187 .distance_from_start_index = distance_from_start_index,
188 .key = key,
189 .value = value,
190 };
191 key = tmp.key;
192 value = tmp.value;
193 distance_from_start_index = tmp.distance_from_start_index;
173 fn internalPut(hm: &Self, orig_key: K, orig_value: V) {
174 var key = orig_key;
175 var value = orig_value;
176 const start_index = hm.keyToIndex(key);
177 var roll_over: usize = 0;
178 var distance_from_start_index: usize = 0;
179 while (roll_over < hm.entries.len; {roll_over += 1; distance_from_start_index += 1}) {
180 const index = (start_index + roll_over) % hm.entries.len;
181 const entry = &hm.entries[index];
182
183 if (entry.used && !eql(entry.key, key)) {
184 if (entry.distance_from_start_index < distance_from_start_index) {
185 // robin hood to the rescue
186 const tmp = *entry;
187 hm.max_distance_from_start_index = math.max(hm.max_distance_from_start_index,
188 distance_from_start_index);
189 *entry = Entry {
190 .used = true,
191 .distance_from_start_index = distance_from_start_index,
192 .key = key,
193 .value = value,
194 };
195 key = tmp.key;
196 value = tmp.value;
197 distance_from_start_index = tmp.distance_from_start_index;
198 }
199 continue;
194200 }
195 continue;
196 }
197201
198 if (!entry.used) {
199 // adding an entry. otherwise overwriting old value with
200 // same key
201 hm.size += 1;
202 }
202 if (!entry.used) {
203 // adding an entry. otherwise overwriting old value with
204 // same key
205 hm.size += 1;
206 }
203207
204 hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index);
205 *entry = Entry {
206 .used = true,
207 .distance_from_start_index = distance_from_start_index,
208 .key = key,
209 .value = value,
210 };
211 return;
208 hm.max_distance_from_start_index = math.max(distance_from_start_index, hm.max_distance_from_start_index);
209 *entry = Entry {
210 .used = true,
211 .distance_from_start_index = distance_from_start_index,
212 .key = key,
213 .value = value,
214 };
215 return;
216 }
217 @unreachable() // put into a full map
212218 }
213 @unreachable() // put into a full map
214 }
215219
216 fn internalGet(hm: &Self, key: K) -> ?&Entry {
217 const start_index = hm.keyToIndex(key);
218 {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;
220 const entry = &hm.entries[index];
220 fn internalGet(hm: &Self, key: K) -> ?&Entry {
221 const start_index = hm.keyToIndex(key);
222 {var roll_over: usize = 0; while (roll_over <= hm.max_distance_from_start_index; roll_over += 1) {
223 const index = (start_index + roll_over) % hm.entries.len;
224 const entry = &hm.entries[index];
221225
222 if (!entry.used) return null;
223 if (eql(entry.key, key)) return entry;
224 }}
225 return null;
226 }
226 if (!entry.used) return null;
227 if (eql(entry.key, key)) return entry;
228 }}
229 return null;
230 }
227231
228 fn keyToIndex(hm: &Self, key: K) -> usize {
229 return usize(hash(key)) % hm.entries.len;
232 fn keyToIndex(hm: &Self, key: K) -> usize {
233 return usize(hash(key)) % hm.entries.len;
234 }
230235 }
231236}
232237
std/list.zig+36-34
......@@ -3,49 +3,51 @@ const assert = debug.assert;
33const mem = @import("mem.zig");
44const Allocator = mem.Allocator;
55
6pub struct List(T: type) {
7 const Self = this;
6pub fn List(inline T: type) -> type{
7 struct {
8 const Self = this;
89
9 items: []T,
10 len: usize,
11 allocator: &Allocator,
10 items: []T,
11 len: usize,
12 allocator: &Allocator,
1213
13 pub fn init(allocator: &Allocator) -> Self {
14 Self {
15 .items = zeroes,
16 .len = 0,
17 .allocator = allocator,
14 pub fn init(allocator: &Allocator) -> Self {
15 Self {
16 .items = zeroes,
17 .len = 0,
18 .allocator = allocator,
19 }
1820 }
19 }
2021
21 pub fn deinit(l: &Self) {
22 l.allocator.free(T, l.items);
23 }
22 pub fn deinit(l: &Self) {
23 l.allocator.free(T, l.items);
24 }
2425
25 pub fn toSlice(l: &Self) -> []T {
26 return l.items[0...l.len];
27 }
26 pub fn toSlice(l: &Self) -> []T {
27 return l.items[0...l.len];
28 }
2829
29 pub fn append(l: &Self, item: T) -> %void {
30 const new_length = l.len + 1;
31 %return l.ensureCapacity(new_length);
32 l.items[l.len] = item;
33 l.len = new_length;
34 }
30 pub fn append(l: &Self, item: T) -> %void {
31 const new_length = l.len + 1;
32 %return l.ensureCapacity(new_length);
33 l.items[l.len] = item;
34 l.len = new_length;
35 }
3536
36 pub fn resize(l: &Self, new_len: usize) -> %void {
37 %return l.ensureCapacity(new_len);
38 l.len = new_len;
39 }
37 pub fn resize(l: &Self, new_len: usize) -> %void {
38 %return l.ensureCapacity(new_len);
39 l.len = new_len;
40 }
4041
41 pub fn ensureCapacity(l: &Self, new_capacity: usize) -> %void {
42 var better_capacity = l.items.len;
43 if (better_capacity >= new_capacity) return;
44 while (true) {
45 better_capacity += better_capacity / 2 + 8;
46 if (better_capacity >= new_capacity) break;
42 pub fn ensureCapacity(l: &Self, new_capacity: usize) -> %void {
43 var better_capacity = l.items.len;
44 if (better_capacity >= new_capacity) return;
45 while (true) {
46 better_capacity += better_capacity / 2 + 8;
47 if (better_capacity >= new_capacity) break;
48 }
49 l.items = %return l.allocator.realloc(T, l.items, better_capacity);
4750 }
48 l.items = %return l.allocator.realloc(T, l.items, better_capacity);
4951 }
5052}
5153
std/mem.zig+2-2
......@@ -8,7 +8,7 @@ pub const Cmp = math.Cmp;
88pub error NoMem;
99
1010pub type Context = u8;
11pub struct Allocator {
11pub const Allocator = struct {
1212 allocFn: fn (self: &Allocator, n: usize) -> %[]u8,
1313 reallocFn: fn (self: &Allocator, old_mem: []u8, new_size: usize) -> %[]u8,
1414 freeFn: fn (self: &Allocator, mem: []u8),
......@@ -39,7 +39,7 @@ pub struct Allocator {
3939 fn free(self: &Allocator, inline T: type, mem: []T) {
4040 self.freeFn(self, ([]u8)(mem));
4141 }
42}
42};
4343
4444/// Copy all of source into dest at position 0.
4545/// dest.len must be >= source.len.
std/net.zig+4-4
......@@ -13,7 +13,7 @@ pub error NoMem;
1313pub error NotSocket;
1414pub error BadFd;
1515
16struct Connection {
16const Connection = struct {
1717 socket_fd: i32,
1818
1919 pub fn send(c: Connection, buf: []const u8) -> %usize {
......@@ -56,14 +56,14 @@ struct Connection {
5656 else => return error.Unexpected,
5757 }
5858 }
59}
59};
6060
61struct Address {
61const Address = struct {
6262 family: u16,
6363 scope_id: u32,
6464 addr: [16]u8,
6565 sort_key: i32,
66}
66};
6767
6868pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address {
6969 if (hostname.len == 0) {
std/rand.zig+49-47
......@@ -18,7 +18,7 @@ pub const MT19937_64 = MersenneTwister(
1818 43, 6364136223846793005);
1919
2020/// Use `init` to initialize this state.
21pub struct Rand {
21pub const Rand = struct {
2222 const Rng = if (@sizeOf(usize) >= 8) MT19937_64 else MT19937_32;
2323
2424 rng: Rng,
......@@ -91,65 +91,67 @@ pub struct Rand {
9191 };
9292 return T(r.rangeUnsigned(int_type, 0, precision)) / T(precision);
9393 }
94}
95
96struct MersenneTwister(
97 int: type, n: usize, m: usize, r: int,
98 a: int,
99 u: int, d: int,
100 s: int, b: int,
101 t: int, c: int,
102 l: int, f: int)
94};
95
96fn MersenneTwister(
97 inline int: type, inline n: usize, inline m: usize, inline r: int,
98 inline a: int,
99 inline u: int, inline d: int,
100 inline s: int, inline b: int,
101 inline t: int, inline c: int,
102 inline l: int, inline f: int) -> type
103103{
104 const Self = this;
104 struct {
105 const Self = this;
105106
106 array: [n]int,
107 index: usize,
107 array: [n]int,
108 index: usize,
108109
109 pub fn init(mt: &Self, seed: int) {
110 mt.index = n;
110 pub fn init(mt: &Self, seed: int) {
111 mt.index = n;
111112
112 var prev_value = seed;
113 mt.array[0] = prev_value;
114 {var i: usize = 1; while (i < n; i += 1) {
115 prev_value = int(i) +% f *% (prev_value ^ (prev_value >> (int.bit_count - 2)));
116 mt.array[i] = prev_value;
117 }};
118 }
113 var prev_value = seed;
114 mt.array[0] = prev_value;
115 {var i: usize = 1; while (i < n; i += 1) {
116 prev_value = int(i) +% f *% (prev_value ^ (prev_value >> (int.bit_count - 2)));
117 mt.array[i] = prev_value;
118 }};
119 }
119120
120 pub fn get(mt: &Self) -> int {
121 const mag01 = []int{0, a};
122 const LM: int = (1 << r) - 1;
123 const UM = ~LM;
121 pub fn get(mt: &Self) -> int {
122 const mag01 = []int{0, a};
123 const LM: int = (1 << r) - 1;
124 const UM = ~LM;
124125
125 if (mt.index >= n) {
126 var i: usize = 0;
126 if (mt.index >= n) {
127 var i: usize = 0;
127128
128 while (i < n - m; i += 1) {
129 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 }
129 while (i < n - m; i += 1) {
130 const x = (mt.array[i] & UM) | (mt.array[i + 1] & LM);
131 mt.array[i] = mt.array[i + m] ^ (x >> 1) ^ mag01[x & 0x1];
132 }
132133
133 while (i < n - 1; i += 1) {
134 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];
134 while (i < n - 1; i += 1) {
135 const x = (mt.array[i] & UM) | (mt.array[i + 1] & LM);
136 mt.array[i] = mt.array[i + m - n] ^ (x >> 1) ^ mag01[x & 0x1];
136137
137 }
138 const x = (mt.array[i] & UM) | (mt.array[0] & LM);
139 mt.array[i] = mt.array[m - 1] ^ (x >> 1) ^ mag01[x & 0x1];
138 }
139 const x = (mt.array[i] & UM) | (mt.array[0] & LM);
140 mt.array[i] = mt.array[m - 1] ^ (x >> 1) ^ mag01[x & 0x1];
140141
141 mt.index = 0;
142 }
142 mt.index = 0;
143 }
143144
144 var x = mt.array[mt.index];
145 mt.index += 1;
145 var x = mt.array[mt.index];
146 mt.index += 1;
146147
147 x ^= ((x >> u) & d);
148 x ^= ((x <<% s) & b);
149 x ^= ((x <<% t) & c);
150 x ^= (x >> l);
148 x ^= ((x >> u) & d);
149 x ^= ((x <<% s) & b);
150 x ^= ((x <<% t) & c);
151 x ^= (x >> l);
151152
152 return x;
153 return x;
154 }
153155 }
154156}
155157