| author | |
| committer | |
| log | 5e64c4d92f109638111d78b6ab97feb645ee0a01 |
| tree | e0bede139e1ef7ffb7f6478f7a8c69bb4a2c8781 |
| parent | f1eafe4ebb2e1258ee398641d0537e227fe2ea0d |
guess number example prints the answer now10 files changed, 201 insertions(+), 308 deletions(-)
CMakeLists.txt+1| ... | ... | @@ -118,6 +118,7 @@ set(C_HEADERS |
| 118 | 118 | set(ZIG_STD_SRC |
| 119 | 119 | "${CMAKE_SOURCE_DIR}/std/bootstrap.zig" |
| 120 | 120 | "${CMAKE_SOURCE_DIR}/std/std.zig" |
| 121 | "${CMAKE_SOURCE_DIR}/std/rand.zig" | |
| 121 | 122 | ) |
| 122 | 123 | |
| 123 | 124 | set(C_HEADERS_DEST "lib/zig/include") |
doc/langref.md+1-1| ... | ... | @@ -36,7 +36,7 @@ TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | Variabl |
| 36 | 36 | |
| 37 | 37 | VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression)) |
| 38 | 38 | |
| 39 | StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructMember) token(RBrace) | |
| 39 | StructDecl : many(Directive) option(FnVisibleMod) token(Struct) token(Symbol) token(LBrace) many(StructMember) token(RBrace) | |
| 40 | 40 | |
| 41 | 41 | StructMember: StructField | FnDecl |
| 42 | 42 |
example/guess_number/main.zig+5-4| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | export executable "guess_number"; |
| 2 | 2 | |
| 3 | 3 | use "std.zig"; |
| 4 | use "rand.zig"; | |
| 4 | 5 | |
| 5 | 6 | // TODO don't duplicate these; implement pub const |
| 6 | 7 | const stdout_fileno : isize = 1; |
| ... | ... | @@ -11,16 +12,16 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { |
| 11 | 12 | |
| 12 | 13 | var seed : u32; |
| 13 | 14 | var err : isize; |
| 14 | // TODO #sizeof(u32) instead of 4 | |
| 15 | if ({err = os_get_random_bytes(&seed as &u8, 4); err != 4}) { | |
| 15 | if ({err = os_get_random_bytes(&seed as &u8, #sizeof(u32)); err != #sizeof(u32)}) { | |
| 16 | 16 | // TODO full error message |
| 17 | 17 | fprint_str(stderr_fileno, "unable to get random bytes"); |
| 18 | 18 | return 1; |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | var rand_state = rand_init(seed); | |
| 21 | var rand : Rand; | |
| 22 | rand.init(seed); | |
| 22 | 23 | |
| 23 | const answer = rand_u64(&rand_state, 0, 100) + 1; | |
| 24 | const answer = rand.range_u64(0, 100) + 1; | |
| 24 | 25 | |
| 25 | 26 | print_str("Answer: "); |
| 26 | 27 | print_u64(answer); |
example/rand/main.zig deleted-120| ... | ... | @@ -1,120 +0,0 @@ |
| 1 | export executable "rand"; | |
| 2 | ||
| 3 | use "std.zig"; | |
| 4 | ||
| 5 | // Mersenne Twister | |
| 6 | const ARRAY_SIZE : u16 = 624; | |
| 7 | ||
| 8 | /// Use `rand_init` to initialize this state. | |
| 9 | struct Rand { | |
| 10 | // TODO use ARRAY_SIZE here | |
| 11 | array: [624]u32, | |
| 12 | // TODO use #typeof(ARRAY_SIZE) here | |
| 13 | index: u16, | |
| 14 | ||
| 15 | /// Get 32 bits of randomness. | |
| 16 | pub fn get_u32(r: &Rand) -> u32 { | |
| 17 | if (r.index == 0) { | |
| 18 | r.generate_numbers(); | |
| 19 | } | |
| 20 | ||
| 21 | // temper the number | |
| 22 | var y : u32 = r.array[r.index]; | |
| 23 | y ^= y >> 11; | |
| 24 | y ^= (y >> 7) & 0x9d2c5680; | |
| 25 | y ^= (y >> 15) & 0xefc60000; | |
| 26 | y ^= y >> 18; | |
| 27 | ||
| 28 | r.index = (r.index + 1) % ARRAY_SIZE; | |
| 29 | return y; | |
| 30 | } | |
| 31 | ||
| 32 | /// Fill `buf` with randomness. | |
| 33 | pub fn get_bytes(r: &Rand, buf: []u8) { | |
| 34 | var bytes_left = r.get_bytes_aligned(buf); | |
| 35 | if (bytes_left > 0) { | |
| 36 | var rand_val_array : [#sizeof(u32)]u8; | |
| 37 | *(rand_val_array.ptr as &u32) = r.get_u32(); | |
| 38 | while (bytes_left > 0) { | |
| 39 | // TODO array index operator so we can remove the .ptr | |
| 40 | buf.ptr[buf.len - bytes_left] = rand_val_array[#sizeof(u32) - bytes_left]; | |
| 41 | bytes_left -= 1; | |
| 42 | } | |
| 43 | } | |
| 44 | } | |
| 45 | ||
| 46 | /// Get a random unsigned integer with even distribution between `start` | |
| 47 | /// inclusive and `end` exclusive. | |
| 48 | pub fn range_u64(r: &Rand, start: u64, end: u64) -> u64 { | |
| 49 | const range = end - start; | |
| 50 | const leftover = #max_value(u64) % range; | |
| 51 | const upper_bound = #max_value(u64) - leftover; | |
| 52 | var rand_val_array : [#sizeof(u64)]u8; | |
| 53 | ||
| 54 | while (true) { | |
| 55 | r.get_bytes_aligned(rand_val_array); | |
| 56 | const rand_val = *(rand_val_array.ptr as &u64); | |
| 57 | if (rand_val < upper_bound) { | |
| 58 | return start + (rand_val % range); | |
| 59 | } | |
| 60 | } | |
| 61 | // TODO detect simple constant in while loop and no breaks and turn it into unreachable | |
| 62 | // type. then we can remove this unreachable. | |
| 63 | unreachable; | |
| 64 | } | |
| 65 | ||
| 66 | fn generate_numbers(r: &Rand) { | |
| 67 | var i : #typeof(ARRAY_SIZE) = 0; | |
| 68 | while (i < ARRAY_SIZE) { | |
| 69 | const y : u32 = (r.array[i] & 0x80000000) + (r.array[(i + 1) % ARRAY_SIZE] & 0x7fffffff); | |
| 70 | const untempered : u32 = r.array[(i + 397) % ARRAY_SIZE] ^ (y >> 1); | |
| 71 | r.array[i] = if ((y % 2) == 0) { | |
| 72 | untempered | |
| 73 | } else { | |
| 74 | // y is odd | |
| 75 | untempered ^ 0x9908b0df | |
| 76 | }; | |
| 77 | i += 1; | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 81 | // does not populate the remaining (buf.len % 4) bytes | |
| 82 | fn get_bytes_aligned(r: &Rand, buf: []u8) -> usize { | |
| 83 | var bytes_left = buf.len; | |
| 84 | while (bytes_left >= 4) { | |
| 85 | // TODO: array access so we can remove .ptr | |
| 86 | *(&buf.ptr[buf.len - bytes_left] as &u32) = r.get_u32(); | |
| 87 | bytes_left -= #sizeof(u32); | |
| 88 | } | |
| 89 | return bytes_left; | |
| 90 | } | |
| 91 | } | |
| 92 | ||
| 93 | /// Initialize random state with the given seed. | |
| 94 | pub fn rand_init(r: &Rand, seed: u32) { | |
| 95 | r.index = 0; | |
| 96 | r.array[0] = seed; | |
| 97 | var i : #typeof(ARRAY_SIZE) = 1; | |
| 98 | while (i < ARRAY_SIZE) { | |
| 99 | const prev_value : u64 = r.array[i - 1]; | |
| 100 | r.array[i] = ((prev_value ^ (prev_value << 30)) * 0x6c078965 + i) as u32; | |
| 101 | i += 1; | |
| 102 | } | |
| 103 | } | |
| 104 | ||
| 105 | pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { | |
| 106 | var rand : Rand; | |
| 107 | var i : u8 = 0; | |
| 108 | while (i < 20) { | |
| 109 | rand_init(&rand, i); | |
| 110 | var j : u8 = 0; | |
| 111 | while (j < 20) { | |
| 112 | print_u64(rand.range_u64(0, 100) + 1); | |
| 113 | print_str(" "); | |
| 114 | j += 1; | |
| 115 | } | |
| 116 | print_str("\n"); | |
| 117 | i += 1; | |
| 118 | } | |
| 119 | return 0; | |
| 120 | } |
src/analyze.cpp+31-5| ... | ... | @@ -474,7 +474,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 474 | 474 | add_node_error(g, child->data.param_decl.type, |
| 475 | 475 | buf_sprintf("parameter of type 'unreachable' not allowed")); |
| 476 | 476 | } else if (type_entry->id == TypeTableEntryIdVoid) { |
| 477 | if (node->data.fn_proto.visib_mod == FnProtoVisibModExport) { | |
| 477 | if (node->data.fn_proto.visib_mod == VisibModExport) { | |
| 478 | 478 | add_node_error(g, child->data.param_decl.type, |
| 479 | 479 | buf_sprintf("parameter of type 'void' not allowed on exported functions")); |
| 480 | 480 | } |
| ... | ... | @@ -599,8 +599,8 @@ static void preview_fn_def(CodeGen *g, ImportTableEntry *import, AstNode *node, |
| 599 | 599 | |
| 600 | 600 | auto entry = fn_table->maybe_get(proto_name); |
| 601 | 601 | bool skip = false; |
| 602 | bool is_internal = (proto_node->data.fn_proto.visib_mod != FnProtoVisibModExport); | |
| 603 | bool is_pub = (proto_node->data.fn_proto.visib_mod != FnProtoVisibModPrivate); | |
| 602 | bool is_internal = (proto_node->data.fn_proto.visib_mod != VisibModExport); | |
| 603 | bool is_pub = (proto_node->data.fn_proto.visib_mod != VisibModPrivate); | |
| 604 | 604 | if (entry) { |
| 605 | 605 | add_node_error(g, node, |
| 606 | 606 | buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); |
| ... | ... | @@ -2199,7 +2199,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo |
| 2199 | 2199 | node->codegen_node->data.fn_def_node.block_context = context; |
| 2200 | 2200 | |
| 2201 | 2201 | AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto; |
| 2202 | bool is_exported = (fn_proto->visib_mod == FnProtoVisibModExport); | |
| 2202 | bool is_exported = (fn_proto->visib_mod == VisibModExport); | |
| 2203 | 2203 | for (int i = 0; i < fn_proto->params.length; i += 1) { |
| 2204 | 2204 | AstNode *param_decl_node = fn_proto->params.at(i); |
| 2205 | 2205 | assert(param_decl_node->type == NodeTypeParamDecl); |
| ... | ... | @@ -2293,7 +2293,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, |
| 2293 | 2293 | break; |
| 2294 | 2294 | |
| 2295 | 2295 | FnTableEntry *fn_entry = entry->value; |
| 2296 | bool is_pub = (fn_entry->proto_node->data.fn_proto.visib_mod != FnProtoVisibModPrivate); | |
| 2296 | bool is_pub = (fn_entry->proto_node->data.fn_proto.visib_mod != VisibModPrivate); | |
| 2297 | 2297 | if (is_pub) { |
| 2298 | 2298 | auto existing_entry = import->fn_table.maybe_get(entry->key); |
| 2299 | 2299 | if (existing_entry) { |
| ... | ... | @@ -2306,6 +2306,32 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, |
| 2306 | 2306 | } |
| 2307 | 2307 | } |
| 2308 | 2308 | } |
| 2309 | ||
| 2310 | // import all the public types | |
| 2311 | { | |
| 2312 | auto it = target_import->type_table.entry_iterator(); | |
| 2313 | for (;;) { | |
| 2314 | auto *entry = it.next(); | |
| 2315 | if (!entry) | |
| 2316 | break; | |
| 2317 | ||
| 2318 | TypeTableEntry *type_entry = entry->value; | |
| 2319 | if (type_entry->id == TypeTableEntryIdStruct) { | |
| 2320 | AstNode *decl_node = type_entry->data.structure.decl_node; | |
| 2321 | bool is_pub = (decl_node->data.struct_decl.visib_mod != VisibModPrivate); | |
| 2322 | if (is_pub) { | |
| 2323 | auto existing_entry = import->type_table.maybe_get(entry->key); | |
| 2324 | if (existing_entry) { | |
| 2325 | add_node_error(g, node, | |
| 2326 | buf_sprintf("import of type '%s' overrides existing definition", | |
| 2327 | buf_ptr(&type_entry->name))); | |
| 2328 | } else { | |
| 2329 | import->type_table.put(entry->key, entry->value); | |
| 2330 | } | |
| 2331 | } | |
| 2332 | } | |
| 2333 | } | |
| 2334 | } | |
| 2309 | 2335 | break; |
| 2310 | 2336 | } |
| 2311 | 2337 | case NodeTypeStructDecl: |
src/codegen.cpp+2-2| ... | ... | @@ -2164,7 +2164,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 2164 | 2164 | assert(proto_node->type == NodeTypeFnProto); |
| 2165 | 2165 | Buf *proto_name = &proto_node->data.fn_proto.name; |
| 2166 | 2166 | |
| 2167 | bool is_private = (proto_node->data.fn_proto.visib_mod == FnProtoVisibModPrivate); | |
| 2167 | bool is_private = (proto_node->data.fn_proto.visib_mod == VisibModPrivate); | |
| 2168 | 2168 | |
| 2169 | 2169 | if (buf_eql_str(proto_name, "main") && !is_private) { |
| 2170 | 2170 | g->have_exported_main = true; |
| ... | ... | @@ -2287,7 +2287,7 @@ static void generate_h_file(CodeGen *g) { |
| 2287 | 2287 | assert(proto_node->type == NodeTypeFnProto); |
| 2288 | 2288 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 2289 | 2289 | |
| 2290 | if (fn_proto->visib_mod != FnProtoVisibModExport) | |
| 2290 | if (fn_proto->visib_mod != VisibModExport) | |
| 2291 | 2291 | continue; |
| 2292 | 2292 | |
| 2293 | 2293 | Buf return_type_c = BUF_INIT; |
src/parser.cpp+54-25| ... | ... | @@ -2387,34 +2387,40 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato |
| 2387 | 2387 | FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(token(Arrow) Type) |
| 2388 | 2388 | */ |
| 2389 | 2389 | static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory) { |
| 2390 | Token *token = &pc->tokens->at(*token_index); | |
| 2391 | ||
| 2392 | FnProtoVisibMod visib_mod; | |
| 2393 | ||
| 2394 | if (token->id == TokenIdKeywordPub) { | |
| 2395 | visib_mod = FnProtoVisibModPub; | |
| 2396 | *token_index += 1; | |
| 2390 | Token *first_token = &pc->tokens->at(*token_index); | |
| 2397 | 2391 | |
| 2398 | Token *fn_token = &pc->tokens->at(*token_index); | |
| 2399 | *token_index += 1; | |
| 2400 | ast_expect_token(pc, fn_token, TokenIdKeywordFn); | |
| 2401 | } else if (token->id == TokenIdKeywordExport) { | |
| 2402 | visib_mod = FnProtoVisibModExport; | |
| 2403 | *token_index += 1; | |
| 2392 | VisibMod visib_mod; | |
| 2404 | 2393 | |
| 2405 | Token *fn_token = &pc->tokens->at(*token_index); | |
| 2406 | *token_index += 1; | |
| 2407 | ast_expect_token(pc, fn_token, TokenIdKeywordFn); | |
| 2408 | } else if (token->id == TokenIdKeywordFn) { | |
| 2409 | visib_mod = FnProtoVisibModPrivate; | |
| 2394 | if (first_token->id == TokenIdKeywordPub) { | |
| 2395 | Token *next_token = &pc->tokens->at(*token_index + 1); | |
| 2396 | if (next_token->id == TokenIdKeywordFn) { | |
| 2397 | visib_mod = VisibModPub; | |
| 2398 | *token_index += 2; | |
| 2399 | } else if (mandatory) { | |
| 2400 | ast_invalid_token_error(pc, first_token); | |
| 2401 | } else { | |
| 2402 | return nullptr; | |
| 2403 | } | |
| 2404 | } else if (first_token->id == TokenIdKeywordExport) { | |
| 2405 | Token *next_token = &pc->tokens->at(*token_index + 1); | |
| 2406 | if (next_token->id == TokenIdKeywordFn) { | |
| 2407 | visib_mod = VisibModExport; | |
| 2408 | *token_index += 2; | |
| 2409 | } else if (mandatory) { | |
| 2410 | ast_invalid_token_error(pc, first_token); | |
| 2411 | } else { | |
| 2412 | return nullptr; | |
| 2413 | } | |
| 2414 | } else if (first_token->id == TokenIdKeywordFn) { | |
| 2415 | visib_mod = VisibModPrivate; | |
| 2410 | 2416 | *token_index += 1; |
| 2411 | 2417 | } else if (mandatory) { |
| 2412 | ast_invalid_token_error(pc, token); | |
| 2418 | ast_invalid_token_error(pc, first_token); | |
| 2413 | 2419 | } else { |
| 2414 | 2420 | return nullptr; |
| 2415 | 2421 | } |
| 2416 | 2422 | |
| 2417 | AstNode *node = ast_create_node(pc, NodeTypeFnProto, token); | |
| 2423 | AstNode *node = ast_create_node(pc, NodeTypeFnProto, first_token); | |
| 2418 | 2424 | node->data.fn_proto.visib_mod = visib_mod; |
| 2419 | 2425 | node->data.fn_proto.directives = pc->directive_list; |
| 2420 | 2426 | pc->directive_list = nullptr; |
| ... | ... | @@ -2584,22 +2590,45 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) { |
| 2584 | 2590 | } |
| 2585 | 2591 | |
| 2586 | 2592 | /* |
| 2587 | StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructMember) token(RBrace) | |
| 2593 | StructDecl : many(Directive) option(FnVisibleMod) token(Struct) token(Symbol) token(LBrace) many(StructMember) token(RBrace) | |
| 2588 | 2594 | StructMember: StructField | FnDecl |
| 2589 | 2595 | StructField : token(Symbol) token(Colon) Type token(Comma) |
| 2590 | 2596 | */ |
| 2591 | 2597 | static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) { |
| 2592 | Token *struct_kw = &pc->tokens->at(*token_index); | |
| 2593 | if (struct_kw->id != TokenIdKeywordStruct) | |
| 2598 | Token *first_token = &pc->tokens->at(*token_index); | |
| 2599 | ||
| 2600 | VisibMod visib_mod; | |
| 2601 | ||
| 2602 | if (first_token->id == TokenIdKeywordPub) { | |
| 2603 | Token *next_token = &pc->tokens->at(*token_index + 1); | |
| 2604 | if (next_token->id == TokenIdKeywordStruct) { | |
| 2605 | visib_mod = VisibModPub; | |
| 2606 | *token_index += 2; | |
| 2607 | } else { | |
| 2608 | return nullptr; | |
| 2609 | } | |
| 2610 | } else if (first_token->id == TokenIdKeywordExport) { | |
| 2611 | Token *next_token = &pc->tokens->at(*token_index + 1); | |
| 2612 | if (next_token->id == TokenIdKeywordStruct) { | |
| 2613 | visib_mod = VisibModExport; | |
| 2614 | *token_index += 2; | |
| 2615 | } else { | |
| 2616 | return nullptr; | |
| 2617 | } | |
| 2618 | } else if (first_token->id == TokenIdKeywordStruct) { | |
| 2619 | visib_mod = VisibModPrivate; | |
| 2620 | *token_index += 1; | |
| 2621 | } else { | |
| 2594 | 2622 | return nullptr; |
| 2595 | *token_index += 1; | |
| 2623 | } | |
| 2596 | 2624 | |
| 2597 | 2625 | Token *struct_name = &pc->tokens->at(*token_index); |
| 2598 | 2626 | *token_index += 1; |
| 2599 | 2627 | ast_expect_token(pc, struct_name, TokenIdSymbol); |
| 2600 | 2628 | |
| 2601 | AstNode *node = ast_create_node(pc, NodeTypeStructDecl, struct_kw); | |
| 2629 | AstNode *node = ast_create_node(pc, NodeTypeStructDecl, first_token); | |
| 2602 | 2630 | ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name); |
| 2631 | node->data.struct_decl.visib_mod = visib_mod; | |
| 2603 | 2632 | |
| 2604 | 2633 | ast_eat_token(pc, token_index, TokenIdLBrace); |
| 2605 | 2634 |
src/parser.hpp+6-5| ... | ... | @@ -65,15 +65,15 @@ struct AstNodeRoot { |
| 65 | 65 | ZigList<AstNode *> top_level_decls; |
| 66 | 66 | }; |
| 67 | 67 | |
| 68 | enum FnProtoVisibMod { | |
| 69 | FnProtoVisibModPrivate, | |
| 70 | FnProtoVisibModPub, | |
| 71 | FnProtoVisibModExport, | |
| 68 | enum VisibMod { | |
| 69 | VisibModPrivate, | |
| 70 | VisibModPub, | |
| 71 | VisibModExport, | |
| 72 | 72 | }; |
| 73 | 73 | |
| 74 | 74 | struct AstNodeFnProto { |
| 75 | 75 | ZigList<AstNode *> *directives; |
| 76 | FnProtoVisibMod visib_mod; | |
| 76 | VisibMod visib_mod; | |
| 77 | 77 | Buf name; |
| 78 | 78 | ZigList<AstNode *> params; |
| 79 | 79 | AstNode *return_type; |
| ... | ... | @@ -284,6 +284,7 @@ struct AstNodeStructDecl { |
| 284 | 284 | ZigList<AstNode *> fields; |
| 285 | 285 | ZigList<AstNode *> fns; |
| 286 | 286 | ZigList<AstNode *> *directives; |
| 287 | VisibMod visib_mod; | |
| 287 | 288 | }; |
| 288 | 289 | |
| 289 | 290 | struct AstNodeStructField { |
std/errno.zig deleted-146| ... | ... | @@ -1,146 +0,0 @@ |
| 1 | pub const EPERM = 1; // Operation not permitted | |
| 2 | pub const ENOENT = 2; // No such file or directory | |
| 3 | pub const ESRCH = 3; // No such process | |
| 4 | pub const EINTR = 4; // Interrupted system call | |
| 5 | pub const EIO = 5; // I/O error | |
| 6 | pub const ENXIO = 6; // No such device or address | |
| 7 | pub const E2BIG = 7; // Arg list too long | |
| 8 | pub const ENOEXEC = 8; // Exec format error | |
| 9 | pub const EBADF = 9; // Bad file number | |
| 10 | pub const ECHILD = 10; // No child processes | |
| 11 | pub const EAGAIN = 11; // Try again | |
| 12 | pub const ENOMEM = 12; // Out of memory | |
| 13 | pub const EACCES = 13; // Permission denied | |
| 14 | pub const EFAULT = 14; // Bad address | |
| 15 | pub const ENOTBLK = 15; // Block device required | |
| 16 | pub const EBUSY = 16; // Device or resource busy | |
| 17 | pub const EEXIST = 17; // File exists | |
| 18 | pub const EXDEV = 18; // Cross-device link | |
| 19 | pub const ENODEV = 19; // No such device | |
| 20 | pub const ENOTDIR = 20; // Not a directory | |
| 21 | pub const EISDIR = 21; // Is a directory | |
| 22 | pub const EINVAL = 22; // Invalid argument | |
| 23 | pub const ENFILE = 23; // File table overflow | |
| 24 | pub const EMFILE = 24; // Too many open files | |
| 25 | pub const ENOTTY = 25; // Not a typewriter | |
| 26 | pub const ETXTBSY = 26; // Text file busy | |
| 27 | pub const EFBIG = 27; // File too large | |
| 28 | pub const ENOSPC = 28; // No space left on device | |
| 29 | pub const ESPIPE = 29; // Illegal seek | |
| 30 | pub const EROFS = 30; // Read-only file system | |
| 31 | pub const EMLINK = 31; // Too many links | |
| 32 | pub const EPIPE = 32; // Broken pipe | |
| 33 | pub const EDOM = 33; // Math argument out of domain of func | |
| 34 | pub const ERANGE = 34; // Math result not representable | |
| 35 | pub const EDEADLK = 35; // Resource deadlock would occur | |
| 36 | pub const ENAMETOOLONG = 36; // File name too long | |
| 37 | pub const ENOLCK = 37; // No record locks available | |
| 38 | pub const ENOSYS = 38; // Function not implemented | |
| 39 | pub const ENOTEMPTY = 39; // Directory not empty | |
| 40 | pub const ELOOP = 40; // Too many symbolic links encountered | |
| 41 | pub const EWOULDBLOCK = EAGAIN; // Operation would block | |
| 42 | pub const ENOMSG = 42; // No message of desired type | |
| 43 | pub const EIDRM = 43; // Identifier removed | |
| 44 | pub const ECHRNG = 44; // Channel number out of range | |
| 45 | pub const EL2NSYNC = 45; // Level 2 not synchronized | |
| 46 | pub const EL3HLT = 46; // Level 3 halted | |
| 47 | pub const EL3RST = 47; // Level 3 reset | |
| 48 | pub const ELNRNG = 48; // Link number out of range | |
| 49 | pub const EUNATCH = 49; // Protocol driver not attached | |
| 50 | pub const ENOCSI = 50; // No CSI structure available | |
| 51 | pub const EL2HLT = 51; // Level 2 halted | |
| 52 | pub const EBADE = 52; // Invalid exchange | |
| 53 | pub const EBADR = 53; // Invalid request descriptor | |
| 54 | pub const EXFULL = 54; // Exchange full | |
| 55 | pub const ENOANO = 55; // No anode | |
| 56 | pub const EBADRQC = 56; // Invalid request code | |
| 57 | pub const EBADSLT = 57; // Invalid slot | |
| 58 | ||
| 59 | pub const EBFONT = 59; // Bad font file format | |
| 60 | pub const ENOSTR = 60; // Device not a stream | |
| 61 | pub const ENODATA = 61; // No data available | |
| 62 | pub const ETIME = 62; // Timer expired | |
| 63 | pub const ENOSR = 63; // Out of streams resources | |
| 64 | pub const ENONET = 64; // Machine is not on the network | |
| 65 | pub const ENOPKG = 65; // Package not installed | |
| 66 | pub const EREMOTE = 66; // Object is remote | |
| 67 | pub const ENOLINK = 67; // Link has been severed | |
| 68 | pub const EADV = 68; // Advertise error | |
| 69 | pub const ESRMNT = 69; // Srmount error | |
| 70 | pub const ECOMM = 70; // Communication error on send | |
| 71 | pub const EPROTO = 71; // Protocol error | |
| 72 | pub const EMULTIHOP = 72; // Multihop attempted | |
| 73 | pub const EDOTDOT = 73; // RFS specific error | |
| 74 | pub const EBADMSG = 74; // Not a data message | |
| 75 | pub const EOVERFLOW = 75; // Value too large for defined data type | |
| 76 | pub const ENOTUNIQ = 76; // Name not unique on network | |
| 77 | pub const EBADFD = 77; // File descriptor in bad state | |
| 78 | pub const EREMCHG = 78; // Remote address changed | |
| 79 | pub const ELIBACC = 79; // Can not access a needed shared library | |
| 80 | pub const ELIBBAD = 80; // Accessing a corrupted shared library | |
| 81 | pub const ELIBSCN = 81; // .lib section in a.out corrupted | |
| 82 | pub const ELIBMAX = 82; // Attempting to link in too many shared libraries | |
| 83 | pub const ELIBEXEC = 83; // Cannot exec a shared library directly | |
| 84 | pub const EILSEQ = 84; // Illegal byte sequence | |
| 85 | pub const ERESTART = 85; // Interrupted system call should be restarted | |
| 86 | pub const ESTRPIPE = 86; // Streams pipe error | |
| 87 | pub const EUSERS = 87; // Too many users | |
| 88 | pub const ENOTSOCK = 88; // Socket operation on non-socket | |
| 89 | pub const EDESTADDRREQ = 89; // Destination address required | |
| 90 | pub const EMSGSIZE = 90; // Message too long | |
| 91 | pub const EPROTOTYPE = 91; // Protocol wrong type for socket | |
| 92 | pub const ENOPROTOOPT = 92; // Protocol not available | |
| 93 | pub const EPROTONOSUPPORT = 93; // Protocol not supported | |
| 94 | pub const ESOCKTNOSUPPORT = 94; // Socket type not supported | |
| 95 | pub const EOPNOTSUPP = 95; // Operation not supported on transport endpoint | |
| 96 | pub const EPFNOSUPPORT = 96; // Protocol family not supported | |
| 97 | pub const EAFNOSUPPORT = 97; // Address family not supported by protocol | |
| 98 | pub const EADDRINUSE = 98; // Address already in use | |
| 99 | pub const EADDRNOTAVAIL = 99; // Cannot assign requested address | |
| 100 | pub const ENETDOWN = 100; // Network is down | |
| 101 | pub const ENETUNREACH = 101; // Network is unreachable | |
| 102 | pub const ENETRESET = 102; // Network dropped connection because of reset | |
| 103 | pub const ECONNABORTED = 103; // Software caused connection abort | |
| 104 | pub const ECONNRESET = 104; // Connection reset by peer | |
| 105 | pub const ENOBUFS = 105; // No buffer space available | |
| 106 | pub const EISCONN = 106; // Transport endpoint is already connected | |
| 107 | pub const ENOTCONN = 107; // Transport endpoint is not connected | |
| 108 | pub const ESHUTDOWN = 108; // Cannot send after transport endpoint shutdown | |
| 109 | pub const ETOOMANYREFS = 109; // Too many references: cannot splice | |
| 110 | pub const ETIMEDOUT = 110; // Connection timed out | |
| 111 | pub const ECONNREFUSED = 111; // Connection refused | |
| 112 | pub const EHOSTDOWN = 112; // Host is down | |
| 113 | pub const EHOSTUNREACH = 113; // No route to host | |
| 114 | pub const EALREADY = 114; // Operation already in progress | |
| 115 | pub const EINPROGRESS = 115; // Operation now in progress | |
| 116 | pub const ESTALE = 116; // Stale NFS file handle | |
| 117 | pub const EUCLEAN = 117; // Structure needs cleaning | |
| 118 | pub const ENOTNAM = 118; // Not a XENIX named type file | |
| 119 | pub const ENAVAIL = 119; // No XENIX semaphores available | |
| 120 | pub const EISNAM = 120; // Is a named type file | |
| 121 | pub const EREMOTEIO = 121; // Remote I/O error | |
| 122 | pub const EDQUOT = 122; // Quota exceeded | |
| 123 | ||
| 124 | pub const ENOMEDIUM = 123; // No medium found | |
| 125 | pub const EMEDIUMTYPE = 124; // Wrong medium type | |
| 126 | ||
| 127 | // nameserver query return codes | |
| 128 | pub const ENSROK = 0; // DNS server returned answer with no data | |
| 129 | pub const ENSRNODATA = 160; // DNS server returned answer with no data | |
| 130 | pub const ENSRFORMERR = 161; // DNS server claims query was misformatted | |
| 131 | pub const ENSRSERVFAIL = 162; // DNS server returned general failure | |
| 132 | pub const ENSRNOTFOUND = 163; // Domain name not found | |
| 133 | pub const ENSRNOTIMP = 164; // DNS server does not implement requested operation | |
| 134 | pub const ENSRREFUSED = 165; // DNS server refused query | |
| 135 | pub const ENSRBADQUERY = 166; // Misformatted DNS query | |
| 136 | pub const ENSRBADNAME = 167; // Misformatted domain name | |
| 137 | pub const ENSRBADFAMILY = 168; // Unsupported address family | |
| 138 | pub const ENSRBADRESP = 169; // Misformatted DNS reply | |
| 139 | pub const ENSRCONNREFUSED = 170; // Could not contact DNS servers | |
| 140 | pub const ENSRTIMEOUT = 171; // Timeout while contacting DNS servers | |
| 141 | pub const ENSROF = 172; // End of file | |
| 142 | pub const ENSRFILE = 173; // Error reading file | |
| 143 | pub const ENSRNOMEM = 174; // Out of memory | |
| 144 | pub const ENSRDESTRUCTION = 175; // Application terminated lookup | |
| 145 | pub const ENSRQUERYDOMAINTOOLONG = 176; // Domain name is too long | |
| 146 | pub const ENSRCNAMELOOP = 177; // Domain name is too long |
std/rand.zig created+101| ... | ... | @@ -0,0 +1,101 @@ |
| 1 | // Mersenne Twister | |
| 2 | const ARRAY_SIZE : u16 = 624; | |
| 3 | ||
| 4 | /// Use `rand_init` to initialize this state. | |
| 5 | pub struct Rand { | |
| 6 | // TODO use ARRAY_SIZE here | |
| 7 | array: [624]u32, | |
| 8 | // TODO use #typeof(ARRAY_SIZE) here | |
| 9 | index: u16, | |
| 10 | ||
| 11 | /// Initialize random state with the given seed. | |
| 12 | pub fn init(r: &Rand, seed: u32) { | |
| 13 | r.index = 0; | |
| 14 | r.array[0] = seed; | |
| 15 | var i : #typeof(ARRAY_SIZE) = 1; | |
| 16 | while (i < ARRAY_SIZE) { | |
| 17 | const prev_value : u64 = r.array[i - 1]; | |
| 18 | r.array[i] = ((prev_value ^ (prev_value << 30)) * 0x6c078965 + i) as u32; | |
| 19 | i += 1; | |
| 20 | } | |
| 21 | } | |
| 22 | ||
| 23 | ||
| 24 | /// Get 32 bits of randomness. | |
| 25 | pub fn get_u32(r: &Rand) -> u32 { | |
| 26 | if (r.index == 0) { | |
| 27 | r.generate_numbers(); | |
| 28 | } | |
| 29 | ||
| 30 | // temper the number | |
| 31 | var y : u32 = r.array[r.index]; | |
| 32 | y ^= y >> 11; | |
| 33 | y ^= (y >> 7) & 0x9d2c5680; | |
| 34 | y ^= (y >> 15) & 0xefc60000; | |
| 35 | y ^= y >> 18; | |
| 36 | ||
| 37 | r.index = (r.index + 1) % ARRAY_SIZE; | |
| 38 | return y; | |
| 39 | } | |
| 40 | ||
| 41 | /// Fill `buf` with randomness. | |
| 42 | pub fn get_bytes(r: &Rand, buf: []u8) { | |
| 43 | var bytes_left = r.get_bytes_aligned(buf); | |
| 44 | if (bytes_left > 0) { | |
| 45 | var rand_val_array : [#sizeof(u32)]u8; | |
| 46 | *(rand_val_array.ptr as &u32) = r.get_u32(); | |
| 47 | while (bytes_left > 0) { | |
| 48 | // TODO array index operator so we can remove the .ptr | |
| 49 | buf.ptr[buf.len - bytes_left] = rand_val_array[#sizeof(u32) - bytes_left]; | |
| 50 | bytes_left -= 1; | |
| 51 | } | |
| 52 | } | |
| 53 | } | |
| 54 | ||
| 55 | /// Get a random unsigned integer with even distribution between `start` | |
| 56 | /// inclusive and `end` exclusive. | |
| 57 | pub fn range_u64(r: &Rand, start: u64, end: u64) -> u64 { | |
| 58 | const range = end - start; | |
| 59 | const leftover = #max_value(u64) % range; | |
| 60 | const upper_bound = #max_value(u64) - leftover; | |
| 61 | var rand_val_array : [#sizeof(u64)]u8; | |
| 62 | ||
| 63 | while (true) { | |
| 64 | r.get_bytes_aligned(rand_val_array); | |
| 65 | const rand_val = *(rand_val_array.ptr as &u64); | |
| 66 | if (rand_val < upper_bound) { | |
| 67 | return start + (rand_val % range); | |
| 68 | } | |
| 69 | } | |
| 70 | // TODO detect simple constant in while loop and no breaks and turn it into unreachable | |
| 71 | // type. then we can remove this unreachable. | |
| 72 | unreachable; | |
| 73 | } | |
| 74 | ||
| 75 | fn generate_numbers(r: &Rand) { | |
| 76 | var i : #typeof(ARRAY_SIZE) = 0; | |
| 77 | while (i < ARRAY_SIZE) { | |
| 78 | const y : u32 = (r.array[i] & 0x80000000) + (r.array[(i + 1) % ARRAY_SIZE] & 0x7fffffff); | |
| 79 | const untempered : u32 = r.array[(i + 397) % ARRAY_SIZE] ^ (y >> 1); | |
| 80 | r.array[i] = if ((y % 2) == 0) { | |
| 81 | untempered | |
| 82 | } else { | |
| 83 | // y is odd | |
| 84 | untempered ^ 0x9908b0df | |
| 85 | }; | |
| 86 | i += 1; | |
| 87 | } | |
| 88 | } | |
| 89 | ||
| 90 | // does not populate the remaining (buf.len % 4) bytes | |
| 91 | fn get_bytes_aligned(r: &Rand, buf: []u8) -> usize { | |
| 92 | var bytes_left = buf.len; | |
| 93 | while (bytes_left >= 4) { | |
| 94 | // TODO: array access so we can remove .ptr | |
| 95 | *(&buf.ptr[buf.len - bytes_left] as &u32) = r.get_u32(); | |
| 96 | bytes_left -= #sizeof(u32); | |
| 97 | } | |
| 98 | return bytes_left; | |
| 99 | } | |
| 100 | } | |
| 101 |