Skip to content

Commit

Permalink
replace %defer with errdefer
Browse files Browse the repository at this point in the history
See #632

now we have 1 less sigil
  • Loading branch information
andrewrk committed Jan 24, 2018
1 parent ad2527d commit b3a6faf
Show file tree
Hide file tree
Showing 21 changed files with 87 additions and 89 deletions.
4 changes: 2 additions & 2 deletions doc/docgen.zig
Expand Up @@ -318,7 +318,7 @@ const Action = enum {

fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc {
var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator);
%defer urls.deinit();
errdefer urls.deinit();

var header_stack_size: usize = 0;
var last_action = Action.Open;
Expand Down Expand Up @@ -399,7 +399,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc {
}
} else if (mem.eql(u8, tag_name, "see_also")) {
var list = std.ArrayList(SeeAlsoItem).init(allocator);
%defer list.deinit();
errdefer list.deinit();

while (true) {
const see_also_tok = tokenizer.next();
Expand Down
14 changes: 7 additions & 7 deletions doc/langref.html.in
Expand Up @@ -2533,7 +2533,7 @@ test "defer unwinding" {
deferUnwindExample();
}

// The %defer keyword is similar to defer, but will only execute if the
// The errdefer keyword is similar to defer, but will only execute if the
// scope returns with an error.
//
// This is especially useful in allowing a function to clean up properly
Expand All @@ -2547,7 +2547,7 @@ fn deferErrorExample(is_error: bool) -> %void {
warn("end of function\n");
}

%defer {
errdefer {
warn("encountered an error!\n");
}

Expand All @@ -2556,7 +2556,7 @@ fn deferErrorExample(is_error: bool) -> %void {
}
}

test "%defer unwinding" {
test "errdefer unwinding" {
_ = deferErrorExample(false);
_ = deferErrorExample(true);
}
Expand Down Expand Up @@ -2922,7 +2922,7 @@ fn doAThing(str: []u8) {
{#code_end#}
<p>
The other component to error handling is defer statements.
In addition to an unconditional <code>defer</code>, Zig has <code>%defer</code>,
In addition to an unconditional <code>defer</code>, Zig has <code>errdefer</code>,
which evaluates the deferred expression on block exit path if and only if
the function returned with an error from the block.
</p>
Expand All @@ -2934,7 +2934,7 @@ fn createFoo(param: i32) -> %Foo {
const foo = try tryToAllocateFoo();
// now we have allocated foo. we need to free it if the function fails.
// but we want to return it if the function succeeds.
%defer deallocateFoo(foo);
errdefer deallocateFoo(foo);

const tmp_buf = allocateTmpBuffer() ?? return error.OutOfMemory;
// tmp_buf is truly a temporary resource, and we for sure want to clean it up
Expand All @@ -2943,7 +2943,7 @@ fn createFoo(param: i32) -> %Foo {

if (param > 1337) return error.InvalidParam;

// here the %defer will not run since we're returning success from the function.
// here the errdefer will not run since we're returning success from the function.
// but the defer will run!
return foo;
}
Expand Down Expand Up @@ -5619,7 +5619,7 @@ TryExpression = "try" Expression

BreakExpression = "break" option(":" Symbol) option(Expression)

Defer(body) = option("%") "defer" body
Defer(body) = ("defer" | "deferror") body

IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))

Expand Down
4 changes: 2 additions & 2 deletions src-self-hosted/main.zig
Expand Up @@ -371,7 +371,7 @@ pub fn main2() -> %void {
defer allocator.free(full_cache_dir);

const zig_lib_dir = try resolveZigLibDir(allocator, zig_install_prefix);
%defer allocator.free(zig_lib_dir);
errdefer allocator.free(zig_lib_dir);

const module = try Module.create(allocator, root_name, zig_root_source_file,
Target.Native, build_kind, build_mode, zig_lib_dir, full_cache_dir);
Expand Down Expand Up @@ -587,7 +587,7 @@ fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const
/// Caller must free result
fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) -> %[]u8 {
const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig");
%defer allocator.free(test_zig_dir);
errdefer allocator.free(test_zig_dir);

const test_index_file = try os.path.join(allocator, test_zig_dir, "std", "index.zig");
defer allocator.free(test_index_file);
Expand Down
14 changes: 7 additions & 7 deletions src-self-hosted/module.zig
Expand Up @@ -113,19 +113,19 @@ pub const Module = struct {
kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) -> %&Module
{
var name_buffer = try Buffer.init(allocator, name);
%defer name_buffer.deinit();
errdefer name_buffer.deinit();

const context = c.LLVMContextCreate() ?? return error.OutOfMemory;
%defer c.LLVMContextDispose(context);
errdefer c.LLVMContextDispose(context);

const module = c.LLVMModuleCreateWithNameInContext(name_buffer.ptr(), context) ?? return error.OutOfMemory;
%defer c.LLVMDisposeModule(module);
errdefer c.LLVMDisposeModule(module);

const builder = c.LLVMCreateBuilderInContext(context) ?? return error.OutOfMemory;
%defer c.LLVMDisposeBuilder(builder);
errdefer c.LLVMDisposeBuilder(builder);

const module_ptr = try allocator.create(Module);
%defer allocator.destroy(module_ptr);
errdefer allocator.destroy(module_ptr);

*module_ptr = Module {
.allocator = allocator,
Expand Down Expand Up @@ -211,13 +211,13 @@ pub const Module = struct {
try printError("unable to get real path '{}': {}", root_src_path, err);
return err;
};
%defer self.allocator.free(root_src_real_path);
errdefer self.allocator.free(root_src_real_path);

const source_code = io.readFileAllocExtra(root_src_real_path, self.allocator, 3) catch |err| {
try printError("unable to open '{}': {}", root_src_real_path, err);
return err;
};
%defer self.allocator.free(source_code);
errdefer self.allocator.free(source_code);
source_code[source_code.len - 3] = '\n';
source_code[source_code.len - 2] = '\n';
source_code[source_code.len - 1] = '\n';
Expand Down
30 changes: 15 additions & 15 deletions src-self-hosted/parser.zig
Expand Up @@ -127,7 +127,7 @@ pub const Parser = struct {

const root_node = x: {
const root_node = try self.createRoot();
%defer self.allocator.destroy(root_node);
errdefer self.allocator.destroy(root_node);
// This stack append has to succeed for freeAst to work
try stack.append(State.TopLevel);
break :x root_node;
Expand Down Expand Up @@ -577,7 +577,7 @@ pub const Parser = struct {

fn createRoot(self: &Parser) -> %&ast.NodeRoot {
const node = try self.allocator.create(ast.NodeRoot);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);

*node = ast.NodeRoot {
.base = ast.Node {.id = ast.Node.Id.Root},
Expand All @@ -590,7 +590,7 @@ pub const Parser = struct {
extern_token: &const ?Token) -> %&ast.NodeVarDecl
{
const node = try self.allocator.create(ast.NodeVarDecl);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);

*node = ast.NodeVarDecl {
.base = ast.Node {.id = ast.Node.Id.VarDecl},
Expand All @@ -613,7 +613,7 @@ pub const Parser = struct {
cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) -> %&ast.NodeFnProto
{
const node = try self.allocator.create(ast.NodeFnProto);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);

*node = ast.NodeFnProto {
.base = ast.Node {.id = ast.Node.Id.FnProto},
Expand All @@ -635,7 +635,7 @@ pub const Parser = struct {

fn createParamDecl(self: &Parser) -> %&ast.NodeParamDecl {
const node = try self.allocator.create(ast.NodeParamDecl);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);

*node = ast.NodeParamDecl {
.base = ast.Node {.id = ast.Node.Id.ParamDecl},
Expand All @@ -650,7 +650,7 @@ pub const Parser = struct {

fn createBlock(self: &Parser, begin_token: &const Token) -> %&ast.NodeBlock {
const node = try self.allocator.create(ast.NodeBlock);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);

*node = ast.NodeBlock {
.base = ast.Node {.id = ast.Node.Id.Block},
Expand All @@ -663,7 +663,7 @@ pub const Parser = struct {

fn createInfixOp(self: &Parser, op_token: &const Token, op: &const ast.NodeInfixOp.InfixOp) -> %&ast.NodeInfixOp {
const node = try self.allocator.create(ast.NodeInfixOp);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);

*node = ast.NodeInfixOp {
.base = ast.Node {.id = ast.Node.Id.InfixOp},
Expand All @@ -677,7 +677,7 @@ pub const Parser = struct {

fn createPrefixOp(self: &Parser, op_token: &const Token, op: &const ast.NodePrefixOp.PrefixOp) -> %&ast.NodePrefixOp {
const node = try self.allocator.create(ast.NodePrefixOp);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);

*node = ast.NodePrefixOp {
.base = ast.Node {.id = ast.Node.Id.PrefixOp},
Expand All @@ -690,7 +690,7 @@ pub const Parser = struct {

fn createIdentifier(self: &Parser, name_token: &const Token) -> %&ast.NodeIdentifier {
const node = try self.allocator.create(ast.NodeIdentifier);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);

*node = ast.NodeIdentifier {
.base = ast.Node {.id = ast.Node.Id.Identifier},
Expand All @@ -701,7 +701,7 @@ pub const Parser = struct {

fn createIntegerLiteral(self: &Parser, token: &const Token) -> %&ast.NodeIntegerLiteral {
const node = try self.allocator.create(ast.NodeIntegerLiteral);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);

*node = ast.NodeIntegerLiteral {
.base = ast.Node {.id = ast.Node.Id.IntegerLiteral},
Expand All @@ -712,7 +712,7 @@ pub const Parser = struct {

fn createFloatLiteral(self: &Parser, token: &const Token) -> %&ast.NodeFloatLiteral {
const node = try self.allocator.create(ast.NodeFloatLiteral);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);

*node = ast.NodeFloatLiteral {
.base = ast.Node {.id = ast.Node.Id.FloatLiteral},
Expand All @@ -723,14 +723,14 @@ pub const Parser = struct {

fn createAttachIdentifier(self: &Parser, dest_ptr: &const DestPtr, name_token: &const Token) -> %&ast.NodeIdentifier {
const node = try self.createIdentifier(name_token);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);
try dest_ptr.store(&node.base);
return node;
}

fn createAttachParamDecl(self: &Parser, list: &ArrayList(&ast.Node)) -> %&ast.NodeParamDecl {
const node = try self.createParamDecl();
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);
try list.append(&node.base);
return node;
}
Expand All @@ -740,7 +740,7 @@ pub const Parser = struct {
inline_token: &const ?Token) -> %&ast.NodeFnProto
{
const node = try self.createFnProto(fn_token, extern_token, cc_token, visib_token, inline_token);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);
try list.append(&node.base);
return node;
}
Expand All @@ -749,7 +749,7 @@ pub const Parser = struct {
mut_token: &const Token, comptime_token: &const ?Token, extern_token: &const ?Token) -> %&ast.NodeVarDecl
{
const node = try self.createVarDecl(visib_token, mut_token, comptime_token, extern_token);
%defer self.allocator.destroy(node);
errdefer self.allocator.destroy(node);
try list.append(&node.base);
return node;
}
Expand Down
15 changes: 5 additions & 10 deletions src/parser.cpp
Expand Up @@ -1495,23 +1495,18 @@ static AstNode *ast_parse_break_expr(ParseContext *pc, size_t *token_index) {
}

/*
Defer(body) = option("%") "defer" body
Defer(body) = ("defer" | "errdefer") body
*/
static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) {
Token *token = &pc->tokens->at(*token_index);

NodeType node_type;
ReturnKind kind;

if (token->id == TokenIdPercent) {
Token *next_token = &pc->tokens->at(*token_index + 1);
if (next_token->id == TokenIdKeywordDefer) {
kind = ReturnKindError;
node_type = NodeTypeDefer;
*token_index += 2;
} else {
return nullptr;
}
if (token->id == TokenIdKeywordErrdefer) {
kind = ReturnKindError;
node_type = NodeTypeDefer;
*token_index += 1;
} else if (token->id == TokenIdKeywordDefer) {
kind = ReturnKindUnconditional;
node_type = NodeTypeDefer;
Expand Down
2 changes: 2 additions & 0 deletions src/tokenizer.cpp
Expand Up @@ -118,6 +118,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"defer", TokenIdKeywordDefer},
{"else", TokenIdKeywordElse},
{"enum", TokenIdKeywordEnum},
{"errdefer", TokenIdKeywordErrdefer},
{"error", TokenIdKeywordError},
{"export", TokenIdKeywordExport},
{"extern", TokenIdKeywordExtern},
Expand Down Expand Up @@ -1514,6 +1515,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordDefer: return "defer";
case TokenIdKeywordElse: return "else";
case TokenIdKeywordEnum: return "enum";
case TokenIdKeywordErrdefer: return "errdefer";
case TokenIdKeywordError: return "error";
case TokenIdKeywordExport: return "export";
case TokenIdKeywordExtern: return "extern";
Expand Down
1 change: 1 addition & 0 deletions src/tokenizer.hpp
Expand Up @@ -57,6 +57,7 @@ enum TokenId {
TokenIdKeywordDefer,
TokenIdKeywordElse,
TokenIdKeywordEnum,
TokenIdKeywordErrdefer,
TokenIdKeywordError,
TokenIdKeywordExport,
TokenIdKeywordExtern,
Expand Down
6 changes: 3 additions & 3 deletions std/buf_map.zig
Expand Up @@ -30,14 +30,14 @@ pub const BufMap = struct {
pub fn set(self: &BufMap, key: []const u8, value: []const u8) -> %void {
if (self.hash_map.get(key)) |entry| {
const value_copy = try self.copy(value);
%defer self.free(value_copy);
errdefer self.free(value_copy);
_ = try self.hash_map.put(key, value_copy);
self.free(entry.value);
} else {
const key_copy = try self.copy(key);
%defer self.free(key_copy);
errdefer self.free(key_copy);
const value_copy = try self.copy(value);
%defer self.free(value_copy);
errdefer self.free(value_copy);
_ = try self.hash_map.put(key_copy, value_copy);
}
}
Expand Down
2 changes: 1 addition & 1 deletion std/buf_set.zig
Expand Up @@ -27,7 +27,7 @@ pub const BufSet = struct {
pub fn put(self: &BufSet, key: []const u8) -> %void {
if (self.hash_map.get(key) == null) {
const key_copy = try self.copy(key);
%defer self.free(key_copy);
errdefer self.free(key_copy);
_ = try self.hash_map.put(key_copy, {});
}
}
Expand Down
2 changes: 1 addition & 1 deletion std/cstr.zig
Expand Up @@ -71,7 +71,7 @@ pub const NullTerminated2DArray = struct {
byte_count += index_size;

const buf = try allocator.alignedAlloc(u8, @alignOf(?&u8), byte_count);
%defer allocator.free(buf);
errdefer allocator.free(buf);

var write_index = index_size;
const index_buf = ([]?&u8)(buf);
Expand Down
8 changes: 4 additions & 4 deletions std/debug/index.zig
Expand Up @@ -248,10 +248,10 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) -> %&ElfStackTrace {
.compile_unit_list = ArrayList(CompileUnit).init(allocator),
};
st.self_exe_file = try os.openSelfExe();
%defer st.self_exe_file.close();
errdefer st.self_exe_file.close();

try st.elf.openFile(allocator, &st.self_exe_file);
%defer st.elf.close();
errdefer st.elf.close();

st.debug_info = (try st.elf.findSection(".debug_info")) ?? return error.MissingDebugInfo;
st.debug_abbrev = (try st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo;
Expand Down Expand Up @@ -524,7 +524,7 @@ const LineNumberProgram = struct {
return error.InvalidDebugInfo;
} else self.include_dirs[file_entry.dir_index];
const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name);
%defer self.file_entries.allocator.free(file_name);
errdefer self.file_entries.allocator.free(file_name);
return LineInfo {
.line = if (self.prev_line >= 0) usize(self.prev_line) else 0,
.column = self.prev_column,
Expand Down Expand Up @@ -563,7 +563,7 @@ fn getString(st: &ElfStackTrace, offset: u64) -> %[]u8 {

fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %[]u8 {
const buf = try global_allocator.alloc(u8, size);
%defer global_allocator.free(buf);
errdefer global_allocator.free(buf);
if ((try in_stream.read(buf)) < size) return error.EndOfFile;
return buf;
}
Expand Down

0 comments on commit b3a6faf

Please sign in to comment.