authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-03 11:51:29-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-03 11:51:29-05:00
logabf5ae6897bb23e49e4232ab8be7ed61ea9520b6
treea0ff1d117e79a63827995c65d22a3fc4e46a37e1
parentb8f59e14cdbf90cf724ed9e721c1909293f41b3b

*WIP* error sets - support fns called at comptime


8 files changed, 55 insertions(+), 20 deletions(-)

TODO+4
...@@ -25,3 +25,7 @@ comptime test for err...@@ -25,3 +25,7 @@ comptime test for err
2525
2626
27undefined in infer error 27undefined in infer error
28
29change readlink back to inferred error
30
31syntax - ?a!b should be ?(a!b) but it's (?a)!b
src/ir.cpp+29-2
...@@ -10123,6 +10123,13 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,...@@ -10123,6 +10123,13 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,
10123 if (type_is_invalid(payload_type))10123 if (type_is_invalid(payload_type))
10124 return ira->codegen->builtin_types.entry_invalid;10124 return ira->codegen->builtin_types.entry_invalid;
1012510125
10126 if (err_set_type->id != TypeTableEntryIdErrorSet) {
10127 ir_add_error(ira, instruction->err_set->other,
10128 buf_sprintf("expected error set type, found type '%s'",
10129 buf_ptr(&err_set_type->name)));
10130 return ira->codegen->builtin_types.entry_invalid;
10131 }
10132
10126 TypeTableEntry *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type);10133 TypeTableEntry *result_type = get_error_union_type(ira->codegen, err_set_type, payload_type);
1012710134
10128 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);10135 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
...@@ -10412,9 +10419,17 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -10412,9 +10419,17 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
10412 }10419 }
1041310420
10414 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;10421 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
10415 TypeTableEntry *return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node);10422 TypeTableEntry *specified_return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node);
10416 if (type_is_invalid(return_type))10423 if (type_is_invalid(specified_return_type))
10417 return ira->codegen->builtin_types.entry_invalid;10424 return ira->codegen->builtin_types.entry_invalid;
10425 TypeTableEntry *return_type;
10426 TypeTableEntry *inferred_err_set_type = nullptr;
10427 if (fn_proto_node->data.fn_proto.auto_err_set) {
10428 inferred_err_set_type = get_auto_err_set_type(ira->codegen, fn_entry);
10429 return_type = get_error_union_type(ira->codegen, inferred_err_set_type, specified_return_type);
10430 } else {
10431 return_type = specified_return_type;
10432 }
1041810433
10419 IrInstruction *result;10434 IrInstruction *result;
1042010435
...@@ -10428,6 +10443,18 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -10428,6 +10443,18 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
10428 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,10443 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
10429 nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec);10444 nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec);
1043010445
10446 if (inferred_err_set_type != nullptr) {
10447 inferred_err_set_type->data.error_set.infer_fn = nullptr;
10448 if (result->value.type->id == TypeTableEntryIdErrorUnion) {
10449 TypeTableEntry *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type;
10450 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;
10451 inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors;
10452 } else if (result->value.type->id == TypeTableEntryIdErrorSet) {
10453 inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count;
10454 inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors;
10455 }
10456 }
10457
10431 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);10458 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
1043210459
10433 if (type_is_invalid(result->value.type))10460 if (type_is_invalid(result->value.type))
src/parser.cpp+1-1
...@@ -2589,7 +2589,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,...@@ -2589,7 +2589,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
2589 Token *colon_token = &pc->tokens->at(*token_index);2589 Token *colon_token = &pc->tokens->at(*token_index);
2590 if (colon_token->id == TokenIdColon) {2590 if (colon_token->id == TokenIdColon) {
2591 *token_index += 1;2591 *token_index += 1;
2592 field_node->data.struct_field.type = ast_parse_prefix_op_expr(pc, token_index, true);2592 field_node->data.struct_field.type = ast_parse_type_expr(pc, token_index, true);
2593 }2593 }
2594 Token *eq_token = &pc->tokens->at(*token_index);2594 Token *eq_token = &pc->tokens->at(*token_index);
2595 if (eq_token->id == TokenIdEq) {2595 if (eq_token->id == TokenIdEq) {
std/base64.zig+3-3
...@@ -181,7 +181,7 @@ pub const Base64DecoderWithIgnore = struct {...@@ -181,7 +181,7 @@ pub const Base64DecoderWithIgnore = struct {
181 }181 }
182182
183 /// If no characters end up being ignored or padding, this will be the exact decoded size.183 /// If no characters end up being ignored or padding, this will be the exact decoded size.
184 pub fn calcSizeUpperBound(encoded_len: usize) !usize {184 pub fn calcSizeUpperBound(encoded_len: usize) usize {
185 return @divTrunc(encoded_len, 4) * 3;185 return @divTrunc(encoded_len, 4) * 3;
186 }186 }
187187
...@@ -430,7 +430,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void...@@ -430,7 +430,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
430 const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init(430 const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init(
431 standard_alphabet_chars, standard_pad_char, "");431 standard_alphabet_chars, standard_pad_char, "");
432 var buffer: [0x100]u8 = undefined;432 var buffer: [0x100]u8 = undefined;
433 var decoded = buffer[0..try Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)];433 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)];
434 var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded);434 var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded);
435 assert(written <= decoded.len);435 assert(written <= decoded.len);
436 assert(mem.eql(u8, decoded[0..written], expected_decoded));436 assert(mem.eql(u8, decoded[0..written], expected_decoded));
...@@ -449,7 +449,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi...@@ -449,7 +449,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi
449 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(449 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(
450 standard_alphabet_chars, standard_pad_char, " ");450 standard_alphabet_chars, standard_pad_char, " ");
451 var buffer: [0x100]u8 = undefined;451 var buffer: [0x100]u8 = undefined;
452 var decoded = buffer[0..try Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)];452 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)];
453 var written = try standard_decoder_ignore_space.decode(decoded, encoded);453 var written = try standard_decoder_ignore_space.decode(decoded, encoded);
454 assert(mem.eql(u8, decoded[0..written], expected_decoded));454 assert(mem.eql(u8, decoded[0..written], expected_decoded));
455}455}
std/build.zig+5-5
...@@ -554,7 +554,7 @@ pub const Builder = struct {...@@ -554,7 +554,7 @@ pub const Builder = struct {
554 }554 }
555555
556 fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,556 fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
557 argv: []const []const u8) %void557 argv: []const []const u8) !void
558 {558 {
559 if (self.verbose) {559 if (self.verbose) {
560 printCmd(cwd, argv);560 printCmd(cwd, argv);
...@@ -1942,12 +1942,12 @@ pub const RemoveDirStep = struct {...@@ -1942,12 +1942,12 @@ pub const RemoveDirStep = struct {
19421942
1943pub const Step = struct {1943pub const Step = struct {
1944 name: []const u8,1944 name: []const u8,
1945 makeFn: fn(self: &Step) %void,1945 makeFn: fn(self: &Step) error!void,
1946 dependencies: ArrayList(&Step),1946 dependencies: ArrayList(&Step),
1947 loop_flag: bool,1947 loop_flag: bool,
1948 done_flag: bool,1948 done_flag: bool,
19491949
1950 pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)%void) Step {1950 pub fn init(name: []const u8, allocator: &Allocator, makeFn: fn (&Step)error!void) Step {
1951 return Step {1951 return Step {
1952 .name = name,1952 .name = name,
1953 .makeFn = makeFn,1953 .makeFn = makeFn,
...@@ -1972,11 +1972,11 @@ pub const Step = struct {...@@ -1972,11 +1972,11 @@ pub const Step = struct {
1972 self.dependencies.append(other) catch unreachable;1972 self.dependencies.append(other) catch unreachable;
1973 }1973 }
19741974
1975 fn makeNoOp(self: &Step) %void {}1975 fn makeNoOp(self: &Step) (error{}!void) {}
1976};1976};
19771977
1978fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8,1978fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8,
1979 filename_name_only: []const u8) %void1979 filename_name_only: []const u8) !void
1980{1980{
1981 const out_dir = os.path.dirname(output_path);1981 const out_dir = os.path.dirname(output_path);
1982 const out_basename = os.path.basename(output_path);1982 const out_basename = os.path.basename(output_path);
std/fmt/index.zig+3-3
...@@ -198,7 +198,7 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@...@@ -198,7 +198,7 @@ pub fn formatValue(value: var, context: var, comptime Errors: type, output: fn(@
198 return formatInt(value, 10, false, 0, context, Errors, output);198 return formatInt(value, 10, false, 0, context, Errors, output);
199 },199 },
200 builtin.TypeId.Float => {200 builtin.TypeId.Float => {
201 return formatFloat(value, context, output);201 return formatFloat(value, context, Errors, output);
202 },202 },
203 builtin.TypeId.Void => {203 builtin.TypeId.Void => {
204 return output(context, "void");204 return output(context, "void");
...@@ -417,7 +417,7 @@ const FormatIntBuf = struct {...@@ -417,7 +417,7 @@ const FormatIntBuf = struct {
417 out_buf: []u8,417 out_buf: []u8,
418 index: usize,418 index: usize,
419};419};
420fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) !void {420fn formatIntCallback(context: &FormatIntBuf, bytes: []const u8) (error{}!void) {
421 mem.copy(u8, context.out_buf[context.index..], bytes);421 mem.copy(u8, context.out_buf[context.index..], bytes);
422 context.index += bytes.len;422 context.index += bytes.len;
423}423}
...@@ -499,7 +499,7 @@ fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) !void {...@@ -499,7 +499,7 @@ fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) !void {
499499
500pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 {500pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 {
501 var context = BufPrintContext { .remaining = buf, };501 var context = BufPrintContext { .remaining = buf, };
502 try format(&context, bufPrintWrite, fmt, args);502 try format(&context, error{BufferTooSmall}, bufPrintWrite, fmt, args);
503 return buf[0..buf.len - context.remaining.len];503 return buf[0..buf.len - context.remaining.len];
504}504}
505505
std/os/child_process.zig+8-4
...@@ -28,7 +28,7 @@ pub const ChildProcess = struct {...@@ -28,7 +28,7 @@ pub const ChildProcess = struct {
28 pub stdout: ?io.File,28 pub stdout: ?io.File,
29 pub stderr: ?io.File,29 pub stderr: ?io.File,
3030
31 pub term: ?%Term,31 pub term: ?SpawnError!Term,
3232
33 pub argv: []const []const u8,33 pub argv: []const []const u8,
3434
...@@ -54,6 +54,10 @@ pub const ChildProcess = struct {...@@ -54,6 +54,10 @@ pub const ChildProcess = struct {
54 err_pipe: if (is_windows) void else [2]i32,54 err_pipe: if (is_windows) void else [2]i32,
55 llnode: if (is_windows) void else LinkedList(&ChildProcess).Node,55 llnode: if (is_windows) void else LinkedList(&ChildProcess).Node,
5656
57 pub const SpawnError = error {
58
59 };
60
57 pub const Term = union(enum) {61 pub const Term = union(enum) {
58 Exited: i32,62 Exited: i32,
59 Signal: i32,63 Signal: i32,
...@@ -185,7 +189,7 @@ pub const ChildProcess = struct {...@@ -185,7 +189,7 @@ pub const ChildProcess = struct {
185 /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.189 /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns.
186 /// If it succeeds, the caller owns result.stdout and result.stderr memory.190 /// If it succeeds, the caller owns result.stdout and result.stderr memory.
187 pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8,191 pub fn exec(allocator: &mem.Allocator, argv: []const []const u8, cwd: ?[]const u8,
188 env_map: ?&const BufMap, max_output_size: usize) %ExecResult192 env_map: ?&const BufMap, max_output_size: usize) !ExecResult
189 {193 {
190 const child = try ChildProcess.init(argv, allocator);194 const child = try ChildProcess.init(argv, allocator);
191 defer child.deinit();195 defer child.deinit();
...@@ -246,7 +250,7 @@ pub const ChildProcess = struct {...@@ -246,7 +250,7 @@ pub const ChildProcess = struct {
246 fn waitUnwrappedWindows(self: &ChildProcess) !void {250 fn waitUnwrappedWindows(self: &ChildProcess) !void {
247 const result = os.windowsWaitSingle(self.handle, windows.INFINITE);251 const result = os.windowsWaitSingle(self.handle, windows.INFINITE);
248252
249 self.term = (%Term)(x: {253 self.term = (SpawnError!Term)(x: {
250 var exit_code: windows.DWORD = undefined;254 var exit_code: windows.DWORD = undefined;
251 if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) {255 if (windows.GetExitCodeProcess(self.handle, &exit_code) == 0) {
252 break :x Term { .Unknown = 0 };256 break :x Term { .Unknown = 0 };
...@@ -631,7 +635,7 @@ pub const ChildProcess = struct {...@@ -631,7 +635,7 @@ pub const ChildProcess = struct {
631};635};
632636
633fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8,637fn windowsCreateProcess(app_name: &u8, cmd_line: &u8, envp_ptr: ?&u8, cwd_ptr: ?&u8,
634 lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) %void638 lpStartupInfo: &windows.STARTUPINFOA, lpProcessInformation: &windows.PROCESS_INFORMATION) !void
635{639{
636 if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0,640 if (windows.CreateProcessA(app_name, cmd_line, null, null, windows.TRUE, 0,
637 @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0)641 @ptrCast(?&c_void, envp_ptr), cwd_ptr, lpStartupInfo, lpProcessInformation) == 0)
std/os/index.zig+2-2
...@@ -1072,7 +1072,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) !void {...@@ -1072,7 +1072,7 @@ pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) !void {
1072}1072}
10731073
1074/// Read value of a symbolic link.1074/// Read value of a symbolic link.
1075pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 {1075pub fn readLink(allocator: &Allocator, pathname: []const u8) error![]u8 {
1076 const path_buf = try allocator.alloc(u8, pathname.len + 1);1076 const path_buf = try allocator.alloc(u8, pathname.len + 1);
1077 defer allocator.free(path_buf);1077 defer allocator.free(path_buf);
10781078
...@@ -1267,7 +1267,7 @@ pub const ArgIteratorWindows = struct {...@@ -1267,7 +1267,7 @@ pub const ArgIteratorWindows = struct {
1267 }1267 }
12681268
1269 /// You must free the returned memory when done.1269 /// You must free the returned memory when done.
1270 pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?internalNext.errors![]u8 {1270 pub fn next(self: &ArgIteratorWindows, allocator: &Allocator) ?(@typeOf(internalNext).ReturnType.ErrorSet![]u8) {
1271 // march forward over whitespace1271 // march forward over whitespace
1272 while (true) : (self.index += 1) {1272 while (true) : (self.index += 1) {
1273 const byte = self.cmd_line[self.index];1273 const byte = self.cmd_line[self.index];