Commit 632d143bff

Andrew Kelley <superjoe30@gmail.com>
2018-01-07 23:28:20
replace `a %% b` with `a catch b`
See #632 better fits the convention of using keywords for control flow
1 parent 66717db
doc/docgen.zig
@@ -45,7 +45,7 @@ const State = enum {
 fn gen(in: &io.InStream, out: &io.OutStream) {
     var state = State.Start;
     while (true) {
-        const byte = in.readByte() %% |err| {
+        const byte = in.readByte() catch |err| {
             if (err == error.EndOfStream) {
                 return;
             }
doc/home.html.in
@@ -142,7 +142,7 @@ pub fn addOverflow(comptime T: type, a: T, b: T) -&gt; %T {
 }
 
 fn getNumberWithDefault(s: []u8) -&gt; u32 {
-    parseUnsigned(u32, s, 10) %% 42
+    parseUnsigned(u32, s, 10) catch 42
 }
 
 fn getNumberOrCrash(s: []u8) -&gt; u32 {
@@ -150,8 +150,8 @@ fn getNumberOrCrash(s: []u8) -&gt; u32 {
 }
 
 fn addTwoTogetherOrReturnErr(a_str: []u8, b_str: []u8) -&gt; %u32 {
-    const a = parseUnsigned(u32, a_str, 10) %% |err| return err;
-    const b = parseUnsigned(u32, b_str, 10) %% |err| return err;
+    const a = parseUnsigned(u32, a_str, 10) catch |err| return err;
+    const b = parseUnsigned(u32, b_str, 10) catch |err| return err;
     return a + b;
 }</code></pre>
     <h3 id="hashmap">HashMap with Custom Allocator</h3>
@@ -424,7 +424,7 @@ pub fn main() -&gt; %void {
         } else if (arg[0] == '-') {
             return usage(exe);
         } else {
-            var is = io.InStream.open(arg, null) %% |err| {
+            var is = io.InStream.open(arg, null) catch |err| {
                 %%io.stderr.printf("Unable to open file: {}\n", @errorName(err));
                 return err;
             };
@@ -449,7 +449,7 @@ fn cat_stream(is: &amp;io.InStream) -&gt; %void {
     var buf: [1024 * 4]u8 = undefined;
 
     while (true) {
-        const bytes_read = is.read(buf[0..]) %% |err| {
+        const bytes_read = is.read(buf[0..]) catch |err| {
             %%io.stderr.printf("Unable to read from stream: {}\n", @errorName(err));
             return err;
         };
@@ -458,7 +458,7 @@ fn cat_stream(is: &amp;io.InStream) -&gt; %void {
             break;
         }
 
-        io.stdout.write(buf[0..bytes_read]) %% |err| {
+        io.stdout.write(buf[0..bytes_read]) catch |err| {
             %%io.stderr.printf("Unable to write to stdout: {}\n", @errorName(err));
             return err;
         };
doc/langref.html.in
@@ -1211,8 +1211,8 @@ unwrapped == 1234</code></pre>
           </td>
         </tr>
         <tr>
-          <td><pre><code class="zig">a %% b
-a %% |err| b</code></pre></td>
+          <td><pre><code class="zig">a catch b
+a catch |err| b</code></pre></td>
           <td>
             <ul>
               <li><a href="#errors">Error Unions</a></li>
@@ -1226,7 +1226,7 @@ a %% |err| b</code></pre></td>
           </td>
           <td>
             <pre><code class="zig">const value: %u32 = null;
-const unwrapped = value %% 1234;
+const unwrapped = value catch 1234;
 unwrapped == 1234</code></pre>
           </td>
         </tr>
@@ -1238,7 +1238,7 @@ unwrapped == 1234</code></pre>
             </ul>
           </td>
           <td>Equivalent to:
-            <pre><code class="zig">a %% unreachable</code></pre>
+            <pre><code class="zig">a catch unreachable</code></pre>
           </td>
           <td>
             <pre><code class="zig">const value: %u32 = 5678;
@@ -1482,7 +1482,7 @@ x{}
 == != &lt; &gt; &lt;= &gt;=
 and
 or
-?? %%
+?? catch
 = *= /= %= += -= &lt;&lt;= &gt;&gt;= &amp;= ^= |=</code></pre>
       <h2 id="arrays">Arrays</h2>
       <pre><code class="zig">const assert = @import("std").debug.assert;
@@ -1829,7 +1829,7 @@ Test 1/1 pointer alignment safety...incorrect alignment
     return root.main();
                     ^
 /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:47:13: 0x0000000000216050 in ??? (test)
-    callMain(argc, argv, envp) %% std.os.posix.exit(1);
+    callMain(argc, argv, envp) catch std.os.posix.exit(1);
             ^
 /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:34:25: 0x0000000000215fa0 in ??? (test)
     posixCallMainAndExit()
@@ -1885,7 +1885,7 @@ lib/zig/std/special/bootstrap.zig:60:21: 0x00000000002149e7 in ??? (test)
     return root.main();
                     ^
 lib/zig/std/special/bootstrap.zig:47:13: 0x00000000002148a0 in ??? (test)
-    callMain(argc, argv, envp) %% std.os.posix.exit(1);
+    callMain(argc, argv, envp) catch std.os.posix.exit(1);
             ^
 lib/zig/std/special/bootstrap.zig:34:25: 0x00000000002147f0 in ??? (test)
     posixCallMainAndExit()
@@ -2965,7 +2965,7 @@ lib/zig/std/special/bootstrap.zig:60:21: 0x0000000000214947 in ??? (test)
     return root.main();
                     ^
 lib/zig/std/special/bootstrap.zig:47:13: 0x0000000000214800 in ??? (test)
-    callMain(argc, argv, envp) %% std.os.posix.exit(1);
+    callMain(argc, argv, envp) catch std.os.posix.exit(1);
             ^
 lib/zig/std/special/bootstrap.zig:34:25: 0x0000000000214750 in ??? (test)
     posixCallMainAndExit()
@@ -3019,7 +3019,7 @@ extern fn bar(value: u32);</code></pre>
       <pre><code class="zig">pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: c_uint) -&gt; noreturn;
 
 fn foo() {
-    const value = bar() %% ExitProcess(1);
+    const value = bar() catch ExitProcess(1);
     assert(value == 1234);
 }
 
@@ -3209,7 +3209,7 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 {
       </ul>
       <p>If you want to provide a default value, you can use the <code>%%</code> binary operator:</p>
       <pre><code class="zig">fn doAThing(str: []u8) {
-    const number = parseU64(str, 10) %% 13;
+    const number = parseU64(str, 10) catch 13;
     // ...
 }</code></pre>
       <p>
@@ -3220,7 +3220,7 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 {
       <p>Let's say you wanted to return the error if you got one, otherwise continue with the
       function logic:</p>
       <pre><code class="zig">fn doAThing(str: []u8) -&gt; %void {
-    const number = parseU64(str, 10) %% |err| return err;
+    const number = parseU64(str, 10) catch |err| return err;
     // ...
 }</code></pre>
       <p>
@@ -3239,7 +3239,7 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 {
         Maybe you know with complete certainty that an expression will never be an error.
         In this case you can do this:
       </p>
-      <pre><code class="zig">const number = parseU64("1234", 10) %% unreachable;</code></pre>
+      <pre><code class="zig">const number = parseU64("1234", 10) catch unreachable;</code></pre>
       <p>
       Here we know for sure that "1234" will parse successfully. So we put the
       <code>unreachable</code> value on the right hand side. <code>unreachable</code> generates
@@ -3250,7 +3250,7 @@ pub fn parseU64(buf: []const u8, radix: u8) -&gt; %u64 {
       <p>Again there is a syntactic shortcut for this:</p>
       <pre><code class="zig">const number = %%parseU64("1234", 10);</code></pre>
       <p>
-      The <code>%%</code> <em>prefix</em> operator is equivalent to <code class="zig">expression %% unreachable</code>. It unwraps an error union type,
+      The <code>%%</code> <em>prefix</em> operator is equivalent to <code class="zig">expression catch unreachable</code>. It unwraps an error union type,
       and panics in debug mode if the value was an error.
       </p>
       <p>
@@ -4984,7 +4984,7 @@ Test 1/1 safety check...reached unreachable code
     return root.main();
                     ^
 /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:37:13: 0x00000000002148d0 in ??? (test)
-    callMain(argc, argv, envp) %% exit(1);
+    callMain(argc, argv, envp) catch exit(1);
             ^
 /home/andy/dev/zig/build/lib/zig/std/special/bootstrap.zig:30:20: 0x0000000000214820 in ??? (test)
     callMainAndExit()
@@ -5909,7 +5909,7 @@ UnwrapExpression = BoolOrExpression (UnwrapNullable | UnwrapError) | BoolOrExpre
 
 UnwrapNullable = "??" Expression
 
-UnwrapError = "%%" option("|" Symbol "|") Expression
+UnwrapError = "catch" option("|" Symbol "|") Expression
 
 AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | UnwrapExpression
 
example/cat/main.zig
@@ -20,7 +20,7 @@ pub fn main() -> %void {
         } else if (arg[0] == '-') {
             return usage(exe);
         } else {
-            var file = io.File.openRead(arg, null) %% |err| {
+            var file = io.File.openRead(arg, null) catch |err| {
                 warn("Unable to open file: {}\n", @errorName(err));
                 return err;
             };
@@ -45,7 +45,7 @@ fn cat_file(stdout: &io.File, file: &io.File) -> %void {
     var buf: [1024 * 4]u8 = undefined;
 
     while (true) {
-        const bytes_read = file.read(buf[0..]) %% |err| {
+        const bytes_read = file.read(buf[0..]) catch |err| {
             warn("Unable to read from stream: {}\n", @errorName(err));
             return err;
         };
@@ -54,7 +54,7 @@ fn cat_file(stdout: &io.File, file: &io.File) -> %void {
             break;
         }
 
-        stdout.write(buf[0..bytes_read]) %% |err| {
+        stdout.write(buf[0..bytes_read]) catch |err| {
             warn("Unable to write to stdout: {}\n", @errorName(err));
             return err;
         };
@@ -62,7 +62,7 @@ fn cat_file(stdout: &io.File, file: &io.File) -> %void {
 }
 
 fn unwrapArg(arg: %[]u8) -> %[]u8 {
-    return arg %% |err| {
+    return arg catch |err| {
         warn("Unable to parse command line: {}\n", err);
         return err;
     };
example/guess_number/main.zig
@@ -25,12 +25,12 @@ pub fn main() -> %void {
         try stdout.print("\nGuess a number between 1 and 100: ");
         var line_buf : [20]u8 = undefined;
 
-        const line_len = stdin_file.read(line_buf[0..]) %% |err| {
+        const line_len = stdin_file.read(line_buf[0..]) catch |err| {
             try stdout.print("Unable to read from stdin: {}\n", @errorName(err));
             return err;
         };
 
-        const guess = fmt.parseUnsigned(u8, line_buf[0..line_len - 1], 10) %% {
+        const guess = fmt.parseUnsigned(u8, line_buf[0..line_len - 1], 10) catch {
             try stdout.print("Invalid number.\n");
             continue;
         };
src/all_types.hpp
@@ -389,7 +389,7 @@ enum NodeType {
     NodeTypeArrayType,
     NodeTypeErrorType,
     NodeTypeVarLiteral,
-    NodeTypeTryExpr,
+    NodeTypeIfErrorExpr,
     NodeTypeTestExpr,
 };
 
@@ -546,7 +546,7 @@ struct AstNodeBinOpExpr {
     AstNode *op2;
 };
 
-struct AstNodeUnwrapErrorExpr {
+struct AstNodeCatchExpr {
     AstNode *op1;
     AstNode *symbol; // can be null
     AstNode *op2;
@@ -860,7 +860,7 @@ struct AstNode {
         AstNodeErrorValueDecl error_value_decl;
         AstNodeTestDecl test_decl;
         AstNodeBinOpExpr bin_op_expr;
-        AstNodeUnwrapErrorExpr unwrap_err_expr;
+        AstNodeCatchExpr unwrap_err_expr;
         AstNodePrefixOpExpr prefix_op_expr;
         AstNodeAddrOfExpr addr_of_expr;
         AstNodeFnCallExpr fn_call_expr;
@@ -868,7 +868,7 @@ struct AstNode {
         AstNodeSliceExpr slice_expr;
         AstNodeUse use;
         AstNodeIfBoolExpr if_bool_expr;
-        AstNodeTryExpr try_expr;
+        AstNodeTryExpr if_err_expr;
         AstNodeTestExpr test_expr;
         AstNodeWhileExpr while_expr;
         AstNodeForExpr for_expr;
src/analyze.cpp
@@ -2933,7 +2933,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
         case NodeTypeArrayType:
         case NodeTypeErrorType:
         case NodeTypeVarLiteral:
-        case NodeTypeTryExpr:
+        case NodeTypeIfErrorExpr:
         case NodeTypeTestExpr:
             zig_unreachable();
     }
src/ast_render.cpp
@@ -68,7 +68,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
         case PrefixOpDereference: return "*";
         case PrefixOpMaybe: return "?";
         case PrefixOpError: return "%";
-        case PrefixOpUnwrapError: return "%%";
+        case PrefixOpUnwrapError: return "catch";
         case PrefixOpUnwrapMaybe: return "??";
     }
     zig_unreachable();
@@ -241,8 +241,8 @@ static const char *node_type_str(NodeType node_type) {
             return "ErrorType";
         case NodeTypeVarLiteral:
             return "VarLiteral";
-        case NodeTypeTryExpr:
-            return "TryExpr";
+        case NodeTypeIfErrorExpr:
+            return "IfErrorExpr";
         case NodeTypeTestExpr:
             return "TestExpr";
     }
@@ -872,23 +872,23 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
                 fprintf(ar->f, "null");
                 break;
             }
-        case NodeTypeTryExpr:
+        case NodeTypeIfErrorExpr:
             {
                 fprintf(ar->f, "if (");
-                render_node_grouped(ar, node->data.try_expr.target_node);
+                render_node_grouped(ar, node->data.if_err_expr.target_node);
                 fprintf(ar->f, ") ");
-                if (node->data.try_expr.var_symbol) {
-                    const char *ptr_str = node->data.try_expr.var_is_ptr ? "*" : "";
-                    const char *var_name = buf_ptr(node->data.try_expr.var_symbol);
+                if (node->data.if_err_expr.var_symbol) {
+                    const char *ptr_str = node->data.if_err_expr.var_is_ptr ? "*" : "";
+                    const char *var_name = buf_ptr(node->data.if_err_expr.var_symbol);
                     fprintf(ar->f, "|%s%s| ", ptr_str, var_name);
                 }
-                render_node_grouped(ar, node->data.try_expr.then_node);
-                if (node->data.try_expr.else_node) {
+                render_node_grouped(ar, node->data.if_err_expr.then_node);
+                if (node->data.if_err_expr.else_node) {
                     fprintf(ar->f, " else ");
-                    if (node->data.try_expr.err_symbol) {
-                        fprintf(ar->f, "|%s| ", buf_ptr(node->data.try_expr.err_symbol));
+                    if (node->data.if_err_expr.err_symbol) {
+                        fprintf(ar->f, "|%s| ", buf_ptr(node->data.if_err_expr.err_symbol));
                     }
-                    render_node_grouped(ar, node->data.try_expr.else_node);
+                    render_node_grouped(ar, node->data.if_err_expr.else_node);
                 }
                 break;
             }
src/ir.cpp
@@ -4665,16 +4665,16 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
     return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
 }
 
-static IrInstruction *ir_gen_try_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
-    assert(node->type == NodeTypeTryExpr);
+static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
+    assert(node->type == NodeTypeIfErrorExpr);
 
-    AstNode *target_node = node->data.try_expr.target_node;
-    AstNode *then_node = node->data.try_expr.then_node;
-    AstNode *else_node = node->data.try_expr.else_node;
-    bool var_is_ptr = node->data.try_expr.var_is_ptr;
+    AstNode *target_node = node->data.if_err_expr.target_node;
+    AstNode *then_node = node->data.if_err_expr.then_node;
+    AstNode *else_node = node->data.if_err_expr.else_node;
+    bool var_is_ptr = node->data.if_err_expr.var_is_ptr;
     bool var_is_const = true;
-    Buf *var_symbol = node->data.try_expr.var_symbol;
-    Buf *err_symbol = node->data.try_expr.err_symbol;
+    Buf *var_symbol = node->data.if_err_expr.var_symbol;
+    Buf *err_symbol = node->data.if_err_expr.err_symbol;
 
     IrInstruction *err_val_ptr = ir_gen_node_extra(irb, target_node, scope, LVAL_PTR);
     if (err_val_ptr == irb->codegen->invalid_instruction)
@@ -5411,8 +5411,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
             return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
         case NodeTypeVarLiteral:
             return ir_lval_wrap(irb, scope, ir_gen_var_literal(irb, scope, node), lval);
-        case NodeTypeTryExpr:
-            return ir_lval_wrap(irb, scope, ir_gen_try_expr(irb, scope, node), lval);
+        case NodeTypeIfErrorExpr:
+            return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);
         case NodeTypeTestExpr:
             return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval);
         case NodeTypeSwitchExpr:
src/parser.cpp
@@ -1407,15 +1407,15 @@ static AstNode *ast_parse_if_try_test_expr(ParseContext *pc, size_t *token_index
     }
 
     if (err_name_tok != nullptr) {
-        AstNode *node = ast_create_node(pc, NodeTypeTryExpr, if_token);
-        node->data.try_expr.target_node = condition;
-        node->data.try_expr.var_is_ptr = var_is_ptr;
+        AstNode *node = ast_create_node(pc, NodeTypeIfErrorExpr, if_token);
+        node->data.if_err_expr.target_node = condition;
+        node->data.if_err_expr.var_is_ptr = var_is_ptr;
         if (var_name_tok != nullptr) {
-            node->data.try_expr.var_symbol = token_buf(var_name_tok);
+            node->data.if_err_expr.var_symbol = token_buf(var_name_tok);
         }
-        node->data.try_expr.then_node = body_node;
-        node->data.try_expr.err_symbol = token_buf(err_name_tok);
-        node->data.try_expr.else_node = else_node;
+        node->data.if_err_expr.then_node = body_node;
+        node->data.if_err_expr.err_symbol = token_buf(err_name_tok);
+        node->data.if_err_expr.else_node = else_node;
         return node;
     } else if (var_name_tok != nullptr) {
         AstNode *node = ast_create_node(pc, NodeTypeTestExpr, if_token);
@@ -2041,7 +2041,7 @@ static BinOpType ast_parse_ass_op(ParseContext *pc, size_t *token_index, bool ma
 /*
 UnwrapExpression : BoolOrExpression (UnwrapMaybe | UnwrapError) | BoolOrExpression
 UnwrapMaybe : "??" BoolOrExpression
-UnwrapError : "%%" option("|" "Symbol" "|") BoolOrExpression
+UnwrapError = "catch" option("|" Symbol "|") Expression
 */
 static AstNode *ast_parse_unwrap_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
     AstNode *lhs = ast_parse_bool_or_expr(pc, token_index, mandatory);
@@ -2061,7 +2061,7 @@ static AstNode *ast_parse_unwrap_expr(ParseContext *pc, size_t *token_index, boo
         node->data.bin_op_expr.op2 = rhs;
 
         return node;
-    } else if (token->id == TokenIdPercentPercent) {
+    } else if (token->id == TokenIdKeywordCatch) {
         *token_index += 1;
 
         AstNode *node = ast_create_node(pc, NodeTypeUnwrapErrorExpr, token);
@@ -2157,10 +2157,10 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
             if (node->data.if_bool_expr.else_node)
                 return statement_terminates_without_semicolon(node->data.if_bool_expr.else_node);
             return node->data.if_bool_expr.then_block->type == NodeTypeBlock;
-        case NodeTypeTryExpr:
-            if (node->data.try_expr.else_node)
-                return statement_terminates_without_semicolon(node->data.try_expr.else_node);
-            return node->data.try_expr.then_node->type == NodeTypeBlock;
+        case NodeTypeIfErrorExpr:
+            if (node->data.if_err_expr.else_node)
+                return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);
+            return node->data.if_err_expr.then_node->type == NodeTypeBlock;
         case NodeTypeTestExpr:
             if (node->data.test_expr.else_node)
                 return statement_terminates_without_semicolon(node->data.test_expr.else_node);
@@ -2833,10 +2833,10 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
             visit_field(&node->data.if_bool_expr.then_block, visit, context);
             visit_field(&node->data.if_bool_expr.else_node, visit, context);
             break;
-        case NodeTypeTryExpr:
-            visit_field(&node->data.try_expr.target_node, visit, context);
-            visit_field(&node->data.try_expr.then_node, visit, context);
-            visit_field(&node->data.try_expr.else_node, visit, context);
+        case NodeTypeIfErrorExpr:
+            visit_field(&node->data.if_err_expr.target_node, visit, context);
+            visit_field(&node->data.if_err_expr.then_node, visit, context);
+            visit_field(&node->data.if_err_expr.else_node, visit, context);
             break;
         case NodeTypeTestExpr:
             visit_field(&node->data.test_expr.target_node, visit, context);
src/tokenizer.cpp
@@ -111,6 +111,7 @@ static const struct ZigKeyword zig_keywords[] = {
     {"and", TokenIdKeywordAnd},
     {"asm", TokenIdKeywordAsm},
     {"break", TokenIdKeywordBreak},
+    {"catch", TokenIdKeywordCatch},
     {"coldcc", TokenIdKeywordColdCC},
     {"comptime", TokenIdKeywordCompTime},
     {"const", TokenIdKeywordConst},
@@ -1512,6 +1513,7 @@ const char * token_name(TokenId id) {
         case TokenIdKeywordAnd: return "and";
         case TokenIdKeywordAsm: return "asm";
         case TokenIdKeywordBreak: return "break";
+        case TokenIdKeywordCatch: return "catch";
         case TokenIdKeywordColdCC: return "coldcc";
         case TokenIdKeywordCompTime: return "comptime";
         case TokenIdKeywordConst: return "const";
src/tokenizer.hpp
@@ -47,10 +47,10 @@ enum TokenId {
     TokenIdFloatLiteral,
     TokenIdIntLiteral,
     TokenIdKeywordAlign,
-    TokenIdKeywordSection,
     TokenIdKeywordAnd,
     TokenIdKeywordAsm,
     TokenIdKeywordBreak,
+    TokenIdKeywordCatch,
     TokenIdKeywordColdCC,
     TokenIdKeywordCompTime,
     TokenIdKeywordConst,
@@ -74,6 +74,7 @@ enum TokenId {
     TokenIdKeywordPacked,
     TokenIdKeywordPub,
     TokenIdKeywordReturn,
+    TokenIdKeywordSection,
     TokenIdKeywordStdcallCC,
     TokenIdKeywordStruct,
     TokenIdKeywordSwitch,
src-self-hosted/main.zig
@@ -21,7 +21,7 @@ error ZigInstallationNotFound;
 const default_zig_cache_name = "zig-cache";
 
 pub fn main() -> %void {
-    main2() %% |err| {
+    main2() catch |err| {
         if (err != error.InvalidCommandLineArguments) {
             warn("{}\n", @errorName(err));
         }
@@ -571,12 +571,12 @@ fn printZen() -> %void {
 /// Caller must free result
 fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) -> %[]u8 {
     if (zig_install_prefix_arg) |zig_install_prefix| {
-        return testZigInstallPrefix(allocator, zig_install_prefix) %% |err| {
+        return testZigInstallPrefix(allocator, zig_install_prefix) catch |err| {
             warn("No Zig installation found at prefix {}: {}\n", zig_install_prefix_arg, @errorName(err));
             return error.ZigInstallationNotFound;
         };
     } else {
-        return findZigLibDir(allocator) %% |err| {
+        return findZigLibDir(allocator) catch |err| {
             warn("Unable to find zig lib directory: {}.\nReinstall Zig or use --zig-install-prefix.\n",
                 @errorName(err));
             return error.ZigLibDirNotFound;
@@ -611,7 +611,7 @@ fn findZigLibDir(allocator: &mem.Allocator) -> %[]u8 {
             break;
         }
 
-        return testZigInstallPrefix(allocator, test_dir) %% |err| {
+        return testZigInstallPrefix(allocator, test_dir) catch |err| {
             cur_path = test_dir;
             continue;
         };
src-self-hosted/module.zig
@@ -207,13 +207,13 @@ pub const Module = struct {
         }
 
         const root_src_path = self.root_src_path ?? @panic("TODO handle null root src path");
-        const root_src_real_path = os.path.real(self.allocator, root_src_path) %% |err| {
+        const root_src_real_path = os.path.real(self.allocator, root_src_path) catch |err| {
             try printError("unable to get real path '{}': {}", root_src_path, err);
             return err;
         };
         %defer self.allocator.free(root_src_real_path);
 
-        const source_code = io.readFileAllocExtra(root_src_real_path, self.allocator, 3) %% |err| {
+        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;
         };
src-self-hosted/parser.zig
@@ -96,12 +96,12 @@ pub const Parser = struct {
         var stack = self.initUtilityArrayList(&ast.Node);
         defer self.deinitUtilityArrayList(stack);
 
-        stack.append(&root_node.base) %% unreachable;
+        stack.append(&root_node.base) catch unreachable;
         while (stack.popOrNull()) |node| {
             var i: usize = 0;
             while (node.iterate(i)) |child| : (i += 1) {
                 if (child.iterate(0) != null) {
-                    stack.append(child) %% unreachable;
+                    stack.append(child) catch unreachable;
                 } else {
                     child.destroy(self.allocator);
                 }
@@ -111,7 +111,7 @@ pub const Parser = struct {
     }
 
     pub fn parse(self: &Parser) -> %&ast.NodeRoot {
-        const result = self.parseInner() %% |err| x: {
+        const result = self.parseInner() catch |err| x: {
             if (self.cleanup_root_node) |root_node| {
                 self.freeAst(root_node);
             }
@@ -156,14 +156,14 @@ pub const Parser = struct {
                     const token = self.getNextToken();
                     switch (token.id) {
                         Token.Id.Keyword_pub, Token.Id.Keyword_export => {
-                            stack.append(State { .TopLevelExtern = token }) %% unreachable;
+                            stack.append(State { .TopLevelExtern = token }) catch unreachable;
                             continue;
                         },
                         Token.Id.Eof => return root_node,
                         else => {
                             self.putBackToken(token);
                             // TODO shouldn't need this cast
-                            stack.append(State { .TopLevelExtern = null }) %% unreachable;
+                            stack.append(State { .TopLevelExtern = null }) catch unreachable;
                             continue;
                         },
                     }
@@ -176,7 +176,7 @@ pub const Parser = struct {
                                 .visib_token = visib_token,
                                 .extern_token = token,
                             },
-                        }) %% unreachable;
+                        }) catch unreachable;
                         continue;
                     }
                     self.putBackToken(token);
@@ -185,14 +185,14 @@ pub const Parser = struct {
                             .visib_token = visib_token,
                             .extern_token = null,
                         },
-                    }) %% unreachable;
+                    }) catch unreachable;
                     continue;
                 },
                 State.TopLevelDecl => |ctx| {
                     const token = self.getNextToken();
                     switch (token.id) {
                         Token.Id.Keyword_var, Token.Id.Keyword_const => {
-                            stack.append(State.TopLevel) %% unreachable;
+                            stack.append(State.TopLevel) catch unreachable;
                             // TODO shouldn't need these casts
                             const var_decl_node = try self.createAttachVarDecl(&root_node.decls, ctx.visib_token,
                                 token, (?Token)(null), ctx.extern_token);
@@ -200,7 +200,7 @@ pub const Parser = struct {
                             continue;
                         },
                         Token.Id.Keyword_fn => {
-                            stack.append(State.TopLevel) %% unreachable;
+                            stack.append(State.TopLevel) catch unreachable;
                             // TODO shouldn't need these casts
                             const fn_proto = try self.createAttachFnProto(&root_node.decls, token,
                                 ctx.extern_token, (?Token)(null), (?Token)(null), (?Token)(null));
@@ -212,7 +212,7 @@ pub const Parser = struct {
                             @panic("TODO extern with string literal");
                         },
                         Token.Id.Keyword_coldcc, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
-                            stack.append(State.TopLevel) %% unreachable;
+                            stack.append(State.TopLevel) catch unreachable;
                             const fn_token = try self.eatToken(Token.Id.Keyword_fn);
                             // TODO shouldn't need this cast
                             const fn_proto = try self.createAttachFnProto(&root_node.decls, fn_token,
@@ -226,7 +226,7 @@ pub const Parser = struct {
                 },
                 State.VarDecl => |var_decl| {
                     var_decl.name_token = try self.eatToken(Token.Id.Identifier);
-                    stack.append(State { .VarDeclAlign = var_decl }) %% unreachable;
+                    stack.append(State { .VarDeclAlign = var_decl }) catch unreachable;
 
                     const next_token = self.getNextToken();
                     if (next_token.id == Token.Id.Colon) {
@@ -238,7 +238,7 @@ pub const Parser = struct {
                     continue;
                 },
                 State.VarDeclAlign => |var_decl| {
-                    stack.append(State { .VarDeclEq = var_decl }) %% unreachable;
+                    stack.append(State { .VarDeclEq = var_decl }) catch unreachable;
 
                     const next_token = self.getNextToken();
                     if (next_token.id == Token.Id.Keyword_align) {
@@ -255,7 +255,7 @@ pub const Parser = struct {
                     const token = self.getNextToken();
                     if (token.id == Token.Id.Equal) {
                         var_decl.eq_token = token;
-                        stack.append(State { .ExpectToken = Token.Id.Semicolon }) %% unreachable;
+                        stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
                         try stack.append(State {
                             .Expression = DestPtr {.NullableField = &var_decl.init_node},
                         });
@@ -273,7 +273,7 @@ pub const Parser = struct {
 
                 State.Expression => |dest_ptr| {
                     // save the dest_ptr for later
-                    stack.append(state) %% unreachable;
+                    stack.append(state) catch unreachable;
                     try stack.append(State.ExpectOperand);
                     continue;
                 },
@@ -383,7 +383,7 @@ pub const Parser = struct {
                     var token = self.getNextToken();
                     switch (token.id) {
                         Token.Id.Keyword_align => {
-                            stack.append(state) %% unreachable;
+                            stack.append(state) catch unreachable;
                             if (addr_of_info.align_expr != null) return self.parseError(token, "multiple align qualifiers");
                             _ = try self.eatToken(Token.Id.LParen);
                             try stack.append(State { .ExpectToken = Token.Id.RParen });
@@ -391,13 +391,13 @@ pub const Parser = struct {
                             continue;
                         },
                         Token.Id.Keyword_const => {
-                            stack.append(state) %% unreachable;
+                            stack.append(state) catch unreachable;
                             if (addr_of_info.const_token != null) return self.parseError(token, "duplicate qualifier: const");
                             addr_of_info.const_token = token;
                             continue;
                         },
                         Token.Id.Keyword_volatile => {
-                            stack.append(state) %% unreachable;
+                            stack.append(state) catch unreachable;
                             if (addr_of_info.volatile_token != null) return self.parseError(token, "duplicate qualifier: volatile");
                             addr_of_info.volatile_token = token;
                             continue;
@@ -416,12 +416,12 @@ pub const Parser = struct {
                     }
                     self.putBackToken(token);
 
-                    stack.append(State { .Expression = dest_ptr }) %% unreachable;
+                    stack.append(State { .Expression = dest_ptr }) catch unreachable;
                     continue;
                 },
 
                 State.FnProto => |fn_proto| {
-                    stack.append(State { .FnProtoAlign = fn_proto }) %% unreachable;
+                    stack.append(State { .FnProtoAlign = fn_proto }) catch unreachable;
                     try stack.append(State { .ParamDecl = fn_proto });
                     try stack.append(State { .ExpectToken = Token.Id.LParen });
 
@@ -442,7 +442,7 @@ pub const Parser = struct {
                     if (token.id == Token.Id.Arrow) {
                         stack.append(State {
                             .TypeExpr = DestPtr {.NullableField = &fn_proto.return_type},
-                        }) %% unreachable;
+                        }) catch unreachable;
                         continue;
                     } else {
                         self.putBackToken(token);
@@ -474,13 +474,13 @@ pub const Parser = struct {
                     }
                     if (token.id == Token.Id.Ellipsis3) {
                         param_decl.var_args_token = token;
-                        stack.append(State { .ExpectToken = Token.Id.RParen }) %% unreachable;
+                        stack.append(State { .ExpectToken = Token.Id.RParen }) catch unreachable;
                         continue;
                     } else {
                         self.putBackToken(token);
                     }
 
-                    stack.append(State { .ParamDecl = fn_proto }) %% unreachable;
+                    stack.append(State { .ParamDecl = fn_proto }) catch unreachable;
                     try stack.append(State.ParamDeclComma);
                     try stack.append(State {
                         .TypeExpr = DestPtr {.Field = &param_decl.type_node}
@@ -506,7 +506,7 @@ pub const Parser = struct {
                         Token.Id.LBrace => {
                             const block = try self.createBlock(token);
                             fn_proto.body_node = &block.base;
-                            stack.append(State { .Block = block }) %% unreachable;
+                            stack.append(State { .Block = block }) catch unreachable;
                             continue;
                         },
                         Token.Id.Semicolon => continue,
@@ -523,7 +523,7 @@ pub const Parser = struct {
                         },
                         else => {
                             self.putBackToken(token);
-                            stack.append(State { .Block = block }) %% unreachable;
+                            stack.append(State { .Block = block }) catch unreachable;
                             try stack.append(State { .Statement = block });
                             continue;
                         },
@@ -560,7 +560,7 @@ pub const Parser = struct {
                         self.putBackToken(mut_token);
                     }
 
-                    stack.append(State { .ExpectToken = Token.Id.Semicolon }) %% unreachable;
+                    stack.append(State { .ExpectToken = Token.Id.Semicolon }) catch unreachable;
                     try stack.append(State { .Expression = DestPtr{.List = &block.statements} });
                     continue;
                 },
@@ -1112,7 +1112,7 @@ fn testCanonical(source: []const u8) {
         // Try it once with unlimited memory, make sure it works
         var fixed_allocator = mem.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
         var failing_allocator = std.debug.FailingAllocator.init(&fixed_allocator.allocator, @maxValue(usize));
-        const result_source = testParse(source, &failing_allocator.allocator) %% @panic("test failed");
+        const result_source = testParse(source, &failing_allocator.allocator) catch @panic("test failed");
         if (!mem.eql(u8, result_source, source)) {
             warn("\n====== expected this output: =========\n");
             warn("{}", source);
src-self-hosted/tokenizer.zig
@@ -557,22 +557,22 @@ pub const Tokenizer = struct {
             return 0;
         } else {
             // check utf8-encoded character.
-            const length = std.unicode.utf8ByteSequenceLength(c0) %% return 1;
+            const length = std.unicode.utf8ByteSequenceLength(c0) catch return 1;
             // the last 3 bytes in the buffer are guaranteed to be '\n',
             // which means we don't need to do any bounds checking here.
             const bytes = self.buffer[self.index..self.index + length];
             switch (length) {
                 2 => {
-                    const value = std.unicode.utf8Decode2(bytes) %% return length;
+                    const value = std.unicode.utf8Decode2(bytes) catch return length;
                     if (value == 0x85) return length; // U+0085 (NEL)
                 },
                 3 => {
-                    const value = std.unicode.utf8Decode3(bytes) %% return length;
+                    const value = std.unicode.utf8Decode3(bytes) catch return length;
                     if (value == 0x2028) return length; // U+2028 (LS)
                     if (value == 0x2029) return length; // U+2029 (PS)
                 },
                 4 => {
-                    _ = std.unicode.utf8Decode4(bytes) %% return length;
+                    _ = std.unicode.utf8Decode4(bytes) catch return length;
                 },
                 else => unreachable,
             }
std/debug/index.zig
@@ -22,8 +22,8 @@ var stderr_file: io.File = undefined;
 var stderr_file_out_stream: io.FileOutStream = undefined;
 var stderr_stream: ?&io.OutStream = null;
 pub fn warn(comptime fmt: []const u8, args: ...) {
-    const stderr = getStderrStream() %% return;
-    stderr.print(fmt, args) %% return;
+    const stderr = getStderrStream() catch return;
+    stderr.print(fmt, args) catch return;
 }
 fn getStderrStream() -> %&io.OutStream {
     if (stderr_stream) |st| {
@@ -39,8 +39,8 @@ fn getStderrStream() -> %&io.OutStream {
 
 /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.
 pub fn dumpStackTrace() {
-    const stderr = getStderrStream() %% return;
-    writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) %% return;
+    const stderr = getStderrStream() catch return;
+    writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) catch return;
 }
 
 /// This function invokes undefined behavior when `ok` is `false`.
@@ -86,9 +86,9 @@ pub fn panic(comptime format: []const u8, args: ...) -> noreturn {
         panicking = true;
     }
 
-    const stderr = getStderrStream() %% os.abort();
-    stderr.print(format ++ "\n", args) %% os.abort();
-    writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) %% os.abort();
+    const stderr = getStderrStream() catch os.abort();
+    stderr.print(format ++ "\n", args) catch os.abort();
+    writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) catch os.abort();
 
     os.abort();
 }
@@ -146,7 +146,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty
                 // at compile time. I'll call it issue #313
                 const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}";
 
-                const compile_unit = findCompileUnit(st, return_address) %% {
+                const compile_unit = findCompileUnit(st, return_address) catch {
                     try out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n    ???\n\n",
                         return_address);
                     continue;
@@ -757,7 +757,7 @@ fn getLineNumberInfo(st: &ElfStackTrace, compile_unit: &const CompileUnit, targe
                         });
                     },
                     else => {
-                        const fwd_amt = math.cast(isize, op_size - 1) %% return error.InvalidDebugInfo;
+                        const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;
                         try in_file.seekForward(fwd_amt);
                     },
                 }
std/fmt/index.zig
@@ -533,7 +533,7 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: u
 }
 
 test "parse u64 digit too big" {
-    _ = parseUnsigned(u64, "123a", 10) %% |err| {
+    _ = parseUnsigned(u64, "123a", 10) catch |err| {
         if (err == error.InvalidChar) return;
         unreachable;
     };
std/os/windows/util.zig
@@ -166,7 +166,7 @@ pub fn windowsUnloadDll(hModule: windows.HMODULE) {
 test "InvalidDll" {
     const DllName = "asdf.dll";
     const allocator = std.debug.global_allocator;
-    const handle = os.windowsLoadDll(allocator, DllName) %%  |err| {
+    const handle = os.windowsLoadDll(allocator, DllName) catch  |err| {
         assert(err == error.DllNotFound);
         return;
     };
std/os/child_process.zig
@@ -383,27 +383,27 @@ pub const ChildProcess = struct {
             // we are the child
             restore_SIGCHLD();
 
-            setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) %%
+            setUpChildIo(self.stdin_behavior, stdin_pipe[0], posix.STDIN_FILENO, dev_null_fd) catch
                 |err| forkChildErrReport(err_pipe[1], err);
-            setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) %%
+            setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch
                 |err| forkChildErrReport(err_pipe[1], err);
-            setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) %%
+            setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch
                 |err| forkChildErrReport(err_pipe[1], err);
 
             if (self.cwd) |cwd| {
-                os.changeCurDir(self.allocator, cwd) %%
+                os.changeCurDir(self.allocator, cwd) catch
                     |err| forkChildErrReport(err_pipe[1], err);
             }
 
             if (self.gid) |gid| {
-                os.posix_setregid(gid, gid) %% |err| forkChildErrReport(err_pipe[1], err);
+                os.posix_setregid(gid, gid) catch |err| forkChildErrReport(err_pipe[1], err);
             }
 
             if (self.uid) |uid| {
-                os.posix_setreuid(uid, uid) %% |err| forkChildErrReport(err_pipe[1], err);
+                os.posix_setreuid(uid, uid) catch |err| forkChildErrReport(err_pipe[1], err);
             }
 
-            os.posixExecve(self.argv, env_map, self.allocator) %%
+            os.posixExecve(self.argv, env_map, self.allocator) catch
                 |err| forkChildErrReport(err_pipe[1], err);
         }
 
@@ -573,7 +573,7 @@ pub const ChildProcess = struct {
         defer self.allocator.free(app_name);
 
         windowsCreateProcess(app_name.ptr, cmd_line.ptr, envp_ptr, cwd_ptr,
-            &siStartInfo, &piProcInfo) %% |no_path_err|
+            &siStartInfo, &piProcInfo) catch |no_path_err|
         {
             if (no_path_err != error.FileNotFound)
                 return no_path_err;
@@ -767,12 +767,12 @@ const ErrInt = @IntType(false, @sizeOf(error) * 8);
 fn writeIntFd(fd: i32, value: ErrInt) -> %void {
     var bytes: [@sizeOf(ErrInt)]u8 = undefined;
     mem.writeInt(bytes[0..], value, builtin.endian);
-    os.posixWrite(fd, bytes[0..]) %% return error.SystemResources;
+    os.posixWrite(fd, bytes[0..]) catch return error.SystemResources;
 }
 
 fn readIntFd(fd: i32) -> %ErrInt {
     var bytes: [@sizeOf(ErrInt)]u8 = undefined;
-    os.posixRead(fd, bytes[0..]) %% return error.SystemResources;
+    os.posixRead(fd, bytes[0..]) catch return error.SystemResources;
     return mem.readInt(bytes[0..], ErrInt, builtin.endian);
 }
 
std/os/index.zig
@@ -842,7 +842,7 @@ pub fn makePath(allocator: &Allocator, full_path: []const u8) -> %void {
 
     var end_index: usize = resolved_path.len;
     while (true) {
-        makeDir(allocator, resolved_path[0..end_index]) %% |err| {
+        makeDir(allocator, resolved_path[0..end_index]) catch |err| {
             if (err == error.PathAlreadyExists) {
                 // TODO stat the file and return an error if it's not a directory
                 // this is important because otherwise a dangling symlink
@@ -915,7 +915,7 @@ pub fn deleteTree(allocator: &Allocator, full_path: []const u8) -> %void {
                 return err;
         }
         {
-            var dir = Dir.open(allocator, full_path) %% |err| {
+            var dir = Dir.open(allocator, full_path) catch |err| {
                 if (err == error.FileNotFound)
                     return;
                 if (err == error.NotDir)
std/os/path.zig
@@ -1102,7 +1102,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
             var buf = try allocator.alloc(u8, 256);
             %defer allocator.free(buf);
             while (true) {
-                const buf_len = math.cast(windows.DWORD, buf.len) %% return error.NameTooLong;
+                const buf_len = math.cast(windows.DWORD, buf.len) catch return error.NameTooLong;
                 const result = windows.GetFinalPathNameByHandleA(h_file, buf.ptr, buf_len, windows.VOLUME_NAME_DOS);
 
                 if (result == 0) {
std/special/bootstrap.zig
@@ -22,7 +22,7 @@ comptime {
 
 extern fn zenMain() -> noreturn {
     // TODO: call exit.
-    root.main() %% {};
+    root.main() catch {};
     while (true) {}
 }
 
@@ -44,7 +44,7 @@ nakedcc fn _start() -> noreturn {
 extern fn WinMainCRTStartup() -> noreturn {
     @setAlignStack(16);
 
-    root.main() %% std.os.windows.ExitProcess(1);
+    root.main() catch std.os.windows.ExitProcess(1);
     std.os.windows.ExitProcess(0);
 }
 
@@ -52,7 +52,7 @@ fn posixCallMainAndExit() -> noreturn {
     const argc = *argc_ptr;
     const argv = @ptrCast(&&u8, &argc_ptr[1]);
     const envp = @ptrCast(&?&u8, &argv[argc + 1]);
-    callMain(argc, argv, envp) %% std.os.posix.exit(1);
+    callMain(argc, argv, envp) catch std.os.posix.exit(1);
     std.os.posix.exit(0);
 }
 
@@ -67,6 +67,6 @@ fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void {
 }
 
 extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 {
-    callMain(usize(c_argc), c_argv, c_envp) %% return 1;
+    callMain(usize(c_argc), c_argv, c_envp) catch return 1;
     return 0;
 }
std/special/build_runner.zig
@@ -117,7 +117,7 @@ pub fn main() -> %void {
     if (builder.validateUserInputDidItFail())
         return usageAndErr(&builder, true, try stderr_stream);
 
-    builder.make(targets.toSliceConst()) %% |err| {
+    builder.make(targets.toSliceConst()) catch |err| {
         if (err == error.InvalidStepName) {
             return usageAndErr(&builder, true, try stderr_stream);
         }
@@ -184,12 +184,12 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream)
 }
 
 fn usageAndErr(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) -> error {
-    usage(builder, already_ran_build, out_stream) %% {};
+    usage(builder, already_ran_build, out_stream) catch {};
     return error.InvalidArgs;
 }
 
 fn unwrapArg(arg: %[]u8) -> %[]u8 {
-    return arg %% |err| {
+    return arg catch |err| {
         warn("Unable to parse command line: {}\n", err);
         return err;
     };
std/build.zig
@@ -300,7 +300,7 @@ pub const Builder = struct {
         s.loop_flag = true;
 
         for (s.dependencies.toSlice()) |dep| {
-            self.makeOneStep(dep) %% |err| {
+            self.makeOneStep(dep) catch |err| {
                 if (err == error.DependencyLoopDetected) {
                     warn("  {}\n", s.name);
                 }
@@ -573,7 +573,7 @@ pub const Builder = struct {
         child.cwd = cwd;
         child.env_map = env_map;
 
-        const term = child.spawnAndWait() %% |err| {
+        const term = child.spawnAndWait() catch |err| {
             warn("Unable to spawn {}: {}\n", argv[0], @errorName(err));
             return err;
         };
@@ -596,7 +596,7 @@ pub const Builder = struct {
     }
 
     pub fn makePath(self: &Builder, path: []const u8) -> %void {
-        os.makePath(self.allocator, self.pathFromRoot(path)) %% |err| {
+        os.makePath(self.allocator, self.pathFromRoot(path)) catch |err| {
             warn("Unable to create path {}: {}\n", path, @errorName(err));
             return err;
         };
@@ -641,11 +641,11 @@ pub const Builder = struct {
 
         const dirname = os.path.dirname(dest_path);
         const abs_source_path = self.pathFromRoot(source_path);
-        os.makePath(self.allocator, dirname) %% |err| {
+        os.makePath(self.allocator, dirname) catch |err| {
             warn("Unable to create path {}: {}\n", dirname, @errorName(err));
             return err;
         };
-        os.copyFileMode(self.allocator, abs_source_path, dest_path, mode) %% |err| {
+        os.copyFileMode(self.allocator, abs_source_path, dest_path, mode) catch |err| {
             warn("Unable to copy {} to {}: {}\n", abs_source_path, dest_path, @errorName(err));
             return err;
         };
@@ -663,7 +663,7 @@ pub const Builder = struct {
         if (builtin.environ == builtin.Environ.msvc) {
             return "cl.exe";
         } else {
-            return os.getEnvVarOwned(self.allocator, "CC") %% |err| 
+            return os.getEnvVarOwned(self.allocator, "CC") catch |err| 
                 if (err == error.EnvironmentVariableNotFound)
                     ([]const u8)("cc")
                 else
@@ -723,7 +723,7 @@ pub const Builder = struct {
 
     pub fn exec(self: &Builder, argv: []const []const u8) -> []u8 {
         const max_output_size = 100 * 1024;
-        const result = os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size) %% |err| {
+        const result = os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size) catch |err| {
             std.debug.panic("Unable to spawn {}: {}", argv[0], @errorName(err));
         };
         switch (result.term) {
@@ -1895,11 +1895,11 @@ pub const WriteFileStep = struct {
         const self = @fieldParentPtr(WriteFileStep, "step", step);
         const full_path = self.builder.pathFromRoot(self.file_path);
         const full_path_dir = os.path.dirname(full_path);
-        os.makePath(self.builder.allocator, full_path_dir) %% |err| {
+        os.makePath(self.builder.allocator, full_path_dir) catch |err| {
             warn("unable to make path {}: {}\n", full_path_dir, @errorName(err));
             return err;
         };
-        io.writeFile(full_path, self.data, self.builder.allocator) %% |err| {
+        io.writeFile(full_path, self.data, self.builder.allocator) catch |err| {
             warn("unable to write {}: {}\n", full_path, @errorName(err));
             return err;
         };
@@ -1942,7 +1942,7 @@ pub const RemoveDirStep = struct {
         const self = @fieldParentPtr(RemoveDirStep, "step", step);
 
         const full_path = self.builder.pathFromRoot(self.dir_path);
-        os.deleteTree(self.builder.allocator, full_path) %% |err| {
+        os.deleteTree(self.builder.allocator, full_path) catch |err| {
             warn("Unable to remove {}: {}\n", full_path, @errorName(err));
             return err;
         };
@@ -1991,13 +1991,13 @@ fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_maj
     const out_basename = os.path.basename(output_path);
     // sym link for libfoo.so.1 to libfoo.so.1.2.3
     const major_only_path = %%os.path.join(allocator, out_dir, filename_major_only);
-    os.atomicSymLink(allocator, out_basename, major_only_path) %% |err| {
+    os.atomicSymLink(allocator, out_basename, major_only_path) catch |err| {
         warn("Unable to symlink {} -> {}\n", major_only_path, out_basename);
         return err;
     };
     // sym link for libfoo.so to libfoo.so.1
     const name_only_path = %%os.path.join(allocator, out_dir, filename_name_only);
-    os.atomicSymLink(allocator, filename_major_only, name_only_path) %% |err| {
+    os.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| {
         warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only);
         return err;
     };
std/heap.zig
@@ -137,9 +137,9 @@ pub const IncrementingAllocator = struct {
 
 test "c_allocator" {
     if (builtin.link_libc) {
-        var slice = c_allocator.alloc(u8, 50) %% return;
+        var slice = c_allocator.alloc(u8, 50) catch return;
         defer c_allocator.free(slice);
-        slice = c_allocator.realloc(u8, slice, 100) %% return;
+        slice = c_allocator.realloc(u8, slice, 100) catch return;
     }
 }
 
test/cases/defer.zig
@@ -18,7 +18,7 @@ test "mixing normal and error defers" {
     assert(result[0] == 'c');
     assert(result[1] == 'a');
 
-    const ok = runSomeErrorDefers(false) %% |err| x: {
+    const ok = runSomeErrorDefers(false) catch |err| x: {
         assert(err == error.FalseNotAllowed);
         break :x true;
     };
test/cases/error.zig
@@ -11,7 +11,7 @@ pub fn bar() -> %i32 {
 }
 
 pub fn baz() -> %i32 {
-    const y = foo() %% 1234;
+    const y = foo() catch 1234;
     return y + 1;
 }
 
@@ -53,8 +53,8 @@ fn shouldBeNotEqual(a: error, b: error) {
 
 
 test "error binary operator" {
-    const a = errBinaryOperatorG(true) %% 3;
-    const b = errBinaryOperatorG(false) %% 3;
+    const a = errBinaryOperatorG(true) catch 3;
+    const b = errBinaryOperatorG(false) catch 3;
     assert(a == 3);
     assert(b == 10);
 }
test/cases/switch.zig
@@ -230,7 +230,7 @@ fn return_a_number() -> %i32 {
 }
 
 test "capture value of switch with all unreachable prongs" {
-    const x = return_a_number() %% |err| switch (err) {
+    const x = return_a_number() catch |err| switch (err) {
         else => unreachable,
     };
     assert(x == 1);
test/compare_output.zig
@@ -395,7 +395,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
     cases.add("%defer and it fails",
         \\const io = @import("std").io;
         \\pub fn main() -> %void {
-        \\    do_test() %% return;
+        \\    do_test() catch return;
         \\}
         \\fn do_test() -> %void {
         \\    const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
@@ -415,7 +415,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) {
     cases.add("%defer and it passes",
         \\const io = @import("std").io;
         \\pub fn main() -> %void {
-        \\    do_test() %% return;
+        \\    do_test() catch return;
         \\}
         \\fn do_test() -> %void {
         \\    const stdout = &(io.FileOutStream.init(&%%io.getStdOut()).stream);
test/compile_errors.zig
@@ -1288,7 +1288,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
 
     cases.add("return from defer expression",
         \\pub fn testTrickyDefer() -> %void {
-        \\    defer canFail() %% {};
+        \\    defer canFail() catch {};
         \\
         \\    defer try canFail();
         \\
test/tests.zig
@@ -259,7 +259,7 @@ pub const CompareOutputContext = struct {
             child.stderr_behavior = StdIo.Pipe;
             child.env_map = &b.env_map;
 
-            child.spawn() %% |err| debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
+            child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
 
             var stdout = Buffer.initNull(b.allocator);
             var stderr = Buffer.initNull(b.allocator);
@@ -270,7 +270,7 @@ pub const CompareOutputContext = struct {
             %%stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size);
             %%stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size);
 
-            const term = child.wait() %% |err| {
+            const term = child.wait() catch |err| {
                 debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
             };
             switch (term) {
@@ -341,7 +341,7 @@ pub const CompareOutputContext = struct {
             child.stdout_behavior = StdIo.Ignore;
             child.stderr_behavior = StdIo.Ignore;
 
-            const term = child.spawnAndWait() %% |err| {
+            const term = child.spawnAndWait() catch |err| {
                 debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
             };
 
@@ -590,7 +590,7 @@ pub const CompileErrorContext = struct {
             child.stdout_behavior = StdIo.Pipe;
             child.stderr_behavior = StdIo.Pipe;
 
-            child.spawn() %% |err| debug.panic("Unable to spawn {}: {}\n", zig_args.items[0], @errorName(err));
+            child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", zig_args.items[0], @errorName(err));
 
             var stdout_buf = Buffer.initNull(b.allocator);
             var stderr_buf = Buffer.initNull(b.allocator);
@@ -601,7 +601,7 @@ pub const CompileErrorContext = struct {
             %%stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size);
             %%stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size);
 
-            const term = child.wait() %% |err| {
+            const term = child.wait() catch |err| {
                 debug.panic("Unable to spawn {}: {}\n", zig_args.items[0], @errorName(err));
             };
             switch (term) {
@@ -862,7 +862,7 @@ pub const TranslateCContext = struct {
             child.stdout_behavior = StdIo.Pipe;
             child.stderr_behavior = StdIo.Pipe;
 
-            child.spawn() %% |err| debug.panic("Unable to spawn {}: {}\n", zig_args.toSliceConst()[0], @errorName(err));
+            child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", zig_args.toSliceConst()[0], @errorName(err));
 
             var stdout_buf = Buffer.initNull(b.allocator);
             var stderr_buf = Buffer.initNull(b.allocator);
@@ -873,7 +873,7 @@ pub const TranslateCContext = struct {
             %%stdout_file_in_stream.stream.readAllBuffer(&stdout_buf, max_stdout_size);
             %%stderr_file_in_stream.stream.readAllBuffer(&stderr_buf, max_stdout_size);
 
-            const term = child.wait() %% |err| {
+            const term = child.wait() catch |err| {
                 debug.panic("Unable to spawn {}: {}\n", zig_args.toSliceConst()[0], @errorName(err));
             };
             switch (term) {